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