// Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null // GameDataEditor.Json using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; using GameDataEditor; namespace GameDataEditor { public static class Json { private sealed class Parser : IDisposable { private enum TOKEN { NONE, CURLY_OPEN, CURLY_CLOSE, SQUARED_OPEN, SQUARED_CLOSE, COLON, COMMA, STRING, NUMBER, TRUE, FALSE, NULL } private const string WORD_BREAK = "{}[],:\""; private StringReader json; private char PeekChar => Convert.ToChar(json.Peek()); private char NextChar => Convert.ToChar(json.Read()); private string NextWord { get { StringBuilder stringBuilder = new StringBuilder(); while (!IsWordBreak(PeekChar)) { stringBuilder.Append(NextChar); if (json.Peek() == -1) { break; } } return stringBuilder.ToString(); } } private TOKEN NextToken { get { EatWhitespace(); if (json.Peek() == -1) { return TOKEN.NONE; } switch (PeekChar) { case '{': return TOKEN.CURLY_OPEN; case '}': json.Read(); return TOKEN.CURLY_CLOSE; case '[': return TOKEN.SQUARED_OPEN; case ']': json.Read(); return TOKEN.SQUARED_CLOSE; case ',': json.Read(); return TOKEN.COMMA; case '"': return TOKEN.STRING; case ':': return TOKEN.COLON; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return TOKEN.NUMBER; default: switch (NextWord) { case "false": return TOKEN.FALSE; case "true": return TOKEN.TRUE; case "null": return TOKEN.NULL; default: return TOKEN.NONE; } } } } private Parser(string jsonString) { json = new StringReader(jsonString); } public static bool IsWordBreak(char c) { return char.IsWhiteSpace(c) || "{}[],:\"".IndexOf(c) != -1; } public static object Parse(string jsonString) { using (Parser parser = new Parser(jsonString)) { return parser.ParseValue(); } } public void Dispose() { json.Dispose(); json = null; } private Dictionary ParseObject() { Dictionary dictionary = new Dictionary(); json.Read(); while (true) { switch (NextToken) { case TOKEN.COMMA: continue; case TOKEN.NONE: return null; case TOKEN.CURLY_CLOSE: return dictionary; } string text = ParseString(); if (text == null) { return null; } if (NextToken != TOKEN.COLON) { return null; } json.Read(); dictionary[text] = ParseValue(); } } private List ParseArray() { List list = new List(); json.Read(); bool flag = true; while (flag) { TOKEN nextToken = NextToken; switch (nextToken) { case TOKEN.NONE: return null; case TOKEN.SQUARED_CLOSE: flag = false; break; default: { object item = ParseByToken(nextToken); list.Add(item); break; } case TOKEN.COMMA: break; } } return list; } private object ParseValue() { TOKEN nextToken = NextToken; return ParseByToken(nextToken); } private object ParseByToken(TOKEN token) { switch (token) { case TOKEN.STRING: return ParseString(); case TOKEN.NUMBER: return ParseNumber(); case TOKEN.CURLY_OPEN: return ParseObject(); case TOKEN.SQUARED_OPEN: return ParseArray(); case TOKEN.TRUE: return true; case TOKEN.FALSE: return false; case TOKEN.NULL: return null; default: return null; }; } private string ParseString() { StringBuilder stringBuilder = new StringBuilder(); json.Read(); bool flag = true; while (flag) { if (json.Peek() == -1) { flag = false; break; } char nextChar = NextChar; switch (nextChar) { case '"': flag = false; break; case '\\': if (json.Peek() == -1) { flag = false; break; } nextChar = NextChar; switch (nextChar) { case '"': case '/': case '\\': stringBuilder.Append(nextChar); 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 'u': { char[] array = new char[4]; for (int i = 0; i < 4; i++) { array[i] = NextChar; } stringBuilder.Append((char)Convert.ToInt32(new string(array), 16)); break; } } break; default: stringBuilder.Append(nextChar); break; } } return stringBuilder.ToString(); } private object ParseNumber() { string nextWord = NextWord; if (nextWord.IndexOf('.') == -1) { long.TryParse(nextWord, out var result); return result; } double.TryParse(nextWord, out var result2); return result2; } private void EatWhitespace() { while (char.IsWhiteSpace(PeekChar)) { json.Read(); if (json.Peek() == -1) { break; } } } } private sealed class Serializer { private StringBuilder builder; private Serializer() { builder = new StringBuilder(); } public static string Serialize(object obj) { Serializer serializer = new Serializer(); serializer.SerializeValue(obj); return serializer.builder.ToString(); } private void SerializeValue(object value) { if (value == null) { builder.Append("null"); } else if (value is string str) { SerializeString(str); } else if (value is bool) { builder.Append((!(bool)value) ? "false" : "true"); } else if (value is IList anArray) { SerializeArray(anArray); } else if (value is IDictionary obj) { SerializeObject(obj); } else if (value is char) { SerializeString(new string((char)value, 1)); } else { SerializeOther(value); } } private void SerializeObject(IDictionary obj) { bool flag = true; builder.Append('{'); foreach (object key in obj.Keys) { if (!flag) { builder.Append(','); } SerializeString(key.ToString()); builder.Append(':'); SerializeValue(obj[key]); flag = false; } builder.Append('}'); } private void SerializeArray(IList anArray) { builder.Append('['); bool flag = true; foreach (object item in anArray) { if (!flag) { builder.Append(','); } SerializeValue(item); flag = false; } builder.Append(']'); } private void SerializeString(string str) { builder.Append('"'); char[] array = str.ToCharArray(); char[] array2 = array; foreach (char c in array2) { switch (c) { case '"': builder.Append("\\\""); continue; case '\\': builder.Append("\\\\"); continue; case '\b': builder.Append("\\b"); continue; case '\f': builder.Append("\\f"); continue; case '\n': builder.Append("\\n"); continue; case '\r': builder.Append("\\r"); continue; case '\t': builder.Append("\\t"); continue; } int num = Convert.ToInt32(c); if (num >= 32 && num <= 126) { builder.Append(c); continue; } builder.Append("\\u"); builder.Append(num.ToString("x4")); } builder.Append('"'); } private void SerializeOther(object value) { if (value is float) { builder.Append(((float)value).ToString("R")); } else if (value is int || value is uint || value is long || value is sbyte || value is byte || value is short || value is ushort || value is ulong) { builder.Append(value); } else if (value is double || value is decimal) { builder.Append(Convert.ToDouble(value).ToString("R")); } else { SerializeString(value.ToString()); } } } public static object Deserialize(string json) { if (json == null) { return null; } return Parser.Parse(json); } public static string Serialize(object obj) { return Serializer.Serialize(obj); } } }