json.cpp 5.1 KB

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