public bool Read() { var state = _state; if (state.Continuation != JsonParserTokenContinuation.None || _maybeBeforePreamble) { goto ReadContinuation; } MainLoop: byte b; byte *currentBuffer = _inputBuffer; uint bufferSize = _bufSize; uint pos = _pos; while (true) { if (pos >= bufferSize) { goto ReturnFalse; } b = currentBuffer[pos]; pos++; _charPos++; if (b == ':' || b == ',') { if (state.CurrentTokenType == JsonParserToken.Separator || state.CurrentTokenType == JsonParserToken.StartObject || state.CurrentTokenType == JsonParserToken.StartArray) { goto Error; } state.CurrentTokenType = JsonParserToken.Separator; continue; } if (b == '\'' || b == '"') { goto ParseString; // PERF: Avoid very lengthy method here; as we are going to return anyways. } if ((b >= '0' && b <= '9') || IsPossibleNegativeNumber(b, bufferSize, pos, currentBuffer)) { goto ParseNumber; // PERF: Avoid very lengthy method here; as we are going to return anyways. } if (b == '{') { state.CurrentTokenType = JsonParserToken.StartObject; goto ReturnTrue; } if (b == '}') { state.CurrentTokenType = JsonParserToken.EndObject; goto ReturnTrue; } if (b == '[') { state.CurrentTokenType = JsonParserToken.StartArray; goto ReturnTrue; } if (b == ']') { state.CurrentTokenType = JsonParserToken.EndArray; goto ReturnTrue; } bool couldRead; if (!ReadUnlikely(b, ref pos, out couldRead)) { continue; // We can only continue here, if there is a failure to parse, we will throw inside ReadUnlikely. } if (couldRead) { goto ReturnTrue; } goto ReturnFalse; } ParseString: { state.EscapePositions.Clear(); _unmanagedWriteBuffer.Clear(); _prevEscapePosition = 0; _currentQuote = b; state.CurrentTokenType = JsonParserToken.String; if (ParseString(ref pos) == false) { state.Continuation = JsonParserTokenContinuation.PartialString; goto ReturnFalse; } _unmanagedWriteBuffer.EnsureSingleChunk(state); goto ReturnTrue; } ParseNumber: { _unmanagedWriteBuffer.Clear(); state.EscapePositions.Clear(); state.Long = 0; _zeroPrefix = b == '0'; _isNegative = false; _isFractionedDouble = false; _isExponent = false; _isOverflow = false; // ParseNumber need to call _charPos++ & _pos++, so we'll reset them for the first char pos--; _charPos--; if (ParseNumber(ref state.Long, ref pos) == false) { state.Continuation = JsonParserTokenContinuation.PartialNumber; goto ReturnFalse; } if (state.CurrentTokenType == JsonParserToken.Float) { _unmanagedWriteBuffer.EnsureSingleChunk(state); } goto ReturnTrue; } Error: ThrowCannotHaveCharInThisPosition(b); ReturnTrue: _pos = pos; return(true); ReturnFalse: _pos = pos; return(false); ReadContinuation: // PERF: This is a "manual procedure" if (state.Continuation != JsonParserTokenContinuation.None) // parse normally { return(ContinueParsingValue()); } state.Continuation = JsonParserTokenContinuation.None; if (_maybeBeforePreamble) { if (ReadMaybeBeforePreamble() == false) { return(false); } } goto MainLoop; }
public bool Read() { if (_state.Continuation != JsonParserTokenContinuation.None) // parse normally { bool read; if (ContinueParsingValue(out read)) { return(read); } } _state.Continuation = JsonParserTokenContinuation.None; if (_line == 0) { // first time, need to check preamble _line++; if (_pos >= _initialPos + _bufSize) { return(false); } if (_inputBuffer[_pos] == Utf8Preamble[0]) { _pos++; _expectedTokenBuffer = Utf8Preamble; _expectedTokenBufferPosition = 1; _expectedTokenString = "UTF8 Preamble"; if (EnsureRestOfToken() == false) { _state.Continuation = JsonParserTokenContinuation.PartialPreamble; return(false); } } } while (true) { if (_pos >= _initialPos + _bufSize) { return(false); } var b = _inputBuffer[_pos++]; _charPos++; switch (b) { case (byte)'\r': if (_pos >= _bufSize) { return(false); } if (_inputBuffer[_pos] == (byte)'\n') { continue; } goto case (byte)'\n'; case (byte)'\n': _line++; _charPos = 1; break; case (byte)' ': case (byte)'\t': case (byte)'\v': case (byte)'\f': //white space, we can safely ignore break; case (byte)':': case (byte)',': switch (_state.CurrentTokenType) { case JsonParserToken.Separator: case JsonParserToken.StartObject: case JsonParserToken.StartArray: throw CreateException("Cannot have a '" + (char)b + "' in this position"); } _state.CurrentTokenType = JsonParserToken.Separator; break; case (byte)'N': _state.CurrentTokenType = JsonParserToken.Float; _expectedTokenBuffer = NaN; _expectedTokenBufferPosition = 1; _expectedTokenString = "NaN"; if (EnsureRestOfToken() == false) { _state.Continuation = JsonParserTokenContinuation.PartialNaN; return(false); } return(true); case (byte)'n': _state.CurrentTokenType = JsonParserToken.Null; _expectedTokenBuffer = BlittableJsonTextWriter.NullBuffer; _expectedTokenBufferPosition = 1; _expectedTokenString = "null"; if (EnsureRestOfToken() == false) { _state.Continuation = JsonParserTokenContinuation.PartialNull; return(false); } return(true); case (byte)'t': _state.CurrentTokenType = JsonParserToken.True; _expectedTokenBuffer = BlittableJsonTextWriter.TrueBuffer; _expectedTokenBufferPosition = 1; _expectedTokenString = "true"; if (EnsureRestOfToken() == false) { _state.Continuation = JsonParserTokenContinuation.PartialTrue; return(false); } return(true); case (byte)'f': _state.CurrentTokenType = JsonParserToken.False; _expectedTokenBuffer = BlittableJsonTextWriter.FalseBuffer; _expectedTokenBufferPosition = 1; _expectedTokenString = "false"; if (EnsureRestOfToken() == false) { _state.Continuation = JsonParserTokenContinuation.PartialFalse; return(false); } return(true); case (byte)'"': case (byte)'\'': _state.EscapePositions.Clear(); _stringBuffer.Clear(); _prevEscapePosition = 0; _currentQuote = b; _state.CurrentTokenType = JsonParserToken.String; if (ParseString() == false) { _state.Continuation = JsonParserTokenContinuation.PartialString; return(false); } _stringBuffer.EnsureSingleChunk(_state); return(true); case (byte)'{': _state.CurrentTokenType = JsonParserToken.StartObject; return(true); case (byte)'[': _state.CurrentTokenType = JsonParserToken.StartArray; return(true); case (byte)'}': _state.CurrentTokenType = JsonParserToken.EndObject; return(true); case (byte)']': _state.CurrentTokenType = JsonParserToken.EndArray; return(true); //numbers case (byte)'0': case (byte)'1': case (byte)'2': case (byte)'3': case (byte)'4': case (byte)'5': case (byte)'6': case (byte)'7': case (byte)'8': case (byte)'9': case (byte)'-': // negative number _stringBuffer.Clear(); _state.EscapePositions.Clear(); _state.Long = 0; _zeroPrefix = b == '0'; _isNegative = false; _isDouble = false; _isExponent = false; // ParseNumber need to call _charPos++ & _pos++, so we'll reset them for the first char _pos--; _charPos--; if (ParseNumber() == false) { _state.Continuation = JsonParserTokenContinuation.PartialNumber; return(false); } if (_state.CurrentTokenType == JsonParserToken.Float) { _stringBuffer.EnsureSingleChunk(_state); } return(true); } } }