PageRenderTime 31ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/Assets/SDKBOX/SDKBOX/Assets/Json.cs

https://bitbucket.org/Anjali__Chayal/outback-slots-ios
C# | 599 lines | 486 code | 74 blank | 39 comment | 140 complexity | a834eb8415c067e9fa0706192670b885 MD5 | raw file
  1. /*****************************************************************************
  2. Copyright © 2015 SDKBOX.
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. THE SOFTWARE.
  18. *****************************************************************************/
  19. using UnityEngine;
  20. using System;
  21. using System.Collections;
  22. using System.Collections.Generic;
  23. using System.Runtime.InteropServices;
  24. namespace Sdkbox
  25. {
  26. public class Json
  27. {
  28. public enum Type {NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT};
  29. private Type _type;
  30. private double _d;
  31. private bool _b;
  32. private string _s;
  33. private List<Json> _a;
  34. private Dictionary<string, Json> _o;
  35. public static Json null_json;
  36. public Json()
  37. {
  38. _type = Type.NUL;
  39. }
  40. public Json(bool b)
  41. {
  42. _type = Type.BOOL;
  43. _b = b;
  44. }
  45. public Json(double d)
  46. {
  47. _type = Type.NUMBER;
  48. _d = d;
  49. }
  50. public Json(string s)
  51. {
  52. _type = Type.STRING;
  53. _s = s;
  54. }
  55. public Json(List<Json> a)
  56. {
  57. _type = Type.ARRAY;
  58. _a = a;
  59. }
  60. public Json(Dictionary<string, Json> o)
  61. {
  62. _type = Type.OBJECT;
  63. _o = o;
  64. }
  65. public Type type()
  66. {
  67. return _type;
  68. }
  69. public bool is_null()
  70. {
  71. return type() == Type.NUL;
  72. }
  73. public bool is_valid()
  74. {
  75. return type() != Type.NUL;
  76. }
  77. // @brief return the integer value from the Json value.
  78. // if this value is not type NUMBER then the result is undefined.
  79. public int int_value()
  80. {
  81. return (int)_d;
  82. }
  83. public bool bool_value()
  84. {
  85. return _b;
  86. }
  87. // @brief return the float value from the Json value.
  88. // if this value is not type NUMBER then the result is undefined.
  89. public float float_value()
  90. {
  91. return (float)_d;
  92. }
  93. // @brief return the double value from the Json value.
  94. // if this value is not type NUMBER then the result is undefined.
  95. public double double_value()
  96. {
  97. return _d;
  98. }
  99. // @brief return the string value from the Json value.
  100. // if this value is not type STRING then the result is undefined.
  101. public string string_value()
  102. {
  103. return _s;
  104. }
  105. // @brief return the array value from the Json value.
  106. // if this value is not type ARRAY then the result is undefined.
  107. public List<Json> array_items()
  108. {
  109. return _a;
  110. }
  111. // @brief return the object value from the Json value.
  112. // if this value is not type OBJECT then the result is undefined.
  113. public Dictionary<string, Json> object_items()
  114. {
  115. return _o;
  116. }
  117. // @brief operator to support json[index]
  118. public Json this[int index]
  119. {
  120. get { return _a[index]; }
  121. set { _a[index] = value; }
  122. }
  123. // @brief operator to suport json["key"]
  124. public Json this[string key]
  125. {
  126. get { return _o[key]; }
  127. set { _o[key] = value; }
  128. }
  129. public static Json parse(string jsonString)
  130. {
  131. JsonParser parser = new JsonParser(jsonString);
  132. Json result = parser.parse_json(0);
  133. // Check for any trailing garbage
  134. parser.consume_whitespace();
  135. if (parser.i != jsonString.Length)
  136. {
  137. char c = jsonString[parser.i];
  138. return new Json(parser.fail("unexpected trailing " + parser.esc(c)));
  139. }
  140. return result;
  141. }
  142. private string encode(string value)
  143. {
  144. string o = "\"";
  145. for (var i = 0; i < value.Length; i++) {
  146. char ch = value[i];
  147. if (ch == '\\') {
  148. o += "\\\\";
  149. } else if (ch == '"') {
  150. o += "\\\"";
  151. } else if (ch == '\b') {
  152. o += "\\b";
  153. } else if (ch == '\f') {
  154. o += "\\f";
  155. } else if (ch == '\n') {
  156. o += "\\n";
  157. } else if (ch == '\r') {
  158. o += "\\r";
  159. } else if (ch == '\t') {
  160. o += "\\t";
  161. } else if (ch <= 0x1f) {
  162. o += string.Format("\\u%{0:x4}", ch);
  163. } else if (ch == 0xe2 && value[i+1] == 0x80 && value[i+2] == 0xa8) {
  164. o += "\\u2028";
  165. i += 2;
  166. } else if (ch == 0xe2 && value[i+1] == 0x80 && value[i+2] == 0xa9) {
  167. o += "\\u2029";
  168. i += 2;
  169. } else {
  170. o += ch;
  171. }
  172. }
  173. o += "\"";
  174. return o;
  175. }
  176. public string dump()
  177. {
  178. switch (type())
  179. {
  180. case Type.NUL:
  181. return "null";
  182. case Type.NUMBER:
  183. return string.Format("{0}", _d);
  184. case Type.BOOL:
  185. return _b ? "true" : "false";
  186. case Type.STRING:
  187. return encode(_s);
  188. case Type.ARRAY:
  189. {
  190. string s = "[";
  191. foreach (var j in _a)
  192. {
  193. s += j.dump() + ",";
  194. }
  195. int l = s.Length;
  196. if (s[l-1] == ',')
  197. s = s.Substring(0, l-1);
  198. s += ']';
  199. return s;
  200. }
  201. case Type.OBJECT:
  202. {
  203. string s = "{";
  204. foreach (var kvp in _o)
  205. {
  206. s += '\"' + kvp.Key + "\":" + kvp.Value.dump() + ",";
  207. }
  208. int l = s.Length;
  209. if (s[l-1] == ',')
  210. s = s.Substring(0, l-1);
  211. s += '}';
  212. return s;
  213. }
  214. default:
  215. return ""; // not use these for now
  216. }
  217. }
  218. class JsonParser
  219. {
  220. private int MAX_DEPTH = 100;
  221. private int MAX_DIGITS = 15;
  222. private string str;
  223. private bool failed;
  224. public int i;
  225. public string err;
  226. public JsonParser(string jsonString)
  227. {
  228. i = 0;
  229. str = jsonString;
  230. err = "";
  231. failed = false;
  232. }
  233. public string fail(string msg)
  234. {
  235. if (!failed)
  236. err = msg;
  237. failed = true;
  238. return msg;
  239. }
  240. public T fail<T>(string msg, T err_ret)
  241. {
  242. if (!failed)
  243. err = msg;
  244. failed = true;
  245. return err_ret;
  246. }
  247. public string esc(char c)
  248. {
  249. if (c >= 0x20 && c <= 0x7f)
  250. {
  251. return string.Format("'{0}' ({1})", c, c);
  252. }
  253. else
  254. {
  255. return string.Format("({1})", c);
  256. }
  257. }
  258. public bool in_range(long x, long lower, long upper)
  259. {
  260. return (x >= lower && x <= upper);
  261. }
  262. public void consume_whitespace()
  263. {
  264. while (i < str.Length && (str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t'))
  265. i++;
  266. }
  267. public char get_next_token()
  268. {
  269. consume_whitespace();
  270. if (i == str.Length)
  271. return fail("unexpected end of input", '\0');
  272. return str[i++];
  273. }
  274. public void encode_utf8(long pt, string o)
  275. {
  276. if (pt < 0)
  277. return;
  278. if (pt < 0x80) {
  279. o += pt;
  280. } else if (pt < 0x800) {
  281. o += (pt >> 6) | 0xC0;
  282. o += (pt & 0x3F) | 0x80;
  283. } else if (pt < 0x10000) {
  284. o += (pt >> 12) | 0xE0;
  285. o += ((pt >> 6) & 0x3F) | 0x80;
  286. o += (pt & 0x3F) | 0x80;
  287. } else {
  288. o += (pt >> 18) | 0xF0;
  289. o += ((pt >> 12) & 0x3F) | 0x80;
  290. o += ((pt >> 6) & 0x3F) | 0x80;
  291. o += (pt & 0x3F) | 0x80;
  292. }
  293. }
  294. public string parse_string()
  295. {
  296. string o = "";
  297. long last_escaped_codepoint = -1;
  298. while (true)
  299. {
  300. if (i == str.Length)
  301. return fail("unexpected end of input in string");
  302. char ch = str[i++];
  303. if (ch == '"')
  304. {
  305. encode_utf8(last_escaped_codepoint, o);
  306. return o;
  307. }
  308. if (in_range(ch, 0, 0x1f))
  309. {
  310. string s = "unescaped " + esc(ch) + " in string";
  311. return fail(s);
  312. }
  313. // The usual case: non-escaped characters
  314. if (ch != '\\')
  315. {
  316. encode_utf8(last_escaped_codepoint, o);
  317. last_escaped_codepoint = -1;
  318. o += ch;
  319. continue;
  320. }
  321. // Handle escapes
  322. if (i == str.Length)
  323. return fail("unexpected end of input in string");
  324. ch = str[i++];
  325. if (ch == 'u')
  326. {
  327. // Extract 4-byte escape sequence
  328. string esc = str.Substring(i, 4);
  329. for (int j = 0; j < 4; j++)
  330. {
  331. if (!in_range(esc[j], 'a', 'f') && !in_range(esc[j], 'A', 'F')
  332. && !in_range(esc[j], '0', '9'))
  333. return fail("bad \\u escape: " + esc);
  334. }
  335. long codepoint = Convert.ToInt64(esc, 16);
  336. // JSON specifies that characters outside the BMP shall be encoded as a pair
  337. // of 4-hex-digit \u escapes encoding their surrogate pair components. Check
  338. // whether we're in the middle of such a beast: the previous codepoint was an
  339. // escaped lead (high) surrogate, and this is a trail (low) surrogate.
  340. if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF)
  341. && in_range(codepoint, 0xDC00, 0xDFFF)) {
  342. // Reassemble the two surrogate pairs into one astral-plane character, per
  343. // the UTF-16 algorithm.
  344. encode_utf8((((last_escaped_codepoint - 0xD800) << 10)
  345. | (codepoint - 0xDC00)) + 0x10000, o);
  346. last_escaped_codepoint = -1;
  347. } else {
  348. encode_utf8(last_escaped_codepoint, o);
  349. last_escaped_codepoint = codepoint;
  350. }
  351. i += 4;
  352. continue;
  353. }
  354. encode_utf8(last_escaped_codepoint, o);
  355. last_escaped_codepoint = -1;
  356. if (ch == 'b') {
  357. o += '\b';
  358. } else if (ch == 'f') {
  359. o += '\f';
  360. } else if (ch == 'n') {
  361. o += '\n';
  362. } else if (ch == 'r') {
  363. o += '\r';
  364. } else if (ch == 't') {
  365. o += '\t';
  366. } else if (ch == '"' || ch == '\\' || ch == '/') {
  367. o += ch;
  368. } else {
  369. return fail("invalid escape character " + esc(ch));
  370. }
  371. }
  372. }
  373. public Json parse_number()
  374. {
  375. int start_pos = i;
  376. if (str[i] == '-')
  377. i++;
  378. // Integer part
  379. if (str[i] == '0')
  380. {
  381. i++;
  382. if (in_range(str[i], '0', '9'))
  383. return new Json(fail("leading 0s not permitted in numbers"));
  384. }
  385. else if (in_range(str[i], '1', '9'))
  386. {
  387. i++;
  388. while (in_range(str[i], '0', '9'))
  389. i++;
  390. }
  391. else
  392. {
  393. return new Json(fail("invalid " + esc(str[i]) + " in number"));
  394. }
  395. if (str[i] != '.' && str[i] != 'e' && str[i] != 'E' && (i - start_pos) <= MAX_DIGITS)
  396. {
  397. return new Json((double)int.Parse(str.Substring(start_pos, i - start_pos)));
  398. }
  399. // Decimal part
  400. if (str[i] == '.')
  401. {
  402. i++;
  403. if (!in_range(str[i], '0', '9'))
  404. return new Json(fail("at least one digit required in fractional part"));
  405. while (in_range(str[i], '0', '9'))
  406. i++;
  407. }
  408. // Exponent part
  409. if (str[i] == 'e' || str[i] == 'E')
  410. {
  411. i++;
  412. if (str[i] == '+' || str[i] == '-')
  413. i++;
  414. if (!in_range(str[i], '0', '9'))
  415. return new Json(fail("at least one digit required in exponent"));
  416. while (in_range(str[i], '0', '9'))
  417. i++;
  418. }
  419. string fstr = str.Substring(start_pos, i - start_pos);
  420. return new Json(float.Parse(fstr));
  421. }
  422. public Json expect(string expected, Json res)
  423. {
  424. i--;
  425. if (str.Substring(i, expected.Length).CompareTo(expected) == 0)
  426. {
  427. i += expected.Length;
  428. return res;
  429. }
  430. else
  431. {
  432. return new Json(fail("parse error: expected " + expected + ", got " + str.Substring(i, expected.Length)));
  433. }
  434. }
  435. public Json parse_json(int depth)
  436. {
  437. if (depth > MAX_DEPTH)
  438. {
  439. return new Json(fail("exceeded maximum nesting depth"));
  440. }
  441. char ch = get_next_token();
  442. if (failed)
  443. return new Json();
  444. if (ch == '-' || (ch >= '0' && ch <= '9'))
  445. {
  446. i--;
  447. return parse_number();
  448. }
  449. if (ch == 't')
  450. return expect("true", new Json(true));
  451. if (ch == 'f')
  452. return expect("false", new Json(false));
  453. if (ch == 'n')
  454. return expect("null", new Json());
  455. if (ch == '"')
  456. return new Json(parse_string());
  457. if (ch == '{')
  458. {
  459. Dictionary<string, Json> data = new Dictionary<string, Json>();
  460. ch = get_next_token();
  461. if (ch == '}')
  462. return new Json(data);
  463. while (true)
  464. {
  465. if (ch != '"')
  466. return new Json(fail("expected '\"' in object, got " + esc(ch)));
  467. string key = parse_string();
  468. if (failed)
  469. return new Json();
  470. ch = get_next_token();
  471. if (ch != ':')
  472. return new Json(fail("expected ':' in object, got " + esc(ch)));
  473. data[key] = parse_json(depth + 1);
  474. if (failed)
  475. return new Json();
  476. ch = get_next_token();
  477. if (ch == '}')
  478. break;
  479. if (ch != ',')
  480. return new Json(fail("expected ',' in object, got " + esc(ch)));
  481. ch = get_next_token();
  482. }
  483. return new Json(data);
  484. }
  485. if (ch == '[')
  486. {
  487. List<Json> data = new List<Json>();
  488. ch = get_next_token();
  489. if (ch == ']')
  490. return new Json(data);
  491. while (true)
  492. {
  493. i--;
  494. data.Add(parse_json(depth + 1));
  495. if (failed)
  496. return new Json();
  497. ch = get_next_token();
  498. if (ch == ']')
  499. break;
  500. if (ch != ',')
  501. return new Json(fail("expected ',' in list, got " + esc(ch)));
  502. get_next_token();
  503. }
  504. return new Json(data);
  505. }
  506. return new Json(fail("expected value, got " + esc(ch)));
  507. }
  508. };
  509. }
  510. }