1037 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			1037 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C#
		
	
	
	
| //#define USE_SharpZipLib
 | |
| #if !UNITY_WEBPLAYER
 | |
| #define USE_FileIO
 | |
| #endif
 | |
| 
 | |
| /* * * * *
 | |
|  * A simple JSON Parser / builder
 | |
|  * ------------------------------
 | |
|  * 
 | |
|  * It mainly has been written as a simple JSON parser. It can build a JSON string
 | |
|  * from the node-tree, or generate a node tree from any valid JSON string.
 | |
|  * 
 | |
|  * If you want to use compression when saving to file / stream / B64 you have to include
 | |
|  * SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) in your project and
 | |
|  * define "USE_SharpZipLib" at the top of the file
 | |
|  * 
 | |
|  * Written by Bunny83 
 | |
|  * 2012-06-09
 | |
|  * 
 | |
|  * Features / attributes:
 | |
|  * - provides strongly typed node classes and lists / dictionaries
 | |
|  * - provides easy access to class members / array items / data values
 | |
|  * - the parser ignores data types. Each value is a string.
 | |
|  * - only double quotes (") are used for quoting strings.
 | |
|  * - values and names are not restricted to quoted strings. They simply add up and are trimmed.
 | |
|  * - There are only 3 types: arrays(JSONArray), objects(JSONClass) and values(JSONData)
 | |
|  * - provides "casting" properties to easily convert to / from those types:
 | |
|  *   int / float / double / bool
 | |
|  * - provides a common interface for each node so no explicit casting is required.
 | |
|  * - the parser try to avoid errors, but if malformed JSON is parsed the result is undefined
 | |
|  * 
 | |
|  * 
 | |
|  * 2012-12-17 Update:
 | |
|  * - Added internal JSONLazyCreator class which simplifies the construction of a JSON tree
 | |
|  *   Now you can simple reference any item that doesn't exist yet and it will return a JSONLazyCreator
 | |
|  *   The class determines the required type by it's further use, creates the type and removes itself.
 | |
|  * - Added binary serialization / deserialization.
 | |
|  * - Added support for BZip2 zipped binary format. Requires the SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ )
 | |
|  *   The usage of the SharpZipLib library can be disabled by removing or commenting out the USE_SharpZipLib define at the top
 | |
|  * - The serializer uses different types when it comes to store the values. Since my data values
 | |
|  *   are all of type string, the serializer will "try" which format fits best. The order is: int, float, double, bool, string.
 | |
|  *   It's not the most efficient way but for a moderate amount of data it should work on all platforms.
 | |
|  * 
 | |
|  * * * * */
 | |
| using System;
 | |
| using System.Collections;
 | |
| using System.Collections.Generic;
 | |
| using System.Linq;
 | |
|  
 | |
| namespace AdjustSdk
 | |
| {
 | |
|     public enum JSONBinaryTag
 | |
|     {
 | |
|         Array            = 1,
 | |
|         Class            = 2,
 | |
|         Value            = 3,
 | |
|         IntValue        = 4,
 | |
|         DoubleValue        = 5,
 | |
|         BoolValue        = 6,
 | |
|         FloatValue        = 7,
 | |
|     }
 | |
|  
 | |
|     public class JSONNode
 | |
|     {
 | |
|         #region common interface
 | |
|         public virtual void Add(string aKey, JSONNode aItem){ }
 | |
|         public virtual JSONNode this[int aIndex]   { get { return null; } set { } }
 | |
|         public virtual JSONNode this[string aKey]  { get { return null; } set { } }
 | |
|         public virtual string Value                { get { return "";   } set { } }
 | |
|         public virtual int Count                   { get { return 0;    } }
 | |
|  
 | |
|         public virtual void Add(JSONNode aItem)
 | |
|         {
 | |
|             Add("", aItem);
 | |
|         }
 | |
|  
 | |
|         public virtual JSONNode Remove(string aKey) { return null; }
 | |
|         public virtual JSONNode Remove(int aIndex) { return null; }
 | |
|         public virtual JSONNode Remove(JSONNode aNode) { return aNode; }
 | |
|  
 | |
|         public virtual IEnumerable<JSONNode> Childs { get { yield break;} }
 | |
|         public IEnumerable<JSONNode> DeepChilds
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 foreach (var C in Childs)
 | |
|                     foreach (var D in C.DeepChilds)
 | |
|                         yield return D;
 | |
|             }
 | |
|         }
 | |
|  
 | |
|         public override string ToString()
 | |
|         {
 | |
|             return "JSONNode";
 | |
|         }
 | |
