1398 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			1398 lines
		
	
	
		
			30 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 now properly identifies types. So generating JSON with this framework should work. | |||
|  |  * - only double quotes (") are used for quoting strings.
 | |||
|  |  * - 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 tries to avoid errors, but if malformed JSON is parsed the result is more or less undefined | |||
|  |  * - It can serialize/deserialize a node tree into/from an experimental compact binary format. It might | |||
|  |  *   be handy if you want to store things in a file and don't want it to be easily modifiable | |||
|  |  *  | |||
|  |  *  | |||
|  |  * 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. | |||
|  |  *  | |||
|  |  * 2017-03-08 Update: | |||
|  |  * - Optimised parsing by using a StringBuilder for token. This prevents performance issues when large | |||
|  |  *   string data fields are contained in the json data. | |||
|  |  * - Finally refactored the badly named JSONClass into JSONObject. | |||
|  |  * - Replaced the old JSONData class by distict typed classes ( JSONString, JSONNumber, JSONBool, JSONNull ) this | |||
|  |  *   allows to propertly convert the node tree back to json without type information loss. The actual value | |||
|  |  *   parsing now happens at parsing time and not when you actually access one of the casting properties. | |||
|  |  *  | |||
|  |  * The MIT License (MIT) | |||
|  |  *  | |||
|  |  * Copyright (c) 2012-2017 Markus Göbel | |||
|  |  *  | |||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | |||
|  |  * of this software and associated documentation files (the "Software"), to deal | |||
|  |  * in the Software without restriction, including without limitation the rights | |||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
|  |  * copies of the Software, and to permit persons to whom the Software is | |||
|  |  * furnished to do so, subject to the following conditions: | |||
|  |  *  | |||
|  |  * The above copyright notice and this permission notice shall be included in all | |||
|  |  * copies or substantial portions of the Software. | |||
|  |  *  | |||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
|  |  * SOFTWARE. | |||
|  |  *  | |||
|  |  * * * * */ | |||
|  | using System; | |||
|  | using System.Collections; | |||
|  | using System.Collections.Generic; | |||
|  | using System.Linq; | |||
|  | using System.Text; | |||
|  | 
 | |||
|  | namespace Touka | |||
|  | { | |||
|  | 	public enum JSONNodeType | |||
|  | 	{ | |||
|  | 		Array = 1, | |||
|  | 		Object = 2, | |||
|  | 		String = 3, | |||
|  | 		Number = 4, | |||
|  | 		NullValue = 5, | |||
|  | 		Boolean = 6, | |||
|  | 		None = 7, | |||
|  | 	} | |||
|  | 
 | |||
|  | 	public abstract partial class JSONNode | |||
|  | 	{ | |||
|  | 		#region common interface | |||
|  | 
 | |||
|  | 		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 bool IsNumber { get { return false; } } | |||
|  | 		public virtual bool IsString { get { return false; } } | |||
|  | 		public virtual bool IsBoolean { get { return false; } } | |||
|  | 		public virtual bool IsNull { get { return false; } } | |||
|  | 		public virtual bool IsArray { get { return false; } } | |||
|  | 		public virtual bool IsObject { get { return false; } } | |||
|  | 
 | |||
|  | 		public virtual void Add(string aKey, JSONNode aItem) | |||
|  | 		{ | |||
|  | 		} | |||
|  | 		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> Children | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				yield break; | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public IEnumerable<JSONNode> DeepChildren | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				foreach (var C in Children) | |||
|  | 					foreach (var D in C.DeepChildren) | |||
|  | 						yield return D; | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override string ToString() | |||
|  | 		{ | |||
|  | 			return "JSONNode"; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public virtual string ToString(string aIndent) | |||
|  | 		{ | |||
|  | 			return ToString(aIndent, ""); | |||
|  | 		} | |||
|  | 
 | |||
|  | 		internal abstract string ToString(string aIndent, string aPrefix); | |||
|  | 
 | |||
|  | 		#endregion common interface | |||
|  | 
 | |||
|  | 		#region typecasting properties | |||
|  | 
 | |||
|  | 		public abstract JSONNodeType Tag { get; } | |||
|  | 
 | |||
|  | 		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 int AsInt | |||
|  | 		{ | |||
|  | 			get { return (int)AsDouble; } | |||
|  | 			set { AsDouble = value; } | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public virtual float AsFloat | |||
|  | 		{ | |||
|  | 			get { return (float)AsDouble; } | |||
|  | 			set { AsDouble = value; } | |||
|  | 		} | |||
|  | 
 | |||
|  | 		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 JSONObject AsObject | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				return this as JSONObject; | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 
 | |||
|  | 		#endregion typecasting properties | |||
|  | 
 | |||
|  | 		#region operators | |||
|  | 
 | |||
|  | 		public static implicit operator JSONNode(string s) | |||
|  | 		{ | |||
|  | 			return new JSONString(s); | |||
|  | 		} | |||
|  | 		public static implicit operator string(JSONNode d) | |||
|  | 		{ | |||
|  | 			return (d == null) ? null : d.Value; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public static implicit operator JSONNode(double n) | |||
|  | 		{ | |||
|  | 			return new JSONNumber(n); | |||
|  | 		} | |||
|  | 		public static implicit operator double(JSONNode d) | |||
|  | 		{ | |||
|  | 			return (d == null) ? 0 : d.AsDouble; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public static implicit operator JSONNode(float n) | |||
|  | 		{ | |||
|  | 			return new JSONNumber(n); | |||
|  | 		} | |||
|  | 		public static implicit operator float(JSONNode d) | |||
|  | 		{ | |||
|  | 			return (d == null) ? 0 : d.AsFloat; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public static implicit operator JSONNode(int n) | |||
|  | 		{ | |||
|  | 			return new JSONNumber(n); | |||
|  | 		} | |||
|  | 		public static implicit operator int(JSONNode d) | |||
|  | 		{ | |||
|  | 			return (d == null) ? 0 : d.AsInt; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public static implicit operator JSONNode(bool b) | |||
|  | 		{ | |||
|  | 			return new JSONBool(b); | |||
|  | 		} | |||
|  | 		public static implicit operator bool(JSONNode d) | |||
|  | 		{ | |||
|  | 			return (d == null) ? false : d.AsBool; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public static bool operator ==(JSONNode a, object b) | |||
|  | 		{ | |||
|  | 			if (ReferenceEquals(a, b)) | |||
|  | 				return true; | |||
|  | 			bool aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; | |||
|  | 			bool bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; | |||
|  | 			return (aIsNull && bIsNull); | |||
|  | 		} | |||
|  | 
 | |||
|  | 		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 StringBuilder m_EscapeBuilder = new StringBuilder(); | |||
|  | 		internal static string Escape(string aText) | |||
|  | 		{ | |||
|  | 			m_EscapeBuilder.Length = 0; | |||
|  | 			if (m_EscapeBuilder.Capacity < aText.Length + aText.Length / 10) | |||
|  | 				m_EscapeBuilder.Capacity = aText.Length + aText.Length / 10; | |||
|  | 			foreach (char c in aText) | |||
|  | 			{ | |||
|  | 				switch (c) | |||
|  | 				{ | |||
|  | 				case '\\': | |||
|  | 					m_EscapeBuilder.Append("\\\\"); | |||
|  | 					break; | |||
|  | 				case '\"': | |||
|  | 					m_EscapeBuilder.Append("\""); | |||
|  | 					break; | |||
|  | 				case '\n': | |||
|  | 					m_EscapeBuilder.Append("\\n"); | |||
|  | 					break; | |||
|  | 				case '\r': | |||
|  | 					m_EscapeBuilder.Append("\\r"); | |||
|  | 					break; | |||
|  | 				case '\t': | |||
|  | 					m_EscapeBuilder.Append("\\t"); | |||
|  | 					break; | |||
|  | 				case '\b': | |||
|  | 					m_EscapeBuilder.Append("\\b"); | |||
|  | 					break; | |||
|  | 				case '\f': | |||
|  | 					m_EscapeBuilder.Append("\\f"); | |||
|  | 					break; | |||
|  | 				default: | |||
|  | 					m_EscapeBuilder.Append(c); | |||
|  | 					break; | |||
|  | 				} | |||
|  | 			} | |||
|  | 			string result = m_EscapeBuilder.ToString(); | |||
|  | 			m_EscapeBuilder.Length = 0; | |||
|  | 			return result; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		static void ParseElement(JSONNode ctx, string token, string tokenName, bool quoted) | |||
|  | 		{ | |||
|  | 			if (quoted) | |||
|  | 			{ | |||
|  | 				ctx.Add(tokenName, token); | |||
|  | 				return; | |||
|  | 			} | |||
|  | 			string tmp = token.ToLower(); | |||
|  | 			if (tmp == "false" || tmp == "true") | |||
|  | 				ctx.Add(tokenName, tmp == "true"); | |||
|  | 			else if (tmp == "null") | |||
|  | 				ctx.Add(tokenName, null); | |||
|  | 			else | |||
|  | 			{ | |||
|  | 				double val; | |||
|  | 				if (double.TryParse(token, out val)) | |||
|  | 					ctx.Add(tokenName, val); | |||
|  | 				else | |||
|  | 					ctx.Add(tokenName, token); | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public static JSONNode Parse(string aJSON) | |||
|  | 		{ | |||
|  | 			Stack<JSONNode> stack = new Stack<JSONNode>(); | |||
|  | 			JSONNode ctx = null; | |||
|  | 			int i = 0; | |||
|  | 			StringBuilder Token = new StringBuilder(); | |||
|  | 			string TokenName = ""; | |||
|  | 			bool QuoteMode = false; | |||
|  | 			bool TokenIsQuoted = false; | |||
|  | 			while (i < aJSON.Length) | |||
|  | 			{ | |||
|  | 				switch (aJSON[i]) | |||
|  | 				{ | |||
|  | 				case '{': | |||
|  | 					if (QuoteMode) | |||
|  | 					{ | |||
|  | 						Token.Append(aJSON[i]); | |||
|  | 						break; | |||
|  | 					} | |||
|  | 					stack.Push(new JSONObject()); | |||
|  | 					if (ctx != null) | |||
|  | 					{ | |||
|  | 						ctx.Add(TokenName, stack.Peek()); | |||
|  | 					} | |||
|  | 					TokenName = ""; | |||
|  | 					Token.Length = 0; | |||
|  | 					ctx = stack.Peek(); | |||
|  | 					break; | |||
|  | 
 | |||
|  | 				case '[': | |||
|  | 					if (QuoteMode) | |||
|  | 					{ | |||
|  | 						Token.Append(aJSON[i]); | |||
|  | 						break; | |||
|  | 					} | |||
|  | 
 | |||
|  | 					stack.Push(new JSONArray()); | |||
|  | 					if (ctx != null) | |||
|  | 					{ | |||
|  | 						ctx.Add(TokenName, stack.Peek()); | |||
|  | 					} | |||
|  | 					TokenName = ""; | |||
|  | 					Token.Length = 0; | |||
|  | 					ctx = stack.Peek(); | |||
|  | 					break; | |||
|  | 
 | |||
|  | 				case '}': | |||
|  | 				case ']': | |||
|  | 					if (QuoteMode) | |||
|  | 					{ | |||
|  | 
 | |||
|  | 						Token.Append(aJSON[i]); | |||
|  | 						break; | |||
|  | 					} | |||
|  | 					if (stack.Count == 0) | |||
|  | 						throw new Exception("JSON Parse: Too many closing brackets"); | |||
|  | 
 | |||
|  | 					stack.Pop(); | |||
|  | 					if (Token.Length > 0) | |||
|  | 					{ | |||
|  | 						ParseElement(ctx, Token.ToString(), TokenName, TokenIsQuoted); | |||
|  | 						TokenIsQuoted = false; | |||
|  | 					} | |||
|  | 					TokenName = ""; | |||
|  | 					Token.Length = 0; | |||
|  | 					if (stack.Count > 0) | |||
|  | 						ctx = stack.Peek(); | |||
|  | 					break; | |||
|  | 
 | |||
|  | 				case ':': | |||
|  | 					if (QuoteMode) | |||
|  | 					{ | |||
|  | 						Token.Append(aJSON[i]); | |||
|  | 						break; | |||
|  | 					} | |||
|  | 					TokenName = Token.ToString().Trim(); | |||
|  | 					Token.Length = 0; | |||
|  | 					TokenIsQuoted = false; | |||
|  | 					break; | |||
|  | 
 | |||
|  | 				case '"': | |||
|  | 					QuoteMode ^= true; | |||
|  | 					TokenIsQuoted |= QuoteMode; | |||
|  | 					break; | |||
|  | 
 | |||
|  | 				case ',': | |||
|  | 					if (QuoteMode) | |||
|  | 					{ | |||
|  | 						Token.Append(aJSON[i]); | |||
|  | 						break; | |||
|  | 					} | |||
|  | 					if (Token.Length > 0) | |||
|  | 					{ | |||
|  | 						ParseElement(ctx, Token.ToString(), TokenName, TokenIsQuoted); | |||
|  | 						TokenIsQuoted = false; | |||
|  | 					} | |||
|  | 					TokenName = ""; | |||
|  | 					Token.Length = 0; | |||
|  | 					TokenIsQuoted = false; | |||
|  | 					break; | |||
|  | 
 | |||
|  | 				case '\r': | |||
|  | 				case '\n': | |||
|  | 					break; | |||
|  | 
 | |||
|  | 				case ' ': | |||
|  | 				case '\t': | |||
|  | 					if (QuoteMode) | |||
|  | 						Token.Append(aJSON[i]); | |||
|  | 					break; | |||
|  | 
 | |||
|  | 				case '\\': | |||
|  | 					++i; | |||
|  | 					if (QuoteMode) | |||
|  | 					{ | |||
|  | 						char C = aJSON[i]; | |||
|  | 						switch (C) | |||
|  | 						{ | |||
|  | 						case 't': | |||
|  | 							Token.Append('\t'); | |||
|  | 							break; | |||
|  | 						case 'r': | |||
|  | 							Token.Append('\r'); | |||
|  | 							break; | |||
|  | 						case 'n': | |||
|  | 							Token.Append('\n'); | |||
|  | 							break; | |||
|  | 						case 'b': | |||
|  | 							Token.Append('\b'); | |||
|  | 							break; | |||
|  | 						case 'f': | |||
|  | 							Token.Append('\f'); | |||
|  | 							break; | |||
|  | 						case 'u': | |||
|  | 							{ | |||
|  | 								string s = aJSON.Substring(i + 1, 4); | |||
|  | 								Token.Append((char)int.Parse( | |||
|  | 									s, | |||
|  | 									System.Globalization.NumberStyles.AllowHexSpecifier)); | |||
|  | 								i += 4; | |||
|  | 								break; | |||
|  | 							} | |||
|  | 						default: | |||
|  | 							Token.Append(C); | |||
|  | 							break; | |||
|  | 						} | |||
|  | 					} | |||
|  | 					break; | |||
|  | 
 | |||
|  | 				default: | |||
|  | 					Token.Append(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 the 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 void SaveToFile(string aFileName) | |||
|  | 		{ | |||
|  | 			#if USE_FileIO | |||
|  | 			System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName); | |||
|  | 			using (var F = System.IO.File.OpenWrite(aFileName)) | |||
|  | 			{ | |||
|  | 				SaveToStream(F); | |||
|  | 			} | |||
|  | 			#else | |||
|  | 			throw new Exception ("Can't use File IO stuff in the webplayer"); | |||
|  | 			#endif | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public string SaveToBase64() | |||
|  | 		{ | |||
|  | 			using (var stream = new System.IO.MemoryStream()) | |||
|  | 			{ | |||
|  | 				SaveToStream(stream); | |||
|  | 				stream.Position = 0; | |||
|  | 				return System.Convert.ToBase64String(stream.ToArray()); | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public static JSONNode Deserialize(System.IO.BinaryReader aReader) | |||
|  | 		{ | |||
|  | 			JSONNodeType type = (JSONNodeType)aReader.ReadByte(); | |||
|  | 			switch (type) | |||
|  | 			{ | |||
|  | 			case JSONNodeType.Array: | |||
|  | 				{ | |||
|  | 					int count = aReader.ReadInt32(); | |||
|  | 					JSONArray tmp = new JSONArray(); | |||
|  | 					for (int i = 0; i < count; i++) | |||
|  | 						tmp.Add(Deserialize(aReader)); | |||
|  | 					return tmp; | |||
|  | 				} | |||
|  | 			case JSONNodeType.Object: | |||
|  | 				{ | |||
|  | 					int count = aReader.ReadInt32(); | |||
|  | 					JSONObject tmp = new JSONObject(); | |||
|  | 					for (int i = 0; i < count; i++) | |||
|  | 					{ | |||
|  | 						string key = aReader.ReadString(); | |||
|  | 						var val = Deserialize(aReader); | |||
|  | 						tmp.Add(key, val); | |||
|  | 					} | |||
|  | 					return tmp; | |||
|  | 				} | |||
|  | 			case JSONNodeType.String: | |||
|  | 				{ | |||
|  | 					return new JSONString(aReader.ReadString()); | |||
|  | 				} | |||
|  | 			case JSONNodeType.Number: | |||
|  | 				{ | |||
|  | 					return new JSONNumber(aReader.ReadDouble()); | |||
|  | 				} | |||
|  | 			case JSONNodeType.Boolean: | |||
|  | 				{ | |||
|  | 					return new JSONBool(aReader.ReadBoolean()); | |||
|  | 				} | |||
|  | 			case JSONNodeType.NullValue: | |||
|  | 				{ | |||
|  | 					return new JSONNull(); | |||
|  | 				} | |||
|  | 			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 the 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 LoadFromFile(string aFileName) | |||
|  | 		{ | |||
|  | 			#if USE_FileIO | |||
|  | 			using (var F = System.IO.File.OpenRead(aFileName)) | |||
|  | 			{ | |||
|  | 				return LoadFromStream(F); | |||
|  | 			} | |||
|  | 			#else | |||
|  | 			throw new Exception ("Can't use File IO stuff in the webplayer"); | |||
|  | 			#endif | |||
|  | 		} | |||
|  | 
 | |||
|  | 		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 JSONNodeType Tag { get { return JSONNodeType.Array; } } | |||
|  | 		public override bool IsArray { get { return true; } } | |||
|  | 
 | |||
|  | 
 | |||
|  | 
 | |||
|  | 		public override JSONNode this[int aIndex] | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				if (aIndex < 0 || aIndex >= m_List.Count) | |||
|  | 					return new JSONLazyCreator(this); | |||
|  | 				return m_List[aIndex]; | |||
|  | 			} | |||
|  | 			set | |||
|  | 			{ | |||
|  | 				if (value == null) | |||
|  | 					value = new JSONNull(); | |||
|  | 				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 | |||
|  | 			{ | |||
|  | 				if (value == null) | |||
|  | 					value = new JSONNull(); | |||
|  | 				m_List.Add(value); | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override int Count | |||
|  | 		{ | |||
|  | 			get { return m_List.Count; } | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override void Add(string aKey, JSONNode aItem) | |||
|  | 		{ | |||
|  | 			if (aItem == null) | |||
|  | 				aItem = new JSONNull(); | |||
|  | 			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> Children | |||
|  | 		{ | |||
|  | 			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; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		internal override string ToString(string aIndent, string aPrefix) | |||
|  | 		{ | |||
|  | 			string result = "[ "; | |||
|  | 			foreach (JSONNode N in m_List) | |||
|  | 			{ | |||
|  | 				if (result.Length > 3) | |||
|  | 					result += ", "; | |||
|  | 				result += "\n"+aPrefix + aIndent + N.ToString(aIndent, aPrefix + aIndent); | |||
|  | 			} | |||
|  | 			result += "\n" + aPrefix + "]"; | |||
|  | 			return result; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override void Serialize(System.IO.BinaryWriter aWriter) | |||
|  | 		{ | |||
|  | 			aWriter.Write((byte)JSONNodeType.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 JSONObject : JSONNode, IEnumerable | |||
|  | 	{ | |||
|  | 		private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>(); | |||
|  | 
 | |||
|  | 		public override JSONNodeType Tag { get { return JSONNodeType.Object; } } | |||
|  | 		public override bool IsObject { get { return true; } } | |||
|  | 
 | |||
|  | 
 | |||
|  | 		public override JSONNode this[string aKey] | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				if (m_Dict.ContainsKey(aKey)) | |||
|  | 					return m_Dict[aKey]; | |||
|  | 				else | |||
|  | 					return new JSONLazyCreator(this, aKey); | |||
|  | 			} | |||
|  | 			set | |||
|  | 			{ | |||
|  | 				if (value == null) | |||
|  | 					value = new JSONNull(); | |||
|  | 				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 (value == null) | |||
|  | 					value = new JSONNull(); | |||
|  | 				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 (aItem == null) | |||
|  | 				aItem = new JSONNull(); | |||
|  | 
 | |||
|  | 			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> Children | |||
|  | 		{ | |||
|  | 			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; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		internal override string ToString(string aIndent, string aPrefix) | |||
|  | 		{ | |||
|  | 			string result = "{ "; | |||
|  | 			foreach (KeyValuePair<string, JSONNode> N in m_Dict) | |||
|  | 			{ | |||
|  | 				if (result.Length > 3) | |||
|  | 					result += ", "; | |||
|  | 				result += "\n" + aPrefix + aIndent + "\"" + Escape(N.Key) + "\" : "; | |||
|  | 				result += N.Value.ToString(aIndent, aPrefix + aIndent); | |||
|  | 			} | |||
|  | 			result += "\n" + aPrefix + "}"; | |||
|  | 			return result; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override void Serialize(System.IO.BinaryWriter aWriter) | |||
|  | 		{ | |||
|  | 			aWriter.Write((byte)JSONNodeType.Object); | |||
|  | 			aWriter.Write(m_Dict.Count); | |||
|  | 			foreach (string K in m_Dict.Keys) | |||
|  | 			{ | |||
|  | 				aWriter.Write(K); | |||
|  | 				m_Dict[K].Serialize(aWriter); | |||
|  | 			} | |||
|  | 		} | |||
|  | 	} | |||
|  | 	// End of JSONObject | |||
|  | 
 | |||
|  | 	public class JSONString : JSONNode | |||
|  | 	{ | |||
|  | 		private string m_Data; | |||
|  | 
 | |||
|  | 		public override JSONNodeType Tag { get { return JSONNodeType.String; } } | |||
|  | 		public override bool IsString { get { return true; } } | |||
|  | 
 | |||
|  | 		public override string Value | |||
|  | 		{ | |||
|  | 			get { return m_Data; } | |||
|  | 			set | |||
|  | 			{ | |||
|  | 				m_Data = value; | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public JSONString(string aData) | |||
|  | 		{ | |||
|  | 			m_Data = aData; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override string ToString() | |||
|  | 		{ | |||
|  | 			return "\"" + Escape(m_Data) + "\""; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		internal override string ToString(string aIndent, string aPrefix) | |||
|  | 		{ | |||
|  | 			return "\"" + Escape(m_Data) + "\""; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override void Serialize(System.IO.BinaryWriter aWriter) | |||
|  | 		{ | |||
|  | 			aWriter.Write((byte)JSONNodeType.String); | |||
|  | 			aWriter.Write(m_Data); | |||
|  | 		} | |||
|  | 	} | |||
|  | 	// End of JSONString | |||
|  | 
 | |||
|  | 
 | |||
|  | 	public class JSONNumber : JSONNode | |||
|  | 	{ | |||
|  | 		private double m_Data; | |||
|  | 
 | |||
|  | 		public override JSONNodeType Tag { get { return JSONNodeType.Number; } } | |||
|  | 		public override bool IsNumber { get { return true; } } | |||
|  | 
 | |||
|  | 
 | |||
|  | 		public override string Value | |||
|  | 		{ | |||
|  | 			get { return m_Data.ToString(); } | |||
|  | 			set | |||
|  | 			{ | |||
|  | 				double v; | |||
|  | 				if (double.TryParse(value, out v)) | |||
|  | 					m_Data = v; | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override double AsDouble | |||
|  | 		{ | |||
|  | 			get { return m_Data; } | |||
|  | 			set { m_Data = value; } | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public JSONNumber(double aData) | |||
|  | 		{ | |||
|  | 			m_Data = aData; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public JSONNumber(string aData) | |||
|  | 		{ | |||
|  | 			Value = aData; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override string ToString() | |||
|  | 		{ | |||
|  | 			return m_Data.ToString(); | |||
|  | 		} | |||
|  | 
 | |||
|  | 		internal override string ToString(string aIndent, string aPrefix) | |||
|  | 		{ | |||
|  | 			return m_Data.ToString(); | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override void Serialize(System.IO.BinaryWriter aWriter) | |||
|  | 		{ | |||
|  | 			aWriter.Write((byte)JSONNodeType.Number); | |||
|  | 			aWriter.Write(m_Data); | |||
|  | 		} | |||
|  | 	} | |||
|  | 	// End of JSONNumber | |||
|  | 
 | |||
|  | 
 | |||
|  | 	public class JSONBool : JSONNode | |||
|  | 	{ | |||
|  | 		private bool m_Data; | |||
|  | 
 | |||
|  | 		public override JSONNodeType Tag { get { return JSONNodeType.Boolean; } } | |||
|  | 		public override bool IsBoolean { get { return true; } } | |||
|  | 
 | |||
|  | 
 | |||
|  | 		public override string Value | |||
|  | 		{ | |||
|  | 			get { return m_Data.ToString(); } | |||
|  | 			set | |||
|  | 			{ | |||
|  | 				bool v; | |||
|  | 				if (bool.TryParse(value, out v)) | |||
|  | 					m_Data = v; | |||
|  | 			} | |||
|  | 		} | |||
|  | 		public override bool AsBool | |||
|  | 		{ | |||
|  | 			get { return m_Data; } | |||
|  | 			set { m_Data = value; } | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public JSONBool(bool aData) | |||
|  | 		{ | |||
|  | 			m_Data = aData; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public JSONBool(string aData) | |||
|  | 		{ | |||
|  | 			Value = aData; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override string ToString() | |||
|  | 		{ | |||
|  | 			return (m_Data) ? "true" : "false"; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		internal override string ToString(string aIndent, string aPrefix) | |||
|  | 		{ | |||
|  | 			return (m_Data) ? "true" : "false"; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override void Serialize(System.IO.BinaryWriter aWriter) | |||
|  | 		{ | |||
|  | 			aWriter.Write((byte)JSONNodeType.Boolean); | |||
|  | 			aWriter.Write(m_Data); | |||
|  | 		} | |||
|  | 	} | |||
|  | 	// End of JSONBool | |||
|  | 
 | |||
|  | 
 | |||
|  | 	public class JSONNull : JSONNode | |||
|  | 	{ | |||
|  | 
 | |||
|  | 		public override JSONNodeType Tag { get { return JSONNodeType.NullValue; } } | |||
|  | 		public override bool IsNull { get { return true; } } | |||
|  | 
 | |||
|  | 
 | |||
|  | 		public override string Value | |||
|  | 		{ | |||
|  | 			get { return "null"; } | |||
|  | 			set { } | |||
|  | 		} | |||
|  | 		public override bool AsBool | |||
|  | 		{ | |||
|  | 			get { return false; } | |||
|  | 			set { } | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override string ToString() | |||
|  | 		{ | |||
|  | 			return "null"; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		internal override string ToString(string aIndent, string aPrefix) | |||
|  | 		{ | |||
|  | 			return "null"; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override bool Equals(object obj) | |||
|  | 		{ | |||
|  | 			if (object.ReferenceEquals(this, obj)) | |||
|  | 				return true; | |||
|  | 			return (obj is JSONNull); | |||
|  | 		} | |||
|  | 		public override int GetHashCode() | |||
|  | 		{ | |||
|  | 			return base.GetHashCode(); | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override void Serialize(System.IO.BinaryWriter aWriter) | |||
|  | 		{ | |||
|  | 			aWriter.Write((byte)JSONNodeType.NullValue); | |||
|  | 		} | |||
|  | 	} | |||
|  | 	// End of JSONNull | |||
|  | 
 | |||
|  | 	internal class JSONLazyCreator : JSONNode | |||
|  | 	{ | |||
|  | 		private JSONNode m_Node = null; | |||
|  | 		private string m_Key = null; | |||
|  | 
 | |||
|  | 		public override JSONNodeType Tag { get { return JSONNodeType.None; } } | |||
|  | 
 | |||
|  | 		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 JSONObject(); | |||
|  | 				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 JSONObject(); | |||
|  | 			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 ""; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		internal override string ToString(string aIndent, string aPrefix) | |||
|  | 		{ | |||
|  | 			return ""; | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override int AsInt | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				JSONNumber tmp = new JSONNumber(0); | |||
|  | 				Set(tmp); | |||
|  | 				return 0; | |||
|  | 			} | |||
|  | 			set | |||
|  | 			{ | |||
|  | 				JSONNumber tmp = new JSONNumber(value); | |||
|  | 				Set(tmp); | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override float AsFloat | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				JSONNumber tmp = new JSONNumber(0.0f); | |||
|  | 				Set(tmp); | |||
|  | 				return 0.0f; | |||
|  | 			} | |||
|  | 			set | |||
|  | 			{ | |||
|  | 				JSONNumber tmp = new JSONNumber(value); | |||
|  | 				Set(tmp); | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override double AsDouble | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				JSONNumber tmp = new JSONNumber(0.0); | |||
|  | 				Set(tmp); | |||
|  | 				return 0.0; | |||
|  | 			} | |||
|  | 			set | |||
|  | 			{ | |||
|  | 				JSONNumber tmp = new JSONNumber(value); | |||
|  | 				Set(tmp); | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override bool AsBool | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				JSONBool tmp = new JSONBool(false); | |||
|  | 				Set(tmp); | |||
|  | 				return false; | |||
|  | 			} | |||
|  | 			set | |||
|  | 			{ | |||
|  | 				JSONBool tmp = new JSONBool(value); | |||
|  | 				Set(tmp); | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override JSONArray AsArray | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				JSONArray tmp = new JSONArray(); | |||
|  | 				Set(tmp); | |||
|  | 				return tmp; | |||
|  | 			} | |||
|  | 		} | |||
|  | 
 | |||
|  | 		public override JSONObject AsObject | |||
|  | 		{ | |||
|  | 			get | |||
|  | 			{ | |||
|  | 				JSONObject tmp = new JSONObject(); | |||
|  | 				Set(tmp); | |||
|  | 				return tmp; | |||
|  | 			} | |||
|  | 		} | |||
|  | 	} | |||
|  | 	// End of JSONLazyCreator | |||
|  | 
 | |||
|  | 	public static class JSON | |||
|  | 	{ | |||
|  | 		public static JSONNode Parse(string aJSON) | |||
|  | 		{ | |||
|  | 			return JSONNode.Parse(aJSON); | |||
|  | 		} | |||
|  | 	} | |||
|  | } |