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