Line data Source code
1 0 : /*
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 <zephyr/sys/util.h>
11 : #include <stddef.h>
12 : #include <zephyr/toolchain.h>
13 : #include <zephyr/types.h>
14 : #include <sys/types.h>
15 :
16 : #ifdef __cplusplus
17 : extern "C" {
18 : #endif
19 :
20 : /**
21 : * @defgroup json JSON
22 : * @ingroup utilities
23 : * @{
24 : */
25 :
26 0 : 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 :
32 : JSON_TOK_NONE = '_',
33 : JSON_TOK_OBJECT_START = '{',
34 : JSON_TOK_OBJECT_END = '}',
35 : JSON_TOK_ARRAY_START = '[',
36 : JSON_TOK_ARRAY_END = ']',
37 : JSON_TOK_STRING = '"',
38 : JSON_TOK_STRING_BUF = 's',
39 : JSON_TOK_COLON = ':',
40 : JSON_TOK_COMMA = ',',
41 : JSON_TOK_NUMBER = '0',
42 : JSON_TOK_FLOAT = '1',
43 : JSON_TOK_OPAQUE = '2',
44 : JSON_TOK_OBJ_ARRAY = '3',
45 : JSON_TOK_ENCODED_OBJ = '4',
46 : JSON_TOK_INT64 = '5',
47 : JSON_TOK_UINT64 = '6',
48 : JSON_TOK_FLOAT_FP = '7',
49 : JSON_TOK_DOUBLE_FP = '8',
50 : JSON_TOK_INT = 'i',
51 : JSON_TOK_UINT = 'u',
52 : JSON_TOK_TRUE = 't',
53 : JSON_TOK_FALSE = 'f',
54 : JSON_TOK_MIXED_ARRAY = 'm',
55 : JSON_TOK_NULL = 'n',
56 : JSON_TOK_ERROR = '!',
57 : JSON_TOK_EOF = '\0',
58 : };
59 :
60 0 : struct json_token {
61 0 : enum json_tokens type;
62 0 : char *start;
63 0 : char *end;
64 : };
65 :
66 0 : struct json_lexer {
67 0 : void *(*state)(struct json_lexer *lex);
68 0 : char *start;
69 0 : char *pos;
70 0 : char *end;
71 0 : struct json_token tok;
72 : };
73 :
74 0 : struct json_obj {
75 0 : struct json_lexer lex;
76 : };
77 :
78 0 : struct json_obj_token {
79 0 : char *start;
80 0 : size_t length;
81 : };
82 :
83 :
84 0 : struct json_obj_descr {
85 0 : const char *field_name;
86 :
87 : /* Alignment can be 1, 2, 4, or 8. The macros to create
88 : * a struct json_obj_descr will store the alignment's
89 : * power of 2 in order to keep this value in the 0-3 range
90 : * and thus use only 2 bits.
91 : */
92 0 : uint32_t align_shift : 2;
93 :
94 : /* 127 characters is more than enough for a field name. */
95 0 : uint32_t field_name_len : 7;
96 :
97 : /* Valid values here (enum json_tokens): JSON_TOK_STRING,
98 : * JSON_TOK_NUMBER, JSON_TOK_TRUE, JSON_TOK_FALSE,
99 : * JSON_TOK_OBJECT_START, JSON_TOK_ARRAY_START. (All others
100 : * ignored.) Maximum value is '}' (125), so this has to be 7 bits
101 : * long.
102 : */
103 0 : uint32_t type : 7;
104 :
105 : /* 65535 bytes is more than enough for many JSON payloads. */
106 0 : uint32_t offset : 16;
107 :
108 : union {
109 : struct {
110 0 : const struct json_obj_descr *sub_descr;
111 0 : size_t sub_descr_len;
112 0 : } object;
113 : struct {
114 0 : const struct json_obj_descr *element_descr;
115 0 : size_t n_elements;
116 0 : } array;
117 : struct {
118 0 : size_t size;
119 0 : } field;
120 0 : };
121 : };
122 :
123 : /**
124 : * @brief Function pointer type to append bytes to a buffer while
125 : * encoding JSON data.
126 : *
127 : * @param bytes Contents to write to the output
128 : * @param len Number of bytes to append to output
129 : * @param data User-provided pointer
130 : *
131 : * @return This callback function should return a negative number on
132 : * error (which will be propagated to the return value of
133 : * json_obj_encode()), or 0 on success.
134 : */
135 1 : typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
136 : void *data);
137 :
138 : #define Z_ALIGN_SHIFT(type) (__alignof__(type) == 1 ? 0 : \
139 : __alignof__(type) == 2 ? 1 : \
140 : __alignof__(type) == 4 ? 2 : 3)
141 :
142 : /**
143 : * @brief Helper macro to declare a descriptor for supported primitive
144 : * values.
145 : *
146 : * @param struct_ Struct packing the values
147 : * @param field_name_ Field name in the struct
148 : * @param type_ Token type for JSON value corresponding to a primitive
149 : * type. Must be one of: JSON_TOK_STRING for strings, JSON_TOK_NUMBER
150 : * for numbers, JSON_TOK_TRUE (or JSON_TOK_FALSE) for booleans.
151 : *
152 : * Here's an example of use:
153 : *
154 : * struct foo {
155 : * int32_t some_int;
156 : * };
157 : *
158 : * struct json_obj_descr foo[] = {
159 : * JSON_OBJ_DESCR_PRIM(struct foo, some_int, JSON_TOK_NUMBER),
160 : * };
161 : */
162 1 : #define JSON_OBJ_DESCR_PRIM(struct_, field_name_, type_) \
163 : { \
164 : .field_name = (#field_name_), \
165 : .align_shift = Z_ALIGN_SHIFT(struct_), \
166 : .field_name_len = sizeof(#field_name_) - 1, \
167 : .type = type_, \
168 : .offset = offsetof(struct_, field_name_), \
169 : .field = { \
170 : .size = SIZEOF_FIELD(struct_, field_name_) \
171 : }, \
172 : }
173 :
174 : /**
175 : * @brief Helper macro to declare a descriptor for an object value
176 : *
177 : * @param struct_ Struct packing the values
178 : * @param field_name_ Field name in the struct
179 : * @param sub_descr_ Array of json_obj_descr describing the subobject
180 : *
181 : * Here's an example of use:
182 : *
183 : * struct nested {
184 : * int32_t foo;
185 : * struct {
186 : * int32_t baz;
187 : * } bar;
188 : * };
189 : *
190 : * struct json_obj_descr nested_bar[] = {
191 : * { ... declare bar.baz descriptor ... },
192 : * };
193 : * struct json_obj_descr nested[] = {
194 : * { ... declare foo descriptor ... },
195 : * JSON_OBJ_DESCR_OBJECT(struct nested, bar, nested_bar),
196 : * };
197 : */
198 1 : #define JSON_OBJ_DESCR_OBJECT(struct_, field_name_, sub_descr_) \
199 : { \
200 : .field_name = (#field_name_), \
201 : .align_shift = Z_ALIGN_SHIFT(struct_), \
202 : .field_name_len = (sizeof(#field_name_) - 1), \
203 : .type = JSON_TOK_OBJECT_START, \
204 : .offset = offsetof(struct_, field_name_), \
205 : .object = { \
206 : .sub_descr = sub_descr_, \
207 : .sub_descr_len = ARRAY_SIZE(sub_descr_), \
208 : }, \
209 : }
210 :
211 : /**
212 : * @internal @brief Helper macro to declare an element descriptor
213 : *
214 : * @param struct_ Struct packing the values
215 : * @param len_field_ Field name in the struct for the number of elements
216 : * in the array
217 : * @param elem_type_ Element type, must be a primitive type
218 : * @param union_ Optional macro argument containing array or object descriptor
219 : */
220 : #define Z_JSON_ELEMENT_DESCR(struct_, len_field_, elem_type_, union_) \
221 : (const struct json_obj_descr[]) \
222 : { \
223 : { \
224 : .align_shift = Z_ALIGN_SHIFT(struct_), \
225 : .type = elem_type_, \
226 : .offset = offsetof(struct_, len_field_), \
227 : union_ \
228 : } \
229 : }
230 :
231 : /**
232 : * @internal @brief Helper macro to declare an array descriptor
233 : *
234 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
235 : * @param elem_descr_len_ Number of elements in elem_descr_
236 : */
237 : #define Z_JSON_DESCR_ARRAY(elem_descr_, elem_descr_len_) \
238 : { \
239 : .array = { \
240 : .element_descr = elem_descr_, \
241 : .n_elements = elem_descr_len_, \
242 : }, \
243 : }
244 :
245 : /**
246 : * @internal @brief Helper macro to declare an object descriptor
247 : *
248 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
249 : * @param elem_descr_len_ Number of elements in elem_descr_
250 : */
251 : #define Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_) \
252 : .object = { \
253 : .sub_descr = elem_descr_, \
254 : .sub_descr_len = elem_descr_len_, \
255 : }, \
256 :
257 : /**
258 : * @internal @brief Helper macro to declare a field descriptor
259 : *
260 : * @param struct_ Struct packing the values
261 : * @param field_name_ Field name in the struct
262 : */
263 : #define Z_JSON_DESCR_FIELD(struct_, field_name_) \
264 : { \
265 : .field = { \
266 : .size = SIZEOF_FIELD(struct_, field_name_), \
267 : }, \
268 : }
269 :
270 : /**
271 : * @brief Helper macro to declare a descriptor for an array of primitives
272 : *
273 : * @param struct_ Struct packing the values
274 : * @param field_name_ Field name in the struct
275 : * @param max_len_ Maximum number of elements in array
276 : * @param len_field_ Field name in the struct for the number of elements
277 : * in the array
278 : * @param elem_type_ Element type, must be a primitive type
279 : *
280 : * Here's an example of use:
281 : *
282 : * struct example {
283 : * int32_t foo[10];
284 : * size_t foo_len;
285 : * };
286 : *
287 : * struct json_obj_descr array[] = {
288 : * JSON_OBJ_DESCR_ARRAY(struct example, foo, 10, foo_len,
289 : * JSON_TOK_NUMBER)
290 : * };
291 : */
292 : #define JSON_OBJ_DESCR_ARRAY(struct_, field_name_, max_len_, \
293 1 : len_field_, elem_type_) \
294 : { \
295 : .field_name = (#field_name_), \
296 : .align_shift = Z_ALIGN_SHIFT(struct_), \
297 : .field_name_len = sizeof(#field_name_) - 1, \
298 : .type = JSON_TOK_ARRAY_START, \
299 : .offset = offsetof(struct_, field_name_), \
300 : .array = { \
301 : .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \
302 : elem_type_, \
303 : Z_JSON_DESCR_FIELD(struct_, field_name_[0])), \
304 : .n_elements = (max_len_), \
305 : }, \
306 : }
307 :
308 : /**
309 : * @brief Helper macro to declare a descriptor for an array of objects
310 : *
311 : * @param struct_ Struct packing the values
312 : * @param field_name_ Field name in the struct containing the array
313 : * @param max_len_ Maximum number of elements in the array
314 : * @param len_field_ Field name in the struct for the number of elements
315 : * in the array
316 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
317 : * @param elem_descr_len_ Number of elements in elem_descr_
318 : *
319 : * Here's an example of use:
320 : *
321 : * struct person_height {
322 : * const char *name;
323 : * int32_t height;
324 : * };
325 : *
326 : * struct people_heights {
327 : * struct person_height heights[10];
328 : * size_t heights_len;
329 : * };
330 : *
331 : * struct json_obj_descr person_height_descr[] = {
332 : * JSON_OBJ_DESCR_PRIM(struct person_height, name, JSON_TOK_STRING),
333 : * JSON_OBJ_DESCR_PRIM(struct person_height, height, JSON_TOK_NUMBER),
334 : * };
335 : *
336 : * struct json_obj_descr array[] = {
337 : * JSON_OBJ_DESCR_OBJ_ARRAY(struct people_heights, heights, 10,
338 : * heights_len, person_height_descr,
339 : * ARRAY_SIZE(person_height_descr)),
340 : * };
341 : */
342 : #define JSON_OBJ_DESCR_OBJ_ARRAY(struct_, field_name_, max_len_, \
343 1 : len_field_, elem_descr_, elem_descr_len_) \
344 : { \
345 : .field_name = (#field_name_), \
346 : .align_shift = Z_ALIGN_SHIFT(struct_), \
347 : .field_name_len = sizeof(#field_name_) - 1, \
348 : .type = JSON_TOK_ARRAY_START, \
349 : .offset = offsetof(struct_, field_name_), \
350 : .array = { \
351 : .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \
352 : JSON_TOK_OBJECT_START, \
353 : Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \
354 : .n_elements = (max_len_), \
355 : }, \
356 : }
357 :
358 : /**
359 : * @brief Helper macro to declare a descriptor for an array of array
360 : *
361 : * @param struct_ Struct packing the values
362 : * @param field_name_ Field name in the struct containing the array
363 : * @param max_len_ Maximum number of elements in the array
364 : * @param len_field_ Field name in the struct for the number of elements
365 : * in the array
366 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
367 : * @param elem_descr_len_ Number of elements in elem_descr_
368 : *
369 : * Here's an example of use:
370 : *
371 : * struct person_height {
372 : * const char *name;
373 : * int32_t height;
374 : * };
375 : *
376 : * struct person_heights_array {
377 : * struct person_height heights;
378 : * }
379 : *
380 : * struct people_heights {
381 : * struct person_height_array heights[10];
382 : * size_t heights_len;
383 : * };
384 : *
385 : * struct json_obj_descr person_height_descr[] = {
386 : * JSON_OBJ_DESCR_PRIM(struct person_height, name, JSON_TOK_STRING),
387 : * JSON_OBJ_DESCR_PRIM(struct person_height, height, JSON_TOK_NUMBER),
388 : * };
389 : *
390 : * struct json_obj_descr person_height_array_descr[] = {
391 : * JSON_OBJ_DESCR_OBJECT(struct person_heights_array,
392 : * heights, person_height_descr),
393 : * };
394 : *
395 : * struct json_obj_descr array_array[] = {
396 : * JSON_OBJ_DESCR_ARRAY_ARRAY(struct people_heights, heights, 10,
397 : * heights_len, person_height_array_descr,
398 : * ARRAY_SIZE(person_height_array_descr)),
399 : * };
400 : */
401 : #define JSON_OBJ_DESCR_ARRAY_ARRAY(struct_, field_name_, max_len_, len_field_, \
402 1 : elem_descr_, elem_descr_len_) \
403 : { \
404 : .field_name = (#field_name_), \
405 : .align_shift = Z_ALIGN_SHIFT(struct_), \
406 : .field_name_len = sizeof(#field_name_) - 1, \
407 : .type = JSON_TOK_ARRAY_START, \
408 : .offset = offsetof(struct_, field_name_), \
409 : .array = { \
410 : .element_descr = Z_JSON_ELEMENT_DESCR( \
411 : struct_, len_field_, JSON_TOK_ARRAY_START, \
412 : Z_JSON_DESCR_ARRAY( \
413 : elem_descr_, \
414 : 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \
415 : .n_elements = (max_len_), \
416 : }, \
417 : }
418 :
419 : /**
420 : * @brief Variant of JSON_OBJ_DESCR_ARRAY_ARRAY that can be used when the
421 : * structure and JSON field names differ.
422 : *
423 : * This is useful when the JSON field is not a valid C identifier.
424 : *
425 : * @param struct_ Struct packing the values
426 : * @param json_field_name_ String, field name in JSON strings
427 : * @param struct_field_name_ Field name in the struct containing the array
428 : * @param max_len_ Maximum number of elements in the array
429 : * @param len_field_ Field name in the struct for the number of elements
430 : * in the array
431 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
432 : * @param elem_descr_len_ Number of elements in elem_descr_
433 : *
434 : * @see JSON_OBJ_DESCR_ARRAY_ARRAY
435 : */
436 : #define JSON_OBJ_DESCR_ARRAY_ARRAY_NAMED(struct_, json_field_name_, struct_field_name_, \
437 1 : max_len_, len_field_, elem_descr_, elem_descr_len_) \
438 : { \
439 : .field_name = (#json_field_name_), \
440 : .align_shift = Z_ALIGN_SHIFT(struct_), \
441 : .field_name_len = sizeof(#json_field_name_) - 1, \
442 : .type = JSON_TOK_ARRAY_START, \
443 : .offset = offsetof(struct_, struct_field_name_), \
444 : .array = { \
445 : .element_descr = Z_JSON_ELEMENT_DESCR( \
446 : struct_, len_field_, JSON_TOK_ARRAY_START, \
447 : Z_JSON_DESCR_ARRAY( \
448 : elem_descr_, \
449 : 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \
450 : .n_elements = (max_len_), \
451 : }, \
452 : }
453 :
454 : /**
455 : * @brief Variant of JSON_OBJ_DESCR_PRIM that can be used when the
456 : * structure and JSON field names differ.
457 : *
458 : * This is useful when the JSON field is not a valid C identifier.
459 : *
460 : * @param struct_ Struct packing the values.
461 : * @param json_field_name_ String, field name in JSON strings
462 : * @param struct_field_name_ Field name in the struct
463 : * @param type_ Token type for JSON value corresponding to a primitive
464 : * type.
465 : *
466 : * @see JSON_OBJ_DESCR_PRIM
467 : */
468 : #define JSON_OBJ_DESCR_PRIM_NAMED(struct_, json_field_name_, \
469 1 : struct_field_name_, type_) \
470 : { \
471 : .field_name = (json_field_name_), \
472 : .align_shift = Z_ALIGN_SHIFT(struct_), \
473 : .field_name_len = sizeof(json_field_name_) - 1, \
474 : .type = type_, \
475 : .offset = offsetof(struct_, struct_field_name_), \
476 : .field = { \
477 : .size = SIZEOF_FIELD(struct_, struct_field_name_) \
478 : }, \
479 : }
480 :
481 : /**
482 : * @brief Variant of JSON_OBJ_DESCR_OBJECT that can be used when the
483 : * structure and JSON field names differ.
484 : *
485 : * This is useful when the JSON field is not a valid C identifier.
486 : *
487 : * @param struct_ Struct packing the values
488 : * @param json_field_name_ String, field name in JSON strings
489 : * @param struct_field_name_ Field name in the struct
490 : * @param sub_descr_ Array of json_obj_descr describing the subobject
491 : *
492 : * @see JSON_OBJ_DESCR_OBJECT
493 : */
494 : #define JSON_OBJ_DESCR_OBJECT_NAMED(struct_, json_field_name_, \
495 1 : struct_field_name_, sub_descr_) \
496 : { \
497 : .field_name = (json_field_name_), \
498 : .align_shift = Z_ALIGN_SHIFT(struct_), \
499 : .field_name_len = (sizeof(json_field_name_) - 1), \
500 : .type = JSON_TOK_OBJECT_START, \
501 : .offset = offsetof(struct_, struct_field_name_), \
502 : .object = { \
503 : .sub_descr = sub_descr_, \
504 : .sub_descr_len = ARRAY_SIZE(sub_descr_), \
505 : }, \
506 : }
507 :
508 : /**
509 : * @brief Variant of JSON_OBJ_DESCR_ARRAY that can be used when the
510 : * structure and JSON field names differ.
511 : *
512 : * This is useful when the JSON field is not a valid C identifier.
513 : *
514 : * @param struct_ Struct packing the values
515 : * @param json_field_name_ String, field name in JSON strings
516 : * @param struct_field_name_ Field name in the struct
517 : * @param max_len_ Maximum number of elements in array
518 : * @param len_field_ Field name in the struct for the number of elements
519 : * in the array
520 : * @param elem_type_ Element type, must be a primitive type
521 : *
522 : * @see JSON_OBJ_DESCR_ARRAY
523 : */
524 : #define JSON_OBJ_DESCR_ARRAY_NAMED(struct_, json_field_name_,\
525 : struct_field_name_, max_len_, len_field_, \
526 1 : elem_type_) \
527 : { \
528 : .field_name = (json_field_name_), \
529 : .align_shift = Z_ALIGN_SHIFT(struct_), \
530 : .field_name_len = sizeof(json_field_name_) - 1, \
531 : .type = JSON_TOK_ARRAY_START, \
532 : .offset = offsetof(struct_, struct_field_name_), \
533 : .array = { \
534 : .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \
535 : elem_type_, \
536 : Z_JSON_DESCR_FIELD(struct_, struct_field_name_[0])), \
537 : .n_elements = (max_len_), \
538 : }, \
539 : }
540 :
541 : /**
542 : * @brief Variant of JSON_OBJ_DESCR_OBJ_ARRAY that can be used when
543 : * the structure and JSON field names differ.
544 : *
545 : * This is useful when the JSON field is not a valid C identifier.
546 : *
547 : * @param struct_ Struct packing the values
548 : * @param json_field_name_ String, field name of the array in JSON strings
549 : * @param struct_field_name_ Field name in the struct containing the array
550 : * @param max_len_ Maximum number of elements in the array
551 : * @param len_field_ Field name in the struct for the number of elements
552 : * in the array
553 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
554 : * @param elem_descr_len_ Number of elements in elem_descr_
555 : *
556 : * Here's an example of use:
557 : *
558 : * struct person_height {
559 : * const char *name;
560 : * int32_t height;
561 : * };
562 : *
563 : * struct people_heights {
564 : * struct person_height heights[10];
565 : * size_t heights_len;
566 : * };
567 : *
568 : * struct json_obj_descr person_height_descr[] = {
569 : * JSON_OBJ_DESCR_PRIM(struct person_height, name, JSON_TOK_STRING),
570 : * JSON_OBJ_DESCR_PRIM(struct person_height, height, JSON_TOK_NUMBER),
571 : * };
572 : *
573 : * struct json_obj_descr array[] = {
574 : * JSON_OBJ_DESCR_OBJ_ARRAY_NAMED(struct people_heights,
575 : * "people-heights", heights,
576 : * 10, heights_len,
577 : * person_height_descr,
578 : * ARRAY_SIZE(person_height_descr)),
579 : * };
580 : */
581 : #define JSON_OBJ_DESCR_OBJ_ARRAY_NAMED(struct_, json_field_name_, \
582 : struct_field_name_, max_len_, \
583 : len_field_, elem_descr_, \
584 1 : elem_descr_len_) \
585 : { \
586 : .field_name = json_field_name_, \
587 : .align_shift = Z_ALIGN_SHIFT(struct_), \
588 : .field_name_len = sizeof(json_field_name_) - 1, \
589 : .type = JSON_TOK_ARRAY_START, \
590 : .offset = offsetof(struct_, struct_field_name_), \
591 : .array = { \
592 : .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \
593 : JSON_TOK_OBJECT_START, \
594 : Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \
595 : .n_elements = (max_len_), \
596 : }, \
597 : }
598 :
599 : /**
600 : * @brief Parses the JSON-encoded object pointed to by @a json, with
601 : * size @a len, according to the descriptor pointed to by @a descr.
602 : * Values are stored in a struct pointed to by @a val. Set up the
603 : * descriptor like this:
604 : *
605 : * struct s { int32_t foo; char *bar; }
606 : * struct json_obj_descr descr[] = {
607 : * JSON_OBJ_DESCR_PRIM(struct s, foo, JSON_TOK_NUMBER),
608 : * JSON_OBJ_DESCR_PRIM(struct s, bar, JSON_TOK_STRING),
609 : * };
610 : *
611 : * Since this parser is designed for machine-to-machine communications, some
612 : * liberties were taken to simplify the design:
613 : * (1) strings are not unescaped (but only valid escape sequences are
614 : * accepted);
615 : * (2) no UTF-8 validation is performed; and
616 : * (3) only integer numbers are supported (no strtod() in the minimal libc).
617 : *
618 : * @param json Pointer to JSON-encoded value to be parsed
619 : * @param len Length of JSON-encoded value
620 : * @param descr Pointer to the descriptor array
621 : * @param descr_len Number of elements in the descriptor array. Must be less
622 : * than 63 due to implementation detail reasons (if more fields are
623 : * necessary, use two descriptors)
624 : * @param val Pointer to the struct to hold the decoded values
625 : *
626 : * @return < 0 if error, bitmap of decoded fields on success (bit 0
627 : * is set if first field in the descriptor has been properly decoded, etc).
628 : */
629 1 : int64_t json_obj_parse(char *json, size_t len,
630 : const struct json_obj_descr *descr, size_t descr_len,
631 : void *val);
632 :
633 : /**
634 : * @brief Parses the JSON-encoded array pointed to by @a json, with
635 : * size @a len, according to the descriptor pointed to by @a descr.
636 : * Values are stored in a struct pointed to by @a val. Set up the
637 : * descriptor like this:
638 : *
639 : * struct s { int32_t foo; char *bar; }
640 : * struct json_obj_descr descr[] = {
641 : * JSON_OBJ_DESCR_PRIM(struct s, foo, JSON_TOK_NUMBER),
642 : * JSON_OBJ_DESCR_PRIM(struct s, bar, JSON_TOK_STRING),
643 : * };
644 : * struct a { struct s baz[10]; size_t count; }
645 : * struct json_obj_descr array[] = {
646 : * JSON_OBJ_DESCR_OBJ_ARRAY(struct a, baz, 10, count,
647 : * descr, ARRAY_SIZE(descr)),
648 : * };
649 : *
650 : * Since this parser is designed for machine-to-machine communications, some
651 : * liberties were taken to simplify the design:
652 : * (1) strings are not unescaped (but only valid escape sequences are
653 : * accepted);
654 : * (2) no UTF-8 validation is performed; and
655 : * (3) only integer numbers are supported (no strtod() in the minimal libc).
656 : *
657 : * @param json Pointer to JSON-encoded array to be parsed
658 : * @param len Length of JSON-encoded array
659 : * @param descr Pointer to the descriptor array
660 : * @param val Pointer to the struct to hold the decoded values
661 : *
662 : * @return 0 if array has been successfully parsed. A negative value
663 : * indicates an error (as defined on errno.h).
664 : */
665 1 : int json_arr_parse(char *json, size_t len,
666 : const struct json_obj_descr *descr, void *val);
667 :
668 : /**
669 : * @brief Initialize single-object array parsing
670 : *
671 : * JSON-encoded array data is going to be parsed one object at a time. Data is provided by
672 : * @a payload with the size of @a len bytes.
673 : *
674 : * Function validate that Json Array start is detected and initialize @a json object for
675 : * Json object parsing separately.
676 : *
677 : * @param json Provide storage for parser states. To be used when parsing the array.
678 : * @param payload Pointer to JSON-encoded array to be parsed
679 : * @param len Length of JSON-encoded array
680 : *
681 : * @return 0 if array start is detected and initialization is successful or negative error
682 : * code in case of failure.
683 : */
684 1 : int json_arr_separate_object_parse_init(struct json_obj *json, char *payload, size_t len);
685 :
686 : /**
687 : * @brief Parse a single object from array.
688 : *
689 : * Parses the JSON-encoded object pointed to by @a json object array, with
690 : * size @a len, according to the descriptor pointed to by @a descr.
691 : *
692 : * @param json Pointer to JSON-object message state
693 : * @param descr Pointer to the descriptor array
694 : * @param descr_len Number of elements in the descriptor array. Must be less than 31.
695 : * @param val Pointer to the struct to hold the decoded values
696 : *
697 : * @return < 0 if error, 0 for end of message, bitmap of decoded fields on success (bit 0
698 : * is set if first field in the descriptor has been properly decoded, etc).
699 : */
700 1 : int json_arr_separate_parse_object(struct json_obj *json, const struct json_obj_descr *descr,
701 : size_t descr_len, void *val);
702 :
703 : /**
704 : * @brief Escapes the string so it can be used to encode JSON objects
705 : *
706 : * @param str The string to escape; the escape string is stored the
707 : * buffer pointed to by this parameter
708 : * @param len Points to a size_t containing the size before and after
709 : * the escaping process
710 : * @param buf_size The size of buffer str points to
711 : *
712 : * @return 0 if string has been escaped properly, or -ENOMEM if there
713 : * was not enough space to escape the buffer
714 : */
715 1 : ssize_t json_escape(char *str, size_t *len, size_t buf_size);
716 :
717 : /**
718 : * @brief Calculates the JSON-escaped string length
719 : *
720 : * @param str The string to analyze
721 : * @param len String size
722 : *
723 : * @return The length str would have if it were escaped
724 : */
725 1 : size_t json_calc_escaped_len(const char *str, size_t len);
726 :
727 : /**
728 : * @brief Calculates the string length to fully encode an object
729 : *
730 : * @param descr Pointer to the descriptor array
731 : * @param descr_len Number of elements in the descriptor array
732 : * @param val Struct holding the values
733 : *
734 : * @return Number of bytes necessary to encode the values if >0,
735 : * an error code is returned.
736 : */
737 1 : ssize_t json_calc_encoded_len(const struct json_obj_descr *descr,
738 : size_t descr_len, const void *val);
739 :
740 : /**
741 : * @brief Calculates the string length to fully encode an array
742 : *
743 : * @param descr Pointer to the descriptor array
744 : * @param val Struct holding the values
745 : *
746 : * @return Number of bytes necessary to encode the values if >0,
747 : * an error code is returned.
748 : */
749 1 : ssize_t json_calc_encoded_arr_len(const struct json_obj_descr *descr,
750 : const void *val);
751 :
752 : /**
753 : * @brief Encodes an object in a contiguous memory location
754 : *
755 : * @param descr Pointer to the descriptor array
756 : * @param descr_len Number of elements in the descriptor array
757 : * @param val Struct holding the values
758 : * @param buffer Buffer to store the JSON data
759 : * @param buf_size Size of buffer, in bytes, with space for the terminating
760 : * NUL character
761 : *
762 : * @return 0 if object has been successfully encoded. A negative value
763 : * indicates an error (as defined on errno.h).
764 : */
765 1 : int json_obj_encode_buf(const struct json_obj_descr *descr, size_t descr_len,
766 : const void *val, char *buffer, size_t buf_size);
767 :
768 : /**
769 : * @brief Encodes an array in a contiguous memory location
770 : *
771 : * @param descr Pointer to the descriptor array
772 : * @param val Struct holding the values
773 : * @param buffer Buffer to store the JSON data
774 : * @param buf_size Size of buffer, in bytes, with space for the terminating
775 : * NUL character
776 : *
777 : * @return 0 if object has been successfully encoded. A negative value
778 : * indicates an error (as defined on errno.h).
779 : */
780 1 : int json_arr_encode_buf(const struct json_obj_descr *descr, const void *val,
781 : char *buffer, size_t buf_size);
782 :
783 : /**
784 : * @brief Encodes an object using an arbitrary writer function
785 : *
786 : * @param descr Pointer to the descriptor array
787 : * @param descr_len Number of elements in the descriptor array
788 : * @param val Struct holding the values
789 : * @param append_bytes Function to append bytes to the output
790 : * @param data Data pointer to be passed to the append_bytes callback
791 : * function.
792 : *
793 : * @return 0 if object has been successfully encoded. A negative value
794 : * indicates an error.
795 : */
796 1 : int json_obj_encode(const struct json_obj_descr *descr, size_t descr_len,
797 : const void *val, json_append_bytes_t append_bytes,
798 : void *data);
799 :
800 : /**
801 : * @brief Encodes an array using an arbitrary writer function
802 : *
803 : * @param descr Pointer to the descriptor array
804 : * @param val Struct holding the values
805 : * @param append_bytes Function to append bytes to the output
806 : * @param data Data pointer to be passed to the append_bytes callback
807 : * function.
808 : *
809 : * @return 0 if object has been successfully encoded. A negative value
810 : * indicates an error.
811 : */
812 1 : int json_arr_encode(const struct json_obj_descr *descr, const void *val,
813 : json_append_bytes_t append_bytes, void *data);
814 :
815 : /**
816 : * @brief Descriptor for a mixed-type JSON array.
817 : *
818 : * This structure describes a top-level JSON array whose elements may be
819 : * of different types (primitives, objects, arrays, or nested mixed arrays).
820 : * Each element in the array is described by an entry in a descriptor array.
821 : *
822 : * Mixed arrays are useful for parsing and encoding JSON arrays that do not
823 : * have a homogeneous element type, such as:
824 : *
825 : * [ "string", 42, { "foo": 1 }, [1,2,3], true ]
826 : *
827 : * @note This structure and its associated macros are intended for use with
828 : * the mixed array parsing and encoding APIs (see json_mixed_arr_parse()).
829 : */
830 1 : struct json_mixed_arr_descr {
831 0 : uint32_t type : 7;
832 0 : size_t count_offset;
833 :
834 : union {
835 : struct {
836 0 : size_t offset;
837 0 : size_t size;
838 0 : } primitive;
839 :
840 : struct {
841 0 : const struct json_obj_descr *sub_descr;
842 0 : size_t sub_descr_len;
843 : size_t offset;
844 0 : } object;
845 :
846 : struct {
847 0 : const struct json_obj_descr *element_descr;
848 0 : size_t n_elements;
849 : size_t offset;
850 0 : } array;
851 :
852 : struct {
853 0 : const struct json_mixed_arr_descr *sub_descr;
854 : size_t sub_descr_len;
855 : size_t offset;
856 0 : } mixed_array;
857 0 : };
858 : };
859 :
860 : /**
861 : * @brief Helper macro to declare a mixed array primitive element descriptor.
862 : *
863 : * @param struct_ Struct containing the value.
864 : * @param field_name_ Field name in the struct.
865 : * @param type_ Token type for the JSON value (see enum json_tokens).
866 : * @param count_field_ Field name in the struct for the number of elements.
867 : *
868 : * Example:
869 : * struct foo { int x; size_t x_count; };
870 : * const struct json_mixed_arr_descr foo_descr[] = {
871 : * JSON_MIXED_ARR_DESCR_PRIM(struct foo, x, JSON_TOK_NUMBER, x_count),
872 : * };
873 : */
874 1 : #define JSON_MIXED_ARR_DESCR_PRIM(struct_, field_name_, type_, count_field_) \
875 : { \
876 : .type = type_, \
877 : .count_offset = offsetof(struct_, count_field_), \
878 : .primitive = { \
879 : .offset = offsetof(struct_, field_name_), \
880 : .size = SIZEOF_FIELD(struct_, field_name_) \
881 : } \
882 : }
883 :
884 : /**
885 : * @brief Helper macro to declare a mixed array object element descriptor.
886 : *
887 : * @param struct_ Struct containing the object.
888 : * @param field_name_ Field name in the struct.
889 : * @param sub_descr_ Array of json_obj_descr describing the object fields.
890 : * @param count_field_ Field name in the struct for the number of elements.
891 : *
892 : * Example:
893 : * struct bar { int y; };
894 : * struct foo { struct bar b; size_t b_count; };
895 : * const struct json_obj_descr bar_descr[] = { ... };
896 : * const struct json_mixed_arr_descr foo_descr[] = {
897 : * JSON_MIXED_ARR_DESCR_OBJECT(struct foo, b, bar_descr, b_count),
898 : * };
899 : */
900 1 : #define JSON_MIXED_ARR_DESCR_OBJECT(struct_, field_name_, sub_descr_, count_field_) \
901 : { \
902 : .type = JSON_TOK_OBJECT_START, \
903 : .count_offset = offsetof(struct_, count_field_), \
904 : .object = { \
905 : .sub_descr = sub_descr_, \
906 : .sub_descr_len = ARRAY_SIZE(sub_descr_), \
907 : .offset = offsetof(struct_, field_name_) \
908 : } \
909 : }
910 :
911 : /**
912 : * @brief Helper macro to declare a mixed array homogeneous array element descriptor.
913 : *
914 : * @param struct_ Struct containing the array.
915 : * @param field_name_ Field name in the struct.
916 : * @param max_len_ Maximum number of elements in the array.
917 : * @param elem_descr_ Element descriptor (pointer to json_obj_descr array).
918 : * @param count_field_ Field name in the struct for the number of elements.
919 : *
920 : * Example:
921 : * struct foo {
922 : * int arr[4];
923 : * size_t arr_count;
924 : * };
925 : * const struct json_obj_descr arr_elem_descr[] = {
926 : * JSON_OBJ_DESCR_ARRAY(struct foo, arr, 4, arr_count, JSON_TOK_NUMBER),
927 : * };
928 : * const struct json_mixed_arr_descr foo_descr[] = {
929 : * JSON_MIXED_ARR_DESCR_ARRAY(struct foo, arr, 4, arr_elem_descr, arr_count),
930 : * };
931 : */
932 1 : #define JSON_MIXED_ARR_DESCR_ARRAY(struct_, field_name_, max_len_, elem_descr_, count_field_) \
933 : { \
934 : .type = JSON_TOK_ARRAY_START, \
935 : .count_offset = offsetof(struct_, count_field_), \
936 : .array = { \
937 : .element_descr = elem_descr_, \
938 : .n_elements = (max_len_), \
939 : .offset = offsetof(struct_, field_name_) \
940 : } \
941 : }
942 :
943 : /**
944 : * @brief Helper macro to declare a nested mixed array element descriptor.
945 : *
946 : * @param struct_ Struct containing the nested mixed array.
947 : * @param field_name_ Field name in the struct.
948 : * @param sub_descr_ Mixed array descriptor for the nested array.
949 : * @param count_field_ Field name in the struct for the number of elements.
950 : *
951 : * Example:
952 : * struct foo { ...; size_t nested_count; };
953 : * const struct json_mixed_arr_descr nested_descr[] = { ... };
954 : * const struct json_mixed_arr_descr foo_descr[] = {
955 : * JSON_MIXED_ARR_DESCR_MIXED_ARRAY(struct foo, nested, nested_descr, nested_count),
956 : * };
957 : */
958 1 : #define JSON_MIXED_ARR_DESCR_MIXED_ARRAY(struct_, field_name_, sub_descr_, count_field_) \
959 : { \
960 : .type = JSON_TOK_MIXED_ARRAY, \
961 : .count_offset = offsetof(struct_, count_field_), \
962 : .mixed_array = { \
963 : .sub_descr = sub_descr_, \
964 : .sub_descr_len = ARRAY_SIZE(sub_descr_), \
965 : .offset = offsetof(struct_, field_name_) \
966 : } \
967 : }
968 :
969 : /**
970 : * @brief Parse a JSON mixed array into a C structure.
971 : *
972 : * This function parses a JSON array (which may contain elements of varying types)
973 : * according to the provided mixed array descriptor and stores the result in the
974 : * user-supplied structure.
975 : *
976 : * @param json Pointer to the input JSON string.
977 : * @param len Length of the input JSON string.
978 : * @param descr Descriptor array describing the structure of the mixed array.
979 : * @param descr_len Number of elements in the descriptor array.
980 : * @param val Pointer to the structure to populate with parsed data.
981 : *
982 : * @return < 0 if error, number of elements parsed on success.
983 : */
984 1 : int json_mixed_arr_parse(char *json, size_t len,
985 : const struct json_mixed_arr_descr *descr,
986 : size_t descr_len, void *val);
987 :
988 : /**
989 : * @brief Encode a C structure as a JSON mixed array.
990 : *
991 : * This function encodes a C structure, described by the mixed array descriptor,
992 : * as a JSON array.
993 : *
994 : * @param descr Descriptor array describing the structure of the mixed array.
995 : * @param descr_len Number of elements in the descriptor array.
996 : * @param val Pointer to the structure to encode.
997 : * @param append_bytes Function to append bytes to the output
998 : * @param data Data pointer to be passed to the append_bytes callback
999 : * function.
1000 : *
1001 : * @return 0 if mixed array has been successfully encoded. Negative error code on failure.
1002 : */
1003 1 : int json_mixed_arr_encode(const struct json_mixed_arr_descr *descr,
1004 : size_t descr_len, void *val,
1005 : json_append_bytes_t append_bytes,
1006 : void *data);
1007 :
1008 : /**
1009 : * @brief Encode a C structure as a JSON mixed array into a buffer.
1010 : *
1011 : * This function encodes a C structure, described by the mixed array descriptor,
1012 : * as a JSON array and writes the result into the provided buffer.
1013 : *
1014 : * @param descr Descriptor array describing the structure of the mixed array.
1015 : * @param descr_len Number of elements in the descriptor array.
1016 : * @param val Pointer to the structure to encode.
1017 : * @param buffer Output buffer to write the JSON string.
1018 : * @param buf_size Size of the output buffer.
1019 : *
1020 : * @return 0 if mixed array has been successfully encoded. Negative error code on failure.
1021 : */
1022 1 : int json_mixed_arr_encode_buf(const struct json_mixed_arr_descr *descr,
1023 : size_t descr_len, void *val,
1024 : char *buffer, size_t buf_size);
1025 :
1026 : /**
1027 : * @brief Calculate the length of the encoded JSON mixed array.
1028 : *
1029 : * This function calculates the number of bytes required to encode the given
1030 : * structure as a JSON mixed array, according to the provided descriptor.
1031 : *
1032 : * @param descr Descriptor array describing the structure of the mixed array.
1033 : * @param descr_len Number of elements in the descriptor array.
1034 : * @param val Pointer to the structure to encode.
1035 : *
1036 : * @return Number of bytes required for encoding, or negative error code.
1037 : */
1038 1 : ssize_t json_calc_mixed_arr_len(const struct json_mixed_arr_descr *descr,
1039 : size_t descr_len, void *val);
1040 :
1041 : #ifdef __cplusplus
1042 : }
1043 : #endif
1044 :
1045 : /**
1046 : * @}
1047 : */
1048 : #endif /* ZEPHYR_INCLUDE_DATA_JSON_H_ */
|