From 6fa17e759737e3225c6cc4ba830b921428c50781 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Thu, 5 Nov 2015 19:44:26 +0000 Subject: Reimplement JSON recursion by detecting the depth in the tokenizer. Added a TODO around a possible change to the tokenizer API, changing PushBack(token) into just Rewind() or something similar. --- csharp/src/Google.Protobuf/JsonTokenizer.cs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'csharp/src/Google.Protobuf/JsonTokenizer.cs') diff --git a/csharp/src/Google.Protobuf/JsonTokenizer.cs b/csharp/src/Google.Protobuf/JsonTokenizer.cs index 108ccebe..ba031886 100644 --- a/csharp/src/Google.Protobuf/JsonTokenizer.cs +++ b/csharp/src/Google.Protobuf/JsonTokenizer.cs @@ -58,6 +58,13 @@ namespace Google.Protobuf private readonly PushBackReader reader; private JsonToken bufferedToken; private State state; + private int objectDepth = 0; + + /// + /// Returns the depth of the stack, purely in objects (not collections). + /// Informally, this is the number of remaining unclosed '{' characters we have. + /// + internal int ObjectDepth { get { return objectDepth; } } internal JsonTokenizer(TextReader reader) { @@ -66,6 +73,8 @@ namespace Google.Protobuf containerStack.Push(ContainerType.Document); } + // TODO: Why do we allow a different token to be pushed back? It might be better to always remember the previous + // token returned, and allow a parameterless Rewind() method (which could only be called once, just like the current PushBack). internal void PushBack(JsonToken token) { if (bufferedToken != null) @@ -73,6 +82,14 @@ namespace Google.Protobuf throw new InvalidOperationException("Can't push back twice"); } bufferedToken = token; + if (token.Type == JsonToken.TokenType.StartObject) + { + objectDepth--; + } + else if (token.Type == JsonToken.TokenType.EndObject) + { + objectDepth++; + } } /// @@ -94,6 +111,14 @@ namespace Google.Protobuf { var ret = bufferedToken; bufferedToken = null; + if (ret.Type == JsonToken.TokenType.StartObject) + { + objectDepth++; + } + else if (ret.Type == JsonToken.TokenType.EndObject) + { + objectDepth--; + } return ret; } if (state == State.ReaderExhausted) @@ -141,10 +166,12 @@ namespace Google.Protobuf ValidateState(ValueStates, "Invalid state to read an open brace: "); state = State.ObjectStart; containerStack.Push(ContainerType.Object); + objectDepth++; return JsonToken.StartObject; case '}': ValidateState(State.ObjectAfterProperty | State.ObjectStart, "Invalid state to read a close brace: "); PopContainer(); + objectDepth--; return JsonToken.EndObject; case '[': ValidateState(ValueStates, "Invalid state to read an open square bracket: "); -- cgit v1.2.3