|         public virtual string ToString(string aPrefix)
 | |
|         {
 | |
|             return "JSONNode";
 | |
|         }
 | |
|  
 | |
|         #endregion common interface
 | |
|  
 | |
|         #region typecasting properties
 | |
|         public virtual int AsInt
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 int v = 0;
 | |
|                 if (int.TryParse(Value,out v))
 | |
|                     return v;
 | |
|                 return 0;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 Value = value.ToString();
 | |
|             }
 | |
|         }
 | |
|         public virtual float AsFloat
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 float v = 0.0f;
 | |
|                 if (float.TryParse(Value,out v))
 | |
|                     return v;
 | |
|                 return 0.0f;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 Value = value.ToString();
 | |
|             }
 | |
|         }
 | |
|         public virtual double AsDouble
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 double v = 0.0;
 | |
|                 if (double.TryParse(Value,out v))
 | |
|                     return v;
 | |
|                 return 0.0;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 Value = value.ToString();
 | |
|             }
 | |
|         }
 | |
|         public virtual bool AsBool
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 bool v = false;
 | |
|                 if (bool.TryParse(Value,out v))
 | |
|                     return v;
 | |
|                 return !string.IsNullOrEmpty(Value);
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 Value = (value)?"true":"false";
 | |
|             }
 | |
|         }
 | |
|         public virtual JSONArray AsArray
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return this as JSONArray;
 | |
|             }
 | |
|         }
 | |
|         public virtual JSONClass AsObject
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return this as JSONClass;
 | |
|             }
 | |
|         }
 | |
|  
 | |
|  
 | |
|         #endregion typecasting properties
 | |
|  
 | |
|         #region operators
 | |
|         public static implicit operator JSONNode(string s)
 | |
|         {
 | |
|             return new JSONData(s);
 | |
|         }
 | |
|         public static implicit operator string(JSONNode d)
 | |
|         {
 | |
|             return (d == null)?null:d.Value;
 | |
|         }
 | |
|         public static bool operator ==(JSONNode a, object b)
 | |
|         {
 | |
|             if (b == null && a is JSONLazyCreator)
 | |
|                 return true;
 | |
|             return System.Object.ReferenceEquals(a,b);
 | |
|         }
 | |
|  
 | |
|         public static bool operator !=(JSONNode a, object b)
 | |
|         {
 | |
|             return !(a == b);
 | |
|         }
 | |
|         public override bool Equals (object obj)
 | |
|         {
 | |
|             return System.Object.ReferenceEquals(this, obj);
 | |
|         }
 | |
|         public override int GetHashCode ()
 | |
|         {
 | |
|             return base.GetHashCode();
 | |
|         }
 | |
|  
 | |
|  
 | |
|         #endregion operators
 | |
|  
 | |
|         internal static string Escape(string aText)
 | |
|         {
 | |
|             string result = "";
 | |
|             foreach(char c in aText)
 | |
|             {
 | |
|                 switch(c)
 | |
|                 {
 | |
|                     case '\\' : result += "\\\\"; break;
 | |
|                     case '\"' : result += "\\\""; break;
 | |
|                     case '\n' : result += "\\n" ; break;
 | |
|                     case '\r' : result += "\\r" ; break;
 | |
|                     case '\t' : result += "\\t" ; break;
 | |
|                     case '\b' : result += "\\b" ; break;
 | |
|                     case '\f' : result += "\\f" ; break;
 | |
|                     default   : result += c     ; break;
 | |
|                 }
 | |
|             }
 | |
|             return result;
 | |
|         }
 | |
|  
 | |
|         public static JSONNode Parse(string aJSON)
 | |
