private char UnEscapeUnicode() { var code = 0; for (var i = 0; i < 4; i++) { Consume(); var ch = _nextChar; code <<= 4; if ('0' <= ch && ch <= '9') { code += ch - '0'; } else if ('a' <= ch && ch <= 'f') { code += 10 + ch - 'a'; } else if ('A' <= ch && ch <= 'F') { code += 10 + ch - 'A'; } else { throw JsonParserException.InvalidError(string.Format("unicode escape '{0}'", ch), _position); } } return((char)code); }
private string GetString() { Consume(); var start = _position; var len = 0; while (true) { if (_isEnd) { throw JsonParserException.UnexpectedEnd(start + len); } var ch = _nextChar; if (ch == '"') { Consume(); return(new string(_charBuffer, 0, len)); } if (ch == '\\') { ch = UnEscape(); } else if (ch < ' ') { throw JsonParserException.UnexpectedError(ch, _position); } if (len >= _charBuffer.Length) { Array.Resize(ref _charBuffer, _charBuffer.Length * 2); } _charBuffer[len++] = ch; Consume(); } }
private double GetNumber() { var result = 0d; var sign = 1; if (_nextChar == '-') { sign = -1; Consume(); if (!IsNumber()) { throw JsonParserException.ExpectingError("digit", _position); } } do { result = result * 10.0 + (_nextChar - '0'); Consume(); } while (IsNumber()); if (_nextChar == '.') { Consume(); if (!IsNumber()) { throw JsonParserException.ExpectingError("digit", _position); } var exp = 0.1; do { result += (_nextChar - '0') * exp; exp *= 0.1; Consume(); } while (IsNumber()); } if (_nextChar == 'e' || _nextChar == 'E') { Consume(); var expSign = 1; var exp = 0; if (_nextChar == '-' || _nextChar == '+') { if (_nextChar == '-') { expSign = -1; } Consume(); } if (!IsNumber()) { throw JsonParserException.ExpectingError("digit", _position); } do { exp = exp * 10 + (_nextChar - '0'); Consume(); } while (IsNumber()); result = result * Math.Pow(10, expSign * exp); } return(sign * result); }
private void CheckToken(string s) { Consume(); foreach (var ch in s) { if (ch != _nextChar) { throw JsonParserException.ExpectingError(string.Format("'{0}'", ch), _position); } Consume(); } }
private char UnEscape() { Consume(); var ch = _nextChar; switch (ch) { case '\\': case '/': case '"': break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case 'u': ch = UnEscapeUnicode(); break; default: throw JsonParserException.InvalidError(string.Format("escape character '{0}'", ch), _position); } return(ch); }
private object ParseInternal(TextReader reader, int maxDepth) { Setup(reader); var stack = new Context[maxDepth]; var depth = 0; var context = new Context(); SkipWhiteSpaces(); while (true) { var value = new InternalObject(); switch (_nextChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': value.Number = GetNumber(); break; case 'n': CheckToken("ull"); value.Type = JsonType.Null; break; case 't': CheckToken("rue"); value.Type = JsonType.True; break; case 'f': // ReSharper disable once StringLiteralTypo CheckToken("alse"); value.Type = JsonType.False; break; case '"': value.Type = JsonType.String; value.String = GetString(); break; case '[': if (depth == maxDepth) { throw JsonParserException.TooDeepNesting(depth, _position); } Consume(); stack[depth++] = context; context = new Context { Array = new JsonArray() }; SkipWhiteSpaces(); continue; case ']': if (context.Array == null) { throw JsonParserException.UnexpectedError(_nextChar, _position); } Consume(); value.Type = JsonType.Array; value.Array = context.Array; context = stack[--depth]; break; case '{': if (depth == maxDepth) { throw JsonParserException.TooDeepNesting(depth, _position); } Consume(); stack[depth++] = context; context = new Context { Dictionary = new JsonDictionary() }; goto GetKey; case '}': if (context.Dictionary == null) { throw JsonParserException.UnexpectedError(_nextChar, _position); } Consume(); value.Type = JsonType.Object; value.Dictionary = context.Dictionary; context = stack[--depth]; break; default: if (_isEnd) { throw JsonParserException.UnexpectedEnd(_position); } throw JsonParserException.UnexpectedError(_nextChar, _position); } SkipWhiteSpaces(); // Start if (depth == 0) { if (_isEnd) { return(JsonObject.ToValue(value)); } throw JsonParserException.UnexpectedError(_nextChar, _position); } // Array if (context.Key == null) { context.Array.Add(value); if (_nextChar == ']') { continue; } if (_nextChar != ',') { throw JsonParserException.ExpectingError("',' or ']'", _position); } Consume(); SkipWhiteSpaces(); continue; } // Object context.Dictionary.Add(context.Key, value); if (_nextChar == '}') { continue; } if (_nextChar != ',') { throw JsonParserException.ExpectingError("',' or '}'", _position); } Consume(); GetKey: SkipWhiteSpaces(); if (_nextChar == '}') { continue; } if (_nextChar != '"') { throw JsonParserException.ExpectingError("string", _position); } context.Key = GetString(); SkipWhiteSpaces(); if (_nextChar != ':') { throw JsonParserException.ExpectingError("':'", _position); } Consume(); SkipWhiteSpaces(); } }