json.h 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /*
  2. * Copyright (c) 2017 Intel Corporation
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #ifndef ZEPHYR_INCLUDE_DATA_JSON_H_
  7. #define ZEPHYR_INCLUDE_DATA_JSON_H_
  8. #include <stddef.h>
  9. #include <stdint.h>
  10. #include <sys/types.h>
  11. #ifdef __cplusplus
  12. extern "C" {
  13. #endif
  14. #define ROUND_UP(x, align) \
  15. (((unsigned long)(x) + ((unsigned long)(align)-1)) & \
  16. ~((unsigned long)(align)-1))
  17. /**
  18. * @brief Structured Data
  19. * @defgroup structured_data Structured Data
  20. */
  21. /**
  22. * @defgroup json JSON
  23. * @ingroup structured_data
  24. * @{
  25. */
  26. enum json_tokens {
  27. /* Before changing this enum, ensure that its maximum
  28. * value is still within 7 bits. See comment next to the
  29. * declaration of `type` in struct json_obj_descr.
  30. */
  31. JSON_TOK_NONE = '_',
  32. JSON_TOK_OBJECT_START = '{',
  33. JSON_TOK_OBJECT_END = '}',
  34. JSON_TOK_LIST_START = '[',
  35. JSON_TOK_LIST_END = ']',
  36. JSON_TOK_STRING = '"',
  37. JSON_TOK_COLON = ':',
  38. JSON_TOK_COMMA = ',',
  39. JSON_TOK_NUMBER = '0',
  40. JSON_TOK_TRUE = 't',
  41. JSON_TOK_FALSE = 'f',
  42. JSON_TOK_NULL = 'n',
  43. JSON_TOK_ERROR = '!',
  44. JSON_TOK_EOF = '\0',
  45. };
  46. struct json_obj_descr {
  47. const char *field_name;
  48. uint32_t align_shift;
  49. uint32_t field_name_len;
  50. uint32_t type;
  51. uint32_t offset;
  52. union {
  53. struct {
  54. const struct json_obj_descr *sub_descr;
  55. size_t sub_descr_len;
  56. } object;
  57. struct {
  58. const struct json_obj_descr *element_descr;
  59. size_t n_elements;
  60. } array;
  61. };
  62. };
  63. /**
  64. * @brief Function pointer type to append bytes to a buffer while
  65. * encoding JSON data.
  66. *
  67. * @param bytes Contents to write to the output
  68. * @param len Number of bytes in @param bytes to append to output
  69. * @param data User-provided pointer
  70. *
  71. * @return This callback function should return a negative number on
  72. * error (which will be propagated to the return value of
  73. * json_obj_encode()), or 0 on success.
  74. */
  75. typedef int (*json_append_bytes_t)(const char *bytes, size_t len, void *data);
  76. #define Z_ALIGN_SHIFT(type) \
  77. (__alignof__(type) == 1 \
  78. ? 0 \
  79. : __alignof__(type) == 2 ? 1 : __alignof__(type) == 4 ? 2 : 3)
  80. /**
  81. * @brief Helper macro to declare a descriptor for supported primitive
  82. * values.
  83. *
  84. * @param struct_ Struct packing the values
  85. *
  86. * @param field_name_ Field name in the struct
  87. *
  88. * @param type_ Token type for JSON value corresponding to a primitive
  89. * type. Must be one of: JSON_TOK_STRING for strings, JSON_TOK_NUMBER
  90. * for numbers, JSON_TOK_TRUE (or JSON_TOK_FALSE) for booleans.
  91. *
  92. * Here's an example of use:
  93. *
  94. * struct foo {
  95. * int some_int;
  96. * };
  97. *
  98. * struct json_obj_descr foo[] = {
  99. * JSON_OBJ_DESCR_PRIM(struct foo, some_int, JSON_TOK_NUMBER),
  100. * };
  101. */
  102. #define JSON_OBJ_DESCR_PRIM(struct_, field_name_, type_) \
  103. { \
  104. .field_name = (#field_name_), .align_shift = Z_ALIGN_SHIFT(struct_), \
  105. .field_name_len = sizeof(#field_name_) - 1, .type = type_, \
  106. .offset = offsetof(struct_, field_name_), \
  107. }
  108. /**
  109. * @brief Helper macro to declare a descriptor for an object value
  110. *
  111. * @param struct_ Struct packing the values
  112. *
  113. * @param field_name_ Field name in the struct
  114. *
  115. * @param sub_descr_ Array of json_obj_descr describing the subobject
  116. *
  117. * Here's an example of use:
  118. *
  119. * struct nested {
  120. * int foo;
  121. * struct {
  122. * int baz;
  123. * } bar;
  124. * };
  125. *
  126. * struct json_obj_descr nested_bar[] = {
  127. * { ... declare bar.baz descriptor ... },
  128. * };
  129. * struct json_obj_descr nested[] = {
  130. * { ... declare foo descriptor ... },
  131. * JSON_OBJ_DESCR_OBJECT(struct nested, bar, nested_bar),
  132. * };
  133. */
  134. #define JSON_OBJ_DESCR_OBJECT(struct_, field_name_, sub_descr_) \
  135. { \
  136. .field_name = (#field_name_), .align_shift = Z_ALIGN_SHIFT(struct_), \
  137. .field_name_len = (sizeof(#field_name_) - 1), \
  138. .type = JSON_TOK_OBJECT_START, \
  139. .offset = offsetof(struct_, field_name_), \
  140. .object = { \
  141. .sub_descr = sub_descr_, \
  142. .sub_descr_len = ARRAY_SIZE(sub_descr_), \
  143. }, \
  144. }
  145. /**
  146. * @brief Helper macro to declare a descriptor for an array of primitives
  147. *
  148. * @param struct_ Struct packing the values
  149. *
  150. * @param field_name_ Field name in the struct
  151. *
  152. * @param max_len_ Maximum number of elements in array
  153. *
  154. * @param len_field_ Field name in the struct for the number of elements
  155. * in the array
  156. *
  157. * @param elem_type_ Element type, must be a primitive type
  158. *
  159. * Here's an example of use:
  160. *
  161. * struct example {
  162. * int foo[10];
  163. * size_t foo_len;
  164. * };
  165. *
  166. * struct json_obj_descr array[] = {
  167. * JSON_OBJ_DESCR_ARRAY(struct example, foo, 10, foo_len,
  168. * JSON_TOK_NUMBER)
  169. * };
  170. */
  171. #define JSON_OBJ_DESCR_ARRAY(struct_, field_name_, max_len_, len_field_, \
  172. elem_type_) \
  173. { \
  174. .field_name = (#field_name_), .align_shift = Z_ALIGN_SHIFT(struct_), \
  175. .field_name_len = sizeof(#field_name_) - 1, \
  176. .type = JSON_TOK_LIST_START, .offset = offsetof(struct_, field_name_), \
  177. .array = { \
  178. .element_descr = \
  179. &(struct json_obj_descr){ \
  180. .align_shift = Z_ALIGN_SHIFT(struct_), \
  181. .type = elem_type_, \
  182. .offset = offsetof(struct_, len_field_), \
  183. }, \
  184. .n_elements = (max_len_), \
  185. }, \
  186. }
  187. /**
  188. * @brief Helper macro to declare a descriptor for an array of objects
  189. *
  190. * @param struct_ Struct packing the values
  191. *
  192. * @param field_name_ Field name in the struct containing the array
  193. *
  194. * @param max_len_ Maximum number of elements in the array
  195. *
  196. * @param len_field_ Field name in the struct for the number of elements
  197. * in the array
  198. *
  199. * @param elem_descr_ Element descriptor, pointer to a descriptor array
  200. *
  201. * @param elem_descr_len_ Number of elements in elem_descr_
  202. *
  203. * Here's an example of use:
  204. *
  205. * struct person_height {
  206. * const char *name;
  207. * int height;
  208. * };
  209. *
  210. * struct people_heights {
  211. * struct person_height heights[10];
  212. * size_t heights_len;
  213. * };
  214. *
  215. * struct json_obj_descr person_height_descr[] = {
  216. * JSON_OBJ_DESCR_PRIM(struct person_height, name, JSON_TOK_STRING),
  217. * JSON_OBJ_DESCR_PRIM(struct person_height, height, JSON_TOK_NUMBER),
  218. * };
  219. *
  220. * struct json_obj_descr array[] = {
  221. * JSON_OBJ_DESCR_OBJ_ARRAY(struct people_heights, heights, 10,
  222. * heights_len, person_height_descr,
  223. * ARRAY_SIZE(person_height_descr)),
  224. * };
  225. */
  226. #define JSON_OBJ_DESCR_OBJ_ARRAY(struct_, field_name_, max_len_, len_field_, \
  227. elem_descr_, elem_descr_len_) \
  228. { \
  229. .field_name = (#field_name_), .align_shift = Z_ALIGN_SHIFT(struct_), \
  230. .field_name_len = sizeof(#field_name_) - 1, \
  231. .type = JSON_TOK_LIST_START, .offset = offsetof(struct_, field_name_), \
  232. .array = { \
  233. .element_descr = \
  234. &(struct json_obj_descr){ \
  235. .align_shift = Z_ALIGN_SHIFT(struct_), \
  236. .type = JSON_TOK_OBJECT_START, \
  237. .offset = offsetof(struct_, len_field_), \
  238. .object = \
  239. { \
  240. .sub_descr = elem_descr_, \
  241. .sub_descr_len = elem_descr_len_, \
  242. }, \
  243. }, \
  244. .n_elements = (max_len_), \
  245. }, \
  246. }
  247. /**
  248. * @brief Helper macro to declare a descriptor for an array of array
  249. *
  250. * @param struct_ Struct packing the values
  251. *
  252. * @param field_name_ Field name in the struct containing the array
  253. *
  254. * @param max_len_ Maximum number of elements in the array
  255. *
  256. * @param len_field_ Field name in the struct for the number of elements
  257. * in the array
  258. *
  259. * @param elem_descr_ Element descriptor, pointer to a descriptor array
  260. *
  261. * @param elem_descr_len_ Number of elements in elem_descr_
  262. *
  263. * Here's an example of use:
  264. *
  265. * struct person_height {
  266. * const char *name;
  267. * int height;
  268. * };
  269. *
  270. * struct person_heights_array {
  271. * struct person_height heights;
  272. * }
  273. *
  274. * struct people_heights {
  275. * struct person_height_array heights[10];
  276. * size_t heights_len;
  277. * };
  278. *
  279. * struct json_obj_descr person_height_descr[] = {
  280. * JSON_OBJ_DESCR_PRIM(struct person_height, name, JSON_TOK_STRING),
  281. * JSON_OBJ_DESCR_PRIM(struct person_height, height, JSON_TOK_NUMBER),
  282. * };
  283. *
  284. * struct json_obj_descr person_height_array_descr[] = {
  285. * JSON_OBJ_DESCR_OBJECT(struct person_heights_array,
  286. * heights, person_heigth_descr),
  287. * };
  288. *
  289. * struct json_obj_descr array_array[] = {
  290. * JSON_OBJ_DESCR_ARRAY_ARRAY(struct people_heights, heights, 10,
  291. * heights_len, person_height_array_descr,
  292. * ARRAY_SIZE(person_height_array_descr)),
  293. * };
  294. */
  295. #define JSON_OBJ_DESCR_ARRAY_ARRAY(struct_, field_name_, max_len_, len_field_, \
  296. elem_descr_, elem_descr_len_) \
  297. { \
  298. .field_name = (#field_name_), .align_shift = Z_ALIGN_SHIFT(struct_), \
  299. .field_name_len = sizeof(#field_name_) - 1, \
  300. .type = JSON_TOK_LIST_START, .offset = offsetof(struct_, field_name_), \
  301. .array = { \
  302. .element_descr = \
  303. &(struct json_obj_descr){ \
  304. .align_shift = Z_ALIGN_SHIFT(struct_), \
  305. .type = JSON_TOK_LIST_START, \
  306. .offset = offsetof(struct_, len_field_), \
  307. .object = \
  308. { \
  309. .sub_descr = elem_descr_, \
  310. .sub_descr_len = elem_descr_len_, \
  311. }, \
  312. }, \
  313. .n_elements = (max_len_), \
  314. }, \
  315. }
  316. /**
  317. * @brief Variant of JSON_OBJ_DESCR_PRIM that can be used when the
  318. * structure and JSON field names differ.
  319. *
  320. * This is useful when the JSON field is not a valid C identifier.
  321. *
  322. * @param struct_ Struct packing the values.
  323. *
  324. * @param json_field_name_ String, field name in JSON strings
  325. *
  326. * @param struct_field_name_ Field name in the struct
  327. *
  328. * @param type_ Token type for JSON value corresponding to a primitive
  329. * type.
  330. *
  331. * @see JSON_OBJ_DESCR_PRIM
  332. */
  333. #define JSON_OBJ_DESCR_PRIM_NAMED(struct_, json_field_name_, \
  334. struct_field_name_, type_) \
  335. { \
  336. .field_name = (json_field_name_), \
  337. .align_shift = Z_ALIGN_SHIFT(struct_), \
  338. .field_name_len = sizeof(json_field_name_) - 1, .type = type_, \
  339. .offset = offsetof(struct_, struct_field_name_), \
  340. }
  341. /**
  342. * @brief Variant of JSON_OBJ_DESCR_OBJECT that can be used when the
  343. * structure and JSON field names differ.
  344. *
  345. * This is useful when the JSON field is not a valid C identifier.
  346. *
  347. * @param struct_ Struct packing the values
  348. *
  349. * @param json_field_name_ String, field name in JSON strings
  350. *
  351. * @param struct_field_name_ Field name in the struct
  352. *
  353. * @param sub_descr_ Array of json_obj_descr describing the subobject
  354. *
  355. * @see JSON_OBJ_DESCR_OBJECT
  356. */
  357. #define JSON_OBJ_DESCR_OBJECT_NAMED(struct_, json_field_name_, \
  358. struct_field_name_, sub_descr_) \
  359. { \
  360. .field_name = (json_field_name_), \
  361. .align_shift = Z_ALIGN_SHIFT(struct_), \
  362. .field_name_len = (sizeof(json_field_name_) - 1), \
  363. .type = JSON_TOK_OBJECT_START, \
  364. .offset = offsetof(struct_, struct_field_name_), \
  365. .object = { \
  366. .sub_descr = sub_descr_, \
  367. .sub_descr_len = ARRAY_SIZE(sub_descr_), \
  368. }, \
  369. }
  370. /**
  371. * @brief Variant of JSON_OBJ_DESCR_ARRAY that can be used when the
  372. * structure and JSON field names differ.
  373. *
  374. * This is useful when the JSON field is not a valid C identifier.
  375. *
  376. * @param struct_ Struct packing the values
  377. *
  378. * @param json_field_name_ String, field name in JSON strings
  379. *
  380. * @param struct_field_name_ Field name in the struct
  381. *
  382. * @param max_len_ Maximum number of elements in array
  383. *
  384. * @param len_field_ Field name in the struct for the number of elements
  385. * in the array
  386. *
  387. * @param elem_type_ Element type, must be a primitive type
  388. *
  389. * @see JSON_OBJ_DESCR_ARRAY
  390. */
  391. #define JSON_OBJ_DESCR_ARRAY_NAMED(struct_, json_field_name_, \
  392. struct_field_name_, max_len_, len_field_, \
  393. elem_type_) \
  394. { \
  395. .field_name = (json_field_name_), \
  396. .align_shift = Z_ALIGN_SHIFT(struct_), \
  397. .field_name_len = sizeof(json_field_name_) - 1, \
  398. .type = JSON_TOK_LIST_START, \
  399. .offset = offsetof(struct_, struct_field_name_), \
  400. .array = { \
  401. .element_descr = \
  402. &(struct json_obj_descr){ \
  403. .align_shift = Z_ALIGN_SHIFT(struct_), \
  404. .type = elem_type_, \
  405. .offset = offsetof(struct_, len_field_), \
  406. }, \
  407. .n_elements = (max_len_), \
  408. }, \
  409. }
  410. /**
  411. * @brief Variant of JSON_OBJ_DESCR_OBJ_ARRAY that can be used when
  412. * the structure and JSON field names differ.
  413. *
  414. * This is useful when the JSON field is not a valid C identifier.
  415. *
  416. * @param struct_ Struct packing the values
  417. *
  418. * @param json_field_name_ String, field name of the array in JSON strings
  419. *
  420. * @param struct_field_name_ Field name in the struct containing the array
  421. *
  422. * @param max_len_ Maximum number of elements in the array
  423. *
  424. * @param len_field_ Field name in the struct for the number of elements
  425. * in the array
  426. *
  427. * @param elem_descr_ Element descriptor, pointer to a descriptor array
  428. *
  429. * @param elem_descr_len_ Number of elements in elem_descr_
  430. *
  431. * Here's an example of use:
  432. *
  433. * struct person_height {
  434. * const char *name;
  435. * int height;
  436. * };
  437. *
  438. * struct people_heights {
  439. * struct person_height heights[10];
  440. * size_t heights_len;
  441. * };
  442. *
  443. * struct json_obj_descr person_height_descr[] = {
  444. * JSON_OBJ_DESCR_PRIM(struct person_height, name, JSON_TOK_STRING),
  445. * JSON_OBJ_DESCR_PRIM(struct person_height, height, JSON_TOK_NUMBER),
  446. * };
  447. *
  448. * struct json_obj_descr array[] = {
  449. * JSON_OBJ_DESCR_OBJ_ARRAY_NAMED(struct people_heights,
  450. * "people-heights", heights,
  451. * 10, heights_len,
  452. * person_height_descr,
  453. * ARRAY_SIZE(person_height_descr)),
  454. * };
  455. */
  456. #define JSON_OBJ_DESCR_OBJ_ARRAY_NAMED( \
  457. struct_, json_field_name_, struct_field_name_, max_len_, len_field_, \
  458. elem_descr_, elem_descr_len_) \
  459. { \
  460. .field_name = json_field_name_, .align_shift = Z_ALIGN_SHIFT(struct_), \
  461. .field_name_len = sizeof(json_field_name_) - 1, \
  462. .type = JSON_TOK_LIST_START, \
  463. .offset = offsetof(struct_, struct_field_name_), \
  464. .element_descr = \
  465. &(struct json_obj_descr){ \
  466. .align_shift = Z_ALIGN_SHIFT(struct_), \
  467. .type = JSON_TOK_OBJECT_START, \
  468. .offset = offsetof(struct_, len_field_), \
  469. .object = \
  470. { \
  471. .sub_descr = elem_descr_, \
  472. .sub_descr_len = elem_descr_len_, \
  473. }, \
  474. }, \
  475. .n_elements = (max_len_), \
  476. }
  477. /**
  478. * @brief Parses the JSON-encoded object pointer to by @a json, with
  479. * size @a len, according to the descriptor pointed to by @a descr.
  480. * Values are stored in a struct pointed to by @a val. Set up the
  481. * descriptor like this:
  482. *
  483. * struct s { int foo; char *bar; }
  484. * struct json_obj_descr descr[] = {
  485. * JSON_OBJ_DESCR_PRIM(struct s, foo, JSON_TOK_NUMBER),
  486. * JSON_OBJ_DESCR_PRIM(struct s, bar, JSON_TOK_STRING),
  487. * };
  488. *
  489. * Since this parser is designed for machine-to-machine communications, some
  490. * liberties were taken to simplify the design:
  491. * (1) strings are not unescaped (but only valid escape sequences are
  492. * accepted);
  493. * (2) no UTF-8 validation is performed; and
  494. * (3) only integer numbers are supported (no strtod() in the minimal libc).
  495. *
  496. * @param json Pointer to JSON-encoded value to be parsed
  497. *
  498. * @param len Length of JSON-encoded value
  499. *
  500. * @param descr Pointer to the descriptor array
  501. *
  502. * @param descr_len Number of elements in the descriptor array. Must be less
  503. * than 31 due to implementation detail reasons (if more fields are
  504. * necessary, use two descriptors)
  505. *
  506. * @param val Pointer to the struct to hold the decoded values
  507. *
  508. * @return < 0 if error, bitmap of decoded fields on success (bit 0
  509. * is set if first field in the descriptor has been properly decoded, etc).
  510. */
  511. int json_obj_parse(char *json,
  512. size_t len,
  513. const struct json_obj_descr *descr,
  514. size_t descr_len,
  515. void *val);
  516. /**
  517. * @brief Escapes the string so it can be used to encode JSON objects
  518. *
  519. * @param str The string to escape; the escape string is stored the
  520. * buffer pointed to by this parameter
  521. *
  522. * @param len Points to a size_t containing the size before and after
  523. * the escaping process
  524. *
  525. * @param buf_size The size of buffer str points to
  526. *
  527. * @return 0 if string has been escaped properly, or -ENOMEM if there
  528. * was not enough space to escape the buffer
  529. */
  530. ssize_t json_escape(char *str, size_t *len, size_t buf_size);
  531. /**
  532. * @brief Calculates the JSON-escaped string length
  533. *
  534. * @param str The string to analyze
  535. *
  536. * @param len String size
  537. *
  538. * @return The length str would have if it were escaped
  539. */
  540. size_t json_calc_escaped_len(const char *str, size_t len);
  541. /**
  542. * @brief Calculates the string length to fully encode an object
  543. *
  544. * @param descr Pointer to the descriptor array
  545. *
  546. * @param descr_len Number of elements in the descriptor array
  547. *
  548. * @param val Struct holding the values
  549. *
  550. * @return Number of bytes necessary to encode the values if >0,
  551. * an error code is returned.
  552. */
  553. ssize_t json_calc_encoded_len(const struct json_obj_descr *descr,
  554. size_t descr_len,
  555. const void *val);
  556. /**
  557. * @brief Encodes an object in a contiguous memory location
  558. *
  559. * @param descr Pointer to the descriptor array
  560. *
  561. * @param descr_len Number of elements in the descriptor array
  562. *
  563. * @param val Struct holding the values
  564. *
  565. * @param buffer Buffer to store the JSON data
  566. *
  567. * @param buf_size Size of buffer, in bytes, with space for the terminating
  568. * NUL character
  569. *
  570. * @return 0 if object has been successfully encoded. A negative value
  571. * indicates an error (as defined on errno.h).
  572. */
  573. int json_obj_encode_buf(const struct json_obj_descr *descr,
  574. size_t descr_len,
  575. const void *val,
  576. char *buffer,
  577. size_t buf_size);
  578. /**
  579. * @brief Encodes an object using an arbitrary writer function
  580. *
  581. * @param descr Pointer to the descriptor array
  582. *
  583. * @param descr_len Number of elements in the descriptor array
  584. *
  585. * @param val Struct holding the values
  586. *
  587. * @param append_bytes Function to append bytes to the output
  588. *
  589. * @param data Data pointer to be passed to the append_bytes callback
  590. * function.
  591. *
  592. * @return 0 if object has been successfully encoded. A negative value
  593. * indicates an error.
  594. */
  595. int json_obj_encode(const struct json_obj_descr *descr,
  596. size_t descr_len,
  597. const void *val,
  598. json_append_bytes_t append_bytes,
  599. void *data);
  600. #ifdef __cplusplus
  601. }
  602. #endif
  603. /**
  604. * @}
  605. */
  606. #endif /* ZEPHYR_INCLUDE_DATA_JSON_H_ */