1 /*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/sys/__assert.h>
8 #include <ctype.h>
9 #include <errno.h>
10 #include <limits.h>
11 #include <zephyr/sys/printk.h>
12 #include <zephyr/sys/util.h>
13 #include <stdbool.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <zephyr/types.h>
17
18 #include <zephyr/data/json.h>
19
20 struct json_obj_key_value {
21 const char *key;
22 size_t key_len;
23 struct json_token value;
24 };
25
lexer_consume(struct json_lexer * lex,struct json_token * tok,enum json_tokens empty_token)26 static bool lexer_consume(struct json_lexer *lex, struct json_token *tok,
27 enum json_tokens empty_token)
28 {
29 if (lex->tok.type == empty_token) {
30 return false;
31 }
32
33 *tok = lex->tok;
34 lex->tok.type = empty_token;
35
36 return true;
37 }
38
lexer_next(struct json_lexer * lex,struct json_token * tok)39 static bool lexer_next(struct json_lexer *lex, struct json_token *tok)
40 {
41 while (lex->state) {
42 if (lexer_consume(lex, tok, JSON_TOK_NONE)) {
43 return true;
44 }
45
46 lex->state = lex->state(lex);
47 }
48
49 return lexer_consume(lex, tok, JSON_TOK_EOF);
50 }
51
52 static void *lexer_json(struct json_lexer *lex);
53
emit(struct json_lexer * lex,enum json_tokens token)54 static void emit(struct json_lexer *lex, enum json_tokens token)
55 {
56 lex->tok.type = token;
57 lex->tok.start = lex->start;
58 lex->tok.end = lex->pos;
59 lex->start = lex->pos;
60 }
61
next(struct json_lexer * lex)62 static int next(struct json_lexer *lex)
63 {
64 if (lex->pos >= lex->end) {
65 lex->pos = lex->end + 1;
66
67 return '\0';
68 }
69
70 return *lex->pos++;
71 }
72
ignore(struct json_lexer * lex)73 static void ignore(struct json_lexer *lex)
74 {
75 lex->start = lex->pos;
76 }
77
backup(struct json_lexer * lex)78 static void backup(struct json_lexer *lex)
79 {
80 lex->pos--;
81 }
82
peek(struct json_lexer * lex)83 static int peek(struct json_lexer *lex)
84 {
85 int chr = next(lex);
86
87 backup(lex);
88
89 return chr;
90 }
91
lexer_string(struct json_lexer * lex)92 static void *lexer_string(struct json_lexer *lex)
93 {
94 ignore(lex);
95
96 while (true) {
97 int chr = next(lex);
98
99 if (chr == '\0') {
100 emit(lex, JSON_TOK_ERROR);
101 return NULL;
102 }
103
104 if (chr == '\\') {
105 switch (next(lex)) {
106 case '"':
107 case '\\':
108 case '/':
109 case 'b':
110 case 'f':
111 case 'n':
112 case 'r':
113 case 't':
114 continue;
115 case 'u':
116 if (isxdigit(next(lex)) == 0) {
117 goto error;
118 }
119
120 if (isxdigit(next(lex)) == 0) {
121 goto error;
122 }
123
124 if (isxdigit(next(lex)) == 0) {
125 goto error;
126 }
127
128 if (isxdigit(next(lex)) == 0) {
129 goto error;
130 }
131
132 break;
133 default:
134 goto error;
135 }
136 }
137
138 if (chr == '"') {
139 backup(lex);
140 emit(lex, JSON_TOK_STRING);
141
142 next(lex);
143 ignore(lex);
144
145 return lexer_json;
146 }
147 }
148
149 error:
150 emit(lex, JSON_TOK_ERROR);
151 return NULL;
152 }
153
accept_run(struct json_lexer * lex,const char * run)154 static int accept_run(struct json_lexer *lex, const char *run)
155 {
156 for (; *run; run++) {
157 if (next(lex) != *run) {
158 return -EINVAL;
159 }
160 }
161
162 return 0;
163 }
164
lexer_boolean(struct json_lexer * lex)165 static void *lexer_boolean(struct json_lexer *lex)
166 {
167 backup(lex);
168
169 switch (next(lex)) {
170 case 't':
171 if (!accept_run(lex, "rue")) {
172 emit(lex, JSON_TOK_TRUE);
173 return lexer_json;
174 }
175 break;
176 case 'f':
177 if (!accept_run(lex, "alse")) {
178 emit(lex, JSON_TOK_FALSE);
179 return lexer_json;
180 }
181 break;
182 }
183
184 emit(lex, JSON_TOK_ERROR);
185 return NULL;
186 }
187
lexer_null(struct json_lexer * lex)188 static void *lexer_null(struct json_lexer *lex)
189 {
190 if (accept_run(lex, "ull") < 0) {
191 emit(lex, JSON_TOK_ERROR);
192 return NULL;
193 }
194
195 emit(lex, JSON_TOK_NULL);
196 return lexer_json;
197 }
198
lexer_number(struct json_lexer * lex)199 static void *lexer_number(struct json_lexer *lex)
200 {
201 while (true) {
202 int chr = next(lex);
203
204 if (isdigit(chr) != 0 || chr == '.') {
205 continue;
206 }
207
208 backup(lex);
209 emit(lex, JSON_TOK_NUMBER);
210
211 return lexer_json;
212 }
213 }
214
lexer_json(struct json_lexer * lex)215 static void *lexer_json(struct json_lexer *lex)
216 {
217 while (true) {
218 int chr = next(lex);
219
220 switch (chr) {
221 case '\0':
222 emit(lex, JSON_TOK_EOF);
223 return NULL;
224 case '}':
225 case '{':
226 case '[':
227 case ']':
228 case ',':
229 case ':':
230 emit(lex, (enum json_tokens)chr);
231 return lexer_json;
232 case '"':
233 return lexer_string;
234 case 'n':
235 return lexer_null;
236 case 't':
237 case 'f':
238 return lexer_boolean;
239 case '-':
240 if (isdigit(peek(lex)) != 0) {
241 return lexer_number;
242 }
243
244 __fallthrough;
245 default:
246 if (isspace(chr) != 0) {
247 ignore(lex);
248 continue;
249 }
250
251 if (isdigit(chr) != 0) {
252 return lexer_number;
253 }
254
255 emit(lex, JSON_TOK_ERROR);
256 return NULL;
257 }
258 }
259 }
260
lexer_init(struct json_lexer * lex,char * data,size_t len)261 static void lexer_init(struct json_lexer *lex, char *data, size_t len)
262 {
263 lex->state = lexer_json;
264 lex->start = data;
265 lex->pos = data;
266 lex->end = data + len;
267 lex->tok.type = JSON_TOK_NONE;
268 }
269
obj_init(struct json_obj * json,char * data,size_t len)270 static int obj_init(struct json_obj *json, char *data, size_t len)
271 {
272 struct json_token tok;
273
274 lexer_init(&json->lex, data, len);
275
276 if (!lexer_next(&json->lex, &tok)) {
277 return -EINVAL;
278 }
279
280 if (tok.type != JSON_TOK_OBJECT_START) {
281 return -EINVAL;
282 }
283
284 return 0;
285 }
286
arr_init(struct json_obj * json,char * data,size_t len)287 static int arr_init(struct json_obj *json, char *data, size_t len)
288 {
289 struct json_token tok;
290
291 lexer_init(&json->lex, data, len);
292
293 if (!lexer_next(&json->lex, &tok)) {
294 return -EINVAL;
295 }
296
297 if (tok.type != JSON_TOK_ARRAY_START) {
298 return -EINVAL;
299 }
300
301 return 0;
302 }
303
element_token(enum json_tokens token)304 static int element_token(enum json_tokens token)
305 {
306 switch (token) {
307 case JSON_TOK_OBJECT_START:
308 case JSON_TOK_ARRAY_START:
309 case JSON_TOK_STRING:
310 case JSON_TOK_NUMBER:
311 case JSON_TOK_FLOAT:
312 case JSON_TOK_OPAQUE:
313 case JSON_TOK_OBJ_ARRAY:
314 case JSON_TOK_TRUE:
315 case JSON_TOK_FALSE:
316 return 0;
317 default:
318 return -EINVAL;
319 }
320 }
321
obj_next(struct json_obj * json,struct json_obj_key_value * kv)322 static int obj_next(struct json_obj *json,
323 struct json_obj_key_value *kv)
324 {
325 struct json_token tok;
326
327 if (!lexer_next(&json->lex, &tok)) {
328 return -EINVAL;
329 }
330
331 /* Match end of object or next key */
332 switch (tok.type) {
333 case JSON_TOK_OBJECT_END:
334 kv->key = NULL;
335 kv->key_len = 0;
336 kv->value = tok;
337
338 return 0;
339 case JSON_TOK_COMMA:
340 if (!lexer_next(&json->lex, &tok)) {
341 return -EINVAL;
342 }
343
344 if (tok.type != JSON_TOK_STRING) {
345 return -EINVAL;
346 }
347
348 __fallthrough;
349 case JSON_TOK_STRING:
350 kv->key = tok.start;
351 kv->key_len = (size_t)(tok.end - tok.start);
352 break;
353 default:
354 return -EINVAL;
355 }
356
357 /* Match : after key */
358 if (!lexer_next(&json->lex, &tok)) {
359 return -EINVAL;
360 }
361
362 if (tok.type != JSON_TOK_COLON) {
363 return -EINVAL;
364 }
365
366 /* Match value */
367 if (!lexer_next(&json->lex, &kv->value)) {
368 return -EINVAL;
369 }
370
371 return element_token(kv->value.type);
372 }
373
arr_next(struct json_obj * json,struct json_token * value)374 static int arr_next(struct json_obj *json, struct json_token *value)
375 {
376 if (!lexer_next(&json->lex, value)) {
377 return -EINVAL;
378 }
379
380 if (value->type == JSON_TOK_ARRAY_END) {
381 return 0;
382 }
383
384 if (value->type == JSON_TOK_COMMA) {
385 if (!lexer_next(&json->lex, value)) {
386 return -EINVAL;
387 }
388 }
389
390 return element_token(value->type);
391 }
392
decode_num(const struct json_token * token,int32_t * num)393 static int decode_num(const struct json_token *token, int32_t *num)
394 {
395 /* FIXME: strtod() is not available in newlib/minimal libc,
396 * so using strtol() here.
397 */
398 char *endptr;
399 char prev_end;
400
401 prev_end = *token->end;
402 *token->end = '\0';
403
404 errno = 0;
405 *num = strtol(token->start, &endptr, 10);
406
407 *token->end = prev_end;
408
409 if (errno != 0) {
410 return -errno;
411 }
412
413 if (endptr != token->end) {
414 return -EINVAL;
415 }
416
417 return 0;
418 }
419
equivalent_types(enum json_tokens type1,enum json_tokens type2)420 static bool equivalent_types(enum json_tokens type1, enum json_tokens type2)
421 {
422 if (type1 == JSON_TOK_TRUE || type1 == JSON_TOK_FALSE) {
423 return type2 == JSON_TOK_TRUE || type2 == JSON_TOK_FALSE;
424 }
425
426 if (type1 == JSON_TOK_NUMBER && type2 == JSON_TOK_FLOAT) {
427 return true;
428 }
429
430 if (type1 == JSON_TOK_STRING && type2 == JSON_TOK_OPAQUE) {
431 return true;
432 }
433
434 if (type1 == JSON_TOK_ARRAY_START && type2 == JSON_TOK_OBJ_ARRAY) {
435 return true;
436 }
437
438 return type1 == type2;
439 }
440
441 static int64_t obj_parse(struct json_obj *obj,
442 const struct json_obj_descr *descr, size_t descr_len,
443 void *val);
444 static int arr_parse(struct json_obj *obj,
445 const struct json_obj_descr *elem_descr,
446 size_t max_elements, void *field, void *val);
447
448 static int arr_data_parse(struct json_obj *obj, struct json_obj_token *val);
449
decode_value(struct json_obj * obj,const struct json_obj_descr * descr,struct json_token * value,void * field,void * val)450 static int64_t decode_value(struct json_obj *obj,
451 const struct json_obj_descr *descr,
452 struct json_token *value, void *field, void *val)
453 {
454
455 if (!equivalent_types(value->type, descr->type)) {
456 return -EINVAL;
457 }
458
459 switch (descr->type) {
460 case JSON_TOK_OBJECT_START:
461 return obj_parse(obj, descr->object.sub_descr,
462 descr->object.sub_descr_len,
463 field);
464 case JSON_TOK_ARRAY_START:
465 return arr_parse(obj, descr->array.element_descr,
466 descr->array.n_elements, field, val);
467 case JSON_TOK_OBJ_ARRAY: {
468 struct json_obj_token *obj_token = field;
469
470 obj_token->start = value->start;
471 return arr_data_parse(obj, obj_token);
472 }
473
474 case JSON_TOK_FALSE:
475 case JSON_TOK_TRUE: {
476 bool *v = field;
477
478 *v = value->type == JSON_TOK_TRUE;
479
480 return 0;
481 }
482 case JSON_TOK_NUMBER: {
483 int32_t *num = field;
484
485 return decode_num(value, num);
486 }
487 case JSON_TOK_OPAQUE:
488 case JSON_TOK_FLOAT: {
489 struct json_obj_token *obj_token = field;
490
491 obj_token->start = value->start;
492 obj_token->length = value->end - value->start;
493 return 0;
494 }
495 case JSON_TOK_STRING: {
496 char **str = field;
497
498 *value->end = '\0';
499 *str = value->start;
500
501 return 0;
502 }
503 default:
504 return -EINVAL;
505 }
506 }
507
get_elem_size(const struct json_obj_descr * descr)508 static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
509 {
510 switch (descr->type) {
511 case JSON_TOK_NUMBER:
512 return sizeof(int32_t);
513 case JSON_TOK_OPAQUE:
514 case JSON_TOK_FLOAT:
515 case JSON_TOK_OBJ_ARRAY:
516 return sizeof(struct json_obj_token);
517 case JSON_TOK_STRING:
518 return sizeof(char *);
519 case JSON_TOK_TRUE:
520 case JSON_TOK_FALSE:
521 return sizeof(bool);
522 case JSON_TOK_ARRAY_START:
523 return descr->array.n_elements * get_elem_size(descr->array.element_descr);
524 case JSON_TOK_OBJECT_START: {
525 ptrdiff_t total = 0;
526 size_t i;
527
528 for (i = 0; i < descr->object.sub_descr_len; i++) {
529 ptrdiff_t s = get_elem_size(&descr->object.sub_descr[i]);
530
531 total += ROUND_UP(s, 1 << descr->align_shift);
532 }
533
534 return total;
535 }
536 default:
537 return -EINVAL;
538 }
539 }
540
arr_parse(struct json_obj * obj,const struct json_obj_descr * elem_descr,size_t max_elements,void * field,void * val)541 static int arr_parse(struct json_obj *obj,
542 const struct json_obj_descr *elem_descr,
543 size_t max_elements, void *field, void *val)
544 {
545 ptrdiff_t elem_size = get_elem_size(elem_descr);
546 void *last_elem = (char *)field + elem_size * max_elements;
547 size_t *elements = NULL;
548 struct json_token value;
549
550 if (val) {
551 elements = (size_t *)((char *)val + elem_descr->offset);
552 }
553
554 __ASSERT_NO_MSG(elem_size > 0);
555
556 if (elements) {
557 *elements = 0;
558 }
559
560 while (!arr_next(obj, &value)) {
561 if (value.type == JSON_TOK_ARRAY_END) {
562 return 0;
563 }
564
565 if (field == last_elem) {
566 return -ENOSPC;
567 }
568
569 if (decode_value(obj, elem_descr, &value, field, NULL) < 0) {
570 return -EINVAL;
571 }
572
573 if (elements) {
574 (*elements)++;
575 }
576 field = (char *)field + elem_size;
577 }
578
579 return -EINVAL;
580 }
581
arr_data_parse(struct json_obj * obj,struct json_obj_token * val)582 static int arr_data_parse(struct json_obj *obj, struct json_obj_token *val)
583 {
584 bool string_state = false;
585 int array_in_array = 1;
586
587 /* Init length to zero */
588 val->length = 0;
589
590 while (obj->lex.pos != obj->lex.end) {
591 if (string_state) {
592 if (*obj->lex.pos == JSON_TOK_STRING) {
593 string_state = false;
594 }
595 } else {
596 if (*obj->lex.pos == JSON_TOK_ARRAY_END) {
597 array_in_array--;
598 if (array_in_array == 0) {
599 /* Set array data length + 1 object end */
600 val->length = obj->lex.pos - val->start + 1;
601 /* Init Lexer that Object Parse can be finished properly */
602 obj->lex.state = lexer_json;
603 /* Move position to before array end */
604 obj->lex.pos--;
605 obj->lex.tok.end = obj->lex.pos;
606 obj->lex.tok.start = val->start;
607 obj->lex.tok.type = JSON_TOK_NONE;
608 return 0;
609 }
610 } else if (*obj->lex.pos == JSON_TOK_STRING) {
611 string_state = true;
612 } else if (*obj->lex.pos == JSON_TOK_ARRAY_START) {
613 /* arrary in array update structure count */
614 array_in_array++;
615 }
616 }
617 obj->lex.pos++;
618 }
619
620 return -EINVAL;
621 }
622
obj_parse(struct json_obj * obj,const struct json_obj_descr * descr,size_t descr_len,void * val)623 static int64_t obj_parse(struct json_obj *obj, const struct json_obj_descr *descr,
624 size_t descr_len, void *val)
625 {
626 struct json_obj_key_value kv;
627 int64_t decoded_fields = 0;
628 size_t i;
629 int ret;
630
631 while (!obj_next(obj, &kv)) {
632 if (kv.value.type == JSON_TOK_OBJECT_END) {
633 return decoded_fields;
634 }
635
636 for (i = 0; i < descr_len; i++) {
637 void *decode_field = (char *)val + descr[i].offset;
638
639 /* Field has been decoded already, skip */
640 if (decoded_fields & ((int64_t)1 << i)) {
641 continue;
642 }
643
644 /* Check if it's the i-th field */
645 if (kv.key_len != descr[i].field_name_len) {
646 continue;
647 }
648
649 if (memcmp(kv.key, descr[i].field_name,
650 descr[i].field_name_len)) {
651 continue;
652 }
653
654 /* Store the decoded value */
655 ret = decode_value(obj, &descr[i], &kv.value,
656 decode_field, val);
657 if (ret < 0) {
658 return ret;
659 }
660
661 decoded_fields |= (int64_t)1<<i;
662 break;
663 }
664 }
665
666 return -EINVAL;
667 }
668
json_obj_parse(char * payload,size_t len,const struct json_obj_descr * descr,size_t descr_len,void * val)669 int64_t json_obj_parse(char *payload, size_t len,
670 const struct json_obj_descr *descr, size_t descr_len,
671 void *val)
672 {
673 struct json_obj obj;
674 int64_t ret;
675
676 __ASSERT_NO_MSG(descr_len < (sizeof(ret) * CHAR_BIT - 1));
677
678 ret = obj_init(&obj, payload, len);
679 if (ret < 0) {
680 return ret;
681 }
682
683 return obj_parse(&obj, descr, descr_len, val);
684 }
685
json_arr_parse(char * payload,size_t len,const struct json_obj_descr * descr,void * val)686 int json_arr_parse(char *payload, size_t len,
687 const struct json_obj_descr *descr, void *val)
688 {
689 struct json_obj arr;
690 int ret;
691
692 ret = arr_init(&arr, payload, len);
693 if (ret < 0) {
694 return ret;
695 }
696
697 void *ptr = (char *)val + descr->offset;
698
699 return arr_parse(&arr, descr->array.element_descr,
700 descr->array.n_elements, ptr, val);
701 }
702
703
json_arr_separate_object_parse_init(struct json_obj * json,char * payload,size_t len)704 int json_arr_separate_object_parse_init(struct json_obj *json, char *payload, size_t len)
705 {
706 return arr_init(json, payload, len);
707 }
708
json_arr_separate_parse_object(struct json_obj * json,const struct json_obj_descr * descr,size_t descr_len,void * val)709 int json_arr_separate_parse_object(struct json_obj *json, const struct json_obj_descr *descr,
710 size_t descr_len, void *val)
711 {
712 struct json_token tok;
713
714 if (!lexer_next(&json->lex, &tok)) {
715 return -EINVAL;
716 }
717
718 if (tok.type == JSON_TOK_ARRAY_END) {
719 return 0;
720 } else if (tok.type == JSON_TOK_COMMA) {
721 if (!lexer_next(&json->lex, &tok)) {
722 return -EINVAL;
723 }
724 }
725
726 if (tok.type != JSON_TOK_OBJECT_START) {
727 return -EINVAL;
728 }
729
730 return obj_parse(json, descr, descr_len, val);
731 }
732
escape_as(char chr)733 static char escape_as(char chr)
734 {
735 switch (chr) {
736 case '"':
737 return '"';
738 case '\\':
739 return '\\';
740 case '\b':
741 return 'b';
742 case '\f':
743 return 'f';
744 case '\n':
745 return 'n';
746 case '\r':
747 return 'r';
748 case '\t':
749 return 't';
750 }
751
752 return 0;
753 }
754
json_escape_internal(const char * str,json_append_bytes_t append_bytes,void * data)755 static int json_escape_internal(const char *str,
756 json_append_bytes_t append_bytes,
757 void *data)
758 {
759 const char *cur;
760 int ret = 0;
761
762 for (cur = str; ret == 0 && *cur; cur++) {
763 char escaped = escape_as(*cur);
764
765 if (escaped) {
766 char bytes[2] = { '\\', escaped };
767
768 ret = append_bytes(bytes, 2, data);
769 } else {
770 ret = append_bytes(cur, 1, data);
771 }
772 }
773
774 return ret;
775 }
776
json_calc_escaped_len(const char * str,size_t len)777 size_t json_calc_escaped_len(const char *str, size_t len)
778 {
779 size_t escaped_len = len;
780 size_t pos;
781
782 for (pos = 0; pos < len; pos++) {
783 if (escape_as(str[pos])) {
784 escaped_len++;
785 }
786 }
787
788 return escaped_len;
789 }
790
json_escape(char * str,size_t * len,size_t buf_size)791 ssize_t json_escape(char *str, size_t *len, size_t buf_size)
792 {
793 char *next; /* Points after next character to escape. */
794 char *dest; /* Points after next place to write escaped character. */
795 size_t escaped_len = json_calc_escaped_len(str, *len);
796
797 if (escaped_len == *len) {
798 /*
799 * If no escape is necessary, there is nothing to do.
800 */
801 return 0;
802 }
803
804 if (escaped_len >= buf_size) {
805 return -ENOMEM;
806 }
807
808 /*
809 * By walking backwards in the buffer from the end positions
810 * of both the original and escaped strings, we avoid using
811 * extra space. Characters in the original string are
812 * overwritten only after they have already been escaped.
813 */
814 str[escaped_len] = '\0';
815 for (next = &str[*len], dest = &str[escaped_len]; next != str;) {
816 char next_c = *(--next);
817 char escape = escape_as(next_c);
818
819 if (escape) {
820 *(--dest) = escape;
821 *(--dest) = '\\';
822 } else {
823 *(--dest) = next_c;
824 }
825 }
826 *len = escaped_len;
827
828 return 0;
829 }
830
831 static int encode(const struct json_obj_descr *descr, const void *val,
832 json_append_bytes_t append_bytes, void *data);
833
arr_encode(const struct json_obj_descr * elem_descr,const void * field,const void * val,json_append_bytes_t append_bytes,void * data)834 static int arr_encode(const struct json_obj_descr *elem_descr,
835 const void *field, const void *val,
836 json_append_bytes_t append_bytes, void *data)
837 {
838 ptrdiff_t elem_size = get_elem_size(elem_descr);
839 /*
840 * NOTE: Since an element descriptor's offset isn't meaningful
841 * (array elements occur at multiple offsets in `val'), we use
842 * its space in elem_descr to store the offset to the field
843 * containing the number of elements.
844 */
845 size_t n_elem = *(size_t *)((char *)val + elem_descr->offset);
846 size_t i;
847 int ret;
848
849 ret = append_bytes("[", 1, data);
850 if (ret < 0) {
851 return ret;
852 }
853
854 for (i = 0; i < n_elem; i++) {
855 /*
856 * Though "field" points at the next element in the
857 * array which we need to encode, the value in
858 * elem_descr->offset is actually the offset of the
859 * length field in the "parent" struct containing the
860 * array.
861 *
862 * To patch things up, we lie to encode() about where
863 * the field is by exactly the amount it will offset
864 * it. This is a size optimization for struct
865 * json_obj_descr: the alternative is to keep a
866 * separate field next to element_descr which is an
867 * offset to the length field in the parent struct,
868 * but that would add a size_t to every descriptor.
869 */
870 ret = encode(elem_descr, (char *)field - elem_descr->offset,
871 append_bytes, data);
872 if (ret < 0) {
873 return ret;
874 }
875
876 if (i < n_elem - 1) {
877 ret = append_bytes(",", 1, data);
878 if (ret < 0) {
879 return ret;
880 }
881 }
882
883 field = (char *)field + elem_size;
884 }
885
886 return append_bytes("]", 1, data);
887 }
888
str_encode(const char ** str,json_append_bytes_t append_bytes,void * data)889 static int str_encode(const char **str, json_append_bytes_t append_bytes,
890 void *data)
891 {
892 int ret;
893
894 ret = append_bytes("\"", 1, data);
895 if (ret < 0) {
896 return ret;
897 }
898
899 ret = json_escape_internal(*str, append_bytes, data);
900 if (!ret) {
901 return append_bytes("\"", 1, data);
902 }
903
904 return ret;
905 }
906
num_encode(const int32_t * num,json_append_bytes_t append_bytes,void * data)907 static int num_encode(const int32_t *num, json_append_bytes_t append_bytes,
908 void *data)
909 {
910 char buf[3 * sizeof(int32_t)];
911 int ret;
912
913 ret = snprintk(buf, sizeof(buf), "%d", *num);
914 if (ret < 0) {
915 return ret;
916 }
917 if (ret >= (int)sizeof(buf)) {
918 return -ENOMEM;
919 }
920
921 return append_bytes(buf, (size_t)ret, data);
922 }
923
float_ascii_encode(struct json_obj_token * num,json_append_bytes_t append_bytes,void * data)924 static int float_ascii_encode(struct json_obj_token *num, json_append_bytes_t append_bytes,
925 void *data)
926 {
927
928 return append_bytes(num->start, num->length, data);
929 }
930
opaque_string_encode(struct json_obj_token * opaque,json_append_bytes_t append_bytes,void * data)931 static int opaque_string_encode(struct json_obj_token *opaque, json_append_bytes_t append_bytes,
932 void *data)
933 {
934 int ret;
935
936 ret = append_bytes("\"", 1, data);
937 if (ret < 0) {
938 return ret;
939 }
940
941 ret = append_bytes(opaque->start, opaque->length, data);
942 if (ret < 0) {
943 return ret;
944 }
945
946 return append_bytes("\"", 1, data);
947 }
948
bool_encode(const bool * value,json_append_bytes_t append_bytes,void * data)949 static int bool_encode(const bool *value, json_append_bytes_t append_bytes,
950 void *data)
951 {
952 if (*value) {
953 return append_bytes("true", 4, data);
954 }
955
956 return append_bytes("false", 5, data);
957 }
958
encode(const struct json_obj_descr * descr,const void * val,json_append_bytes_t append_bytes,void * data)959 static int encode(const struct json_obj_descr *descr, const void *val,
960 json_append_bytes_t append_bytes, void *data)
961 {
962 void *ptr = (char *)val + descr->offset;
963
964 switch (descr->type) {
965 case JSON_TOK_FALSE:
966 case JSON_TOK_TRUE:
967 return bool_encode(ptr, append_bytes, data);
968 case JSON_TOK_STRING:
969 return str_encode(ptr, append_bytes, data);
970 case JSON_TOK_ARRAY_START:
971 return arr_encode(descr->array.element_descr, ptr,
972 val, append_bytes, data);
973 case JSON_TOK_OBJECT_START:
974 return json_obj_encode(descr->object.sub_descr,
975 descr->object.sub_descr_len,
976 ptr, append_bytes, data);
977 case JSON_TOK_NUMBER:
978 return num_encode(ptr, append_bytes, data);
979 case JSON_TOK_FLOAT:
980 return float_ascii_encode(ptr, append_bytes, data);
981 case JSON_TOK_OPAQUE:
982 return opaque_string_encode(ptr, append_bytes, data);
983 default:
984 return -EINVAL;
985 }
986 }
987
json_obj_encode(const struct json_obj_descr * descr,size_t descr_len,const void * val,json_append_bytes_t append_bytes,void * data)988 int json_obj_encode(const struct json_obj_descr *descr, size_t descr_len,
989 const void *val, json_append_bytes_t append_bytes,
990 void *data)
991 {
992 size_t i;
993 int ret;
994
995 ret = append_bytes("{", 1, data);
996 if (ret < 0) {
997 return ret;
998 }
999
1000 for (i = 0; i < descr_len; i++) {
1001 ret = str_encode((const char **)&descr[i].field_name,
1002 append_bytes, data);
1003 if (ret < 0) {
1004 return ret;
1005 }
1006
1007 ret = append_bytes(":", 1, data);
1008 if (ret < 0) {
1009 return ret;
1010 }
1011
1012 ret = encode(&descr[i], val, append_bytes, data);
1013 if (ret < 0) {
1014 return ret;
1015 }
1016
1017 if (i < descr_len - 1) {
1018 ret = append_bytes(",", 1, data);
1019 if (ret < 0) {
1020 return ret;
1021 }
1022 }
1023 }
1024
1025 return append_bytes("}", 1, data);
1026 }
1027
json_arr_encode(const struct json_obj_descr * descr,const void * val,json_append_bytes_t append_bytes,void * data)1028 int json_arr_encode(const struct json_obj_descr *descr, const void *val,
1029 json_append_bytes_t append_bytes, void *data)
1030 {
1031 void *ptr = (char *)val + descr->offset;
1032
1033 return arr_encode(descr->array.element_descr, ptr, val, append_bytes,
1034 data);
1035 }
1036
1037 struct appender {
1038 char *buffer;
1039 size_t used;
1040 size_t size;
1041 };
1042
append_bytes_to_buf(const char * bytes,size_t len,void * data)1043 static int append_bytes_to_buf(const char *bytes, size_t len, void *data)
1044 {
1045 struct appender *appender = data;
1046
1047 if (len >= appender->size - appender->used) {
1048 return -ENOMEM;
1049 }
1050
1051 memcpy(appender->buffer + appender->used, bytes, len);
1052 appender->used += len;
1053 appender->buffer[appender->used] = '\0';
1054
1055 return 0;
1056 }
1057
json_obj_encode_buf(const struct json_obj_descr * descr,size_t descr_len,const void * val,char * buffer,size_t buf_size)1058 int json_obj_encode_buf(const struct json_obj_descr *descr, size_t descr_len,
1059 const void *val, char *buffer, size_t buf_size)
1060 {
1061 struct appender appender = { .buffer = buffer, .size = buf_size };
1062
1063 return json_obj_encode(descr, descr_len, val, append_bytes_to_buf,
1064 &appender);
1065 }
1066
json_arr_encode_buf(const struct json_obj_descr * descr,const void * val,char * buffer,size_t buf_size)1067 int json_arr_encode_buf(const struct json_obj_descr *descr, const void *val,
1068 char *buffer, size_t buf_size)
1069 {
1070 struct appender appender = { .buffer = buffer, .size = buf_size };
1071
1072 return json_arr_encode(descr, val, append_bytes_to_buf, &appender);
1073 }
1074
measure_bytes(const char * bytes,size_t len,void * data)1075 static int measure_bytes(const char *bytes, size_t len, void *data)
1076 {
1077 ssize_t *total = data;
1078
1079 *total += (ssize_t)len;
1080
1081 ARG_UNUSED(bytes);
1082
1083 return 0;
1084 }
1085
json_calc_encoded_len(const struct json_obj_descr * descr,size_t descr_len,const void * val)1086 ssize_t json_calc_encoded_len(const struct json_obj_descr *descr,
1087 size_t descr_len, const void *val)
1088 {
1089 ssize_t total = 0;
1090 int ret;
1091
1092 ret = json_obj_encode(descr, descr_len, val, measure_bytes, &total);
1093 if (ret < 0) {
1094 return ret;
1095 }
1096
1097 return total;
1098 }
1099
json_calc_encoded_arr_len(const struct json_obj_descr * descr,const void * val)1100 ssize_t json_calc_encoded_arr_len(const struct json_obj_descr *descr,
1101 const void *val)
1102 {
1103 ssize_t total = 0;
1104 int ret;
1105
1106 ret = json_arr_encode(descr, val, measure_bytes, &total);
1107 if (ret < 0) {
1108 return ret;
1109 }
1110
1111 return total;
1112 }
1113