Assignment for RMIT Mixed Reality in 2020
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.

1352 lines
44 KiB

  1. /* * * * *
  2. * A simple JSON Parser / builder
  3. * ------------------------------
  4. *
  5. * It mainly has been written as a simple JSON parser. It can build a JSON string
  6. * from the node-tree, or generate a node tree from any valid JSON string.
  7. *
  8. * If you want to use compression when saving to file / stream / B64 you have to include
  9. * SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) in your project and
  10. * define "USE_SharpZipLib" at the top of the file
  11. *
  12. * Written by Bunny83
  13. * 2012-06-09
  14. *
  15. * [2012-06-09 First Version]
  16. * - provides strongly typed node classes and lists / dictionaries
  17. * - provides easy access to class members / array items / data values
  18. * - the parser now properly identifies types. So generating JSON with this framework should work.
  19. * - only double quotes (") are used for quoting strings.
  20. * - provides "casting" properties to easily convert to / from those types:
  21. * int / float / double / bool
  22. * - provides a common interface for each node so no explicit casting is required.
  23. * - the parser tries to avoid errors, but if malformed JSON is parsed the result is more or less undefined
  24. * - It can serialize/deserialize a node tree into/from an experimental compact binary format. It might
  25. * be handy if you want to store things in a file and don't want it to be easily modifiable
  26. *
  27. * [2012-12-17 Update]
  28. * - Added internal JSONLazyCreator class which simplifies the construction of a JSON tree
  29. * Now you can simple reference any item that doesn't exist yet and it will return a JSONLazyCreator
  30. * The class determines the required type by it's further use, creates the type and removes itself.
  31. * - Added binary serialization / deserialization.
  32. * - Added support for BZip2 zipped binary format. Requires the SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ )
  33. * The usage of the SharpZipLib library can be disabled by removing or commenting out the USE_SharpZipLib define at the top
  34. * - The serializer uses different types when it comes to store the values. Since my data values
  35. * are all of type string, the serializer will "try" which format fits best. The order is: int, float, double, bool, string.
  36. * It's not the most efficient way but for a moderate amount of data it should work on all platforms.
  37. *
  38. * [2017-03-08 Update]
  39. * - Optimised parsing by using a StringBuilder for token. This prevents performance issues when large
  40. * string data fields are contained in the json data.
  41. * - Finally refactored the badly named JSONClass into JSONObject.
  42. * - Replaced the old JSONData class by distict typed classes ( JSONString, JSONNumber, JSONBool, JSONNull ) this
  43. * allows to propertly convert the node tree back to json without type information loss. The actual value
  44. * parsing now happens at parsing time and not when you actually access one of the casting properties.
  45. *
  46. * [2017-04-11 Update]
  47. * - Fixed parsing bug where empty string values have been ignored.
  48. * - Optimised "ToString" by using a StringBuilder internally. This should heavily improve performance for large files
  49. * - Changed the overload of "ToString(string aIndent)" to "ToString(int aIndent)"
  50. *
  51. * [2017-11-29 Update]
  52. * - Removed the IEnumerator implementations on JSONArray & JSONObject and replaced it with a common
  53. * struct Enumerator in JSONNode that should avoid garbage generation. The enumerator always works
  54. * on KeyValuePair<string, JSONNode>, even for JSONArray.
  55. * - Added two wrapper Enumerators that allows for easy key or value enumeration. A JSONNode now has
  56. * a "Keys" and a "Values" enumerable property. Those are also struct enumerators / enumerables
  57. * - A KeyValuePair<string, JSONNode> can now be implicitly converted into a JSONNode. This allows
  58. * a foreach loop over a JSONNode to directly access the values only. Since KeyValuePair as well as
  59. * all the Enumerators are structs, no garbage is allocated.
  60. * - To add Linq support another "LinqEnumerator" is available through the "Linq" property. This
  61. * enumerator does implement the generic IEnumerable interface so most Linq extensions can be used
  62. * on this enumerable object. This one does allocate memory as it's a wrapper class.
  63. * - The Escape method now escapes all control characters (# < 32) in strings as uncode characters
  64. * (\uXXXX) and if the static bool JSONNode.forceASCII is set to true it will also escape all
  65. * characters # > 127. This might be useful if you require an ASCII output. Though keep in mind
  66. * when your strings contain many non-ascii characters the strings become much longer (x6) and are
  67. * no longer human readable.
  68. * - The node types JSONObject and JSONArray now have an "Inline" boolean switch which will default to
  69. * false. It can be used to serialize this element inline even you serialize with an indented format
  70. * This is useful for arrays containing numbers so it doesn't place every number on a new line
  71. * - Extracted the binary serialization code into a seperate extension file. All classes are now declared
  72. * as "partial" so an extension file can even add a new virtual or abstract method / interface to
  73. * JSONNode and override it in the concrete type classes. It's of course a hacky approach which is
  74. * generally not recommended, but i wanted to keep everything tightly packed.
  75. * - Added a static CreateOrGet method to the JSONNull class. Since this class is immutable it could
  76. * be reused without major problems. If you have a lot null fields in your data it will help reduce
  77. * the memory / garbage overhead. I also added a static setting (reuseSameInstance) to JSONNull
  78. * (default is true) which will change the behaviour of "CreateOrGet". If you set this to false
  79. * CreateOrGet will not reuse the cached instance but instead create a new JSONNull instance each time.
  80. * I made the JSONNull constructor private so if you need to create an instance manually use
  81. * JSONNull.CreateOrGet()
  82. *
  83. * [2018-01-09 Update]
  84. * - Changed all double.TryParse and double.ToString uses to use the invariant culture to avoid problems
  85. * on systems with a culture that uses a comma as decimal point.
  86. *
  87. * [2018-01-26 Update]
  88. * - Added AsLong. Note that a JSONNumber is stored as double and can't represent all long values. However
  89. * storing it as string would work.
  90. * - Added static setting "JSONNode.longAsString" which controls the default type that is used by the
  91. * LazyCreator when using AsLong
  92. *
  93. * [2018-04-25 Update]
  94. * - Added support for parsing single values (JSONBool, JSONString, JSONNumber, JSONNull) as top level value.
  95. *
  96. * The MIT License (MIT)
  97. *
  98. * Copyright (c) 2012-2017 Markus Göbel (Bunny83)
  99. *
  100. * Permission is hereby granted, free of charge, to any person obtaining a copy
  101. * of this software and associated documentation files (the "Software"), to deal
  102. * in the Software without restriction, including without limitation the rights
  103. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  104. * copies of the Software, and to permit persons to whom the Software is
  105. * furnished to do so, subject to the following conditions:
  106. *
  107. * The above copyright notice and this permission notice shall be included in all
  108. * copies or substantial portions of the Software.
  109. *
  110. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  111. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  112. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  113. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  114. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  115. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  116. * SOFTWARE.
  117. *
  118. * * * * */
  119. using System;
  120. using System.Collections;
  121. using System.Collections.Generic;
  122. using System.Globalization;
  123. using System.Linq;
  124. using System.Text;
  125. // renaming the namespace to avoid conflict
  126. namespace OVRSimpleJSON // SimpleJSON
  127. {
  128. public enum JSONNodeType
  129. {
  130. Array = 1,
  131. Object = 2,
  132. String = 3,
  133. Number = 4,
  134. NullValue = 5,
  135. Boolean = 6,
  136. None = 7,
  137. Custom = 0xFF,
  138. }
  139. public enum JSONTextMode
  140. {
  141. Compact,
  142. Indent
  143. }
  144. public abstract partial class JSONNode
  145. {
  146. #region Enumerators
  147. public struct Enumerator
  148. {
  149. private enum Type { None, Array, Object }
  150. private Type type;
  151. private Dictionary<string, JSONNode>.Enumerator m_Object;
  152. private List<JSONNode>.Enumerator m_Array;
  153. public bool IsValid { get { return type != Type.None; } }
  154. public Enumerator(List<JSONNode>.Enumerator aArrayEnum)
  155. {
  156. type = Type.Array;
  157. m_Object = default(Dictionary<string, JSONNode>.Enumerator);
  158. m_Array = aArrayEnum;
  159. }
  160. public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum)
  161. {
  162. type = Type.Object;
  163. m_Object = aDictEnum;
  164. m_Array = default(List<JSONNode>.Enumerator);
  165. }
  166. public KeyValuePair<string, JSONNode> Current
  167. {
  168. get {
  169. if (type == Type.Array)
  170. return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current);
  171. else if (type == Type.Object)
  172. return m_Object.Current;
  173. return new KeyValuePair<string, JSONNode>(string.Empty, null);
  174. }
  175. }
  176. public bool MoveNext()
  177. {
  178. if (type == Type.Array)
  179. return m_Array.MoveNext();
  180. else if (type == Type.Object)
  181. return m_Object.MoveNext();
  182. return false;
  183. }
  184. }
  185. public struct ValueEnumerator
  186. {
  187. private Enumerator m_Enumerator;
  188. public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { }
  189. public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { }
  190. public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; }
  191. public JSONNode Current { get { return m_Enumerator.Current.Value; } }
  192. public bool MoveNext() { return m_Enumerator.MoveNext(); }
  193. public ValueEnumerator GetEnumerator() { return this; }
  194. }
  195. public struct KeyEnumerator
  196. {
  197. private Enumerator m_Enumerator;
  198. public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { }
  199. public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { }
  200. public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; }
  201. public string Current { get { return m_Enumerator.Current.Key; } }
  202. public bool MoveNext() { return m_Enumerator.MoveNext(); }
  203. public KeyEnumerator GetEnumerator() { return this; }
  204. }
  205. public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IEnumerable<KeyValuePair<string, JSONNode>>
  206. {
  207. private JSONNode m_Node;
  208. private Enumerator m_Enumerator;
  209. internal LinqEnumerator(JSONNode aNode)
  210. {
  211. m_Node = aNode;
  212. if (m_Node != null)
  213. m_Enumerator = m_Node.GetEnumerator();
  214. }
  215. public KeyValuePair<string, JSONNode> Current { get { return m_Enumerator.Current; } }
  216. object IEnumerator.Current { get { return m_Enumerator.Current; } }
  217. public bool MoveNext() { return m_Enumerator.MoveNext(); }
  218. public void Dispose()
  219. {
  220. m_Node = null;
  221. m_Enumerator = new Enumerator();
  222. }
  223. public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator()
  224. {
  225. return new LinqEnumerator(m_Node);
  226. }
  227. public void Reset()
  228. {
  229. if (m_Node != null)
  230. m_Enumerator = m_Node.GetEnumerator();
  231. }
  232. IEnumerator IEnumerable.GetEnumerator()
  233. {
  234. return new LinqEnumerator(m_Node);
  235. }
  236. }
  237. #endregion Enumerators
  238. #region common interface
  239. public static bool forceASCII = false; // Use Unicode by default
  240. public static bool longAsString = false; // lazy creator creates a JSONString instead of JSONNumber
  241. public abstract JSONNodeType Tag { get; }
  242. public virtual JSONNode this[int aIndex] { get { return null; } set { } }
  243. public virtual JSONNode this[string aKey] { get { return null; } set { } }
  244. public virtual string Value { get { return ""; } set { } }
  245. public virtual int Count { get { return 0; } }
  246. public virtual bool IsNumber { get { return false; } }
  247. public virtual bool IsString { get { return false; } }
  248. public virtual bool IsBoolean { get { return false; } }
  249. public virtual bool IsNull { get { return false; } }
  250. public virtual bool IsArray { get { return false; } }
  251. public virtual bool IsObject { get { return false; } }
  252. public virtual bool Inline { get { return false; } set { } }
  253. public virtual void Add(string aKey, JSONNode aItem)
  254. {
  255. }
  256. public virtual void Add(JSONNode aItem)
  257. {
  258. Add("", aItem);
  259. }
  260. public virtual JSONNode Remove(string aKey)
  261. {
  262. return null;
  263. }
  264. public virtual JSONNode Remove(int aIndex)
  265. {
  266. return null;
  267. }
  268. public virtual JSONNode Remove(JSONNode aNode)
  269. {
  270. return aNode;
  271. }
  272. public virtual IEnumerable<JSONNode> Children
  273. {
  274. get
  275. {
  276. yield break;
  277. }
  278. }
  279. public IEnumerable<JSONNode> DeepChildren
  280. {
  281. get
  282. {
  283. foreach (var C in Children)
  284. foreach (var D in C.DeepChildren)
  285. yield return D;
  286. }
  287. }
  288. public override string ToString()
  289. {
  290. StringBuilder sb = new StringBuilder();
  291. WriteToStringBuilder(sb, 0, 0, JSONTextMode.Compact);
  292. return sb.ToString();
  293. }
  294. public virtual string ToString(int aIndent)
  295. {
  296. StringBuilder sb = new StringBuilder();
  297. WriteToStringBuilder(sb, 0, aIndent, JSONTextMode.Indent);
  298. return sb.ToString();
  299. }
  300. internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode);
  301. public abstract Enumerator GetEnumerator();
  302. public IEnumerable<KeyValuePair<string, JSONNode>> Linq { get { return new LinqEnumerator(this); } }
  303. public KeyEnumerator Keys { get { return new KeyEnumerator(GetEnumerator()); } }
  304. public ValueEnumerator Values { get { return new ValueEnumerator(GetEnumerator()); } }
  305. #endregion common interface
  306. #region typecasting properties
  307. public virtual double AsDouble
  308. {
  309. get
  310. {
  311. double v = 0.0;
  312. if (double.TryParse(Value,NumberStyles.Float, CultureInfo.InvariantCulture, out v))
  313. return v;
  314. return 0.0;
  315. }
  316. set
  317. {
  318. Value = value.ToString(CultureInfo.InvariantCulture);
  319. }
  320. }
  321. public virtual int AsInt
  322. {
  323. get { return (int)AsDouble; }
  324. set { AsDouble = value; }
  325. }
  326. public virtual float AsFloat
  327. {
  328. get { return (float)AsDouble; }
  329. set { AsDouble = value; }
  330. }
  331. public virtual bool AsBool
  332. {
  333. get
  334. {
  335. bool v = false;
  336. if (bool.TryParse(Value, out v))
  337. return v;
  338. return !string.IsNullOrEmpty(Value);
  339. }
  340. set
  341. {
  342. Value = (value) ? "true" : "false";
  343. }
  344. }
  345. public virtual long AsLong
  346. {
  347. get
  348. {
  349. long val = 0;
  350. if (long.TryParse(Value, out val))
  351. return val;
  352. return 0L;
  353. }
  354. set
  355. {
  356. Value = value.ToString();
  357. }
  358. }
  359. public virtual JSONArray AsArray
  360. {
  361. get
  362. {
  363. return this as JSONArray;
  364. }
  365. }
  366. public virtual JSONObject AsObject
  367. {
  368. get
  369. {
  370. return this as JSONObject;
  371. }
  372. }
  373. #endregion typecasting properties
  374. #region operators
  375. public static implicit operator JSONNode(string s)
  376. {
  377. return new JSONString(s);
  378. }
  379. public static implicit operator string(JSONNode d)
  380. {
  381. return (d == null) ? null : d.Value;
  382. }
  383. public static implicit operator JSONNode(double n)
  384. {
  385. return new JSONNumber(n);
  386. }
  387. public static implicit operator double(JSONNode d)
  388. {
  389. return (d == null) ? 0 : d.AsDouble;
  390. }
  391. public static implicit operator JSONNode(float n)
  392. {
  393. return new JSONNumber(n);
  394. }
  395. public static implicit operator float(JSONNode d)
  396. {
  397. return (d == null) ? 0 : d.AsFloat;
  398. }
  399. public static implicit operator JSONNode(int n)
  400. {
  401. return new JSONNumber(n);
  402. }
  403. public static implicit operator int(JSONNode d)
  404. {
  405. return (d == null) ? 0 : d.AsInt;
  406. }
  407. public static implicit operator JSONNode(long n)
  408. {
  409. if (longAsString)
  410. return new JSONString(n.ToString());
  411. return new JSONNumber(n);
  412. }
  413. public static implicit operator long(JSONNode d)
  414. {
  415. return (d == null) ? 0L : d.AsLong;
  416. }
  417. public static implicit operator JSONNode(bool b)
  418. {
  419. return new JSONBool(b);
  420. }
  421. public static implicit operator bool(JSONNode d)
  422. {
  423. return (d == null) ? false : d.AsBool;
  424. }
  425. public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue)
  426. {
  427. return aKeyValue.Value;
  428. }
  429. public static bool operator ==(JSONNode a, object b)
  430. {
  431. if (ReferenceEquals(a, b))
  432. return true;
  433. bool aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator;
  434. bool bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator;
  435. if (aIsNull && bIsNull)
  436. return true;
  437. return !aIsNull && a.Equals(b);
  438. }
  439. public static bool operator !=(JSONNode a, object b)
  440. {
  441. return !(a == b);
  442. }
  443. public override bool Equals(object obj)
  444. {
  445. return ReferenceEquals(this, obj);
  446. }
  447. public override int GetHashCode()
  448. {
  449. return base.GetHashCode();
  450. }
  451. #endregion operators
  452. [ThreadStatic]
  453. private static StringBuilder m_EscapeBuilder;
  454. internal static StringBuilder EscapeBuilder
  455. {
  456. get {
  457. if (m_EscapeBuilder == null)
  458. m_EscapeBuilder = new StringBuilder();
  459. return m_EscapeBuilder;
  460. }
  461. }
  462. internal static string Escape(string aText)
  463. {
  464. var sb = EscapeBuilder;
  465. sb.Length = 0;
  466. if (sb.Capacity < aText.Length + aText.Length / 10)
  467. sb.Capacity = aText.Length + aText.Length / 10;
  468. foreach (char c in aText)
  469. {
  470. switch (c)
  471. {
  472. case '\\':
  473. sb.Append("\\\\");
  474. break;
  475. case '\"':
  476. sb.Append("\\\"");
  477. break;
  478. case '\n':
  479. sb.Append("\\n");
  480. break;
  481. case '\r':
  482. sb.Append("\\r");
  483. break;
  484. case '\t':
  485. sb.Append("\\t");
  486. break;
  487. case '\b':
  488. sb.Append("\\b");
  489. break;
  490. case '\f':
  491. sb.Append("\\f");
  492. break;
  493. default:
  494. if (c < ' ' || (forceASCII && c > 127))
  495. {
  496. ushort val = c;
  497. sb.Append("\\u").Append(val.ToString("X4"));
  498. }
  499. else
  500. sb.Append(c);
  501. break;
  502. }
  503. }
  504. string result = sb.ToString();
  505. sb.Length = 0;
  506. return result;
  507. }
  508. private static JSONNode ParseElement(string token, bool quoted)
  509. {
  510. if (quoted)
  511. return token;
  512. string tmp = token.ToLower();
  513. if (tmp == "false" || tmp == "true")
  514. return tmp == "true";
  515. if (tmp == "null")
  516. return JSONNull.CreateOrGet();
  517. double val;
  518. if (double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out val))
  519. return val;
  520. else
  521. return token;
  522. }
  523. public static JSONNode Parse(string aJSON)
  524. {
  525. Stack<JSONNode> stack = new Stack<JSONNode>();
  526. JSONNode ctx = null;
  527. int i = 0;
  528. StringBuilder Token = new StringBuilder();
  529. string TokenName = "";
  530. bool QuoteMode = false;
  531. bool TokenIsQuoted = false;
  532. while (i < aJSON.Length)
  533. {
  534. switch (aJSON[i])
  535. {
  536. case '{':
  537. if (QuoteMode)
  538. {
  539. Token.Append(aJSON[i]);
  540. break;
  541. }
  542. stack.Push(new JSONObject());
  543. if (ctx != null)
  544. {
  545. ctx.Add(TokenName, stack.Peek());
  546. }
  547. TokenName = "";
  548. Token.Length = 0;
  549. ctx = stack.Peek();
  550. break;
  551. case '[':
  552. if (QuoteMode)
  553. {
  554. Token.Append(aJSON[i]);
  555. break;
  556. }
  557. stack.Push(new JSONArray());
  558. if (ctx != null)
  559. {
  560. ctx.Add(TokenName, stack.Peek());
  561. }
  562. TokenName = "";
  563. Token.Length = 0;
  564. ctx = stack.Peek();
  565. break;
  566. case '}':
  567. case ']':
  568. if (QuoteMode)
  569. {
  570. Token.Append(aJSON[i]);
  571. break;
  572. }
  573. if (stack.Count == 0)
  574. throw new Exception("JSON Parse: Too many closing brackets");
  575. stack.Pop();
  576. if (Token.Length > 0 || TokenIsQuoted)
  577. ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted));
  578. TokenIsQuoted = false;
  579. TokenName = "";
  580. Token.Length = 0;
  581. if (stack.Count > 0)
  582. ctx = stack.Peek();
  583. break;
  584. case ':':
  585. if (QuoteMode)
  586. {
  587. Token.Append(aJSON[i]);
  588. break;
  589. }
  590. TokenName = Token.ToString();
  591. Token.Length = 0;
  592. TokenIsQuoted = false;
  593. break;
  594. case '"':
  595. QuoteMode ^= true;
  596. TokenIsQuoted |= QuoteMode;
  597. break;
  598. case ',':
  599. if (QuoteMode)
  600. {
  601. Token.Append(aJSON[i]);
  602. break;
  603. }
  604. if (Token.Length > 0 || TokenIsQuoted)
  605. ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted));
  606. TokenIsQuoted = false;
  607. TokenName = "";
  608. Token.Length = 0;
  609. TokenIsQuoted = false;
  610. break;
  611. case '\r':
  612. case '\n':
  613. break;
  614. case ' ':
  615. case '\t':
  616. if (QuoteMode)
  617. Token.Append(aJSON[i]);
  618. break;
  619. case '\\':
  620. ++i;
  621. if (QuoteMode)
  622. {
  623. char C = aJSON[i];
  624. switch (C)
  625. {
  626. case 't':
  627. Token.Append('\t');
  628. break;
  629. case 'r':
  630. Token.Append('\r');
  631. break;
  632. case 'n':
  633. Token.Append('\n');
  634. break;
  635. case 'b':
  636. Token.Append('\b');
  637. break;
  638. case 'f':
  639. Token.Append('\f');
  640. break;
  641. case 'u':
  642. {
  643. string s = aJSON.Substring(i + 1, 4);
  644. Token.Append((char)int.Parse(
  645. s,
  646. System.Globalization.NumberStyles.AllowHexSpecifier));
  647. i += 4;
  648. break;
  649. }
  650. default:
  651. Token.Append(C);
  652. break;
  653. }
  654. }
  655. break;
  656. default:
  657. Token.Append(aJSON[i]);
  658. break;
  659. }
  660. ++i;
  661. }
  662. if (QuoteMode)
  663. {
  664. throw new Exception("JSON Parse: Quotation marks seems to be messed up.");
  665. }
  666. if (ctx == null)
  667. return ParseElement(Token.ToString(), TokenIsQuoted);
  668. return ctx;
  669. }
  670. }
  671. // End of JSONNode
  672. public partial class JSONArray : JSONNode
  673. {
  674. private List<JSONNode> m_List = new List<JSONNode>();
  675. private bool inline = false;
  676. public override bool Inline
  677. {
  678. get { return inline; }
  679. set { inline = value; }
  680. }
  681. public override JSONNodeType Tag { get { return JSONNodeType.Array; } }
  682. public override bool IsArray { get { return true; } }
  683. public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); }
  684. public override JSONNode this[int aIndex]
  685. {
  686. get
  687. {
  688. if (aIndex < 0 || aIndex >= m_List.Count)
  689. return new JSONLazyCreator(this);
  690. return m_List[aIndex];
  691. }
  692. set
  693. {
  694. if (value == null)
  695. value = JSONNull.CreateOrGet();
  696. if (aIndex < 0 || aIndex >= m_List.Count)
  697. m_List.Add(value);
  698. else
  699. m_List[aIndex] = value;
  700. }
  701. }
  702. public override JSONNode this[string aKey]
  703. {
  704. get { return new JSONLazyCreator(this); }
  705. set
  706. {
  707. if (value == null)
  708. value = JSONNull.CreateOrGet();
  709. m_List.Add(value);
  710. }
  711. }
  712. public override int Count
  713. {
  714. get { return m_List.Count; }
  715. }
  716. public override void Add(string aKey, JSONNode aItem)
  717. {
  718. if (aItem == null)
  719. aItem = JSONNull.CreateOrGet();
  720. m_List.Add(aItem);
  721. }
  722. public override JSONNode Remove(int aIndex)
  723. {
  724. if (aIndex < 0 || aIndex >= m_List.Count)
  725. return null;
  726. JSONNode tmp = m_List[aIndex];
  727. m_List.RemoveAt(aIndex);
  728. return tmp;
  729. }
  730. public override JSONNode Remove(JSONNode aNode)
  731. {
  732. m_List.Remove(aNode);
  733. return aNode;
  734. }
  735. public override IEnumerable<JSONNode> Children
  736. {
  737. get
  738. {
  739. foreach (JSONNode N in m_List)
  740. yield return N;
  741. }
  742. }
  743. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  744. {
  745. aSB.Append('[');
  746. int count = m_List.Count;
  747. if (inline)
  748. aMode = JSONTextMode.Compact;
  749. for (int i = 0; i < count; i++)
  750. {
  751. if (i > 0)
  752. aSB.Append(',');
  753. if (aMode == JSONTextMode.Indent)
  754. aSB.AppendLine();
  755. if (aMode == JSONTextMode.Indent)
  756. aSB.Append(' ', aIndent + aIndentInc);
  757. m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
  758. }
  759. if (aMode == JSONTextMode.Indent)
  760. aSB.AppendLine().Append(' ', aIndent);
  761. aSB.Append(']');
  762. }
  763. }
  764. // End of JSONArray
  765. public partial class JSONObject : JSONNode
  766. {
  767. private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>();
  768. private bool inline = false;
  769. public override bool Inline
  770. {
  771. get { return inline; }
  772. set { inline = value; }
  773. }
  774. public override JSONNodeType Tag { get { return JSONNodeType.Object; } }
  775. public override bool IsObject { get { return true; } }
  776. public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); }
  777. public override JSONNode this[string aKey]
  778. {
  779. get
  780. {
  781. if (m_Dict.ContainsKey(aKey))
  782. return m_Dict[aKey];
  783. else
  784. return new JSONLazyCreator(this, aKey);
  785. }
  786. set
  787. {
  788. if (value == null)
  789. value = JSONNull.CreateOrGet();
  790. if (m_Dict.ContainsKey(aKey))
  791. m_Dict[aKey] = value;
  792. else
  793. m_Dict.Add(aKey, value);
  794. }
  795. }
  796. public override JSONNode this[int aIndex]
  797. {
  798. get
  799. {
  800. if (aIndex < 0 || aIndex >= m_Dict.Count)
  801. return null;
  802. return m_Dict.ElementAt(aIndex).Value;
  803. }
  804. set
  805. {
  806. if (value == null)
  807. value = JSONNull.CreateOrGet();
  808. if (aIndex < 0 || aIndex >= m_Dict.Count)
  809. return;
  810. string key = m_Dict.ElementAt(aIndex).Key;
  811. m_Dict[key] = value;
  812. }
  813. }
  814. public override int Count
  815. {
  816. get { return m_Dict.Count; }
  817. }
  818. public override void Add(string aKey, JSONNode aItem)
  819. {
  820. if (aItem == null)
  821. aItem = JSONNull.CreateOrGet();
  822. if (!string.IsNullOrEmpty(aKey))
  823. {
  824. if (m_Dict.ContainsKey(aKey))
  825. m_Dict[aKey] = aItem;
  826. else
  827. m_Dict.Add(aKey, aItem);
  828. }
  829. else
  830. m_Dict.Add(Guid.NewGuid().ToString(), aItem);
  831. }
  832. public override JSONNode Remove(string aKey)
  833. {
  834. if (!m_Dict.ContainsKey(aKey))
  835. return null;
  836. JSONNode tmp = m_Dict[aKey];
  837. m_Dict.Remove(aKey);
  838. return tmp;
  839. }
  840. public override JSONNode Remove(int aIndex)
  841. {
  842. if (aIndex < 0 || aIndex >= m_Dict.Count)
  843. return null;
  844. var item = m_Dict.ElementAt(aIndex);
  845. m_Dict.Remove(item.Key);
  846. return item.Value;
  847. }
  848. public override JSONNode Remove(JSONNode aNode)
  849. {
  850. try
  851. {
  852. var item = m_Dict.Where(k => k.Value == aNode).First();
  853. m_Dict.Remove(item.Key);
  854. return aNode;
  855. }
  856. catch
  857. {
  858. return null;
  859. }
  860. }
  861. public override IEnumerable<JSONNode> Children
  862. {
  863. get
  864. {
  865. foreach (KeyValuePair<string, JSONNode> N in m_Dict)
  866. yield return N.Value;
  867. }
  868. }
  869. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  870. {
  871. aSB.Append('{');
  872. bool first = true;
  873. if (inline)
  874. aMode = JSONTextMode.Compact;
  875. foreach (var k in m_Dict)
  876. {
  877. if (!first)
  878. aSB.Append(',');
  879. first = false;
  880. if (aMode == JSONTextMode.Indent)
  881. aSB.AppendLine();
  882. if (aMode == JSONTextMode.Indent)
  883. aSB.Append(' ', aIndent + aIndentInc);
  884. aSB.Append('\"').Append(Escape(k.Key)).Append('\"');
  885. if (aMode == JSONTextMode.Compact)
  886. aSB.Append(':');
  887. else
  888. aSB.Append(" : ");
  889. k.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode);
  890. }
  891. if (aMode == JSONTextMode.Indent)
  892. aSB.AppendLine().Append(' ', aIndent);
  893. aSB.Append('}');
  894. }
  895. }
  896. // End of JSONObject
  897. public partial class JSONString : JSONNode
  898. {
  899. private string m_Data;
  900. public override JSONNodeType Tag { get { return JSONNodeType.String; } }
  901. public override bool IsString { get { return true; } }
  902. public override Enumerator GetEnumerator() { return new Enumerator(); }
  903. public override string Value
  904. {
  905. get { return m_Data; }
  906. set
  907. {
  908. m_Data = value;
  909. }
  910. }
  911. public JSONString(string aData)
  912. {
  913. m_Data = aData;
  914. }
  915. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  916. {
  917. aSB.Append('\"').Append(Escape(m_Data)).Append('\"');
  918. }
  919. public override bool Equals(object obj)
  920. {
  921. if (base.Equals(obj))
  922. return true;
  923. string s = obj as string;
  924. if (s != null)
  925. return m_Data == s;
  926. JSONString s2 = obj as JSONString;
  927. if (s2 != null)
  928. return m_Data == s2.m_Data;
  929. return false;
  930. }
  931. public override int GetHashCode()
  932. {
  933. return m_Data.GetHashCode();
  934. }
  935. }
  936. // End of JSONString
  937. public partial class JSONNumber : JSONNode
  938. {
  939. private double m_Data;
  940. public override JSONNodeType Tag { get { return JSONNodeType.Number; } }
  941. public override bool IsNumber { get { return true; } }
  942. public override Enumerator GetEnumerator() { return new Enumerator(); }
  943. public override string Value
  944. {
  945. get { return m_Data.ToString(CultureInfo.InvariantCulture); }
  946. set
  947. {
  948. double v;
  949. if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out v))
  950. m_Data = v;
  951. }
  952. }
  953. public override double AsDouble
  954. {
  955. get { return m_Data; }
  956. set { m_Data = value; }
  957. }
  958. public override long AsLong
  959. {
  960. get { return (long)m_Data; }
  961. set { m_Data = value; }
  962. }
  963. public JSONNumber(double aData)
  964. {
  965. m_Data = aData;
  966. }
  967. public JSONNumber(string aData)
  968. {
  969. Value = aData;
  970. }
  971. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  972. {
  973. aSB.Append(Value);
  974. }
  975. private static bool IsNumeric(object value)
  976. {
  977. return value is int || value is uint
  978. || value is float || value is double
  979. || value is decimal
  980. || value is long || value is ulong
  981. || value is short || value is ushort
  982. || value is sbyte || value is byte;
  983. }
  984. public override bool Equals(object obj)
  985. {
  986. if (obj == null)
  987. return false;
  988. if (base.Equals(obj))
  989. return true;
  990. JSONNumber s2 = obj as JSONNumber;
  991. if (s2 != null)
  992. return m_Data == s2.m_Data;
  993. if (IsNumeric(obj))
  994. return Convert.ToDouble(obj) == m_Data;
  995. return false;
  996. }
  997. public override int GetHashCode()
  998. {
  999. return m_Data.GetHashCode();
  1000. }
  1001. }
  1002. // End of JSONNumber
  1003. public partial class JSONBool : JSONNode
  1004. {
  1005. private bool m_Data;
  1006. public override JSONNodeType Tag { get { return JSONNodeType.Boolean; } }
  1007. public override bool IsBoolean { get { return true; } }
  1008. public override Enumerator GetEnumerator() { return new Enumerator(); }
  1009. public override string Value
  1010. {
  1011. get { return m_Data.ToString(); }
  1012. set
  1013. {
  1014. bool v;
  1015. if (bool.TryParse(value, out v))
  1016. m_Data = v;
  1017. }
  1018. }
  1019. public override bool AsBool
  1020. {
  1021. get { return m_Data; }
  1022. set { m_Data = value; }
  1023. }
  1024. public JSONBool(bool aData)
  1025. {
  1026. m_Data = aData;
  1027. }
  1028. public JSONBool(string aData)
  1029. {
  1030. Value = aData;
  1031. }
  1032. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  1033. {
  1034. aSB.Append((m_Data) ? "true" : "false");
  1035. }
  1036. public override bool Equals(object obj)
  1037. {
  1038. if (obj == null)
  1039. return false;
  1040. if (obj is bool)
  1041. return m_Data == (bool)obj;
  1042. return false;
  1043. }
  1044. public override int GetHashCode()
  1045. {
  1046. return m_Data.GetHashCode();
  1047. }
  1048. }
  1049. // End of JSONBool
  1050. public partial class JSONNull : JSONNode
  1051. {
  1052. static JSONNull m_StaticInstance = new JSONNull();
  1053. public static bool reuseSameInstance = true;
  1054. public static JSONNull CreateOrGet()
  1055. {
  1056. if (reuseSameInstance)
  1057. return m_StaticInstance;
  1058. return new JSONNull();
  1059. }
  1060. private JSONNull() { }
  1061. public override JSONNodeType Tag { get { return JSONNodeType.NullValue; } }
  1062. public override bool IsNull { get { return true; } }
  1063. public override Enumerator GetEnumerator() { return new Enumerator(); }
  1064. public override string Value
  1065. {
  1066. get { return "null"; }
  1067. set { }
  1068. }
  1069. public override bool AsBool
  1070. {
  1071. get { return false; }
  1072. set { }
  1073. }
  1074. public override bool Equals(object obj)
  1075. {
  1076. if (object.ReferenceEquals(this, obj))
  1077. return true;
  1078. return (obj is JSONNull);
  1079. }
  1080. public override int GetHashCode()
  1081. {
  1082. return 0;
  1083. }
  1084. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  1085. {
  1086. aSB.Append("null");
  1087. }
  1088. }
  1089. // End of JSONNull
  1090. internal partial class JSONLazyCreator : JSONNode
  1091. {
  1092. private JSONNode m_Node = null;
  1093. private string m_Key = null;
  1094. public override JSONNodeType Tag { get { return JSONNodeType.None; } }
  1095. public override Enumerator GetEnumerator() { return new Enumerator(); }
  1096. public JSONLazyCreator(JSONNode aNode)
  1097. {
  1098. m_Node = aNode;
  1099. m_Key = null;
  1100. }
  1101. public JSONLazyCreator(JSONNode aNode, string aKey)
  1102. {
  1103. m_Node = aNode;
  1104. m_Key = aKey;
  1105. }
  1106. private T Set<T>(T aVal) where T : JSONNode
  1107. {
  1108. if (m_Key == null)
  1109. m_Node.Add(aVal);
  1110. else
  1111. m_Node.Add(m_Key, aVal);
  1112. m_Node = null; // Be GC friendly.
  1113. return aVal;
  1114. }
  1115. public override JSONNode this[int aIndex]
  1116. {
  1117. get { return new JSONLazyCreator(this); }
  1118. set { Set(new JSONArray()).Add(value); }
  1119. }
  1120. public override JSONNode this[string aKey]
  1121. {
  1122. get { return new JSONLazyCreator(this, aKey); }
  1123. set { Set(new JSONObject()).Add(aKey, value); }
  1124. }
  1125. public override void Add(JSONNode aItem)
  1126. {
  1127. Set(new JSONArray()).Add(aItem);
  1128. }
  1129. public override void Add(string aKey, JSONNode aItem)
  1130. {
  1131. Set(new JSONObject()).Add(aKey, aItem);
  1132. }
  1133. public static bool operator ==(JSONLazyCreator a, object b)
  1134. {
  1135. if (b == null)
  1136. return true;
  1137. return System.Object.ReferenceEquals(a, b);
  1138. }
  1139. public static bool operator !=(JSONLazyCreator a, object b)
  1140. {
  1141. return !(a == b);
  1142. }
  1143. public override bool Equals(object obj)
  1144. {
  1145. if (obj == null)
  1146. return true;
  1147. return System.Object.ReferenceEquals(this, obj);
  1148. }
  1149. public override int GetHashCode()
  1150. {
  1151. return 0;
  1152. }
  1153. public override int AsInt
  1154. {
  1155. get { Set(new JSONNumber(0)); return 0; }
  1156. set { Set(new JSONNumber(value)); }
  1157. }
  1158. public override float AsFloat
  1159. {
  1160. get { Set(new JSONNumber(0.0f)); return 0.0f; }
  1161. set { Set(new JSONNumber(value)); }
  1162. }
  1163. public override double AsDouble
  1164. {
  1165. get { Set(new JSONNumber(0.0)); return 0.0; }
  1166. set { Set(new JSONNumber(value)); }
  1167. }
  1168. public override long AsLong
  1169. {
  1170. get
  1171. {
  1172. if (longAsString)
  1173. Set(new JSONString("0"));
  1174. else
  1175. Set(new JSONNumber(0.0));
  1176. return 0L;
  1177. }
  1178. set
  1179. {
  1180. if (longAsString)
  1181. Set(new JSONString(value.ToString()));
  1182. else
  1183. Set(new JSONNumber(value));
  1184. }
  1185. }
  1186. public override bool AsBool
  1187. {
  1188. get { Set(new JSONBool(false)); return false; }
  1189. set { Set(new JSONBool(value)); }
  1190. }
  1191. public override JSONArray AsArray
  1192. {
  1193. get { return Set(new JSONArray()); }
  1194. }
  1195. public override JSONObject AsObject
  1196. {
  1197. get { return Set(new JSONObject()); }
  1198. }
  1199. internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode)
  1200. {
  1201. aSB.Append("null");
  1202. }
  1203. }
  1204. // End of JSONLazyCreator
  1205. public static class JSON
  1206. {
  1207. public static JSONNode Parse(string aJSON)
  1208. {
  1209. return JSONNode.Parse(aJSON);
  1210. }
  1211. }
  1212. }