/// <inheritdoc />
            public override bool Read()
            {
                JsonTokenType jsonTokenType;
                int nextTokenOffset;
                // First check if we just finished an array or object context
                if (!this.arrayAndObjectEndStack.Empty() && (this.arrayAndObjectEndStack.Peek() == this.jsonBinaryBuffer.Position))
                {
                    if (this.JsonObjectState.InArrayContext)
                    {
                        jsonTokenType = JsonTokenType.EndArray;
                    }
                    else if (this.JsonObjectState.InObjectContext)
                    {
                        jsonTokenType = JsonTokenType.EndObject;
                    }
                    else
                    {
                        throw new JsonInvalidTokenException();
                    }

                    nextTokenOffset = 0;
                    this.arrayAndObjectEndStack.Pop();
                }
                else
                {
                    // We are not at the end of a context.
                    if (this.jsonBinaryBuffer.IsEof)
                    {
                        // Need to check if we are still inside of an object or array
                        if (this.JsonObjectState.CurrentDepth != 0)
                        {
                            if (this.JsonObjectState.InObjectContext)
                            {
                                throw new JsonMissingEndObjectException();
                            }
                            else if (this.JsonObjectState.InArrayContext)
                            {
                                throw new JsonMissingEndArrayException();
                            }
                            else
                            {
                                throw new InvalidOperationException("Expected to be in either array or object context");
                            }
                        }

                        return false;
                    }

                    if ((this.JsonObjectState.CurrentDepth == 0) && (this.CurrentTokenType != JsonTokenType.NotStarted))
                    {
                        // There are trailing characters outside of the outter most object or array
                        throw new JsonUnexpectedTokenException();
                    }

                    byte firstByte = this.jsonBinaryBuffer.Peek();
                    jsonTokenType = JsonBinaryReader.GetJsonTokenType(firstByte);
                    if ((jsonTokenType == JsonTokenType.String) && this.JsonObjectState.IsPropertyExpected)
                    {
                        jsonTokenType = JsonTokenType.FieldName;
                    }

                    // If this is begin array/object token then we need to identify where array/object end token is.
                    // Also the next token offset is just the array type marker + length prefix + count prefix
                    if ((jsonTokenType == JsonTokenType.BeginArray) || (jsonTokenType == JsonTokenType.BeginObject))
                    {
                        if (!JsonBinaryEncoding.TryGetValueLength(
                            this.jsonBinaryBuffer.GetBufferedRawJsonToken().Span,
                            out int arrayOrObjectLength))
                        {
                            throw new JsonUnexpectedTokenException();
                        }

                        this.arrayAndObjectEndStack.Push(this.jsonBinaryBuffer.Position + arrayOrObjectLength);
                        nextTokenOffset = JsonBinaryReader.GetArrayOrObjectPrefixLength(firstByte);
                    }
                    else
                    {
                        if (!JsonBinaryEncoding.TryGetValueLength(
                            this.jsonBinaryBuffer.GetBufferedRawJsonToken().Span,
                            out nextTokenOffset))
                        {
                            throw new JsonUnexpectedTokenException();
                        }
                    }
                }

                this.JsonObjectState.RegisterToken(jsonTokenType);
                this.currentTokenPosition = this.jsonBinaryBuffer.Position;
                this.jsonBinaryBuffer.SkipBytes(nextTokenOffset);
                return true;
            }
Exemple #2
0
            /// <inheritdoc />
            public override bool Read()
            {
                // Check if we just finished an array or object context
                if (!this.arrayAndObjectEndStack.Empty() && this.arrayAndObjectEndStack.Peek() == this.jsonBinaryBuffer.Position)
                {
                    if (this.JsonObjectState.InArrayContext)
                    {
                        this.JsonObjectState.RegisterEndArray();
                    }
                    else if (this.JsonObjectState.InObjectContext)
                    {
                        this.JsonObjectState.RegisterEndObject();
                    }
                    else
                    {
                        throw new JsonInvalidTokenException();
                    }

                    this.currentTokenPosition = this.jsonBinaryBuffer.Position;
                    this.arrayAndObjectEndStack.Pop();
                }
                else if (this.jsonBinaryBuffer.IsEof)
                {
                    // Need to check if we are still inside of an object or array
                    if (this.JsonObjectState.CurrentDepth != 0)
                    {
                        if (this.JsonObjectState.InObjectContext)
                        {
                            throw new JsonMissingEndObjectException();
                        }

                        if (this.JsonObjectState.InArrayContext)
                        {
                            throw new JsonMissingEndArrayException();
                        }

                        throw new InvalidOperationException("Expected to be in either array or object context");
                    }

                    return(false);
                }
                else if (this.JsonObjectState.CurrentDepth == 0 && this.CurrentTokenType != JsonTokenType.NotStarted)
                {
                    // There are trailing characters outside of the outter most object or array
                    throw new JsonUnexpectedTokenException();
                }
                else
                {
                    ReadOnlySpan <byte> readOnlySpan = this.jsonBinaryBuffer.GetBufferedRawJsonToken().Span;
                    int nextTokenOffset = JsonBinaryEncoding.GetValueLength(readOnlySpan);

                    byte          typeMarker    = readOnlySpan[0];
                    JsonTokenType jsonTokenType = JsonBinaryReader.GetJsonTokenType(typeMarker);
                    switch (jsonTokenType)
                    {
                    case JsonTokenType.String when this.JsonObjectState.IsPropertyExpected:
                        jsonTokenType = JsonTokenType.FieldName;
                        break;

                    // If this is begin array/object token then we need to identify where array/object end token is.
                    // Also the next token offset is just the array type marker + length prefix + count prefix
                    case JsonTokenType.BeginArray:
                    case JsonTokenType.BeginObject:
                        this.arrayAndObjectEndStack.Push(this.jsonBinaryBuffer.Position + nextTokenOffset);
                        nextTokenOffset = JsonBinaryReader.GetArrayOrObjectPrefixLength(typeMarker);
                        break;
                    }

                    this.JsonObjectState.RegisterToken(jsonTokenType);
                    this.currentTokenPosition = this.jsonBinaryBuffer.Position;
                    this.jsonBinaryBuffer.SkipBytes(nextTokenOffset);
                }

                return(true);
            }