|         {
 | |
|             Stack<JSONNode> stack = new Stack<JSONNode>();
 | |
|             JSONNode ctx = null;
 | |
|             int i = 0;
 | |
|             string Token = "";
 | |
|             string TokenName = "";
 | |
|             bool QuoteMode = false;
 | |
|             while (i < aJSON.Length)
 | |
|             {
 | |
|                 switch (aJSON[i])
 | |
|                 {
 | |
|                     case '{':
 | |
|                         if (QuoteMode)
 | |
|                         {
 | |
|                             Token += aJSON[i];
 | |
|                             break;
 | |
|                         }
 | |
|                         stack.Push(new JSONClass());
 | |
|                         if (ctx != null)
 | |
|                         {
 | |
|                             TokenName = TokenName.Trim();
 | |
|                             if (ctx is JSONArray)
 | |
|                                 ctx.Add(stack.Peek());
 | |
|                             else if (TokenName != "")
 | |
|                                 ctx.Add(TokenName,stack.Peek());
 | |
|                         }
 | |
|                         TokenName = "";
 | |
|                         Token = "";
 | |
|                         ctx = stack.Peek();
 | |
|                     break;
 | |
|  
 | |
|                     case '[':
 | |
|                         if (QuoteMode)
 | |
|                         {
 | |
|                             Token += aJSON[i];
 | |
|                             break;
 | |
|                         }
 | |
|  
 | |
|                         stack.Push(new JSONArray());
 | |
|                         if (ctx != null)
 | |
|                         {
 | |
|                             TokenName = TokenName.Trim();
 | |
|                             if (ctx is JSONArray)
 | |
|                                 ctx.Add(stack.Peek());
 | |
|                             else if (TokenName != "")
 | |
|                                 ctx.Add(TokenName,stack.Peek());
 | |
|                         }
 | |
|                         TokenName = "";
 | |
|                         Token = "";
 | |
|                         ctx = stack.Peek();
 | |
|                     break;
 | |
|  
 | |
|                     case '}':
 | |
|                     case ']':
 | |
|                         if (QuoteMode)
 | |
|                         {
 | |
|                             Token += aJSON[i];
 | |
|                             break;
 | |
|                         }
 | |
|                         if (stack.Count == 0)
 | |
|                             throw new Exception("JSON Parse: Too many closing brackets");
 | |
|  
 | |
|                         stack.Pop();
 | |
|                         if (Token != "")
 | |
|                         {
 | |
|                             TokenName = TokenName.Trim();
 | |
|                             if (ctx is JSONArray)
 | |
|                                 ctx.Add(Token);
 | |
|                             else if (TokenName != "")
 | |
|                                 ctx.Add(TokenName,Token);
 | |
|                         }
 | |
|                         TokenName = "";
 | |
|                         Token = "";
 | |
|                         if (stack.Count>0)
 | |
|                             ctx = stack.Peek();
 | |
|                     break;
 | |
|  
 | |
|                     case ':':
 | |
|                         if (QuoteMode)
 | |
|                         {
 | |
|                             Token += aJSON[i];
 | |
|                             break;
 | |
|                         }
 | |
|                         TokenName = Token;
 | |
|                         Token = "";
 | |
|                     break;
 | |
|  
 | |
|                     case '"':
 | |
|                         QuoteMode ^= true;
 | |
|                     break;
 | |
|  
 | |
|                     case ',':
 | |
|                         if (QuoteMode)
 | |
|                         {
 | |
|                             Token += aJSON[i];
 | |
|                             break;
 | |
|                         }
 | |
|                         if (Token != "")
 | |
|                         {
 | |
|                             if (ctx is JSONArray)
 | |
|                                 ctx.Add(Token);
 | |
|                             else if (TokenName != "")
 | |
|                                 ctx.Add(TokenName, Token);
 | |
|                         }
 | |
|                         TokenName = "";
 | |
|                         Token = "";
 | |
|                     break;
 | |
|  
 | |
|                     case '\r':
 | |
|                     case '\n':
 | |
|                     break;
 | |
|  
 | |
|                     case ' ':
 | |
|                     case '\t':
 | |
|                         if (QuoteMode)
 | |
|                             Token += aJSON[i];
 | |
|                     break;
 | |
|  
 | |
|                     case '\\':
 | |
|                         ++i;
 | |
|                         if (QuoteMode)
 | |
|                         {
 | |
|                             char C = aJSON[i];
 | |
|                             switch (C)
 | |
|                             {
 | |
|                                 case 't' : Token += '\t'; break;
 | |
|                                 case 'r' : Token += '\r'; break;
 | |
|                                 case 'n' : Token += '\n'; break;
 | |
|                                 case 'b' : Token += '\b'; break;
 | |
|                                 case 'f' : Token += '\f'; break;
 | |
|                                 case 'u':
 | |
|                                 {
 | |
|                                     string s = aJSON.Substring(i+1,4);
 | |
|                                     Token += (char)int.Parse(s, System.Globalization.NumberStyles.AllowHexSpecifier);
 | |
|                                     i += 4;
 | |
|                                     break;
 | |
|                                 }
 | |
|                                 default  : Token += C; break;
 | |
|                             }
 | |
|                         }
 | |
|                     break;
 | |
|  
 | |
|                     default:
 | |
|                         Token += aJSON[i];
 | |
|                     break;
 | |
|                 }
 | |
|                 ++i;
 | |
|             }
 | |
|             if (QuoteMode)
 | |
|             {
 | |
|                 throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
 | |
|             }
 | |
|             return ctx;
 | |
|         }
 | |
