]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/basic/json.c
json: add a nice JSON parser
[thirdparty/systemd.git] / src / basic / json.c
CommitLineData
cd0b6c53
LP
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno.h>
4#include <math.h>
5#include <stdarg.h>
6#include <stdio_ext.h>
7#include <stdlib.h>
8#include <string.h>
9#include <sys/types.h>
10
11#include "sd-messages.h"
12
13#include "alloc-util.h"
14#include "fd-util.h"
15#include "fileio.h"
16#include "float.h"
17#include "hexdecoct.h"
18#include "json-internal.h"
19#include "json.h"
20#include "macro.h"
21#include "string-table.h"
22#include "string-util.h"
23#include "strv.h"
24#include "terminal-util.h"
25#include "utf8.h"
26
27typedef struct JsonSource {
28 /* When we parse from a file or similar, encodes the filename, to indicate the source of a json variant */
29 size_t n_ref;
30 unsigned max_line;
31 unsigned max_column;
32 char name[];
33} JsonSource;
34
35/* On x86-64 this whole structure should have a size of 6 * 64 bit = 48 bytes */
36struct JsonVariant {
37 union {
38 /* We either maintain a reference counter for this variant itself, or we are embedded into an
39 * array/object, in which case only that surrounding object is ref-counted. (If 'embedded' is false,
40 * see below.) */
41 size_t n_ref;
42
43 /* If this JsonVariant is part of an array/object, then this field points to the surrounding
44 * JSON_VARIANT_ARRAY/JSON_VARIANT_OBJECT object. (If 'embedded' is true, see below.) */
45 JsonVariant *parent;
46 };
47
48 JsonVariantType type:5;
49
50 /* A marker whether this variant is embedded into in array/object or not. If true, the 'parent' pointer above
51 * is valid. If false, the 'n_ref' field above is valid instead. */
52 bool is_embedded:1;
53
54 /* In some conditions (for example, if this object is part of an array of strings or objects), we don't store
55 * any data inline, but instead simply reference an external object and act as surrogate of it. In that case
56 * this bool is set, and the external object is referenced through the .reference field below. */
57 bool is_reference:1;
58
59 /* While comparing two arrays, we use this for marking what we already have seen */
60 bool is_marked:1;
61
62 /* If this was parsed from some file or buffer, this stores where from, as well as the source line/column */
63 unsigned line, column;
64 JsonSource *source;
65
66 union {
67 /* For simple types we store the value in-line. */
68 JsonValue value;
69
70 /* For objects and arrays we store the number of elements immediately following */
71 size_t n_elements;
72
73 /* If is_reference as indicated above is set, this is where the reference object is actually stored. */
74 JsonVariant *reference;
75
76 /* Strings are placed immediately after the structure. Note that when this is a JsonVariant embedded
77 * into an array we might encode strings up to INLINE_STRING_LENGTH characters directly inside the
78 * element, while longer strings are stored as references. When this object is not embedded into an
79 * array, but stand-alone we allocate the right size for the whole structure, i.e. the array might be
80 * much larger than INLINE_STRING_LENGTH.
81 *
82 * Note that because we want to allocate arrays of the JsonVariant structure we specify [0] here,
83 * rather than the prettier []. If we wouldn't, then this char array would have undefined size, and so
84 * would the union and then the struct this is included in. And of structures with undefined size we
85 * can't allocate arrays (at least not easily). */
86 char string[0];
87 };
88};
89
90/* Inside string arrays we have a series of JasonVariant structures one after the other. In this case, strings longer
91 * than INLINE_STRING_MAX are stored as references, and all shorter ones inline. (This means — on x86-64 — strings up
92 * to 15 chars are stored within the array elements, and all others in separate allocations) */
93#define INLINE_STRING_MAX (sizeof(JsonVariant) - offsetof(JsonVariant, string) - 1U)
94
95/* Let's make sure this structure isn't increased in size accidentally. This check is only for our most relevant arch
96 * (x86-64). */
97#ifdef __x86_64__
98assert_cc(sizeof(JsonVariant) == 48U);
99assert_cc(INLINE_STRING_MAX == 15U);
100#endif
101
102static JsonSource* json_source_new(const char *name) {
103 JsonSource *s;
104
105 assert(name);
106
107 s = malloc(offsetof(JsonSource, name) + strlen(name) + 1);
108 if (!s)
109 return NULL;
110
111 *s = (JsonSource) {
112 .n_ref = 1,
113 };
114 strcpy(s->name, name);
115
116 return s;
117}
118
119DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(JsonSource, json_source, mfree);
120
121static bool json_source_equal(JsonSource *a, JsonSource *b) {
122 if (a == b)
123 return true;
124
125 if (!a || !b)
126 return false;
127
128 return streq(a->name, b->name);
129}
130
131DEFINE_TRIVIAL_CLEANUP_FUNC(JsonSource*, json_source_unref);
132
133static bool json_variant_is_magic(const JsonVariant *v) {
134 return v == JSON_VARIANT_MAGIC_TRUE ||
135 v == JSON_VARIANT_MAGIC_FALSE ||
136 v == JSON_VARIANT_MAGIC_NULL ||
137 v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
138 v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
139 v == JSON_VARIANT_MAGIC_ZERO_REAL ||
140 v == JSON_VARIANT_MAGIC_EMPTY_STRING ||
141 v == JSON_VARIANT_MAGIC_EMPTY_ARRAY ||
142 v == JSON_VARIANT_MAGIC_EMPTY_OBJECT;
143}
144
145static JsonVariant *json_variant_dereference(JsonVariant *v) {
146
147 /* Recursively dereference variants that are references to other variants */
148
149 if (!v)
150 return NULL;
151
152 if (json_variant_is_magic(v))
153 return v;
154
155 if (!v->is_reference)
156 return v;
157
158 return json_variant_dereference(v->reference);
159}
160
161static JsonVariant *json_variant_normalize(JsonVariant *v) {
162
163 /* Converts json variants to their normalized form, i.e. fully dereferenced and wherever possible converted to
164 * the "magic" version if there is one */
165
166 if (!v)
167 return NULL;
168
169 v = json_variant_dereference(v);
170
171 switch (json_variant_type(v)) {
172
173 case JSON_VARIANT_BOOLEAN:
174 return json_variant_boolean(v) ? JSON_VARIANT_MAGIC_TRUE : JSON_VARIANT_MAGIC_FALSE;
175
176 case JSON_VARIANT_NULL:
177 return JSON_VARIANT_MAGIC_NULL;
178
179 case JSON_VARIANT_INTEGER:
180 return json_variant_integer(v) == 0 ? JSON_VARIANT_MAGIC_ZERO_INTEGER : v;
181
182 case JSON_VARIANT_UNSIGNED:
183 return json_variant_unsigned(v) == 0 ? JSON_VARIANT_MAGIC_ZERO_UNSIGNED : v;
184
185 case JSON_VARIANT_REAL:
186#pragma GCC diagnostic push
187#pragma GCC diagnostic ignored "-Wfloat-equal"
188 return json_variant_real(v) == 0.0 ? JSON_VARIANT_MAGIC_ZERO_REAL : v;
189#pragma GCC diagnostic pop
190
191 case JSON_VARIANT_STRING:
192 return isempty(json_variant_string(v)) ? JSON_VARIANT_MAGIC_EMPTY_STRING : v;
193
194 case JSON_VARIANT_ARRAY:
195 return json_variant_elements(v) == 0 ? JSON_VARIANT_MAGIC_EMPTY_ARRAY : v;
196
197 case JSON_VARIANT_OBJECT:
198 return json_variant_elements(v) == 0 ? JSON_VARIANT_MAGIC_EMPTY_OBJECT : v;
199
200 default:
201 return v;
202 }
203}
204
205static JsonVariant *json_variant_conservative_normalize(JsonVariant *v) {
206
207 /* Much like json_variant_normalize(), but won't simplify if the variant has a source/line location attached to
208 * it, in order not to lose context */
209
210 if (!v)
211 return NULL;
212
213 if (json_variant_is_magic(v))
214 return v;
215
216 if (v->source || v->line > 0 || v->column > 0)
217 return v;
218
219 return json_variant_normalize(v);
220}
221
222static int json_variant_new(JsonVariant **ret, JsonVariantType type, size_t space) {
223 JsonVariant *v;
224
225 assert_return(ret, -EINVAL);
226
227 v = malloc0(offsetof(JsonVariant, value) + space);
228 if (!v)
229 return -ENOMEM;
230
231 v->n_ref = 1;
232 v->type = type;
233
234 *ret = v;
235 return 0;
236}
237
238int json_variant_new_integer(JsonVariant **ret, intmax_t i) {
239 JsonVariant *v;
240 int r;
241
242 assert_return(ret, -EINVAL);
243
244 if (i == 0) {
245 *ret = JSON_VARIANT_MAGIC_ZERO_INTEGER;
246 return 0;
247 }
248
249 r = json_variant_new(&v, JSON_VARIANT_INTEGER, sizeof(i));
250 if (r < 0)
251 return r;
252
253 v->value.integer = i;
254 *ret = v;
255
256 return 0;
257}
258
259int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u) {
260 JsonVariant *v;
261 int r;
262
263 assert_return(ret, -EINVAL);
264 if (u == 0) {
265 *ret = JSON_VARIANT_MAGIC_ZERO_UNSIGNED;
266 return 0;
267 }
268
269 r = json_variant_new(&v, JSON_VARIANT_UNSIGNED, sizeof(u));
270 if (r < 0)
271 return r;
272
273 v->value.unsig = u;
274 *ret = v;
275
276 return 0;
277}
278
279int json_variant_new_real(JsonVariant **ret, long double d) {
280 JsonVariant *v;
281 int r;
282
283 assert_return(ret, -EINVAL);
284
285#pragma GCC diagnostic push
286#pragma GCC diagnostic ignored "-Wfloat-equal"
287 if (d == 0.0) {
288#pragma GCC diagnostic pop
289 *ret = JSON_VARIANT_MAGIC_ZERO_REAL;
290 return 0;
291 }
292
293 r = json_variant_new(&v, JSON_VARIANT_REAL, sizeof(d));
294 if (r < 0)
295 return r;
296
297 v->value.real = d;
298 *ret = v;
299
300 return 0;
301}
302
303int json_variant_new_boolean(JsonVariant **ret, bool b) {
304 assert_return(ret, -EINVAL);
305
306 if (b)
307 *ret = JSON_VARIANT_MAGIC_TRUE;
308 else
309 *ret = JSON_VARIANT_MAGIC_FALSE;
310
311 return 0;
312}
313
314int json_variant_new_null(JsonVariant **ret) {
315 assert_return(ret, -EINVAL);
316
317 *ret = JSON_VARIANT_MAGIC_NULL;
318 return 0;
319}
320
321int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n) {
322 JsonVariant *v;
323 int r;
324
325 assert_return(ret, -EINVAL);
326 if (!s) {
327 assert_return(n == 0, -EINVAL);
328 return json_variant_new_null(ret);
329 }
330 if (n == 0) {
331 *ret = JSON_VARIANT_MAGIC_EMPTY_STRING;
332 return 0;
333 }
334
335 r = json_variant_new(&v, JSON_VARIANT_STRING, n + 1);
336 if (r < 0)
337 return r;
338
339 memcpy(v->string, s, n);
340 v->string[n] = 0;
341
342 *ret = v;
343 return 0;
344}
345
346static void json_variant_set(JsonVariant *a, JsonVariant *b) {
347 assert(a);
348
349 b = json_variant_dereference(b);
350 if (!b) {
351 a->type = JSON_VARIANT_NULL;
352 return;
353 }
354
355 a->type = json_variant_type(b);
356 switch (a->type) {
357
358 case JSON_VARIANT_INTEGER:
359 a->value.integer = json_variant_integer(b);
360 break;
361
362 case JSON_VARIANT_UNSIGNED:
363 a->value.unsig = json_variant_unsigned(b);
364 break;
365
366 case JSON_VARIANT_REAL:
367 a->value.real = json_variant_real(b);
368 break;
369
370 case JSON_VARIANT_BOOLEAN:
371 a->value.boolean = json_variant_boolean(b);
372 break;
373
374 case JSON_VARIANT_STRING: {
375 const char *s;
376
377 assert_se(s = json_variant_string(b));
378
379 /* Short strings we can store inline */
380 if (strnlen(s, INLINE_STRING_MAX+1) <= INLINE_STRING_MAX) {
381 strcpy(a->string, s);
382 break;
383 }
384
385 /* For longer strings, use a reference… */
386 _fallthrough_;
387 }
388
389 case JSON_VARIANT_ARRAY:
390 case JSON_VARIANT_OBJECT:
391 a->is_reference = true;
392 a->reference = json_variant_ref(json_variant_conservative_normalize(b));
393 break;
394
395 case JSON_VARIANT_NULL:
396 break;
397
398 default:
399 assert_not_reached("Unexpected variant type");
400 }
401}
402
403static void json_variant_copy_source(JsonVariant *v, JsonVariant *from) {
404 assert(v);
405 assert(from);
406
407 if (json_variant_is_magic(from))
408 return;
409
410 v->line = from->line;
411 v->column = from->column;
412 v->source = json_source_ref(from->source);
413}
414
415int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n) {
416 JsonVariant *v;
417 size_t i;
418
419 assert_return(ret, -EINVAL);
420 if (n == 0) {
421 *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY;
422 return 0;
423 }
424 assert_return(array, -EINVAL);
425
426 v = new(JsonVariant, n + 1);
427 if (!v)
428 return -ENOMEM;
429
430 *v = (JsonVariant) {
431 .n_ref = 1,
432 .type = JSON_VARIANT_ARRAY,
433 .n_elements = n,
434 };
435
436 for (i = 0; i < n; i++) {
437 JsonVariant *w = v + 1 + i;
438
439 *w = (JsonVariant) {
440 .is_embedded = true,
441 .parent = v,
442 };
443
444 json_variant_set(w, array[i]);
445 json_variant_copy_source(w, array[i]);
446 }
447
448 *ret = v;
449 return 0;
450}
451
452int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n) {
453 JsonVariant *v;
454 size_t i;
455
456 assert_return(ret, -EINVAL);
457 if (n == 0) {
458 *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY;
459 return 0;
460 }
461 assert_return(p, -EINVAL);
462
463 v = new(JsonVariant, n + 1);
464 if (!v)
465 return -ENOMEM;
466
467 *v = (JsonVariant) {
468 .n_ref = 1,
469 .type = JSON_VARIANT_ARRAY,
470 .n_elements = n,
471 };
472
473 for (i = 0; i < n; i++) {
474 JsonVariant *w = v + 1 + i;
475
476 *w = (JsonVariant) {
477 .is_embedded = true,
478 .parent = v,
479 };
480
481 w->type = JSON_VARIANT_UNSIGNED;
482 w->value.unsig = ((const uint8_t*) p)[i];
483 }
484
485 *ret = v;
486 return 0;
487}
488
489int json_variant_new_array_strv(JsonVariant **ret, char **l) {
490 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
491 size_t n;
492 int r;
493
494 assert(ret);
495
496 n = strv_length(l);
497 if (n == 0) {
498 *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY;
499 return 0;
500 }
501
502 v = new0(JsonVariant, n + 1);
503 if (!v)
504 return -ENOMEM;
505
506 *v = (JsonVariant) {
507 .n_ref = 1,
508 .type = JSON_VARIANT_ARRAY,
509 };
510
511 for (v->n_elements = 0; v->n_elements < n; v->n_elements++) {
512 JsonVariant *w = v + 1 + v->n_elements;
513 size_t k;
514
515 w->is_embedded = true;
516 w->parent = v;
517 w->type = JSON_VARIANT_STRING;
518
519 k = strlen(l[v->n_elements]);
520
521 if (k > INLINE_STRING_MAX) {
522 /* If string is too long, store it as reference. */
523
524 r = json_variant_new_stringn(&w->reference, l[v->n_elements], k);
525 if (r < 0)
526 return r;
527
528 w->is_reference = true;
529 } else
530 memcpy(w->string, l[v->n_elements], k+1);
531 }
532
533 *ret = TAKE_PTR(v);
534 return 0;
535}
536
537int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n) {
538 JsonVariant *v;
539 size_t i;
540
541 assert_return(ret, -EINVAL);
542 if (n == 0) {
543 *ret = JSON_VARIANT_MAGIC_EMPTY_OBJECT;
544 return 0;
545 }
546 assert_return(array, -EINVAL);
547 assert_return(n % 2 == 0, -EINVAL);
548
549 v = new(JsonVariant, n + 1);
550 if (!v)
551 return -ENOMEM;
552
553 *v = (JsonVariant) {
554 .n_ref = 1,
555 .type = JSON_VARIANT_OBJECT,
556 .n_elements = n,
557 };
558
559 for (i = 0; i < n; i++) {
560 JsonVariant *w = v + 1 + i;
561
562 *w = (JsonVariant) {
563 .is_embedded = true,
564 .parent = v,
565 };
566
567 json_variant_set(w, array[i]);
568 json_variant_copy_source(w, array[i]);
569 }
570
571 *ret = v;
572 return 0;
573}
574
575static void json_variant_free_inner(JsonVariant *v) {
576 assert(v);
577
578 if (json_variant_is_magic(v))
579 return;
580
581 json_source_unref(v->source);
582
583 if (v->is_reference) {
584 json_variant_unref(v->reference);
585 return;
586 }
587
588 if (IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT)) {
589 size_t i;
590
591 for (i = 0; i < v->n_elements; i++)
592 json_variant_free_inner(v + 1 + i);
593 }
594}
595
596JsonVariant *json_variant_ref(JsonVariant *v) {
597 if (!v)
598 return NULL;
599 if (json_variant_is_magic(v))
600 return v;
601
602 if (v->is_embedded)
603 json_variant_ref(v->parent); /* ref the compounding variant instead */
604 else {
605 assert(v->n_ref > 0);
606 v->n_ref++;
607 }
608
609 return v;
610}
611
612JsonVariant *json_variant_unref(JsonVariant *v) {
613 if (!v)
614 return NULL;
615 if (json_variant_is_magic(v))
616 return NULL;
617
618 if (v->is_embedded)
619 json_variant_unref(v->parent);
620 else {
621 assert(v->n_ref > 0);
622 v->n_ref--;
623
624 if (v->n_ref == 0) {
625 json_variant_free_inner(v);
626 free(v);
627 }
628 }
629
630 return NULL;
631}
632
633void json_variant_unref_many(JsonVariant **array, size_t n) {
634 size_t i;
635
636 assert(array || n == 0);
637
638 for (i = 0; i < n; i++)
639 json_variant_unref(array[i]);
640}
641
642const char *json_variant_string(JsonVariant *v) {
643 if (!v)
644 return NULL;
645 if (v == JSON_VARIANT_MAGIC_EMPTY_STRING)
646 return "";
647 if (json_variant_is_magic(v))
648 goto mismatch;
649 if (v->is_reference)
650 return json_variant_string(v->reference);
651 if (v->type != JSON_VARIANT_STRING)
652 goto mismatch;
653
654 return v->string;
655
656mismatch:
657 log_debug("Non-string JSON variant requested as string, returning NULL.");
658 return NULL;
659}
660
661bool json_variant_boolean(JsonVariant *v) {
662 if (!v)
663 goto mismatch;
664 if (v == JSON_VARIANT_MAGIC_TRUE)
665 return true;
666 if (v == JSON_VARIANT_MAGIC_FALSE)
667 return false;
668 if (json_variant_is_magic(v))
669 goto mismatch;
670 if (v->type != JSON_VARIANT_BOOLEAN)
671 goto mismatch;
672 if (v->is_reference)
673 return json_variant_boolean(v->reference);
674
675 return v->value.boolean;
676
677mismatch:
678 log_debug("Non-boolean JSON variant requested as boolean, returning false.");
679 return false;
680}
681
682intmax_t json_variant_integer(JsonVariant *v) {
683 if (!v)
684 goto mismatch;
685 if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
686 v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
687 v == JSON_VARIANT_MAGIC_ZERO_REAL)
688 return 0;
689 if (json_variant_is_magic(v))
690 goto mismatch;
691 if (v->is_reference)
692 return json_variant_integer(v->reference);
693
694 switch (v->type) {
695
696 case JSON_VARIANT_INTEGER:
697 return v->value.integer;
698
699 case JSON_VARIANT_UNSIGNED:
700 if (v->value.unsig <= INTMAX_MAX)
701 return (intmax_t) v->value.unsig;
702
703 log_debug("Unsigned integer %ju requested as signed integer and out of range, returning 0.", v->value.unsig);
704 return 0;
705
706 case JSON_VARIANT_REAL: {
707 intmax_t converted;
708
709 converted = (intmax_t) v->value.real;
710
711#pragma GCC diagnostic push
712#pragma GCC diagnostic ignored "-Wfloat-equal"
713 if ((long double) converted == v->value.real)
714#pragma GCC diagnostic pop
715 return converted;
716
717 log_debug("Real %Lg requested as integer, and cannot be converted losslessly, returning 0.", v->value.real);
718 return 0;
719 }
720
721 default:
722 break;
723 }
724
725mismatch:
726 log_debug("Non-integer JSON variant requested as integer, returning 0.");
727 return 0;
728}
729
730uintmax_t json_variant_unsigned(JsonVariant *v) {
731 if (!v)
732 goto mismatch;
733 if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
734 v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
735 v == JSON_VARIANT_MAGIC_ZERO_REAL)
736 return 0;
737 if (json_variant_is_magic(v))
738 goto mismatch;
739 if (v->is_reference)
740 return json_variant_integer(v->reference);
741
742 switch (v->type) {
743
744 case JSON_VARIANT_INTEGER:
745 if (v->value.integer >= 0)
746 return (uintmax_t) v->value.integer;
747
748 log_debug("Signed integer %ju requested as unsigned integer and out of range, returning 0.", v->value.integer);
749 return 0;
750
751 case JSON_VARIANT_UNSIGNED:
752 return v->value.unsig;
753
754 case JSON_VARIANT_REAL: {
755 uintmax_t converted;
756
757 converted = (uintmax_t) v->value.real;
758
759#pragma GCC diagnostic push
760#pragma GCC diagnostic ignored "-Wfloat-equal"
761 if ((long double) converted == v->value.real)
762#pragma GCC diagnostic pop
763 return converted;
764
765 log_debug("Real %Lg requested as unsigned integer, and cannot be converted losslessly, returning 0.", v->value.real);
766 return 0;
767 }
768
769 default:
770 break;
771 }
772
773mismatch:
774 log_debug("Non-integer JSON variant requested as unsigned, returning 0.");
775 return 0;
776}
777
778long double json_variant_real(JsonVariant *v) {
779 if (!v)
780 return 0.0;
781 if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
782 v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
783 v == JSON_VARIANT_MAGIC_ZERO_REAL)
784 return 0.0;
785 if (json_variant_is_magic(v))
786 goto mismatch;
787 if (v->is_reference)
788 return json_variant_real(v->reference);
789
790 switch (v->type) {
791
792 case JSON_VARIANT_REAL:
793 return v->value.real;
794
795 case JSON_VARIANT_INTEGER: {
796 long double converted;
797
798 converted = (long double) v->value.integer;
799
800 if ((intmax_t) converted == v->value.integer)
801 return converted;
802
803 log_debug("Signed integer %ji requested as real, and cannot be converted losslessly, returning 0.", v->value.integer);
804 return 0.0;
805 }
806
807 case JSON_VARIANT_UNSIGNED: {
808 long double converted;
809
810 converted = (long double) v->value.unsig;
811
812 if ((uintmax_t) converted == v->value.unsig)
813 return converted;
814
815 log_debug("Unsigned integer %ju requested as real, and cannot be converted losslessly, returning 0.", v->value.unsig);
816 return 0.0;
817 }
818
819 default:
820 break;
821 }
822
823mismatch:
824 log_debug("Non-integer JSON variant requested as integer, returning 0.");
825 return 0;
826}
827
828bool json_variant_is_negative(JsonVariant *v) {
829 if (!v)
830 goto mismatch;
831 if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
832 v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
833 v == JSON_VARIANT_MAGIC_ZERO_REAL)
834 return false;
835 if (json_variant_is_magic(v))
836 goto mismatch;
837 if (v->is_reference)
838 return json_variant_is_negative(v->reference);
839
840 /* This function is useful as checking whether numbers are negative is pretty complex since we have three types
841 * of numbers. And some JSON code (OCI for example) uses negative numbers to mark "not defined" numeric
842 * values. */
843
844 switch (v->type) {
845
846 case JSON_VARIANT_REAL:
847 return v->value.real < 0;
848
849 case JSON_VARIANT_INTEGER:
850 return v->value.integer < 0;
851
852 case JSON_VARIANT_UNSIGNED:
853 return false;
854
855 default:
856 break;
857 }
858
859mismatch:
860 log_debug("Non-integer JSON variant tested for negativity, returning false.");
861 return false;
862}
863
864JsonVariantType json_variant_type(JsonVariant *v) {
865
866 if (!v)
867 return _JSON_VARIANT_TYPE_INVALID;
868
869 if (v == JSON_VARIANT_MAGIC_TRUE || v == JSON_VARIANT_MAGIC_FALSE)
870 return JSON_VARIANT_BOOLEAN;
871
872 if (v == JSON_VARIANT_MAGIC_NULL)
873 return JSON_VARIANT_NULL;
874
875 if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER)
876 return JSON_VARIANT_INTEGER;
877
878 if (v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED)
879 return JSON_VARIANT_UNSIGNED;
880
881 if (v == JSON_VARIANT_MAGIC_ZERO_REAL)
882 return JSON_VARIANT_REAL;
883
884 if (v == JSON_VARIANT_MAGIC_EMPTY_STRING)
885 return JSON_VARIANT_STRING;
886
887 if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY)
888 return JSON_VARIANT_ARRAY;
889
890 if (v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
891 return JSON_VARIANT_OBJECT;
892
893 return v->type;
894}
895
896bool json_variant_has_type(JsonVariant *v, JsonVariantType type) {
897 JsonVariantType rt;
898
899 v = json_variant_dereference(v);
900
901 rt = json_variant_type(v);
902 if (rt == type)
903 return true;
904
905 /* All three magic zeroes qualify as integer, unsigned and as real */
906 if ((v == JSON_VARIANT_MAGIC_ZERO_INTEGER || v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || v == JSON_VARIANT_MAGIC_ZERO_REAL) &&
907 IN_SET(type, JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL, JSON_VARIANT_NUMBER))
908 return true;
909
910 /* All other magic variant types are only equal to themselves */
911 if (json_variant_is_magic(v))
912 return false;
913
914 /* Handle the "number" pseudo type */
915 if (type == JSON_VARIANT_NUMBER)
916 return IN_SET(rt, JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL);
917
918 /* Integer conversions are OK in many cases */
919 if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_UNSIGNED)
920 return v->value.integer >= 0;
921 if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_INTEGER)
922 return v->value.unsig <= INTMAX_MAX;
923
924 /* Any integer that can be converted lossley to a real and back may also be considered a real */
925 if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_REAL)
926 return (intmax_t) (long double) v->value.integer == v->value.integer;
927 if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_REAL)
928 return (uintmax_t) (long double) v->value.unsig == v->value.unsig;
929
930#pragma GCC diagnostic push
931#pragma GCC diagnostic ignored "-Wfloat-equal"
932 /* Any real that can be converted losslessly to an integer and back may also be considered an integer */
933 if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_INTEGER)
934 return (long double) (intmax_t) v->value.real == v->value.real;
935 if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_UNSIGNED)
936 return (long double) (uintmax_t) v->value.real == v->value.real;
937#pragma GCC diagnostic pop
938
939 return false;
940}
941
942size_t json_variant_elements(JsonVariant *v) {
943 if (!v)
944 return 0;
945 if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY ||
946 v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
947 return 0;
948 if (json_variant_is_magic(v))
949 goto mismatch;
950 if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT))
951 goto mismatch;
952 if (v->is_reference)
953 return json_variant_elements(v->reference);
954
955 return v->n_elements;
956
957mismatch:
958 log_debug("Number of elements in non-array/non-object JSON variant requested, returning 0.");
959 return 0;
960}
961
962JsonVariant *json_variant_by_index(JsonVariant *v, size_t idx) {
963 if (!v)
964 return NULL;
965 if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY ||
966 v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
967 return NULL;
968 if (json_variant_is_magic(v))
969 goto mismatch;
970 if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT))
971 goto mismatch;
972 if (v->is_reference)
973 return json_variant_by_index(v->reference, idx);
974 if (idx >= v->n_elements)
975 return NULL;
976
977 return json_variant_conservative_normalize(v + 1 + idx);
978
979mismatch:
980 log_debug("Element in non-array/non-object JSON variant requested by index, returning NULL.");
981 return NULL;
982}
983
984JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key) {
985 size_t i;
986
987 if (!v)
988 goto not_found;
989 if (!key)
990 goto not_found;
991 if (v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
992 goto not_found;
993 if (json_variant_is_magic(v))
994 goto mismatch;
995 if (v->type != JSON_VARIANT_OBJECT)
996 goto mismatch;
997 if (v->is_reference)
998 return json_variant_by_key(v->reference, key);
999
1000 for (i = 0; i < v->n_elements; i += 2) {
1001 JsonVariant *p;
1002
1003 p = json_variant_dereference(v + 1 + i);
1004
1005 if (!json_variant_has_type(p, JSON_VARIANT_STRING))
1006 continue;
1007
1008 if (streq(json_variant_string(p), key)) {
1009
1010 if (ret_key)
1011 *ret_key = json_variant_conservative_normalize(v + 1 + i);
1012
1013 return json_variant_conservative_normalize(v + 1 + i + 1);
1014 }
1015 }
1016
1017not_found:
1018 if (ret_key)
1019 *ret_key = NULL;
1020
1021 return NULL;
1022
1023mismatch:
1024 log_debug("Element in non-object JSON variant requested by key, returning NULL.");
1025 if (ret_key)
1026 *ret_key = NULL;
1027
1028 return NULL;
1029}
1030
1031JsonVariant *json_variant_by_key(JsonVariant *v, const char *key) {
1032 return json_variant_by_key_full(v, key, NULL);
1033}
1034
1035bool json_variant_equal(JsonVariant *a, JsonVariant *b) {
1036 JsonVariantType t;
1037
1038 a = json_variant_normalize(a);
1039 b = json_variant_normalize(b);
1040
1041 if (a == b)
1042 return true;
1043
1044 t = json_variant_type(a);
1045 if (!json_variant_has_type(b, t))
1046 return false;
1047
1048 switch (t) {
1049
1050 case JSON_VARIANT_STRING:
1051 return streq(json_variant_string(a), json_variant_string(b));
1052
1053 case JSON_VARIANT_INTEGER:
1054 return json_variant_integer(a) == json_variant_integer(b);
1055
1056 case JSON_VARIANT_UNSIGNED:
1057 return json_variant_unsigned(a) == json_variant_unsigned(b);
1058
1059 case JSON_VARIANT_REAL:
1060#pragma GCC diagnostic push
1061#pragma GCC diagnostic ignored "-Wfloat-equal"
1062 return json_variant_real(a) == json_variant_real(b);
1063#pragma GCC diagnostic pop
1064
1065 case JSON_VARIANT_BOOLEAN:
1066 return json_variant_boolean(a) == json_variant_boolean(b);
1067
1068 case JSON_VARIANT_NULL:
1069 return true;
1070
1071 case JSON_VARIANT_ARRAY: {
1072 size_t i, n;
1073
1074 n = json_variant_elements(a);
1075 if (n != json_variant_elements(b))
1076 return false;
1077
1078 for (i = 0; i < n; i++) {
1079 if (!json_variant_equal(json_variant_by_index(a, i), json_variant_by_index(b, i)))
1080 return false;
1081 }
1082
1083 return true;
1084 }
1085
1086 case JSON_VARIANT_OBJECT: {
1087 size_t i, n;
1088
1089 n = json_variant_elements(a);
1090 if (n != json_variant_elements(b))
1091 return false;
1092
1093 /* Iterate through all keys in 'a' */
1094 for (i = 0; i < n; i += 2) {
1095 bool found = false;
1096 size_t j;
1097
1098 /* Match them against all keys in 'b' */
1099 for (j = 0; j < n; j += 2) {
1100 JsonVariant *key_b;
1101
1102 key_b = json_variant_by_index(b, j);
1103
1104 /* During the first iteration unmark everything */
1105 if (i == 0)
1106 key_b->is_marked = false;
1107 else if (key_b->is_marked) /* In later iterations if we already marked something, don't bother with it again */
1108 continue;
1109
1110 if (found)
1111 continue;
1112
1113 if (json_variant_equal(json_variant_by_index(a, i), key_b) &&
1114 json_variant_equal(json_variant_by_index(a, i+1), json_variant_by_index(b, j+1))) {
1115 /* Key and values match! */
1116 key_b->is_marked = found = true;
1117
1118 /* In the first iteration we continue the inner loop since we want to mark
1119 * everything, otherwise exit the loop quickly after we found what we were
1120 * looking for. */
1121 if (i != 0)
1122 break;
1123 }
1124 }
1125
1126 if (!found)
1127 return false;
1128 }
1129
1130 return true;
1131 }
1132
1133 default:
1134 assert_not_reached("Unknown variant type.");
1135 }
1136}
1137
1138int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column) {
1139 assert_return(v, -EINVAL);
1140
1141 if (ret_source)
1142 *ret_source = json_variant_is_magic(v) || !v->source ? NULL : v->source->name;
1143
1144 if (ret_line)
1145 *ret_line = json_variant_is_magic(v) ? 0 : v->line;
1146
1147 if (ret_column)
1148 *ret_column = json_variant_is_magic(v) ? 0 : v->column;
1149
1150 return 0;
1151}
1152
1153static int print_source(FILE *f, JsonVariant *v, unsigned flags, bool whitespace) {
1154 size_t w, k;
1155
1156 if (!FLAGS_SET(flags, JSON_FORMAT_SOURCE|JSON_FORMAT_PRETTY))
1157 return 0;
1158
1159 if (json_variant_is_magic(v))
1160 return 0;
1161
1162 if (!v->source && v->line == 0 && v->column == 0)
1163 return 0;
1164
1165 /* The max width we need to format the line numbers for this source file */
1166 w = (v->source && v->source->max_line > 0) ?
1167 DECIMAL_STR_WIDTH(v->source->max_line) :
1168 DECIMAL_STR_MAX(unsigned)-1;
1169 k = (v->source && v->source->max_column > 0) ?
1170 DECIMAL_STR_WIDTH(v->source->max_column) :
1171 DECIMAL_STR_MAX(unsigned) -1;
1172
1173 if (whitespace) {
1174 size_t i, n;
1175
1176 n = 1 + (v->source ? strlen(v->source->name) : 0) +
1177 ((v->source && (v->line > 0 || v->column > 0)) ? 1 : 0) +
1178 (v->line > 0 ? w : 0) +
1179 (((v->source || v->line > 0) && v->column > 0) ? 1 : 0) +
1180 (v->column > 0 ? k : 0) +
1181 2;
1182
1183 for (i = 0; i < n; i++)
1184 fputc(' ', f);
1185 } else {
1186 fputc('[', f);
1187
1188 if (v->source)
1189 fputs(v->source->name, f);
1190 if (v->source && (v->line > 0 || v->column > 0))
1191 fputc(':', f);
1192 if (v->line > 0)
1193 fprintf(f, "%*u", (int) w, v->line);
1194 if ((v->source || v->line > 0) || v->column > 0)
1195 fputc(':', f);
1196 if (v->column > 0)
1197 fprintf(f, "%*u", (int) k, v->column);
1198
1199 fputc(']', f);
1200 fputc(' ', f);
1201 }
1202
1203 return 0;
1204}
1205
1206static int json_format(FILE *f, JsonVariant *v, unsigned flags, const char *prefix) {
1207 int r;
1208
1209 assert(f);
1210 assert(v);
1211
1212 switch (json_variant_type(v)) {
1213
1214 case JSON_VARIANT_REAL: {
1215 locale_t loc;
1216
1217 loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
1218 if (loc == (locale_t) 0)
1219 return -errno;
1220
1221 if (flags & JSON_FORMAT_COLOR)
1222 fputs(ANSI_HIGHLIGHT_BLUE, f);
1223
1224 fprintf(f, "%.*Le", DECIMAL_DIG, json_variant_real(v));
1225
1226 if (flags & JSON_FORMAT_COLOR)
1227 fputs(ANSI_NORMAL, f);
1228
1229 freelocale(loc);
1230 break;
1231 }
1232
1233 case JSON_VARIANT_INTEGER:
1234 if (flags & JSON_FORMAT_COLOR)
1235 fputs(ANSI_HIGHLIGHT_BLUE, f);
1236
1237 fprintf(f, "%" PRIdMAX, json_variant_integer(v));
1238
1239 if (flags & JSON_FORMAT_COLOR)
1240 fputs(ANSI_NORMAL, f);
1241 break;
1242
1243 case JSON_VARIANT_UNSIGNED:
1244 if (flags & JSON_FORMAT_COLOR)
1245 fputs(ANSI_HIGHLIGHT_BLUE, f);
1246
1247 fprintf(f, "%" PRIuMAX, json_variant_unsigned(v));
1248
1249 if (flags & JSON_FORMAT_COLOR)
1250 fputs(ANSI_NORMAL, f);
1251 break;
1252
1253 case JSON_VARIANT_BOOLEAN:
1254
1255 if (flags & JSON_FORMAT_COLOR)
1256 fputs(ANSI_HIGHLIGHT, f);
1257
1258 if (json_variant_boolean(v))
1259 fputs("true", f);
1260 else
1261 fputs("false", f);
1262
1263 if (flags & JSON_FORMAT_COLOR)
1264 fputs(ANSI_NORMAL, f);
1265
1266 break;
1267
1268 case JSON_VARIANT_NULL:
1269 if (flags & JSON_FORMAT_COLOR)
1270 fputs(ANSI_HIGHLIGHT, f);
1271
1272 fputs("null", f);
1273
1274 if (flags & JSON_FORMAT_COLOR)
1275 fputs(ANSI_NORMAL, f);
1276 break;
1277
1278 case JSON_VARIANT_STRING: {
1279 const char *q;
1280
1281 fputc('"', f);
1282
1283 if (flags & JSON_FORMAT_COLOR)
1284 fputs(ANSI_GREEN, f);
1285
1286 for (q = json_variant_string(v); *q; q++) {
1287
1288 switch (*q) {
1289
1290 case '"':
1291 fputs("\\\"", f);
1292 break;
1293
1294 case '\\':
1295 fputs("\\\\", f);
1296 break;
1297
1298 case '/':
1299 fputs("\\/", f);
1300 break;
1301
1302 case '\b':
1303 fputs("\\b", f);
1304 break;
1305
1306 case '\f':
1307 fputs("\\f", f);
1308 break;
1309
1310 case '\n':
1311 fputs("\\n", f);
1312 break;
1313
1314 case '\r':
1315 fputs("\\r", f);
1316 break;
1317
1318 case '\t':
1319 fputs("\\t", f);
1320 break;
1321
1322 default:
1323 if (*q >= 0 && *q < ' ')
1324 fprintf(f, "\\u%04x", *q);
1325 else
1326 fputc(*q, f);
1327 break;
1328 }
1329 }
1330
1331 if (flags & JSON_FORMAT_COLOR)
1332 fputs(ANSI_NORMAL, f);
1333
1334 fputc('"', f);
1335 break;
1336 }
1337
1338 case JSON_VARIANT_ARRAY: {
1339 size_t i, n;
1340
1341 n = json_variant_elements(v);
1342
1343 if (n == 0)
1344 fputs("[]", f);
1345 else {
1346 const char *prefix2;
1347
1348 if (flags & JSON_FORMAT_PRETTY) {
1349 prefix2 = strjoina(strempty(prefix), "\t");
1350 fputs("[\n", f);
1351 } else {
1352 prefix2 = strempty(prefix);
1353 fputc('[', f);
1354 }
1355
1356 for (i = 0; i < n; i++) {
1357 JsonVariant *e;
1358
1359 assert_se(e = json_variant_by_index(v, i));
1360
1361 if (i > 0) {
1362 if (flags & JSON_FORMAT_PRETTY)
1363 fputs(",\n", f);
1364 else
1365 fputc(',', f);
1366 }
1367
1368 if (flags & JSON_FORMAT_PRETTY) {
1369 print_source(f, e, flags, false);
1370 fputs(prefix2, f);
1371 }
1372
1373 r = json_format(f, e, flags, prefix2);
1374 if (r < 0)
1375 return r;
1376 }
1377
1378 if (flags & JSON_FORMAT_PRETTY) {
1379 fputc('\n', f);
1380 print_source(f, v, flags, true);
1381 fputs(strempty(prefix), f);
1382 }
1383
1384 fputc(']', f);
1385 }
1386 break;
1387 }
1388
1389 case JSON_VARIANT_OBJECT: {
1390 size_t i, n;
1391
1392 n = json_variant_elements(v);
1393
1394 if (n == 0)
1395 fputs("{}", f);
1396 else {
1397 const char *prefix2;
1398
1399 if (flags & JSON_FORMAT_PRETTY) {
1400 prefix2 = strjoina(strempty(prefix), "\t");
1401 fputs("{\n", f);
1402 } else {
1403 prefix2 = strempty(prefix);
1404 fputc('{', f);
1405 }
1406
1407 for (i = 0; i < n; i += 2) {
1408 JsonVariant *e;
1409
1410 e = json_variant_by_index(v, i);
1411
1412 if (i > 0) {
1413 if (flags & JSON_FORMAT_PRETTY)
1414 fputs(",\n", f);
1415 else
1416 fputc(',', f);
1417 }
1418
1419 if (flags & JSON_FORMAT_PRETTY) {
1420 print_source(f, e, flags, false);
1421 fputs(prefix2, f);
1422 }
1423
1424 r = json_format(f, e, flags, prefix2);
1425 if (r < 0)
1426 return r;
1427
1428 fputs(flags & JSON_FORMAT_PRETTY ? " : " : ":", f);
1429
1430 r = json_format(f, json_variant_by_index(v, i+1), flags, prefix2);
1431 if (r < 0)
1432 return r;
1433 }
1434
1435 if (flags & JSON_FORMAT_PRETTY) {
1436 fputc('\n', f);
1437 print_source(f, v, flags, true);
1438 fputs(strempty(prefix), f);
1439 }
1440
1441 fputc('}', f);
1442 }
1443 break;
1444 }
1445
1446 default:
1447 assert_not_reached("Unexpected variant type.");
1448 }
1449
1450 return 0;
1451}
1452
1453int json_variant_format(JsonVariant *v, unsigned flags, char **ret) {
1454 _cleanup_free_ char *s = NULL;
1455 size_t sz = 0;
1456 int r;
1457
1458 assert_return(v, -EINVAL);
1459 assert_return(ret, -EINVAL);
1460
1461 {
1462 _cleanup_fclose_ FILE *f = NULL;
1463
1464 f = open_memstream(&s, &sz);
1465 if (!f)
1466 return -ENOMEM;
1467
1468 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
1469
1470 json_variant_dump(v, flags, f, NULL);
1471
1472 r = fflush_and_check(f);
1473 }
1474 if (r < 0)
1475 return r;
1476
1477 assert(s);
1478 *ret = TAKE_PTR(s);
1479
1480 return (int) sz;
1481}
1482
1483void json_variant_dump(JsonVariant *v, unsigned flags, FILE *f, const char *prefix) {
1484 if (!v)
1485 return;
1486
1487 if (!f)
1488 f = stdout;
1489
1490 print_source(f, v, flags, false);
1491
1492 if (flags & JSON_FORMAT_SSE)
1493 fputs("data: ", f);
1494 if (flags & JSON_FORMAT_SEQ)
1495 fputc('\x1e', f); /* ASCII Record Separator */
1496
1497 json_format(f, v, flags, prefix);
1498
1499 if (flags & (JSON_FORMAT_PRETTY|JSON_FORMAT_SEQ|JSON_FORMAT_SSE|JSON_FORMAT_NEWLINE))
1500 fputc('\n', f);
1501 if (flags & JSON_FORMAT_SSE)
1502 fputc('\n', f); /* In case of SSE add a second newline */
1503}
1504
1505static int json_variant_copy(JsonVariant **nv, JsonVariant *v) {
1506 JsonVariantType t;
1507 JsonVariant *c;
1508 JsonValue value;
1509 const void *source;
1510 size_t k;
1511
1512 assert(nv);
1513 assert(v);
1514
1515 /* Let's copy the simple types literally, and the larger types by references */
1516 t = json_variant_type(v);
1517 switch (t) {
1518 case JSON_VARIANT_INTEGER:
1519 k = sizeof(intmax_t);
1520 value.integer = json_variant_integer(v);
1521 source = &value;
1522 break;
1523
1524 case JSON_VARIANT_UNSIGNED:
1525 k = sizeof(uintmax_t);
1526 value.unsig = json_variant_unsigned(v);
1527 source = &value;
1528 break;
1529
1530 case JSON_VARIANT_REAL:
1531 k = sizeof(long double);
1532 value.real = json_variant_real(v);
1533 source = &value;
1534 break;
1535
1536 case JSON_VARIANT_BOOLEAN:
1537 k = sizeof(bool);
1538 value.boolean = json_variant_boolean(v);
1539 source = &value;
1540 break;
1541
1542 case JSON_VARIANT_NULL:
1543 k = 0;
1544 source = NULL;
1545 break;
1546
1547 case JSON_VARIANT_STRING:
1548 source = json_variant_string(v);
1549 k = strnlen(source, INLINE_STRING_MAX + 1);
1550 if (k <= INLINE_STRING_MAX) {
1551 k ++;
1552 break;
1553 }
1554
1555 _fallthrough_;
1556
1557 default:
1558 /* Everything else copy by reference */
1559
1560 c = malloc0(offsetof(JsonVariant, reference) + sizeof(JsonVariant*));
1561 if (!c)
1562 return -ENOMEM;
1563
1564 c->n_ref = 1;
1565 c->type = t;
1566 c->is_reference = true;
1567 c->reference = json_variant_ref(json_variant_normalize(v));
1568
1569 *nv = c;
1570 return 0;
1571 }
1572
1573 c = malloc0(offsetof(JsonVariant, value) + k);
1574 if (!c)
1575 return -ENOMEM;
1576
1577 c->n_ref = 1;
1578 c->type = t;
1579
1580 memcpy_safe(&c->value, source, k);
1581
1582 *nv = c;
1583 return 0;
1584}
1585
1586static bool json_single_ref(JsonVariant *v) {
1587
1588 /* Checks whether the caller is the single owner of the object, i.e. can get away with changing it */
1589
1590 if (json_variant_is_magic(v))
1591 return false;
1592
1593 if (v->is_embedded)
1594 return json_single_ref(v->parent);
1595
1596 assert(v->n_ref > 0);
1597 return v->n_ref == 1;
1598}
1599
1600static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned line, unsigned column) {
1601 JsonVariant *w;
1602 int r;
1603
1604 assert(v);
1605
1606 /* Patch in source and line/column number. Tries to do this in-place if the caller is the sole referencer of
1607 * the object. If not, allocates a new object, possibly a surrogate for the original one */
1608
1609 if (!*v)
1610 return 0;
1611
1612 if (source && line > source->max_line)
1613 source->max_line = line;
1614 if (source && column > source->max_column)
1615 source->max_column = column;
1616
1617 if (json_variant_is_magic(*v)) {
1618
1619 if (!source && line == 0 && column == 0)
1620 return 0;
1621
1622 } else {
1623 if (json_source_equal((*v)->source, source) &&
1624 (*v)->line == line &&
1625 (*v)->column == column)
1626 return 0;
1627
1628 if (json_single_ref(*v)) { /* Sole reference? */
1629 json_source_unref((*v)->source);
1630 (*v)->source = json_source_ref(source);
1631 (*v)->line = line;
1632 (*v)->column = column;
1633 return 1;
1634 }
1635 }
1636
1637 r = json_variant_copy(&w, *v);
1638 if (r < 0)
1639 return r;
1640
1641 assert(!json_variant_is_magic(w));
1642 assert(!w->is_embedded);
1643 assert(w->n_ref == 1);
1644 assert(!w->source);
1645
1646 w->source = json_source_ref(source);
1647 w->line = line;
1648 w->column = column;
1649
1650 json_variant_unref(*v);
1651 *v = w;
1652
1653 return 1;
1654}
1655
1656static void inc_lines_columns(unsigned *line, unsigned *column, const char *s, size_t n) {
1657 assert(line);
1658 assert(column);
1659 assert(s || n == 0);
1660
1661 while (n > 0) {
1662
1663 if (*s == '\n') {
1664 (*line)++;
1665 *column = 1;
1666 } else if (*s >= 0 && *s < 127) /* Process ASCII chars quickly */
1667 (*column)++;
1668 else {
1669 int w;
1670
1671 w = utf8_encoded_valid_unichar(s);
1672 if (w < 0) /* count invalid unichars as normal characters */
1673 w = 1;
1674 else if ((size_t) w > n) /* never read more than the specified number of characters */
1675 w = (int) n;
1676
1677 (*column)++;
1678
1679 s += w;
1680 n -= w;
1681 continue;
1682 }
1683
1684 s++;
1685 n--;
1686 }
1687}
1688
1689static int unhex_ucs2(const char *c, uint16_t *ret) {
1690 int aa, bb, cc, dd;
1691 uint16_t x;
1692
1693 assert(c);
1694 assert(ret);
1695
1696 aa = unhexchar(c[0]);
1697 if (aa < 0)
1698 return -EINVAL;
1699
1700 bb = unhexchar(c[1]);
1701 if (bb < 0)
1702 return -EINVAL;
1703
1704 cc = unhexchar(c[2]);
1705 if (cc < 0)
1706 return -EINVAL;
1707
1708 dd = unhexchar(c[3]);
1709 if (dd < 0)
1710 return -EINVAL;
1711
1712 x = ((uint16_t) aa << 12) |
1713 ((uint16_t) bb << 8) |
1714 ((uint16_t) cc << 4) |
1715 ((uint16_t) dd);
1716
1717 if (x <= 0)
1718 return -EINVAL;
1719
1720 *ret = x;
1721
1722 return 0;
1723}
1724
1725static int json_parse_string(const char **p, char **ret) {
1726 _cleanup_free_ char *s = NULL;
1727 size_t n = 0, allocated = 0;
1728 const char *c;
1729
1730 assert(p);
1731 assert(*p);
1732 assert(ret);
1733
1734 c = *p;
1735
1736 if (*c != '"')
1737 return -EINVAL;
1738
1739 c++;
1740
1741 for (;;) {
1742 int len;
1743
1744 /* Check for EOF */
1745 if (*c == 0)
1746 return -EINVAL;
1747
1748 /* Check for control characters 0x00..0x1f */
1749 if (*c > 0 && *c < ' ')
1750 return -EINVAL;
1751
1752 /* Check for control character 0x7f */
1753 if (*c == 0x7f)
1754 return -EINVAL;
1755
1756 if (*c == '"') {
1757 if (!s) {
1758 s = strdup("");
1759 if (!s)
1760 return -ENOMEM;
1761 } else
1762 s[n] = 0;
1763
1764 *p = c + 1;
1765
1766 *ret = s;
1767 s = NULL;
1768 return JSON_TOKEN_STRING;
1769 }
1770
1771 if (*c == '\\') {
1772 char ch = 0;
1773 c++;
1774
1775 if (*c == 0)
1776 return -EINVAL;
1777
1778 if (IN_SET(*c, '"', '\\', '/'))
1779 ch = *c;
1780 else if (*c == 'b')
1781 ch = '\b';
1782 else if (*c == 'f')
1783 ch = '\f';
1784 else if (*c == 'n')
1785 ch = '\n';
1786 else if (*c == 'r')
1787 ch = '\r';
1788 else if (*c == 't')
1789 ch = '\t';
1790 else if (*c == 'u') {
1791 char16_t x;
1792 int r;
1793
1794 r = unhex_ucs2(c + 1, &x);
1795 if (r < 0)
1796 return r;
1797
1798 c += 5;
1799
1800 if (!GREEDY_REALLOC(s, allocated, n + 5))
1801 return -ENOMEM;
1802
1803 if (!utf16_is_surrogate(x))
1804 n += utf8_encode_unichar(s + n, (char32_t) x);
1805 else if (utf16_is_trailing_surrogate(x))
1806 return -EINVAL;
1807 else {
1808 char16_t y;
1809
1810 if (c[0] != '\\' || c[1] != 'u')
1811 return -EINVAL;
1812
1813 r = unhex_ucs2(c + 2, &y);
1814 if (r < 0)
1815 return r;
1816
1817 c += 6;
1818
1819 if (!utf16_is_trailing_surrogate(y))
1820 return -EINVAL;
1821
1822 n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y));
1823 }
1824
1825 continue;
1826 } else
1827 return -EINVAL;
1828
1829 if (!GREEDY_REALLOC(s, allocated, n + 2))
1830 return -ENOMEM;
1831
1832 s[n++] = ch;
1833 c ++;
1834 continue;
1835 }
1836
1837 len = utf8_encoded_valid_unichar(c);
1838 if (len < 0)
1839 return len;
1840
1841 if (!GREEDY_REALLOC(s, allocated, n + len + 1))
1842 return -ENOMEM;
1843
1844 memcpy(s + n, c, len);
1845 n += len;
1846 c += len;
1847 }
1848}
1849
1850static int json_parse_number(const char **p, JsonValue *ret) {
1851 bool negative = false, exponent_negative = false, is_real = false;
1852 long double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
1853 intmax_t i = 0;
1854 uintmax_t u = 0;
1855 const char *c;
1856
1857 assert(p);
1858 assert(*p);
1859 assert(ret);
1860
1861 c = *p;
1862
1863 if (*c == '-') {
1864 negative = true;
1865 c++;
1866 }
1867
1868 if (*c == '0')
1869 c++;
1870 else {
1871 if (!strchr("123456789", *c) || *c == 0)
1872 return -EINVAL;
1873
1874 do {
1875 if (!is_real) {
1876 if (negative) {
1877
1878 if (i < INTMAX_MIN / 10) /* overflow */
1879 is_real = true;
1880 else {
1881 intmax_t t = 10 * i;
1882
1883 if (t < INTMAX_MIN + (*c - '0')) /* overflow */
1884 is_real = true;
1885 else
1886 i = t - (*c - '0');
1887 }
1888 } else {
1889 if (u > UINTMAX_MAX / 10) /* overflow */
1890 is_real = true;
1891 else {
1892 uintmax_t t = 10 * u;
1893
1894 if (t > UINTMAX_MAX - (*c - '0')) /* overflow */
1895 is_real = true;
1896 else
1897 u = t + (*c - '0');
1898 }
1899 }
1900 }
1901
1902 x = 10.0 * x + (*c - '0');
1903
1904 c++;
1905 } while (strchr("0123456789", *c) && *c != 0);
1906 }
1907
1908 if (*c == '.') {
1909 is_real = true;
1910 c++;
1911
1912 if (!strchr("0123456789", *c) || *c == 0)
1913 return -EINVAL;
1914
1915 do {
1916 y = 10.0 * y + (*c - '0');
1917 shift = 10.0 * shift;
1918 c++;
1919 } while (strchr("0123456789", *c) && *c != 0);
1920 }
1921
1922 if (*c == 'e' || *c == 'E') {
1923 is_real = true;
1924 c++;
1925
1926 if (*c == '-') {
1927 exponent_negative = true;
1928 c++;
1929 } else if (*c == '+')
1930 c++;
1931
1932 if (!strchr("0123456789", *c) || *c == 0)
1933 return -EINVAL;
1934
1935 do {
1936 exponent = 10.0 * exponent + (*c - '0');
1937 c++;
1938 } while (strchr("0123456789", *c) && *c != 0);
1939 }
1940
1941 *p = c;
1942
1943 if (is_real) {
1944 ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10l((exponent_negative ? -1.0 : 1.0) * exponent);
1945 return JSON_TOKEN_REAL;
1946 } else if (negative) {
1947 ret->integer = i;
1948 return JSON_TOKEN_INTEGER;
1949 } else {
1950 ret->unsig = u;
1951 return JSON_TOKEN_UNSIGNED;
1952 }
1953}
1954
1955int json_tokenize(
1956 const char **p,
1957 char **ret_string,
1958 JsonValue *ret_value,
1959 unsigned *ret_line, /* 'ret_line' returns the line at the beginning of this token */
1960 unsigned *ret_column,
1961 void **state,
1962 unsigned *line, /* 'line' is used as a line state, it always reflect the line we are at after the token was read */
1963 unsigned *column) {
1964
1965 unsigned start_line, start_column;
1966 const char *start, *c;
1967 size_t n;
1968 int t, r;
1969
1970 enum {
1971 STATE_NULL,
1972 STATE_VALUE,
1973 STATE_VALUE_POST,
1974 };
1975
1976 assert(p);
1977 assert(*p);
1978 assert(ret_string);
1979 assert(ret_value);
1980 assert(ret_line);
1981 assert(ret_column);
1982 assert(line);
1983 assert(column);
1984 assert(state);
1985
1986 t = PTR_TO_INT(*state);
1987 if (t == STATE_NULL) {
1988 *line = 1;
1989 *column = 1;
1990 t = STATE_VALUE;
1991 }
1992
1993 /* Skip over the whitespace */
1994 n = strspn(*p, WHITESPACE);
1995 inc_lines_columns(line, column, *p, n);
1996 c = *p + n;
1997
1998 /* Remember where we started processing this token */
1999 start = c;
2000 start_line = *line;
2001 start_column = *column;
2002
2003 if (*c == 0) {
2004 *ret_string = NULL;
2005 *ret_value = JSON_VALUE_NULL;
2006 r = JSON_TOKEN_END;
2007 goto finish;
2008 }
2009
2010 switch (t) {
2011
2012 case STATE_VALUE:
2013
2014 if (*c == '{') {
2015 c++;
2016 *state = INT_TO_PTR(STATE_VALUE);
2017 r = JSON_TOKEN_OBJECT_OPEN;
2018 goto null_return;
2019
2020 } else if (*c == '}') {
2021 c++;
2022 *state = INT_TO_PTR(STATE_VALUE_POST);
2023 r = JSON_TOKEN_OBJECT_CLOSE;
2024 goto null_return;
2025
2026 } else if (*c == '[') {
2027 c++;
2028 *state = INT_TO_PTR(STATE_VALUE);
2029 r = JSON_TOKEN_ARRAY_OPEN;
2030 goto null_return;
2031
2032 } else if (*c == ']') {
2033 c++;
2034 *state = INT_TO_PTR(STATE_VALUE_POST);
2035 r = JSON_TOKEN_ARRAY_CLOSE;
2036 goto null_return;
2037
2038 } else if (*c == '"') {
2039
2040 r = json_parse_string(&c, ret_string);
2041 if (r < 0)
2042 return r;
2043
2044 *ret_value = JSON_VALUE_NULL;
2045 *state = INT_TO_PTR(STATE_VALUE_POST);
2046 goto finish;
2047
2048 } else if (strchr("-0123456789", *c)) {
2049
2050 r = json_parse_number(&c, ret_value);
2051 if (r < 0)
2052 return r;
2053
2054 *ret_string = NULL;
2055 *state = INT_TO_PTR(STATE_VALUE_POST);
2056 goto finish;
2057
2058 } else if (startswith(c, "true")) {
2059 *ret_string = NULL;
2060 ret_value->boolean = true;
2061 c += 4;
2062 *state = INT_TO_PTR(STATE_VALUE_POST);
2063 r = JSON_TOKEN_BOOLEAN;
2064 goto finish;
2065
2066 } else if (startswith(c, "false")) {
2067 *ret_string = NULL;
2068 ret_value->boolean = false;
2069 c += 5;
2070 *state = INT_TO_PTR(STATE_VALUE_POST);
2071 r = JSON_TOKEN_BOOLEAN;
2072 goto finish;
2073
2074 } else if (startswith(c, "null")) {
2075 *ret_string = NULL;
2076 *ret_value = JSON_VALUE_NULL;
2077 c += 4;
2078 *state = INT_TO_PTR(STATE_VALUE_POST);
2079 r = JSON_TOKEN_NULL;
2080 goto finish;
2081
2082 }
2083
2084 return -EINVAL;
2085
2086 case STATE_VALUE_POST:
2087
2088 if (*c == ':') {
2089 c++;
2090 *state = INT_TO_PTR(STATE_VALUE);
2091 r = JSON_TOKEN_COLON;
2092 goto null_return;
2093
2094 } else if (*c == ',') {
2095 c++;
2096 *state = INT_TO_PTR(STATE_VALUE);
2097 r = JSON_TOKEN_COMMA;
2098 goto null_return;
2099
2100 } else if (*c == '}') {
2101 c++;
2102 *state = INT_TO_PTR(STATE_VALUE_POST);
2103 r = JSON_TOKEN_OBJECT_CLOSE;
2104 goto null_return;
2105
2106 } else if (*c == ']') {
2107 c++;
2108 *state = INT_TO_PTR(STATE_VALUE_POST);
2109 r = JSON_TOKEN_ARRAY_CLOSE;
2110 goto null_return;
2111 }
2112
2113 return -EINVAL;
2114
2115 default:
2116 assert_not_reached("Unexpected tokenizer state");
2117 }
2118
2119null_return:
2120 *ret_string = NULL;
2121 *ret_value = JSON_VALUE_NULL;
2122
2123finish:
2124 inc_lines_columns(line, column, start, c - start);
2125 *p = c;
2126
2127 *ret_line = start_line;
2128 *ret_column = start_column;
2129
2130 return r;
2131}
2132
2133typedef enum JsonExpect {
2134 /* The following values are used by json_parse() */
2135 EXPECT_TOPLEVEL,
2136 EXPECT_END,
2137 EXPECT_OBJECT_FIRST_KEY,
2138 EXPECT_OBJECT_NEXT_KEY,
2139 EXPECT_OBJECT_COLON,
2140 EXPECT_OBJECT_VALUE,
2141 EXPECT_OBJECT_COMMA,
2142 EXPECT_ARRAY_FIRST_ELEMENT,
2143 EXPECT_ARRAY_NEXT_ELEMENT,
2144 EXPECT_ARRAY_COMMA,
2145
2146 /* And these are used by json_build() */
2147 EXPECT_ARRAY_ELEMENT,
2148 EXPECT_OBJECT_KEY,
2149} JsonExpect;
2150
2151typedef struct JsonStack {
2152 JsonExpect expect;
2153 JsonVariant **elements;
2154 size_t n_elements, n_elements_allocated;
2155 unsigned line_before;
2156 unsigned column_before;
2157} JsonStack;
2158
2159static void json_stack_release(JsonStack *s) {
2160 assert(s);
2161
2162 json_variant_unref_many(s->elements, s->n_elements);
2163 s->elements = mfree(s->elements);
2164}
2165
2166static int json_parse_internal(
2167 const char **input,
2168 JsonSource *source,
2169 JsonVariant **ret,
2170 unsigned *line,
2171 unsigned *column,
2172 bool continue_end) {
2173
2174 size_t n_stack = 1, n_stack_allocated = 0, i;
2175 unsigned line_buffer = 0, column_buffer = 0;
2176 void *tokenizer_state = NULL;
2177 JsonStack *stack = NULL;
2178 const char *p;
2179 int r;
2180
2181 assert_return(input, -EINVAL);
2182 assert_return(ret, -EINVAL);
2183
2184 p = *input;
2185
2186 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack))
2187 return -ENOMEM;
2188
2189 stack[0] = (JsonStack) {
2190 .expect = EXPECT_TOPLEVEL,
2191 };
2192
2193 if (!line)
2194 line = &line_buffer;
2195 if (!column)
2196 column = &column_buffer;
2197
2198 for (;;) {
2199 _cleanup_free_ char *string = NULL;
2200 unsigned line_token, column_token;
2201 JsonVariant *add = NULL;
2202 JsonStack *current;
2203 JsonValue value;
2204 int token;
2205
2206 assert(n_stack > 0);
2207 current = stack + n_stack - 1;
2208
2209 if (continue_end && current->expect == EXPECT_END)
2210 goto done;
2211
2212 token = json_tokenize(&p, &string, &value, &line_token, &column_token, &tokenizer_state, line, column);
2213 if (token < 0) {
2214 r = token;
2215 goto finish;
2216 }
2217
2218 switch (token) {
2219
2220 case JSON_TOKEN_END:
2221 if (current->expect != EXPECT_END) {
2222 r = -EINVAL;
2223 goto finish;
2224 }
2225
2226 assert(current->n_elements == 1);
2227 assert(n_stack == 1);
2228 goto done;
2229
2230 case JSON_TOKEN_COLON:
2231
2232 if (current->expect != EXPECT_OBJECT_COLON) {
2233 r = -EINVAL;
2234 goto finish;
2235 }
2236
2237 current->expect = EXPECT_OBJECT_VALUE;
2238 break;
2239
2240 case JSON_TOKEN_COMMA:
2241
2242 if (current->expect == EXPECT_OBJECT_COMMA)
2243 current->expect = EXPECT_OBJECT_NEXT_KEY;
2244 else if (current->expect == EXPECT_ARRAY_COMMA)
2245 current->expect = EXPECT_ARRAY_NEXT_ELEMENT;
2246 else {
2247 r = -EINVAL;
2248 goto finish;
2249 }
2250
2251 break;
2252
2253 case JSON_TOKEN_OBJECT_OPEN:
2254
2255 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2256 r = -EINVAL;
2257 goto finish;
2258 }
2259
2260 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
2261 r = -ENOMEM;
2262 goto finish;
2263 }
2264 current = stack + n_stack - 1;
2265
2266 /* Prepare the expect for when we return from the child */
2267 if (current->expect == EXPECT_TOPLEVEL)
2268 current->expect = EXPECT_END;
2269 else if (current->expect == EXPECT_OBJECT_VALUE)
2270 current->expect = EXPECT_OBJECT_COMMA;
2271 else {
2272 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2273 current->expect = EXPECT_ARRAY_COMMA;
2274 }
2275
2276 stack[n_stack++] = (JsonStack) {
2277 .expect = EXPECT_OBJECT_FIRST_KEY,
2278 .line_before = line_token,
2279 .column_before = column_token,
2280 };
2281
2282 current = stack + n_stack - 1;
2283 break;
2284
2285 case JSON_TOKEN_OBJECT_CLOSE:
2286 if (!IN_SET(current->expect, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_COMMA)) {
2287 r = -EINVAL;
2288 goto finish;
2289 }
2290
2291 assert(n_stack > 1);
2292
2293 r = json_variant_new_object(&add, current->elements, current->n_elements);
2294 if (r < 0)
2295 goto finish;
2296
2297 line_token = current->line_before;
2298 column_token = current->column_before;
2299
2300 json_stack_release(current);
2301 n_stack--, current--;
2302
2303 break;
2304
2305 case JSON_TOKEN_ARRAY_OPEN:
2306 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2307 r = -EINVAL;
2308 goto finish;
2309 }
2310
2311 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
2312 r = -ENOMEM;
2313 goto finish;
2314 }
2315 current = stack + n_stack - 1;
2316
2317 /* Prepare the expect for when we return from the child */
2318 if (current->expect == EXPECT_TOPLEVEL)
2319 current->expect = EXPECT_END;
2320 else if (current->expect == EXPECT_OBJECT_VALUE)
2321 current->expect = EXPECT_OBJECT_COMMA;
2322 else {
2323 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2324 current->expect = EXPECT_ARRAY_COMMA;
2325 }
2326
2327 stack[n_stack++] = (JsonStack) {
2328 .expect = EXPECT_ARRAY_FIRST_ELEMENT,
2329 .line_before = line_token,
2330 .column_before = column_token,
2331 };
2332
2333 break;
2334
2335 case JSON_TOKEN_ARRAY_CLOSE:
2336 if (!IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_COMMA)) {
2337 r = -EINVAL;
2338 goto finish;
2339 }
2340
2341 assert(n_stack > 1);
2342
2343 r = json_variant_new_array(&add, current->elements, current->n_elements);
2344 if (r < 0)
2345 goto finish;
2346
2347 line_token = current->line_before;
2348 column_token = current->column_before;
2349
2350 json_stack_release(current);
2351 n_stack--, current--;
2352 break;
2353
2354 case JSON_TOKEN_STRING:
2355 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_NEXT_KEY, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2356 r = -EINVAL;
2357 goto finish;
2358 }
2359
2360 r = json_variant_new_string(&add, string);
2361 if (r < 0)
2362 goto finish;
2363
2364 if (current->expect == EXPECT_TOPLEVEL)
2365 current->expect = EXPECT_END;
2366 else if (IN_SET(current->expect, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_NEXT_KEY))
2367 current->expect = EXPECT_OBJECT_COLON;
2368 else if (current->expect == EXPECT_OBJECT_VALUE)
2369 current->expect = EXPECT_OBJECT_COMMA;
2370 else {
2371 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2372 current->expect = EXPECT_ARRAY_COMMA;
2373 }
2374
2375 break;
2376
2377 case JSON_TOKEN_REAL:
2378 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2379 r = -EINVAL;
2380 goto finish;
2381 }
2382
2383 r = json_variant_new_real(&add, value.real);
2384 if (r < 0)
2385 goto finish;
2386
2387 if (current->expect == EXPECT_TOPLEVEL)
2388 current->expect = EXPECT_END;
2389 else if (current->expect == EXPECT_OBJECT_VALUE)
2390 current->expect = EXPECT_OBJECT_COMMA;
2391 else {
2392 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2393 current->expect = EXPECT_ARRAY_COMMA;
2394 }
2395
2396 break;
2397
2398 case JSON_TOKEN_INTEGER:
2399 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2400 r = -EINVAL;
2401 goto finish;
2402 }
2403
2404 r = json_variant_new_integer(&add, value.integer);
2405 if (r < 0)
2406 goto finish;
2407
2408 if (current->expect == EXPECT_TOPLEVEL)
2409 current->expect = EXPECT_END;
2410 else if (current->expect == EXPECT_OBJECT_VALUE)
2411 current->expect = EXPECT_OBJECT_COMMA;
2412 else {
2413 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2414 current->expect = EXPECT_ARRAY_COMMA;
2415 }
2416
2417 break;
2418
2419 case JSON_TOKEN_UNSIGNED:
2420 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2421 r = -EINVAL;
2422 goto finish;
2423 }
2424
2425 r = json_variant_new_unsigned(&add, value.unsig);
2426 if (r < 0)
2427 goto finish;
2428
2429 if (current->expect == EXPECT_TOPLEVEL)
2430 current->expect = EXPECT_END;
2431 else if (current->expect == EXPECT_OBJECT_VALUE)
2432 current->expect = EXPECT_OBJECT_COMMA;
2433 else {
2434 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2435 current->expect = EXPECT_ARRAY_COMMA;
2436 }
2437
2438 break;
2439
2440 case JSON_TOKEN_BOOLEAN:
2441 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2442 r = -EINVAL;
2443 goto finish;
2444 }
2445
2446 r = json_variant_new_boolean(&add, value.boolean);
2447 if (r < 0)
2448 goto finish;
2449
2450 if (current->expect == EXPECT_TOPLEVEL)
2451 current->expect = EXPECT_END;
2452 else if (current->expect == EXPECT_OBJECT_VALUE)
2453 current->expect = EXPECT_OBJECT_COMMA;
2454 else {
2455 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2456 current->expect = EXPECT_ARRAY_COMMA;
2457 }
2458
2459 break;
2460
2461 case JSON_TOKEN_NULL:
2462 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2463 r = -EINVAL;
2464 goto finish;
2465 }
2466
2467 r = json_variant_new_null(&add);
2468 if (r < 0)
2469 goto finish;
2470
2471 if (current->expect == EXPECT_TOPLEVEL)
2472 current->expect = EXPECT_END;
2473 else if (current->expect == EXPECT_OBJECT_VALUE)
2474 current->expect = EXPECT_OBJECT_COMMA;
2475 else {
2476 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2477 current->expect = EXPECT_ARRAY_COMMA;
2478 }
2479
2480 break;
2481
2482 default:
2483 assert_not_reached("Unexpected token");
2484 }
2485
2486 if (add) {
2487 (void) json_variant_set_source(&add, source, line_token, column_token);
2488
2489 if (!GREEDY_REALLOC(current->elements, current->n_elements_allocated, current->n_elements + 1)) {
2490 r = -ENOMEM;
2491 goto finish;
2492 }
2493
2494 current->elements[current->n_elements++] = add;
2495 }
2496 }
2497
2498done:
2499 assert(n_stack == 1);
2500 assert(stack[0].n_elements == 1);
2501
2502 *ret = json_variant_ref(stack[0].elements[0]);
2503 *input = p;
2504 r = 0;
2505
2506finish:
2507 for (i = 0; i < n_stack; i++)
2508 json_stack_release(stack + i);
2509
2510 free(stack);
2511
2512 return r;
2513}
2514
2515int json_parse(const char *input, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
2516 return json_parse_internal(&input, NULL, ret, ret_line, ret_column, false);
2517}
2518
2519int json_parse_continue(const char **p, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
2520 return json_parse_internal(p, NULL, ret, ret_line, ret_column, true);
2521}
2522
2523int json_parse_file(FILE *f, const char *path, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
2524 _cleanup_(json_source_unrefp) JsonSource *source = NULL;
2525 _cleanup_free_ char *text = NULL;
2526 const char *p;
2527 int r;
2528
2529 if (f)
2530 r = read_full_stream(f, &text, NULL);
2531 else if (path)
2532 r = read_full_file(path, &text, NULL);
2533 else
2534 return -EINVAL;
2535 if (r < 0)
2536 return r;
2537
2538 if (path) {
2539 source = json_source_new(path);
2540 if (!source)
2541 return -ENOMEM;
2542 }
2543
2544 p = text;
2545 return json_parse_internal(&p, source, ret, ret_line, ret_column, false);
2546}
2547
2548int json_buildv(JsonVariant **ret, va_list ap) {
2549 JsonStack *stack = NULL;
2550 size_t n_stack = 1, n_stack_allocated = 0, i;
2551 int r;
2552
2553 assert_return(ret, -EINVAL);
2554
2555 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack))
2556 return -ENOMEM;
2557
2558 stack[0] = (JsonStack) {
2559 .expect = EXPECT_TOPLEVEL,
2560 };
2561
2562 for (;;) {
2563 JsonVariant *add = NULL;
2564 JsonStack *current;
2565 int command;
2566
2567 assert(n_stack > 0);
2568 current = stack + n_stack - 1;
2569
2570 if (current->expect == EXPECT_END)
2571 goto done;
2572
2573 command = va_arg(ap, int);
2574
2575 switch (command) {
2576
2577 case _JSON_BUILD_STRING: {
2578 const char *p;
2579
2580 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2581 r = -EINVAL;
2582 goto finish;
2583 }
2584
2585 p = va_arg(ap, const char *);
2586
2587 r = json_variant_new_string(&add, p);
2588 if (r < 0)
2589 goto finish;
2590
2591 if (current->expect == EXPECT_TOPLEVEL)
2592 current->expect = EXPECT_END;
2593 else if (current->expect == EXPECT_OBJECT_VALUE)
2594 current->expect = EXPECT_OBJECT_KEY;
2595 else
2596 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2597
2598 break;
2599 }
2600
2601 case _JSON_BUILD_INTEGER: {
2602 intmax_t j;
2603
2604 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2605 r = -EINVAL;
2606 goto finish;
2607 }
2608
2609 j = va_arg(ap, intmax_t);
2610
2611 r = json_variant_new_integer(&add, j);
2612 if (r < 0)
2613 goto finish;
2614
2615 if (current->expect == EXPECT_TOPLEVEL)
2616 current->expect = EXPECT_END;
2617 else if (current->expect == EXPECT_OBJECT_VALUE)
2618 current->expect = EXPECT_OBJECT_KEY;
2619 else
2620 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2621
2622 break;
2623 }
2624
2625 case _JSON_BUILD_UNSIGNED: {
2626 uintmax_t j;
2627
2628 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2629 r = -EINVAL;
2630 goto finish;
2631 }
2632
2633 j = va_arg(ap, uintmax_t);
2634
2635 r = json_variant_new_unsigned(&add, j);
2636 if (r < 0)
2637 goto finish;
2638
2639 if (current->expect == EXPECT_TOPLEVEL)
2640 current->expect = EXPECT_END;
2641 else if (current->expect == EXPECT_OBJECT_VALUE)
2642 current->expect = EXPECT_OBJECT_KEY;
2643 else
2644 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2645
2646 break;
2647 }
2648
2649 case _JSON_BUILD_REAL: {
2650 long double d;
2651
2652 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2653 r = -EINVAL;
2654 goto finish;
2655 }
2656
2657 d = va_arg(ap, long double);
2658
2659 r = json_variant_new_real(&add, d);
2660 if (r < 0)
2661 goto finish;
2662
2663 if (current->expect == EXPECT_TOPLEVEL)
2664 current->expect = EXPECT_END;
2665 else if (current->expect == EXPECT_OBJECT_VALUE)
2666 current->expect = EXPECT_OBJECT_KEY;
2667 else
2668 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2669
2670 break;
2671 }
2672
2673 case _JSON_BUILD_BOOLEAN: {
2674 bool b;
2675
2676 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2677 r = -EINVAL;
2678 goto finish;
2679 }
2680
2681 b = va_arg(ap, int);
2682
2683 r = json_variant_new_boolean(&add, b);
2684 if (r < 0)
2685 goto finish;
2686
2687 if (current->expect == EXPECT_TOPLEVEL)
2688 current->expect = EXPECT_END;
2689 else if (current->expect == EXPECT_OBJECT_VALUE)
2690 current->expect = EXPECT_OBJECT_KEY;
2691 else
2692 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2693
2694 break;
2695 }
2696
2697 case _JSON_BUILD_NULL:
2698
2699 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2700 r = -EINVAL;
2701 goto finish;
2702 }
2703
2704 r = json_variant_new_null(&add);
2705 if (r < 0)
2706 goto finish;
2707
2708 if (current->expect == EXPECT_TOPLEVEL)
2709 current->expect = EXPECT_END;
2710 else if (current->expect == EXPECT_OBJECT_VALUE)
2711 current->expect = EXPECT_OBJECT_KEY;
2712 else
2713 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2714
2715 break;
2716
2717 case _JSON_BUILD_VARIANT:
2718
2719 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2720 r = -EINVAL;
2721 goto finish;
2722 }
2723
2724 add = va_arg(ap, JsonVariant*);
2725 if (!add)
2726 add = JSON_VARIANT_MAGIC_NULL;
2727 else
2728 json_variant_ref(add);
2729
2730 if (current->expect == EXPECT_TOPLEVEL)
2731 current->expect = EXPECT_END;
2732 else if (current->expect == EXPECT_OBJECT_VALUE)
2733 current->expect = EXPECT_OBJECT_KEY;
2734 else
2735 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2736
2737 break;
2738
2739 case _JSON_BUILD_LITERAL: {
2740 const char *l;
2741
2742 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2743 r = -EINVAL;
2744 goto finish;
2745 }
2746
2747 l = va_arg(ap, const char *);
2748
2749 if (!l)
2750 add = JSON_VARIANT_MAGIC_NULL;
2751 else {
2752 r = json_parse(l, &add, NULL, NULL);
2753 if (r < 0)
2754 goto finish;
2755 }
2756
2757 if (current->expect == EXPECT_TOPLEVEL)
2758 current->expect = EXPECT_END;
2759 else if (current->expect == EXPECT_OBJECT_VALUE)
2760 current->expect = EXPECT_OBJECT_KEY;
2761 else
2762 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2763
2764 break;
2765 }
2766
2767 case _JSON_BUILD_ARRAY_BEGIN:
2768
2769 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2770 r = -EINVAL;
2771 goto finish;
2772 }
2773
2774 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
2775 r = -ENOMEM;
2776 goto finish;
2777 }
2778 current = stack + n_stack - 1;
2779
2780 if (current->expect == EXPECT_TOPLEVEL)
2781 current->expect = EXPECT_END;
2782 else if (current->expect == EXPECT_OBJECT_VALUE)
2783 current->expect = EXPECT_OBJECT_KEY;
2784 else
2785 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2786
2787 stack[n_stack++] = (JsonStack) {
2788 .expect = EXPECT_ARRAY_ELEMENT,
2789 };
2790
2791 break;
2792
2793 case _JSON_BUILD_ARRAY_END:
2794 if (current->expect != EXPECT_ARRAY_ELEMENT) {
2795 r = -EINVAL;
2796 goto finish;
2797 }
2798
2799 assert(n_stack > 1);
2800
2801 r = json_variant_new_array(&add, current->elements, current->n_elements);
2802 if (r < 0)
2803 goto finish;
2804
2805 json_stack_release(current);
2806 n_stack--, current--;
2807
2808 break;
2809
2810 case _JSON_BUILD_STRV: {
2811 char **l;
2812
2813 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2814 r = -EINVAL;
2815 goto finish;
2816 }
2817
2818 l = va_arg(ap, char **);
2819
2820 r = json_variant_new_array_strv(&add, l);
2821 if (r < 0)
2822 goto finish;
2823
2824 if (current->expect == EXPECT_TOPLEVEL)
2825 current->expect = EXPECT_END;
2826 else if (current->expect == EXPECT_OBJECT_VALUE)
2827 current->expect = EXPECT_OBJECT_KEY;
2828 else
2829 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2830
2831 break;
2832 }
2833
2834 case _JSON_BUILD_OBJECT_BEGIN:
2835
2836 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2837 r = -EINVAL;
2838 goto finish;
2839 }
2840
2841 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
2842 r = -ENOMEM;
2843 goto finish;
2844 }
2845 current = stack + n_stack - 1;
2846
2847 if (current->expect == EXPECT_TOPLEVEL)
2848 current->expect = EXPECT_END;
2849 else if (current->expect == EXPECT_OBJECT_VALUE)
2850 current->expect = EXPECT_OBJECT_KEY;
2851 else
2852 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2853
2854 stack[n_stack++] = (JsonStack) {
2855 .expect = EXPECT_OBJECT_KEY,
2856 };
2857
2858 break;
2859
2860 case _JSON_BUILD_OBJECT_END:
2861
2862 if (current->expect != EXPECT_OBJECT_KEY) {
2863 r = -EINVAL;
2864 goto finish;
2865 }
2866
2867 assert(n_stack > 1);
2868
2869 r = json_variant_new_object(&add, current->elements, current->n_elements);
2870 if (r < 0)
2871 goto finish;
2872
2873 json_stack_release(current);
2874 n_stack--, current--;
2875
2876 break;
2877
2878 case _JSON_BUILD_PAIR: {
2879 const char *n;
2880
2881 if (current->expect != EXPECT_OBJECT_KEY) {
2882 r = -EINVAL;
2883 goto finish;
2884 }
2885
2886 n = va_arg(ap, const char *);
2887
2888 r = json_variant_new_string(&add, n);
2889 if (r < 0)
2890 goto finish;
2891
2892 current->expect = EXPECT_OBJECT_VALUE;
2893 break;
2894 }}
2895
2896 if (add) {
2897 if (!GREEDY_REALLOC(current->elements, current->n_elements_allocated, current->n_elements + 1)) {
2898 r = -ENOMEM;
2899 goto finish;
2900 }
2901
2902 current->elements[current->n_elements++] = add;
2903 }
2904 }
2905
2906done:
2907 assert(n_stack == 1);
2908 assert(stack[0].n_elements == 1);
2909
2910 *ret = json_variant_ref(stack[0].elements[0]);
2911 r = 0;
2912
2913finish:
2914 for (i = 0; i < n_stack; i++)
2915 json_stack_release(stack + i);
2916
2917 free(stack);
2918
2919 va_end(ap);
2920
2921 return r;
2922}
2923
2924int json_build(JsonVariant **ret, ...) {
2925 va_list ap;
2926 int r;
2927
2928 va_start(ap, ret);
2929 r = json_buildv(ret, ap);
2930 va_end(ap);
2931
2932 return r;
2933}
2934
2935int json_log_internal(
2936 JsonVariant *variant,
2937 int level,
2938 int error,
2939 const char *file,
2940 int line,
2941 const char *func,
2942 const char *format, ...) {
2943
2944 PROTECT_ERRNO;
2945
2946 unsigned source_line, source_column;
2947 char buffer[LINE_MAX];
2948 const char *source;
2949 va_list ap;
2950 int r;
2951
2952 if (error < 0)
2953 error = -error;
2954
2955 errno = error;
2956
2957 va_start(ap, format);
2958 (void) vsnprintf(buffer, sizeof buffer, format, ap);
2959 va_end(ap);
2960
2961 if (variant) {
2962 r = json_variant_get_source(variant, &source, &source_line, &source_column);
2963 if (r < 0)
2964 return r;
2965 } else {
2966 source = NULL;
2967 source_line = 0;
2968 source_column = 0;
2969 }
2970
2971 if (source && source_line > 0 && source_column > 0)
2972 return log_struct_internal(
2973 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
2974 error,
2975 file, line, func,
2976 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
2977 "CONFIG_FILE=%s", source,
2978 "CONFIG_LINE=%u", source_line,
2979 "CONFIG_COLUMN=%u", source_column,
2980 LOG_MESSAGE("%s:%u: %s", source, line, buffer),
2981 NULL);
2982 else
2983 return log_struct_internal(
2984 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
2985 error,
2986 file, line, func,
2987 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
2988 LOG_MESSAGE("%s", buffer),
2989 NULL);
2990}
2991
2992int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata) {
2993 const JsonDispatch *p;
2994 size_t i, n, m;
2995 int r, done = 0;
2996 bool *found;
2997
2998 if (!json_variant_is_object(v)) {
2999 json_log(v, flags, 0, "JSON variant is not an object.");
3000
3001 if (flags & JSON_PERMISSIVE)
3002 return 0;
3003
3004 return -EINVAL;
3005 }
3006
3007 for (p = table, m = 0; p->name; p++)
3008 m++;
3009
3010 found = newa0(bool, m);
3011
3012 n = json_variant_elements(v);
3013 for (i = 0; i < n; i += 2) {
3014 JsonVariant *key, *value;
3015
3016 assert_se(key = json_variant_by_index(v, i));
3017 assert_se(value = json_variant_by_index(v, i+1));
3018
3019 for (p = table; p->name; p++)
3020 if (p->name == (const char*) -1 ||
3021 streq_ptr(json_variant_string(key), p->name))
3022 break;
3023
3024 if (p->name) { /* Found a matching entry! :-) */
3025 JsonDispatchFlags merged_flags;
3026
3027 merged_flags = flags | p->flags;
3028
3029 if (p->type != _JSON_VARIANT_TYPE_INVALID &&
3030 !json_variant_has_type(value, p->type)) {
3031
3032 json_log(value, merged_flags, 0,
3033 "Object field '%s' has wrong type %s, expected %s.", json_variant_string(key),
3034 json_variant_type_to_string(json_variant_type(value)), json_variant_type_to_string(p->type));
3035
3036 if (merged_flags & JSON_PERMISSIVE)
3037 continue;
3038
3039 return -EINVAL;
3040 }
3041
3042 if (found[p-table]) {
3043 json_log(value, merged_flags, 0, "Duplicate object field '%s'.", json_variant_string(key));
3044
3045 if (merged_flags & JSON_PERMISSIVE)
3046 continue;
3047
3048 return -ENOTUNIQ;
3049 }
3050
3051 found[p-table] = true;
3052
3053 if (p->callback) {
3054 r = p->callback(json_variant_string(key), value, merged_flags, (uint8_t*) userdata + p->offset);
3055 if (r < 0) {
3056 if (merged_flags & JSON_PERMISSIVE)
3057 continue;
3058
3059 return r;
3060 }
3061 }
3062
3063 done ++;
3064
3065 } else { /* Didn't find a matching entry! :-( */
3066
3067 if (bad) {
3068 r = bad(json_variant_string(key), value, flags, userdata);
3069 if (r < 0) {
3070 if (flags & JSON_PERMISSIVE)
3071 continue;
3072
3073 return r;
3074 } else
3075 done ++;
3076
3077 } else {
3078 json_log(value, flags, 0, "Unexpected object field '%s'.", json_variant_string(key));
3079
3080 if (flags & JSON_PERMISSIVE)
3081 continue;
3082
3083 return -EADDRNOTAVAIL;
3084 }
3085 }
3086 }
3087
3088 for (p = table; p->name; p++) {
3089 JsonDispatchFlags merged_flags = p->flags | flags;
3090
3091 if ((merged_flags & JSON_MANDATORY) && !found[p-table]) {
3092 json_log(v, merged_flags, 0, "Missing object field '%s'.", p->name);
3093
3094 if ((merged_flags & JSON_PERMISSIVE))
3095 continue;
3096
3097 return -ENXIO;
3098 }
3099 }
3100
3101 return done;
3102}
3103
3104int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3105 bool *b = userdata;
3106
3107 assert(variant);
3108 assert(b);
3109
3110 if (!json_variant_is_boolean(variant)) {
3111 json_log(variant, flags, 0, "JSON field '%s' is not a boolean.", strna(name));
3112 return -EINVAL;
3113 }
3114
3115 *b = json_variant_boolean(variant);
3116 return 0;
3117}
3118
3119int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3120 int *b = userdata;
3121
3122 assert(variant);
3123 assert(b);
3124
3125 if (!json_variant_is_boolean(variant)) {
3126 json_log(variant, flags, 0, "JSON field '%s' is not a boolean.", strna(name));
3127 return -EINVAL;
3128 }
3129
3130 *b = json_variant_boolean(variant);
3131 return 0;
3132}
3133
3134int json_dispatch_integer(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3135 intmax_t *i = userdata;
3136
3137 assert(variant);
3138 assert(i);
3139
3140 if (!json_variant_is_integer(variant)) {
3141 json_log(variant, flags, 0, "JSON field '%s' is not an integer.", strna(name));
3142 return -EINVAL;
3143 }
3144
3145 *i = json_variant_integer(variant);
3146 return 0;
3147}
3148
3149int json_dispatch_unsigned(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3150 uintmax_t *u = userdata;
3151
3152 assert(variant);
3153 assert(u);
3154
3155 if (!json_variant_is_unsigned(variant)) {
3156 json_log(variant, flags, 0, "JSON field '%s' is not an unsigned integer.", strna(name));
3157 return -EINVAL;
3158 }
3159
3160 *u = json_variant_unsigned(variant);
3161 return 0;
3162}
3163
3164int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3165 uint32_t *u = userdata;
3166
3167 assert(variant);
3168 assert(u);
3169
3170 if (!json_variant_is_unsigned(variant)) {
3171 json_log(variant, flags, 0, "JSON field '%s' is not an unsigned integer.", strna(name));
3172 return -EINVAL;
3173 }
3174
3175 if (json_variant_unsigned(variant) > UINT32_MAX) {
3176 json_log(variant, flags, 0, "JSON field '%s' out of bounds.", strna(name));
3177 return -ERANGE;
3178 }
3179
3180 *u = (uint32_t) json_variant_unsigned(variant);
3181 return 0;
3182}
3183
3184int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3185 int32_t *i = userdata;
3186
3187 assert(variant);
3188 assert(i);
3189
3190 if (!json_variant_is_integer(variant)) {
3191 json_log(variant, flags, 0, "JSON field '%s' is not an integer.", strna(name));
3192 return -EINVAL;
3193 }
3194
3195 if (json_variant_integer(variant) < INT32_MIN || json_variant_integer(variant) > INT32_MAX) {
3196 json_log(variant, flags, 0, "JSON field '%s' out of bounds.", strna(name));
3197 return -ERANGE;
3198 }
3199
3200 *i = (int32_t) json_variant_integer(variant);
3201 return 0;
3202}
3203
3204int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3205 char **s = userdata;
3206 int r;
3207
3208 assert(variant);
3209 assert(s);
3210
3211 if (json_variant_is_null(variant)) {
3212 *s = mfree(*s);
3213 return 0;
3214 }
3215
3216 if (!json_variant_is_string(variant)) {
3217 json_log(variant, flags, 0, "JSON field '%s' is not a string.", strna(name));
3218 return -EINVAL;
3219 }
3220
3221 r = free_and_strdup(s, json_variant_string(variant));
3222 if (r < 0)
3223 return json_log(variant, flags, r, "Failed to allocate string: %m");
3224
3225 return 0;
3226}
3227
3228int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3229 _cleanup_strv_free_ char **l = NULL;
3230 char ***s = userdata;
3231 size_t i;
3232 int r;
3233
3234 assert(variant);
3235 assert(s);
3236
3237 if (json_variant_is_null(variant)) {
3238 *s = strv_free(*s);
3239 return 0;
3240 }
3241
3242 if (!json_variant_is_array(variant)) {
3243 json_log(variant, 0, flags, "JSON field '%s' is not an array.", strna(name));
3244 return -EINVAL;
3245 }
3246
3247 for (i = 0; i < json_variant_elements(variant); i++) {
3248 JsonVariant *e;
3249
3250 assert_se(e = json_variant_by_index(variant, i));
3251
3252 if (!json_variant_is_string(e)) {
3253 json_log(e, 0, flags, "JSON array element is not a string.");
3254 return -EINVAL;
3255 }
3256
3257 r = strv_extend(&l, json_variant_string(e));
3258 if (r < 0)
3259 return json_log(variant, flags, r, "Failed to append array element: %m");
3260 }
3261
3262 strv_free_and_replace(*s, l);
3263 return 0;
3264}
3265
3266int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3267 JsonVariant **p = userdata;
3268
3269 assert(variant);
3270 assert(p);
3271
3272 json_variant_unref(*p);
3273 *p = json_variant_ref(variant);
3274
3275 return 0;
3276}
3277
3278static const char* const json_variant_type_table[_JSON_VARIANT_TYPE_MAX] = {
3279 [JSON_VARIANT_STRING] = "string",
3280 [JSON_VARIANT_INTEGER] = "integer",
3281 [JSON_VARIANT_UNSIGNED] = "unsigned",
3282 [JSON_VARIANT_REAL] = "real",
3283 [JSON_VARIANT_NUMBER] = "number",
3284 [JSON_VARIANT_BOOLEAN] = "boolean",
3285 [JSON_VARIANT_ARRAY] = "array",
3286 [JSON_VARIANT_OBJECT] = "object",
3287 [JSON_VARIANT_NULL] = "null",
3288};
3289
3290DEFINE_STRING_TABLE_LOOKUP(json_variant_type, JsonVariantType);