mirror of
https://github.com/FriendshipIsEpic/FiE-Game.git
synced 2024-11-26 07:18:00 +01:00
462 lines
No EOL
8.7 KiB
C#
462 lines
No EOL
8.7 KiB
C#
// 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<string, object> ParseObject()
|
|
{
|
|
Dictionary<string, object> dictionary = new Dictionary<string, object>();
|
|
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<object> ParseArray()
|
|
{
|
|
List<object> list = new List<object>();
|
|
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);
|
|
}
|
|
}
|
|
} |