|  
 | |
|         public virtual void Serialize(System.IO.BinaryWriter aWriter) {}
 | |
|  
 | |
|         public void SaveToStream(System.IO.Stream aData)
 | |
|         {
 | |
|             var W = new System.IO.BinaryWriter(aData);
 | |
|             Serialize(W);
 | |
|         }
 | |
|  
 | |
|         #if USE_SharpZipLib
 | |
|         public void SaveToCompressedStream(System.IO.Stream aData)
 | |
|         {
 | |
|             using (var gzipOut = new ICSharpCode.SharpZipLib.BZip2.BZip2OutputStream(aData))
 | |
|             {
 | |
|                 gzipOut.IsStreamOwner = false;
 | |
|                 SaveToStream(gzipOut);
 | |
|                 gzipOut.Close();
 | |
|             }
 | |
|         }
 | |
|  
 | |
|         public void SaveToCompressedFile(string aFileName)
 | |
|         {
 | |
|             #if USE_FileIO
 | |
|             System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName);
 | |
|             using(var F = System.IO.File.OpenWrite(aFileName))
 | |
|             {
 | |
|                 SaveToCompressedStream(F);
 | |
|             }
 | |
|             #else
 | |
|             throw new Exception("Can't use File IO stuff in webplayer");
 | |
|             #endif
 | |
|         }
 | |
|         public string SaveToCompressedBase64()
 | |
|         {
 | |
|             using (var stream = new System.IO.MemoryStream())
 | |
|             {
 | |
|                 SaveToCompressedStream(stream);
 | |
|                 stream.Position = 0;
 | |
|                 return System.Convert.ToBase64String(stream.ToArray());
 | |
|             }
 | |
|         }
 | |
|  
 | |
|         #else
 | |
|         public void SaveToCompressedStream(System.IO.Stream aData)
 | |
|         {
 | |
|             throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
 | |
|         }
 | |
|         public void SaveToCompressedFile(string aFileName)
 | |
|         {
 | |
|             throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
 | |
|         }
 | |
|         public string SaveToCompressedBase64()
 | |
|         {
 | |
|             throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
 | |
|         }
 | |
|         #endif
 | |
|         
 | |
|         public static JSONNode Deserialize(System.IO.BinaryReader aReader)
 | |
|         {
 | |
|             JSONBinaryTag type = (JSONBinaryTag)aReader.ReadByte();
 | |
|             switch(type)
 | |
|             {
 | |
|             case JSONBinaryTag.Array:
 | |
|             {
 | |
|                 int count = aReader.ReadInt32();
 | |
|                 JSONArray tmp = new JSONArray();
 | |
|                 for(int i = 0; i < count; i++)
 | |
|                     tmp.Add(Deserialize(aReader));
 | |
|                 return tmp;
 | |
|             }
 | |
|             case JSONBinaryTag.Class:
 | |
|             {
 | |
|                 int count = aReader.ReadInt32();                
 | |
|                 JSONClass tmp = new JSONClass();
 | |
|                 for(int i = 0; i < count; i++)
 | |
|                 {
 | |
|                     string key = aReader.ReadString();
 | |
|                     var val = Deserialize(aReader);
 | |
|                     tmp.Add(key, val);
 | |
|                 }
 | |
|                 return tmp;
 | |
|             }
 | |
|             case JSONBinaryTag.Value:
 | |
|             {
 | |
|                 return new JSONData(aReader.ReadString());
 | |
|             }
 | |
|             case JSONBinaryTag.IntValue:
 | |
|             {
 | |
|                 return new JSONData(aReader.ReadInt32());
 | |
|             }
 | |
|             case JSONBinaryTag.DoubleValue:
 | |
|             {
 | |
|                 return new JSONData(aReader.ReadDouble());
 | |
|             }
 | |
|             case JSONBinaryTag.BoolValue:
 | |
|             {
 | |
|                 return new JSONData(aReader.ReadBoolean());
 | |
|             }
 | |
|             case JSONBinaryTag.FloatValue:
 | |
|             {
 | |
|                 return new JSONData(aReader.ReadSingle());
 | |
|             }
 | |
|  
 | |
|             default:
 | |
|             {
 | |
|                 throw new Exception("Error deserializing JSON. Unknown tag: " + type);
 | |
|             }
 | |
|             }
 | |
|         }
 | |
|  
 | |
|         #if USE_SharpZipLib
 | |
|         public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
 | |
