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_COLON = ':',
39 : JSON_TOK_COMMA = ',',
40 : JSON_TOK_NUMBER = '0',
41 : JSON_TOK_FLOAT = '1',
42 : JSON_TOK_OPAQUE = '2',
43 : JSON_TOK_OBJ_ARRAY = '3',
44 : JSON_TOK_ENCODED_OBJ = '4',
45 : JSON_TOK_INT64 = '5',
46 : JSON_TOK_UINT64 = '6',
47 : JSON_TOK_TRUE = 't',
48 : JSON_TOK_FALSE = 'f',
49 : JSON_TOK_NULL = 'n',
50 : JSON_TOK_ERROR = '!',
51 : JSON_TOK_EOF = '\0',
52 : };
53 :
54 0 : struct json_token {
55 0 : enum json_tokens type;
56 0 : char *start;
57 0 : char *end;
58 : };
59 :
60 0 : struct json_lexer {
61 0 : void *(*state)(struct json_lexer *lex);
62 0 : char *start;
63 0 : char *pos;
64 0 : char *end;
65 0 : struct json_token tok;
66 : };
67 :
68 0 : struct json_obj {
69 0 : struct json_lexer lex;
70 : };
71 :
72 0 : struct json_obj_token {
73 0 : char *start;
74 0 : size_t length;
75 : };
76 :
77 :
78 0 : struct json_obj_descr {
79 0 : const char *field_name;
80 :
81 : /* Alignment can be 1, 2, 4, or 8. The macros to create
82 : * a struct json_obj_descr will store the alignment's
83 : * power of 2 in order to keep this value in the 0-3 range
84 : * and thus use only 2 bits.
85 : */
86 0 : uint32_t align_shift : 2;
87 :
88 : /* 127 characters is more than enough for a field name. */
89 0 : uint32_t field_name_len : 7;
90 :
91 : /* Valid values here (enum json_tokens): JSON_TOK_STRING,
92 : * JSON_TOK_NUMBER, JSON_TOK_TRUE, JSON_TOK_FALSE,
93 : * JSON_TOK_OBJECT_START, JSON_TOK_ARRAY_START. (All others
94 : * ignored.) Maximum value is '}' (125), so this has to be 7 bits
95 : * long.
96 : */
97 0 : uint32_t type : 7;
98 :
99 : /* 65535 bytes is more than enough for many JSON payloads. */
100 0 : uint32_t offset : 16;
101 :
102 : union {
103 : struct {
104 0 : const struct json_obj_descr *sub_descr;
105 0 : size_t sub_descr_len;
106 0 : } object;
107 : struct {
108 0 : const struct json_obj_descr *element_descr;
109 0 : size_t n_elements;
110 0 : } array;
111 0 : };
112 : };
113 :
114 : /**
115 : * @brief Function pointer type to append bytes to a buffer while
116 : * encoding JSON data.
117 : *
118 : * @param bytes Contents to write to the output
119 : * @param len Number of bytes to append to output
120 : * @param data User-provided pointer
121 : *
122 : * @return This callback function should return a negative number on
123 : * error (which will be propagated to the return value of
124 : * json_obj_encode()), or 0 on success.
125 : */
126 1 : typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
127 : void *data);
128 :
129 : #define Z_ALIGN_SHIFT(type) (__alignof__(type) == 1 ? 0 : \
130 : __alignof__(type) == 2 ? 1 : \
131 : __alignof__(type) == 4 ? 2 : 3)
132 :
133 : /**
134 : * @brief Helper macro to declare a descriptor for supported primitive
135 : * values.
136 : *
137 : * @param struct_ Struct packing the values
138 : * @param field_name_ Field name in the struct
139 : * @param type_ Token type for JSON value corresponding to a primitive
140 : * type. Must be one of: JSON_TOK_STRING for strings, JSON_TOK_NUMBER
141 : * for numbers, JSON_TOK_TRUE (or JSON_TOK_FALSE) for booleans.
142 : *
143 : * Here's an example of use:
144 : *
145 : * struct foo {
146 : * int32_t some_int;
147 : * };
148 : *
149 : * struct json_obj_descr foo[] = {
150 : * JSON_OBJ_DESCR_PRIM(struct foo, some_int, JSON_TOK_NUMBER),
151 : * };
152 : */
153 1 : #define JSON_OBJ_DESCR_PRIM(struct_, field_name_, type_) \
154 : { \
155 : .field_name = (#field_name_), \
156 : .align_shift = Z_ALIGN_SHIFT(struct_), \
157 : .field_name_len = sizeof(#field_name_) - 1, \
158 : .type = type_, \
159 : .offset = offsetof(struct_, field_name_), \
160 : }
161 :
162 : /**
163 : * @brief Helper macro to declare a descriptor for an object value
164 : *
165 : * @param struct_ Struct packing the values
166 : * @param field_name_ Field name in the struct
167 : * @param sub_descr_ Array of json_obj_descr describing the subobject
168 : *
169 : * Here's an example of use:
170 : *
171 : * struct nested {
172 : * int32_t foo;
173 : * struct {
174 : * int32_t baz;
175 : * } bar;
176 : * };
177 : *
178 : * struct json_obj_descr nested_bar[] = {
179 : * { ... declare bar.baz descriptor ... },
180 : * };
181 : * struct json_obj_descr nested[] = {
182 : * { ... declare foo descriptor ... },
183 : * JSON_OBJ_DESCR_OBJECT(struct nested, bar, nested_bar),
184 : * };
185 : */
186 1 : #define JSON_OBJ_DESCR_OBJECT(struct_, field_name_, sub_descr_) \
187 : { \
188 : .field_name = (#field_name_), \
189 : .align_shift = Z_ALIGN_SHIFT(struct_), \
190 : .field_name_len = (sizeof(#field_name_) - 1), \
191 : .type = JSON_TOK_OBJECT_START, \
192 : .offset = offsetof(struct_, field_name_), \
193 : .object = { \
194 : .sub_descr = sub_descr_, \
195 : .sub_descr_len = ARRAY_SIZE(sub_descr_), \
196 : }, \
197 : }
198 :
199 : /**
200 : * @internal @brief Helper macro to declare an element descriptor
201 : *
202 : * @param struct_ Struct packing the values
203 : * @param len_field_ Field name in the struct for the number of elements
204 : * in the array
205 : * @param elem_type_ Element type, must be a primitive type
206 : * @param union_ Optional macro argument containing array or object descriptor
207 : */
208 : #define Z_JSON_ELEMENT_DESCR(struct_, len_field_, elem_type_, union_) \
209 : (const struct json_obj_descr[]) \
210 : { \
211 : { \
212 : .align_shift = Z_ALIGN_SHIFT(struct_), \
213 : .type = elem_type_, \
214 : .offset = offsetof(struct_, len_field_), \
215 : union_ \
216 : } \
217 : }
218 :
219 : /**
220 : * @internal @brief Helper macro to declare an array descriptor
221 : *
222 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
223 : * @param elem_descr_len_ Number of elements in elem_descr_
224 : */
225 : #define Z_JSON_DESCR_ARRAY(elem_descr_, elem_descr_len_) \
226 : { \
227 : .array = { \
228 : .element_descr = elem_descr_, \
229 : .n_elements = elem_descr_len_, \
230 : }, \
231 : }
232 :
233 : /**
234 : * @internal @brief Helper macro to declare an object descriptor
235 : *
236 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
237 : * @param elem_descr_len_ Number of elements in elem_descr_
238 : */
239 : #define Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_) \
240 : { \
241 : .object = { \
242 : .sub_descr = elem_descr_, \
243 : .sub_descr_len = elem_descr_len_, \
244 : }, \
245 : }
246 :
247 : /**
248 : * @brief Helper macro to declare a descriptor for an array of primitives
249 : *
250 : * @param struct_ Struct packing the values
251 : * @param field_name_ Field name in the struct
252 : * @param max_len_ Maximum number of elements in array
253 : * @param len_field_ Field name in the struct for the number of elements
254 : * in the array
255 : * @param elem_type_ Element type, must be a primitive type
256 : *
257 : * Here's an example of use:
258 : *
259 : * struct example {
260 : * int32_t foo[10];
261 : * size_t foo_len;
262 : * };
263 : *
264 : * struct json_obj_descr array[] = {
265 : * JSON_OBJ_DESCR_ARRAY(struct example, foo, 10, foo_len,
266 : * JSON_TOK_NUMBER)
267 : * };
268 : */
269 : #define JSON_OBJ_DESCR_ARRAY(struct_, field_name_, max_len_, \
270 1 : len_field_, elem_type_) \
271 : { \
272 : .field_name = (#field_name_), \
273 : .align_shift = Z_ALIGN_SHIFT(struct_), \
274 : .field_name_len = sizeof(#field_name_) - 1, \
275 : .type = JSON_TOK_ARRAY_START, \
276 : .offset = offsetof(struct_, field_name_), \
277 : .array = { \
278 : .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \
279 : elem_type_,), \
280 : .n_elements = (max_len_), \
281 : }, \
282 : }
283 :
284 : /**
285 : * @brief Helper macro to declare a descriptor for an array of objects
286 : *
287 : * @param struct_ Struct packing the values
288 : * @param field_name_ Field name in the struct containing the array
289 : * @param max_len_ Maximum number of elements in the array
290 : * @param len_field_ Field name in the struct for the number of elements
291 : * in the array
292 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
293 : * @param elem_descr_len_ Number of elements in elem_descr_
294 : *
295 : * Here's an example of use:
296 : *
297 : * struct person_height {
298 : * const char *name;
299 : * int32_t height;
300 : * };
301 : *
302 : * struct people_heights {
303 : * struct person_height heights[10];
304 : * size_t heights_len;
305 : * };
306 : *
307 : * struct json_obj_descr person_height_descr[] = {
308 : * JSON_OBJ_DESCR_PRIM(struct person_height, name, JSON_TOK_STRING),
309 : * JSON_OBJ_DESCR_PRIM(struct person_height, height, JSON_TOK_NUMBER),
310 : * };
311 : *
312 : * struct json_obj_descr array[] = {
313 : * JSON_OBJ_DESCR_OBJ_ARRAY(struct people_heights, heights, 10,
314 : * heights_len, person_height_descr,
315 : * ARRAY_SIZE(person_height_descr)),
316 : * };
317 : */
318 : #define JSON_OBJ_DESCR_OBJ_ARRAY(struct_, field_name_, max_len_, \
319 1 : len_field_, elem_descr_, elem_descr_len_) \
320 : { \
321 : .field_name = (#field_name_), \
322 : .align_shift = Z_ALIGN_SHIFT(struct_), \
323 : .field_name_len = sizeof(#field_name_) - 1, \
324 : .type = JSON_TOK_ARRAY_START, \
325 : .offset = offsetof(struct_, field_name_), \
326 : .array = { \
327 : .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \
328 : JSON_TOK_OBJECT_START, \
329 : Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \
330 : .n_elements = (max_len_), \
331 : }, \
332 : }
333 :
334 : /**
335 : * @brief Helper macro to declare a descriptor for an array of array
336 : *
337 : * @param struct_ Struct packing the values
338 : * @param field_name_ Field name in the struct containing the array
339 : * @param max_len_ Maximum number of elements in the array
340 : * @param len_field_ Field name in the struct for the number of elements
341 : * in the array
342 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
343 : * @param elem_descr_len_ Number of elements in elem_descr_
344 : *
345 : * Here's an example of use:
346 : *
347 : * struct person_height {
348 : * const char *name;
349 : * int32_t height;
350 : * };
351 : *
352 : * struct person_heights_array {
353 : * struct person_height heights;
354 : * }
355 : *
356 : * struct people_heights {
357 : * struct person_height_array heights[10];
358 : * size_t heights_len;
359 : * };
360 : *
361 : * struct json_obj_descr person_height_descr[] = {
362 : * JSON_OBJ_DESCR_PRIM(struct person_height, name, JSON_TOK_STRING),
363 : * JSON_OBJ_DESCR_PRIM(struct person_height, height, JSON_TOK_NUMBER),
364 : * };
365 : *
366 : * struct json_obj_descr person_height_array_descr[] = {
367 : * JSON_OBJ_DESCR_OBJECT(struct person_heights_array,
368 : * heights, person_height_descr),
369 : * };
370 : *
371 : * struct json_obj_descr array_array[] = {
372 : * JSON_OBJ_DESCR_ARRAY_ARRAY(struct people_heights, heights, 10,
373 : * heights_len, person_height_array_descr,
374 : * ARRAY_SIZE(person_height_array_descr)),
375 : * };
376 : */
377 : #define JSON_OBJ_DESCR_ARRAY_ARRAY(struct_, field_name_, max_len_, len_field_, \
378 1 : elem_descr_, elem_descr_len_) \
379 : { \
380 : .field_name = (#field_name_), \
381 : .align_shift = Z_ALIGN_SHIFT(struct_), \
382 : .field_name_len = sizeof(#field_name_) - 1, \
383 : .type = JSON_TOK_ARRAY_START, \
384 : .offset = offsetof(struct_, field_name_), \
385 : .array = { \
386 : .element_descr = Z_JSON_ELEMENT_DESCR( \
387 : struct_, len_field_, JSON_TOK_ARRAY_START, \
388 : Z_JSON_DESCR_ARRAY( \
389 : elem_descr_, \
390 : 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \
391 : .n_elements = (max_len_), \
392 : }, \
393 : }
394 :
395 : /**
396 : * @brief Variant of JSON_OBJ_DESCR_ARRAY_ARRAY that can be used when the
397 : * structure and JSON field names differ.
398 : *
399 : * This is useful when the JSON field is not a valid C identifier.
400 : *
401 : * @param struct_ Struct packing the values
402 : * @param json_field_name_ String, field name in JSON strings
403 : * @param struct_field_name_ Field name in the struct containing the array
404 : * @param max_len_ Maximum number of elements in the array
405 : * @param len_field_ Field name in the struct for the number of elements
406 : * in the array
407 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
408 : * @param elem_descr_len_ Number of elements in elem_descr_
409 : *
410 : * @see JSON_OBJ_DESCR_ARRAY_ARRAY
411 : */
412 : #define JSON_OBJ_DESCR_ARRAY_ARRAY_NAMED(struct_, json_field_name_, struct_field_name_, \
413 1 : max_len_, len_field_, elem_descr_, elem_descr_len_) \
414 : { \
415 : .field_name = (#json_field_name_), \
416 : .align_shift = Z_ALIGN_SHIFT(struct_), \
417 : .field_name_len = sizeof(#json_field_name_) - 1, \
418 : .type = JSON_TOK_ARRAY_START, \
419 : .offset = offsetof(struct_, struct_field_name_), \
420 : .array = { \
421 : .element_descr = Z_JSON_ELEMENT_DESCR( \
422 : struct_, len_field_, JSON_TOK_ARRAY_START, \
423 : Z_JSON_DESCR_ARRAY( \
424 : elem_descr_, \
425 : 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \
426 : .n_elements = (max_len_), \
427 : }, \
428 : }
429 :
430 : /**
431 : * @brief Variant of JSON_OBJ_DESCR_PRIM that can be used when the
432 : * structure and JSON field names differ.
433 : *
434 : * This is useful when the JSON field is not a valid C identifier.
435 : *
436 : * @param struct_ Struct packing the values.
437 : * @param json_field_name_ String, field name in JSON strings
438 : * @param struct_field_name_ Field name in the struct
439 : * @param type_ Token type for JSON value corresponding to a primitive
440 : * type.
441 : *
442 : * @see JSON_OBJ_DESCR_PRIM
443 : */
444 : #define JSON_OBJ_DESCR_PRIM_NAMED(struct_, json_field_name_, \
445 1 : struct_field_name_, type_) \
446 : { \
447 : .field_name = (json_field_name_), \
448 : .align_shift = Z_ALIGN_SHIFT(struct_), \
449 : .field_name_len = sizeof(json_field_name_) - 1, \
450 : .type = type_, \
451 : .offset = offsetof(struct_, struct_field_name_), \
452 : }
453 :
454 : /**
455 : * @brief Variant of JSON_OBJ_DESCR_OBJECT 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 sub_descr_ Array of json_obj_descr describing the subobject
464 : *
465 : * @see JSON_OBJ_DESCR_OBJECT
466 : */
467 : #define JSON_OBJ_DESCR_OBJECT_NAMED(struct_, json_field_name_, \
468 1 : struct_field_name_, sub_descr_) \
469 : { \
470 : .field_name = (json_field_name_), \
471 : .align_shift = Z_ALIGN_SHIFT(struct_), \
472 : .field_name_len = (sizeof(json_field_name_) - 1), \
473 : .type = JSON_TOK_OBJECT_START, \
474 : .offset = offsetof(struct_, struct_field_name_), \
475 : .object = { \
476 : .sub_descr = sub_descr_, \
477 : .sub_descr_len = ARRAY_SIZE(sub_descr_), \
478 : }, \
479 : }
480 :
481 : /**
482 : * @brief Variant of JSON_OBJ_DESCR_ARRAY 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 max_len_ Maximum number of elements in array
491 : * @param len_field_ Field name in the struct for the number of elements
492 : * in the array
493 : * @param elem_type_ Element type, must be a primitive type
494 : *
495 : * @see JSON_OBJ_DESCR_ARRAY
496 : */
497 : #define JSON_OBJ_DESCR_ARRAY_NAMED(struct_, json_field_name_,\
498 : struct_field_name_, max_len_, len_field_, \
499 1 : elem_type_) \
500 : { \
501 : .field_name = (json_field_name_), \
502 : .align_shift = Z_ALIGN_SHIFT(struct_), \
503 : .field_name_len = sizeof(json_field_name_) - 1, \
504 : .type = JSON_TOK_ARRAY_START, \
505 : .offset = offsetof(struct_, struct_field_name_), \
506 : .array = { \
507 : .element_descr = \
508 : Z_JSON_ELEMENT_DESCR(struct_, len_field_, elem_type_,), \
509 : .n_elements = (max_len_), \
510 : }, \
511 : }
512 :
513 : /**
514 : * @brief Variant of JSON_OBJ_DESCR_OBJ_ARRAY that can be used when
515 : * the structure and JSON field names differ.
516 : *
517 : * This is useful when the JSON field is not a valid C identifier.
518 : *
519 : * @param struct_ Struct packing the values
520 : * @param json_field_name_ String, field name of the array in JSON strings
521 : * @param struct_field_name_ Field name in the struct containing the array
522 : * @param max_len_ Maximum number of elements in the array
523 : * @param len_field_ Field name in the struct for the number of elements
524 : * in the array
525 : * @param elem_descr_ Element descriptor, pointer to a descriptor array
526 : * @param elem_descr_len_ Number of elements in elem_descr_
527 : *
528 : * Here's an example of use:
529 : *
530 : * struct person_height {
531 : * const char *name;
532 : * int32_t height;
533 : * };
534 : *
535 : * struct people_heights {
536 : * struct person_height heights[10];
537 : * size_t heights_len;
538 : * };
539 : *
540 : * struct json_obj_descr person_height_descr[] = {
541 : * JSON_OBJ_DESCR_PRIM(struct person_height, name, JSON_TOK_STRING),
542 : * JSON_OBJ_DESCR_PRIM(struct person_height, height, JSON_TOK_NUMBER),
543 : * };
544 : *
545 : * struct json_obj_descr array[] = {
546 : * JSON_OBJ_DESCR_OBJ_ARRAY_NAMED(struct people_heights,
547 : * "people-heights", heights,
548 : * 10, heights_len,
549 : * person_height_descr,
550 : * ARRAY_SIZE(person_height_descr)),
551 : * };
552 : */
553 : #define JSON_OBJ_DESCR_OBJ_ARRAY_NAMED(struct_, json_field_name_, \
554 : struct_field_name_, max_len_, \
555 : len_field_, elem_descr_, \
556 1 : elem_descr_len_) \
557 : { \
558 : .field_name = json_field_name_, \
559 : .align_shift = Z_ALIGN_SHIFT(struct_), \
560 : .field_name_len = sizeof(json_field_name_) - 1, \
561 : .type = JSON_TOK_ARRAY_START, \
562 : .offset = offsetof(struct_, struct_field_name_), \
563 : .array = { \
564 : .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \
565 : JSON_TOK_OBJECT_START, \
566 : Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \
567 : .n_elements = (max_len_), \
568 : }, \
569 : }
570 :
571 : /**
572 : * @brief Parses the JSON-encoded object pointed to by @a json, with
573 : * size @a len, according to the descriptor pointed to by @a descr.
574 : * Values are stored in a struct pointed to by @a val. Set up the
575 : * descriptor like this:
576 : *
577 : * struct s { int32_t foo; char *bar; }
578 : * struct json_obj_descr descr[] = {
579 : * JSON_OBJ_DESCR_PRIM(struct s, foo, JSON_TOK_NUMBER),
580 : * JSON_OBJ_DESCR_PRIM(struct s, bar, JSON_TOK_STRING),
581 : * };
582 : *
583 : * Since this parser is designed for machine-to-machine communications, some
584 : * liberties were taken to simplify the design:
585 : * (1) strings are not unescaped (but only valid escape sequences are
586 : * accepted);
587 : * (2) no UTF-8 validation is performed; and
588 : * (3) only integer numbers are supported (no strtod() in the minimal libc).
589 : *
590 : * @param json Pointer to JSON-encoded value to be parsed
591 : * @param len Length of JSON-encoded value
592 : * @param descr Pointer to the descriptor array
593 : * @param descr_len Number of elements in the descriptor array. Must be less
594 : * than 63 due to implementation detail reasons (if more fields are
595 : * necessary, use two descriptors)
596 : * @param val Pointer to the struct to hold the decoded values
597 : *
598 : * @return < 0 if error, bitmap of decoded fields on success (bit 0
599 : * is set if first field in the descriptor has been properly decoded, etc).
600 : */
601 1 : int64_t json_obj_parse(char *json, size_t len,
602 : const struct json_obj_descr *descr, size_t descr_len,
603 : void *val);
604 :
605 : /**
606 : * @brief Parses the JSON-encoded array pointed to by @a json, with
607 : * size @a len, according to the descriptor pointed to by @a descr.
608 : * Values are stored in a struct pointed to by @a val. Set up the
609 : * descriptor like this:
610 : *
611 : * struct s { int32_t foo; char *bar; }
612 : * struct json_obj_descr descr[] = {
613 : * JSON_OBJ_DESCR_PRIM(struct s, foo, JSON_TOK_NUMBER),
614 : * JSON_OBJ_DESCR_PRIM(struct s, bar, JSON_TOK_STRING),
615 : * };
616 : * struct a { struct s baz[10]; size_t count; }
617 : * struct json_obj_descr array[] = {
618 : * JSON_OBJ_DESCR_OBJ_ARRAY(struct a, baz, 10, count,
619 : * descr, ARRAY_SIZE(descr)),
620 : * };
621 : *
622 : * Since this parser is designed for machine-to-machine communications, some
623 : * liberties were taken to simplify the design:
624 : * (1) strings are not unescaped (but only valid escape sequences are
625 : * accepted);
626 : * (2) no UTF-8 validation is performed; and
627 : * (3) only integer numbers are supported (no strtod() in the minimal libc).
628 : *
629 : * @param json Pointer to JSON-encoded array to be parsed
630 : * @param len Length of JSON-encoded array
631 : * @param descr Pointer to the descriptor array
632 : * @param val Pointer to the struct to hold the decoded values
633 : *
634 : * @return 0 if array has been successfully parsed. A negative value
635 : * indicates an error (as defined on errno.h).
636 : */
637 1 : int json_arr_parse(char *json, size_t len,
638 : const struct json_obj_descr *descr, void *val);
639 :
640 : /**
641 : * @brief Initialize single-object array parsing
642 : *
643 : * JSON-encoded array data is going to be parsed one object at a time. Data is provided by
644 : * @a payload with the size of @a len bytes.
645 : *
646 : * Function validate that Json Array start is detected and initialize @a json object for
647 : * Json object parsing separately.
648 : *
649 : * @param json Provide storage for parser states. To be used when parsing the array.
650 : * @param payload Pointer to JSON-encoded array to be parsed
651 : * @param len Length of JSON-encoded array
652 : *
653 : * @return 0 if array start is detected and initialization is successful or negative error
654 : * code in case of failure.
655 : */
656 1 : int json_arr_separate_object_parse_init(struct json_obj *json, char *payload, size_t len);
657 :
658 : /**
659 : * @brief Parse a single object from array.
660 : *
661 : * Parses the JSON-encoded object pointed to by @a json object array, with
662 : * size @a len, according to the descriptor pointed to by @a descr.
663 : *
664 : * @param json Pointer to JSON-object message state
665 : * @param descr Pointer to the descriptor array
666 : * @param descr_len Number of elements in the descriptor array. Must be less than 31.
667 : * @param val Pointer to the struct to hold the decoded values
668 : *
669 : * @return < 0 if error, 0 for end of message, bitmap of decoded fields on success (bit 0
670 : * is set if first field in the descriptor has been properly decoded, etc).
671 : */
672 1 : int json_arr_separate_parse_object(struct json_obj *json, const struct json_obj_descr *descr,
673 : size_t descr_len, void *val);
674 :
675 : /**
676 : * @brief Escapes the string so it can be used to encode JSON objects
677 : *
678 : * @param str The string to escape; the escape string is stored the
679 : * buffer pointed to by this parameter
680 : * @param len Points to a size_t containing the size before and after
681 : * the escaping process
682 : * @param buf_size The size of buffer str points to
683 : *
684 : * @return 0 if string has been escaped properly, or -ENOMEM if there
685 : * was not enough space to escape the buffer
686 : */
687 1 : ssize_t json_escape(char *str, size_t *len, size_t buf_size);
688 :
689 : /**
690 : * @brief Calculates the JSON-escaped string length
691 : *
692 : * @param str The string to analyze
693 : * @param len String size
694 : *
695 : * @return The length str would have if it were escaped
696 : */
697 1 : size_t json_calc_escaped_len(const char *str, size_t len);
698 :
699 : /**
700 : * @brief Calculates the string length to fully encode an object
701 : *
702 : * @param descr Pointer to the descriptor array
703 : * @param descr_len Number of elements in the descriptor array
704 : * @param val Struct holding the values
705 : *
706 : * @return Number of bytes necessary to encode the values if >0,
707 : * an error code is returned.
708 : */
709 1 : ssize_t json_calc_encoded_len(const struct json_obj_descr *descr,
710 : size_t descr_len, const void *val);
711 :
712 : /**
713 : * @brief Calculates the string length to fully encode an array
714 : *
715 : * @param descr Pointer to the descriptor array
716 : * @param val Struct holding the values
717 : *
718 : * @return Number of bytes necessary to encode the values if >0,
719 : * an error code is returned.
720 : */
721 1 : ssize_t json_calc_encoded_arr_len(const struct json_obj_descr *descr,
722 : const void *val);
723 :
724 : /**
725 : * @brief Encodes an object in a contiguous memory location
726 : *
727 : * @param descr Pointer to the descriptor array
728 : * @param descr_len Number of elements in the descriptor array
729 : * @param val Struct holding the values
730 : * @param buffer Buffer to store the JSON data
731 : * @param buf_size Size of buffer, in bytes, with space for the terminating
732 : * NUL character
733 : *
734 : * @return 0 if object has been successfully encoded. A negative value
735 : * indicates an error (as defined on errno.h).
736 : */
737 1 : int json_obj_encode_buf(const struct json_obj_descr *descr, size_t descr_len,
738 : const void *val, char *buffer, size_t buf_size);
739 :
740 : /**
741 : * @brief Encodes an array in a contiguous memory location
742 : *
743 : * @param descr Pointer to the descriptor array
744 : * @param val Struct holding the values
745 : * @param buffer Buffer to store the JSON data
746 : * @param buf_size Size of buffer, in bytes, with space for the terminating
747 : * NUL character
748 : *
749 : * @return 0 if object has been successfully encoded. A negative value
750 : * indicates an error (as defined on errno.h).
751 : */
752 1 : int json_arr_encode_buf(const struct json_obj_descr *descr, const void *val,
753 : char *buffer, size_t buf_size);
754 :
755 : /**
756 : * @brief Encodes an object using an arbitrary writer function
757 : *
758 : * @param descr Pointer to the descriptor array
759 : * @param descr_len Number of elements in the descriptor array
760 : * @param val Struct holding the values
761 : * @param append_bytes Function to append bytes to the output
762 : * @param data Data pointer to be passed to the append_bytes callback
763 : * function.
764 : *
765 : * @return 0 if object has been successfully encoded. A negative value
766 : * indicates an error.
767 : */
768 1 : int json_obj_encode(const struct json_obj_descr *descr, size_t descr_len,
769 : const void *val, json_append_bytes_t append_bytes,
770 : void *data);
771 :
772 : /**
773 : * @brief Encodes an array using an arbitrary writer function
774 : *
775 : * @param descr Pointer to the descriptor array
776 : * @param val Struct holding the values
777 : * @param append_bytes Function to append bytes to the output
778 : * @param data Data pointer to be passed to the append_bytes callback
779 : * function.
780 : *
781 : * @return 0 if object has been successfully encoded. A negative value
782 : * indicates an error.
783 : */
784 1 : int json_arr_encode(const struct json_obj_descr *descr, const void *val,
785 : json_append_bytes_t append_bytes, void *data);
786 :
787 : #ifdef __cplusplus
788 : }
789 : #endif
790 :
791 : /**
792 : * @}
793 : */
794 : #endif /* ZEPHYR_INCLUDE_DATA_JSON_H_ */
|