// /** // * File: JSONParser.cs // * Author: haraldwolff // * // * This file and it's content is copyrighted by the Author and / or copyright holder. // * Any use wihtout proper permission is illegal and may lead to legal actions. // * // * // **/ using System; using ln.type; using System.Text; using System.Globalization; using System.IO; namespace ln.json { public class JSONParser { static char[] chNull = new char[] { 'n', 'u', 'l', 'l' }; static char[] chTrue = new char[] { 't', 'r', 'u', 'e' }; static char[] chFalse = new char[] { 'f', 'a', 'l', 's', 'e' }; public static JSONValue Parse(String jsonSource) { return ParseValue(new StringReader(jsonSource)); } public static JSONValue Parse(TextReader reader) => ParseValue(reader); public static JSONValue ParseFile(string filename) { using (StreamReader streamReader = new StreamReader(filename)) return ParseValue(streamReader); } static void SkipWhitespace(TextReader reader) { while (char.IsWhiteSpace((char) reader.Peek()) && (reader.Peek()!=-1)) reader.Read(); } static void Read(TextReader reader, StringBuilder stringBuilder, Func condition) { int ch; while (condition((char) (ch = reader.Peek())) && (ch!=-1)) stringBuilder.Append((char)reader.Read()); } static JSONValue ParseValue(TextReader reader) { SkipWhitespace(reader); switch (reader.Peek()) { case '"': return parseString(reader); case 't': return parseTrue(reader); case 'f': return parseFalse(reader); case 'n': return parseNull(reader); case '[': return parseArray(reader); case '{': return parseObject(reader); case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': return parseNumber(reader); default: throw new FormatException(String.Format("Unexpected character: {0} [ 0x{0:x4} ]", reader.Peek())); } } static JSONString parseString(TextReader reader) { if (reader.Peek() != '"') throw new FormatException("Unexpected character"); StringBuilder stringBuilder = new StringBuilder(); reader.Read(); int ch; while ((ch = reader.Read()) != '"') { if (ch == -1) throw new EndOfStreamException(); stringBuilder.Append((char) ch); if (ch == '\\') stringBuilder.Append((char) reader.Read()); // if (ch == '\\') // { // ch = reader.Read(); // if (ch == -1) // throw new EndOfStreamException(); // switch (ch) // { // case '\\': // stringBuilder.Append('\\'); // break; // case '/': // stringBuilder.Append('/'); // break; // case 'b': // stringBuilder.Append('\b'); // break; // case 'f': // stringBuilder.Append('\f'); // break; // case 'n': // stringBuilder.Append('\n'); // break; // case 'r': // stringBuilder.Append('\r'); // break; // case 't': // stringBuilder.Append('\t'); // break; // case '"': // stringBuilder.Append('"'); // break; // case 'u': // char[] hexDigits = new char[4]; // reader.ReadBlock(hexDigits, 0, 4); // ch = int.Parse(hexDigits, System.Globalization.NumberStyles.HexNumber); // stringBuilder.Append((char) ch); // break; // default: // throw new FormatException(); // } // } // else // stringBuilder.Append((char) ch); } SkipWhitespace(reader); return new JSONString(JSONString.Unescape(stringBuilder.ToString())); } static JSONNumber parseNumber(TextReader reader) { StringBuilder sb = new StringBuilder(); if (reader.Peek() == '-') { sb.Append((char)reader.Read()); } Read(reader,sb,char.IsDigit); if (reader.Peek() == '.') { sb.Append('.'); reader.Read(); Read(reader,sb,char.IsDigit); } if ((reader.Peek() == 'e') || (reader.Peek() == 'E')) { sb.Append('e'); if ((reader.Peek() == '-')|| (reader.Peek() == '+')) { sb.Append((char)reader.Read()); } Read(reader, sb, char.IsDigit); } SkipWhitespace(reader); return new JSONNumber(decimal.Parse(sb.ToString(),CultureInfo.InvariantCulture)); } static JSONArray parseArray(TextReader reader) { if (reader.Peek() != '[') throw new FormatException("Unexpected character"); JSONArray array = new JSONArray(); reader.Read(); while (reader.Peek() != ']') { array.Add(ParseValue(reader)); if (reader.Peek() == ',') { reader.Read(); SkipWhitespace(reader); } } reader.Read(); SkipWhitespace(reader); return array; } static JSONObject parseObject(TextReader reader) { if (reader.Peek() != '{') throw new FormatException("Unexpected character"); JSONObject o = new JSONObject(); reader.Read(); SkipWhitespace(reader); while (reader.Peek() != '}') { JSONString s = parseString(reader); if (reader.Peek() != ':') throw new FormatException("expected :"); reader.Read(); o.Add(s.Value, ParseValue(reader)); if (reader.Peek() == ',') { reader.Read(); SkipWhitespace(reader); } } reader.Read(); SkipWhitespace(reader); return o; } static JSONTrue parseTrue(TextReader reader) { char[] ch = new char[4]; for (int n = 0; n < ch.Length; n++) { ch[n] = (char)reader.Read(); } if (ch.AreEqual(chTrue)) { SkipWhitespace(reader); return JSONTrue.Instance; } throw new FormatException(); } static JSONFalse parseFalse(TextReader reader) { char[] ch = new char[5]; for (int n = 0; n < ch.Length; n++) { ch[n] = (char)reader.Read(); } if (ch.AreEqual(chFalse)) { SkipWhitespace(reader); return JSONFalse.Instance; } throw new FormatException(); } static JSONNull parseNull(TextReader reader) { char[] ch = new char[4]; for (int n=0;n