iron_json.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. #include "iron_json.h"
  2. #include "iron_string.h"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdbool.h>
  6. #include <jsmn.h>
  7. void *gc_alloc(size_t size);
  8. static const int PTR_SIZE = 8;
  9. static char *source;
  10. static jsmntok_t *tokens;
  11. static int num_tokens;
  12. static uint32_t ti; // token index
  13. static uint8_t *decoded;
  14. static uint32_t wi; // write index
  15. static uint32_t bottom;
  16. static uint32_t array_count;
  17. static inline uint64_t pad(uint32_t di, int n) {
  18. return (n - (di % n)) % n;
  19. }
  20. static void store_u8(uint8_t u8) {
  21. *(uint8_t *)(decoded + wi) = u8;
  22. wi += 1;
  23. }
  24. static void store_i32(int32_t i32) {
  25. // TODO: signed overflow is UB
  26. // if (i32 > INT32_MAX)
  27. // i32 = (int32_t)(i32 - INT32_MAX - 1) - INT32_MAX - 1;
  28. wi += pad(wi, 4);
  29. *(int32_t *)(decoded + wi) = i32;
  30. wi += 4;
  31. }
  32. static void store_u32(uint32_t u32) {
  33. wi += pad(wi, 4);
  34. *(uint32_t *)(decoded + wi) = u32;
  35. wi += 4;
  36. }
  37. static void store_f32(float f32) {
  38. wi += pad(wi, 4);
  39. *(float *)(decoded + wi) = f32;
  40. wi += 4;
  41. }
  42. static void store_ptr(uint32_t ptr) {
  43. wi += pad(wi, PTR_SIZE);
  44. *(uint64_t *)(decoded + wi) = (uint64_t)decoded + (uint64_t)ptr;
  45. wi += PTR_SIZE;
  46. }
  47. static void store_ptr_abs(void *ptr) {
  48. wi += pad(wi, PTR_SIZE);
  49. *(uint64_t *)(decoded + wi) = (uint64_t)ptr;
  50. wi += PTR_SIZE;
  51. }
  52. static void store_string_bytes(char *str, uint32_t len) {
  53. for (uint32_t i = 0; i < len; ++i) {
  54. store_u8(str[i]);
  55. }
  56. store_u8('\0');
  57. }
  58. static bool is_key(char *s, jsmntok_t *t) {
  59. return t->type == JSMN_STRING && s[t->end + 1] == ':';
  60. }
  61. static jsmntok_t get_token() {
  62. jsmntok_t t = tokens[ti];
  63. while (is_key(source, &t)) {
  64. ti++;
  65. t = tokens[ti];
  66. }
  67. return t;
  68. }
  69. static int traverse(uint32_t wi) {
  70. jsmntok_t t = get_token();
  71. if (t.type == JSMN_OBJECT) {
  72. ti++;
  73. uint32_t size = 0;
  74. for (uint32_t i = 0; i < t.size; ++i) {
  75. size += traverse(wi + size);
  76. }
  77. return pad(wi, PTR_SIZE) + size;
  78. }
  79. else if (t.type == JSMN_PRIMITIVE) {
  80. ti++;
  81. if (source[t.start] == 't' || source[t.start] == 'f') { // bool
  82. return 1;
  83. }
  84. else if (source[t.start] == 'n') { // null
  85. return pad(wi, PTR_SIZE) + PTR_SIZE;
  86. }
  87. else { // number
  88. return pad(wi, 4) + 4;
  89. }
  90. }
  91. else if (t.type == JSMN_ARRAY) {
  92. ti++;
  93. for (uint32_t i = 0; i < t.size; ++i) {
  94. traverse(0);
  95. }
  96. return pad(wi, PTR_SIZE) + PTR_SIZE;
  97. }
  98. else if (t.type == JSMN_STRING) {
  99. ti++;
  100. return pad(wi, PTR_SIZE) + PTR_SIZE;
  101. }
  102. return 0;
  103. }
  104. static int token_size() {
  105. uint32_t _ti = ti;
  106. uint32_t len = traverse(0);
  107. ti = _ti;
  108. return len;
  109. }
  110. static bool has_dot(char *str, uint32_t len) {
  111. for (uint32_t i = 0; i < len; ++i) {
  112. if (str[i] == '.') {
  113. return true;
  114. }
  115. }
  116. return false;
  117. }
  118. static void token_write() {
  119. jsmntok_t t = get_token();
  120. if (t.type == JSMN_OBJECT) {
  121. // TODO: Object containing another object
  122. // Write object contents
  123. uint32_t size = token_size();
  124. size += pad(size, PTR_SIZE);
  125. bottom += size * array_count;
  126. ti++;
  127. for (uint32_t i = 0; i < t.size; ++i) {
  128. token_write();
  129. }
  130. }
  131. else if (t.type == JSMN_PRIMITIVE) {
  132. ti++;
  133. if (source[t.start] == 't' || source[t.start] == 'f') { // bool
  134. store_u8(source[t.start] == 't' ? 1 : 0);
  135. }
  136. else if (source[t.start] == 'n') { // null
  137. store_ptr_abs(NULL);
  138. }
  139. else {
  140. has_dot(source + t.start, t.end - t.start) ?
  141. store_f32(strtof(source + t.start, NULL)) :
  142. #ifdef _WIN32
  143. store_i32(_strtoi64(source + t.start, NULL, 10));
  144. #else
  145. store_i32(strtol(source + t.start, NULL, 10));
  146. #endif
  147. }
  148. }
  149. else if (t.type == JSMN_ARRAY) {
  150. ti++;
  151. store_ptr(bottom);
  152. uint32_t _wi = wi;
  153. wi = bottom;
  154. store_ptr(bottom + PTR_SIZE + 4 + 4); // Pointer to buffer contents
  155. store_u32(t.size); // Element count
  156. store_u32(0); // Capacity = 0 -> do not free on first realloc
  157. bottom = wi;
  158. if (t.size == 0) {
  159. wi = _wi;
  160. return;
  161. }
  162. uint32_t count = t.size;
  163. array_count = count;
  164. t = get_token();
  165. if (t.type == JSMN_OBJECT) {
  166. // Struct pointers
  167. uint32_t size = token_size();
  168. size += pad(size, PTR_SIZE);
  169. for (uint32_t i = 0; i < count; ++i) {
  170. store_ptr(bottom + count * PTR_SIZE + i * size);
  171. }
  172. // Struct contents
  173. bottom = pad(wi, PTR_SIZE) + wi;
  174. for (uint32_t i = 0; i < count; ++i) {
  175. wi = pad(wi, PTR_SIZE) + wi;
  176. token_write();
  177. }
  178. }
  179. else if (t.type == JSMN_STRING) {
  180. // String pointers
  181. uint32_t _ti = ti;
  182. uint32_t strings_length = 0;
  183. for (uint32_t i = 0; i < count; ++i) {
  184. store_ptr(bottom + count * PTR_SIZE + strings_length);
  185. uint32_t length = t.end - t.start; // String length
  186. strings_length += length;
  187. strings_length += 1; // '\0'
  188. ti++;
  189. t = get_token();
  190. }
  191. ti = _ti;
  192. t = get_token();
  193. // String bytes
  194. for (uint32_t i = 0; i < count; ++i) {
  195. store_string_bytes(source + t.start, t.end - t.start);
  196. ti++;
  197. t = get_token();
  198. }
  199. bottom = pad(wi, PTR_SIZE) + wi;
  200. }
  201. else {
  202. // Array contents
  203. for (uint32_t i = 0; i < count; ++i) {
  204. token_write();
  205. }
  206. bottom = pad(wi, PTR_SIZE) + wi;
  207. }
  208. wi = _wi;
  209. array_count = 1;
  210. }
  211. else if (t.type == JSMN_STRING) {
  212. ti++;
  213. store_ptr(bottom);
  214. uint32_t _wi = wi;
  215. wi = bottom;
  216. store_string_bytes(source + t.start, t.end - t.start);
  217. bottom = pad(wi, PTR_SIZE) + wi;
  218. wi = _wi;
  219. }
  220. }
  221. static void load_tokens(char *s) {
  222. jsmn_parser parser;
  223. jsmn_init(&parser);
  224. num_tokens = jsmn_parse(&parser, s, strlen(s), NULL, 0);
  225. tokens = malloc(sizeof(jsmntok_t) * num_tokens);
  226. jsmn_init(&parser);
  227. jsmn_parse(&parser, s, strlen(s), tokens, num_tokens);
  228. source = s;
  229. ti = 0;
  230. }
  231. void *json_parse(char *s) {
  232. load_tokens(s);
  233. uint32_t out_size = strlen(s) * 2;
  234. decoded = gc_alloc(out_size);
  235. wi = 0;
  236. bottom = 0;
  237. array_count = 1;
  238. token_write();
  239. free(tokens);
  240. return decoded;
  241. }
  242. static void token_write_to_map(any_map_t *m) {
  243. jsmntok_t t = get_token();
  244. if (t.type == JSMN_OBJECT) {
  245. // TODO: Object containing another object
  246. ti++;
  247. for (uint32_t i = 0; i < t.size; ++i) {
  248. token_write_to_map(m);
  249. }
  250. }
  251. else if (t.type == JSMN_PRIMITIVE) {
  252. jsmntok_t tkey = tokens[ti - 1];
  253. ti++;
  254. any_map_set(m, substring(source, tkey.start, tkey.end), substring(source, t.start, t.end));
  255. }
  256. else if (t.type == JSMN_ARRAY) {
  257. ti++;
  258. }
  259. else if (t.type == JSMN_STRING) {
  260. jsmntok_t tkey = tokens[ti - 1];
  261. ti++;
  262. any_map_set(m, substring(source, tkey.start, tkey.end), substring(source, t.start, t.end));
  263. }
  264. }
  265. any_map_t *json_parse_to_map(char *s) {
  266. load_tokens(s);
  267. any_map_t *m = any_map_create();
  268. token_write_to_map(m);
  269. free(tokens);
  270. return m;
  271. }
  272. static char *encoded;
  273. static int keys;
  274. void json_encode_begin() {
  275. encoded = "{";
  276. keys = 0;
  277. }
  278. char *json_encode_end() {
  279. encoded = string_join(encoded, "}");
  280. return encoded;
  281. }
  282. void json_encode_key(char *k) {
  283. if (keys > 0) {
  284. encoded = string_join(encoded, ",");
  285. }
  286. encoded = string_join(encoded, "\"");
  287. encoded = string_join(encoded, k);
  288. encoded = string_join(encoded, "\":");
  289. keys++;
  290. }
  291. void json_encode_string_value(char *v) {
  292. encoded = string_join(encoded, "\"");
  293. encoded = string_join(encoded, v);
  294. encoded = string_join(encoded, "\"");
  295. }
  296. void json_encode_string(char *k, char *v) {
  297. json_encode_key(k);
  298. json_encode_string_value(v);
  299. }
  300. void json_encode_string_array(char *k, char_ptr_array_t *a) {
  301. json_encode_begin_array(k);
  302. for (uint32_t i = 0; i < a->length; ++i) {
  303. if (i > 0) {
  304. encoded = string_join(encoded, ",");
  305. }
  306. json_encode_string_value(a->buffer[i]);
  307. }
  308. json_encode_end_array();
  309. }
  310. void json_encode_f32(char *k, float f) {
  311. json_encode_key(k);
  312. encoded = string_join(encoded, f32_to_string_with_zeros(f));
  313. }
  314. void json_encode_i32(char *k, int i) {
  315. json_encode_key(k);
  316. encoded = string_join(encoded, i32_to_string(i));
  317. }
  318. void json_encode_null(char *k) {
  319. json_encode_key(k);
  320. encoded = string_join(encoded, "null");
  321. }
  322. void json_encode_f32_array(char *k, f32_array_t *a) {
  323. json_encode_begin_array(k);
  324. for (uint32_t i = 0; i < a->length; ++i) {
  325. if (i > 0) {
  326. encoded = string_join(encoded, ",");
  327. }
  328. encoded = string_join(encoded, f32_to_string(a->buffer[i]));
  329. }
  330. json_encode_end_array();
  331. }
  332. void json_encode_i32_array(char *k, i32_array_t *a) {
  333. json_encode_begin_array(k);
  334. for (uint32_t i = 0; i < a->length; ++i) {
  335. if (i > 0) {
  336. encoded = string_join(encoded, ",");
  337. }
  338. encoded = string_join(encoded, i32_to_string(a->buffer[i]));
  339. }
  340. json_encode_end_array();
  341. }
  342. void json_encode_bool(char *k, bool b) {
  343. json_encode_key(k);
  344. encoded = string_join(encoded, b ? "true" : "false");
  345. }
  346. void json_encode_begin_array(char *k) {
  347. json_encode_key(k);
  348. encoded = string_join(encoded, "[");
  349. }
  350. void json_encode_end_array() {
  351. encoded = string_join(encoded, "]");
  352. }
  353. void json_encode_begin_object() {
  354. keys = 0;
  355. encoded = string_join(encoded, "{");
  356. }
  357. void json_encode_end_object() {
  358. encoded = string_join(encoded, "}");
  359. }
  360. void json_encode_map(any_map_t *m) {
  361. any_array_t *keys = map_keys(m);
  362. for (uint32_t i = 0; i < keys->length; i++) {
  363. json_encode_string(keys->buffer[i], any_map_get(m, keys->buffer[i]));
  364. }
  365. }