json.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. /*
  2. * Copyright (c) 2017 Intel Corporation
  3. * Copyright (c) 2022 L. A. F. Pereira <[email protected]>
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. */
  7. #include <assert.h>
  8. #include <ctype.h>
  9. #include <errno.h>
  10. #include <limits.h>
  11. #include <stdbool.h>
  12. #include <stdint.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include "json.h"
  17. #include "lwan.h"
  18. #include "int-to-str.h"
  19. struct token {
  20. enum json_tokens type;
  21. char *start;
  22. char *end;
  23. };
  24. struct lexer {
  25. void *(*state)(struct lexer *lexer);
  26. char *start;
  27. char *pos;
  28. char *end;
  29. struct token token;
  30. };
  31. struct json_obj {
  32. struct lexer lexer;
  33. };
  34. struct json_obj_key_value {
  35. const char *key;
  36. size_t key_len;
  37. struct token value;
  38. };
  39. static bool lexer_consume(struct lexer *lexer,
  40. struct token *token,
  41. enum json_tokens empty_token)
  42. {
  43. if (lexer->token.type == empty_token) {
  44. return false;
  45. }
  46. *token = lexer->token;
  47. lexer->token.type = empty_token;
  48. return true;
  49. }
  50. static bool lexer_next(struct lexer *lexer, struct token *token)
  51. {
  52. while (lexer->state) {
  53. if (lexer_consume(lexer, token, JSON_TOK_NONE)) {
  54. return true;
  55. }
  56. lexer->state = lexer->state(lexer);
  57. }
  58. return lexer_consume(lexer, token, JSON_TOK_EOF);
  59. }
  60. static void *lexer_json(struct lexer *lexer);
  61. static void emit(struct lexer *lexer, enum json_tokens token)
  62. {
  63. lexer->token.type = token;
  64. lexer->token.start = lexer->start;
  65. lexer->token.end = lexer->pos;
  66. lexer->start = lexer->pos;
  67. }
  68. static void* emit_cont(struct lexer *lexer, enum json_tokens token)
  69. {
  70. emit(lexer, token);
  71. return lexer_json;
  72. }
  73. static void* emit_end(struct lexer *lexer, enum json_tokens token)
  74. {
  75. emit(lexer, token);
  76. return NULL;
  77. }
  78. static int next(struct lexer *lexer)
  79. {
  80. if (lexer->pos >= lexer->end) {
  81. lexer->pos = lexer->end + 1;
  82. return '\0';
  83. }
  84. return *lexer->pos++;
  85. }
  86. static void ignore(struct lexer *lexer) { lexer->start = lexer->pos; }
  87. static void backup(struct lexer *lexer) { lexer->pos--; }
  88. static int peek(struct lexer *lexer)
  89. {
  90. int chr = next(lexer);
  91. backup(lexer);
  92. return chr;
  93. }
  94. static void *lexer_string(struct lexer *lexer)
  95. {
  96. ignore(lexer);
  97. while (true) {
  98. int chr = next(lexer);
  99. if (UNLIKELY(chr == '\0')) {
  100. return emit_end(lexer, JSON_TOK_ERROR);
  101. }
  102. if (chr == '\\') {
  103. switch (next(lexer)) {
  104. case '"':
  105. case '\\':
  106. case '/':
  107. case 'b':
  108. case 'f':
  109. case 'n':
  110. case 'r':
  111. case 't':
  112. continue;
  113. case 'u':
  114. if (UNLIKELY(!isxdigit(next(lexer)))) {
  115. goto error;
  116. }
  117. if (UNLIKELY(!isxdigit(next(lexer)))) {
  118. goto error;
  119. }
  120. if (UNLIKELY(!isxdigit(next(lexer)))) {
  121. goto error;
  122. }
  123. if (UNLIKELY(!isxdigit(next(lexer)))) {
  124. goto error;
  125. }
  126. break;
  127. default:
  128. goto error;
  129. }
  130. }
  131. if (chr == '"') {
  132. backup(lexer);
  133. emit(lexer, JSON_TOK_STRING);
  134. next(lexer);
  135. ignore(lexer);
  136. return lexer_json;
  137. }
  138. }
  139. error:
  140. return emit_end(lexer, JSON_TOK_ERROR);
  141. }
  142. static int accept_run(struct lexer *lexer, const char *run)
  143. {
  144. for (; *run; run++) {
  145. if (UNLIKELY(next(lexer) != *run)) {
  146. return -EINVAL;
  147. }
  148. }
  149. return 0;
  150. }
  151. static void *lexer_boolean(struct lexer *lexer)
  152. {
  153. /* Already matched either `t' or `f' at this point */
  154. switch (next(lexer)) {
  155. case 'r':
  156. if (LIKELY(!accept_run(lexer, "ue"))) {
  157. return emit_cont(lexer, JSON_TOK_TRUE);
  158. }
  159. break;
  160. case 'a':
  161. if (LIKELY(!accept_run(lexer, "lse"))) {
  162. return emit_cont(lexer, JSON_TOK_FALSE);
  163. }
  164. break;
  165. }
  166. return emit_end(lexer, JSON_TOK_ERROR);
  167. }
  168. static void *lexer_null(struct lexer *lexer)
  169. {
  170. if (UNLIKELY(accept_run(lexer, "ull") < 0)) {
  171. return emit_end(lexer, JSON_TOK_ERROR);
  172. }
  173. return emit_cont(lexer, JSON_TOK_NULL);
  174. }
  175. static void *lexer_number(struct lexer *lexer)
  176. {
  177. while (true) {
  178. int chr = next(lexer);
  179. if (isdigit(chr) || chr == '.') {
  180. continue;
  181. }
  182. backup(lexer);
  183. return emit_cont(lexer, JSON_TOK_NUMBER);
  184. }
  185. }
  186. static void *lexer_json(struct lexer *lexer)
  187. {
  188. while (true) {
  189. int chr = next(lexer);
  190. switch (chr) {
  191. case '\0':
  192. return emit_end(lexer, JSON_TOK_EOF);
  193. case '}':
  194. case '{':
  195. case '[':
  196. case ']':
  197. case ',':
  198. case ':':
  199. return emit_cont(lexer, (enum json_tokens)chr);
  200. case '"':
  201. return lexer_string;
  202. case 'n':
  203. return lexer_null;
  204. case 't':
  205. case 'f':
  206. return lexer_boolean;
  207. case '-':
  208. if (LIKELY(isdigit(peek(lexer)))) {
  209. return lexer_number;
  210. }
  211. /* fallthrough */
  212. default:
  213. if (isspace(chr)) {
  214. ignore(lexer);
  215. continue;
  216. }
  217. if (LIKELY(isdigit(chr))) {
  218. return lexer_number;
  219. }
  220. return emit_end(lexer, JSON_TOK_ERROR);
  221. }
  222. }
  223. }
  224. static void lexer_init(struct lexer *lexer, char *data, size_t len)
  225. {
  226. lexer->state = lexer_json;
  227. lexer->start = data;
  228. lexer->pos = data;
  229. lexer->end = data + len;
  230. lexer->token.type = JSON_TOK_NONE;
  231. }
  232. static int obj_init(struct json_obj *json, char *data, size_t len)
  233. {
  234. struct token token;
  235. lexer_init(&json->lexer, data, len);
  236. if (UNLIKELY(!lexer_next(&json->lexer, &token))) {
  237. return -EINVAL;
  238. }
  239. if (UNLIKELY(token.type != JSON_TOK_OBJECT_START)) {
  240. return -EINVAL;
  241. }
  242. return 0;
  243. }
  244. static int element_token(enum json_tokens token)
  245. {
  246. switch (token) {
  247. case JSON_TOK_OBJECT_START:
  248. case JSON_TOK_LIST_START:
  249. case JSON_TOK_STRING:
  250. case JSON_TOK_NUMBER:
  251. case JSON_TOK_TRUE:
  252. case JSON_TOK_FALSE:
  253. return 0;
  254. default:
  255. return -EINVAL;
  256. }
  257. }
  258. static int obj_next(struct json_obj *json, struct json_obj_key_value *kv)
  259. {
  260. struct token token;
  261. if (UNLIKELY(!lexer_next(&json->lexer, &token))) {
  262. return -EINVAL;
  263. }
  264. /* Match end of object or next key */
  265. switch (token.type) {
  266. case JSON_TOK_OBJECT_END:
  267. kv->key = NULL;
  268. kv->key_len = 0;
  269. kv->value = token;
  270. return 0;
  271. case JSON_TOK_COMMA:
  272. if (UNLIKELY(!lexer_next(&json->lexer, &token))) {
  273. return -EINVAL;
  274. }
  275. if (UNLIKELY(token.type != JSON_TOK_STRING)) {
  276. return -EINVAL;
  277. }
  278. /* fallthrough */
  279. case JSON_TOK_STRING:
  280. kv->key = token.start;
  281. kv->key_len = (size_t)(token.end - token.start);
  282. break;
  283. default:
  284. return -EINVAL;
  285. }
  286. /* Match : after key */
  287. if (UNLIKELY(!lexer_next(&json->lexer, &token))) {
  288. return -EINVAL;
  289. }
  290. if (UNLIKELY(token.type != JSON_TOK_COLON)) {
  291. return -EINVAL;
  292. }
  293. /* Match value */
  294. if (UNLIKELY(!lexer_next(&json->lexer, &kv->value))) {
  295. return -EINVAL;
  296. }
  297. return element_token(kv->value.type);
  298. }
  299. static int arr_next(struct json_obj *json, struct token *value)
  300. {
  301. if (UNLIKELY(!lexer_next(&json->lexer, value))) {
  302. return -EINVAL;
  303. }
  304. if (value->type == JSON_TOK_LIST_END) {
  305. return 0;
  306. }
  307. if (value->type == JSON_TOK_COMMA) {
  308. if (UNLIKELY(!lexer_next(&json->lexer, value))) {
  309. return -EINVAL;
  310. }
  311. }
  312. return element_token(value->type);
  313. }
  314. static int decode_num(const struct token *token, int32_t *num)
  315. {
  316. /* FIXME: strtod() is not available in newlib/minimal libc,
  317. * so using strtol() here.
  318. */
  319. char *endptr;
  320. char prev_end;
  321. prev_end = *token->end;
  322. *token->end = '\0';
  323. errno = 0;
  324. long v = strtol(token->start, &endptr, 10);
  325. if ((long)(int)v != v) {
  326. return -ERANGE;
  327. }
  328. *num = (int)v;
  329. *token->end = prev_end;
  330. if (errno != 0) {
  331. return -errno;
  332. }
  333. if (endptr != token->end) {
  334. return -EINVAL;
  335. }
  336. return 0;
  337. }
  338. static bool equivalent_types(enum json_tokens type1, enum json_tokens type2)
  339. {
  340. if (type1 == JSON_TOK_TRUE || type1 == JSON_TOK_FALSE) {
  341. return type2 == JSON_TOK_TRUE || type2 == JSON_TOK_FALSE;
  342. }
  343. return type1 == type2;
  344. }
  345. static int obj_parse(struct json_obj *obj,
  346. const struct json_obj_descr *descr,
  347. size_t descr_len,
  348. void *val);
  349. static int arr_parse(struct json_obj *obj,
  350. const struct json_obj_descr *elem_descr,
  351. size_t max_elements,
  352. void *field,
  353. void *val);
  354. static int decode_value(struct json_obj *obj,
  355. const struct json_obj_descr *descr,
  356. struct token *value,
  357. void *field,
  358. void *val)
  359. {
  360. if (!equivalent_types(value->type, descr->type)) {
  361. return -EINVAL;
  362. }
  363. switch (descr->type) {
  364. case JSON_TOK_OBJECT_START:
  365. return obj_parse(obj, descr->object.sub_descr,
  366. descr->object.sub_descr_len, field);
  367. case JSON_TOK_LIST_START:
  368. return arr_parse(obj, descr->array.element_descr,
  369. descr->array.n_elements, field, val);
  370. case JSON_TOK_FALSE:
  371. case JSON_TOK_TRUE: {
  372. bool *v = field;
  373. *v = value->type == JSON_TOK_TRUE;
  374. return 0;
  375. }
  376. case JSON_TOK_NUMBER: {
  377. int32_t *num = field;
  378. return decode_num(value, num);
  379. }
  380. case JSON_TOK_STRING: {
  381. char **str = field;
  382. *value->end = '\0';
  383. *str = value->start;
  384. return 0;
  385. }
  386. default:
  387. return -EINVAL;
  388. }
  389. }
  390. static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
  391. {
  392. switch (descr->type) {
  393. case JSON_TOK_NUMBER:
  394. return sizeof(int32_t);
  395. case JSON_TOK_STRING:
  396. return sizeof(char *);
  397. case JSON_TOK_TRUE:
  398. case JSON_TOK_FALSE:
  399. return sizeof(bool);
  400. case JSON_TOK_LIST_START:
  401. return (ptrdiff_t)descr->array.n_elements *
  402. get_elem_size(descr->array.element_descr);
  403. case JSON_TOK_OBJECT_START: {
  404. ptrdiff_t total = 0;
  405. size_t i;
  406. for (i = 0; i < descr->object.sub_descr_len; i++) {
  407. ptrdiff_t s = get_elem_size(&descr->object.sub_descr[i]);
  408. total += (ptrdiff_t)ROUND_UP(s, descr->object.sub_descr[i].align);
  409. }
  410. return total;
  411. }
  412. default:
  413. return -EINVAL;
  414. }
  415. }
  416. static int arr_parse(struct json_obj *obj,
  417. const struct json_obj_descr *elem_descr,
  418. size_t max_elements,
  419. void *field,
  420. void *val)
  421. {
  422. ptrdiff_t elem_size = get_elem_size(elem_descr);
  423. void *last_elem = (char *)field + elem_size * (ptrdiff_t)max_elements;
  424. size_t *elements = (size_t *)((char *)val + elem_descr->offset);
  425. struct token value;
  426. assert(elem_size > 0);
  427. *elements = 0;
  428. while (!arr_next(obj, &value)) {
  429. if (value.type == JSON_TOK_LIST_END) {
  430. return 0;
  431. }
  432. if (UNLIKELY(field == last_elem)) {
  433. return -ENOSPC;
  434. }
  435. if (UNLIKELY(decode_value(obj, elem_descr, &value, field, val) < 0)) {
  436. return -EINVAL;
  437. }
  438. (*elements)++;
  439. field = (char *)field + elem_size;
  440. }
  441. return -EINVAL;
  442. }
  443. static int obj_parse(struct json_obj *obj,
  444. const struct json_obj_descr *descr,
  445. size_t descr_len,
  446. void *val)
  447. {
  448. struct json_obj_key_value kv;
  449. int32_t decoded_fields = 0;
  450. size_t i;
  451. int ret;
  452. while (!obj_next(obj, &kv)) {
  453. if (kv.value.type == JSON_TOK_OBJECT_END) {
  454. return decoded_fields;
  455. }
  456. for (i = 0; i < descr_len; i++) {
  457. void *decode_field = (char *)val + descr[i].offset;
  458. /* Field has been decoded already, skip */
  459. if (decoded_fields & (1 << i)) {
  460. continue;
  461. }
  462. /* Check if it's the i-th field */
  463. if (kv.key_len != descr[i].field_name_len) {
  464. continue;
  465. }
  466. if (memcmp(kv.key, descr[i].field_name, descr[i].field_name_len)) {
  467. continue;
  468. }
  469. /* Store the decoded value */
  470. ret = decode_value(obj, &descr[i], &kv.value, decode_field, val);
  471. if (UNLIKELY(UNLIKELY(ret < 0))) {
  472. return ret;
  473. }
  474. decoded_fields |= 1 << i;
  475. break;
  476. }
  477. }
  478. return -EINVAL;
  479. }
  480. int json_obj_parse(char *payload,
  481. size_t len,
  482. const struct json_obj_descr *descr,
  483. size_t descr_len,
  484. void *val)
  485. {
  486. struct json_obj obj;
  487. int ret;
  488. assert(descr_len < (sizeof(ret) * CHAR_BIT - 1));
  489. ret = obj_init(&obj, payload, len);
  490. if (UNLIKELY(ret < 0)) {
  491. return ret;
  492. }
  493. return obj_parse(&obj, descr, descr_len, val);
  494. }
  495. /*
  496. * Routines has_zero() and has_value() are from
  497. * https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
  498. */
  499. static ALWAYS_INLINE uint64_t has_zero(uint64_t v)
  500. {
  501. return (v - 0x0101010101010101UL) & ~v & 0x8080808080808080UL;
  502. }
  503. static ALWAYS_INLINE uint64_t has_value(uint64_t x, char n)
  504. {
  505. return has_zero(x ^ (~0UL / 255 * (uint64_t)n));
  506. }
  507. static char escape_as(char chr)
  508. {
  509. static const char escaped[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 't'};
  510. uint64_t mask = has_value(0x225c080c0a0d0909UL, chr);
  511. return mask == 0 ? 0 : escaped[__builtin_clzl(mask) / 8];
  512. }
  513. static int json_escape_internal(const char *str,
  514. json_append_bytes_t append_bytes,
  515. void *data)
  516. {
  517. const char *cur;
  518. const char *unescaped;
  519. int ret = 0;
  520. for (cur = unescaped = str; *cur; cur++) {
  521. char escaped = escape_as(*cur);
  522. if (escaped) {
  523. char bytes[2] = {'\\', escaped};
  524. if (cur - unescaped) {
  525. ret |= append_bytes(unescaped, (size_t)(cur - unescaped), data);
  526. unescaped = cur + 1;
  527. }
  528. ret |= append_bytes(bytes, 2, data);
  529. }
  530. }
  531. if (cur - unescaped)
  532. ret |= append_bytes(unescaped, (size_t)(cur - unescaped), data);
  533. return ret;
  534. }
  535. size_t json_calc_escaped_len(const char *str, size_t len)
  536. {
  537. size_t escaped_len = len;
  538. size_t pos;
  539. for (pos = 0; pos < len; pos++) {
  540. if (escape_as(str[pos])) {
  541. escaped_len++;
  542. }
  543. }
  544. return escaped_len;
  545. }
  546. ssize_t json_escape(char *str, size_t *len, size_t buf_size)
  547. {
  548. char *next; /* Points after next character to escape. */
  549. char *dest; /* Points after next place to write escaped character. */
  550. size_t escaped_len = json_calc_escaped_len(str, *len);
  551. if (escaped_len == *len) {
  552. /*
  553. * If no escape is necessary, there is nothing to do.
  554. */
  555. return 0;
  556. }
  557. if (UNLIKELY(escaped_len >= buf_size)) {
  558. return -ENOMEM;
  559. }
  560. /*
  561. * By walking backwards in the buffer from the end positions
  562. * of both the original and escaped strings, we avoid using
  563. * extra space. Characters in the original string are
  564. * overwritten only after they have already been escaped.
  565. */
  566. str[escaped_len] = '\0';
  567. for (next = &str[*len], dest = &str[escaped_len]; next != str;) {
  568. char next_c = *(--next);
  569. char escape = escape_as(next_c);
  570. if (escape) {
  571. *(--dest) = escape;
  572. *(--dest) = '\\';
  573. } else {
  574. *(--dest) = next_c;
  575. }
  576. }
  577. *len = escaped_len;
  578. return 0;
  579. }
  580. static int encode(const struct json_obj_descr *descr,
  581. const void *val,
  582. json_append_bytes_t append_bytes,
  583. void *data,
  584. bool escape_key);
  585. static int arr_encode(const struct json_obj_descr *elem_descr,
  586. const void *field,
  587. const void *val,
  588. json_append_bytes_t append_bytes,
  589. void *data,
  590. bool escape_key)
  591. {
  592. ptrdiff_t elem_size = get_elem_size(elem_descr);
  593. /*
  594. * NOTE: Since an element descriptor's offset isn't meaningful (array
  595. * elements occur at multiple offsets in `val'), we use its space in
  596. * elem_descr to store the offset to the field containing the number of
  597. * elements.
  598. */
  599. size_t n_elem = *(size_t *)((char *)val + elem_descr->offset);
  600. int ret = append_bytes("[", 1, data);
  601. if (LIKELY(n_elem)) {
  602. n_elem--;
  603. for (size_t i = 0; i < n_elem; i++) {
  604. /*
  605. * Though "field" points at the next element in the array which we
  606. * need to encode, the value in elem_descr->offset is actually the
  607. * offset of the length field in the "parent" struct containing the
  608. * array.
  609. *
  610. * To patch things up, we lie to encode() about where the field is
  611. * by exactly the amount it will offset it. This is a size
  612. * optimization for struct json_obj_descr: the alternative is to
  613. * keep a separate field next to element_descr which is an offset to
  614. * the length field in the parent struct, but that would add a
  615. * size_t to every descriptor.
  616. */
  617. ret |= encode(elem_descr, (char *)field - elem_descr->offset,
  618. append_bytes, data, escape_key);
  619. ret |= append_bytes(",", 1, data);
  620. field = (char *)field + elem_size;
  621. }
  622. ret |= encode(elem_descr, (char *)field - elem_descr->offset,
  623. append_bytes, data, escape_key);
  624. }
  625. return ret | append_bytes("]", 1, data);
  626. }
  627. static int str_encode(const char **str,
  628. json_append_bytes_t append_bytes,
  629. void *data)
  630. {
  631. int ret = append_bytes("\"", 1, data);
  632. ret |= json_escape_internal(*str, append_bytes, data);
  633. return ret | append_bytes("\"", 1, data);
  634. }
  635. static int
  636. num_encode(const int32_t *num, json_append_bytes_t append_bytes, void *data)
  637. {
  638. char buf[INT_TO_STR_BUFFER_SIZE];
  639. size_t len;
  640. char *as_string = int_to_string(*num, buf, &len);
  641. return append_bytes(as_string, len, data);
  642. }
  643. static int
  644. bool_encode(const bool *value, json_append_bytes_t append_bytes, void *data)
  645. {
  646. if (*value) {
  647. return append_bytes("true", 4, data);
  648. }
  649. return append_bytes("false", 5, data);
  650. }
  651. int json_arr_encode_full(const struct json_obj_descr *descr,
  652. const void *val,
  653. json_append_bytes_t append_bytes,
  654. void *data,
  655. bool escape_key)
  656. {
  657. void *ptr = (char *)val + descr->offset;
  658. return arr_encode(descr->array.element_descr, ptr, val, append_bytes, data,
  659. escape_key);
  660. }
  661. static int encode(const struct json_obj_descr *descr,
  662. const void *val,
  663. json_append_bytes_t append_bytes,
  664. void *data,
  665. bool escape_key)
  666. {
  667. void *ptr = (char *)val + descr->offset;
  668. switch (descr->type) {
  669. case JSON_TOK_FALSE:
  670. case JSON_TOK_TRUE:
  671. return bool_encode(ptr, append_bytes, data);
  672. case JSON_TOK_STRING:
  673. return str_encode(ptr, append_bytes, data);
  674. case JSON_TOK_LIST_START:
  675. return arr_encode(descr->array.element_descr, ptr, val,
  676. append_bytes, data, escape_key);
  677. case JSON_TOK_OBJECT_START:
  678. return json_obj_encode_full(descr->object.sub_descr,
  679. descr->object.sub_descr_len, ptr, append_bytes,
  680. data, escape_key);
  681. case JSON_TOK_NUMBER:
  682. return num_encode(ptr, append_bytes, data);
  683. default:
  684. return -EINVAL;
  685. }
  686. }
  687. static inline int encode_key(const struct json_obj_descr *descr,
  688. json_append_bytes_t append_bytes,
  689. void *data,
  690. bool escape_key)
  691. {
  692. int ret;
  693. if (!escape_key) {
  694. /* Keys are encoded twice in the descriptor; once without quotes and
  695. * the trailing comma, and one with. Doing it like so cuts some
  696. * indirect calls to append_bytes(), which in turn also potentially
  697. * cuts some branches in most implementations of it. */
  698. ret = append_bytes(descr->field_name + descr->field_name_len,
  699. descr->field_name_len + 3 /* 3=len('"":') */, data);
  700. } else {
  701. ret = str_encode((const char **)&descr->field_name, append_bytes, data);
  702. ret |= append_bytes(":", 1, data);
  703. }
  704. return ret;
  705. }
  706. int json_obj_encode_full(const struct json_obj_descr *descr,
  707. size_t descr_len,
  708. const void *val,
  709. json_append_bytes_t append_bytes,
  710. void *data,
  711. bool escape_key)
  712. {
  713. int ret = append_bytes("{", 1, data);
  714. if (LIKELY(descr_len)) {
  715. /* To avoid checking if we're encoding the last element on each
  716. * iteration of this loop, start at the second descriptor, and always
  717. * write the comma. Then, after the loop, encode the first descriptor.
  718. * If the descriptor array has only 1 element, this loop won't run. This
  719. * is fine since order isn't important for objects, and we save some
  720. * branches. */
  721. for (size_t i = 1; i < descr_len; i++) {
  722. ret |= encode_key(&descr[i], append_bytes, data, escape_key);
  723. ret |= encode(&descr[i], val, append_bytes, data, escape_key);
  724. ret |= append_bytes(",", 1, data);
  725. }
  726. ret |= encode_key(&descr[0], append_bytes, data, escape_key);
  727. ret |= encode(&descr[0], val, append_bytes, data, escape_key);
  728. }
  729. return ret | append_bytes("}", 1, data);
  730. }
  731. struct appender {
  732. char *buffer;
  733. size_t used;
  734. size_t size;
  735. };
  736. static int append_bytes_to_buf(const char *bytes, size_t len, void *data)
  737. {
  738. struct appender *appender = data;
  739. if (UNLIKELY(len > appender->size - appender->used)) {
  740. return -ENOMEM;
  741. }
  742. memcpy(appender->buffer + appender->used, bytes, len);
  743. appender->used += len;
  744. appender->buffer[appender->used] = '\0';
  745. return 0;
  746. }
  747. int json_obj_encode_buf(const struct json_obj_descr *descr,
  748. size_t descr_len,
  749. const void *val,
  750. char *buffer,
  751. size_t buf_size)
  752. {
  753. struct appender appender = {.buffer = buffer, .size = buf_size};
  754. return json_obj_encode(descr, descr_len, val, append_bytes_to_buf,
  755. &appender);
  756. }
  757. static int
  758. measure_bytes(const char *bytes __attribute__((unused)), size_t len, void *data)
  759. {
  760. ssize_t *total = data;
  761. *total += (ssize_t)len;
  762. return 0;
  763. }
  764. ssize_t json_calc_encoded_len(const struct json_obj_descr *descr,
  765. size_t descr_len,
  766. const void *val)
  767. {
  768. ssize_t total = 0;
  769. int ret;
  770. ret = json_obj_encode(descr, descr_len, val, measure_bytes, &total);
  771. if (UNLIKELY(ret < 0)) {
  772. return ret;
  773. }
  774. return total;
  775. }