From fc4b24891b2cc43dda08f2ac3119d54fe65e8e2b Mon Sep 17 00:00:00 2001 From: "DESKTOP-B25GA9E\\W35" <1733709035@qq.com> Date: Wed, 8 Mar 2023 09:07:14 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E4=B8=BA=E6=BA=90=E7=A0=81=E5=BC=95?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Plugin/LitJson.dll | Bin 58368 -> 0 bytes Assets/Plugin/LitJson.dll.meta | 33 - Assets/Plugin/LitJson.meta | 8 + Assets/Plugin/LitJson/AssemblyInfo.cs.in | 18 + Assets/Plugin/LitJson/AssemblyInfo.cs.in.meta | 7 + Assets/Plugin/LitJson/IJsonWrapper.cs | 60 + Assets/Plugin/LitJson/IJsonWrapper.cs.meta | 11 + Assets/Plugin/LitJson/JsonData.cs | 1059 +++++++++++++++++ Assets/Plugin/LitJson/JsonData.cs.meta | 11 + Assets/Plugin/LitJson/JsonException.cs | 65 + Assets/Plugin/LitJson/JsonException.cs.meta | 11 + Assets/Plugin/LitJson/JsonMapper.cs | 987 +++++++++++++++ Assets/Plugin/LitJson/JsonMapper.cs.meta | 11 + Assets/Plugin/LitJson/JsonMockWrapper.cs | 105 ++ Assets/Plugin/LitJson/JsonMockWrapper.cs.meta | 11 + Assets/Plugin/LitJson/JsonReader.cs | 478 ++++++++ Assets/Plugin/LitJson/JsonReader.cs.meta | 11 + Assets/Plugin/LitJson/JsonWriter.cs | 484 ++++++++ Assets/Plugin/LitJson/JsonWriter.cs.meta | 11 + Assets/Plugin/LitJson/Lexer.cs | 912 ++++++++++++++ Assets/Plugin/LitJson/Lexer.cs.meta | 11 + Assets/Plugin/LitJson/LitJSON.csproj.meta | 7 + .../Plugin/LitJson/Netstandard15Polyfill.cs | 24 + .../LitJson/Netstandard15Polyfill.cs.meta | 11 + Assets/Plugin/LitJson/ParserToken.cs | 44 + Assets/Plugin/LitJson/ParserToken.cs.meta | 11 + Assets/Plugin/LitJson/litjson.png | Bin 0 -> 3356 bytes Assets/Plugin/LitJson/litjson.png.meta | 92 ++ 28 files changed, 4460 insertions(+), 33 deletions(-) delete mode 100644 Assets/Plugin/LitJson.dll delete mode 100644 Assets/Plugin/LitJson.dll.meta create mode 100644 Assets/Plugin/LitJson.meta create mode 100644 Assets/Plugin/LitJson/AssemblyInfo.cs.in create mode 100644 Assets/Plugin/LitJson/AssemblyInfo.cs.in.meta create mode 100644 Assets/Plugin/LitJson/IJsonWrapper.cs create mode 100644 Assets/Plugin/LitJson/IJsonWrapper.cs.meta create mode 100644 Assets/Plugin/LitJson/JsonData.cs create mode 100644 Assets/Plugin/LitJson/JsonData.cs.meta create mode 100644 Assets/Plugin/LitJson/JsonException.cs create mode 100644 Assets/Plugin/LitJson/JsonException.cs.meta create mode 100644 Assets/Plugin/LitJson/JsonMapper.cs create mode 100644 Assets/Plugin/LitJson/JsonMapper.cs.meta create mode 100644 Assets/Plugin/LitJson/JsonMockWrapper.cs create mode 100644 Assets/Plugin/LitJson/JsonMockWrapper.cs.meta create mode 100644 Assets/Plugin/LitJson/JsonReader.cs create mode 100644 Assets/Plugin/LitJson/JsonReader.cs.meta create mode 100644 Assets/Plugin/LitJson/JsonWriter.cs create mode 100644 Assets/Plugin/LitJson/JsonWriter.cs.meta create mode 100644 Assets/Plugin/LitJson/Lexer.cs create mode 100644 Assets/Plugin/LitJson/Lexer.cs.meta create mode 100644 Assets/Plugin/LitJson/LitJSON.csproj.meta create mode 100644 Assets/Plugin/LitJson/Netstandard15Polyfill.cs create mode 100644 Assets/Plugin/LitJson/Netstandard15Polyfill.cs.meta create mode 100644 Assets/Plugin/LitJson/ParserToken.cs create mode 100644 Assets/Plugin/LitJson/ParserToken.cs.meta create mode 100644 Assets/Plugin/LitJson/litjson.png create mode 100644 Assets/Plugin/LitJson/litjson.png.meta diff --git a/Assets/Plugin/LitJson.dll b/Assets/Plugin/LitJson.dll deleted file mode 100644 index 9708a68237758aa9c598f03d04085fe509480466..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58368 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≦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 diff --git a/Assets/Plugin/LitJson.dll.meta b/Assets/Plugin/LitJson.dll.meta deleted file mode 100644 index 13f152f..0000000 --- a/Assets/Plugin/LitJson.dll.meta +++ /dev/null @@ -1,33 +0,0 @@ -fileFormatVersion: 2 -guid: c1e390103eefc6b428c4a597b86aeb92 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 0 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - Windows Store Apps: WindowsStoreApps - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Plugin/LitJson.meta b/Assets/Plugin/LitJson.meta new file mode 100644 index 0000000..cb1b56a --- /dev/null +++ b/Assets/Plugin/LitJson.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 24989a04c7189984cb5ec48003446fb6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/AssemblyInfo.cs.in b/Assets/Plugin/LitJson/AssemblyInfo.cs.in new file mode 100644 index 0000000..2cd1f90 --- /dev/null +++ b/Assets/Plugin/LitJson/AssemblyInfo.cs.in @@ -0,0 +1,18 @@ +using System; +using System.Reflection; +using System.Runtime.CompilerServices; + + +[assembly: CLSCompliant (true)] + +[assembly: AssemblyTitle ("LitJson")] +[assembly: AssemblyDescription ("LitJSON library")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("LitJSON")] +[assembly: AssemblyCopyright ( + "The authors disclaim copyright to this source code")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +[assembly: AssemblyVersion ("@ASSEMBLY_VERSION@")] diff --git a/Assets/Plugin/LitJson/AssemblyInfo.cs.in.meta b/Assets/Plugin/LitJson/AssemblyInfo.cs.in.meta new file mode 100644 index 0000000..dc5e60a --- /dev/null +++ b/Assets/Plugin/LitJson/AssemblyInfo.cs.in.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 62c5b44632e7f514cbaa9ed6169c0cda +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/IJsonWrapper.cs b/Assets/Plugin/LitJson/IJsonWrapper.cs new file mode 100644 index 0000000..9b7e2d1 --- /dev/null +++ b/Assets/Plugin/LitJson/IJsonWrapper.cs @@ -0,0 +1,60 @@ +#region Header +/** + * IJsonWrapper.cs + * Interface that represents a type capable of handling all kinds of JSON + * data. This is mainly used when mapping objects through JsonMapper, and + * it's implemented by JsonData. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System.Collections; +using System.Collections.Specialized; + + +namespace LitJson +{ + public enum JsonType + { + None, + + Object, + Array, + String, + Int, + Long, + Double, + Boolean + } + + public interface IJsonWrapper : IList, IOrderedDictionary + { + bool IsArray { get; } + bool IsBoolean { get; } + bool IsDouble { get; } + bool IsInt { get; } + bool IsLong { get; } + bool IsObject { get; } + bool IsString { get; } + + bool GetBoolean (); + double GetDouble (); + int GetInt (); + JsonType GetJsonType (); + long GetLong (); + string GetString (); + + void SetBoolean (bool val); + void SetDouble (double val); + void SetInt (int val); + void SetJsonType (JsonType type); + void SetLong (long val); + void SetString (string val); + + string ToJson (); + void ToJson (JsonWriter writer); + } +} diff --git a/Assets/Plugin/LitJson/IJsonWrapper.cs.meta b/Assets/Plugin/LitJson/IJsonWrapper.cs.meta new file mode 100644 index 0000000..50305cb --- /dev/null +++ b/Assets/Plugin/LitJson/IJsonWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb44247cc2867754296abb0cc48fe239 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/JsonData.cs b/Assets/Plugin/LitJson/JsonData.cs new file mode 100644 index 0000000..e89e4b1 --- /dev/null +++ b/Assets/Plugin/LitJson/JsonData.cs @@ -0,0 +1,1059 @@ +#region Header +/** + * JsonData.cs + * Generic type to hold JSON data (objects, arrays, and so on). This is + * the default type returned by JsonMapper.ToObject(). + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; + + +namespace LitJson +{ + public class JsonData : IJsonWrapper, IEquatable + { + #region Fields + private IList inst_array; + private bool inst_boolean; + private double inst_double; + private int inst_int; + private long inst_long; + private IDictionary inst_object; + private string inst_string; + private string json; + private JsonType type; + + // Used to implement the IOrderedDictionary interface + private IList> object_list; + #endregion + + + #region Properties + public int Count { + get { return EnsureCollection ().Count; } + } + + public bool IsArray { + get { return type == JsonType.Array; } + } + + public bool IsBoolean { + get { return type == JsonType.Boolean; } + } + + public bool IsDouble { + get { return type == JsonType.Double; } + } + + public bool IsInt { + get { return type == JsonType.Int; } + } + + public bool IsLong { + get { return type == JsonType.Long; } + } + + public bool IsObject { + get { return type == JsonType.Object; } + } + + public bool IsString { + get { return type == JsonType.String; } + } + + public ICollection Keys { + get { EnsureDictionary (); return inst_object.Keys; } + } + + /// + /// Determines whether the json contains an element that has the specified key. + /// + /// The key to locate in the json. + /// true if the json contains an element that has the specified key; otherwise, false. + public Boolean ContainsKey(String key) { + EnsureDictionary(); + return this.inst_object.Keys.Contains(key); + } + #endregion + + + #region ICollection Properties + int ICollection.Count { + get { + return Count; + } + } + + bool ICollection.IsSynchronized { + get { + return EnsureCollection ().IsSynchronized; + } + } + + object ICollection.SyncRoot { + get { + return EnsureCollection ().SyncRoot; + } + } + #endregion + + + #region IDictionary Properties + bool IDictionary.IsFixedSize { + get { + return EnsureDictionary ().IsFixedSize; + } + } + + bool IDictionary.IsReadOnly { + get { + return EnsureDictionary ().IsReadOnly; + } + } + + ICollection IDictionary.Keys { + get { + EnsureDictionary (); + IList keys = new List (); + + foreach (KeyValuePair entry in + object_list) { + keys.Add (entry.Key); + } + + return (ICollection) keys; + } + } + + ICollection IDictionary.Values { + get { + EnsureDictionary (); + IList values = new List (); + + foreach (KeyValuePair entry in + object_list) { + values.Add (entry.Value); + } + + return (ICollection) values; + } + } + #endregion + + + + #region IJsonWrapper Properties + bool IJsonWrapper.IsArray { + get { return IsArray; } + } + + bool IJsonWrapper.IsBoolean { + get { return IsBoolean; } + } + + bool IJsonWrapper.IsDouble { + get { return IsDouble; } + } + + bool IJsonWrapper.IsInt { + get { return IsInt; } + } + + bool IJsonWrapper.IsLong { + get { return IsLong; } + } + + bool IJsonWrapper.IsObject { + get { return IsObject; } + } + + bool IJsonWrapper.IsString { + get { return IsString; } + } + #endregion + + + #region IList Properties + bool IList.IsFixedSize { + get { + return EnsureList ().IsFixedSize; + } + } + + bool IList.IsReadOnly { + get { + return EnsureList ().IsReadOnly; + } + } + #endregion + + + #region IDictionary Indexer + object IDictionary.this[object key] { + get { + return EnsureDictionary ()[key]; + } + + set { + if (! (key is String)) + throw new ArgumentException ( + "The key has to be a string"); + + JsonData data = ToJsonData (value); + + this[(string) key] = data; + } + } + #endregion + + + #region IOrderedDictionary Indexer + object IOrderedDictionary.this[int idx] { + get { + EnsureDictionary (); + return object_list[idx].Value; + } + + set { + EnsureDictionary (); + JsonData data = ToJsonData (value); + + KeyValuePair old_entry = object_list[idx]; + + inst_object[old_entry.Key] = data; + + KeyValuePair entry = + new KeyValuePair (old_entry.Key, data); + + object_list[idx] = entry; + } + } + #endregion + + + #region IList Indexer + object IList.this[int index] { + get { + return EnsureList ()[index]; + } + + set { + EnsureList (); + JsonData data = ToJsonData (value); + + this[index] = data; + } + } + #endregion + + + #region Public Indexers + public JsonData this[string prop_name] { + get { + EnsureDictionary (); + return inst_object[prop_name]; + } + + set { + EnsureDictionary (); + + KeyValuePair entry = + new KeyValuePair (prop_name, value); + + if (inst_object.ContainsKey (prop_name)) { + for (int i = 0; i < object_list.Count; i++) { + if (object_list[i].Key == prop_name) { + object_list[i] = entry; + break; + } + } + } else + object_list.Add (entry); + + inst_object[prop_name] = value; + + json = null; + } + } + + public JsonData this[int index] { + get { + EnsureCollection (); + + if (type == JsonType.Array) + return inst_array[index]; + + return object_list[index].Value; + } + + set { + EnsureCollection (); + + if (type == JsonType.Array) + inst_array[index] = value; + else { + KeyValuePair entry = object_list[index]; + KeyValuePair new_entry = + new KeyValuePair (entry.Key, value); + + object_list[index] = new_entry; + inst_object[entry.Key] = value; + } + + json = null; + } + } + #endregion + + + #region Constructors + public JsonData () + { + } + + public JsonData (bool boolean) + { + type = JsonType.Boolean; + inst_boolean = boolean; + } + + public JsonData (double number) + { + type = JsonType.Double; + inst_double = number; + } + + public JsonData (int number) + { + type = JsonType.Int; + inst_int = number; + } + + public JsonData (long number) + { + type = JsonType.Long; + inst_long = number; + } + + public JsonData (object obj) + { + if (obj is Boolean) { + type = JsonType.Boolean; + inst_boolean = (bool) obj; + return; + } + + if (obj is Double) { + type = JsonType.Double; + inst_double = (double) obj; + return; + } + + if (obj is Int32) { + type = JsonType.Int; + inst_int = (int) obj; + return; + } + + if (obj is Int64) { + type = JsonType.Long; + inst_long = (long) obj; + return; + } + + if (obj is String) { + type = JsonType.String; + inst_string = (string) obj; + return; + } + + throw new ArgumentException ( + "Unable to wrap the given object with JsonData"); + } + + public JsonData (string str) + { + type = JsonType.String; + inst_string = str; + } + #endregion + + + #region Implicit Conversions + public static implicit operator JsonData (Boolean data) + { + return new JsonData (data); + } + + public static implicit operator JsonData (Double data) + { + return new JsonData (data); + } + + public static implicit operator JsonData (Int32 data) + { + return new JsonData (data); + } + + public static implicit operator JsonData (Int64 data) + { + return new JsonData (data); + } + + public static implicit operator JsonData (String data) + { + return new JsonData (data); + } + #endregion + + + #region Explicit Conversions + public static explicit operator Boolean (JsonData data) + { + if (data.type != JsonType.Boolean) + throw new InvalidCastException ( + "Instance of JsonData doesn't hold a double"); + + return data.inst_boolean; + } + + public static explicit operator Double (JsonData data) + { + if (data.type != JsonType.Double) + throw new InvalidCastException ( + "Instance of JsonData doesn't hold a double"); + + return data.inst_double; + } + + public static explicit operator Int32(JsonData data) + { + if (data.type != JsonType.Int && data.type != JsonType.Long) + { + throw new InvalidCastException( + "Instance of JsonData doesn't hold an int"); + } + + // cast may truncate data... but that's up to the user to consider + return data.type == JsonType.Int ? data.inst_int : (int)data.inst_long; + } + + public static explicit operator Int64(JsonData data) + { + if (data.type != JsonType.Long && data.type != JsonType.Int) + { + throw new InvalidCastException( + "Instance of JsonData doesn't hold a long"); + } + + return data.type == JsonType.Long ? data.inst_long : data.inst_int; + } + + public static explicit operator String (JsonData data) + { + if (data.type != JsonType.String) + throw new InvalidCastException ( + "Instance of JsonData doesn't hold a string"); + + return data.inst_string; + } + #endregion + + + #region ICollection Methods + void ICollection.CopyTo (Array array, int index) + { + EnsureCollection ().CopyTo (array, index); + } + #endregion + + + #region IDictionary Methods + void IDictionary.Add (object key, object value) + { + JsonData data = ToJsonData (value); + + EnsureDictionary ().Add (key, data); + + KeyValuePair entry = + new KeyValuePair ((string) key, data); + object_list.Add (entry); + + json = null; + } + + void IDictionary.Clear () + { + EnsureDictionary ().Clear (); + object_list.Clear (); + json = null; + } + + bool IDictionary.Contains (object key) + { + return EnsureDictionary ().Contains (key); + } + + IDictionaryEnumerator IDictionary.GetEnumerator () + { + return ((IOrderedDictionary) this).GetEnumerator (); + } + + void IDictionary.Remove (object key) + { + EnsureDictionary ().Remove (key); + + for (int i = 0; i < object_list.Count; i++) { + if (object_list[i].Key == (string) key) { + object_list.RemoveAt (i); + break; + } + } + + json = null; + } + #endregion + + + #region IEnumerable Methods + IEnumerator IEnumerable.GetEnumerator () + { + return EnsureCollection ().GetEnumerator (); + } + #endregion + + + #region IJsonWrapper Methods + bool IJsonWrapper.GetBoolean () + { + if (type != JsonType.Boolean) + throw new InvalidOperationException ( + "JsonData instance doesn't hold a boolean"); + + return inst_boolean; + } + + double IJsonWrapper.GetDouble () + { + if (type != JsonType.Double) + throw new InvalidOperationException ( + "JsonData instance doesn't hold a double"); + + return inst_double; + } + + int IJsonWrapper.GetInt () + { + if (type != JsonType.Int) + throw new InvalidOperationException ( + "JsonData instance doesn't hold an int"); + + return inst_int; + } + + long IJsonWrapper.GetLong () + { + if (type != JsonType.Long) + throw new InvalidOperationException ( + "JsonData instance doesn't hold a long"); + + return inst_long; + } + + string IJsonWrapper.GetString () + { + if (type != JsonType.String) + throw new InvalidOperationException ( + "JsonData instance doesn't hold a string"); + + return inst_string; + } + + void IJsonWrapper.SetBoolean (bool val) + { + type = JsonType.Boolean; + inst_boolean = val; + json = null; + } + + void IJsonWrapper.SetDouble (double val) + { + type = JsonType.Double; + inst_double = val; + json = null; + } + + void IJsonWrapper.SetInt (int val) + { + type = JsonType.Int; + inst_int = val; + json = null; + } + + void IJsonWrapper.SetLong (long val) + { + type = JsonType.Long; + inst_long = val; + json = null; + } + + void IJsonWrapper.SetString (string val) + { + type = JsonType.String; + inst_string = val; + json = null; + } + + string IJsonWrapper.ToJson () + { + return ToJson (); + } + + void IJsonWrapper.ToJson (JsonWriter writer) + { + ToJson (writer); + } + #endregion + + + #region IList Methods + int IList.Add (object value) + { + return Add (value); + } + + void IList.Clear () + { + EnsureList ().Clear (); + json = null; + } + + bool IList.Contains (object value) + { + return EnsureList ().Contains (value); + } + + int IList.IndexOf (object value) + { + return EnsureList ().IndexOf (value); + } + + void IList.Insert (int index, object value) + { + EnsureList ().Insert (index, value); + json = null; + } + + void IList.Remove (object value) + { + EnsureList ().Remove (value); + json = null; + } + + void IList.RemoveAt (int index) + { + EnsureList ().RemoveAt (index); + json = null; + } + #endregion + + + #region IOrderedDictionary Methods + IDictionaryEnumerator IOrderedDictionary.GetEnumerator () + { + EnsureDictionary (); + + return new OrderedDictionaryEnumerator ( + object_list.GetEnumerator ()); + } + + void IOrderedDictionary.Insert (int idx, object key, object value) + { + string property = (string) key; + JsonData data = ToJsonData (value); + + this[property] = data; + + KeyValuePair entry = + new KeyValuePair (property, data); + + object_list.Insert (idx, entry); + } + + void IOrderedDictionary.RemoveAt (int idx) + { + EnsureDictionary (); + + inst_object.Remove (object_list[idx].Key); + object_list.RemoveAt (idx); + } + #endregion + + + #region Private Methods + private ICollection EnsureCollection () + { + if (type == JsonType.Array) + return (ICollection) inst_array; + + if (type == JsonType.Object) + return (ICollection) inst_object; + + throw new InvalidOperationException ( + "The JsonData instance has to be initialized first"); + } + + private IDictionary EnsureDictionary () + { + if (type == JsonType.Object) + return (IDictionary) inst_object; + + if (type != JsonType.None) + throw new InvalidOperationException ( + "Instance of JsonData is not a dictionary"); + + type = JsonType.Object; + inst_object = new Dictionary (); + object_list = new List> (); + + return (IDictionary) inst_object; + } + + private IList EnsureList () + { + if (type == JsonType.Array) + return (IList) inst_array; + + if (type != JsonType.None) + throw new InvalidOperationException ( + "Instance of JsonData is not a list"); + + type = JsonType.Array; + inst_array = new List (); + + return (IList) inst_array; + } + + private JsonData ToJsonData (object obj) + { + if (obj == null) + return null; + + if (obj is JsonData) + return (JsonData) obj; + + return new JsonData (obj); + } + + private static void WriteJson (IJsonWrapper obj, JsonWriter writer) + { + if (obj == null) { + writer.Write (null); + return; + } + + if (obj.IsString) { + writer.Write (obj.GetString ()); + return; + } + + if (obj.IsBoolean) { + writer.Write (obj.GetBoolean ()); + return; + } + + if (obj.IsDouble) { + writer.Write (obj.GetDouble ()); + return; + } + + if (obj.IsInt) { + writer.Write (obj.GetInt ()); + return; + } + + if (obj.IsLong) { + writer.Write (obj.GetLong ()); + return; + } + + if (obj.IsArray) { + writer.WriteArrayStart (); + foreach (object elem in (IList) obj) + WriteJson ((JsonData) elem, writer); + writer.WriteArrayEnd (); + + return; + } + + if (obj.IsObject) { + writer.WriteObjectStart (); + + foreach (DictionaryEntry entry in ((IDictionary) obj)) { + writer.WritePropertyName ((string) entry.Key); + WriteJson ((JsonData) entry.Value, writer); + } + writer.WriteObjectEnd (); + + return; + } + } + #endregion + + + public int Add (object value) + { + JsonData data = ToJsonData (value); + + json = null; + + return EnsureList ().Add (data); + } + + public bool Remove(object obj) + { + json = null; + if(IsObject) + { + JsonData value = null; + if (inst_object.TryGetValue((string)obj, out value)) + return inst_object.Remove((string)obj) && object_list.Remove(new KeyValuePair((string)obj, value)); + else + throw new KeyNotFoundException("The specified key was not found in the JsonData object."); + } + if(IsArray) + { + return inst_array.Remove(ToJsonData(obj)); + } + throw new InvalidOperationException ( + "Instance of JsonData is not an object or a list."); + } + + public void Clear () + { + if (IsObject) { + ((IDictionary) this).Clear (); + return; + } + + if (IsArray) { + ((IList) this).Clear (); + return; + } + } + + public bool Equals (JsonData x) + { + if (x == null) + return false; + + if (x.type != this.type) + { + // further check to see if this is a long to int comparison + if ((x.type != JsonType.Int && x.type != JsonType.Long) + || (this.type != JsonType.Int && this.type != JsonType.Long)) + { + return false; + } + } + + switch (this.type) { + case JsonType.None: + return true; + + case JsonType.Object: + return this.inst_object.Equals (x.inst_object); + + case JsonType.Array: + return this.inst_array.Equals (x.inst_array); + + case JsonType.String: + return this.inst_string.Equals (x.inst_string); + + case JsonType.Int: + { + if (x.IsLong) + { + if (x.inst_long < Int32.MinValue || x.inst_long > Int32.MaxValue) + return false; + return this.inst_int.Equals((int)x.inst_long); + } + return this.inst_int.Equals(x.inst_int); + } + + case JsonType.Long: + { + if (x.IsInt) + { + if (this.inst_long < Int32.MinValue || this.inst_long > Int32.MaxValue) + return false; + return x.inst_int.Equals((int)this.inst_long); + } + return this.inst_long.Equals(x.inst_long); + } + + case JsonType.Double: + return this.inst_double.Equals (x.inst_double); + + case JsonType.Boolean: + return this.inst_boolean.Equals (x.inst_boolean); + } + + return false; + } + + public JsonType GetJsonType () + { + return type; + } + + public void SetJsonType (JsonType type) + { + if (this.type == type) + return; + + switch (type) { + case JsonType.None: + break; + + case JsonType.Object: + inst_object = new Dictionary (); + object_list = new List> (); + break; + + case JsonType.Array: + inst_array = new List (); + break; + + case JsonType.String: + inst_string = default (String); + break; + + case JsonType.Int: + inst_int = default (Int32); + break; + + case JsonType.Long: + inst_long = default (Int64); + break; + + case JsonType.Double: + inst_double = default (Double); + break; + + case JsonType.Boolean: + inst_boolean = default (Boolean); + break; + } + + this.type = type; + } + + public string ToJson () + { + if (json != null) + return json; + + StringWriter sw = new StringWriter (); + JsonWriter writer = new JsonWriter (sw); + writer.Validate = false; + + WriteJson (this, writer); + json = sw.ToString (); + + return json; + } + + public void ToJson (JsonWriter writer) + { + bool old_validate = writer.Validate; + + writer.Validate = false; + + WriteJson (this, writer); + + writer.Validate = old_validate; + } + + public override string ToString () + { + switch (type) { + case JsonType.Array: + return "JsonData array"; + + case JsonType.Boolean: + return inst_boolean.ToString (); + + case JsonType.Double: + return inst_double.ToString (); + + case JsonType.Int: + return inst_int.ToString (); + + case JsonType.Long: + return inst_long.ToString (); + + case JsonType.Object: + return "JsonData object"; + + case JsonType.String: + return inst_string; + } + + return "Uninitialized JsonData"; + } + } + + + internal class OrderedDictionaryEnumerator : IDictionaryEnumerator + { + IEnumerator> list_enumerator; + + + public object Current { + get { return Entry; } + } + + public DictionaryEntry Entry { + get { + KeyValuePair curr = list_enumerator.Current; + return new DictionaryEntry (curr.Key, curr.Value); + } + } + + public object Key { + get { return list_enumerator.Current.Key; } + } + + public object Value { + get { return list_enumerator.Current.Value; } + } + + + public OrderedDictionaryEnumerator ( + IEnumerator> enumerator) + { + list_enumerator = enumerator; + } + + + public bool MoveNext () + { + return list_enumerator.MoveNext (); + } + + public void Reset () + { + list_enumerator.Reset (); + } + } +} diff --git a/Assets/Plugin/LitJson/JsonData.cs.meta b/Assets/Plugin/LitJson/JsonData.cs.meta new file mode 100644 index 0000000..992beec --- /dev/null +++ b/Assets/Plugin/LitJson/JsonData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ba9ae4dfe94b3c429e3c53e1c98fb3a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/JsonException.cs b/Assets/Plugin/LitJson/JsonException.cs new file mode 100644 index 0000000..4efd890 --- /dev/null +++ b/Assets/Plugin/LitJson/JsonException.cs @@ -0,0 +1,65 @@ +#region Header +/** + * JsonException.cs + * Base class throwed by LitJSON when a parsing error occurs. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; + + +namespace LitJson +{ + public class JsonException : +#if NETSTANDARD1_5 + Exception +#else + ApplicationException +#endif + { + public JsonException () : base () + { + } + + internal JsonException (ParserToken token) : + base (String.Format ( + "Invalid token '{0}' in input string", token)) + { + } + + internal JsonException (ParserToken token, + Exception inner_exception) : + base (String.Format ( + "Invalid token '{0}' in input string", token), + inner_exception) + { + } + + internal JsonException (int c) : + base (String.Format ( + "Invalid character '{0}' in input string", (char) c)) + { + } + + internal JsonException (int c, Exception inner_exception) : + base (String.Format ( + "Invalid character '{0}' in input string", (char) c), + inner_exception) + { + } + + + public JsonException (string message) : base (message) + { + } + + public JsonException (string message, Exception inner_exception) : + base (message, inner_exception) + { + } + } +} diff --git a/Assets/Plugin/LitJson/JsonException.cs.meta b/Assets/Plugin/LitJson/JsonException.cs.meta new file mode 100644 index 0000000..66e10a6 --- /dev/null +++ b/Assets/Plugin/LitJson/JsonException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9867c685641adf747be0d8e36823cb43 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/JsonMapper.cs b/Assets/Plugin/LitJson/JsonMapper.cs new file mode 100644 index 0000000..99946cf --- /dev/null +++ b/Assets/Plugin/LitJson/JsonMapper.cs @@ -0,0 +1,987 @@ +#region Header +/** + * JsonMapper.cs + * JSON to .Net object and object to JSON conversions. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; + + +namespace LitJson +{ + internal struct PropertyMetadata + { + public MemberInfo Info; + public bool IsField; + public Type Type; + } + + + internal struct ArrayMetadata + { + private Type element_type; + private bool is_array; + private bool is_list; + + + public Type ElementType { + get { + if (element_type == null) + return typeof (JsonData); + + return element_type; + } + + set { element_type = value; } + } + + public bool IsArray { + get { return is_array; } + set { is_array = value; } + } + + public bool IsList { + get { return is_list; } + set { is_list = value; } + } + } + + + internal struct ObjectMetadata + { + private Type element_type; + private bool is_dictionary; + + private IDictionary properties; + + + public Type ElementType { + get { + if (element_type == null) + return typeof (JsonData); + + return element_type; + } + + set { element_type = value; } + } + + public bool IsDictionary { + get { return is_dictionary; } + set { is_dictionary = value; } + } + + public IDictionary Properties { + get { return properties; } + set { properties = value; } + } + } + + + internal delegate void ExporterFunc (object obj, JsonWriter writer); + public delegate void ExporterFunc (T obj, JsonWriter writer); + + internal delegate object ImporterFunc (object input); + public delegate TValue ImporterFunc (TJson input); + + public delegate IJsonWrapper WrapperFactory (); + + + public class JsonMapper + { + #region Fields + private static readonly int max_nesting_depth; + + private static readonly IFormatProvider datetime_format; + + private static readonly IDictionary base_exporters_table; + private static readonly IDictionary custom_exporters_table; + + private static readonly IDictionary> base_importers_table; + private static readonly IDictionary> custom_importers_table; + + private static readonly IDictionary array_metadata; + private static readonly object array_metadata_lock = new Object (); + + private static readonly IDictionary> conv_ops; + private static readonly object conv_ops_lock = new Object (); + + private static readonly IDictionary object_metadata; + private static readonly object object_metadata_lock = new Object (); + + private static readonly IDictionary> type_properties; + private static readonly object type_properties_lock = new Object (); + + private static readonly JsonWriter static_writer; + private static readonly object static_writer_lock = new Object (); + #endregion + + + #region Constructors + static JsonMapper () + { + max_nesting_depth = 100; + + array_metadata = new Dictionary (); + conv_ops = new Dictionary> (); + object_metadata = new Dictionary (); + type_properties = new Dictionary> (); + + static_writer = new JsonWriter (); + + datetime_format = DateTimeFormatInfo.InvariantInfo; + + base_exporters_table = new Dictionary (); + custom_exporters_table = new Dictionary (); + + base_importers_table = new Dictionary> (); + custom_importers_table = new Dictionary> (); + + RegisterBaseExporters (); + RegisterBaseImporters (); + } + #endregion + + + #region Private Methods + private static void AddArrayMetadata (Type type) + { + if (array_metadata.ContainsKey (type)) + return; + + ArrayMetadata data = new ArrayMetadata (); + + data.IsArray = type.IsArray; + + if (type.GetInterface ("System.Collections.IList") != null) + data.IsList = true; + + foreach (PropertyInfo p_info in type.GetProperties ()) { + if (p_info.Name != "Item") + continue; + + ParameterInfo[] parameters = p_info.GetIndexParameters (); + + if (parameters.Length != 1) + continue; + + if (parameters[0].ParameterType == typeof (int)) + data.ElementType = p_info.PropertyType; + } + + lock (array_metadata_lock) { + try { + array_metadata.Add (type, data); + } catch (ArgumentException) { + return; + } + } + } + + private static void AddObjectMetadata (Type type) + { + if (object_metadata.ContainsKey (type)) + return; + + ObjectMetadata data = new ObjectMetadata (); + + if (type.GetInterface ("System.Collections.IDictionary") != null) + data.IsDictionary = true; + + data.Properties = new Dictionary (); + + foreach (PropertyInfo p_info in type.GetProperties ()) { + if (p_info.Name == "Item") { + ParameterInfo[] parameters = p_info.GetIndexParameters (); + + if (parameters.Length != 1) + continue; + + if (parameters[0].ParameterType == typeof (string)) + data.ElementType = p_info.PropertyType; + + continue; + } + + PropertyMetadata p_data = new PropertyMetadata (); + p_data.Info = p_info; + p_data.Type = p_info.PropertyType; + + data.Properties.Add (p_info.Name, p_data); + } + + foreach (FieldInfo f_info in type.GetFields ()) { + PropertyMetadata p_data = new PropertyMetadata (); + p_data.Info = f_info; + p_data.IsField = true; + p_data.Type = f_info.FieldType; + + data.Properties.Add (f_info.Name, p_data); + } + + lock (object_metadata_lock) { + try { + object_metadata.Add (type, data); + } catch (ArgumentException) { + return; + } + } + } + + private static void AddTypeProperties (Type type) + { + if (type_properties.ContainsKey (type)) + return; + + IList props = new List (); + + foreach (PropertyInfo p_info in type.GetProperties ()) { + if (p_info.Name == "Item") + continue; + + PropertyMetadata p_data = new PropertyMetadata (); + p_data.Info = p_info; + p_data.IsField = false; + props.Add (p_data); + } + + foreach (FieldInfo f_info in type.GetFields ()) { + PropertyMetadata p_data = new PropertyMetadata (); + p_data.Info = f_info; + p_data.IsField = true; + + props.Add (p_data); + } + + lock (type_properties_lock) { + try { + type_properties.Add (type, props); + } catch (ArgumentException) { + return; + } + } + } + + private static MethodInfo GetConvOp (Type t1, Type t2) + { + lock (conv_ops_lock) { + if (! conv_ops.ContainsKey (t1)) + conv_ops.Add (t1, new Dictionary ()); + } + + if (conv_ops[t1].ContainsKey (t2)) + return conv_ops[t1][t2]; + + MethodInfo op = t1.GetMethod ( + "op_Implicit", new Type[] { t2 }); + + lock (conv_ops_lock) { + try { + conv_ops[t1].Add (t2, op); + } catch (ArgumentException) { + return conv_ops[t1][t2]; + } + } + + return op; + } + + private static object ReadValue (Type inst_type, JsonReader reader) + { + reader.Read (); + + if (reader.Token == JsonToken.ArrayEnd) + return null; + + Type underlying_type = Nullable.GetUnderlyingType(inst_type); + Type value_type = underlying_type ?? inst_type; + + if (reader.Token == JsonToken.Null) { + #if NETSTANDARD1_5 + if (inst_type.IsClass() || underlying_type != null) { + return null; + } + #else + if (inst_type.IsClass || underlying_type != null) { + return null; + } + #endif + + throw new JsonException (String.Format ( + "Can't assign null to an instance of type {0}", + inst_type)); + } + + if (reader.Token == JsonToken.Double || + reader.Token == JsonToken.Int || + reader.Token == JsonToken.Long || + reader.Token == JsonToken.String || + reader.Token == JsonToken.Boolean) { + + Type json_type = reader.Value.GetType (); + + if (value_type.IsAssignableFrom (json_type)) + return reader.Value; + + // If there's a custom importer that fits, use it + if (custom_importers_table.ContainsKey (json_type) && + custom_importers_table[json_type].ContainsKey ( + value_type)) { + + ImporterFunc importer = + custom_importers_table[json_type][value_type]; + + return importer (reader.Value); + } + + // Maybe there's a base importer that works + if (base_importers_table.ContainsKey (json_type) && + base_importers_table[json_type].ContainsKey ( + value_type)) { + + ImporterFunc importer = + base_importers_table[json_type][value_type]; + + return importer (reader.Value); + } + + // Maybe it's an enum + #if NETSTANDARD1_5 + if (value_type.IsEnum()) + return Enum.ToObject (value_type, reader.Value); + #else + if (value_type.IsEnum) + return Enum.ToObject (value_type, reader.Value); + #endif + // Try using an implicit conversion operator + MethodInfo conv_op = GetConvOp (value_type, json_type); + + if (conv_op != null) + return conv_op.Invoke (null, + new object[] { reader.Value }); + + // No luck + throw new JsonException (String.Format ( + "Can't assign value '{0}' (type {1}) to type {2}", + reader.Value, json_type, inst_type)); + } + + object instance = null; + + if (reader.Token == JsonToken.ArrayStart) { + + AddArrayMetadata (inst_type); + ArrayMetadata t_data = array_metadata[inst_type]; + + if (! t_data.IsArray && ! t_data.IsList) + throw new JsonException (String.Format ( + "Type {0} can't act as an array", + inst_type)); + + IList list; + Type elem_type; + + if (! t_data.IsArray) { + list = (IList) Activator.CreateInstance (inst_type); + elem_type = t_data.ElementType; + } else { + list = new ArrayList (); + elem_type = inst_type.GetElementType (); + } + + list.Clear(); + + while (true) { + object item = ReadValue (elem_type, reader); + if (item == null && reader.Token == JsonToken.ArrayEnd) + break; + + list.Add (item); + } + + if (t_data.IsArray) { + int n = list.Count; + instance = Array.CreateInstance (elem_type, n); + + for (int i = 0; i < n; i++) + ((Array) instance).SetValue (list[i], i); + } else + instance = list; + + } else if (reader.Token == JsonToken.ObjectStart) { + AddObjectMetadata (value_type); + ObjectMetadata t_data = object_metadata[value_type]; + + instance = Activator.CreateInstance (value_type); + + while (true) { + reader.Read (); + + if (reader.Token == JsonToken.ObjectEnd) + break; + + string property = (string) reader.Value; + + if (t_data.Properties.ContainsKey (property)) { + PropertyMetadata prop_data = + t_data.Properties[property]; + + if (prop_data.IsField) { + ((FieldInfo) prop_data.Info).SetValue ( + instance, ReadValue (prop_data.Type, reader)); + } else { + PropertyInfo p_info = + (PropertyInfo) prop_data.Info; + + if (p_info.CanWrite) + p_info.SetValue ( + instance, + ReadValue (prop_data.Type, reader), + null); + else + ReadValue (prop_data.Type, reader); + } + + } else { + if (! t_data.IsDictionary) { + + if (! reader.SkipNonMembers) { + throw new JsonException (String.Format ( + "The type {0} doesn't have the " + + "property '{1}'", + inst_type, property)); + } else { + ReadSkip (reader); + continue; + } + } + + ((IDictionary) instance).Add ( + property, ReadValue ( + t_data.ElementType, reader)); + } + + } + + } + + return instance; + } + + private static IJsonWrapper ReadValue (WrapperFactory factory, + JsonReader reader) + { + reader.Read (); + + if (reader.Token == JsonToken.ArrayEnd || + reader.Token == JsonToken.Null) + return null; + + IJsonWrapper instance = factory (); + + if (reader.Token == JsonToken.String) { + instance.SetString ((string) reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Double) { + instance.SetDouble ((double) reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Int) { + instance.SetInt ((int) reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Long) { + instance.SetLong ((long) reader.Value); + return instance; + } + + if (reader.Token == JsonToken.Boolean) { + instance.SetBoolean ((bool) reader.Value); + return instance; + } + + if (reader.Token == JsonToken.ArrayStart) { + instance.SetJsonType (JsonType.Array); + + while (true) { + IJsonWrapper item = ReadValue (factory, reader); + if (item == null && reader.Token == JsonToken.ArrayEnd) + break; + + ((IList) instance).Add (item); + } + } + else if (reader.Token == JsonToken.ObjectStart) { + instance.SetJsonType (JsonType.Object); + + while (true) { + reader.Read (); + + if (reader.Token == JsonToken.ObjectEnd) + break; + + string property = (string) reader.Value; + + ((IDictionary) instance)[property] = ReadValue ( + factory, reader); + } + + } + + return instance; + } + + private static void ReadSkip (JsonReader reader) + { + ToWrapper ( + delegate { return new JsonMockWrapper (); }, reader); + } + + private static void RegisterBaseExporters () + { + base_exporters_table[typeof (byte)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((byte) obj)); + }; + + base_exporters_table[typeof (char)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToString ((char) obj)); + }; + + base_exporters_table[typeof (DateTime)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToString ((DateTime) obj, + datetime_format)); + }; + + base_exporters_table[typeof (decimal)] = + delegate (object obj, JsonWriter writer) { + writer.Write ((decimal) obj); + }; + + base_exporters_table[typeof (sbyte)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((sbyte) obj)); + }; + + base_exporters_table[typeof (short)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((short) obj)); + }; + + base_exporters_table[typeof (ushort)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToInt32 ((ushort) obj)); + }; + + base_exporters_table[typeof (uint)] = + delegate (object obj, JsonWriter writer) { + writer.Write (Convert.ToUInt64 ((uint) obj)); + }; + + base_exporters_table[typeof (ulong)] = + delegate (object obj, JsonWriter writer) { + writer.Write ((ulong) obj); + }; + + base_exporters_table[typeof(DateTimeOffset)] = + delegate (object obj, JsonWriter writer) { + writer.Write(((DateTimeOffset)obj).ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", datetime_format)); + }; + } + + private static void RegisterBaseImporters () + { + ImporterFunc importer; + + importer = delegate (object input) { + return Convert.ToByte ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (byte), importer); + + importer = delegate (object input) { + return Convert.ToUInt64 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (ulong), importer); + + importer = delegate (object input) { + return Convert.ToInt64((int)input); + }; + RegisterImporter(base_importers_table, typeof(int), + typeof(long), importer); + + importer = delegate (object input) { + return Convert.ToSByte ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (sbyte), importer); + + importer = delegate (object input) { + return Convert.ToInt16 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (short), importer); + + importer = delegate (object input) { + return Convert.ToUInt16 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (ushort), importer); + + importer = delegate (object input) { + return Convert.ToUInt32 ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (uint), importer); + + importer = delegate (object input) { + return Convert.ToSingle ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (float), importer); + + importer = delegate (object input) { + return Convert.ToDouble ((int) input); + }; + RegisterImporter (base_importers_table, typeof (int), + typeof (double), importer); + + importer = delegate (object input) { + return Convert.ToDecimal ((double) input); + }; + RegisterImporter (base_importers_table, typeof (double), + typeof (decimal), importer); + + importer = delegate (object input) { + return Convert.ToSingle((double)input); + }; + RegisterImporter(base_importers_table, typeof(double), + typeof(float), importer); + + importer = delegate (object input) { + return Convert.ToUInt32 ((long) input); + }; + RegisterImporter (base_importers_table, typeof (long), + typeof (uint), importer); + + importer = delegate (object input) { + return Convert.ToChar ((string) input); + }; + RegisterImporter (base_importers_table, typeof (string), + typeof (char), importer); + + importer = delegate (object input) { + return Convert.ToDateTime ((string) input, datetime_format); + }; + RegisterImporter (base_importers_table, typeof (string), + typeof (DateTime), importer); + + importer = delegate (object input) { + return DateTimeOffset.Parse((string)input, datetime_format); + }; + RegisterImporter(base_importers_table, typeof(string), + typeof(DateTimeOffset), importer); + } + + private static void RegisterImporter ( + IDictionary> table, + Type json_type, Type value_type, ImporterFunc importer) + { + if (! table.ContainsKey (json_type)) + table.Add (json_type, new Dictionary ()); + + table[json_type][value_type] = importer; + } + + private static void WriteValue (object obj, JsonWriter writer, + bool writer_is_private, + int depth) + { + if (depth > max_nesting_depth) + throw new JsonException ( + String.Format ("Max allowed object depth reached while " + + "trying to export from type {0}", + obj.GetType ())); + + if (obj == null) { + writer.Write (null); + return; + } + + if (obj is IJsonWrapper) { + if (writer_is_private) + writer.TextWriter.Write (((IJsonWrapper) obj).ToJson ()); + else + ((IJsonWrapper) obj).ToJson (writer); + + return; + } + + if (obj is String) { + writer.Write ((string) obj); + return; + } + + if (obj is Double) { + writer.Write ((double) obj); + return; + } + + if (obj is Single) + { + writer.Write((float)obj); + return; + } + + if (obj is Int32) { + writer.Write ((int) obj); + return; + } + + if (obj is Boolean) { + writer.Write ((bool) obj); + return; + } + + if (obj is Int64) { + writer.Write ((long) obj); + return; + } + + if (obj is Array) { + writer.WriteArrayStart (); + + foreach (object elem in (Array) obj) + WriteValue (elem, writer, writer_is_private, depth + 1); + + writer.WriteArrayEnd (); + + return; + } + + if (obj is IList) { + writer.WriteArrayStart (); + foreach (object elem in (IList) obj) + WriteValue (elem, writer, writer_is_private, depth + 1); + writer.WriteArrayEnd (); + + return; + } + + if (obj is IDictionary dictionary) { + writer.WriteObjectStart (); + foreach (DictionaryEntry entry in dictionary) { + var propertyName = entry.Key is string key ? + key + : Convert.ToString(entry.Key, CultureInfo.InvariantCulture); + writer.WritePropertyName (propertyName); + WriteValue (entry.Value, writer, writer_is_private, + depth + 1); + } + writer.WriteObjectEnd (); + + return; + } + + Type obj_type = obj.GetType (); + + // See if there's a custom exporter for the object + if (custom_exporters_table.ContainsKey (obj_type)) { + ExporterFunc exporter = custom_exporters_table[obj_type]; + exporter (obj, writer); + + return; + } + + // If not, maybe there's a base exporter + if (base_exporters_table.ContainsKey (obj_type)) { + ExporterFunc exporter = base_exporters_table[obj_type]; + exporter (obj, writer); + + return; + } + + // Last option, let's see if it's an enum + if (obj is Enum) { + Type e_type = Enum.GetUnderlyingType (obj_type); + + if (e_type == typeof (long)) + writer.Write ((long) obj); + else if (e_type == typeof (uint)) + writer.Write ((uint) obj); + else if (e_type == typeof (ulong)) + writer.Write ((ulong) obj); + else if (e_type == typeof(ushort)) + writer.Write ((ushort)obj); + else if (e_type == typeof(short)) + writer.Write ((short)obj); + else if (e_type == typeof(byte)) + writer.Write ((byte)obj); + else if (e_type == typeof(sbyte)) + writer.Write ((sbyte)obj); + else + writer.Write ((int) obj); + + return; + } + + // Okay, so it looks like the input should be exported as an + // object + AddTypeProperties (obj_type); + IList props = type_properties[obj_type]; + + writer.WriteObjectStart (); + foreach (PropertyMetadata p_data in props) { + if (p_data.IsField) { + writer.WritePropertyName (p_data.Info.Name); + WriteValue (((FieldInfo) p_data.Info).GetValue (obj), + writer, writer_is_private, depth + 1); + } + else { + PropertyInfo p_info = (PropertyInfo) p_data.Info; + + if (p_info.CanRead) { + writer.WritePropertyName (p_data.Info.Name); + WriteValue (p_info.GetValue (obj, null), + writer, writer_is_private, depth + 1); + } + } + } + writer.WriteObjectEnd (); + } + #endregion + + + public static string ToJson (object obj) + { + lock (static_writer_lock) { + static_writer.Reset (); + + WriteValue (obj, static_writer, true, 0); + + return static_writer.ToString (); + } + } + + public static void ToJson (object obj, JsonWriter writer) + { + WriteValue (obj, writer, false, 0); + } + + public static JsonData ToObject (JsonReader reader) + { + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, reader); + } + + public static JsonData ToObject (TextReader reader) + { + JsonReader json_reader = new JsonReader (reader); + + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, json_reader); + } + + public static JsonData ToObject (string json) + { + return (JsonData) ToWrapper ( + delegate { return new JsonData (); }, json); + } + + public static T ToObject (JsonReader reader) + { + return (T) ReadValue (typeof (T), reader); + } + + public static T ToObject (TextReader reader) + { + JsonReader json_reader = new JsonReader (reader); + + return (T) ReadValue (typeof (T), json_reader); + } + + public static T ToObject (string json) + { + JsonReader reader = new JsonReader (json); + + return (T) ReadValue (typeof (T), reader); + } + + public static object ToObject(string json, Type ConvertType ) + { + JsonReader reader = new JsonReader(json); + + return ReadValue(ConvertType, reader); + } + + public static IJsonWrapper ToWrapper (WrapperFactory factory, + JsonReader reader) + { + return ReadValue (factory, reader); + } + + public static IJsonWrapper ToWrapper (WrapperFactory factory, + string json) + { + JsonReader reader = new JsonReader (json); + + return ReadValue (factory, reader); + } + + public static void RegisterExporter (ExporterFunc exporter) + { + ExporterFunc exporter_wrapper = + delegate (object obj, JsonWriter writer) { + exporter ((T) obj, writer); + }; + + custom_exporters_table[typeof (T)] = exporter_wrapper; + } + + public static void RegisterImporter ( + ImporterFunc importer) + { + ImporterFunc importer_wrapper = + delegate (object input) { + return importer ((TJson) input); + }; + + RegisterImporter (custom_importers_table, typeof (TJson), + typeof (TValue), importer_wrapper); + } + + public static void UnregisterExporters () + { + custom_exporters_table.Clear (); + } + + public static void UnregisterImporters () + { + custom_importers_table.Clear (); + } + } +} diff --git a/Assets/Plugin/LitJson/JsonMapper.cs.meta b/Assets/Plugin/LitJson/JsonMapper.cs.meta new file mode 100644 index 0000000..fb2c4d4 --- /dev/null +++ b/Assets/Plugin/LitJson/JsonMapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 496f84edeb6468045a3c9cfc026b963a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/JsonMockWrapper.cs b/Assets/Plugin/LitJson/JsonMockWrapper.cs new file mode 100644 index 0000000..dfe7adb --- /dev/null +++ b/Assets/Plugin/LitJson/JsonMockWrapper.cs @@ -0,0 +1,105 @@ +#region Header +/** + * JsonMockWrapper.cs + * Mock object implementing IJsonWrapper, to facilitate actions like + * skipping data more efficiently. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections; +using System.Collections.Specialized; + + +namespace LitJson +{ + public class JsonMockWrapper : IJsonWrapper + { + public bool IsArray { get { return false; } } + public bool IsBoolean { get { return false; } } + public bool IsDouble { get { return false; } } + public bool IsInt { get { return false; } } + public bool IsLong { get { return false; } } + public bool IsObject { get { return false; } } + public bool IsString { get { return false; } } + + public bool GetBoolean () { return false; } + public double GetDouble () { return 0.0; } + public int GetInt () { return 0; } + public JsonType GetJsonType () { return JsonType.None; } + public long GetLong () { return 0L; } + public string GetString () { return ""; } + + public void SetBoolean (bool val) {} + public void SetDouble (double val) {} + public void SetInt (int val) {} + public void SetJsonType (JsonType type) {} + public void SetLong (long val) {} + public void SetString (string val) {} + + public string ToJson () { return ""; } + public void ToJson (JsonWriter writer) {} + + + bool IList.IsFixedSize { get { return true; } } + bool IList.IsReadOnly { get { return true; } } + + object IList.this[int index] { + get { return null; } + set {} + } + + int IList.Add (object value) { return 0; } + void IList.Clear () {} + bool IList.Contains (object value) { return false; } + int IList.IndexOf (object value) { return -1; } + void IList.Insert (int i, object v) {} + void IList.Remove (object value) {} + void IList.RemoveAt (int index) {} + + + int ICollection.Count { get { return 0; } } + bool ICollection.IsSynchronized { get { return false; } } + object ICollection.SyncRoot { get { return null; } } + + void ICollection.CopyTo (Array array, int index) {} + + + IEnumerator IEnumerable.GetEnumerator () { return null; } + + + bool IDictionary.IsFixedSize { get { return true; } } + bool IDictionary.IsReadOnly { get { return true; } } + + ICollection IDictionary.Keys { get { return null; } } + ICollection IDictionary.Values { get { return null; } } + + object IDictionary.this[object key] { + get { return null; } + set {} + } + + void IDictionary.Add (object k, object v) {} + void IDictionary.Clear () {} + bool IDictionary.Contains (object key) { return false; } + void IDictionary.Remove (object key) {} + + IDictionaryEnumerator IDictionary.GetEnumerator () { return null; } + + + object IOrderedDictionary.this[int idx] { + get { return null; } + set {} + } + + IDictionaryEnumerator IOrderedDictionary.GetEnumerator () { + return null; + } + void IOrderedDictionary.Insert (int i, object k, object v) {} + void IOrderedDictionary.RemoveAt (int i) {} + } +} diff --git a/Assets/Plugin/LitJson/JsonMockWrapper.cs.meta b/Assets/Plugin/LitJson/JsonMockWrapper.cs.meta new file mode 100644 index 0000000..60dd0fe --- /dev/null +++ b/Assets/Plugin/LitJson/JsonMockWrapper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a6cf14146c882034b8e1e1cf5c467ec1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/JsonReader.cs b/Assets/Plugin/LitJson/JsonReader.cs new file mode 100644 index 0000000..e47eabc --- /dev/null +++ b/Assets/Plugin/LitJson/JsonReader.cs @@ -0,0 +1,478 @@ +#region Header +/** + * JsonReader.cs + * Stream-like access to JSON text. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; + + +namespace LitJson +{ + public enum JsonToken + { + None, + + ObjectStart, + PropertyName, + ObjectEnd, + + ArrayStart, + ArrayEnd, + + Int, + Long, + Double, + + String, + + Boolean, + Null + } + + + public class JsonReader + { + #region Fields + private static readonly IDictionary> parse_table; + + private Stack automaton_stack; + private int current_input; + private int current_symbol; + private bool end_of_json; + private bool end_of_input; + private Lexer lexer; + private bool parser_in_string; + private bool parser_return; + private bool read_started; + private TextReader reader; + private bool reader_is_owned; + private bool skip_non_members; + private object token_value; + private JsonToken token; + #endregion + + + #region Public Properties + public bool AllowComments { + get { return lexer.AllowComments; } + set { lexer.AllowComments = value; } + } + + public bool AllowSingleQuotedStrings { + get { return lexer.AllowSingleQuotedStrings; } + set { lexer.AllowSingleQuotedStrings = value; } + } + + public bool SkipNonMembers { + get { return skip_non_members; } + set { skip_non_members = value; } + } + + public bool EndOfInput { + get { return end_of_input; } + } + + public bool EndOfJson { + get { return end_of_json; } + } + + public JsonToken Token { + get { return token; } + } + + public object Value { + get { return token_value; } + } + #endregion + + + #region Constructors + static JsonReader () + { + parse_table = PopulateParseTable (); + } + + public JsonReader (string json_text) : + this (new StringReader (json_text), true) + { + } + + public JsonReader (TextReader reader) : + this (reader, false) + { + } + + private JsonReader (TextReader reader, bool owned) + { + if (reader == null) + throw new ArgumentNullException ("reader"); + + parser_in_string = false; + parser_return = false; + + read_started = false; + automaton_stack = new Stack (); + automaton_stack.Push ((int) ParserToken.End); + automaton_stack.Push ((int) ParserToken.Text); + + lexer = new Lexer (reader); + + end_of_input = false; + end_of_json = false; + + skip_non_members = true; + + this.reader = reader; + reader_is_owned = owned; + } + #endregion + + + #region Static Methods + private static IDictionary> PopulateParseTable () + { + // See section A.2. of the manual for details + IDictionary> parse_table = new Dictionary> (); + + TableAddRow (parse_table, ParserToken.Array); + TableAddCol (parse_table, ParserToken.Array, '[', + '[', + (int) ParserToken.ArrayPrime); + + TableAddRow (parse_table, ParserToken.ArrayPrime); + TableAddCol (parse_table, ParserToken.ArrayPrime, '"', + (int) ParserToken.Value, + + (int) ParserToken.ValueRest, + ']'); + TableAddCol (parse_table, ParserToken.ArrayPrime, '[', + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + TableAddCol (parse_table, ParserToken.ArrayPrime, ']', + ']'); + TableAddCol (parse_table, ParserToken.ArrayPrime, '{', + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Number, + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.True, + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.False, + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Null, + (int) ParserToken.Value, + (int) ParserToken.ValueRest, + ']'); + + TableAddRow (parse_table, ParserToken.Object); + TableAddCol (parse_table, ParserToken.Object, '{', + '{', + (int) ParserToken.ObjectPrime); + + TableAddRow (parse_table, ParserToken.ObjectPrime); + TableAddCol (parse_table, ParserToken.ObjectPrime, '"', + (int) ParserToken.Pair, + (int) ParserToken.PairRest, + '}'); + TableAddCol (parse_table, ParserToken.ObjectPrime, '}', + '}'); + + TableAddRow (parse_table, ParserToken.Pair); + TableAddCol (parse_table, ParserToken.Pair, '"', + (int) ParserToken.String, + ':', + (int) ParserToken.Value); + + TableAddRow (parse_table, ParserToken.PairRest); + TableAddCol (parse_table, ParserToken.PairRest, ',', + ',', + (int) ParserToken.Pair, + (int) ParserToken.PairRest); + TableAddCol (parse_table, ParserToken.PairRest, '}', + (int) ParserToken.Epsilon); + + TableAddRow (parse_table, ParserToken.String); + TableAddCol (parse_table, ParserToken.String, '"', + '"', + (int) ParserToken.CharSeq, + '"'); + + TableAddRow (parse_table, ParserToken.Text); + TableAddCol (parse_table, ParserToken.Text, '[', + (int) ParserToken.Array); + TableAddCol (parse_table, ParserToken.Text, '{', + (int) ParserToken.Object); + + TableAddRow (parse_table, ParserToken.Value); + TableAddCol (parse_table, ParserToken.Value, '"', + (int) ParserToken.String); + TableAddCol (parse_table, ParserToken.Value, '[', + (int) ParserToken.Array); + TableAddCol (parse_table, ParserToken.Value, '{', + (int) ParserToken.Object); + TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Number, + (int) ParserToken.Number); + TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.True, + (int) ParserToken.True); + TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.False, + (int) ParserToken.False); + TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Null, + (int) ParserToken.Null); + + TableAddRow (parse_table, ParserToken.ValueRest); + TableAddCol (parse_table, ParserToken.ValueRest, ',', + ',', + (int) ParserToken.Value, + (int) ParserToken.ValueRest); + TableAddCol (parse_table, ParserToken.ValueRest, ']', + (int) ParserToken.Epsilon); + + return parse_table; + } + + private static void TableAddCol (IDictionary> parse_table, ParserToken row, int col, + params int[] symbols) + { + parse_table[(int) row].Add (col, symbols); + } + + private static void TableAddRow (IDictionary> parse_table, ParserToken rule) + { + parse_table.Add ((int) rule, new Dictionary ()); + } + #endregion + + + #region Private Methods + private void ProcessNumber (string number) + { + if (number.IndexOf ('.') != -1 || + number.IndexOf ('e') != -1 || + number.IndexOf ('E') != -1) { + + double n_double; + if (double.TryParse (number, NumberStyles.Any, CultureInfo.InvariantCulture, out n_double)) { + token = JsonToken.Double; + token_value = n_double; + + return; + } + } + + int n_int32; + if (int.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int32)) { + token = JsonToken.Int; + token_value = n_int32; + + return; + } + + long n_int64; + if (long.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int64)) { + token = JsonToken.Long; + token_value = n_int64; + + return; + } + + ulong n_uint64; + if (ulong.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_uint64)) + { + token = JsonToken.Long; + token_value = n_uint64; + + return; + } + + // Shouldn't happen, but just in case, return something + token = JsonToken.Int; + token_value = 0; + } + + private void ProcessSymbol () + { + if (current_symbol == '[') { + token = JsonToken.ArrayStart; + parser_return = true; + + } else if (current_symbol == ']') { + token = JsonToken.ArrayEnd; + parser_return = true; + + } else if (current_symbol == '{') { + token = JsonToken.ObjectStart; + parser_return = true; + + } else if (current_symbol == '}') { + token = JsonToken.ObjectEnd; + parser_return = true; + + } else if (current_symbol == '"') { + if (parser_in_string) { + parser_in_string = false; + + parser_return = true; + + } else { + if (token == JsonToken.None) + token = JsonToken.String; + + parser_in_string = true; + } + + } else if (current_symbol == (int) ParserToken.CharSeq) { + token_value = lexer.StringValue; + + } else if (current_symbol == (int) ParserToken.False) { + token = JsonToken.Boolean; + token_value = false; + parser_return = true; + + } else if (current_symbol == (int) ParserToken.Null) { + token = JsonToken.Null; + parser_return = true; + + } else if (current_symbol == (int) ParserToken.Number) { + ProcessNumber (lexer.StringValue); + + parser_return = true; + + } else if (current_symbol == (int) ParserToken.Pair) { + token = JsonToken.PropertyName; + + } else if (current_symbol == (int) ParserToken.True) { + token = JsonToken.Boolean; + token_value = true; + parser_return = true; + + } + } + + private bool ReadToken () + { + if (end_of_input) + return false; + + lexer.NextToken (); + + if (lexer.EndOfInput) { + Close (); + + return false; + } + + current_input = lexer.Token; + + return true; + } + #endregion + + + public void Close () + { + if (end_of_input) + return; + + end_of_input = true; + end_of_json = true; + + if (reader_is_owned) + { + using(reader){} + } + + reader = null; + } + + public bool Read () + { + if (end_of_input) + return false; + + if (end_of_json) { + end_of_json = false; + automaton_stack.Clear (); + automaton_stack.Push ((int) ParserToken.End); + automaton_stack.Push ((int) ParserToken.Text); + } + + parser_in_string = false; + parser_return = false; + + token = JsonToken.None; + token_value = null; + + if (! read_started) { + read_started = true; + + if (! ReadToken ()) + return false; + } + + + int[] entry_symbols; + + while (true) { + if (parser_return) { + if (automaton_stack.Peek () == (int) ParserToken.End) + end_of_json = true; + + return true; + } + + current_symbol = automaton_stack.Pop (); + + ProcessSymbol (); + + if (current_symbol == current_input) { + if (! ReadToken ()) { + if (automaton_stack.Peek () != (int) ParserToken.End) + throw new JsonException ( + "Input doesn't evaluate to proper JSON text"); + + if (parser_return) + return true; + + return false; + } + + continue; + } + + try { + + entry_symbols = + parse_table[current_symbol][current_input]; + + } catch (KeyNotFoundException e) { + throw new JsonException ((ParserToken) current_input, e); + } + + if (entry_symbols[0] == (int) ParserToken.Epsilon) + continue; + + for (int i = entry_symbols.Length - 1; i >= 0; i--) + automaton_stack.Push (entry_symbols[i]); + } + } + + } +} diff --git a/Assets/Plugin/LitJson/JsonReader.cs.meta b/Assets/Plugin/LitJson/JsonReader.cs.meta new file mode 100644 index 0000000..559da80 --- /dev/null +++ b/Assets/Plugin/LitJson/JsonReader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 084113975cf9bfd48a72aa8809c523c9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/JsonWriter.cs b/Assets/Plugin/LitJson/JsonWriter.cs new file mode 100644 index 0000000..4bfaaac --- /dev/null +++ b/Assets/Plugin/LitJson/JsonWriter.cs @@ -0,0 +1,484 @@ +#region Header +/** + * JsonWriter.cs + * Stream-like facility to output JSON text. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; + + +namespace LitJson +{ + internal enum Condition + { + InArray, + InObject, + NotAProperty, + Property, + Value + } + + internal class WriterContext + { + public int Count; + public bool InArray; + public bool InObject; + public bool ExpectingValue; + public int Padding; + } + + public class JsonWriter + { + #region Fields + private static readonly NumberFormatInfo number_format; + + private WriterContext context; + private Stack ctx_stack; + private bool has_reached_end; + private char[] hex_seq; + private int indentation; + private int indent_value; + private StringBuilder inst_string_builder; + private bool pretty_print; + private bool validate; + private bool lower_case_properties; + private TextWriter writer; + #endregion + + + #region Properties + public int IndentValue { + get { return indent_value; } + set { + indentation = (indentation / indent_value) * value; + indent_value = value; + } + } + + public bool PrettyPrint { + get { return pretty_print; } + set { pretty_print = value; } + } + + public TextWriter TextWriter { + get { return writer; } + } + + public bool Validate { + get { return validate; } + set { validate = value; } + } + + public bool LowerCaseProperties { + get { return lower_case_properties; } + set { lower_case_properties = value; } + } + #endregion + + + #region Constructors + static JsonWriter () + { + number_format = NumberFormatInfo.InvariantInfo; + } + + public JsonWriter () + { + inst_string_builder = new StringBuilder (); + writer = new StringWriter (inst_string_builder); + + Init (); + } + + public JsonWriter (StringBuilder sb) : + this (new StringWriter (sb)) + { + } + + public JsonWriter (TextWriter writer) + { + if (writer == null) + throw new ArgumentNullException ("writer"); + + this.writer = writer; + + Init (); + } + #endregion + + + #region Private Methods + private void DoValidation (Condition cond) + { + if (! context.ExpectingValue) + context.Count++; + + if (! validate) + return; + + if (has_reached_end) + throw new JsonException ( + "A complete JSON symbol has already been written"); + + switch (cond) { + case Condition.InArray: + if (! context.InArray) + throw new JsonException ( + "Can't close an array here"); + break; + + case Condition.InObject: + if (! context.InObject || context.ExpectingValue) + throw new JsonException ( + "Can't close an object here"); + break; + + case Condition.NotAProperty: + if (context.InObject && ! context.ExpectingValue) + throw new JsonException ( + "Expected a property"); + break; + + case Condition.Property: + if (! context.InObject || context.ExpectingValue) + throw new JsonException ( + "Can't add a property here"); + break; + + case Condition.Value: + if (! context.InArray && + (! context.InObject || ! context.ExpectingValue)) + throw new JsonException ( + "Can't add a value here"); + + break; + } + } + + private void Init () + { + has_reached_end = false; + hex_seq = new char[4]; + indentation = 0; + indent_value = 4; + pretty_print = false; + validate = true; + lower_case_properties = false; + + ctx_stack = new Stack (); + context = new WriterContext (); + ctx_stack.Push (context); + } + + private static void IntToHex (int n, char[] hex) + { + int num; + + for (int i = 0; i < 4; i++) { + num = n % 16; + + if (num < 10) + hex[3 - i] = (char) ('0' + num); + else + hex[3 - i] = (char) ('A' + (num - 10)); + + n >>= 4; + } + } + + private void Indent () + { + if (pretty_print) + indentation += indent_value; + } + + + private void Put (string str) + { + if (pretty_print && ! context.ExpectingValue) + for (int i = 0; i < indentation; i++) + writer.Write (' '); + + writer.Write (str); + } + + private void PutNewline () + { + PutNewline (true); + } + + private void PutNewline (bool add_comma) + { + if (add_comma && ! context.ExpectingValue && + context.Count > 1) + writer.Write (','); + + if (pretty_print && ! context.ExpectingValue) + writer.Write (Environment.NewLine); + } + + private void PutString (string str) + { + Put (String.Empty); + + writer.Write ('"'); + + int n = str.Length; + for (int i = 0; i < n; i++) { + switch (str[i]) { + case '\n': + writer.Write ("\\n"); + continue; + + case '\r': + writer.Write ("\\r"); + continue; + + case '\t': + writer.Write ("\\t"); + continue; + + case '"': + case '\\': + writer.Write ('\\'); + writer.Write (str[i]); + continue; + + case '\f': + writer.Write ("\\f"); + continue; + + case '\b': + writer.Write ("\\b"); + continue; + } + + if ((int) str[i] >= 32 && (int) str[i] <= 126) { + writer.Write (str[i]); + continue; + } + + // Default, turn into a \uXXXX sequence + IntToHex ((int) str[i], hex_seq); + writer.Write ("\\u"); + writer.Write (hex_seq); + } + + writer.Write ('"'); + } + + private void Unindent () + { + if (pretty_print) + indentation -= indent_value; + } + #endregion + + + public override string ToString () + { + if (inst_string_builder == null) + return String.Empty; + + return inst_string_builder.ToString (); + } + + public void Reset () + { + has_reached_end = false; + + ctx_stack.Clear (); + context = new WriterContext (); + ctx_stack.Push (context); + + if (inst_string_builder != null) + inst_string_builder.Remove (0, inst_string_builder.Length); + } + + public void Write (bool boolean) + { + DoValidation (Condition.Value); + PutNewline (); + + Put (boolean ? "true" : "false"); + + context.ExpectingValue = false; + } + + public void Write (decimal number) + { + DoValidation (Condition.Value); + PutNewline (); + + Put (Convert.ToString (number, number_format)); + + context.ExpectingValue = false; + } + + public void Write (double number) + { + DoValidation (Condition.Value); + PutNewline (); + + string str = Convert.ToString (number, number_format); + Put (str); + + if (str.IndexOf ('.') == -1 && + str.IndexOf ('E') == -1) + writer.Write (".0"); + + context.ExpectingValue = false; + } + + public void Write(float number) + { + DoValidation(Condition.Value); + PutNewline(); + + string str = Convert.ToString(number, number_format); + Put(str); + + context.ExpectingValue = false; + } + + public void Write (int number) + { + DoValidation (Condition.Value); + PutNewline (); + + Put (Convert.ToString (number, number_format)); + + context.ExpectingValue = false; + } + + public void Write (long number) + { + DoValidation (Condition.Value); + PutNewline (); + + Put (Convert.ToString (number, number_format)); + + context.ExpectingValue = false; + } + + public void Write (string str) + { + DoValidation (Condition.Value); + PutNewline (); + + if (str == null) + Put ("null"); + else + PutString (str); + + context.ExpectingValue = false; + } + + [CLSCompliant(false)] + public void Write (ulong number) + { + DoValidation (Condition.Value); + PutNewline (); + + Put (Convert.ToString (number, number_format)); + + context.ExpectingValue = false; + } + + public void WriteArrayEnd () + { + DoValidation (Condition.InArray); + PutNewline (false); + + ctx_stack.Pop (); + if (ctx_stack.Count == 1) + has_reached_end = true; + else { + context = ctx_stack.Peek (); + context.ExpectingValue = false; + } + + Unindent (); + Put ("]"); + } + + public void WriteArrayStart () + { + DoValidation (Condition.NotAProperty); + PutNewline (); + + Put ("["); + + context = new WriterContext (); + context.InArray = true; + ctx_stack.Push (context); + + Indent (); + } + + public void WriteObjectEnd () + { + DoValidation (Condition.InObject); + PutNewline (false); + + ctx_stack.Pop (); + if (ctx_stack.Count == 1) + has_reached_end = true; + else { + context = ctx_stack.Peek (); + context.ExpectingValue = false; + } + + Unindent (); + Put ("}"); + } + + public void WriteObjectStart () + { + DoValidation (Condition.NotAProperty); + PutNewline (); + + Put ("{"); + + context = new WriterContext (); + context.InObject = true; + ctx_stack.Push (context); + + Indent (); + } + + public void WritePropertyName (string property_name) + { + DoValidation (Condition.Property); + PutNewline (); + string propertyName = (property_name == null || !lower_case_properties) + ? property_name + : property_name.ToLowerInvariant(); + + PutString (propertyName); + + if (pretty_print) { + if (propertyName.Length > context.Padding) + context.Padding = propertyName.Length; + + for (int i = context.Padding - propertyName.Length; + i >= 0; i--) + writer.Write (' '); + + writer.Write (": "); + } else + writer.Write (':'); + + context.ExpectingValue = true; + } + } +} diff --git a/Assets/Plugin/LitJson/JsonWriter.cs.meta b/Assets/Plugin/LitJson/JsonWriter.cs.meta new file mode 100644 index 0000000..eda6cec --- /dev/null +++ b/Assets/Plugin/LitJson/JsonWriter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3cda2caaf9ed41b4f9d2f97f25c70070 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/Lexer.cs b/Assets/Plugin/LitJson/Lexer.cs new file mode 100644 index 0000000..cb62d55 --- /dev/null +++ b/Assets/Plugin/LitJson/Lexer.cs @@ -0,0 +1,912 @@ +#region Header +/** + * Lexer.cs + * JSON lexer implementation based on a finite state machine. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + + +namespace LitJson +{ + internal class FsmContext + { + public bool Return; + public int NextState; + public Lexer L; + public int StateStack; + } + + + internal class Lexer + { + #region Fields + private delegate bool StateHandler (FsmContext ctx); + + private static readonly int[] fsm_return_table; + private static readonly StateHandler[] fsm_handler_table; + + private bool allow_comments; + private bool allow_single_quoted_strings; + private bool end_of_input; + private FsmContext fsm_context; + private int input_buffer; + private int input_char; + private TextReader reader; + private int state; + private StringBuilder string_buffer; + private string string_value; + private int token; + private int unichar; + #endregion + + + #region Properties + public bool AllowComments { + get { return allow_comments; } + set { allow_comments = value; } + } + + public bool AllowSingleQuotedStrings { + get { return allow_single_quoted_strings; } + set { allow_single_quoted_strings = value; } + } + + public bool EndOfInput { + get { return end_of_input; } + } + + public int Token { + get { return token; } + } + + public string StringValue { + get { return string_value; } + } + #endregion + + + #region Constructors + static Lexer () + { + PopulateFsmTables (out fsm_handler_table, out fsm_return_table); + } + + public Lexer (TextReader reader) + { + allow_comments = true; + allow_single_quoted_strings = true; + + input_buffer = 0; + string_buffer = new StringBuilder (128); + state = 1; + end_of_input = false; + this.reader = reader; + + fsm_context = new FsmContext (); + fsm_context.L = this; + } + #endregion + + + #region Static Methods + private static int HexValue (int digit) + { + switch (digit) { + case 'a': + case 'A': + return 10; + + case 'b': + case 'B': + return 11; + + case 'c': + case 'C': + return 12; + + case 'd': + case 'D': + return 13; + + case 'e': + case 'E': + return 14; + + case 'f': + case 'F': + return 15; + + default: + return digit - '0'; + } + } + + private static void PopulateFsmTables (out StateHandler[] fsm_handler_table, out int[] fsm_return_table) + { + // See section A.1. of the manual for details of the finite + // state machine. + fsm_handler_table = new StateHandler[28] { + State1, + State2, + State3, + State4, + State5, + State6, + State7, + State8, + State9, + State10, + State11, + State12, + State13, + State14, + State15, + State16, + State17, + State18, + State19, + State20, + State21, + State22, + State23, + State24, + State25, + State26, + State27, + State28 + }; + + fsm_return_table = new int[28] { + (int) ParserToken.Char, + 0, + (int) ParserToken.Number, + (int) ParserToken.Number, + 0, + (int) ParserToken.Number, + 0, + (int) ParserToken.Number, + 0, + 0, + (int) ParserToken.True, + 0, + 0, + 0, + (int) ParserToken.False, + 0, + 0, + (int) ParserToken.Null, + (int) ParserToken.CharSeq, + (int) ParserToken.Char, + 0, + 0, + (int) ParserToken.CharSeq, + (int) ParserToken.Char, + 0, + 0, + 0, + 0 + }; + } + + private static char ProcessEscChar (int esc_char) + { + switch (esc_char) { + case '"': + case '\'': + case '\\': + case '/': + return Convert.ToChar (esc_char); + + case 'n': + return '\n'; + + case 't': + return '\t'; + + case 'r': + return '\r'; + + case 'b': + return '\b'; + + case 'f': + return '\f'; + + default: + // Unreachable + return '?'; + } + } + + private static bool State1 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') + continue; + + if (ctx.L.input_char >= '1' && ctx.L.input_char <= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 3; + return true; + } + + switch (ctx.L.input_char) { + case '"': + ctx.NextState = 19; + ctx.Return = true; + return true; + + case ',': + case ':': + case '[': + case ']': + case '{': + case '}': + ctx.NextState = 1; + ctx.Return = true; + return true; + + case '-': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 2; + return true; + + case '0': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 4; + return true; + + case 'f': + ctx.NextState = 12; + return true; + + case 'n': + ctx.NextState = 16; + return true; + + case 't': + ctx.NextState = 9; + return true; + + case '\'': + if (! ctx.L.allow_single_quoted_strings) + return false; + + ctx.L.input_char = '"'; + ctx.NextState = 23; + ctx.Return = true; + return true; + + case '/': + if (! ctx.L.allow_comments) + return false; + + ctx.NextState = 25; + return true; + + default: + return false; + } + } + + return true; + } + + private static bool State2 (FsmContext ctx) + { + ctx.L.GetChar (); + + if (ctx.L.input_char >= '1' && ctx.L.input_char<= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 3; + return true; + } + + switch (ctx.L.input_char) { + case '0': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 4; + return true; + + default: + return false; + } + } + + private static bool State3 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + continue; + } + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) { + case ',': + case ']': + case '}': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 1; + return true; + + case '.': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 5; + return true; + + case 'e': + case 'E': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 7; + return true; + + default: + return false; + } + } + return true; + } + + private static bool State4 (FsmContext ctx) + { + ctx.L.GetChar (); + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) { + case ',': + case ']': + case '}': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 1; + return true; + + case '.': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 5; + return true; + + case 'e': + case 'E': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 7; + return true; + + default: + return false; + } + } + + private static bool State5 (FsmContext ctx) + { + ctx.L.GetChar (); + + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 6; + return true; + } + + return false; + } + + private static bool State6 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + continue; + } + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r') { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) { + case ',': + case ']': + case '}': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 1; + return true; + + case 'e': + case 'E': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 7; + return true; + + default: + return false; + } + } + + return true; + } + + private static bool State7 (FsmContext ctx) + { + ctx.L.GetChar (); + + if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 8; + return true; + } + + switch (ctx.L.input_char) { + case '+': + case '-': + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + ctx.NextState = 8; + return true; + + default: + return false; + } + } + + private static bool State8 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char >= '0' && ctx.L.input_char<= '9') { + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + continue; + } + + if (ctx.L.input_char == ' ' || + ctx.L.input_char >= '\t' && ctx.L.input_char<= '\r') { + ctx.Return = true; + ctx.NextState = 1; + return true; + } + + switch (ctx.L.input_char) { + case ',': + case ']': + case '}': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + return true; + } + + private static bool State9 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'r': + ctx.NextState = 10; + return true; + + default: + return false; + } + } + + private static bool State10 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'u': + ctx.NextState = 11; + return true; + + default: + return false; + } + } + + private static bool State11 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'e': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State12 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'a': + ctx.NextState = 13; + return true; + + default: + return false; + } + } + + private static bool State13 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'l': + ctx.NextState = 14; + return true; + + default: + return false; + } + } + + private static bool State14 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 's': + ctx.NextState = 15; + return true; + + default: + return false; + } + } + + private static bool State15 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'e': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State16 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'u': + ctx.NextState = 17; + return true; + + default: + return false; + } + } + + private static bool State17 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'l': + ctx.NextState = 18; + return true; + + default: + return false; + } + } + + private static bool State18 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'l': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State19 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + switch (ctx.L.input_char) { + case '"': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 20; + return true; + + case '\\': + ctx.StateStack = 19; + ctx.NextState = 21; + return true; + + default: + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + continue; + } + } + + return true; + } + + private static bool State20 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case '"': + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State21 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case 'u': + ctx.NextState = 22; + return true; + + case '"': + case '\'': + case '/': + case '\\': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + ctx.L.string_buffer.Append ( + ProcessEscChar (ctx.L.input_char)); + ctx.NextState = ctx.StateStack; + return true; + + default: + return false; + } + } + + private static bool State22 (FsmContext ctx) + { + int counter = 0; + int mult = 4096; + + ctx.L.unichar = 0; + + while (ctx.L.GetChar ()) { + + if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9' || + ctx.L.input_char >= 'A' && ctx.L.input_char <= 'F' || + ctx.L.input_char >= 'a' && ctx.L.input_char <= 'f') { + + ctx.L.unichar += HexValue (ctx.L.input_char) * mult; + + counter++; + mult /= 16; + + if (counter == 4) { + ctx.L.string_buffer.Append ( + Convert.ToChar (ctx.L.unichar)); + ctx.NextState = ctx.StateStack; + return true; + } + + continue; + } + + return false; + } + + return true; + } + + private static bool State23 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + switch (ctx.L.input_char) { + case '\'': + ctx.L.UngetChar (); + ctx.Return = true; + ctx.NextState = 24; + return true; + + case '\\': + ctx.StateStack = 23; + ctx.NextState = 21; + return true; + + default: + ctx.L.string_buffer.Append ((char) ctx.L.input_char); + continue; + } + } + + return true; + } + + private static bool State24 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case '\'': + ctx.L.input_char = '"'; + ctx.Return = true; + ctx.NextState = 1; + return true; + + default: + return false; + } + } + + private static bool State25 (FsmContext ctx) + { + ctx.L.GetChar (); + + switch (ctx.L.input_char) { + case '*': + ctx.NextState = 27; + return true; + + case '/': + ctx.NextState = 26; + return true; + + default: + return false; + } + } + + private static bool State26 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char == '\n') { + ctx.NextState = 1; + return true; + } + } + + return true; + } + + private static bool State27 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char == '*') { + ctx.NextState = 28; + return true; + } + } + + return true; + } + + private static bool State28 (FsmContext ctx) + { + while (ctx.L.GetChar ()) { + if (ctx.L.input_char == '*') + continue; + + if (ctx.L.input_char == '/') { + ctx.NextState = 1; + return true; + } + + ctx.NextState = 27; + return true; + } + + return true; + } + #endregion + + + private bool GetChar () + { + if ((input_char = NextChar ()) != -1) + return true; + + end_of_input = true; + return false; + } + + private int NextChar () + { + if (input_buffer != 0) { + int tmp = input_buffer; + input_buffer = 0; + + return tmp; + } + + return reader.Read (); + } + + public bool NextToken () + { + StateHandler handler; + fsm_context.Return = false; + + while (true) { + handler = fsm_handler_table[state - 1]; + + if (! handler (fsm_context)) + throw new JsonException (input_char); + + if (end_of_input) + return false; + + if (fsm_context.Return) { + string_value = string_buffer.ToString (); + string_buffer.Remove (0, string_buffer.Length); + token = fsm_return_table[state - 1]; + + if (token == (int) ParserToken.Char) + token = input_char; + + state = fsm_context.NextState; + + return true; + } + + state = fsm_context.NextState; + } + } + + private void UngetChar () + { + input_buffer = input_char; + } + } +} diff --git a/Assets/Plugin/LitJson/Lexer.cs.meta b/Assets/Plugin/LitJson/Lexer.cs.meta new file mode 100644 index 0000000..d7bfe5e --- /dev/null +++ b/Assets/Plugin/LitJson/Lexer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e5d8fbea5f811044fa786e4f915d339d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/LitJSON.csproj.meta b/Assets/Plugin/LitJson/LitJSON.csproj.meta new file mode 100644 index 0000000..e932a82 --- /dev/null +++ b/Assets/Plugin/LitJson/LitJSON.csproj.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3b357981191bd544eae0b5a95b7f6b22 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/Netstandard15Polyfill.cs b/Assets/Plugin/LitJson/Netstandard15Polyfill.cs new file mode 100644 index 0000000..55b02a2 --- /dev/null +++ b/Assets/Plugin/LitJson/Netstandard15Polyfill.cs @@ -0,0 +1,24 @@ +#if NETSTANDARD1_5 +using System; +using System.Reflection; +namespace LitJson +{ + internal static class Netstandard15Polyfill + { + internal static Type GetInterface(this Type type, string name) + { + return type.GetTypeInfo().GetInterface(name); + } + + internal static bool IsClass(this Type type) + { + return type.GetTypeInfo().IsClass; + } + + internal static bool IsEnum(this Type type) + { + return type.GetTypeInfo().IsEnum; + } + } +} +#endif \ No newline at end of file diff --git a/Assets/Plugin/LitJson/Netstandard15Polyfill.cs.meta b/Assets/Plugin/LitJson/Netstandard15Polyfill.cs.meta new file mode 100644 index 0000000..dddacc0 --- /dev/null +++ b/Assets/Plugin/LitJson/Netstandard15Polyfill.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1ad71d58c21d573439a60de7a867666e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/ParserToken.cs b/Assets/Plugin/LitJson/ParserToken.cs new file mode 100644 index 0000000..e23d477 --- /dev/null +++ b/Assets/Plugin/LitJson/ParserToken.cs @@ -0,0 +1,44 @@ +#region Header +/** + * ParserToken.cs + * Internal representation of the tokens used by the lexer and the parser. + * + * The authors disclaim copyright to this source code. For more details, see + * the COPYING file included with this distribution. + **/ +#endregion + + +namespace LitJson +{ + internal enum ParserToken + { + // Lexer tokens (see section A.1.1. of the manual) + None = System.Char.MaxValue + 1, + Number, + True, + False, + Null, + CharSeq, + // Single char + Char, + + // Parser Rules (see section A.2.1 of the manual) + Text, + Object, + ObjectPrime, + Pair, + PairRest, + Array, + ArrayPrime, + Value, + ValueRest, + String, + + // End of input + End, + + // The empty rule + Epsilon + } +} diff --git a/Assets/Plugin/LitJson/ParserToken.cs.meta b/Assets/Plugin/LitJson/ParserToken.cs.meta new file mode 100644 index 0000000..b8cf3ce --- /dev/null +++ b/Assets/Plugin/LitJson/ParserToken.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: daba7ea4f41da0e49a36f9be037bb5ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugin/LitJson/litjson.png b/Assets/Plugin/LitJson/litjson.png new file mode 100644 index 0000000000000000000000000000000000000000..a4c15e5bbd11ae56f6707941c9e5dedfad044e95 GIT binary patch literal 3356 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