json.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /*
  2. * Copyright (c) 2012-2016 Daniele Bartolini and individual contributors.
  3. * License: https://github.com/taylor001/crown/blob/master/LICENSE
  4. */
  5. #include "dynamic_string.h"
  6. #include "json.h"
  7. #include "map.h"
  8. #include "string_utils.h"
  9. #include "temp_allocator.h"
  10. namespace crown
  11. {
  12. namespace json
  13. {
  14. static const char* next(const char* json, const char c = 0)
  15. {
  16. CE_ASSERT_NOT_NULL(json);
  17. if (c && c != *json)
  18. {
  19. CE_ASSERT(false, "Expected '%c' got '%c'", c, *json);
  20. }
  21. return ++json;
  22. }
  23. static const char* skip_string(const char* json)
  24. {
  25. CE_ASSERT_NOT_NULL(json);
  26. bool escaped = false;
  27. while (*++json)
  28. {
  29. if (*json == '"' && !escaped)
  30. {
  31. ++json;
  32. return json;
  33. }
  34. else if (*json == '\\') escaped = true;
  35. else escaped = false;
  36. }
  37. return json;
  38. }
  39. static const char* skip_value(const char* json)
  40. {
  41. CE_ASSERT_NOT_NULL(json);
  42. switch (*json)
  43. {
  44. case '"': json = skip_string(json); break;
  45. case '[': json = skip_block(json, '[', ']'); break;
  46. case '{': json = skip_block(json, '{', '}'); break;
  47. default: for (; *json != ',' && *json != '}' && *json != ']'; ++json) ; break;
  48. }
  49. return json;
  50. }
  51. JsonValueType::Enum type(const char* json)
  52. {
  53. CE_ASSERT_NOT_NULL(json);
  54. switch (*json)
  55. {
  56. case '"': return JsonValueType::STRING;
  57. case '{': return JsonValueType::OBJECT;
  58. case '[': return JsonValueType::ARRAY;
  59. case '-': return JsonValueType::NUMBER;
  60. default: return (isdigit(*json)) ? JsonValueType::NUMBER : (*json == 'n' ? JsonValueType::NIL : JsonValueType::BOOL);
  61. }
  62. }
  63. static f64 parse_number(const char* json)
  64. {
  65. CE_ASSERT_NOT_NULL(json);
  66. TempAllocator512 alloc;
  67. Array<char> number(alloc);
  68. if (*json == '-')
  69. {
  70. array::push_back(number, '-');
  71. ++json;
  72. }
  73. while (isdigit(*json))
  74. {
  75. array::push_back(number, *json);
  76. ++json;
  77. }
  78. if (*json == '.')
  79. {
  80. array::push_back(number, '.');
  81. while (*++json && isdigit(*json))
  82. {
  83. array::push_back(number, *json);
  84. }
  85. }
  86. if (*json == 'e' || *json == 'E')
  87. {
  88. array::push_back(number, *json);
  89. ++json;
  90. if (*json == '-' || *json == '+')
  91. {
  92. array::push_back(number, *json);
  93. ++json;
  94. }
  95. while (isdigit(*json))
  96. {
  97. array::push_back(number, *json);
  98. ++json;
  99. }
  100. }
  101. array::push_back(number, '\0');
  102. f64 val;
  103. int ok = sscanf(array::begin(number), "%lf", &val);
  104. CE_ASSERT(ok == 1, "Failed to parse f64: %s", array::begin(number));
  105. CE_UNUSED(ok);
  106. return val;
  107. }
  108. s32 parse_int(const char* json)
  109. {
  110. return (s32)parse_number(json);
  111. }
  112. f32 parse_float(const char* json)
  113. {
  114. return (f32)parse_number(json);
  115. }
  116. bool parse_bool(const char* json)
  117. {
  118. CE_ASSERT_NOT_NULL(json);
  119. switch (*json)
  120. {
  121. case 't':
  122. json = next(json, 't');
  123. json = next(json, 'r');
  124. json = next(json, 'u');
  125. json = next(json, 'e');
  126. return true;
  127. case 'f':
  128. json = next(json, 'f');
  129. json = next(json, 'a');
  130. json = next(json, 'l');
  131. json = next(json, 's');
  132. json = next(json, 'e');
  133. return false;
  134. default:
  135. CE_FATAL("Bad boolean");
  136. return false;
  137. }
  138. }
  139. void parse_string(const char* json, DynamicString& string)
  140. {
  141. CE_ASSERT_NOT_NULL(json);
  142. if (*json == '"')
  143. {
  144. while (*++json)
  145. {
  146. // Empty string
  147. if (*json == '"')
  148. {
  149. ++json;
  150. return;
  151. }
  152. else if (*json == '\\')
  153. {
  154. ++json;
  155. switch (*json)
  156. {
  157. case '"': string += '"'; break;
  158. case '\\': string += '\\'; break;
  159. case '/': string += '/'; break;
  160. case 'b': string += '\b'; break;
  161. case 'f': string += '\f'; break;
  162. case 'n': string += '\n'; break;
  163. case 'r': string += '\r'; break;
  164. case 't': string += '\t'; break;
  165. default:
  166. {
  167. CE_FATAL("Bad escape character");
  168. break;
  169. }
  170. }
  171. }
  172. else
  173. {
  174. string += *json;
  175. }
  176. }
  177. }
  178. CE_FATAL("Bad string");
  179. }
  180. void parse_array(const char* json, JsonArray& array)
  181. {
  182. CE_ASSERT_NOT_NULL(json);
  183. if (*json == '[')
  184. {
  185. json = skip_spaces(++json);
  186. if (*json == ']')
  187. return;
  188. while (*json)
  189. {
  190. array::push_back(array, json);
  191. json = skip_value(json);
  192. json = skip_spaces(json);
  193. if (*json == ']')
  194. return;
  195. json = next(json, ',');
  196. json = skip_spaces(json);
  197. }
  198. }
  199. CE_FATAL("Bad array");
  200. }
  201. void parse_object(const char* json, JsonObject& object)
  202. {
  203. CE_ASSERT_NOT_NULL(json);
  204. if (*json == '{')
  205. {
  206. json = skip_spaces(++json);
  207. if (*json == '}')
  208. return;
  209. while (*json)
  210. {
  211. const char* key_begin = *json == '"' ? (json + 1) : json;
  212. TempAllocator256 ta;
  213. DynamicString key(ta);
  214. parse_string(json, key);
  215. FixedString fs_key(key_begin, key.length());
  216. json = skip_string(json);
  217. json = skip_spaces(json);
  218. json = next(json, ':');
  219. json = skip_spaces(json);
  220. map::set(object._map, fs_key, json);
  221. json = skip_value(json);
  222. json = skip_spaces(json);
  223. if (*json == '}')
  224. return;
  225. json = next(json, ',');
  226. json = skip_spaces(json);
  227. }
  228. }
  229. CE_FATAL("Bad object");
  230. }
  231. void parse(const char* json, JsonObject& object)
  232. {
  233. CE_ASSERT_NOT_NULL(json);
  234. parse_object(json, object);
  235. }
  236. void parse(Buffer& json, JsonObject& object)
  237. {
  238. array::push_back(json, '\0');
  239. array::pop_back(json);
  240. parse(array::begin(json), object);
  241. }
  242. } // namespace json
  243. } // namespace crown