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