|         {
 | |
|             var zin = new ICSharpCode.SharpZipLib.BZip2.BZip2InputStream(aData);
 | |
|             return LoadFromStream(zin);
 | |
|         }
 | |
|         public static JSONNode LoadFromCompressedFile(string aFileName)
 | |
|         {
 | |
|             #if USE_FileIO
 | |
|             using(var F = System.IO.File.OpenRead(aFileName))
 | |
|             {
 | |
|                 return LoadFromCompressedStream(F);
 | |
|             }
 | |
|             #else
 | |
|             throw new Exception("Can't use File IO stuff in webplayer");
 | |
|             #endif
 | |
|         }
 | |
|         public static JSONNode LoadFromCompressedBase64(string aBase64)
 | |
|         {
 | |
|             var tmp = System.Convert.FromBase64String(aBase64);
 | |
|             var stream = new System.IO.MemoryStream(tmp);
 | |
|             stream.Position = 0;
 | |
|             return LoadFromCompressedStream(stream);
 | |
|         }
 | |
|         #else
 | |
|         public static JSONNode LoadFromCompressedFile(string aFileName)
 | |
|         {
 | |
|             throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
 | |
|         }
 | |
|         public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
 | |
|         {
 | |
|             throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
 | |
|         }
 | |
|         public static JSONNode LoadFromCompressedBase64(string aBase64)
 | |
|         {
 | |
|             throw new Exception("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
 | |
|         }
 | |
|         #endif
 | |
|  
 | |
|         public static JSONNode LoadFromStream(System.IO.Stream aData)
 | |
|         {
 | |
|             using(var R = new System.IO.BinaryReader(aData))
 | |
|             {
 | |
|                 return Deserialize(R);
 | |
|             }
 | |
|         }
 | |
|         public static JSONNode LoadFromBase64(string aBase64)
 | |
|         {
 | |
|             var tmp = System.Convert.FromBase64String(aBase64);
 | |
|             var stream = new System.IO.MemoryStream(tmp);
 | |
|             stream.Position = 0;
 | |
|             return LoadFromStream(stream);
 | |
|         }
 | |
|     } // End of JSONNode
 | |
|  
 | |
|     public class JSONArray : JSONNode, IEnumerable
 | |
|     {
 | |
|         private List<JSONNode> m_List = new List<JSONNode>();
 | |
|         public override JSONNode this[int aIndex]
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (aIndex<0 || aIndex >= m_List.Count)
 | |
|                     return new JSONLazyCreator(this);
 | |
|                 return m_List[aIndex];
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 if (aIndex<0 || aIndex >= m_List.Count)
 | |
|                     m_List.Add(value);
 | |
|                 else
 | |
|                     m_List[aIndex] = value;
 | |
|             }
 | |
|         }
 | |
|         public override JSONNode this[string aKey]
 | |
|         {
 | |
|             get{ return new JSONLazyCreator(this);}
 | |
|             set{ m_List.Add(value); }
 | |
|         }
 | |
|         public override int Count
 | |
|         {
 | |
|             get { return m_List.Count; }
 | |
|         }
 | |
|         public override void Add(string aKey, JSONNode aItem)
 | |
|         {
 | |
|             m_List.Add(aItem);
 | |
|         }
 | |
|         public override JSONNode Remove(int aIndex)
 | |
|         {
 | |
|             if (aIndex < 0 || aIndex >= m_List.Count)
 | |
|                 return null;
 | |
|             JSONNode tmp = m_List[aIndex];
 | |
|             m_List.RemoveAt(aIndex);
 | |
|             return tmp;
 | |
|         }
 | |
|         public override JSONNode Remove(JSONNode aNode)
 | |
|         {
 | |
|             m_List.Remove(aNode);
 | |
|             return aNode;
 | |
|         }
 | |
|         public override IEnumerable<JSONNode> Childs
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 foreach(JSONNode N in m_List)
 | |
|                     yield return N;
 | |
|             }
 | |
|         }
 | |
|         public IEnumerator GetEnumerator()
 | |
|         {
 | |
|             foreach(JSONNode N in m_List)
 | |
|                 yield return N;
 | |
|         }
 | |
|         public override string ToString()
 | |
|         {
 | |
|             string result = "[ ";
 | |
|             foreach (JSONNode N in m_List)
 | |
|             {
 | |
|                 if (result.Length > 2)
 | |
|                     result += ", ";
 | |
|                 result += N.ToString();
 | |
|             }
 | |
|             result += " ]";
 | |
|             return result;
 | |
|         }
 | |
|         public override string ToString(string aPrefix)
 | |
