Exemple #1
0
        public ValueParseResult TryParse(ReadOnlySpan <byte> readerSpan, out JsonValue result, out int consumedLength, out int lineSpan, out int colSpan)
        {
            result         = null;
            consumedLength = 0;
            lineSpan       = 1;
            colSpan        = 0;

            // is input empty
            if (readerSpan.Length <= 0 && this._innerReader == null)
            {
                // did any prior processing occur
                return(this._innerReader != null
                    ? _cleanup(this, ValueParseResult.FailureEOF)
                    : ValueParseResult.EOF);
            }

            // continue parsing?
            if (this._innerReader != null)
            {
                var innerResult = this.ParseInner(readerSpan, out result, ref consumedLength);
                switch (innerResult.Type)
                {
                case ValueParseResultType.Success:
                    this._innerReader.Dispose();
                    this._innerReader = null;
                    return(_cleanup(this, innerResult));

                case ValueParseResultType.EOF:
                    return(innerResult);

                case ValueParseResultType.Failure:
                    return(_cleanup(this, innerResult));
                }
            }

            // not continuing, find any token
            while (consumedLength < readerSpan.Length)
            {
                switch (readerSpan[consumedLength++])
                {
                case JsonTokens.WhitespaceSpace:
                    ++this._colSpan;
                    ++this._streamPos;
                    break;

                case JsonTokens.WhitespaceHorizontalTab:
                    this._colSpan += 4;     // fite me
                    ++this._streamPos;
                    break;

                case JsonTokens.WhitespaceCarriageReturn:
                    // usually as part of CRLF, really no other reason for it to exist
                    // old macs don't exist
                    break;

                case JsonTokens.WhitespaceNewline:
                    ++this._lineSpan;
                    this._colSpan = 0;
                    ++this._streamPos;
                    break;

                case JsonTokens.NullFirst:
                    this._innerReader = new JsonNullReader();
                    break;

                case JsonTokens.TrueFirst:
                case JsonTokens.FalseFirst:
                    this._innerReader = new JsonBooleanReader();
                    break;

                case JsonTokens.NumberSign:
                case JsonTokens.Digit0:
                case JsonTokens.Digit1:
                case JsonTokens.Digit2:
                case JsonTokens.Digit3:
                case JsonTokens.Digit4:
                case JsonTokens.Digit5:
                case JsonTokens.Digit6:
                case JsonTokens.Digit7:
                case JsonTokens.Digit8:
                case JsonTokens.Digit9:
                    this._innerReader = new JsonNumberReader();
                    break;

                case JsonTokens.QuoteMark:
                    this._innerReader = new JsonStringReader();
                    break;

                case JsonTokens.OpeningBracket:
                    this._innerReader = new JsonArrayReader(new ValueReaderCollection());
                    break;

                case JsonTokens.OpeningBrace:
                    this._innerReader = new JsonObjectReader(new ValueReaderCollection());
                    break;

                default:
                    if (Rune.DecodeFromUtf8(readerSpan[(consumedLength - 1)..], out var rune, out _) != OperationStatus.Done)
        public ValueParseResult TryParse(ReadOnlySpan <byte> readerSpan, out ImmutableArray <JsonValue> result, out int consumedLength, out int lineSpan, out int colSpan)
        {
            result         = default;
            consumedLength = 0;
            lineSpan       = 1;
            colSpan        = 0;

            // is input empty
            if (readerSpan.Length <= 0 && this._innerReader == null)
            {
                // did any prior processing occur
                return(this._arr != null
                    ? _cleanup(this, ValueParseResult.FailureEOF)
                    : ValueParseResult.EOF);
            }

            // if we are not continuing, ensure it's an object that's being parsed
            if (this._arr == null)
            {
                if (readerSpan[consumedLength++] != JsonTokens.OpeningBracket)
                {
                    if (Rune.DecodeFromUtf8(readerSpan, out var rune, out _) != OperationStatus.Done)
                    {
                        rune = default;
                    }

                    return(_cleanup(this, ValueParseResult.Failure("Unexpected token, expected {.", rune)));
                }

                this._expectedNext = ExpectedToken.ValueOrEnd;
                this._arr          = ImmutableArray.CreateBuilder <JsonValue>();
                ++this._colSpan;
                ++this._streamPos;
            }

            // if continuing, check if any value is being parsed
            if (this._innerReader != null)
            {
                // valid only if expecting value
                if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd)
                {
                    return(_cleanup(this, ValueParseResult.Failure("Invalid internal state.", default)));
                }

                // parse inner value
                ++consumedLength;
                var innerResult = this.ParseInner(readerSpan, ref consumedLength);
                switch (innerResult.Type)
                {
                case ValueParseResultType.Success:
                    this._innerReader.Reset();
                    this._innerReader = null;
                    break;

                case ValueParseResultType.EOF:
                    return(innerResult);

                case ValueParseResultType.Failure:
                    return(_cleanup(this, innerResult));
                }
            }

            // read and parse array items
            var completedParsing = false;

            while (consumedLength < readerSpan.Length)
            {
                switch (readerSpan[consumedLength++])
                {
                case JsonTokens.WhitespaceSpace:
                    ++this._colSpan;
                    ++this._streamPos;
                    break;

                case JsonTokens.WhitespaceHorizontalTab:
                    this._colSpan += 4;     // fite me
                    ++this._streamPos;
                    break;

                case JsonTokens.WhitespaceCarriageReturn:
                    // usually as part of CRLF, really no other reason for it to exist
                    // old macs don't exist
                    break;

                case JsonTokens.WhitespaceNewline:
                    ++this._lineSpan;
                    this._colSpan = 0;
                    ++this._streamPos;
                    break;

                case JsonTokens.ItemSeparator:
                    if (this._expectedNext != ExpectedToken.ItemSeparatorOrEnd)
                    {
                        return(_cleanup(this, ValueParseResult.Failure("Unexpected item separator.", new Rune(JsonTokens.ItemSeparator))));
                    }

                    ++this._colSpan;
                    ++this._streamPos;
                    this._expectedNext = ExpectedToken.Value;
                    break;

                case JsonTokens.ClosingBracket:
                    if (this._expectedNext != ExpectedToken.ItemSeparatorOrEnd && this._expectedNext != ExpectedToken.ValueOrEnd)
                    {
                        return(_cleanup(this, ValueParseResult.Failure("Unexpected array end.", new Rune(JsonTokens.ClosingBracket))));
                    }

                    ++this._colSpan;
                    ++this._streamPos;
                    completedParsing = true;
                    break;

                case JsonTokens.NullFirst:
                    if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd)
                    {
                        return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (null).", new Rune(JsonTokens.NullFirst))));
                    }

                    this._innerReader = this._innerReaders.NullReader;
                    break;

                case JsonTokens.TrueFirst:
                case JsonTokens.FalseFirst:
                    if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd)
                    {
                        return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (boolean).", new Rune(readerSpan[consumedLength - 1]))));
                    }

                    this._innerReader = this._innerReaders.BooleanReader;
                    break;

                case JsonTokens.NumberSign:
                case JsonTokens.Digit0:
                case JsonTokens.Digit1:
                case JsonTokens.Digit2:
                case JsonTokens.Digit3:
                case JsonTokens.Digit4:
                case JsonTokens.Digit5:
                case JsonTokens.Digit6:
                case JsonTokens.Digit7:
                case JsonTokens.Digit8:
                case JsonTokens.Digit9:
                    if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd)
                    {
                        return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (number).", new Rune(readerSpan[consumedLength - 1]))));
                    }

                    this._innerReader = this._innerReaders.NumberReader;
                    break;

                case JsonTokens.QuoteMark:
                    if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd)
                    {
                        return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (string).", new Rune(JsonTokens.QuoteMark))));
                    }

                    this._innerReader = this._innerReaders.StringReader;
                    break;

                case JsonTokens.OpeningBracket:
                    if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd)
                    {
                        return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (array).", new Rune(JsonTokens.OpeningBracket))));
                    }

                    this._innerReader = new JsonArrayReader(this._innerReaders);
                    break;

                case JsonTokens.OpeningBrace:
                    if (this._expectedNext != ExpectedToken.Value && this._expectedNext != ExpectedToken.ValueOrEnd)
                    {
                        return(_cleanup(this, ValueParseResult.Failure("Unexpected array item (object).", new Rune(JsonTokens.OpeningBracket))));
                    }

                    this._innerReader = new JsonObjectReader(this._innerReaders);
                    break;

                default:
                    if (Rune.DecodeFromUtf8(readerSpan[(consumedLength - 1)..], out var rune, out _) != OperationStatus.Done)