json.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. // Copyright (C) 2004-2025 Artifex Software, Inc.
  2. //
  3. // This file is part of MuPDF.
  4. //
  5. // MuPDF is free software: you can redistribute it and/or modify it under the
  6. // terms of the GNU Affero General Public License as published by the Free
  7. // Software Foundation, either version 3 of the License, or (at your option)
  8. // any later version.
  9. //
  10. // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
  11. // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  12. // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. // details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
  17. //
  18. // Alternative licensing terms are available from the licensor.
  19. // For commercial licensing, see <https://www.artifex.com/> or contact
  20. // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
  21. // CA 94129, USA, for further information.
  22. #include "mupdf/fitz.h"
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <limits.h>
  26. /* JSON parse */
  27. struct json_parser {
  28. fz_context *ctx;
  29. fz_pool *pool;
  30. const char *s;
  31. };
  32. static fz_json *json_parse_element(struct json_parser *pp);
  33. static void json_error(struct json_parser *pp, const char *error)
  34. {
  35. fz_throw(pp->ctx, FZ_ERROR_SYNTAX, "%s in JSON", error);
  36. }
  37. static fz_json *json_new_value(fz_context *ctx, fz_pool *pool, int type)
  38. {
  39. fz_json *val = fz_pool_alloc(ctx, pool, sizeof(fz_json));
  40. val->type = type;
  41. return val;
  42. }
  43. static fz_json_array *json_new_array(fz_context *ctx, fz_pool *pool, fz_json *value)
  44. {
  45. fz_json_array *array = fz_pool_alloc(ctx, pool, sizeof(fz_json_array));
  46. array->value = value;
  47. array->next = NULL;
  48. return array;
  49. }
  50. static fz_json_object *json_new_object(fz_context *ctx, fz_pool *pool, const char *key, fz_json *value)
  51. {
  52. fz_json_object *object = fz_pool_alloc(ctx, pool, sizeof(fz_json_object));
  53. object->key = key;
  54. object->value = value;
  55. object->next = NULL;
  56. return object;
  57. }
  58. static int json_accept(struct json_parser *pp, int c)
  59. {
  60. if (*pp->s == c)
  61. {
  62. pp->s++;
  63. return 1;
  64. }
  65. return 0;
  66. }
  67. static int json_accept_range(struct json_parser *pp, int a, int b)
  68. {
  69. if (*pp->s >= a && *pp->s <= b)
  70. {
  71. pp->s++;
  72. return 1;
  73. }
  74. return 0;
  75. }
  76. static void json_expect_range(struct json_parser *pp, int a, int b)
  77. {
  78. if (!json_accept_range(pp, a, b))
  79. fz_throw(pp->ctx, FZ_ERROR_SYNTAX, "expected '%c'-'%c' in JSON", a, b);
  80. }
  81. static void json_expect(struct json_parser *pp, int c)
  82. {
  83. if (!json_accept(pp, c))
  84. fz_throw(pp->ctx, FZ_ERROR_SYNTAX, "expected '%c' in JSON", c);
  85. }
  86. static void json_parse_ws(struct json_parser *pp)
  87. {
  88. int c = *pp->s;
  89. while (c == 0x0a || c == 0x0d || c == 0x09 || c == 0x20)
  90. c = *(++pp->s);
  91. }
  92. static int unhex(int c)
  93. {
  94. if (c >= '0' && c <= '9') return c - '0';
  95. if (c >= 'a' && c <= 'f') return c - 'a' + 0xA;
  96. if (c >= 'A' && c <= 'F') return c - 'A' + 0xA;
  97. return 0;
  98. }
  99. static int json_expect_hex(struct json_parser *pp)
  100. {
  101. int c = *pp->s++;
  102. if (c >= '0' && c <= '9') return c - '0';
  103. if (c >= 'a' && c <= 'f') return c - 'a' + 0xA;
  104. if (c >= 'A' && c <= 'F') return c - 'A' + 0xA;
  105. json_error(pp, "invalid unicode escape sequence");
  106. return 0;
  107. }
  108. static const char *
  109. json_unescape_string(struct json_parser *pp, const char *s, const char *end, int n)
  110. {
  111. char *str, *p;
  112. int x;
  113. str = p = fz_pool_alloc(pp->ctx, pp->pool, n + 1);
  114. while (s < end)
  115. {
  116. if (*s == '\\')
  117. {
  118. s++;
  119. switch (*s++)
  120. {
  121. case 'u':
  122. x = unhex(*s++) << 12;
  123. x |= unhex(*s++) << 8;
  124. x |= unhex(*s++) << 4;
  125. x |= unhex(*s++);
  126. p += fz_runetochar(p, x);
  127. break;
  128. case '\\': *p++ = '\\'; break;
  129. case '/': *p++ = '/'; break;
  130. case 'b': *p++ = '\b'; break;
  131. case 'f': *p++ = '\f'; break;
  132. case 'n': *p++ = '\n'; break;
  133. case 'r': *p++ = '\r'; break;
  134. case 't': *p++ = '\t'; break;
  135. }
  136. }
  137. else
  138. {
  139. *p++ = *s++;
  140. }
  141. }
  142. *p = 0;
  143. return str;
  144. }
  145. static const char *
  146. json_parse_string(struct json_parser *pp)
  147. {
  148. const char *mark;
  149. int n, c, x;
  150. json_expect(pp, '"');
  151. mark = pp->s;
  152. n = 0;
  153. for (;;)
  154. {
  155. c = (unsigned char) *pp->s++;
  156. if (c < 0x20)
  157. json_error(pp, "bad control character in string literal");
  158. if (c == '"')
  159. break;
  160. if (c == '\\')
  161. {
  162. c = *pp->s++;
  163. if (c == 'u')
  164. {
  165. x = json_expect_hex(pp) << 12;
  166. x |= json_expect_hex(pp) << 8;
  167. x |= json_expect_hex(pp) << 4;
  168. x |= json_expect_hex(pp);
  169. n += fz_runelen(x);
  170. }
  171. else if (c == '"' || c == '\\' || c == '/' || c == 'b' || c == 'f' || c == 'n' || c == 'r' || c == 't')
  172. n += 1;
  173. else
  174. json_error(pp, "bad escaped character");
  175. }
  176. else
  177. {
  178. n += 1;
  179. }
  180. }
  181. return json_unescape_string(pp, mark, pp->s - 1, n);
  182. }
  183. static fz_json *
  184. json_parse_number(struct json_parser *pp)
  185. {
  186. fz_json *val;
  187. const char *mark = pp->s;
  188. json_accept(pp, '-');
  189. if (json_accept(pp, '0'))
  190. {
  191. }
  192. else
  193. {
  194. json_expect_range(pp, '1', '9');
  195. while (json_accept_range(pp, '0', '9'))
  196. ;
  197. }
  198. // fraction
  199. if (json_accept(pp, '.'))
  200. {
  201. json_expect_range(pp, '0', '9');
  202. while (json_accept_range(pp, '0', '9'))
  203. ;
  204. }
  205. // exponent
  206. if (json_accept(pp, 'e') || json_accept(pp, 'E'))
  207. {
  208. if (json_accept(pp, '-') || json_accept(pp, '+'))
  209. ;
  210. json_expect_range(pp, '0', '9');
  211. while (json_accept_range(pp, '0', '9'))
  212. ;
  213. }
  214. val = json_new_value(pp->ctx, pp->pool, FZ_JSON_NUMBER);
  215. val->u.number = fz_atof(mark);
  216. return val;
  217. }
  218. static fz_json *
  219. json_parse_object(struct json_parser *pp)
  220. {
  221. fz_json *obj;
  222. fz_json_object **tail;
  223. const char *key;
  224. fz_json *val;
  225. json_expect(pp, '{');
  226. obj = json_new_value(pp->ctx, pp->pool, FZ_JSON_OBJECT);
  227. tail = &obj->u.object;
  228. json_parse_ws(pp);
  229. if (json_accept(pp, '}'))
  230. return obj;
  231. for (;;)
  232. {
  233. json_parse_ws(pp);
  234. key = json_parse_string(pp);
  235. json_parse_ws(pp);
  236. json_expect(pp, ':');
  237. val = json_parse_element(pp);
  238. *tail = json_new_object(pp->ctx, pp->pool, key, val);
  239. tail = &(*tail)->next;
  240. if (json_accept(pp, '}'))
  241. break;
  242. json_expect(pp, ',');
  243. }
  244. return obj;
  245. }
  246. static fz_json *
  247. json_parse_array(struct json_parser *pp)
  248. {
  249. fz_json *arr;
  250. fz_json_array **tail;
  251. fz_json *val;
  252. json_expect(pp, '[');
  253. arr = json_new_value(pp->ctx, pp->pool, FZ_JSON_ARRAY);
  254. tail = &arr->u.array;
  255. json_parse_ws(pp);
  256. if (json_accept(pp, ']'))
  257. return arr;
  258. for (;;)
  259. {
  260. val = json_parse_element(pp);
  261. *tail = json_new_array(pp->ctx, pp->pool, val);
  262. tail = &(*tail)->next;
  263. if (json_accept(pp, ']'))
  264. break;
  265. json_expect(pp, ',');
  266. }
  267. return arr;
  268. }
  269. static fz_json *
  270. json_parse_value(struct json_parser *pp)
  271. {
  272. fz_json *val;
  273. int lookahead = *pp->s;
  274. if (lookahead == '{')
  275. return json_parse_object(pp);
  276. if (lookahead == '[')
  277. return json_parse_array(pp);
  278. if (lookahead == '"')
  279. {
  280. val = json_new_value(pp->ctx, pp->pool, FZ_JSON_STRING);
  281. val->u.string = json_parse_string(pp);
  282. return val;
  283. }
  284. if (lookahead == '-' || (lookahead >= '0' && lookahead <= '9'))
  285. return json_parse_number(pp);
  286. if (json_accept(pp, 'n'))
  287. {
  288. json_expect(pp, 'u');
  289. json_expect(pp, 'l');
  290. json_expect(pp, 'l');
  291. return json_new_value(pp->ctx, pp->pool, FZ_JSON_NULL);
  292. }
  293. if (json_accept(pp, 't'))
  294. {
  295. json_expect(pp, 'r');
  296. json_expect(pp, 'u');
  297. json_expect(pp, 'e');
  298. return json_new_value(pp->ctx, pp->pool, FZ_JSON_TRUE);
  299. }
  300. if (json_accept(pp, 'f'))
  301. {
  302. json_expect(pp, 'a');
  303. json_expect(pp, 'l');
  304. json_expect(pp, 's');
  305. json_expect(pp, 'e');
  306. return json_new_value(pp->ctx, pp->pool, FZ_JSON_FALSE);
  307. }
  308. json_error(pp, "unexpected token");
  309. return NULL;
  310. }
  311. static fz_json *
  312. json_parse_element(struct json_parser *pp)
  313. {
  314. fz_json *result;
  315. json_parse_ws(pp);
  316. result = json_parse_value(pp);
  317. json_parse_ws(pp);
  318. return result;
  319. }
  320. fz_json *
  321. fz_parse_json(fz_context *ctx, fz_pool *pool, const char *s)
  322. {
  323. struct json_parser p = { ctx, pool, s };
  324. fz_json *result = json_parse_element(&p);
  325. json_expect(&p, 0);
  326. return result;
  327. }
  328. /* JSON stringify */
  329. static void
  330. append_json_string(fz_context *ctx, fz_buffer *out, const char *s)
  331. {
  332. int c;
  333. fz_append_byte(ctx, out, '"');
  334. while (*s)
  335. {
  336. s += fz_chartorune(&c, s);
  337. if (c < 20 || c == '"' || c == '\\' || c >= 127)
  338. {
  339. fz_append_byte(ctx, out, '\\');
  340. switch (c)
  341. {
  342. case '"': fz_append_byte(ctx, out, '"'); break;
  343. case '\\': fz_append_byte(ctx, out, '\\'); break;
  344. case '\n': fz_append_byte(ctx, out, 'n'); break;
  345. case '\r': fz_append_byte(ctx, out, 'r'); break;
  346. case '\t': fz_append_byte(ctx, out, 't'); break;
  347. default: fz_append_printf(ctx, out, "u%04x", c); break;
  348. }
  349. }
  350. else
  351. {
  352. fz_append_byte(ctx, out, c);
  353. }
  354. }
  355. fz_append_byte(ctx, out, '"');
  356. }
  357. static void
  358. write_json_string(fz_context *ctx, fz_output *out, const char *s)
  359. {
  360. int c;
  361. fz_write_byte(ctx, out, '"');
  362. while (*s)
  363. {
  364. s += fz_chartorune(&c, s);
  365. if (c < 20 || c == '"' || c == '\\' || c >= 127)
  366. {
  367. fz_write_byte(ctx, out, '\\');
  368. switch (c)
  369. {
  370. case '"': fz_write_byte(ctx, out, '"'); break;
  371. case '\\': fz_write_byte(ctx, out, '\\'); break;
  372. case '\n': fz_write_byte(ctx, out, 'n'); break;
  373. case '\r': fz_write_byte(ctx, out, 'r'); break;
  374. case '\t': fz_write_byte(ctx, out, 't'); break;
  375. default: fz_write_printf(ctx, out, "u%04x", c); break;
  376. }
  377. }
  378. else
  379. {
  380. fz_write_byte(ctx, out, c);
  381. }
  382. }
  383. fz_write_byte(ctx, out, '"');
  384. }
  385. static const char *format_json_integer(char *out, int v)
  386. {
  387. char buf[32], *s = out;
  388. unsigned int a;
  389. int i = 0;
  390. if (v < 0) {
  391. a = -v;
  392. *s++ = '-';
  393. } else {
  394. a = v;
  395. }
  396. while (a) {
  397. buf[i++] = (a % 10) + '0';
  398. a /= 10;
  399. }
  400. if (i == 0)
  401. buf[i++] = '0';
  402. while (i > 0)
  403. *s++ = buf[--i];
  404. *s = 0;
  405. return out;
  406. }
  407. static const char *format_json_exponent(char *p, int e)
  408. {
  409. *p++ = 'e';
  410. if (e < 0)
  411. {
  412. *p++ = '-';
  413. return format_json_integer(p, -e);
  414. }
  415. else
  416. {
  417. *p++ = '+';
  418. return format_json_integer(p, e);
  419. }
  420. }
  421. static const char *format_json_number(char buf[32], double f)
  422. {
  423. char digits[32], *p = buf, *s = digits;
  424. int exp, ndigits, point;
  425. if (f == 0) return "0";
  426. if (isnan(f)) return "null";
  427. if (isinf(f)) return "null";
  428. /* Fast case for integers. This only works assuming all integers can be
  429. * exactly represented by a float. This is true for 32-bit integers and
  430. * 64-bit floats. */
  431. if (f >= INT_MIN && f <= INT_MAX) {
  432. int i = (int)f;
  433. if ((double)i == f)
  434. return format_json_integer(buf, i);
  435. }
  436. // TODO: use double precision grisu algorithm!
  437. ndigits = fz_grisu(f, digits, &exp);
  438. point = ndigits + exp;
  439. if (signbit(f))
  440. *p++ = '-';
  441. if (point < -5 || point > 21) {
  442. *p++ = *s++;
  443. if (ndigits > 1) {
  444. int n = ndigits - 1;
  445. *p++ = '.';
  446. while (n--)
  447. *p++ = *s++;
  448. }
  449. format_json_exponent(p, point - 1);
  450. }
  451. else if (point <= 0) {
  452. *p++ = '0';
  453. *p++ = '.';
  454. while (point++ < 0)
  455. *p++ = '0';
  456. while (ndigits-- > 0)
  457. *p++ = *s++;
  458. *p = 0;
  459. }
  460. else {
  461. while (ndigits-- > 0) {
  462. *p++ = *s++;
  463. if (--point == 0 && ndigits > 0)
  464. *p++ = '.';
  465. }
  466. while (point-- > 0)
  467. *p++ = '0';
  468. *p = 0;
  469. }
  470. return buf;
  471. }
  472. void
  473. fz_append_json(fz_context *ctx, fz_buffer *out, fz_json *value)
  474. {
  475. fz_json_array *arr;
  476. fz_json_object *obj;
  477. char buf[40];
  478. switch (value->type)
  479. {
  480. case FZ_JSON_NULL:
  481. fz_append_string(ctx, out, "null");
  482. break;
  483. case FZ_JSON_TRUE:
  484. fz_append_string(ctx, out, "true");
  485. break;
  486. case FZ_JSON_FALSE:
  487. fz_append_string(ctx, out, "false");
  488. break;
  489. case FZ_JSON_NUMBER:
  490. fz_append_string(ctx, out, format_json_number(buf, value->u.number));
  491. break;
  492. case FZ_JSON_STRING:
  493. append_json_string(ctx, out, value->u.string);
  494. break;
  495. case FZ_JSON_ARRAY:
  496. fz_append_byte(ctx, out, '[');
  497. for (arr = value->u.array; arr; arr = arr->next)
  498. {
  499. if (arr != value->u.array)
  500. fz_append_byte(ctx, out, ',');
  501. fz_append_json(ctx, out, arr->value);
  502. }
  503. fz_append_byte(ctx, out, ']');
  504. break;
  505. case FZ_JSON_OBJECT:
  506. fz_append_byte(ctx, out, '{');
  507. for (obj = value->u.object; obj; obj = obj->next)
  508. {
  509. if (obj != value->u.object)
  510. fz_append_byte(ctx, out, ',');
  511. append_json_string(ctx, out, obj->key);
  512. fz_append_byte(ctx, out, ':');
  513. fz_append_json(ctx, out, obj->value);
  514. }
  515. fz_append_byte(ctx, out, '}');
  516. break;
  517. }
  518. }
  519. void
  520. fz_write_json(fz_context *ctx, fz_output *out, fz_json *value)
  521. {
  522. fz_json_array *arr;
  523. fz_json_object *obj;
  524. char buf[40];
  525. switch (value->type)
  526. {
  527. case FZ_JSON_NULL:
  528. fz_write_string(ctx, out, "null");
  529. break;
  530. case FZ_JSON_TRUE:
  531. fz_write_string(ctx, out, "true");
  532. break;
  533. case FZ_JSON_FALSE:
  534. fz_write_string(ctx, out, "false");
  535. break;
  536. case FZ_JSON_NUMBER:
  537. fz_write_string(ctx, out, format_json_number(buf, value->u.number));
  538. break;
  539. case FZ_JSON_STRING:
  540. write_json_string(ctx, out, value->u.string);
  541. break;
  542. case FZ_JSON_ARRAY:
  543. fz_write_byte(ctx, out, '[');
  544. for (arr = value->u.array; arr; arr = arr->next)
  545. {
  546. if (arr != value->u.array)
  547. fz_write_byte(ctx, out, ',');
  548. fz_write_json(ctx, out, arr->value);
  549. }
  550. fz_write_byte(ctx, out, ']');
  551. break;
  552. case FZ_JSON_OBJECT:
  553. fz_write_byte(ctx, out, '{');
  554. for (obj = value->u.object; obj; obj = obj->next)
  555. {
  556. if (obj != value->u.object)
  557. fz_write_byte(ctx, out, ',');
  558. write_json_string(ctx, out, obj->key);
  559. fz_write_byte(ctx, out, ':');
  560. fz_write_json(ctx, out, obj->value);
  561. }
  562. fz_write_byte(ctx, out, '}');
  563. break;
  564. }
  565. }
  566. /* JSON accessors */
  567. int fz_json_is_null(fz_context *ctx, fz_json *json)
  568. {
  569. return json && json->type == FZ_JSON_NULL;
  570. }
  571. int fz_json_is_boolean(fz_context *ctx, fz_json *json)
  572. {
  573. return json && (json->type == FZ_JSON_TRUE || json->type == FZ_JSON_FALSE);
  574. }
  575. int fz_json_is_number(fz_context *ctx, fz_json *json)
  576. {
  577. return json && json->type == FZ_JSON_NUMBER;
  578. }
  579. int fz_json_is_string(fz_context *ctx, fz_json *json)
  580. {
  581. return json && json->type == FZ_JSON_STRING;
  582. }
  583. int fz_json_is_array(fz_context *ctx, fz_json *json)
  584. {
  585. return json && json->type == FZ_JSON_ARRAY;
  586. }
  587. int fz_json_is_object(fz_context *ctx, fz_json *json)
  588. {
  589. return json && json->type == FZ_JSON_OBJECT;
  590. }
  591. int fz_json_to_boolean(fz_context *ctx, fz_json *json)
  592. {
  593. return json && json->type == FZ_JSON_TRUE;
  594. }
  595. double fz_json_to_number(fz_context *ctx, fz_json *json)
  596. {
  597. if (json && json->type == FZ_JSON_NUMBER)
  598. return json->u.number;
  599. return 0;
  600. }
  601. const char *fz_json_to_string(fz_context *ctx, fz_json *json)
  602. {
  603. if (json && json->type == FZ_JSON_STRING)
  604. return json->u.string;
  605. return "";
  606. }
  607. int fz_json_array_length(fz_context *ctx, fz_json *array)
  608. {
  609. fz_json_array *entry;
  610. int n = 0;
  611. if (array->type != FZ_JSON_ARRAY)
  612. fz_throw(ctx, FZ_ERROR_ARGUMENT, "not an array");
  613. for (entry = array->u.array; entry; entry = entry->next)
  614. ++n;
  615. return n;
  616. }
  617. fz_json *fz_json_array_get(fz_context *ctx, fz_json *array, int ix)
  618. {
  619. fz_json_array *entry;
  620. int n = 0;
  621. if (array->type != FZ_JSON_ARRAY)
  622. fz_throw(ctx, FZ_ERROR_ARGUMENT, "not an array");
  623. for (entry = array->u.array; entry; entry = entry->next)
  624. {
  625. if (n == ix)
  626. return entry->value;
  627. ++n;
  628. }
  629. return NULL;
  630. }
  631. fz_json *fz_json_object_get(fz_context *ctx, fz_json *object, const char *key)
  632. {
  633. fz_json_object *entry;
  634. if (object->type != FZ_JSON_OBJECT)
  635. fz_throw(ctx, FZ_ERROR_ARGUMENT, "not an object");
  636. for (entry = object->u.object; entry; entry = entry->next)
  637. if (!strcmp(entry->key, key))
  638. return entry->value;
  639. return NULL;
  640. }
  641. /* JSON build objects */
  642. fz_json *fz_json_new_object(fz_context *ctx, fz_pool *pool)
  643. {
  644. return json_new_value(ctx, pool, FZ_JSON_OBJECT);
  645. }
  646. fz_json *fz_json_new_array(fz_context *ctx, fz_pool *pool)
  647. {
  648. return json_new_value(ctx, pool, FZ_JSON_ARRAY);
  649. }
  650. void fz_json_array_push(fz_context *ctx, fz_pool *pool, fz_json *array, fz_json *item)
  651. {
  652. fz_json_array **tail;
  653. if (array->type != FZ_JSON_ARRAY)
  654. fz_throw(ctx, FZ_ERROR_ARGUMENT, "not an array");
  655. tail = &array->u.array;
  656. while (*tail != NULL)
  657. tail = &(*tail)->next;
  658. *tail = json_new_array(ctx, pool, item);
  659. }
  660. void fz_json_object_set(fz_context *ctx, fz_pool *pool, fz_json *object, const char *key, fz_json *item)
  661. {
  662. fz_json_object **tail;
  663. if (object->type != FZ_JSON_OBJECT)
  664. fz_throw(ctx, FZ_ERROR_ARGUMENT, "not an object");
  665. tail = &object->u.object;
  666. while (*tail != NULL)
  667. {
  668. if (!strcmp((*tail)->key, key))
  669. {
  670. // replace old value!
  671. (*tail)->value = item;
  672. return;
  673. }
  674. tail = &(*tail)->next;
  675. }
  676. *tail = json_new_object(ctx, pool, fz_pool_strdup(ctx, pool, key), item);
  677. }
  678. fz_json *fz_json_new_number(fz_context *ctx, fz_pool *pool, double number)
  679. {
  680. fz_json *val = json_new_value(ctx, pool, FZ_JSON_NUMBER);
  681. val->u.number = number;
  682. return val;
  683. }
  684. fz_json *fz_json_new_string(fz_context *ctx, fz_pool *pool, const char *string)
  685. {
  686. fz_json *val = json_new_value(ctx, pool, FZ_JSON_STRING);
  687. val->u.string = fz_pool_strdup(ctx, pool, string);
  688. return val;
  689. }
  690. fz_json *fz_json_new_boolean(fz_context *ctx, fz_pool *pool, int x)
  691. {
  692. if (x)
  693. return json_new_value(ctx, pool, FZ_JSON_TRUE);
  694. return json_new_value(ctx, pool, FZ_JSON_FALSE);
  695. }
  696. fz_json *fz_json_new_null(fz_context *ctx, fz_pool *pool)
  697. {
  698. return json_new_value(ctx, pool, FZ_JSON_NULL);
  699. }