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