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