|         {
 | |
|             string result = "[ ";
 | |
|             foreach (JSONNode N in m_List)
 | |
|             {
 | |
|                 if (result.Length > 3)
 | |
|                     result += ", ";
 | |
|                 result += "\n" + aPrefix + "   ";                
 | |
|                 result += N.ToString(aPrefix+"   ");
 | |
|             }
 | |
|             result += "\n" + aPrefix + "]";
 | |
|             return result;
 | |
|         }
 | |
|         public override void Serialize (System.IO.BinaryWriter aWriter)
 | |
|         {
 | |
|             aWriter.Write((byte)JSONBinaryTag.Array);
 | |
|             aWriter.Write(m_List.Count);
 | |
|             for(int i = 0; i < m_List.Count; i++)
 | |
|             {
 | |
|                 m_List[i].Serialize(aWriter);
 | |
|             }
 | |
|         }
 | |
|     } // End of JSONArray
 | |
|  
 | |
|     public class JSONClass : JSONNode, IEnumerable
 | |
|     {
 | |
|         private Dictionary<string,JSONNode> m_Dict = new Dictionary<string,JSONNode>();
 | |
|         public override JSONNode this[string aKey]
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (m_Dict.ContainsKey(aKey))
 | |
|                     return m_Dict[aKey];
 | |
|                 else
 | |
|                     return new JSONLazyCreator(this, aKey);
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 if (m_Dict.ContainsKey(aKey))
 | |
|                     m_Dict[aKey] = value;
 | |
|                 else
 | |
|                     m_Dict.Add(aKey,value);
 | |
|             }
 | |
|         }
 | |
|         public override JSONNode this[int aIndex]
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (aIndex < 0 || aIndex >= m_Dict.Count)
 | |
|                     return null;
 | |
|                 return m_Dict.ElementAt(aIndex).Value;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 if (aIndex < 0 || aIndex >= m_Dict.Count)
 | |
|                     return;
 | |
|                 string key = m_Dict.ElementAt(aIndex).Key;
 | |
|                 m_Dict[key] = value;
 | |
|             }
 | |
|         }
 | |
|         public override int Count
 | |
|         {
 | |
|             get { return m_Dict.Count; }
 | |
|         }
 | |
|  
 | |
|  
 | |
|         public override void Add(string aKey, JSONNode aItem)
 | |
|         {
 | |
|             if (!string.IsNullOrEmpty(aKey))
 | |
|             {
 | |
|                 if (m_Dict.ContainsKey(aKey))
 | |
|                     m_Dict[aKey] = aItem;
 | |
|                 else
 | |
|                     m_Dict.Add(aKey, aItem);
 | |
|             }
 | |
|             else
 | |
|                 m_Dict.Add(Guid.NewGuid().ToString(), aItem);
 | |
|         }
 | |
|  
 | |
|         public override JSONNode Remove(string aKey)
 | |
|         {
 | |
|             if (!m_Dict.ContainsKey(aKey))
 | |
|                 return null;
 | |
|             JSONNode tmp = m_Dict[aKey];
 | |
|             m_Dict.Remove(aKey);
 | |
|             return tmp;        
 | |
|         }
 | |
|         public override JSONNode Remove(int aIndex)
 | |
|         {
 | |
|             if (aIndex < 0 || aIndex >= m_Dict.Count)
 | |
|                 return null;
 | |
|             var item = m_Dict.ElementAt(aIndex);
 | |
|             m_Dict.Remove(item.Key);
 | |
|             return item.Value;
 | |
|         }
 | |
|         public override JSONNode Remove(JSONNode aNode)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 var item = m_Dict.Where(k => k.Value == aNode).First();
 | |
|                 m_Dict.Remove(item.Key);
 | |
|                 return aNode;
 | |
|             }
 | |
|             catch
 | |
|             {
 | |
|                 return null;
 | |
|             }
 | |
|         }
 | |
|  
 | |
|         public override IEnumerable<JSONNode> Childs
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 foreach(KeyValuePair<string,JSONNode> N in m_Dict)
 | |
|                     yield return N.Value;
 | |
|             }
 | |
|         }
 | |
|  
 | |
|         public IEnumerator GetEnumerator()
 | |
|         {
 | |
|             foreach(KeyValuePair<string, JSONNode> N in m_Dict)
 | |
|                 yield return N;
 | |
|         }
 | |
|         public override string ToString()
 | |
