private void ParseUnquotedProperty() { int initialPosition = _charPos; // parse unquoted property name until whitespace or colon while (true) { switch (_chars[_charPos]) { case '\0': if (_charsUsed == _charPos) { if (ReadData(true) == 0) throw CreateReaderException(this, "Unexpected end while parsing unquoted property name."); break; } _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition); return; default: char currentChar = _chars[_charPos]; if (ValidIdentifierChar(currentChar)) { _charPos++; break; } else if (char.IsWhiteSpace(currentChar) || currentChar == ':') { _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition); return; } throw CreateReaderException(this, "Invalid JavaScript property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); } } }
private void ClearRecentString() { if (_buffer != null) _buffer.Position = 0; _stringReference = new StringReference(); }
private void ReadStringIntoBuffer(char quote) { int charPos = _charPos; int initialPosition = _charPos; int lastWritePosition = _charPos; StringBuffer buffer = null; while (true) { switch (_chars[charPos++]) { case '\0': if (_charsUsed == charPos - 1) { charPos--; if (ReadData(true) == 0) { _charPos = charPos; throw CreateReaderException(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); } } break; case '\\': _charPos = charPos; if (!EnsureChars(0, true)) { _charPos = charPos; throw CreateReaderException(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); } // start of escape sequence int escapeStartPos = charPos - 1; char currentChar = _chars[charPos]; char writeChar; switch (currentChar) { case 'b': charPos++; writeChar = '\b'; break; case 't': charPos++; writeChar = '\t'; break; case 'n': charPos++; writeChar = '\n'; break; case 'f': charPos++; writeChar = '\f'; break; case 'r': charPos++; writeChar = '\r'; break; case '\\': charPos++; writeChar = '\\'; break; case '"': case '\'': case '/': writeChar = currentChar; charPos++; break; case 'u': charPos++; _charPos = charPos; if (EnsureChars(4, true)) { string hexValues = new string(_chars, charPos, 4); char hexChar = Convert.ToChar(int.Parse(hexValues, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo)); writeChar = hexChar; charPos += 4; } else { _charPos = charPos; throw CreateReaderException(this, "Unexpected end while parsing unicode character."); } break; default: charPos++; _charPos = charPos; throw CreateReaderException(this, "Bad JSON escape sequence: {0}.".FormatWith(CultureInfo.InvariantCulture, @"\" + currentChar)); } if (buffer == null) buffer = GetBuffer(); if (escapeStartPos > lastWritePosition) { buffer.Append(_chars, lastWritePosition, escapeStartPos - lastWritePosition); } buffer.Append(writeChar); lastWritePosition = charPos; break; case StringUtils.CarriageReturn: _charPos = charPos - 1; ProcessCarriageReturn(true); charPos = _charPos; break; case StringUtils.LineFeed: _charPos = charPos - 1; ProcessLineFeed(); charPos = _charPos; break; case '"': case '\'': if (_chars[charPos - 1] == quote) { charPos--; if (initialPosition == lastWritePosition) { _stringReference = new StringReference(_chars, initialPosition, charPos - initialPosition); } else { if (buffer == null) buffer = GetBuffer(); if (charPos > lastWritePosition) buffer.Append(_chars, lastWritePosition, charPos - lastWritePosition); _stringReference = new StringReference(buffer.GetInternalBuffer(), 0, buffer.Position); } charPos++; _charPos = charPos; return; } break; } } }
private void ParseComment() { // should have already parsed / character before reaching this method _charPos++; if (!EnsureChars(1, false) || _chars[_charPos] != '*') throw CreateReaderException(this, "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); else _charPos++; int initialPosition = _charPos; bool commentFinished = false; while (!commentFinished) { switch (_chars[_charPos]) { case '\0': if (_charsUsed == _charPos) { if (ReadData(true) == 0) throw CreateReaderException(this, "Unexpected end while parsing comment."); } else { _charPos++; } break; case '*': _charPos++; if (EnsureChars(0, true)) { if (_chars[_charPos] == '/') { _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition - 1); _charPos++; commentFinished = true; } } break; case StringUtils.CarriageReturn: ProcessCarriageReturn(true); break; case StringUtils.LineFeed: ProcessLineFeed(); break; default: _charPos++; break; } } SetToken(JsonToken.Comment, _stringReference.ToString()); ClearRecentString(); }
private void ParseNumber() { ShiftBufferIfNeeded(); char firstChar = _chars[_charPos]; int initialPosition = _charPos; ReadNumberIntoBuffer(); _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition); object numberValue; JsonToken numberType; bool singleDigit = (char.IsDigit(firstChar) && _stringReference.Length == 1); bool nonBase10 = (firstChar == '0' && _stringReference.Length > 1 && _stringReference.Chars[_stringReference.StartIndex + 1] != '.'); if (_readType == ReadType.ReadAsInt32) { if (singleDigit) { // digit char values start at 48 numberValue = firstChar - 48; } else if (nonBase10) { string number = _stringReference.ToString(); // decimal.Parse doesn't support parsing hexadecimal values int integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt32(number, 16) : Convert.ToInt32(number, 8); numberValue = integer; } else { string number = _stringReference.ToString(); numberValue = Convert.ToInt32(number, CultureInfo.InvariantCulture); } numberType = JsonToken.Integer; } else if (_readType == ReadType.ReadAsDecimal) { if (singleDigit) { // digit char values start at 48 numberValue = (decimal)firstChar - 48; } else if (nonBase10) { string number = _stringReference.ToString(); // decimal.Parse doesn't support parsing hexadecimal values long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8); numberValue = Convert.ToDecimal(integer); } else { string number = _stringReference.ToString(); numberValue = decimal.Parse(number, NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture); } numberType = JsonToken.Float; } else { if (singleDigit) { // digit char values start at 48 numberValue = (long)firstChar - 48; numberType = JsonToken.Integer; } else if (nonBase10) { string number = _stringReference.ToString(); numberValue = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(number, 16) : Convert.ToInt64(number, 8); numberType = JsonToken.Integer; } else { string number = _stringReference.ToString(); // it's faster to do 3 indexof with single characters than an indexofany if (number.IndexOf('.') != -1 || number.IndexOf('E') != -1 || number.IndexOf('e') != -1) { numberValue = Convert.ToDouble(number, CultureInfo.InvariantCulture); numberType = JsonToken.Float; } else { try { numberValue = Convert.ToInt64(number, CultureInfo.InvariantCulture); } catch (OverflowException ex) { throw new JsonReaderException("JSON integer {0} is too large or small for an Int64.".FormatWith(CultureInfo.InvariantCulture, number), ex); } numberType = JsonToken.Integer; } } } ClearRecentString(); SetToken(numberType, numberValue); }
private void ParseConstructor() { if (MatchValueWithTrailingSeperator("new")) { EatWhitespace(false); int initialPosition = _charPos; int endPosition; while (true) { char currentChar = _chars[_charPos]; if (currentChar == '\0') { if (_charsUsed == _charPos) { if (ReadData(true) == 0) throw CreateReaderException(this, "Unexpected end while parsing constructor."); } else { endPosition = _charPos; _charPos++; break; } } else if (char.IsLetterOrDigit(currentChar)) { _charPos++; } else if (currentChar == StringUtils.CarriageReturn) { endPosition = _charPos; ProcessCarriageReturn(true); break; } else if (currentChar == StringUtils.LineFeed) { endPosition = _charPos; ProcessLineFeed(); break; } else if (char.IsWhiteSpace(currentChar)) { endPosition = _charPos; _charPos++; break; } else if (currentChar == '(') { endPosition = _charPos; break; } else { throw CreateReaderException(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); } } _stringReference = new StringReference(_chars, initialPosition, endPosition - initialPosition); string constructorName = _stringReference.ToString(); EatWhitespace(false); if (_chars[_charPos] != '(') throw CreateReaderException(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); _charPos++; ClearRecentString(); SetToken(JsonToken.StartConstructor, constructorName); } }