]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/json.c
Add open_memstream_unlocked() wrapper
[thirdparty/systemd.git] / src / shared / json.c
CommitLineData
cd0b6c53
LP
1/* SPDX-License-Identifier: LGPL-2.1+ */
2
3#include <errno.h>
ca78ad1d 4#include <locale.h>
cd0b6c53
LP
5#include <math.h>
6#include <stdarg.h>
cd0b6c53
LP
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
2fe21124 1560 f = open_memstream_unlocked(&s, &sz);
cd0b6c53
LP
1561 if (!f)
1562 return -ENOMEM;
1563
cd0b6c53
LP
1564 json_variant_dump(v, flags, f, NULL);
1565
1566 r = fflush_and_check(f);
1567 }
1568 if (r < 0)
1569 return r;
1570
1571 assert(s);
1572 *ret = TAKE_PTR(s);
1573
1574 return (int) sz;
1575}
1576
897f099b 1577void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix) {
cd0b6c53
LP
1578 if (!v)
1579 return;
1580
1581 if (!f)
1582 f = stdout;
1583
1584 print_source(f, v, flags, false);
1585
ab91733c
LP
1586 if (((flags & (JSON_FORMAT_COLOR_AUTO|JSON_FORMAT_COLOR)) == JSON_FORMAT_COLOR_AUTO) && colors_enabled())
1587 flags |= JSON_FORMAT_COLOR;
1588
cd0b6c53
LP
1589 if (flags & JSON_FORMAT_SSE)
1590 fputs("data: ", f);
1591 if (flags & JSON_FORMAT_SEQ)
1592 fputc('\x1e', f); /* ASCII Record Separator */
1593
1594 json_format(f, v, flags, prefix);
1595
1596 if (flags & (JSON_FORMAT_PRETTY|JSON_FORMAT_SEQ|JSON_FORMAT_SSE|JSON_FORMAT_NEWLINE))
1597 fputc('\n', f);
1598 if (flags & JSON_FORMAT_SSE)
1599 fputc('\n', f); /* In case of SSE add a second newline */
1600}
1601
1602static int json_variant_copy(JsonVariant **nv, JsonVariant *v) {
1603 JsonVariantType t;
1604 JsonVariant *c;
1605 JsonValue value;
1606 const void *source;
1607 size_t k;
1608
1609 assert(nv);
1610 assert(v);
1611
1612 /* Let's copy the simple types literally, and the larger types by references */
1613 t = json_variant_type(v);
1614 switch (t) {
1615 case JSON_VARIANT_INTEGER:
1616 k = sizeof(intmax_t);
1617 value.integer = json_variant_integer(v);
1618 source = &value;
1619 break;
1620
1621 case JSON_VARIANT_UNSIGNED:
1622 k = sizeof(uintmax_t);
1623 value.unsig = json_variant_unsigned(v);
1624 source = &value;
1625 break;
1626
1627 case JSON_VARIANT_REAL:
1628 k = sizeof(long double);
1629 value.real = json_variant_real(v);
1630 source = &value;
1631 break;
1632
1633 case JSON_VARIANT_BOOLEAN:
1634 k = sizeof(bool);
1635 value.boolean = json_variant_boolean(v);
1636 source = &value;
1637 break;
1638
1639 case JSON_VARIANT_NULL:
1640 k = 0;
1641 source = NULL;
1642 break;
1643
1644 case JSON_VARIANT_STRING:
1645 source = json_variant_string(v);
1646 k = strnlen(source, INLINE_STRING_MAX + 1);
1647 if (k <= INLINE_STRING_MAX) {
1648 k ++;
1649 break;
1650 }
1651
1652 _fallthrough_;
1653
1654 default:
1655 /* Everything else copy by reference */
1656
1657 c = malloc0(offsetof(JsonVariant, reference) + sizeof(JsonVariant*));
1658 if (!c)
1659 return -ENOMEM;
1660
1661 c->n_ref = 1;
1662 c->type = t;
1663 c->is_reference = true;
1664 c->reference = json_variant_ref(json_variant_normalize(v));
1665
1666 *nv = c;
1667 return 0;
1668 }
1669
1670 c = malloc0(offsetof(JsonVariant, value) + k);
1671 if (!c)
1672 return -ENOMEM;
1673
1674 c->n_ref = 1;
1675 c->type = t;
1676
1677 memcpy_safe(&c->value, source, k);
1678
1679 *nv = c;
1680 return 0;
1681}
1682
1683static bool json_single_ref(JsonVariant *v) {
1684
1685 /* Checks whether the caller is the single owner of the object, i.e. can get away with changing it */
1686
d520d519 1687 if (!json_variant_is_regular(v))
cd0b6c53
LP
1688 return false;
1689
1690 if (v->is_embedded)
1691 return json_single_ref(v->parent);
1692
1693 assert(v->n_ref > 0);
1694 return v->n_ref == 1;
1695}
1696
1697static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned line, unsigned column) {
1698 JsonVariant *w;
1699 int r;
1700
1701 assert(v);
1702
1703 /* Patch in source and line/column number. Tries to do this in-place if the caller is the sole referencer of
1704 * the object. If not, allocates a new object, possibly a surrogate for the original one */
1705
1706 if (!*v)
1707 return 0;
1708
1709 if (source && line > source->max_line)
1710 source->max_line = line;
1711 if (source && column > source->max_column)
1712 source->max_column = column;
1713
d520d519 1714 if (!json_variant_is_regular(*v)) {
cd0b6c53
LP
1715
1716 if (!source && line == 0 && column == 0)
1717 return 0;
1718
1719 } else {
1720 if (json_source_equal((*v)->source, source) &&
1721 (*v)->line == line &&
1722 (*v)->column == column)
1723 return 0;
1724
1725 if (json_single_ref(*v)) { /* Sole reference? */
1726 json_source_unref((*v)->source);
1727 (*v)->source = json_source_ref(source);
1728 (*v)->line = line;
1729 (*v)->column = column;
1730 return 1;
1731 }
1732 }
1733
1734 r = json_variant_copy(&w, *v);
1735 if (r < 0)
1736 return r;
1737
d520d519 1738 assert(json_variant_is_regular(w));
cd0b6c53
LP
1739 assert(!w->is_embedded);
1740 assert(w->n_ref == 1);
1741 assert(!w->source);
1742
1743 w->source = json_source_ref(source);
1744 w->line = line;
1745 w->column = column;
1746
1747 json_variant_unref(*v);
1748 *v = w;
1749
1750 return 1;
1751}
1752
1753static void inc_lines_columns(unsigned *line, unsigned *column, const char *s, size_t n) {
1754 assert(line);
1755 assert(column);
1756 assert(s || n == 0);
1757
1758 while (n > 0) {
cd0b6c53
LP
1759 if (*s == '\n') {
1760 (*line)++;
1761 *column = 1;
df7f9e0b 1762 } else if ((signed char) *s >= 0 && *s < 127) /* Process ASCII chars quickly */
cd0b6c53
LP
1763 (*column)++;
1764 else {
1765 int w;
1766
92e068b4 1767 w = utf8_encoded_valid_unichar(s, n);
cd0b6c53
LP
1768 if (w < 0) /* count invalid unichars as normal characters */
1769 w = 1;
1770 else if ((size_t) w > n) /* never read more than the specified number of characters */
1771 w = (int) n;
1772
1773 (*column)++;
1774
1775 s += w;
1776 n -= w;
1777 continue;
1778 }
1779
1780 s++;
1781 n--;
1782 }
1783}
1784
1785static int unhex_ucs2(const char *c, uint16_t *ret) {
1786 int aa, bb, cc, dd;
1787 uint16_t x;
1788
1789 assert(c);
1790 assert(ret);
1791
1792 aa = unhexchar(c[0]);
1793 if (aa < 0)
1794 return -EINVAL;
1795
1796 bb = unhexchar(c[1]);
1797 if (bb < 0)
1798 return -EINVAL;
1799
1800 cc = unhexchar(c[2]);
1801 if (cc < 0)
1802 return -EINVAL;
1803
1804 dd = unhexchar(c[3]);
1805 if (dd < 0)
1806 return -EINVAL;
1807
1808 x = ((uint16_t) aa << 12) |
1809 ((uint16_t) bb << 8) |
1810 ((uint16_t) cc << 4) |
1811 ((uint16_t) dd);
1812
1813 if (x <= 0)
1814 return -EINVAL;
1815
1816 *ret = x;
1817
1818 return 0;
1819}
1820
1821static int json_parse_string(const char **p, char **ret) {
1822 _cleanup_free_ char *s = NULL;
1823 size_t n = 0, allocated = 0;
1824 const char *c;
1825
1826 assert(p);
1827 assert(*p);
1828 assert(ret);
1829
1830 c = *p;
1831
1832 if (*c != '"')
1833 return -EINVAL;
1834
1835 c++;
1836
1837 for (;;) {
1838 int len;
1839
1840 /* Check for EOF */
1841 if (*c == 0)
1842 return -EINVAL;
1843
1844 /* Check for control characters 0x00..0x1f */
1845 if (*c > 0 && *c < ' ')
1846 return -EINVAL;
1847
1848 /* Check for control character 0x7f */
1849 if (*c == 0x7f)
1850 return -EINVAL;
1851
1852 if (*c == '"') {
1853 if (!s) {
1854 s = strdup("");
1855 if (!s)
1856 return -ENOMEM;
1857 } else
1858 s[n] = 0;
1859
1860 *p = c + 1;
1861
490c5a37 1862 *ret = TAKE_PTR(s);
cd0b6c53
LP
1863 return JSON_TOKEN_STRING;
1864 }
1865
1866 if (*c == '\\') {
1867 char ch = 0;
1868 c++;
1869
1870 if (*c == 0)
1871 return -EINVAL;
1872
1873 if (IN_SET(*c, '"', '\\', '/'))
1874 ch = *c;
1875 else if (*c == 'b')
1876 ch = '\b';
1877 else if (*c == 'f')
1878 ch = '\f';
1879 else if (*c == 'n')
1880 ch = '\n';
1881 else if (*c == 'r')
1882 ch = '\r';
1883 else if (*c == 't')
1884 ch = '\t';
1885 else if (*c == 'u') {
1886 char16_t x;
1887 int r;
1888
1889 r = unhex_ucs2(c + 1, &x);
1890 if (r < 0)
1891 return r;
1892
1893 c += 5;
1894
1895 if (!GREEDY_REALLOC(s, allocated, n + 5))
1896 return -ENOMEM;
1897
1898 if (!utf16_is_surrogate(x))
1899 n += utf8_encode_unichar(s + n, (char32_t) x);
1900 else if (utf16_is_trailing_surrogate(x))
1901 return -EINVAL;
1902 else {
1903 char16_t y;
1904
1905 if (c[0] != '\\' || c[1] != 'u')
1906 return -EINVAL;
1907
1908 r = unhex_ucs2(c + 2, &y);
1909 if (r < 0)
1910 return r;
1911
1912 c += 6;
1913
1914 if (!utf16_is_trailing_surrogate(y))
1915 return -EINVAL;
1916
1917 n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y));
1918 }
1919
1920 continue;
1921 } else
1922 return -EINVAL;
1923
1924 if (!GREEDY_REALLOC(s, allocated, n + 2))
1925 return -ENOMEM;
1926
1927 s[n++] = ch;
1928 c ++;
1929 continue;
1930 }
1931
92e068b4 1932 len = utf8_encoded_valid_unichar(c, (size_t) -1);
cd0b6c53
LP
1933 if (len < 0)
1934 return len;
1935
1936 if (!GREEDY_REALLOC(s, allocated, n + len + 1))
1937 return -ENOMEM;
1938
1939 memcpy(s + n, c, len);
1940 n += len;
1941 c += len;
1942 }
1943}
1944
1945static int json_parse_number(const char **p, JsonValue *ret) {
1946 bool negative = false, exponent_negative = false, is_real = false;
1947 long double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
1948 intmax_t i = 0;
1949 uintmax_t u = 0;
1950 const char *c;
1951
1952 assert(p);
1953 assert(*p);
1954 assert(ret);
1955
1956 c = *p;
1957
1958 if (*c == '-') {
1959 negative = true;
1960 c++;
1961 }
1962
1963 if (*c == '0')
1964 c++;
1965 else {
1966 if (!strchr("123456789", *c) || *c == 0)
1967 return -EINVAL;
1968
1969 do {
1970 if (!is_real) {
1971 if (negative) {
1972
1973 if (i < INTMAX_MIN / 10) /* overflow */
1974 is_real = true;
1975 else {
1976 intmax_t t = 10 * i;
1977
1978 if (t < INTMAX_MIN + (*c - '0')) /* overflow */
1979 is_real = true;
1980 else
1981 i = t - (*c - '0');
1982 }
1983 } else {
1984 if (u > UINTMAX_MAX / 10) /* overflow */
1985 is_real = true;
1986 else {
1987 uintmax_t t = 10 * u;
1988
1989 if (t > UINTMAX_MAX - (*c - '0')) /* overflow */
1990 is_real = true;
1991 else
1992 u = t + (*c - '0');
1993 }
1994 }
1995 }
1996
1997 x = 10.0 * x + (*c - '0');
1998
1999 c++;
2000 } while (strchr("0123456789", *c) && *c != 0);
2001 }
2002
2003 if (*c == '.') {
2004 is_real = true;
2005 c++;
2006
2007 if (!strchr("0123456789", *c) || *c == 0)
2008 return -EINVAL;
2009
2010 do {
2011 y = 10.0 * y + (*c - '0');
2012 shift = 10.0 * shift;
2013 c++;
2014 } while (strchr("0123456789", *c) && *c != 0);
2015 }
2016
490c5a37 2017 if (IN_SET(*c, 'e', 'E')) {
cd0b6c53
LP
2018 is_real = true;
2019 c++;
2020
2021 if (*c == '-') {
2022 exponent_negative = true;
2023 c++;
2024 } else if (*c == '+')
2025 c++;
2026
2027 if (!strchr("0123456789", *c) || *c == 0)
2028 return -EINVAL;
2029
2030 do {
2031 exponent = 10.0 * exponent + (*c - '0');
2032 c++;
2033 } while (strchr("0123456789", *c) && *c != 0);
2034 }
2035
2036 *p = c;
2037
2038 if (is_real) {
2039 ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10l((exponent_negative ? -1.0 : 1.0) * exponent);
2040 return JSON_TOKEN_REAL;
2041 } else if (negative) {
2042 ret->integer = i;
2043 return JSON_TOKEN_INTEGER;
2044 } else {
2045 ret->unsig = u;
2046 return JSON_TOKEN_UNSIGNED;
2047 }
2048}
2049
2050int json_tokenize(
2051 const char **p,
2052 char **ret_string,
2053 JsonValue *ret_value,
2054 unsigned *ret_line, /* 'ret_line' returns the line at the beginning of this token */
2055 unsigned *ret_column,
2056 void **state,
2057 unsigned *line, /* 'line' is used as a line state, it always reflect the line we are at after the token was read */
2058 unsigned *column) {
2059
2060 unsigned start_line, start_column;
2061 const char *start, *c;
2062 size_t n;
2063 int t, r;
2064
2065 enum {
2066 STATE_NULL,
2067 STATE_VALUE,
2068 STATE_VALUE_POST,
2069 };
2070
2071 assert(p);
2072 assert(*p);
2073 assert(ret_string);
2074 assert(ret_value);
2075 assert(ret_line);
2076 assert(ret_column);
2077 assert(line);
2078 assert(column);
2079 assert(state);
2080
2081 t = PTR_TO_INT(*state);
2082 if (t == STATE_NULL) {
2083 *line = 1;
2084 *column = 1;
2085 t = STATE_VALUE;
2086 }
2087
2088 /* Skip over the whitespace */
2089 n = strspn(*p, WHITESPACE);
2090 inc_lines_columns(line, column, *p, n);
2091 c = *p + n;
2092
2093 /* Remember where we started processing this token */
2094 start = c;
2095 start_line = *line;
2096 start_column = *column;
2097
2098 if (*c == 0) {
2099 *ret_string = NULL;
2100 *ret_value = JSON_VALUE_NULL;
2101 r = JSON_TOKEN_END;
2102 goto finish;
2103 }
2104
2105 switch (t) {
2106
2107 case STATE_VALUE:
2108
2109 if (*c == '{') {
2110 c++;
2111 *state = INT_TO_PTR(STATE_VALUE);
2112 r = JSON_TOKEN_OBJECT_OPEN;
2113 goto null_return;
2114
2115 } else if (*c == '}') {
2116 c++;
2117 *state = INT_TO_PTR(STATE_VALUE_POST);
2118 r = JSON_TOKEN_OBJECT_CLOSE;
2119 goto null_return;
2120
2121 } else if (*c == '[') {
2122 c++;
2123 *state = INT_TO_PTR(STATE_VALUE);
2124 r = JSON_TOKEN_ARRAY_OPEN;
2125 goto null_return;
2126
2127 } else if (*c == ']') {
2128 c++;
2129 *state = INT_TO_PTR(STATE_VALUE_POST);
2130 r = JSON_TOKEN_ARRAY_CLOSE;
2131 goto null_return;
2132
2133 } else if (*c == '"') {
2134
2135 r = json_parse_string(&c, ret_string);
2136 if (r < 0)
2137 return r;
2138
2139 *ret_value = JSON_VALUE_NULL;
2140 *state = INT_TO_PTR(STATE_VALUE_POST);
2141 goto finish;
2142
2143 } else if (strchr("-0123456789", *c)) {
2144
2145 r = json_parse_number(&c, ret_value);
2146 if (r < 0)
2147 return r;
2148
2149 *ret_string = NULL;
2150 *state = INT_TO_PTR(STATE_VALUE_POST);
2151 goto finish;
2152
2153 } else if (startswith(c, "true")) {
2154 *ret_string = NULL;
2155 ret_value->boolean = true;
2156 c += 4;
2157 *state = INT_TO_PTR(STATE_VALUE_POST);
2158 r = JSON_TOKEN_BOOLEAN;
2159 goto finish;
2160
2161 } else if (startswith(c, "false")) {
2162 *ret_string = NULL;
2163 ret_value->boolean = false;
2164 c += 5;
2165 *state = INT_TO_PTR(STATE_VALUE_POST);
2166 r = JSON_TOKEN_BOOLEAN;
2167 goto finish;
2168
2169 } else if (startswith(c, "null")) {
2170 *ret_string = NULL;
2171 *ret_value = JSON_VALUE_NULL;
2172 c += 4;
2173 *state = INT_TO_PTR(STATE_VALUE_POST);
2174 r = JSON_TOKEN_NULL;
2175 goto finish;
2176
2177 }
2178
2179 return -EINVAL;
2180
2181 case STATE_VALUE_POST:
2182
2183 if (*c == ':') {
2184 c++;
2185 *state = INT_TO_PTR(STATE_VALUE);
2186 r = JSON_TOKEN_COLON;
2187 goto null_return;
2188
2189 } else if (*c == ',') {
2190 c++;
2191 *state = INT_TO_PTR(STATE_VALUE);
2192 r = JSON_TOKEN_COMMA;
2193 goto null_return;
2194
2195 } else if (*c == '}') {
2196 c++;
2197 *state = INT_TO_PTR(STATE_VALUE_POST);
2198 r = JSON_TOKEN_OBJECT_CLOSE;
2199 goto null_return;
2200
2201 } else if (*c == ']') {
2202 c++;
2203 *state = INT_TO_PTR(STATE_VALUE_POST);
2204 r = JSON_TOKEN_ARRAY_CLOSE;
2205 goto null_return;
2206 }
2207
2208 return -EINVAL;
2209
2210 default:
2211 assert_not_reached("Unexpected tokenizer state");
2212 }
2213
2214null_return:
2215 *ret_string = NULL;
2216 *ret_value = JSON_VALUE_NULL;
2217
2218finish:
2219 inc_lines_columns(line, column, start, c - start);
2220 *p = c;
2221
2222 *ret_line = start_line;
2223 *ret_column = start_column;
2224
2225 return r;
2226}
2227
2228typedef enum JsonExpect {
2229 /* The following values are used by json_parse() */
2230 EXPECT_TOPLEVEL,
2231 EXPECT_END,
2232 EXPECT_OBJECT_FIRST_KEY,
2233 EXPECT_OBJECT_NEXT_KEY,
2234 EXPECT_OBJECT_COLON,
2235 EXPECT_OBJECT_VALUE,
2236 EXPECT_OBJECT_COMMA,
2237 EXPECT_ARRAY_FIRST_ELEMENT,
2238 EXPECT_ARRAY_NEXT_ELEMENT,
2239 EXPECT_ARRAY_COMMA,
2240
2241 /* And these are used by json_build() */
2242 EXPECT_ARRAY_ELEMENT,
2243 EXPECT_OBJECT_KEY,
2244} JsonExpect;
2245
2246typedef struct JsonStack {
2247 JsonExpect expect;
2248 JsonVariant **elements;
2249 size_t n_elements, n_elements_allocated;
2250 unsigned line_before;
2251 unsigned column_before;
319a4f27 2252 size_t n_suppress; /* When building: if > 0, suppress this many subsequent elements. If == (size_t) -1, suppress all subsequent elements */
cd0b6c53
LP
2253} JsonStack;
2254
2255static void json_stack_release(JsonStack *s) {
2256 assert(s);
2257
2258 json_variant_unref_many(s->elements, s->n_elements);
2259 s->elements = mfree(s->elements);
2260}
2261
2262static int json_parse_internal(
2263 const char **input,
2264 JsonSource *source,
2265 JsonVariant **ret,
2266 unsigned *line,
2267 unsigned *column,
2268 bool continue_end) {
2269
2270 size_t n_stack = 1, n_stack_allocated = 0, i;
2271 unsigned line_buffer = 0, column_buffer = 0;
2272 void *tokenizer_state = NULL;
2273 JsonStack *stack = NULL;
2274 const char *p;
2275 int r;
2276
2277 assert_return(input, -EINVAL);
2278 assert_return(ret, -EINVAL);
2279
2280 p = *input;
2281
2282 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack))
2283 return -ENOMEM;
2284
2285 stack[0] = (JsonStack) {
2286 .expect = EXPECT_TOPLEVEL,
2287 };
2288
2289 if (!line)
2290 line = &line_buffer;
2291 if (!column)
2292 column = &column_buffer;
2293
2294 for (;;) {
2295 _cleanup_free_ char *string = NULL;
2296 unsigned line_token, column_token;
2297 JsonVariant *add = NULL;
2298 JsonStack *current;
2299 JsonValue value;
2300 int token;
2301
2302 assert(n_stack > 0);
2303 current = stack + n_stack - 1;
2304
2305 if (continue_end && current->expect == EXPECT_END)
2306 goto done;
2307
2308 token = json_tokenize(&p, &string, &value, &line_token, &column_token, &tokenizer_state, line, column);
2309 if (token < 0) {
2310 r = token;
2311 goto finish;
2312 }
2313
2314 switch (token) {
2315
2316 case JSON_TOKEN_END:
2317 if (current->expect != EXPECT_END) {
2318 r = -EINVAL;
2319 goto finish;
2320 }
2321
2322 assert(current->n_elements == 1);
2323 assert(n_stack == 1);
2324 goto done;
2325
2326 case JSON_TOKEN_COLON:
2327
2328 if (current->expect != EXPECT_OBJECT_COLON) {
2329 r = -EINVAL;
2330 goto finish;
2331 }
2332
2333 current->expect = EXPECT_OBJECT_VALUE;
2334 break;
2335
2336 case JSON_TOKEN_COMMA:
2337
2338 if (current->expect == EXPECT_OBJECT_COMMA)
2339 current->expect = EXPECT_OBJECT_NEXT_KEY;
2340 else if (current->expect == EXPECT_ARRAY_COMMA)
2341 current->expect = EXPECT_ARRAY_NEXT_ELEMENT;
2342 else {
2343 r = -EINVAL;
2344 goto finish;
2345 }
2346
2347 break;
2348
2349 case JSON_TOKEN_OBJECT_OPEN:
2350
2351 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2352 r = -EINVAL;
2353 goto finish;
2354 }
2355
2356 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
2357 r = -ENOMEM;
2358 goto finish;
2359 }
2360 current = stack + n_stack - 1;
2361
2362 /* Prepare the expect for when we return from the child */
2363 if (current->expect == EXPECT_TOPLEVEL)
2364 current->expect = EXPECT_END;
2365 else if (current->expect == EXPECT_OBJECT_VALUE)
2366 current->expect = EXPECT_OBJECT_COMMA;
2367 else {
2368 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2369 current->expect = EXPECT_ARRAY_COMMA;
2370 }
2371
2372 stack[n_stack++] = (JsonStack) {
2373 .expect = EXPECT_OBJECT_FIRST_KEY,
2374 .line_before = line_token,
2375 .column_before = column_token,
2376 };
2377
2378 current = stack + n_stack - 1;
2379 break;
2380
2381 case JSON_TOKEN_OBJECT_CLOSE:
2382 if (!IN_SET(current->expect, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_COMMA)) {
2383 r = -EINVAL;
2384 goto finish;
2385 }
2386
2387 assert(n_stack > 1);
2388
2389 r = json_variant_new_object(&add, current->elements, current->n_elements);
2390 if (r < 0)
2391 goto finish;
2392
2393 line_token = current->line_before;
2394 column_token = current->column_before;
2395
2396 json_stack_release(current);
2397 n_stack--, current--;
2398
2399 break;
2400
2401 case JSON_TOKEN_ARRAY_OPEN:
2402 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2403 r = -EINVAL;
2404 goto finish;
2405 }
2406
2407 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
2408 r = -ENOMEM;
2409 goto finish;
2410 }
2411 current = stack + n_stack - 1;
2412
2413 /* Prepare the expect for when we return from the child */
2414 if (current->expect == EXPECT_TOPLEVEL)
2415 current->expect = EXPECT_END;
2416 else if (current->expect == EXPECT_OBJECT_VALUE)
2417 current->expect = EXPECT_OBJECT_COMMA;
2418 else {
2419 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2420 current->expect = EXPECT_ARRAY_COMMA;
2421 }
2422
2423 stack[n_stack++] = (JsonStack) {
2424 .expect = EXPECT_ARRAY_FIRST_ELEMENT,
2425 .line_before = line_token,
2426 .column_before = column_token,
2427 };
2428
2429 break;
2430
2431 case JSON_TOKEN_ARRAY_CLOSE:
2432 if (!IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_COMMA)) {
2433 r = -EINVAL;
2434 goto finish;
2435 }
2436
2437 assert(n_stack > 1);
2438
2439 r = json_variant_new_array(&add, current->elements, current->n_elements);
2440 if (r < 0)
2441 goto finish;
2442
2443 line_token = current->line_before;
2444 column_token = current->column_before;
2445
2446 json_stack_release(current);
2447 n_stack--, current--;
2448 break;
2449
2450 case JSON_TOKEN_STRING:
2451 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)) {
2452 r = -EINVAL;
2453 goto finish;
2454 }
2455
2456 r = json_variant_new_string(&add, string);
2457 if (r < 0)
2458 goto finish;
2459
2460 if (current->expect == EXPECT_TOPLEVEL)
2461 current->expect = EXPECT_END;
2462 else if (IN_SET(current->expect, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_NEXT_KEY))
2463 current->expect = EXPECT_OBJECT_COLON;
2464 else if (current->expect == EXPECT_OBJECT_VALUE)
2465 current->expect = EXPECT_OBJECT_COMMA;
2466 else {
2467 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2468 current->expect = EXPECT_ARRAY_COMMA;
2469 }
2470
2471 break;
2472
2473 case JSON_TOKEN_REAL:
2474 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2475 r = -EINVAL;
2476 goto finish;
2477 }
2478
2479 r = json_variant_new_real(&add, value.real);
2480 if (r < 0)
2481 goto finish;
2482
2483 if (current->expect == EXPECT_TOPLEVEL)
2484 current->expect = EXPECT_END;
2485 else if (current->expect == EXPECT_OBJECT_VALUE)
2486 current->expect = EXPECT_OBJECT_COMMA;
2487 else {
2488 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2489 current->expect = EXPECT_ARRAY_COMMA;
2490 }
2491
2492 break;
2493
2494 case JSON_TOKEN_INTEGER:
2495 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2496 r = -EINVAL;
2497 goto finish;
2498 }
2499
2500 r = json_variant_new_integer(&add, value.integer);
2501 if (r < 0)
2502 goto finish;
2503
2504 if (current->expect == EXPECT_TOPLEVEL)
2505 current->expect = EXPECT_END;
2506 else if (current->expect == EXPECT_OBJECT_VALUE)
2507 current->expect = EXPECT_OBJECT_COMMA;
2508 else {
2509 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2510 current->expect = EXPECT_ARRAY_COMMA;
2511 }
2512
2513 break;
2514
2515 case JSON_TOKEN_UNSIGNED:
2516 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2517 r = -EINVAL;
2518 goto finish;
2519 }
2520
2521 r = json_variant_new_unsigned(&add, value.unsig);
2522 if (r < 0)
2523 goto finish;
2524
2525 if (current->expect == EXPECT_TOPLEVEL)
2526 current->expect = EXPECT_END;
2527 else if (current->expect == EXPECT_OBJECT_VALUE)
2528 current->expect = EXPECT_OBJECT_COMMA;
2529 else {
2530 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2531 current->expect = EXPECT_ARRAY_COMMA;
2532 }
2533
2534 break;
2535
2536 case JSON_TOKEN_BOOLEAN:
2537 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2538 r = -EINVAL;
2539 goto finish;
2540 }
2541
2542 r = json_variant_new_boolean(&add, value.boolean);
2543 if (r < 0)
2544 goto finish;
2545
2546 if (current->expect == EXPECT_TOPLEVEL)
2547 current->expect = EXPECT_END;
2548 else if (current->expect == EXPECT_OBJECT_VALUE)
2549 current->expect = EXPECT_OBJECT_COMMA;
2550 else {
2551 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2552 current->expect = EXPECT_ARRAY_COMMA;
2553 }
2554
2555 break;
2556
2557 case JSON_TOKEN_NULL:
2558 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT)) {
2559 r = -EINVAL;
2560 goto finish;
2561 }
2562
2563 r = json_variant_new_null(&add);
2564 if (r < 0)
2565 goto finish;
2566
2567 if (current->expect == EXPECT_TOPLEVEL)
2568 current->expect = EXPECT_END;
2569 else if (current->expect == EXPECT_OBJECT_VALUE)
2570 current->expect = EXPECT_OBJECT_COMMA;
2571 else {
2572 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
2573 current->expect = EXPECT_ARRAY_COMMA;
2574 }
2575
2576 break;
2577
2578 default:
2579 assert_not_reached("Unexpected token");
2580 }
2581
2582 if (add) {
2583 (void) json_variant_set_source(&add, source, line_token, column_token);
2584
2585 if (!GREEDY_REALLOC(current->elements, current->n_elements_allocated, current->n_elements + 1)) {
2586 r = -ENOMEM;
2587 goto finish;
2588 }
2589
2590 current->elements[current->n_elements++] = add;
2591 }
2592 }
2593
2594done:
2595 assert(n_stack == 1);
2596 assert(stack[0].n_elements == 1);
2597
2598 *ret = json_variant_ref(stack[0].elements[0]);
2599 *input = p;
2600 r = 0;
2601
2602finish:
2603 for (i = 0; i < n_stack; i++)
2604 json_stack_release(stack + i);
2605
2606 free(stack);
2607
2608 return r;
2609}
2610
2611int json_parse(const char *input, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
2612 return json_parse_internal(&input, NULL, ret, ret_line, ret_column, false);
2613}
2614
2615int json_parse_continue(const char **p, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
2616 return json_parse_internal(p, NULL, ret, ret_line, ret_column, true);
2617}
2618
2619int json_parse_file(FILE *f, const char *path, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
2620 _cleanup_(json_source_unrefp) JsonSource *source = NULL;
2621 _cleanup_free_ char *text = NULL;
2622 const char *p;
2623 int r;
2624
2625 if (f)
2626 r = read_full_stream(f, &text, NULL);
2627 else if (path)
2628 r = read_full_file(path, &text, NULL);
2629 else
2630 return -EINVAL;
2631 if (r < 0)
2632 return r;
2633
2634 if (path) {
2635 source = json_source_new(path);
2636 if (!source)
2637 return -ENOMEM;
2638 }
2639
2640 p = text;
2641 return json_parse_internal(&p, source, ret, ret_line, ret_column, false);
2642}
2643
2644int json_buildv(JsonVariant **ret, va_list ap) {
2645 JsonStack *stack = NULL;
2646 size_t n_stack = 1, n_stack_allocated = 0, i;
2647 int r;
2648
2649 assert_return(ret, -EINVAL);
2650
2651 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack))
2652 return -ENOMEM;
2653
2654 stack[0] = (JsonStack) {
2655 .expect = EXPECT_TOPLEVEL,
2656 };
2657
2658 for (;;) {
fcadf032 2659 _cleanup_(json_variant_unrefp) JsonVariant *add = NULL;
319a4f27
LP
2660 size_t n_subtract = 0; /* how much to subtract from current->n_suppress, i.e. how many elements would
2661 * have been added to the current variant */
cd0b6c53
LP
2662 JsonStack *current;
2663 int command;
2664
2665 assert(n_stack > 0);
2666 current = stack + n_stack - 1;
2667
2668 if (current->expect == EXPECT_END)
2669 goto done;
2670
2671 command = va_arg(ap, int);
2672
2673 switch (command) {
2674
2675 case _JSON_BUILD_STRING: {
2676 const char *p;
2677
2678 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2679 r = -EINVAL;
2680 goto finish;
2681 }
2682
2683 p = va_arg(ap, const char *);
2684
319a4f27
LP
2685 if (current->n_suppress == 0) {
2686 r = json_variant_new_string(&add, p);
2687 if (r < 0)
2688 goto finish;
2689 }
2690
2691 n_subtract = 1;
cd0b6c53
LP
2692
2693 if (current->expect == EXPECT_TOPLEVEL)
2694 current->expect = EXPECT_END;
2695 else if (current->expect == EXPECT_OBJECT_VALUE)
2696 current->expect = EXPECT_OBJECT_KEY;
2697 else
2698 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2699
2700 break;
2701 }
2702
2703 case _JSON_BUILD_INTEGER: {
2704 intmax_t j;
2705
2706 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2707 r = -EINVAL;
2708 goto finish;
2709 }
2710
2711 j = va_arg(ap, intmax_t);
2712
319a4f27
LP
2713 if (current->n_suppress == 0) {
2714 r = json_variant_new_integer(&add, j);
2715 if (r < 0)
2716 goto finish;
2717 }
2718
2719 n_subtract = 1;
cd0b6c53
LP
2720
2721 if (current->expect == EXPECT_TOPLEVEL)
2722 current->expect = EXPECT_END;
2723 else if (current->expect == EXPECT_OBJECT_VALUE)
2724 current->expect = EXPECT_OBJECT_KEY;
2725 else
2726 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2727
2728 break;
2729 }
2730
2731 case _JSON_BUILD_UNSIGNED: {
2732 uintmax_t j;
2733
2734 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2735 r = -EINVAL;
2736 goto finish;
2737 }
2738
2739 j = va_arg(ap, uintmax_t);
2740
319a4f27
LP
2741 if (current->n_suppress == 0) {
2742 r = json_variant_new_unsigned(&add, j);
2743 if (r < 0)
2744 goto finish;
2745 }
2746
2747 n_subtract = 1;
cd0b6c53
LP
2748
2749 if (current->expect == EXPECT_TOPLEVEL)
2750 current->expect = EXPECT_END;
2751 else if (current->expect == EXPECT_OBJECT_VALUE)
2752 current->expect = EXPECT_OBJECT_KEY;
2753 else
2754 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2755
2756 break;
2757 }
2758
2759 case _JSON_BUILD_REAL: {
2760 long double d;
2761
2762 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2763 r = -EINVAL;
2764 goto finish;
2765 }
2766
2767 d = va_arg(ap, long double);
2768
319a4f27
LP
2769 if (current->n_suppress == 0) {
2770 r = json_variant_new_real(&add, d);
2771 if (r < 0)
2772 goto finish;
2773 }
2774
2775 n_subtract = 1;
cd0b6c53
LP
2776
2777 if (current->expect == EXPECT_TOPLEVEL)
2778 current->expect = EXPECT_END;
2779 else if (current->expect == EXPECT_OBJECT_VALUE)
2780 current->expect = EXPECT_OBJECT_KEY;
2781 else
2782 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2783
2784 break;
2785 }
2786
2787 case _JSON_BUILD_BOOLEAN: {
2788 bool b;
2789
2790 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2791 r = -EINVAL;
2792 goto finish;
2793 }
2794
2795 b = va_arg(ap, int);
2796
319a4f27
LP
2797 if (current->n_suppress == 0) {
2798 r = json_variant_new_boolean(&add, b);
2799 if (r < 0)
2800 goto finish;
2801 }
2802
2803 n_subtract = 1;
cd0b6c53
LP
2804
2805 if (current->expect == EXPECT_TOPLEVEL)
2806 current->expect = EXPECT_END;
2807 else if (current->expect == EXPECT_OBJECT_VALUE)
2808 current->expect = EXPECT_OBJECT_KEY;
2809 else
2810 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2811
2812 break;
2813 }
2814
2815 case _JSON_BUILD_NULL:
2816
2817 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2818 r = -EINVAL;
2819 goto finish;
2820 }
2821
319a4f27
LP
2822 if (current->n_suppress == 0) {
2823 r = json_variant_new_null(&add);
2824 if (r < 0)
2825 goto finish;
2826 }
2827
2828 n_subtract = 1;
cd0b6c53
LP
2829
2830 if (current->expect == EXPECT_TOPLEVEL)
2831 current->expect = EXPECT_END;
2832 else if (current->expect == EXPECT_OBJECT_VALUE)
2833 current->expect = EXPECT_OBJECT_KEY;
2834 else
2835 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2836
2837 break;
2838
2839 case _JSON_BUILD_VARIANT:
2840
2841 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2842 r = -EINVAL;
2843 goto finish;
2844 }
2845
319a4f27
LP
2846 /* Note that we don't care for current->n_suppress here, after all the variant is already
2847 * allocated anyway... */
cd0b6c53
LP
2848 add = va_arg(ap, JsonVariant*);
2849 if (!add)
2850 add = JSON_VARIANT_MAGIC_NULL;
2851 else
2852 json_variant_ref(add);
2853
319a4f27
LP
2854 n_subtract = 1;
2855
cd0b6c53
LP
2856 if (current->expect == EXPECT_TOPLEVEL)
2857 current->expect = EXPECT_END;
2858 else if (current->expect == EXPECT_OBJECT_VALUE)
2859 current->expect = EXPECT_OBJECT_KEY;
2860 else
2861 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2862
2863 break;
2864
2865 case _JSON_BUILD_LITERAL: {
2866 const char *l;
2867
2868 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2869 r = -EINVAL;
2870 goto finish;
2871 }
2872
2873 l = va_arg(ap, const char *);
2874
319a4f27
LP
2875 if (l) {
2876 /* Note that we don't care for current->n_suppress here, we should generate parsing
2877 * errors even in suppressed object properties */
2878
cd0b6c53
LP
2879 r = json_parse(l, &add, NULL, NULL);
2880 if (r < 0)
2881 goto finish;
319a4f27
LP
2882 } else
2883 add = JSON_VARIANT_MAGIC_NULL;
2884
2885 n_subtract = 1;
cd0b6c53
LP
2886
2887 if (current->expect == EXPECT_TOPLEVEL)
2888 current->expect = EXPECT_END;
2889 else if (current->expect == EXPECT_OBJECT_VALUE)
2890 current->expect = EXPECT_OBJECT_KEY;
2891 else
2892 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2893
2894 break;
2895 }
2896
2897 case _JSON_BUILD_ARRAY_BEGIN:
2898
2899 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2900 r = -EINVAL;
2901 goto finish;
2902 }
2903
2904 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
2905 r = -ENOMEM;
2906 goto finish;
2907 }
2908 current = stack + n_stack - 1;
2909
2910 if (current->expect == EXPECT_TOPLEVEL)
2911 current->expect = EXPECT_END;
2912 else if (current->expect == EXPECT_OBJECT_VALUE)
2913 current->expect = EXPECT_OBJECT_KEY;
2914 else
2915 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2916
2917 stack[n_stack++] = (JsonStack) {
2918 .expect = EXPECT_ARRAY_ELEMENT,
319a4f27
LP
2919 .n_suppress = current->n_suppress != 0 ? (size_t) -1 : 0, /* if we shall suppress the
2920 * new array, then we should
2921 * also suppress all array
2922 * members */
cd0b6c53
LP
2923 };
2924
2925 break;
2926
2927 case _JSON_BUILD_ARRAY_END:
2928 if (current->expect != EXPECT_ARRAY_ELEMENT) {
2929 r = -EINVAL;
2930 goto finish;
2931 }
2932
2933 assert(n_stack > 1);
2934
319a4f27
LP
2935 if (current->n_suppress == 0) {
2936 r = json_variant_new_array(&add, current->elements, current->n_elements);
2937 if (r < 0)
2938 goto finish;
2939 }
2940
2941 n_subtract = 1;
cd0b6c53
LP
2942
2943 json_stack_release(current);
2944 n_stack--, current--;
2945
2946 break;
2947
2948 case _JSON_BUILD_STRV: {
2949 char **l;
2950
2951 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2952 r = -EINVAL;
2953 goto finish;
2954 }
2955
2956 l = va_arg(ap, char **);
2957
319a4f27
LP
2958 if (current->n_suppress == 0) {
2959 r = json_variant_new_array_strv(&add, l);
2960 if (r < 0)
2961 goto finish;
2962 }
2963
2964 n_subtract = 1;
cd0b6c53
LP
2965
2966 if (current->expect == EXPECT_TOPLEVEL)
2967 current->expect = EXPECT_END;
2968 else if (current->expect == EXPECT_OBJECT_VALUE)
2969 current->expect = EXPECT_OBJECT_KEY;
2970 else
2971 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2972
2973 break;
2974 }
2975
2976 case _JSON_BUILD_OBJECT_BEGIN:
2977
2978 if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
2979 r = -EINVAL;
2980 goto finish;
2981 }
2982
2983 if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
2984 r = -ENOMEM;
2985 goto finish;
2986 }
2987 current = stack + n_stack - 1;
2988
2989 if (current->expect == EXPECT_TOPLEVEL)
2990 current->expect = EXPECT_END;
2991 else if (current->expect == EXPECT_OBJECT_VALUE)
2992 current->expect = EXPECT_OBJECT_KEY;
2993 else
2994 assert(current->expect == EXPECT_ARRAY_ELEMENT);
2995
2996 stack[n_stack++] = (JsonStack) {
2997 .expect = EXPECT_OBJECT_KEY,
319a4f27
LP
2998 .n_suppress = current->n_suppress != 0 ? (size_t) -1 : 0, /* if we shall suppress the
2999 * new object, then we should
3000 * also suppress all object
3001 * members */
cd0b6c53
LP
3002 };
3003
3004 break;
3005
3006 case _JSON_BUILD_OBJECT_END:
3007
3008 if (current->expect != EXPECT_OBJECT_KEY) {
3009 r = -EINVAL;
3010 goto finish;
3011 }
3012
3013 assert(n_stack > 1);
3014
319a4f27
LP
3015 if (current->n_suppress == 0) {
3016 r = json_variant_new_object(&add, current->elements, current->n_elements);
3017 if (r < 0)
3018 goto finish;
3019 }
3020
3021 n_subtract = 1;
cd0b6c53
LP
3022
3023 json_stack_release(current);
3024 n_stack--, current--;
3025
3026 break;
3027
3028 case _JSON_BUILD_PAIR: {
3029 const char *n;
3030
3031 if (current->expect != EXPECT_OBJECT_KEY) {
3032 r = -EINVAL;
3033 goto finish;
3034 }
3035
3036 n = va_arg(ap, const char *);
3037
319a4f27
LP
3038 if (current->n_suppress == 0) {
3039 r = json_variant_new_string(&add, n);
3040 if (r < 0)
3041 goto finish;
3042 }
3043
3044 n_subtract = 1;
3045
3046 current->expect = EXPECT_OBJECT_VALUE;
3047 break;
3048 }
3049
3050 case _JSON_BUILD_PAIR_CONDITION: {
3051 const char *n;
3052 bool b;
3053
3054 if (current->expect != EXPECT_OBJECT_KEY) {
3055 r = -EINVAL;
cd0b6c53 3056 goto finish;
319a4f27
LP
3057 }
3058
3059 b = va_arg(ap, int);
3060 n = va_arg(ap, const char *);
3061
3062 if (b && current->n_suppress == 0) {
3063 r = json_variant_new_string(&add, n);
3064 if (r < 0)
3065 goto finish;
3066 }
3067
3068 n_subtract = 1; /* we generated one item */
3069
3070 if (!b && current->n_suppress != (size_t) -1)
3071 current->n_suppress += 2; /* Suppress this one and the next item */
cd0b6c53
LP
3072
3073 current->expect = EXPECT_OBJECT_VALUE;
3074 break;
3075 }}
3076
319a4f27
LP
3077 /* If a variant was generated, add it to our current variant, but only if we are not supposed to suppress additions */
3078 if (add && current->n_suppress == 0) {
cd0b6c53
LP
3079 if (!GREEDY_REALLOC(current->elements, current->n_elements_allocated, current->n_elements + 1)) {
3080 r = -ENOMEM;
3081 goto finish;
3082 }
3083
fcadf032 3084 current->elements[current->n_elements++] = TAKE_PTR(add);
cd0b6c53 3085 }
319a4f27
LP
3086
3087 /* If we are supposed to suppress items, let's subtract how many items where generated from that
3088 * counter. Except if the counter is (size_t) -1, i.e. we shall suppress an infinite number of elements
3089 * on this stack level */
3090 if (current->n_suppress != (size_t) -1) {
3091 if (current->n_suppress <= n_subtract) /* Saturated */
3092 current->n_suppress = 0;
3093 else
3094 current->n_suppress -= n_subtract;
3095 }
cd0b6c53
LP
3096 }
3097
3098done:
3099 assert(n_stack == 1);
3100 assert(stack[0].n_elements == 1);
3101
3102 *ret = json_variant_ref(stack[0].elements[0]);
3103 r = 0;
3104
3105finish:
3106 for (i = 0; i < n_stack; i++)
3107 json_stack_release(stack + i);
3108
3109 free(stack);
3110
cd0b6c53
LP
3111 return r;
3112}
3113
3114int json_build(JsonVariant **ret, ...) {
3115 va_list ap;
3116 int r;
3117
3118 va_start(ap, ret);
3119 r = json_buildv(ret, ap);
3120 va_end(ap);
3121
3122 return r;
3123}
3124
3125int json_log_internal(
3126 JsonVariant *variant,
3127 int level,
3128 int error,
3129 const char *file,
3130 int line,
3131 const char *func,
3132 const char *format, ...) {
3133
3134 PROTECT_ERRNO;
3135
3136 unsigned source_line, source_column;
3137 char buffer[LINE_MAX];
3138 const char *source;
3139 va_list ap;
3140 int r;
3141
fc0f6fbf 3142 errno = ERRNO_VALUE(error);
cd0b6c53
LP
3143
3144 va_start(ap, format);
3145 (void) vsnprintf(buffer, sizeof buffer, format, ap);
3146 va_end(ap);
3147
3148 if (variant) {
3149 r = json_variant_get_source(variant, &source, &source_line, &source_column);
3150 if (r < 0)
3151 return r;
3152 } else {
3153 source = NULL;
3154 source_line = 0;
3155 source_column = 0;
3156 }
3157
3158 if (source && source_line > 0 && source_column > 0)
3159 return log_struct_internal(
3160 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
3161 error,
3162 file, line, func,
3163 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
3164 "CONFIG_FILE=%s", source,
3165 "CONFIG_LINE=%u", source_line,
3166 "CONFIG_COLUMN=%u", source_column,
13a16a2b 3167 LOG_MESSAGE("%s:%u:%u: %s", source, source_line, source_column, buffer),
cd0b6c53
LP
3168 NULL);
3169 else
3170 return log_struct_internal(
3171 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD, level),
3172 error,
3173 file, line, func,
3174 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR,
3175 LOG_MESSAGE("%s", buffer),
3176 NULL);
3177}
3178
3179int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata) {
3180 const JsonDispatch *p;
3181 size_t i, n, m;
3182 int r, done = 0;
3183 bool *found;
3184
3185 if (!json_variant_is_object(v)) {
3186 json_log(v, flags, 0, "JSON variant is not an object.");
3187
3188 if (flags & JSON_PERMISSIVE)
3189 return 0;
3190
3191 return -EINVAL;
3192 }
3193
3194 for (p = table, m = 0; p->name; p++)
3195 m++;
3196
3197 found = newa0(bool, m);
3198
3199 n = json_variant_elements(v);
3200 for (i = 0; i < n; i += 2) {
3201 JsonVariant *key, *value;
3202
3203 assert_se(key = json_variant_by_index(v, i));
3204 assert_se(value = json_variant_by_index(v, i+1));
3205
3206 for (p = table; p->name; p++)
3207 if (p->name == (const char*) -1 ||
3208 streq_ptr(json_variant_string(key), p->name))
3209 break;
3210
3211 if (p->name) { /* Found a matching entry! :-) */
3212 JsonDispatchFlags merged_flags;
3213
3214 merged_flags = flags | p->flags;
3215
3216 if (p->type != _JSON_VARIANT_TYPE_INVALID &&
3217 !json_variant_has_type(value, p->type)) {
3218
3219 json_log(value, merged_flags, 0,
3220 "Object field '%s' has wrong type %s, expected %s.", json_variant_string(key),
3221 json_variant_type_to_string(json_variant_type(value)), json_variant_type_to_string(p->type));
3222
3223 if (merged_flags & JSON_PERMISSIVE)
3224 continue;
3225
3226 return -EINVAL;
3227 }
3228
3229 if (found[p-table]) {
3230 json_log(value, merged_flags, 0, "Duplicate object field '%s'.", json_variant_string(key));
3231
3232 if (merged_flags & JSON_PERMISSIVE)
3233 continue;
3234
3235 return -ENOTUNIQ;
3236 }
3237
3238 found[p-table] = true;
3239
3240 if (p->callback) {
3241 r = p->callback(json_variant_string(key), value, merged_flags, (uint8_t*) userdata + p->offset);
3242 if (r < 0) {
3243 if (merged_flags & JSON_PERMISSIVE)
3244 continue;
3245
3246 return r;
3247 }
3248 }
3249
3250 done ++;
3251
3252 } else { /* Didn't find a matching entry! :-( */
3253
3254 if (bad) {
3255 r = bad(json_variant_string(key), value, flags, userdata);
3256 if (r < 0) {
3257 if (flags & JSON_PERMISSIVE)
3258 continue;
3259
3260 return r;
3261 } else
3262 done ++;
3263
3264 } else {
3265 json_log(value, flags, 0, "Unexpected object field '%s'.", json_variant_string(key));
3266
3267 if (flags & JSON_PERMISSIVE)
3268 continue;
3269
3270 return -EADDRNOTAVAIL;
3271 }
3272 }
3273 }
3274
3275 for (p = table; p->name; p++) {
3276 JsonDispatchFlags merged_flags = p->flags | flags;
3277
3278 if ((merged_flags & JSON_MANDATORY) && !found[p-table]) {
3279 json_log(v, merged_flags, 0, "Missing object field '%s'.", p->name);
3280
3281 if ((merged_flags & JSON_PERMISSIVE))
3282 continue;
3283
3284 return -ENXIO;
3285 }
3286 }
3287
3288 return done;
3289}
3290
3291int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3292 bool *b = userdata;
3293
3294 assert(variant);
3295 assert(b);
3296
02dab76e
LP
3297 if (!json_variant_is_boolean(variant))
3298 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a boolean.", strna(name));
cd0b6c53
LP
3299
3300 *b = json_variant_boolean(variant);
3301 return 0;
3302}
3303
3304int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3305 int *b = userdata;
3306
3307 assert(variant);
3308 assert(b);
3309
02dab76e
LP
3310 if (!json_variant_is_boolean(variant))
3311 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a boolean.", strna(name));
cd0b6c53
LP
3312
3313 *b = json_variant_boolean(variant);
3314 return 0;
3315}
3316
3317int json_dispatch_integer(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3318 intmax_t *i = userdata;
3319
3320 assert(variant);
3321 assert(i);
3322
02dab76e
LP
3323 if (!json_variant_is_integer(variant))
3324 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name));
cd0b6c53
LP
3325
3326 *i = json_variant_integer(variant);
3327 return 0;
3328}
3329
3330int json_dispatch_unsigned(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3331 uintmax_t *u = userdata;
3332
3333 assert(variant);
3334 assert(u);
3335
02dab76e
LP
3336 if (!json_variant_is_unsigned(variant))
3337 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an unsigned integer.", strna(name));
cd0b6c53
LP
3338
3339 *u = json_variant_unsigned(variant);
3340 return 0;
3341}
3342
3343int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3344 uint32_t *u = userdata;
3345
3346 assert(variant);
3347 assert(u);
3348
02dab76e
LP
3349 if (!json_variant_is_unsigned(variant))
3350 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an unsigned integer.", strna(name));
cd0b6c53 3351
02dab76e
LP
3352 if (json_variant_unsigned(variant) > UINT32_MAX)
3353 return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds.", strna(name));
cd0b6c53
LP
3354
3355 *u = (uint32_t) json_variant_unsigned(variant);
3356 return 0;
3357}
3358
3359int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3360 int32_t *i = userdata;
3361
3362 assert(variant);
3363 assert(i);
3364
02dab76e
LP
3365 if (!json_variant_is_integer(variant))
3366 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not an integer.", strna(name));
cd0b6c53 3367
02dab76e
LP
3368 if (json_variant_integer(variant) < INT32_MIN || json_variant_integer(variant) > INT32_MAX)
3369 return json_log(variant, flags, SYNTHETIC_ERRNO(ERANGE), "JSON field '%s' out of bounds.", strna(name));
cd0b6c53
LP
3370
3371 *i = (int32_t) json_variant_integer(variant);
3372 return 0;
3373}
3374
3375int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3376 char **s = userdata;
3377 int r;
3378
3379 assert(variant);
3380 assert(s);
3381
3382 if (json_variant_is_null(variant)) {
3383 *s = mfree(*s);
3384 return 0;
3385 }
3386
02dab76e
LP
3387 if (!json_variant_is_string(variant))
3388 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
cd0b6c53
LP
3389
3390 r = free_and_strdup(s, json_variant_string(variant));
3391 if (r < 0)
3392 return json_log(variant, flags, r, "Failed to allocate string: %m");
3393
3394 return 0;
3395}
3396
3397int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3398 _cleanup_strv_free_ char **l = NULL;
3399 char ***s = userdata;
3400 size_t i;
3401 int r;
3402
3403 assert(variant);
3404 assert(s);
3405
3406 if (json_variant_is_null(variant)) {
3407 *s = strv_free(*s);
3408 return 0;
3409 }
3410
02dab76e
LP
3411 if (!json_variant_is_array(variant))
3412 return json_log(variant, SYNTHETIC_ERRNO(EINVAL), flags, "JSON field '%s' is not an array.", strna(name));
cd0b6c53
LP
3413
3414 for (i = 0; i < json_variant_elements(variant); i++) {
3415 JsonVariant *e;
3416
3417 assert_se(e = json_variant_by_index(variant, i));
3418
02dab76e
LP
3419 if (!json_variant_is_string(e))
3420 return json_log(e, flags, SYNTHETIC_ERRNO(EINVAL), "JSON array element is not a string.");
cd0b6c53
LP
3421
3422 r = strv_extend(&l, json_variant_string(e));
3423 if (r < 0)
3424 return json_log(variant, flags, r, "Failed to append array element: %m");
3425 }
3426
3427 strv_free_and_replace(*s, l);
3428 return 0;
3429}
3430
3431int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
3432 JsonVariant **p = userdata;
3433
3434 assert(variant);
3435 assert(p);
3436
3437 json_variant_unref(*p);
3438 *p = json_variant_ref(variant);
3439
3440 return 0;
3441}
3442
3443static const char* const json_variant_type_table[_JSON_VARIANT_TYPE_MAX] = {
3444 [JSON_VARIANT_STRING] = "string",
3445 [JSON_VARIANT_INTEGER] = "integer",
3446 [JSON_VARIANT_UNSIGNED] = "unsigned",
3447 [JSON_VARIANT_REAL] = "real",
3448 [JSON_VARIANT_NUMBER] = "number",
3449 [JSON_VARIANT_BOOLEAN] = "boolean",
3450 [JSON_VARIANT_ARRAY] = "array",
3451 [JSON_VARIANT_OBJECT] = "object",
3452 [JSON_VARIANT_NULL] = "null",
3453};
3454
3455DEFINE_STRING_TABLE_LOOKUP(json_variant_type, JsonVariantType);