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