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