|         {
 | |
|             string result = "{";
 | |
|             foreach (KeyValuePair<string, JSONNode> N in m_Dict)
 | |
|             {
 | |
|                 if (result.Length > 2)
 | |
|                     result += ", ";
 | |
|                 result += "\"" + Escape(N.Key) + "\":" + N.Value.ToString();
 | |
|             }
 | |
|             result += "}";
 | |
|             return result;
 | |
|         }
 | |
|         public override string ToString(string aPrefix)
 | |
|         {
 | |
|             string result = "{ ";
 | |
|             foreach (KeyValuePair<string, JSONNode> N in m_Dict)
 | |
|             {
 | |
|                 if (result.Length > 3)
 | |
|                     result += ", ";
 | |
|                 result += "\n" + aPrefix + "   ";
 | |
|                 result += "\"" + Escape(N.Key) + "\" : " + N.Value.ToString(aPrefix+"   ");
 | |
|             }
 | |
|             result += "\n" + aPrefix + "}";
 | |
|             return result;
 | |
|         }
 | |
|         public override void Serialize (System.IO.BinaryWriter aWriter)
 | |
|         {
 | |
|             aWriter.Write((byte)JSONBinaryTag.Class);
 | |
|             aWriter.Write(m_Dict.Count);
 | |
|             foreach(string K in m_Dict.Keys)
 | |
|             {
 | |
|                 aWriter.Write(K);
 | |
|                 m_Dict[K].Serialize(aWriter);
 | |
|             }
 | |
|         }
 | |
|     } // End of JSONClass
 | |
|  
 | |
|     public class JSONData : JSONNode
 | |
|     {
 | |
|         private string m_Data;
 | |
|         public override string Value
 | |
|         {
 | |
|             get { return m_Data; }
 | |
|             set { m_Data = value; }
 | |
|         }
 | |
|         public JSONData(string aData)
 | |
|         {
 | |
|             m_Data = aData;
 | |
|         }
 | |
|         public JSONData(float aData)
 | |
|         {
 | |
|             AsFloat = aData;
 | |
|         }
 | |
|         public JSONData(double aData)
 | |
|         {
 | |
|             AsDouble = aData;
 | |
|         }
 | |
|         public JSONData(bool aData)
 | |
|         {
 | |
|             AsBool = aData;
 | |
|         }
 | |
|         public JSONData(int aData)
 | |
|         {
 | |
|             AsInt = aData;
 | |
|         }
 | |
|  
 | |
|         public override string ToString()
 | |
|         {
 | |
|             return "\"" + Escape(m_Data) + "\"";
 | |
|         }
 | |
|         public override string ToString(string aPrefix)
 | |
|         {
 | |
|             return "\"" + Escape(m_Data) + "\"";
 | |
|         }
 | |
|         public override void Serialize (System.IO.BinaryWriter aWriter)
 | |
|         {
 | |
|             var tmp = new JSONData("");
 | |
|  
 | |
|             tmp.AsInt = AsInt;
 | |
|             if (tmp.m_Data == this.m_Data)
 | |
|             {
 | |
|                 aWriter.Write((byte)JSONBinaryTag.IntValue);
 | |
|                 aWriter.Write(AsInt);
 | |
|                 return;
 | |
|             }
 | |
|             tmp.AsFloat = AsFloat;
 | |
|             if (tmp.m_Data == this.m_Data)
 | |
|             {
 | |
|                 aWriter.Write((byte)JSONBinaryTag.FloatValue);
 | |
|                 aWriter.Write(AsFloat);
 | |
|                 return;
 | |
|             }
 | |
|             tmp.AsDouble = AsDouble;
 | |
|             if (tmp.m_Data == this.m_Data)
 | |
|             {
 | |
|                 aWriter.Write((byte)JSONBinaryTag.DoubleValue);
 | |
|                 aWriter.Write(AsDouble);
 | |
|                 return;
 | |
|             }
 | |
|  
 | |
|             tmp.AsBool = AsBool;
 | |
|             if (tmp.m_Data == this.m_Data)
 | |
|             {
 | |
|                 aWriter.Write((byte)JSONBinaryTag.BoolValue);
 | |
|                 aWriter.Write(AsBool);
 | |
|                 return;
 | |
|             }
 | |
|             aWriter.Write((byte)JSONBinaryTag.Value);
 | |
|             aWriter.Write(m_Data);
 | |
|         }
 | |
|     } // End of JSONData
 | |
|  
 | |
|     internal class JSONLazyCreator : JSONNode
 | |
