private TextToken GetToken(ITokenMaker tokenMaker, string stringValue) { if ((state & State.StartOfDocument) == State.StartOfDocument) { var next = ReadNoisyContent(); if (next == null) { state = State.ExpectedEndOfDocument; return(tokenMaker.CreateValueToken(stringValue)); } else { reader.PushBack(next.Value); PushBack(TextToken.Name(stringValue)); state = State.ObjectBeforeColon; containerStack.Push(ContainerType.Object); return(TextToken.StartObject); } } if ((state & (State.ObjectStart | State.ObjectAfterComma | State.ObjectAfterProperty)) != 0) { state = State.ObjectBeforeColon; return(tokenMaker.CreateNameToken(stringValue)); } else { ValidateAndModifyStateForValue("Invalid state to read a double quote: "); return(tokenMaker.CreateValueToken(stringValue)); } }
private TextToken GetValueString(string stringValue) { if ((state & (State.ObjectStart | State.ObjectAfterComma)) != 0) { state = State.ObjectBeforeColon; return(TextToken.Name(stringValue)); } else { ValidateAndModifyStateForValue("Invalid state to read a double quote: "); return(TextToken.Value(stringValue)); } }
public TextToken CreateNameToken(string text) { return(TextToken.Name(text)); }
/// <remarks> /// This method essentially just loops through characters skipping whitespace, validating and /// changing state (e.g. from ObjectBeforeColon to ObjectAfterColon) /// until it reaches something which will be a genuine token (e.g. a start object, or a value) at which point /// it returns the token. Although the method is large, it would be relatively hard to break down further... most /// of it is the large switch statement, which sometimes returns and sometimes doesn't. /// </remarks> protected override TextToken NextImpl() { if (state == State.ReaderExhausted) { throw new InvalidOperationException("Next() called after end of document"); } while (true) { var next = reader.Read(); if (next == null) { //ValidateState(State.ExpectedEndOfDocument, "Unexpected end of document in state: "); //state = State.ReaderExhausted; return(TextToken.EndDocument); } if (state == State.StartOfDocument) { reader.PushBack(next.Value); next = ReadNoisyContent(); if (next.Value == '{') { state = State.ArrayStart; containerStack.Push(ContainerType.Array); return(TextToken.StartArray); } else { if (next.Value != '\"') { reader.PushBack(next.Value); } containerStack.Push(ContainerType.Object); var name = ReadName(); if (reader.LastChar == null) { // single value state = State.ExpectedEndOfDocument; if ("null".Equals(name, StringComparison.OrdinalIgnoreCase)) { return(TextToken.Null); } else { return(TextToken.Value(name)); } } PushBack(TextToken.Name(name)); state = State.ObjectStart; return(TextToken.StartObject); } } else if (state == State.ObjectAfterProperty) { if (char.IsWhiteSpace(next.Value)) { continue; } if (next.Value != '}') { reader.PushBack(next.Value); var name = ReadName(); state = State.ObjectAfterColon; return(TextToken.Name(name)); } } else if (state == State.ObjectStart) { next = ReadNoisyContent(); if (next.Value != '}') { reader.PushBack(next.Value); var name = ReadName(); state = State.ObjectAfterColon; return(TextToken.Name(name)); } } switch (next.Value) { // Skip whitespace between tokens case ' ': case '\t': case '\r': case '\n': break; case ':': ValidateState(State.ObjectBeforeColon, "Invalid state to read a colon: "); state = State.ObjectAfterColon; break; case ',': ValidateState(State.ObjectAfterProperty | State.ArrayAfterValue, "Invalid state to read a comma: "); state = state == State.ObjectAfterProperty ? State.ObjectAfterComma : State.ArrayAfterComma; break; case '\'': case '"': return(GetValueString(next.Value)); case '{': ValidateState(ValueStates, "Invalid state to read an open brace: "); state = State.ObjectStart; containerStack.Push(ContainerType.Object); return(TextToken.StartObject); case '}': ValidateState(State.ObjectAfterProperty | State.ObjectStart, "Invalid state to read a close brace: "); PopContainer(); return(TextToken.EndObject); case '[': ValidateState(ValueStates, "Invalid state to read an open square bracket: "); state = State.ArrayStart; containerStack.Push(ContainerType.Array); return(TextToken.StartArray); case ']': ValidateState(State.ArrayAfterValue | State.ArrayStart, "Invalid state to read a close square bracket: "); PopContainer(); return(TextToken.EndArray); case 'n': // Start of null ConsumeLiteral("null"); ValidateAndModifyStateForValue("Invalid state to read a null literal: "); return(TextToken.Null); case 't': // Start of true ConsumeLiteral("true"); ValidateAndModifyStateForValue("Invalid state to read a true literal: "); return(TextToken.True); case 'f': // Start of false ConsumeLiteral("false"); ValidateAndModifyStateForValue("Invalid state to read a false literal: "); return(TextToken.False); case '-': // Start of a number case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': double number = ReadNumber(next.Value); ValidateAndModifyStateForValue("Invalid state to read a number token: "); return(TextToken.Value(number)); default: reader.PushBack(next.Value); return(GetValueString(ReadName())); } } }