forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			1353 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1353 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
/* * * * *
 | 
						|
 * 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
 | 
						|
 *
 | 
						|
 * [2012-06-09 First Version]
 | 
						|
 * - 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.
 | 
						|
 *
 | 
						|
 * [2017-04-11 Update]
 | 
						|
 * - Fixed parsing bug where empty string values have been ignored.
 | 
						|
 * - Optimised "ToString" by using a StringBuilder internally. This should heavily improve performance for large files
 | 
						|
 * - Changed the overload of "ToString(string aIndent)" to "ToString(int aIndent)"
 | 
						|
 *
 | 
						|
 * [2017-11-29 Update]
 | 
						|
 * - Removed the IEnumerator implementations on JSONArray & JSONObject and replaced it with a common
 | 
						|
 *   struct Enumerator in JSONNode that should avoid garbage generation. The enumerator always works
 | 
						|
 *   on KeyValuePair<string, JSONNode>, even for JSONArray.
 | 
						|
 * - Added two wrapper Enumerators that allows for easy key or value enumeration. A JSONNode now has
 | 
						|
 *   a "Keys" and a "Values" enumerable property. Those are also struct enumerators / enumerables
 | 
						|
 * - A KeyValuePair<string, JSONNode> can now be implicitly converted into a JSONNode. This allows
 | 
						|
 *   a foreach loop over a JSONNode to directly access the values only. Since KeyValuePair as well as
 | 
						|
 *   all the Enumerators are structs, no garbage is allocated.
 | 
						|
 * - To add Linq support another "LinqEnumerator" is available through the "Linq" property. This
 | 
						|
 *   enumerator does implement the generic IEnumerable interface so most Linq extensions can be used
 | 
						|
 *   on this enumerable object. This one does allocate memory as it's a wrapper class.
 | 
						|
 * - The Escape method now escapes all control characters (# < 32) in strings as uncode characters
 | 
						|
 *   (\uXXXX) and if the static bool JSONNode.forceASCII is set to true it will also escape all
 | 
						|
 *   characters # > 127. This might be useful if you require an ASCII output. Though keep in mind
 | 
						|
 *   when your strings contain many non-ascii characters the strings become much longer (x6) and are
 | 
						|
 *   no longer human readable.
 | 
						|
 * - The node types JSONObject and JSONArray now have an "Inline" boolean switch which will default to
 | 
						|
 *   false. It can be used to serialize this element inline even you serialize with an indented format
 | 
						|
 *   This is useful for arrays containing numbers so it doesn't place every number on a new line
 | 
						|
 * - Extracted the binary serialization code into a seperate extension file. All classes are now declared
 | 
						|
 *   as "partial" so an extension file can even add a new virtual or abstract method / interface to
 | 
						|
 *   JSONNode and override it in the concrete type classes. It's of course a hacky approach which is
 | 
						|
 *   generally not recommended, but i wanted to keep everything tightly packed.
 | 
						|
 * - Added a static CreateOrGet method to the JSONNull class. Since this class is immutable it could
 | 
						|
 *   be reused without major problems. If you have a lot null fields in your data it will help reduce
 | 
						|
 *   the memory / garbage overhead. I also added a static setting (reuseSameInstance) to JSONNull
 | 
						|
 *   (default is true) which will change the behaviour of "CreateOrGet". If you set this to false
 | 
						|
 *   CreateOrGet will not reuse the cached instance but instead create a new JSONNull instance each time.
 | 
						|
 *   I made the JSONNull constructor private so if you need to create an instance manually use
 | 
						|
 *   JSONNull.CreateOrGet()
 | 
						|
 *
 | 
						|
 * [2018-01-09 Update]
 | 
						|
 * - Changed all double.TryParse and double.ToString uses to use the invariant culture to avoid problems
 | 
						|
 *   on systems with a culture that uses a comma as decimal point.
 | 
						|
 *
 | 
						|
 * [2018-01-26 Update]
 | 
						|
 * - Added AsLong. Note that a JSONNumber is stored as double and can't represent all long values. However
 | 
						|
 *   storing it as string would work.
 | 
						|
 * - Added static setting "JSONNode.longAsString" which controls the default type that is used by the
 | 
						|
 *   LazyCreator when using AsLong
 | 
						|
 *
 | 
						|
 * [2018-04-25 Update]
 | 
						|
 *  - Added support for parsing single values (JSONBool, JSONString, JSONNumber, JSONNull) as top level value.
 | 
						|
 *
 | 
						|
 * The MIT License (MIT)
 | 
						|
 *
 | 
						|
 * Copyright (c) 2012-2017 Markus Göbel (Bunny83)
 | 
						|
 *
 | 
						|
 * 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.Globalization;
 | 
						|
using System.Linq;
 | 
						|
using System.Text;
 | 
						|
 | 
						|
// renaming the namespace to avoid conflict
 | 
						|
namespace OVRSimpleJSON // SimpleJSON
 | 
						|
{
 | 
						|
    public enum JSONNodeType
 | 
						|
    {
 | 
						|
        Array = 1,
 | 
						|
        Object = 2,
 | 
						|
        String = 3,
 | 
						|
        Number = 4,
 | 
						|
        NullValue = 5,
 | 
						|
        Boolean = 6,
 | 
						|
        None = 7,
 | 
						|
        Custom = 0xFF,
 | 
						|
    }
 | 
						|
    public enum JSONTextMode
 | 
						|
    {
 | 
						|
        Compact,
 | 
						|
        Indent
 | 
						|
    }
 | 
						|
 | 
						|
    public abstract partial class JSONNode
 | 
						|
    {
 | 
						|
        #region Enumerators
 | 
						|
        public struct Enumerator
 | 
						|
        {
 | 
						|
            private enum Type { None, Array, Object }
 | 
						|
            private Type type;
 | 
						|
            private Dictionary<string, JSONNode>.Enumerator m_Object;
 | 
						|
            private List<JSONNode>.Enumerator m_Array;
 | 
						|
            public bool IsValid { get { return type != Type.None; } }
 | 
						|
            public Enumerator(List<JSONNode>.Enumerator aArrayEnum)
 | 
						|
            {
 | 
						|
                type = Type.Array;
 | 
						|
                m_Object = default(Dictionary<string, JSONNode>.Enumerator);
 | 
						|
                m_Array = aArrayEnum;
 | 
						|
            }
 | 
						|
            public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
 | 
						|
            {
 | 
						|
                type = Type.Object;
 | 
						|
                m_Object = aDictEnum;
 | 
						|
                m_Array = default(List<JSONNode>.Enumerator);
 | 
						|
            }
 | 
						|
            public KeyValuePair<string, JSONNode> Current
 | 
						|
            {
 | 
						|
                get {
 | 
						|
                    if (type == Type.Array)
 | 
						|
                        return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current);
 | 
						|
                    else if (type == Type.Object)
 | 
						|
                        return m_Object.Current;
 | 
						|
                    return new KeyValuePair<string, JSONNode>(string.Empty, null);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            public bool MoveNext()
 | 
						|
            {
 | 
						|
                if (type == Type.Array)
 | 
						|
                    return m_Array.MoveNext();
 | 
						|
                else if (type == Type.Object)
 | 
						|
                    return m_Object.MoveNext();
 | 
						|
                return false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        public struct ValueEnumerator
 | 
						|
        {
 | 
						|
            private Enumerator m_Enumerator;
 | 
						|
            public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { }
 | 
						|
            public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { }
 | 
						|
            public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; }
 | 
						|
            public JSONNode Current { get { return m_Enumerator.Current.Value; } }
 | 
						|
            public bool MoveNext() { return m_Enumerator.MoveNext(); }
 | 
						|
            public ValueEnumerator GetEnumerator() { return this; }
 | 
						|
        }
 | 
						|
        public struct KeyEnumerator
 | 
						|
        {
 | 
						|
            private Enumerator m_Enumerator;
 | 
						|
            public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { }
 | 
						|
            public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { }
 | 
						|
            public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; }
 | 
						|
            public string Current { get { return m_Enumerator.Current.Key; } }
 | 
						|
            public bool MoveNext() { return m_Enumerator.MoveNext(); }
 | 
						|
            public KeyEnumerator GetEnumerator() { return this; }
 | 
						|
        }
 | 
						|
 | 
						|
        public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IEnumerable<KeyValuePair<string, JSONNode>>
 | 
						|
        {
 | 
						|
            private JSONNode m_Node;
 | 
						|
            private Enumerator m_Enumerator;
 | 
						|
            internal LinqEnumerator(JSONNode aNode)
 | 
						|
            {
 | 
						|
                m_Node = aNode;
 | 
						|
                if (m_Node != null)
 | 
						|
                    m_Enumerator = m_Node.GetEnumerator();
 | 
						|
            }
 | 
						|
            public KeyValuePair<string, JSONNode> Current { get { return m_Enumerator.Current; } }
 | 
						|
            object IEnumerator.Current { get { return m_Enumerator.Current; } }
 | 
						|
            public bool MoveNext() { return m_Enumerator.MoveNext(); }
 | 
						|
 | 
						|
            public void Dispose()
 | 
						|
            {
 | 
						|
                m_Node = null;
 | 
						|
                m_Enumerator = new Enumerator();
 | 
						|
            }
 | 
						|
 | 
						|
            public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator()
 | 
						|
            {
 | 
						|
                return new LinqEnumerator(m_Node);
 | 
						|
            }
 | 
						|
 | 
						|
            public void Reset()
 | 
						|
            {
 | 
						|
                if (m_Node != null)
 | 
						|
                    m_Enumerator = m_Node.GetEnumerator();
 | 
						|
            }
 | 
						|
 | 
						|
            IEnumerator IEnumerable.GetEnumerator()
 | 
						|
            {
 | 
						|
                return new LinqEnumerator(m_Node);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion Enumerators
 | 
						|
 | 
						|
        #region common interface
 | 
						|
 | 
						|
        public static bool forceASCII = false; // Use Unicode by default
 | 
						|
        public static bool longAsString = false; // lazy creator creates a JSONString instead of JSONNumber
 | 
						|
 | 
						|
        public abstract JSONNodeType Tag { get; }
 | 
						|
 | 
						|
        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 bool Inline { get { return false; } set { } }
 | 
						|
 | 
						|
        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()
 | 
						|
        {
 | 
						|
            StringBuilder sb = new StringBuilder();
 | 
						|
            WriteToStringBuilder(sb, 0, 0, JSONTextMode.Compact);
 | 
						|
            return sb.ToString();
 | 
						|
        }
 | 
						|
 | 
						|
        public virtual string ToString(int aIndent)
 | 
						|
        {
 | 
						|
            StringBuilder sb = new StringBuilder();
 | 
						|
            WriteToStringBuilder(sb, 0, aIndent, JSONTextMode.Indent);
 | 
						|
            return sb.ToString();
 | 
						|
        }
 | 
						|
        internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode);
 | 
						|
 | 
						|
        public abstract Enumerator GetEnumerator();
 | 
						|
        public IEnumerable<KeyValuePair<string, JSONNode>> Linq { get { return new LinqEnumerator(this); } }
 | 
						|
        public KeyEnumerator Keys { get { return new KeyEnumerator(GetEnumerator()); } }
 | 
						|
        public ValueEnumerator Values { get { return new ValueEnumerator(GetEnumerator()); } }
 | 
						|
 | 
						|
        #endregion common interface
 | 
						|
 | 
						|
        #region typecasting properties
 | 
						|
 | 
						|
 | 
						|
        public virtual double AsDouble
 | 
						|
        {
 | 
						|
            get
 | 
						|
            {
 | 
						|
                double v = 0.0;
 | 
						|
                if (double.TryParse(Value,NumberStyles.Float, CultureInfo.InvariantCulture, out v))
 | 
						|
                    return v;
 | 
						|
                return 0.0;
 | 
						|
            }
 | 
						|
            set
 | 
						|
            {
 | 
						|
                Value = value.ToString(CultureInfo.InvariantCulture);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        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 long AsLong
 | 
						|
        {
 | 
						|
            get
 | 
						|
            {
 | 
						|
                long val = 0;
 | 
						|
                if (long.TryParse(Value, out val))
 | 
						|
                    return val;
 | 
						|
                return 0L;
 | 
						|
            }
 | 
						|
            set
 | 
						|
            {
 | 
						|
                Value = value.ToString();
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        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(long n)
 | 
						|
        {
 | 
						|
            if (longAsString)
 | 
						|
                return new JSONString(n.ToString());
 | 
						|
            return new JSONNumber(n);
 | 
						|
        }
 | 
						|
        public static implicit operator long(JSONNode d)
 | 
						|
        {
 | 
						|
            return (d == null) ? 0L : d.AsLong;
 | 
						|
        }
 | 
						|
 | 
						|
        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 implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue)
 | 
						|
        {
 | 
						|
            return aKeyValue.Value;
 | 
						|
        }
 | 
						|
 | 
						|
        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;
 | 
						|
            if (aIsNull && bIsNull)
 | 
						|
                return true;
 | 
						|
            return !aIsNull && a.Equals(b);
 | 
						|
        }
 | 
						|
 | 
						|
        public static bool operator !=(JSONNode a, object b)
 | 
						|
        {
 | 
						|
            return !(a == b);
 | 
						|
        }
 | 
						|
 | 
						|
        public override bool Equals(object obj)
 | 
						|
        {
 | 
						|
            return ReferenceEquals(this, obj);
 | 
						|
        }
 | 
						|
 | 
						|
        public override int GetHashCode()
 | 
						|
        {
 | 
						|
            return base.GetHashCode();
 | 
						|
        }
 | 
						|
 | 
						|
        #endregion operators
 | 
						|
 | 
						|
        [ThreadStatic]
 | 
						|
        private static StringBuilder m_EscapeBuilder;
 | 
						|
        internal static StringBuilder EscapeBuilder
 | 
						|
        {
 | 
						|
            get {
 | 
						|
                if (m_EscapeBuilder == null)
 | 
						|
                    m_EscapeBuilder = new StringBuilder();
 | 
						|
                return m_EscapeBuilder;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        internal static string Escape(string aText)
 | 
						|
        {
 | 
						|
            var sb = EscapeBuilder;
 | 
						|
            sb.Length = 0;
 | 
						|
            if (sb.Capacity < aText.Length + aText.Length / 10)
 | 
						|
                sb.Capacity = aText.Length + aText.Length / 10;
 | 
						|
            foreach (char c in aText)
 | 
						|
            {
 | 
						|
                switch (c)
 | 
						|
                {
 | 
						|
                    case '\\':
 | 
						|
                        sb.Append("\\\\");
 | 
						|
                        break;
 | 
						|
                    case '\"':
 | 
						|
                        sb.Append("\\\"");
 | 
						|
                        break;
 | 
						|
                    case '\n':
 | 
						|
                        sb.Append("\\n");
 | 
						|
                        break;
 | 
						|
                    case '\r':
 | 
						|
                        sb.Append("\\r");
 | 
						|
                        break;
 | 
						|
                    case '\t':
 | 
						|
                        sb.Append("\\t");
 | 
						|
                        break;
 | 
						|
                    case '\b':
 | 
						|
                        sb.Append("\\b");
 | 
						|
                        break;
 | 
						|
                    case '\f':
 | 
						|
                        sb.Append("\\f");
 | 
						|
                        break;
 | 
						|
                    default:
 | 
						|
                        if (c < ' ' || (forceASCII && c > 127))
 | 
						|
                        {
 | 
						|
                            ushort val = c;
 | 
						|
                            sb.Append("\\u").Append(val.ToString("X4"));
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                            sb.Append(c);
 | 
						|
                        break;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            string result = sb.ToString();
 | 
						|
            sb.Length = 0;
 | 
						|
            return result;
 | 
						|
        }
 | 
						|
 | 
						|
        private static JSONNode ParseElement(string token, bool quoted)
 | 
						|
        {
 | 
						|
            if (quoted)
 | 
						|
                return token;
 | 
						|
            string tmp = token.ToLower();
 | 
						|
            if (tmp == "false" || tmp == "true")
 | 
						|
                return tmp == "true";
 | 
						|
            if (tmp == "null")
 | 
						|
                return JSONNull.CreateOrGet();
 | 
						|
            double val;
 | 
						|
            if (double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out val))
 | 
						|
                return val;
 | 
						|
            else
 | 
						|
                return 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 || TokenIsQuoted)
 | 
						|
                            ctx.Add(TokenName, ParseElement(Token.ToString(), 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();
 | 
						|
                        Token.Length = 0;
 | 
						|
                        TokenIsQuoted = false;
 | 
						|
                        break;
 | 
						|
 | 
						|
                    case '"':
 | 
						|
                        QuoteMode ^= true;
 | 
						|
                        TokenIsQuoted |= QuoteMode;
 | 
						|
                        break;
 | 
						|
 | 
						|
                    case ',':
 | 
						|
                        if (QuoteMode)
 | 
						|
                        {
 | 
						|
                            Token.Append(aJSON[i]);
 | 
						|
                            break;
 | 
						|
                        }
 | 
						|
                        if (Token.Length > 0 || TokenIsQuoted)
 | 
						|
                            ctx.Add(TokenName, ParseElement(Token.ToString(), 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.");
 | 
						|
            }
 | 
						|
            if (ctx == null)
 | 
						|
                return ParseElement(Token.ToString(), TokenIsQuoted);
 | 
						|
            return ctx;
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
    // End of JSONNode
 | 
						|
 | 
						|
    public partial class JSONArray : JSONNode
 | 
						|
    {
 | 
						|
        private List<JSONNode> m_List = new List<JSONNode>();
 | 
						|
        private bool inline = false;
 | 
						|
        public override bool Inline
 | 
						|
        {
 | 
						|
            get { return inline; }
 | 
						|
            set { inline = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        public override JSONNodeType Tag { get { return JSONNodeType.Array; } }
 | 
						|
        public override bool IsArray { get { return true; } }
 | 
						|
        public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); }
 | 
						|
 | 
						|
        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 = JSONNull.CreateOrGet();
 | 
						|
                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 = JSONNull.CreateOrGet();
 | 
						|
                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 = JSONNull.CreateOrGet();
 | 
						|
            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;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
 | 
						|
        {
 | 
						|
            aSB.Append('[');
 | 
						|
            int count = m_List.Count;
 | 
						|
            if (inline)
 | 
						|
                aMode = JSONTextMode.Compact;
 | 
						|
            for (int i = 0; i < count; i++)
 | 
						|
            {
 | 
						|
                if (i > 0)
 | 
						|
                    aSB.Append(',');
 | 
						|
                if (aMode == JSONTextMode.Indent)
 | 
						|
                    aSB.AppendLine();
 | 
						|
 | 
						|
                if (aMode == JSONTextMode.Indent)
 | 
						|
                    aSB.Append(' ', aIndent + aIndentInc);
 | 
						|
                m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
 | 
						|
            }
 | 
						|
            if (aMode == JSONTextMode.Indent)
 | 
						|
                aSB.AppendLine().Append(' ', aIndent);
 | 
						|
            aSB.Append(']');
 | 
						|
        }
 | 
						|
    }
 | 
						|
    // End of JSONArray
 | 
						|
 | 
						|
    public partial class JSONObject : JSONNode
 | 
						|
    {
 | 
						|
        private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>();
 | 
						|
 | 
						|
        private bool inline = false;
 | 
						|
        public override bool Inline
 | 
						|
        {
 | 
						|
            get { return inline; }
 | 
						|
            set { inline = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        public override JSONNodeType Tag { get { return JSONNodeType.Object; } }
 | 
						|
        public override bool IsObject { get { return true; } }
 | 
						|
 | 
						|
        public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); }
 | 
						|
 | 
						|
 | 
						|
        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 = JSONNull.CreateOrGet();
 | 
						|
                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 = JSONNull.CreateOrGet();
 | 
						|
                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 = JSONNull.CreateOrGet();
 | 
						|
 | 
						|
            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;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
 | 
						|
        {
 | 
						|
            aSB.Append('{');
 | 
						|
            bool first = true;
 | 
						|
            if (inline)
 | 
						|
                aMode = JSONTextMode.Compact;
 | 
						|
            foreach (var k in m_Dict)
 | 
						|
            {
 | 
						|
                if (!first)
 | 
						|
                    aSB.Append(',');
 | 
						|
                first = false;
 | 
						|
                if (aMode == JSONTextMode.Indent)
 | 
						|
                    aSB.AppendLine();
 | 
						|
                if (aMode == JSONTextMode.Indent)
 | 
						|
                    aSB.Append(' ', aIndent + aIndentInc);
 | 
						|
                aSB.Append('\"').Append(Escape(k.Key)).Append('\"');
 | 
						|
                if (aMode == JSONTextMode.Compact)
 | 
						|
                    aSB.Append(':');
 | 
						|
                else
 | 
						|
                    aSB.Append(" : ");
 | 
						|
                k.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
 | 
						|
            }
 | 
						|
            if (aMode == JSONTextMode.Indent)
 | 
						|
                aSB.AppendLine().Append(' ', aIndent);
 | 
						|
            aSB.Append('}');
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
    // End of JSONObject
 | 
						|
 | 
						|
    public partial class JSONString : JSONNode
 | 
						|
    {
 | 
						|
        private string m_Data;
 | 
						|
 | 
						|
        public override JSONNodeType Tag { get { return JSONNodeType.String; } }
 | 
						|
        public override bool IsString { get { return true; } }
 | 
						|
 | 
						|
        public override Enumerator GetEnumerator() { return new Enumerator(); }
 | 
						|
 | 
						|
 | 
						|
        public override string Value
 | 
						|
        {
 | 
						|
            get { return m_Data; }
 | 
						|
            set
 | 
						|
            {
 | 
						|
                m_Data = value;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        public JSONString(string aData)
 | 
						|
        {
 | 
						|
            m_Data = aData;
 | 
						|
        }
 | 
						|
 | 
						|
        internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
 | 
						|
        {
 | 
						|
            aSB.Append('\"').Append(Escape(m_Data)).Append('\"');
 | 
						|
        }
 | 
						|
        public override bool Equals(object obj)
 | 
						|
        {
 | 
						|
            if (base.Equals(obj))
 | 
						|
                return true;
 | 
						|
            string s = obj as string;
 | 
						|
            if (s != null)
 | 
						|
                return m_Data == s;
 | 
						|
            JSONString s2 = obj as JSONString;
 | 
						|
            if (s2 != null)
 | 
						|
                return m_Data == s2.m_Data;
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        public override int GetHashCode()
 | 
						|
        {
 | 
						|
            return m_Data.GetHashCode();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    // End of JSONString
 | 
						|
 | 
						|
    public partial class JSONNumber : JSONNode
 | 
						|
    {
 | 
						|
        private double m_Data;
 | 
						|
 | 
						|
        public override JSONNodeType Tag { get { return JSONNodeType.Number; } }
 | 
						|
        public override bool IsNumber { get { return true; } }
 | 
						|
        public override Enumerator GetEnumerator() { return new Enumerator(); }
 | 
						|
 | 
						|
        public override string Value
 | 
						|
        {
 | 
						|
            get { return m_Data.ToString(CultureInfo.InvariantCulture); }
 | 
						|
            set
 | 
						|
            {
 | 
						|
                double v;
 | 
						|
                if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out v))
 | 
						|
                    m_Data = v;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        public override double AsDouble
 | 
						|
        {
 | 
						|
            get { return m_Data; }
 | 
						|
            set { m_Data = value; }
 | 
						|
        }
 | 
						|
        public override long AsLong
 | 
						|
        {
 | 
						|
            get { return (long)m_Data; }
 | 
						|
            set { m_Data = value; }
 | 
						|
        }
 | 
						|
 | 
						|
        public JSONNumber(double aData)
 | 
						|
        {
 | 
						|
            m_Data = aData;
 | 
						|
        }
 | 
						|
 | 
						|
        public JSONNumber(string aData)
 | 
						|
        {
 | 
						|
            Value = aData;
 | 
						|
        }
 | 
						|
 | 
						|
        internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
 | 
						|
        {
 | 
						|
            aSB.Append(Value);
 | 
						|
        }
 | 
						|
        private static bool IsNumeric(object value)
 | 
						|
        {
 | 
						|
            return value is int || value is uint
 | 
						|
                || value is float || value is double
 | 
						|
                || value is decimal
 | 
						|
                || value is long || value is ulong
 | 
						|
                || value is short || value is ushort
 | 
						|
                || value is sbyte || value is byte;
 | 
						|
        }
 | 
						|
        public override bool Equals(object obj)
 | 
						|
        {
 | 
						|
            if (obj == null)
 | 
						|
                return false;
 | 
						|
            if (base.Equals(obj))
 | 
						|
                return true;
 | 
						|
            JSONNumber s2 = obj as JSONNumber;
 | 
						|
            if (s2 != null)
 | 
						|
                return m_Data == s2.m_Data;
 | 
						|
            if (IsNumeric(obj))
 | 
						|
                return Convert.ToDouble(obj) == m_Data;
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        public override int GetHashCode()
 | 
						|
        {
 | 
						|
            return m_Data.GetHashCode();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    // End of JSONNumber
 | 
						|
 | 
						|
    public partial class JSONBool : JSONNode
 | 
						|
    {
 | 
						|
        private bool m_Data;
 | 
						|
 | 
						|
        public override JSONNodeType Tag { get { return JSONNodeType.Boolean; } }
 | 
						|
        public override bool IsBoolean { get { return true; } }
 | 
						|
        public override Enumerator GetEnumerator() { return new Enumerator(); }
 | 
						|
 | 
						|
        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;
 | 
						|
        }
 | 
						|
 | 
						|
        internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
 | 
						|
        {
 | 
						|
            aSB.Append((m_Data) ? "true" : "false");
 | 
						|
        }
 | 
						|
        public override bool Equals(object obj)
 | 
						|
        {
 | 
						|
            if (obj == null)
 | 
						|
                return false;
 | 
						|
            if (obj is bool)
 | 
						|
                return m_Data == (bool)obj;
 | 
						|
            return false;
 | 
						|
        }
 | 
						|
        public override int GetHashCode()
 | 
						|
        {
 | 
						|
            return m_Data.GetHashCode();
 | 
						|
        }
 | 
						|
    }
 | 
						|
    // End of JSONBool
 | 
						|
 | 
						|
    public partial class JSONNull : JSONNode
 | 
						|
    {
 | 
						|
        static JSONNull m_StaticInstance = new JSONNull();
 | 
						|
        public static bool reuseSameInstance = true;
 | 
						|
        public static JSONNull CreateOrGet()
 | 
						|
        {
 | 
						|
            if (reuseSameInstance)
 | 
						|
                return m_StaticInstance;
 | 
						|
            return new JSONNull();
 | 
						|
        }
 | 
						|
        private JSONNull() { }
 | 
						|
 | 
						|
        public override JSONNodeType Tag { get { return JSONNodeType.NullValue; } }
 | 
						|
        public override bool IsNull { get { return true; } }
 | 
						|
        public override Enumerator GetEnumerator() { return new Enumerator(); }
 | 
						|
 | 
						|
        public override string Value
 | 
						|
        {
 | 
						|
            get { return "null"; }
 | 
						|
            set { }
 | 
						|
        }
 | 
						|
        public override bool AsBool
 | 
						|
        {
 | 
						|
            get { return false; }
 | 
						|
            set { }
 | 
						|
        }
 | 
						|
 | 
						|
        public override bool Equals(object obj)
 | 
						|
        {
 | 
						|
            if (object.ReferenceEquals(this, obj))
 | 
						|
                return true;
 | 
						|
            return (obj is JSONNull);
 | 
						|
        }
 | 
						|
        public override int GetHashCode()
 | 
						|
        {
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
 | 
						|
        internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
 | 
						|
        {
 | 
						|
            aSB.Append("null");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    // End of JSONNull
 | 
						|
 | 
						|
    internal partial class JSONLazyCreator : JSONNode
 | 
						|
    {
 | 
						|
        private JSONNode m_Node = null;
 | 
						|
        private string m_Key = null;
 | 
						|
        public override JSONNodeType Tag { get { return JSONNodeType.None; } }
 | 
						|
        public override Enumerator GetEnumerator() { return new Enumerator(); }
 | 
						|
 | 
						|
        public JSONLazyCreator(JSONNode aNode)
 | 
						|
        {
 | 
						|
            m_Node = aNode;
 | 
						|
            m_Key = null;
 | 
						|
        }
 | 
						|
 | 
						|
        public JSONLazyCreator(JSONNode aNode, string aKey)
 | 
						|
        {
 | 
						|
            m_Node = aNode;
 | 
						|
            m_Key = aKey;
 | 
						|
        }
 | 
						|
 | 
						|
        private T Set<T>(T aVal) where T : JSONNode
 | 
						|
        {
 | 
						|
            if (m_Key == null)
 | 
						|
                m_Node.Add(aVal);
 | 
						|
            else
 | 
						|
                m_Node.Add(m_Key, aVal);
 | 
						|
            m_Node = null; // Be GC friendly.
 | 
						|
            return aVal;
 | 
						|
        }
 | 
						|
 | 
						|
        public override JSONNode this[int aIndex]
 | 
						|
        {
 | 
						|
            get { return new JSONLazyCreator(this); }
 | 
						|
            set { Set(new JSONArray()).Add(value); }
 | 
						|
        }
 | 
						|
 | 
						|
        public override JSONNode this[string aKey]
 | 
						|
        {
 | 
						|
            get { return new JSONLazyCreator(this, aKey); }
 | 
						|
            set { Set(new JSONObject()).Add(aKey, value); }
 | 
						|
        }
 | 
						|
 | 
						|
        public override void Add(JSONNode aItem)
 | 
						|
        {
 | 
						|
            Set(new JSONArray()).Add(aItem);
 | 
						|
        }
 | 
						|
 | 
						|
        public override void Add(string aKey, JSONNode aItem)
 | 
						|
        {
 | 
						|
            Set(new JSONObject()).Add(aKey, aItem);
 | 
						|
        }
 | 
						|
 | 
						|
        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 0;
 | 
						|
        }
 | 
						|
 | 
						|
        public override int AsInt
 | 
						|
        {
 | 
						|
            get { Set(new JSONNumber(0)); return 0; }
 | 
						|
            set { Set(new JSONNumber(value)); }
 | 
						|
        }
 | 
						|
 | 
						|
        public override float AsFloat
 | 
						|
        {
 | 
						|
            get { Set(new JSONNumber(0.0f)); return 0.0f; }
 | 
						|
            set { Set(new JSONNumber(value)); }
 | 
						|
        }
 | 
						|
 | 
						|
        public override double AsDouble
 | 
						|
        {
 | 
						|
            get { Set(new JSONNumber(0.0)); return 0.0; }
 | 
						|
            set { Set(new JSONNumber(value)); }
 | 
						|
        }
 | 
						|
 | 
						|
        public override long AsLong
 | 
						|
        {
 | 
						|
            get
 | 
						|
            {
 | 
						|
                if (longAsString)
 | 
						|
                    Set(new JSONString("0"));
 | 
						|
                else
 | 
						|
                    Set(new JSONNumber(0.0));
 | 
						|
                return 0L;
 | 
						|
            }
 | 
						|
            set
 | 
						|
            {
 | 
						|
                if (longAsString)
 | 
						|
                    Set(new JSONString(value.ToString()));
 | 
						|
                else
 | 
						|
                    Set(new JSONNumber(value));
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        public override bool AsBool
 | 
						|
        {
 | 
						|
            get { Set(new JSONBool(false)); return false; }
 | 
						|
            set { Set(new JSONBool(value)); }
 | 
						|
        }
 | 
						|
 | 
						|
        public override JSONArray AsArray
 | 
						|
        {
 | 
						|
            get { return Set(new JSONArray()); }
 | 
						|
        }
 | 
						|
 | 
						|
        public override JSONObject AsObject
 | 
						|
        {
 | 
						|
            get { return Set(new JSONObject()); }
 | 
						|
        }
 | 
						|
        internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
 | 
						|
        {
 | 
						|
            aSB.Append("null");
 | 
						|
        }
 | 
						|
    }
 | 
						|
    // End of JSONLazyCreator
 | 
						|
 | 
						|
    public static class JSON
 | 
						|
    {
 | 
						|
        public static JSONNode Parse(string aJSON)
 | 
						|
        {
 | 
						|
            return JSONNode.Parse(aJSON);
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |