Ejemplo n.º 1
0
        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;
        }
Ejemplo n.º 2
0
        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);
                }
            }
        }