public void CountersOnReadingSecondChar() { BufferedCharReader reader = new BufferedCharReader(new StringReader("ab")); reader.Next(); reader.Next(); AssertCounters(reader, 2, 1, 2); }
public void NextAfterBackRestoresCounters() { BufferedCharReader reader = new BufferedCharReader(new StringReader("a")); reader.Next(); reader.Back(); reader.Next(); AssertCounters(reader, 1, 1, 1); }
public void BacktrackAfterEnding() { BufferedCharReader reader = new BufferedCharReader(new StringReader(";")); Assert.IsTrue(reader.More()); Assert.AreEqual(';', reader.Next()); Assert.IsFalse(reader.More()); reader.Back(); Assert.IsTrue(reader.More()); Assert.AreEqual(';', reader.Next()); Assert.IsFalse(reader.More()); }
public void CountersWhenBackNextAroundLine() { BufferedCharReader reader = new BufferedCharReader(new StringReader("12\n34")); reader.Next(); AssertCounters(reader, 1, 1, 1); reader.Next(); AssertCounters(reader, 2, 1, 2); reader.Next(); AssertCounters(reader, 3, 1, 3); reader.Next(); AssertCounters(reader, 4, 2, 1); reader.Back(); AssertCounters(reader, 3, 1, 3); reader.Next(); AssertCounters(reader, 4, 2, 1); }
private static char ParseHex(BufferedCharReader input, char[] hexDigits) { Debug.Assert(input != null); Debug.Assert(hexDigits != null); Debug.Assert(hexDigits.Length == 4); hexDigits[0] = input.Next(); hexDigits[1] = input.Next(); hexDigits[2] = input.Next(); hexDigits[3] = input.Next(); return((char)ushort.Parse(new string(hexDigits), NumberStyles.HexNumber)); }
public void CountersUnaffectedWhenReadingPastEOF() { BufferedCharReader reader = new BufferedCharReader(new StringReader("abc")); Assert.AreEqual('a', reader.Next()); Assert.AreEqual('b', reader.Next()); Assert.AreEqual('c', reader.Next()); Assert.IsFalse(reader.More()); Assert.AreEqual(0, reader.Next()); Assert.AreEqual(3, reader.CharCount, "CharCount"); Assert.AreEqual(1, reader.LineNumber, "LineNumber"); Assert.AreEqual(3, reader.LinePosition, "LinePosition"); }
public void CountersOnReadingFirstChar() { BufferedCharReader reader = new BufferedCharReader(new StringReader("a")); reader.Next(); AssertCounters(reader, 1, 1, 1); }
public void BackRewindsCounters() { BufferedCharReader reader = new BufferedCharReader(new StringReader("a")); reader.Next(); reader.Back(); AssertCounters(reader, 0, 0, 0); }
private JsonToken Parse() { char c = NextClean(); if (c == '"' || c == '\'') { return(Yield(JsonToken.String(NextString(c)))); } switch (c) { case '{': _reader.Back(); return(ParseObject()); case '[': _reader.Back(); return(ParseArray()); default: { StringBuilder stringBuilder = new StringBuilder(); char c2 = c; while (c >= ' ' && ",:]}/\\\"[{;=#".IndexOf(c) < 0) { stringBuilder.Append(c); c = _reader.Next(); } _reader.Back(); string text = stringBuilder.ToString().Trim(); if (text.Length == 0) { throw new JsonException("Missing value."); } if (text == "true" || text == "false") { return(Yield(JsonToken.Boolean(text == "true"))); } if (text == "null") { return(Yield(JsonToken.Null())); } if ((c2 >= '0' && c2 <= '9') || c2 == '.' || c2 == '-' || c2 == '+') { if (!double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out double _)) { throw new JsonException($"The text '{text}' has the incorrect syntax for a number."); } return(Yield(JsonToken.Number(text))); } return(Yield(JsonToken.String(text))); } } }
/// <summary> /// Parses the next token from the input and returns it. /// </summary> private JsonToken Parse() { char ch = NextClean(); // // String // if (ch == '"' || ch == '\'') { return(Yield(JsonToken.String(NextString(ch)))); } // // Object // if (ch == '{') { _reader.Back(); return(ParseObject()); } // // Array // if (ch == '[') { _reader.Back(); return(ParseArray()); } // // Handle unquoted text. This could be the values true, false, or // null, or it can be a number. An implementation (such as this one) // is allowed to also accept non-standard forms. // // Accumulate characters until we reach the end of the text or a // formatting character. // StringBuilder sb = new StringBuilder(); char b = ch; while (ch >= ' ' && ",:]}/\\\"[{;=#".IndexOf(ch) < 0) { sb.Append(ch); ch = _reader.Next(); } _reader.Back(); string s = sb.ToString().Trim(); if (s.Length == 0) { throw SyntaxError("Missing value."); } // // Boolean // if (s == JsonBoolean.TrueText || s == JsonBoolean.FalseText) { return(Yield(JsonToken.Boolean(s == JsonBoolean.TrueText))); } // // Null // if (s == JsonNull.Text) { return(Yield(JsonToken.Null())); } // // Number // // Try converting it. We support the 0- and 0x- conventions. // If a number cannot be produced, then the value will just // be a string. Note that the 0-, 0x-, plus, and implied // string conventions are non-standard, but a JSON text parser // is free to accept non-JSON text forms as long as it accepts // all correct JSON text forms. // if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') { if (b == '0' && s.Length > 1) { if (s.Length > 2 && (s[1] == 'x' || s[1] == 'X')) { string parsed = TryParseHex(s); if (!ReferenceEquals(parsed, s)) { return(Yield(JsonToken.Number(parsed))); } } else { string parsed = TryParseOctal(s); if (!ReferenceEquals(parsed, s)) { return(Yield(JsonToken.Number(parsed))); } } } else { double unused; if ((b == '-' && s.Length >= 2 && s[1] == 'I') || // rule out -Infinity that double parsing allows !double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out unused)) { throw SyntaxError(string.Format("The text '{0}' has the incorrect syntax for a number.", s)); } return(Yield(JsonToken.Number(s))); } } // // Treat as String in all other cases, e.g. when unquoted. // return(Yield(JsonToken.String(s))); }
internal static StringBuilder Dequote(BufferedCharReader input, char quote, StringBuilder output) { Debug.Assert(input != null); if (output == null) { output = new StringBuilder(); } char[] hexDigits = null; while (true) { char ch = input.Next(); if (ch == BufferedCharReader.EOF) { throw new FormatException("Unterminated string."); } if (ch == '\\') { ch = input.Next(); switch (ch) { case 'b': output.Append('\b'); break; // Backspace case 't': output.Append('\t'); break; // Horizontal tab case 'n': output.Append('\n'); break; // Newline case 'f': output.Append('\f'); break; // Form feed case 'r': output.Append('\r'); break; // Carriage return case 'u': { if (hexDigits == null) { hexDigits = new char[4]; } output.Append(ParseHex(input, hexDigits)); break; } default: output.Append(ch); break; } } else { if (ch == quote) { return(output); } output.Append(ch); } } }
private static void AssertReadLineNumPos(BufferedCharReader reader, char expected, int line, int pos) { Assert.AreEqual(expected, reader.Next(), "Read"); AssertLineCounters(reader, line, pos); }
internal static StringBuilder Dequote(BufferedCharReader input, char quote, StringBuilder output) { Debug.Assert(input != null); if (output == null) output = new StringBuilder(); char[] hexDigits = null; while (true) { char ch = input.Next(); if ((ch == BufferedCharReader.EOF) || (ch == '\n') || (ch == '\r')) throw new FormatException("Unterminated string."); if (ch == '\\') { ch = input.Next(); switch (ch) { case 'b': output.Append('\b'); break; // Backspace case 't': output.Append('\t'); break; // Horizontal tab case 'n': output.Append('\n'); break; // Newline case 'f': output.Append('\f'); break; // Form feed case 'r': output.Append('\r'); break; // Carriage return case 'u': { if (hexDigits == null) hexDigits = new char[4]; output.Append(ParseHex(input, hexDigits)); break; } default: output.Append(ch); break; } } else { if (ch == quote) return output; output.Append(ch); } } }
internal static StringBuilder Dequote(BufferedCharReader input, char quote, StringBuilder output) { Debug.Assert(input != null); if (output == null) { output = new StringBuilder(); } char[] array = null; while (true) { char c = input.Next(); switch (c) { case '\0': throw new FormatException("Unterminated string."); case '\\': c = input.Next(); switch (c) { case 'b': output.Append('\b'); break; case 't': output.Append('\t'); break; case 'n': output.Append('\n'); break; case 'f': output.Append('\f'); break; case 'r': output.Append('\r'); break; case 'u': if (array == null) { array = new char[4]; } output.Append(ParseHex(input, array)); break; default: output.Append(c); break; } break; default: if (c == quote) { return(output); } output.Append(c); break; } } }
/// <summary> /// Eats the next four characters, assuming hex digits, and converts /// into the represented character value. /// </summary> /// <returns>The parsed character.</returns> private static char ParseHex(BufferedCharReader input, char[] hexDigits) { Debug.Assert(input != null); Debug.Assert(hexDigits != null); Debug.Assert(hexDigits.Length == 4); hexDigits[0] = input.Next(); hexDigits[1] = input.Next(); hexDigits[2] = input.Next(); hexDigits[3] = input.Next(); return (char) ushort.Parse(new string(hexDigits), NumberStyles.HexNumber); }
/// <summary> /// Parses the next token from the input and returns it. /// </summary> private JsonToken Parse() { char ch = NextClean(); // // String // if (ch == '"' || ch == '\'') { return(Yield(JsonToken.String(NextString(ch)))); } // // Object // if (ch == '{') { _reader.Back(); return(ParseObject()); } // // Array // if (ch == '[') { _reader.Back(); return(ParseArray()); } // // Handle unquoted text. This could be the values true, false, or // null, or it can be a number. An implementation (such as this one) // is allowed to also accept non-standard forms. // // Accumulate characters until we reach the end of the text or a // formatting character. // StringBuilder sb = new StringBuilder(); char b = ch; while (ch >= ' ' && ",:]}/\\\"[{;=#".IndexOf(ch) < 0) { sb.Append(ch); ch = _reader.Next(); } _reader.Back(); string s = sb.ToString().Trim(); if (s.Length == 0) { throw new JsonException("Missing value."); } // // Boolean // if (s == JsonBoolean.TrueText || s == JsonBoolean.FalseText) { return(Yield(JsonToken.Boolean(s == JsonBoolean.TrueText))); } // // Null // if (s == JsonNull.Text) { return(Yield(JsonToken.Null())); } // // Number // if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') { double unused; if (!double.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out unused)) { throw new JsonException(string.Format("The text '{0}' has the incorrect syntax for a number.", s)); } return(Yield(JsonToken.Number(s))); } // // Treat as String in all other cases, e.g. when unquoted. // return(Yield(JsonToken.String(s))); }