|     {
 | |
|         private JSONNode m_Node = null;
 | |
|         private string m_Key = null;
 | |
|  
 | |
|         public JSONLazyCreator(JSONNode aNode)
 | |
|         {
 | |
|             m_Node = aNode;
 | |
|             m_Key  = null;
 | |
|         }
 | |
|         public JSONLazyCreator(JSONNode aNode, string aKey)
 | |
|         {
 | |
|             m_Node = aNode;
 | |
|             m_Key = aKey;
 | |
|         }
 | |
|  
 | |
|         private void Set(JSONNode aVal)
 | |
|         {
 | |
|             if (m_Key == null)
 | |
|             {
 | |
|                 m_Node.Add(aVal);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 m_Node.Add(m_Key, aVal);
 | |
|             }
 | |
|             m_Node = null; // Be GC friendly.
 | |
|         }
 | |
|  
 | |
|         public override JSONNode this[int aIndex]
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return new JSONLazyCreator(this);
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 var tmp = new JSONArray();
 | |
|                 tmp.Add(value);
 | |
|                 Set(tmp);
 | |
|             }
 | |
|         }
 | |
|  
 | |
|         public override JSONNode this[string aKey]
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return new JSONLazyCreator(this, aKey);
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 var tmp = new JSONClass();
 | |
|                 tmp.Add(aKey, value);
 | |
|                 Set(tmp);
 | |
|             }
 | |
|         }
 | |
|         public override void Add (JSONNode aItem)
 | |
|         {
 | |
|             var tmp = new JSONArray();
 | |
|             tmp.Add(aItem);
 | |
|             Set(tmp);
 | |
|         }
 | |
|         public override void Add (string aKey, JSONNode aItem)
 | |
|         {
 | |
|             var tmp = new JSONClass();
 | |
|             tmp.Add(aKey, aItem);
 | |
|             Set(tmp);
 | |
|         }
 | |
|         public static bool operator ==(JSONLazyCreator a, object b)
 | |
|         {
 | |
|             if (b == null)
 | |
|                 return true;
 | |
|             return System.Object.ReferenceEquals(a,b);
 | |
|         }
 | |
|  
 | |
|         public static bool operator !=(JSONLazyCreator a, object b)
 | |
|         {
 | |
|             return !(a == b);
 | |
|         }
 | |
|         public override bool Equals (object obj)
 | |
|         {
 | |
|             if (obj == null)
 | |
|                 return true;
 | |
|             return System.Object.ReferenceEquals(this, obj);
 | |
|         }
 | |
|         public override int GetHashCode ()
 | |
|         {
 | |
|             return base.GetHashCode();
 | |
|         }
 | |
|  
 | |
|         public override string ToString()
 | |
|         {
 | |
|             return "";
 | |
|         }
 | |
|         public override string ToString(string aPrefix)
 | |
|         {
 | |
|             return "";
 | |
|         }
 | |
|  
 | |
|         public override int AsInt
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 JSONData tmp = new JSONData(0);
 | |
|                 Set(tmp);
 | |
|                 return 0;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 JSONData tmp = new JSONData(value);
 | |
|                 Set(tmp);
 | |
|             }
 | |
|         }
 | |
|         public override float AsFloat
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 JSONData tmp = new JSONData(0.0f);
 | |
|                 Set(tmp);
 | |
|                 return 0.0f;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 JSONData tmp = new JSONData(value);
 | |
|                 Set(tmp);
 | |
|             }
 | |
|         }
 | |
|         public override double AsDouble
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 JSONData tmp = new JSONData(0.0);
 | |
|                 Set(tmp);
 | |
|                 return 0.0;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 JSONData tmp = new JSONData(value);
 | |
|                 Set(tmp);
 | |
|             }
 | |
|         }
 | |
|         public override bool AsBool
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 JSONData tmp = new JSONData(false);
 | |
|                 Set(tmp);
 | |
|                 return false;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 JSONData tmp = new JSONData(value);
 | |
|                 Set(tmp);
 | |
|             }
 | |
|         }
 | |
|         public override JSONArray AsArray
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 JSONArray tmp = new JSONArray();
 | |
|                 Set(tmp);
 | |
|                 return tmp;
 | |
|             }
 | |
|         }
 | |
|         public override JSONClass AsObject
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 JSONClass tmp = new JSONClass();
 | |
|                 Set(tmp);
 | |
|                 return tmp;
 | |
|             }
 | |
|         }
 | |
|     } // End of JSONLazyCreator
 | |
|  
 | |
|     public static class JSON
 | |
|     {
 | |
|         public static JSONNode Parse(string aJSON)
 | |
|         {
 | |
|             return JSONNode.Parse(aJSON);
 | |
|         }
 | |
|     }
 | |
| } |