context: #region License
  // Copyright (c) 2007 James Newton-King
  //
  // Permission is hereby granted, free of charge, to any person
  // obtaining a copy of this software and associated documentation
  // files (the "Software"), to deal in the Software without
  // restriction, including without limitation the rights to use,
  // copy, modify, merge, publish, distribute, sublicense, and/or sell
  // copies of the Software, and to permit persons to whom the
  // Software is furnished to do so, subject to the following
  // conditions:
  //
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  // OTHER DEALINGS IN THE SOFTWARE.
  #endregion
  
  using System;
  using System.Collections.Generic;
  using System.Text;
  using System.IO;
  using System.Xml;
  using System.Globalization;
  using Newtonsoft.Json.Utilities;
  
  namespace Newtonsoft.Json
  {
      /// <summary>
      /// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
      /// </summary>
      public class JsonTextReader : JsonReader, IJsonLineInfo
      {
          private enum ReadType
          {
              Read,
              ReadAsBytes,
              ReadAsDecimal,
  #if !NET20
              ReadAsDateTimeOffset
  #endif
          }
  
          private readonly TextReader _reader;
          private readonly StringBuffer _buffer;
          private char? _lastChar;
          private int _currentLinePosition;
          private int _currentLineNumber;
          private bool _end;
          private ReadType _readType;
          private Type _objectType;
          private CultureInfo _culture;
  
          /// <summary>
          /// Gets or sets the culture used when reading JSON. Defaults to <see cref="CultureInfo.CurrentCulture"/>.
          /// </summary>
          public CultureInfo Culture
          {
              get { return _culture ?? CultureInfo.CurrentCulture; }
              set { _culture = value; }
          }
  
          /// <summary>
          /// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>.
          /// </summary>
          /// <param name="reader">The <c>TextReader</c> containing the XML data to read.</param>
          public JsonTextReader(TextReader reader, Type objectType)
          {
              if (reader == null)
                  throw new ArgumentNullException("reader");
  
              _reader = reader;
              _objectType = objectType;
              _buffer = new StringBuffer(4096);
              _currentLineNumber = 1;
          }
  
          private void ParseString(char quote)
          {
              ReadStringIntoBuffer(quote);
  
              if (_readType == ReadType.ReadAsBytes)
              {
                  byte[] data;
                  if (_buffer.Position == 0)
                  {
                      data = new byte[0];
                  }
                  else
                  {
                      data = Convert.FromBase64CharArray(_buffer.GetInternalBuffer(), 0, _buffer.Position);
                      _buffer.Position = 0;
                  }
  
                  SetToken(JsonToken.Bytes, data);
              }
              else
              {
                  string text = _buffer.ToString();
                  _buffer.Position = 0;
  
                  if (text.StartsWith("/Date(", StringComparison.Ordinal) && text.EndsWith(")/", StringComparison.Ordinal))
                  {
                      ParseDate(text);
                  }
                  else
                  {
                      SetToken(JsonToken.String, text);
                      QuoteChar = quote;
                  }
              }
          }
          private void ReadStringIntoBuffer(char quote/*, bool readAsText = false*/)
          {
              while (true)
              {
                  char nextChar = (char)PeekNext();
                  if (quote == '\0' && "},]".Contains("" + nextChar))
                  {
                      return;
                  }
                  else
                  {
                      char currentChar = MoveNext();
                      switch (currentChar)
                      {
                          case '\0':
                              if (_end)
                                  throw CreateJsonReaderException("Unterminated string. Expected delimiter: {0}. Line {1}, position {2}.", quote, _currentLineNumber, _currentLinePosition);
  
                              _buffer.Append('\0');
                              break;
                          case '\\':
                              if ((currentChar = MoveNext()) != '\0' || !_end)
                              {
                                  switch (currentChar)
                                  {
                                      case 'b':
                                          _buffer.Append('\b');
                                          break;
                                      case 't':
                                          _buffer.Append('\t');
                                          break;
                                      case 'n':
                                          _buffer.Append('\n');
                                          break;
                                      case 'f':
                                          _buffer.Append('\f');
                                          break;
                                      case 'r':
                                          _buffer.Append('\r');
                                          break;
                                      case '\\':
                                          _buffer.Append('\\');
                                          break;
                                      case '"':
                                      case '\'':
                                      case '/':
                                      case '}':
                                      case ']':
                                      case ',':
                                          _buffer.Append(currentChar);
                                          break;
                                      case 'u':
                                          char[] hexValues = new char[4];
                                          for (int i = 0; i < hexValues.Length; i++)
                                          {
                                              if ((currentChar = MoveNext()) != '\0' || !_end)
                                                  hexValues[i] = currentChar;
                                              else
                                                  throw CreateJsonReaderException("Unexpected end while parsing unicode character. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
                                          }
  
                                          char hexChar = Convert.ToChar(int.Parse(new string(hexValues), NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo));
                                          _buffer.Append(hexChar);
                                          break;
                                      default:
                                          throw CreateJsonReaderException("Bad JSON escape sequence: {0}. Line {1}, position {2}.", @"\" + currentChar, _currentLineNumber, _currentLinePosition);
                                  }
                              }
                              else
                              {
                                  throw CreateJsonReaderException("Unterminated string. Expected delimiter: {0}. Line {1}, position {2}.", quote, _currentLineNumber, _currentLinePosition);
                              }
                              break;
                          case '"':
                          case '\'':
                              if (/*!readAsText && */currentChar == quote)
                              {
                                  return;
                              }
                              else
                              {
                                  _buffer.Append(currentChar);
                              }
                              break;
                          default:
                              _buffer.Append(currentChar);
                              break;
                      }
                  }
              }
          }
  
          private JsonReaderException CreateJsonReaderException(string format, params object[] args)
          {
              string message = format.FormatWith(CultureInfo.InvariantCulture, args);
              return new JsonReaderException(message, null, _currentLineNumber, _currentLinePosition);
          }
  
          private TimeSpan ReadOffset(string offsetText)
          {
              bool negative = (offsetText[0] == '-');
  
              int hours = int.Parse(offsetText.Substring(1, 2), NumberStyles.Integer, CultureInfo.InvariantCulture);
              int minutes = 0;
              if (offsetText.Length >= 5)
                  minutes = int.Parse(offsetText.Substring(3, 2), NumberStyles.Integer, CultureInfo.InvariantCulture);
  
              TimeSpan offset = TimeSpan.FromHours(hours) + TimeSpan.FromMinutes(minutes);
              if (negative)
                  offset = offset.Negate();
  
              return offset;
          }
  
          private void ParseDate(string text)
          {
              string value = text.Substring(6, text.Length - 8);
              DateTimeKind kind = DateTimeKind.Utc;
  
              int index = value.IndexOf('+', 1);
  
              if (index == -1)
                  index = value.IndexOf('-', 1);
  
              TimeSpan offset = TimeSpan.Zero;
  
              if (index != -1)
              {
                  kind = DateTimeKind.Local;
                  offset = ReadOffset(value.Substring(index));
                  value = value.Substring(0, index);
              }
  
              long javaScriptTicks = long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
  
              DateTime utcDateTime = JsonConvert.ConvertJavaScriptTicksToDateTime(javaScriptTicks);
  
  #if !NET20
              if (_readType == ReadType.ReadAsDateTimeOffset)
              {
                  SetToken(JsonToken.Date, new DateTimeOffset(utcDateTime.Add(offset).Ticks, offset));
              }
              else
  #endif
              {
                  DateTime dateTime;
  
                  switch (kind)
                  {
                      case DateTimeKind.Unspecified:
                          dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
                          break;
                      case DateTimeKind.Local:
                          dateTime = utcDateTime.ToLocalTime();
                          break;
                      default:
                          dateTime = utcDateTime;
                          break;
                  }
  
                  SetToken(JsonToken.Date, dateTime);
              }
          }
  
          private const int LineFeedValue = StringUtils.LineFeed;
          private const int CarriageReturnValue = StringUtils.CarriageReturn;
  
          private char MoveNext()
          {
              int value = _reader.Read();
  
              switch (value)
              {
                  case -1:
                      _end = true;
                      return '\0';
                  case CarriageReturnValue:
                      if (_reader.Peek() == LineFeedValue)
                          _reader.Read();
  
                      _currentLineNumber++;
                      _currentLinePosition = 0;
                      break;
                  case LineFeedValue:
                      _currentLineNumber++;
                      _currentLinePosition = 0;
                      break;
                  default:
                      _currentLinePosition++;
                      break;
              }
  
              return (char)value;
          }
  
          private bool HasNext()
          {
              return (_reader.Peek() != -1);
          }
  
          private int PeekNext()
          {
              return _reader.Peek();
          }
  
          /// <summary>
          /// Reads the next JSON token from the stream.
          /// </summary>
          /// <returns>
          /// true if the next token was read successfully; false if there are no more tokens to read.
          /// </returns>
          public override bool Read()
          {
              _readType = ReadType.Read;
              return ReadInternal();
          }
  
          /// <summary>
          /// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
          /// </summary>
          /// <returns>
          /// A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null.
          /// </returns>
          public override byte[] ReadAsBytes()
          {
              _readType = ReadType.ReadAsBytes;
  
              do
              {
                  if (!ReadInternal())
                      throw CreateJsonReaderException("Unexpected end when reading bytes: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
              } while (TokenType == JsonToken.Comment);
  
              if (TokenType == JsonToken.Null)
                  return null;
              if (TokenType == JsonToken.Bytes)
                  return (byte[])Value;
              if (TokenType == JsonToken.StartArray)
              {
                  List<byte> data = new List<byte>();
  
                  while (ReadInternal())
                  {
                      switch (TokenType)
                      {
                          case JsonToken.Integer:
                              data.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture));
                              break;
                          case JsonToken.EndArray:
                              byte[] d = data.ToArray();
                              SetToken(JsonToken.Bytes, d);
                              return d;
                          case JsonToken.Comment:
                              // skip
                              break;
                          default:
                              throw CreateJsonReaderException("Unexpected token when reading bytes: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition);
                      }
                  }
  
                  throw CreateJsonReaderException("Unexpected end when reading bytes: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
              }
  
  
              throw CreateJsonReaderException("Unexpected token when reading bytes: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition);
          }
  
          /// <summary>
          /// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
          /// </summary>
          /// <returns>A <see cref="Nullable{Decimal}"/>.</returns>
          public override decimal? ReadAsDecimal()
          {
              _readType = ReadType.ReadAsDecimal;
  
              do
              {
                  if (!ReadInternal())
                      throw CreateJsonReaderException("Unexpected end when reading decimal: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
              } while (TokenType == JsonToken.Comment);
  
              if (TokenType == JsonToken.Null)
                  return null;
              if (TokenType == JsonToken.Float)
                  return (decimal?)Value;
  
              decimal d;
              if (TokenType == JsonToken.String && decimal.TryParse((string)Value, NumberStyles.Number, Culture, out d))
              {
                  SetToken(JsonToken.Float, d);
                  return d;
              }
  
              throw CreateJsonReaderException("Unexpected token when reading decimal: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition);
          }
  
  #if !NET20
          /// <summary>
          /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
          /// </summary>
          /// <returns>A <see cref="DateTimeOffset"/>.</returns>
          public override DateTimeOffset? ReadAsDateTimeOffset()
          {
              _readType = ReadType.ReadAsDateTimeOffset;
  
              do
              {
                  if (!ReadInternal())
                      throw CreateJsonReaderException("Unexpected end when reading date: Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
              } while (TokenType == JsonToken.Comment);
  
              if (TokenType == JsonToken.Null)
                  return null;
              if (TokenType == JsonToken.Date)
                  return (DateTimeOffset)Value;
  
              DateTimeOffset dt;
              if (TokenType == JsonToken.String && DateTimeOffset.TryParse((string)Value, Culture, DateTimeStyles.None, out dt))
              {
                  SetToken(JsonToken.Date, dt);
                  return dt;
              }
  
              throw CreateJsonReaderException("Unexpected token when reading date: {0}. Line {1}, position {2}.", TokenType, _currentLineNumber, _currentLinePosition);
          }
  #endif
  
          private bool ReadInternal()
          {
              while (true)
              {
                  char currentChar;
                  if (_lastChar != null)
                  {
                      currentChar = _lastChar.Value;
                      _lastChar = null;
                  }
                  else
                  {
                      currentChar = MoveNext();
                  }
  
                  if (currentChar == '\0' && _end)
                      return false;
  
                  switch (CurrentState)
                  {
                      case State.Start:
                      case State.Property:
                      case State.Array:
                      case State.ArrayStart:
                      case State.Constructor:
                      case State.ConstructorStart:
                          return ParseValue(currentChar);
                      case State.Complete:
                          break;
                      case State.Object:
                      case State.ObjectStart:
                          return ParseObject(currentChar);
                      case State.PostValue:
                          // returns true if it hits
                          // end of object or array
                          if (ParsePostValue(currentChar))
                              return true;
                          break;
                      case State.Closed:
                          break;
                      case State.Error:
                          break;
                      default:
                          throw CreateJsonReaderException("Unexpected state: {0}. Line {1}, position {2}.", CurrentState, _currentLineNumber, _currentLinePosition);
                  }
              }
          }
  
          private bool ParsePostValue(char currentChar)
          {
              do
              {
                  switch (currentChar)
                  {
                      case '}':
                          SetToken(JsonToken.EndObject);
                          return true;
                      case ']':
                          SetToken(JsonToken.EndArray);
                          return true;
                      case ')':
                          SetToken(JsonToken.EndConstructor);
                          return true;
                      case '/':
                          ParseComment();
                          return true;
                      case ',':
                          // finished parsing
                          SetStateBasedOnCurrent();
                          return false;
                      case ' ':
                      case StringUtils.Tab:
                      case StringUtils.LineFeed:
                      case StringUtils.CarriageReturn:
                          // eat
                          break;
                      default:
                          if (char.IsWhiteSpace(currentChar))
                          {
                              // eat
                          }
                          else
                          {
                              throw CreateJsonReaderException("After parsing a value an unexpected character was encountered: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
                          }
                          break;
                  }
              } while ((currentChar = MoveNext()) != '\0' || !_end);
  
              return false;
          }
  
          private bool ParseObject(char currentChar)
          {
              do
              {
                  switch (currentChar)
                  {
                      case '}':
                          SetToken(JsonToken.EndObject);
                          return true;
                      case '/':
                          ParseComment();
                          return true;
                      case ' ':
                      case StringUtils.Tab:
                      case StringUtils.LineFeed:
                      case StringUtils.CarriageReturn:
                          // eat
                          break;
                      default:
                          if (char.IsWhiteSpace(currentChar))
                          {
                              // eat
                          }
                          else
                          {
                              return ParseProperty(currentChar);
                          }
                          break;
                  }
              } while ((currentChar = MoveNext()) != '\0' || !_end);
  
              return false;
          }
  
          private bool ParseProperty(char firstChar)
          {
              char currentChar = firstChar;
              char quoteChar;
  
              if (ValidIdentifierChar(currentChar))
              {
                  quoteChar = '\0';
                  currentChar = ParseUnquotedProperty(currentChar);
              }
              else if (currentChar == '"' || currentChar == '\'')
              {
                  quoteChar = currentChar;
                  ReadStringIntoBuffer(quoteChar);
                  currentChar = MoveNext();
              }
              else
              {
                  throw CreateJsonReaderException("Invalid property identifier character: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
              }
  
              if (currentChar != ':')
              {
                  currentChar = MoveNext();
  
                  // finished property. skip any whitespace and move to colon
                  EatWhitespace(currentChar, false, out currentChar);
  
                  if (currentChar != ':')
                      throw CreateJsonReaderException("Invalid character after parsing property name. Expected ':' but got: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
              }
  
              SetToken(JsonToken.PropertyName, _buffer.ToString());
              QuoteChar = quoteChar;
              _buffer.Position = 0;
  
              return true;
          }
  
          private bool ValidIdentifierChar(char value)
          {
              return (char.IsLetterOrDigit(value) || value == '_' || value == '$');
          }
  
          private char ParseUnquotedProperty(char firstChar)
          {
              // parse unquoted property name until whitespace or colon
              _buffer.Append(firstChar);
  
              char currentChar;
  
              while ((currentChar = MoveNext()) != '\0' || !_end)
              {
                  if (char.IsWhiteSpace(currentChar) || currentChar == ':')
                  {
                      return currentChar;
                  }
                  else if (ValidIdentifierChar(currentChar))
                  {
                      _buffer.Append(currentChar);
                  }
                  else
                  {
                      throw CreateJsonReaderException("Invalid JavaScript property identifier character: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
                  }
              }
  
              throw CreateJsonReaderException("Unexpected end when parsing unquoted property name. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
          }
  
          private bool ParseValue(char currentChar)
          {
              return _objectType.FullName.Equals("OBMWS.WSJson") ? ParseAsText(currentChar) : ParseAsDynamic(currentChar);
          }
  
          private bool ParseAsText(char currentChar)
          {
              do
              {
                  switch (currentChar)
                  {
                      case '{':
                          SetToken(JsonToken.StartObject);
                          return true;
                      case '}':
                          SetToken(JsonToken.EndObject);
                          return true;
                      case '[':
                          SetToken(JsonToken.StartArray);
                          return true;
                      case ']':
                          SetToken(JsonToken.EndArray);
                          return true;
                      case ',':
                          SetToken(JsonToken.Undefined);
                          return true;
                      case ')':
                          SetToken(JsonToken.EndConstructor);
                          return true;
                      case '"':
                      case '\'':
                          ParseText(currentChar, '\0');
                          return true;
                      case ' ':
                      case StringUtils.Tab:
                      case StringUtils.LineFeed:
                      case StringUtils.CarriageReturn:
                          // eat
                          break;
                      default:
                          if (char.IsWhiteSpace(currentChar))
                          {
                              // eat
                          }
                          else
                          {
                              ParseText('\0', currentChar);
                              return true;
                          }
                          break;
                  }
              } while ((currentChar = MoveNext()) != '\0' || !_end);
  
              return false;
          }
          private void ParseText(char quote, char currentChar)
          {
              QuoteChar = quote;
  
              if (currentChar != '\0') { _buffer.Append(currentChar); }
  
              ReadStringIntoBuffer(quote);
  
              string text = _buffer.ToString();
              text = string.IsNullOrEmpty(text) ? string.Empty : text.Trim(new char[] { '"', '\'' });
              _buffer.Position = 0;
  
              SetToken(JsonToken.String, text);
          }
  
  
          private bool ParseAsDynamic(char currentChar)
          {
              do
              {
                  switch (currentChar)
                  {
                      case '"':
                      case '\'':
                          ParseString(currentChar);
                          return true;
                      case 't':
                          ParseTrue();
                          return true;
                      case 'f':
                          ParseFalse();
                          return true;
                      case 'n':
                          if (HasNext())
                          {
                              char next = (char)PeekNext();
  
                              if (next == 'u')
                                  ParseNull();
                              else if (next == 'e')
                                  ParseConstructor();
                              else
                                  throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
                          }
                          else
                          {
                              throw CreateJsonReaderException("Unexpected end. Line {0}, position {1}.", _currentLineNumber, _currentLinePosition);
                          }
                          return true;
                      case 'N':
                          ParseNumberNaN();
                          return true;
                      case 'I':
                          ParseNumberPositiveInfinity();
                          return true;
                      case '-':
                          if (PeekNext() == 'I')
                              ParseNumberNegativeInfinity();
                          else
                              ParseNumber(currentChar);
                          return true;
                      case '/':
                          ParseComment();
                          return true;
                      case 'u':
                          ParseUndefined();
                          return true;
                      case '{':
                          SetToken(JsonToken.StartObject);
                          return true;
                      case '[':
                          SetToken(JsonToken.StartArray);
                          return true;
                      case '}':
                          SetToken(JsonToken.EndObject);
                          return true;
                      case ']':
                          SetToken(JsonToken.EndArray);
                          return true;
                      case ',':
                          SetToken(JsonToken.Undefined);
                          return true;
                      case ')':
                          SetToken(JsonToken.EndConstructor);
                          return true;
                      case ' ':
                      case StringUtils.Tab:
                      case StringUtils.LineFeed:
                      case StringUtils.CarriageReturn:
                          // eat
                          break;
                      default:
                          if (char.IsWhiteSpace(currentChar))
                          {
                              // eat
                          }
                          else if (char.IsNumber(currentChar) || currentChar == '-' || currentChar == '.')
                          {
                              ParseNumber(currentChar);
                              return true;
                          }
                          else
                          {
                              throw CreateJsonReaderException("Unexpected character encountered while parsing value: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
                          }
                          break;
                  }
              } while ((currentChar = MoveNext()) != '\0' || !_end);
  
              return false;
          }
  
          private bool EatWhitespace(char initialChar, bool oneOrMore, out char finalChar)
          {
              bool whitespace = false;
              char currentChar = initialChar;
              while (currentChar == ' ' || char.IsWhiteSpace(currentChar))
              {
                  whitespace = true;
                  currentChar = MoveNext();
              }
  
              finalChar = currentChar;
  
              return (!oneOrMore || whitespace);
          }
  
          private void ParseConstructor()
          {
              if (MatchValue('n', "new", true))
              {
                  char currentChar = MoveNext();
  
                  if (EatWhitespace(currentChar, true, out currentChar))
                  {
                      while (char.IsLetter(currentChar))
                      {
                          _buffer.Append(currentChar);
                          currentChar = MoveNext();
                      }
  
                      EatWhitespace(currentChar, false, out currentChar);
  
                      if (currentChar != '(')
                          throw CreateJsonReaderException("Unexpected character while parsing constructor: {0}. Line {1}, position {2}.", currentChar, _currentLineNumber, _currentLinePosition);
  
                      string constructorName = _buffer.ToString();
                      _buffer.Position = 0;
  
                      SetToken(JsonToken.StartConstructor, constructorName);
                  }
              }
          }
  
          private void ParseNumber(char firstChar)
          {
              char currentChar = firstChar;
  
              // parse until seperator character or end
              bool end = false;
              do
              {
                  if (IsSeperator(currentChar))
                  {
                      end = true;
                      _lastChar = currentChar;
                  }
                  else
                  {
                      _buffer.Append(currentChar);
                  }
  
              } while (!end && ((currentChar = MoveNext()) != '\0' || !_end));
  
              string number = _buffer.ToString();
              object numberValue;
              JsonToken numberType;
  
              bool nonBase10 = (firstChar == '0' && !number.StartsWith("0.", StringComparison.OrdinalIgnoreCase));
  
  
gt:             if (_readType == ReadType.ReadAsDecimal)