1 /* SPDX-License-Identifier: LGPL-2.1+ */
11 #include "sd-messages.h"
13 #include "alloc-util.h"
17 #include "hexdecoct.h"
18 #include "json-internal.h"
21 #include "string-table.h"
22 #include "string-util.h"
24 #include "terminal-util.h"
27 /* Refuse putting together variants with a larger depth than 4K 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
30 * The value was 16k, but it was discovered to be too high on llvm/x86-64. See also the issue #10738. */
31 #define DEPTH_MAX (4U*1024U)
32 assert_cc(DEPTH_MAX
<= UINT16_MAX
);
34 typedef struct JsonSource
{
35 /* When we parse from a file or similar, encodes the filename, to indicate the source of a json variant */
42 /* On x86-64 this whole structure should have a size of 6 * 64 bit = 48 bytes */
45 /* We either maintain a reference counter for this variant itself, or we are embedded into an
46 * array/object, in which case only that surrounding object is ref-counted. (If 'embedded' is false,
50 /* If this JsonVariant is part of an array/object, then this field points to the surrounding
51 * JSON_VARIANT_ARRAY/JSON_VARIANT_OBJECT object. (If 'embedded' is true, see below.) */
55 /* If this was parsed from some file or buffer, this stores where from, as well as the source line/column */
57 unsigned line
, column
;
59 JsonVariantType type
:5;
61 /* A marker whether this variant is embedded into in array/object or not. If true, the 'parent' pointer above
62 * is valid. If false, the 'n_ref' field above is valid instead. */
65 /* In some conditions (for example, if this object is part of an array of strings or objects), we don't store
66 * any data inline, but instead simply reference an external object and act as surrogate of it. In that case
67 * this bool is set, and the external object is referenced through the .reference field below. */
70 /* While comparing two arrays, we use this for marking what we already have seen */
73 /* The current 'depth' of the JsonVariant, i.e. how many levels of member variants this has */
77 /* For simple types we store the value in-line. */
80 /* For objects and arrays we store the number of elements immediately following */
83 /* If is_reference as indicated above is set, this is where the reference object is actually stored. */
84 JsonVariant
*reference
;
86 /* Strings are placed immediately after the structure. Note that when this is a JsonVariant embedded
87 * into an array we might encode strings up to INLINE_STRING_LENGTH characters directly inside the
88 * element, while longer strings are stored as references. When this object is not embedded into an
89 * array, but stand-alone we allocate the right size for the whole structure, i.e. the array might be
90 * much larger than INLINE_STRING_LENGTH.
92 * Note that because we want to allocate arrays of the JsonVariant structure we specify [0] here,
93 * rather than the prettier []. If we wouldn't, then this char array would have undefined size, and so
94 * would the union and then the struct this is included in. And of structures with undefined size we
95 * can't allocate arrays (at least not easily). */
100 /* Inside string arrays we have a series of JasonVariant structures one after the other. In this case, strings longer
101 * than INLINE_STRING_MAX are stored as references, and all shorter ones inline. (This means — on x86-64 — strings up
102 * to 15 chars are stored within the array elements, and all others in separate allocations) */
103 #define INLINE_STRING_MAX (sizeof(JsonVariant) - offsetof(JsonVariant, string) - 1U)
105 /* Let's make sure this structure isn't increased in size accidentally. This check is only for our most relevant arch
108 assert_cc(sizeof(JsonVariant
) == 48U);
109 assert_cc(INLINE_STRING_MAX
== 15U);
112 static JsonSource
* json_source_new(const char *name
) {
117 s
= malloc(offsetof(JsonSource
, name
) + strlen(name
) + 1);
124 strcpy(s
->name
, name
);
129 DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(JsonSource
, json_source
, mfree
);
131 static bool json_source_equal(JsonSource
*a
, JsonSource
*b
) {
138 return streq(a
->name
, b
->name
);
141 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonSource
*, json_source_unref
);
143 /* There are four kind of JsonVariant* pointers:
146 * 2. A 'regular' one, i.e. pointing to malloc() memory
147 * 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.
148 * 4. A 'const string' one, i.e. a pointer to a const string.
150 * The four kinds of pointers can be discerned like this:
152 * Detecting #1 is easy, just compare with NULL. Detecting #3 is similarly easy: all magic pointers are below
153 * _JSON_VARIANT_MAGIC_MAX (which is pretty low, within the first memory page, which is special on Linux and other
154 * 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,
155 * otherwise #4. This makes use of the fact that malloc() will return "maximum aligned" memory, which definitely
156 * means the pointer is even. This means we can use the uneven pointers to reference static strings, as long as we
157 * make sure that all static strings used like this are aligned to 2 (or higher), and that we mask the bit on
158 * access. The JSON_VARIANT_STRING_CONST() macro encodes strings as JsonVariant* pointers, with the bit set. */
160 static bool json_variant_is_magic(const JsonVariant
*v
) {
164 return v
< _JSON_VARIANT_MAGIC_MAX
;
167 static bool json_variant_is_const_string(const JsonVariant
*v
) {
169 if (v
< _JSON_VARIANT_MAGIC_MAX
)
172 /* A proper JsonVariant is aligned to whatever malloc() aligns things too, which is definitely not uneven. We
173 * hence use all uneven pointers as indicators for const strings. */
175 return (((uintptr_t) v
) & 1) != 0;
178 static bool json_variant_is_regular(const JsonVariant
*v
) {
180 if (v
< _JSON_VARIANT_MAGIC_MAX
)
183 return (((uintptr_t) v
) & 1) == 0;
186 static JsonVariant
*json_variant_dereference(JsonVariant
*v
) {
188 /* Recursively dereference variants that are references to other variants */
193 if (!json_variant_is_regular(v
))
196 if (!v
->is_reference
)
199 return json_variant_dereference(v
->reference
);
202 static uint16_t json_variant_depth(JsonVariant
*v
) {
204 v
= json_variant_dereference(v
);
208 if (!json_variant_is_regular(v
))
214 static JsonVariant
*json_variant_normalize(JsonVariant
*v
) {
216 /* Converts json variants to their normalized form, i.e. fully dereferenced and wherever possible converted to
217 * the "magic" version if there is one */
222 v
= json_variant_dereference(v
);
224 switch (json_variant_type(v
)) {
226 case JSON_VARIANT_BOOLEAN
:
227 return json_variant_boolean(v
) ? JSON_VARIANT_MAGIC_TRUE
: JSON_VARIANT_MAGIC_FALSE
;
229 case JSON_VARIANT_NULL
:
230 return JSON_VARIANT_MAGIC_NULL
;
232 case JSON_VARIANT_INTEGER
:
233 return json_variant_integer(v
) == 0 ? JSON_VARIANT_MAGIC_ZERO_INTEGER
: v
;
235 case JSON_VARIANT_UNSIGNED
:
236 return json_variant_unsigned(v
) == 0 ? JSON_VARIANT_MAGIC_ZERO_UNSIGNED
: v
;
238 case JSON_VARIANT_REAL
:
239 #pragma GCC diagnostic push
240 #pragma GCC diagnostic ignored "-Wfloat-equal"
241 return json_variant_real(v
) == 0.0 ? JSON_VARIANT_MAGIC_ZERO_REAL
: v
;
242 #pragma GCC diagnostic pop
244 case JSON_VARIANT_STRING
:
245 return isempty(json_variant_string(v
)) ? JSON_VARIANT_MAGIC_EMPTY_STRING
: v
;
247 case JSON_VARIANT_ARRAY
:
248 return json_variant_elements(v
) == 0 ? JSON_VARIANT_MAGIC_EMPTY_ARRAY
: v
;
250 case JSON_VARIANT_OBJECT
:
251 return json_variant_elements(v
) == 0 ? JSON_VARIANT_MAGIC_EMPTY_OBJECT
: v
;
258 static JsonVariant
*json_variant_conservative_normalize(JsonVariant
*v
) {
260 /* Much like json_variant_normalize(), but won't simplify if the variant has a source/line location attached to
261 * it, in order not to lose context */
266 if (!json_variant_is_regular(v
))
269 if (v
->source
|| v
->line
> 0 || v
->column
> 0)
272 return json_variant_normalize(v
);
275 static int json_variant_new(JsonVariant
**ret
, JsonVariantType type
, size_t space
) {
278 assert_return(ret
, -EINVAL
);
280 v
= malloc0(offsetof(JsonVariant
, value
) + space
);
291 int json_variant_new_integer(JsonVariant
**ret
, intmax_t i
) {
295 assert_return(ret
, -EINVAL
);
298 *ret
= JSON_VARIANT_MAGIC_ZERO_INTEGER
;
302 r
= json_variant_new(&v
, JSON_VARIANT_INTEGER
, sizeof(i
));
306 v
->value
.integer
= i
;
312 int json_variant_new_unsigned(JsonVariant
**ret
, uintmax_t u
) {
316 assert_return(ret
, -EINVAL
);
318 *ret
= JSON_VARIANT_MAGIC_ZERO_UNSIGNED
;
322 r
= json_variant_new(&v
, JSON_VARIANT_UNSIGNED
, sizeof(u
));
332 int json_variant_new_real(JsonVariant
**ret
, long double d
) {
336 assert_return(ret
, -EINVAL
);
338 #pragma GCC diagnostic push
339 #pragma GCC diagnostic ignored "-Wfloat-equal"
341 #pragma GCC diagnostic pop
342 *ret
= JSON_VARIANT_MAGIC_ZERO_REAL
;
346 r
= json_variant_new(&v
, JSON_VARIANT_REAL
, sizeof(d
));
356 int json_variant_new_boolean(JsonVariant
**ret
, bool b
) {
357 assert_return(ret
, -EINVAL
);
360 *ret
= JSON_VARIANT_MAGIC_TRUE
;
362 *ret
= JSON_VARIANT_MAGIC_FALSE
;
367 int json_variant_new_null(JsonVariant
**ret
) {
368 assert_return(ret
, -EINVAL
);
370 *ret
= JSON_VARIANT_MAGIC_NULL
;
374 int json_variant_new_stringn(JsonVariant
**ret
, const char *s
, size_t n
) {
378 assert_return(ret
, -EINVAL
);
380 assert_return(n
== 0, -EINVAL
);
381 return json_variant_new_null(ret
);
384 *ret
= JSON_VARIANT_MAGIC_EMPTY_STRING
;
388 r
= json_variant_new(&v
, JSON_VARIANT_STRING
, n
+ 1);
392 memcpy(v
->string
, s
, n
);
399 static void json_variant_set(JsonVariant
*a
, JsonVariant
*b
) {
402 b
= json_variant_dereference(b
);
404 a
->type
= JSON_VARIANT_NULL
;
408 a
->type
= json_variant_type(b
);
411 case JSON_VARIANT_INTEGER
:
412 a
->value
.integer
= json_variant_integer(b
);
415 case JSON_VARIANT_UNSIGNED
:
416 a
->value
.unsig
= json_variant_unsigned(b
);
419 case JSON_VARIANT_REAL
:
420 a
->value
.real
= json_variant_real(b
);
423 case JSON_VARIANT_BOOLEAN
:
424 a
->value
.boolean
= json_variant_boolean(b
);
427 case JSON_VARIANT_STRING
: {
430 assert_se(s
= json_variant_string(b
));
432 /* Short strings we can store inline */
433 if (strnlen(s
, INLINE_STRING_MAX
+1) <= INLINE_STRING_MAX
) {
434 strcpy(a
->string
, s
);
438 /* For longer strings, use a reference… */
442 case JSON_VARIANT_ARRAY
:
443 case JSON_VARIANT_OBJECT
:
444 a
->is_reference
= true;
445 a
->reference
= json_variant_ref(json_variant_conservative_normalize(b
));
448 case JSON_VARIANT_NULL
:
452 assert_not_reached("Unexpected variant type");
456 static void json_variant_copy_source(JsonVariant
*v
, JsonVariant
*from
) {
460 if (!json_variant_is_regular(from
))
463 v
->line
= from
->line
;
464 v
->column
= from
->column
;
465 v
->source
= json_source_ref(from
->source
);
468 int json_variant_new_array(JsonVariant
**ret
, JsonVariant
**array
, size_t n
) {
469 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
471 assert_return(ret
, -EINVAL
);
473 *ret
= JSON_VARIANT_MAGIC_EMPTY_ARRAY
;
476 assert_return(array
, -EINVAL
);
478 v
= new(JsonVariant
, n
+ 1);
484 .type
= JSON_VARIANT_ARRAY
,
487 for (v
->n_elements
= 0; v
->n_elements
< n
; v
->n_elements
++) {
488 JsonVariant
*w
= v
+ 1 + v
->n_elements
,
489 *c
= array
[v
->n_elements
];
492 d
= json_variant_depth(c
);
493 if (d
>= DEPTH_MAX
) /* Refuse too deep nesting */
503 json_variant_set(w
, c
);
504 json_variant_copy_source(w
, c
);
511 int json_variant_new_array_bytes(JsonVariant
**ret
, const void *p
, size_t n
) {
515 assert_return(ret
, -EINVAL
);
517 *ret
= JSON_VARIANT_MAGIC_EMPTY_ARRAY
;
520 assert_return(p
, -EINVAL
);
522 v
= new(JsonVariant
, n
+ 1);
528 .type
= JSON_VARIANT_ARRAY
,
533 for (i
= 0; i
< n
; i
++) {
534 JsonVariant
*w
= v
+ 1 + i
;
539 .type
= JSON_VARIANT_UNSIGNED
,
540 .value
.unsig
= ((const uint8_t*) p
)[i
],
548 int json_variant_new_array_strv(JsonVariant
**ret
, char **l
) {
549 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
557 *ret
= JSON_VARIANT_MAGIC_EMPTY_ARRAY
;
561 v
= new(JsonVariant
, n
+ 1);
567 .type
= JSON_VARIANT_ARRAY
,
571 for (v
->n_elements
= 0; v
->n_elements
< n
; v
->n_elements
++) {
572 JsonVariant
*w
= v
+ 1 + v
->n_elements
;
578 .type
= JSON_VARIANT_STRING
,
581 k
= strlen(l
[v
->n_elements
]);
583 if (k
> INLINE_STRING_MAX
) {
584 /* If string is too long, store it as reference. */
586 r
= json_variant_new_stringn(&w
->reference
, l
[v
->n_elements
], k
);
590 w
->is_reference
= true;
592 memcpy(w
->string
, l
[v
->n_elements
], k
+1);
599 int json_variant_new_object(JsonVariant
**ret
, JsonVariant
**array
, size_t n
) {
600 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
602 assert_return(ret
, -EINVAL
);
604 *ret
= JSON_VARIANT_MAGIC_EMPTY_OBJECT
;
607 assert_return(array
, -EINVAL
);
608 assert_return(n
% 2 == 0, -EINVAL
);
610 v
= new(JsonVariant
, n
+ 1);
616 .type
= JSON_VARIANT_OBJECT
,
619 for (v
->n_elements
= 0; v
->n_elements
< n
; v
->n_elements
++) {
620 JsonVariant
*w
= v
+ 1 + v
->n_elements
,
621 *c
= array
[v
->n_elements
];
624 if ((v
->n_elements
& 1) == 0 &&
625 !json_variant_is_string(c
))
626 return -EINVAL
; /* Every second one needs to be a string, as it is the key name */
628 d
= json_variant_depth(c
);
629 if (d
>= DEPTH_MAX
) /* Refuse too deep nesting */
639 json_variant_set(w
, c
);
640 json_variant_copy_source(w
, c
);
647 static void json_variant_free_inner(JsonVariant
*v
) {
650 if (!json_variant_is_regular(v
))
653 json_source_unref(v
->source
);
655 if (v
->is_reference
) {
656 json_variant_unref(v
->reference
);
660 if (IN_SET(v
->type
, JSON_VARIANT_ARRAY
, JSON_VARIANT_OBJECT
)) {
663 for (i
= 0; i
< v
->n_elements
; i
++)
664 json_variant_free_inner(v
+ 1 + i
);
668 JsonVariant
*json_variant_ref(JsonVariant
*v
) {
671 if (!json_variant_is_regular(v
))
675 json_variant_ref(v
->parent
); /* ref the compounding variant instead */
677 assert(v
->n_ref
> 0);
684 JsonVariant
*json_variant_unref(JsonVariant
*v
) {
687 if (!json_variant_is_regular(v
))
691 json_variant_unref(v
->parent
);
693 assert(v
->n_ref
> 0);
697 json_variant_free_inner(v
);
705 void json_variant_unref_many(JsonVariant
**array
, size_t n
) {
708 assert(array
|| n
== 0);
710 for (i
= 0; i
< n
; i
++)
711 json_variant_unref(array
[i
]);
714 const char *json_variant_string(JsonVariant
*v
) {
717 if (v
== JSON_VARIANT_MAGIC_EMPTY_STRING
)
719 if (json_variant_is_magic(v
))
721 if (json_variant_is_const_string(v
)) {
722 uintptr_t p
= (uintptr_t) v
;
724 assert((p
& 1) != 0);
725 return (const char*) (p
^ 1U);
729 return json_variant_string(v
->reference
);
730 if (v
->type
!= JSON_VARIANT_STRING
)
736 log_debug("Non-string JSON variant requested as string, returning NULL.");
740 bool json_variant_boolean(JsonVariant
*v
) {
743 if (v
== JSON_VARIANT_MAGIC_TRUE
)
745 if (v
== JSON_VARIANT_MAGIC_FALSE
)
747 if (!json_variant_is_regular(v
))
749 if (v
->type
!= JSON_VARIANT_BOOLEAN
)
752 return json_variant_boolean(v
->reference
);
754 return v
->value
.boolean
;
757 log_debug("Non-boolean JSON variant requested as boolean, returning false.");
761 intmax_t json_variant_integer(JsonVariant
*v
) {
764 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
765 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
766 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
768 if (!json_variant_is_regular(v
))
771 return json_variant_integer(v
->reference
);
775 case JSON_VARIANT_INTEGER
:
776 return v
->value
.integer
;
778 case JSON_VARIANT_UNSIGNED
:
779 if (v
->value
.unsig
<= INTMAX_MAX
)
780 return (intmax_t) v
->value
.unsig
;
782 log_debug("Unsigned integer %ju requested as signed integer and out of range, returning 0.", v
->value
.unsig
);
785 case JSON_VARIANT_REAL
: {
788 converted
= (intmax_t) v
->value
.real
;
790 #pragma GCC diagnostic push
791 #pragma GCC diagnostic ignored "-Wfloat-equal"
792 if ((long double) converted
== v
->value
.real
)
793 #pragma GCC diagnostic pop
796 log_debug("Real %Lg requested as integer, and cannot be converted losslessly, returning 0.", v
->value
.real
);
805 log_debug("Non-integer JSON variant requested as integer, returning 0.");
809 uintmax_t json_variant_unsigned(JsonVariant
*v
) {
812 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
813 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
814 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
816 if (!json_variant_is_regular(v
))
819 return json_variant_integer(v
->reference
);
823 case JSON_VARIANT_INTEGER
:
824 if (v
->value
.integer
>= 0)
825 return (uintmax_t) v
->value
.integer
;
827 log_debug("Signed integer %ju requested as unsigned integer and out of range, returning 0.", v
->value
.integer
);
830 case JSON_VARIANT_UNSIGNED
:
831 return v
->value
.unsig
;
833 case JSON_VARIANT_REAL
: {
836 converted
= (uintmax_t) v
->value
.real
;
838 #pragma GCC diagnostic push
839 #pragma GCC diagnostic ignored "-Wfloat-equal"
840 if ((long double) converted
== v
->value
.real
)
841 #pragma GCC diagnostic pop
844 log_debug("Real %Lg requested as unsigned integer, and cannot be converted losslessly, returning 0.", v
->value
.real
);
853 log_debug("Non-integer JSON variant requested as unsigned, returning 0.");
857 long double json_variant_real(JsonVariant
*v
) {
860 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
861 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
862 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
864 if (!json_variant_is_regular(v
))
867 return json_variant_real(v
->reference
);
871 case JSON_VARIANT_REAL
:
872 return v
->value
.real
;
874 case JSON_VARIANT_INTEGER
: {
875 long double converted
;
877 converted
= (long double) v
->value
.integer
;
879 if ((intmax_t) converted
== v
->value
.integer
)
882 log_debug("Signed integer %ji requested as real, and cannot be converted losslessly, returning 0.", v
->value
.integer
);
886 case JSON_VARIANT_UNSIGNED
: {
887 long double converted
;
889 converted
= (long double) v
->value
.unsig
;
891 if ((uintmax_t) converted
== v
->value
.unsig
)
894 log_debug("Unsigned integer %ju requested as real, and cannot be converted losslessly, returning 0.", v
->value
.unsig
);
903 log_debug("Non-integer JSON variant requested as integer, returning 0.");
907 bool json_variant_is_negative(JsonVariant
*v
) {
910 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
911 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
912 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
914 if (!json_variant_is_regular(v
))
917 return json_variant_is_negative(v
->reference
);
919 /* This function is useful as checking whether numbers are negative is pretty complex since we have three types
920 * of numbers. And some JSON code (OCI for example) uses negative numbers to mark "not defined" numeric
925 case JSON_VARIANT_REAL
:
926 return v
->value
.real
< 0;
928 case JSON_VARIANT_INTEGER
:
929 return v
->value
.integer
< 0;
931 case JSON_VARIANT_UNSIGNED
:
939 log_debug("Non-integer JSON variant tested for negativity, returning false.");
943 JsonVariantType
json_variant_type(JsonVariant
*v
) {
946 return _JSON_VARIANT_TYPE_INVALID
;
948 if (json_variant_is_const_string(v
))
949 return JSON_VARIANT_STRING
;
951 if (v
== JSON_VARIANT_MAGIC_TRUE
|| v
== JSON_VARIANT_MAGIC_FALSE
)
952 return JSON_VARIANT_BOOLEAN
;
954 if (v
== JSON_VARIANT_MAGIC_NULL
)
955 return JSON_VARIANT_NULL
;
957 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
)
958 return JSON_VARIANT_INTEGER
;
960 if (v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
)
961 return JSON_VARIANT_UNSIGNED
;
963 if (v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
964 return JSON_VARIANT_REAL
;
966 if (v
== JSON_VARIANT_MAGIC_EMPTY_STRING
)
967 return JSON_VARIANT_STRING
;
969 if (v
== JSON_VARIANT_MAGIC_EMPTY_ARRAY
)
970 return JSON_VARIANT_ARRAY
;
972 if (v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
973 return JSON_VARIANT_OBJECT
;
978 bool json_variant_has_type(JsonVariant
*v
, JsonVariantType type
) {
981 v
= json_variant_dereference(v
);
983 rt
= json_variant_type(v
);
987 /* If it's a const string, then it only can be a string, and if it is not, it's not */
988 if (json_variant_is_const_string(v
))
991 /* All three magic zeroes qualify as integer, unsigned and as real */
992 if ((v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
|| v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
|| v
== JSON_VARIANT_MAGIC_ZERO_REAL
) &&
993 IN_SET(type
, JSON_VARIANT_INTEGER
, JSON_VARIANT_UNSIGNED
, JSON_VARIANT_REAL
, JSON_VARIANT_NUMBER
))
996 /* All other magic variant types are only equal to themselves */
997 if (json_variant_is_magic(v
))
1000 /* Handle the "number" pseudo type */
1001 if (type
== JSON_VARIANT_NUMBER
)
1002 return IN_SET(rt
, JSON_VARIANT_INTEGER
, JSON_VARIANT_UNSIGNED
, JSON_VARIANT_REAL
);
1004 /* Integer conversions are OK in many cases */
1005 if (rt
== JSON_VARIANT_INTEGER
&& type
== JSON_VARIANT_UNSIGNED
)
1006 return v
->value
.integer
>= 0;
1007 if (rt
== JSON_VARIANT_UNSIGNED
&& type
== JSON_VARIANT_INTEGER
)
1008 return v
->value
.unsig
<= INTMAX_MAX
;
1010 /* Any integer that can be converted lossley to a real and back may also be considered a real */
1011 if (rt
== JSON_VARIANT_INTEGER
&& type
== JSON_VARIANT_REAL
)
1012 return (intmax_t) (long double) v
->value
.integer
== v
->value
.integer
;
1013 if (rt
== JSON_VARIANT_UNSIGNED
&& type
== JSON_VARIANT_REAL
)
1014 return (uintmax_t) (long double) v
->value
.unsig
== v
->value
.unsig
;
1016 #pragma GCC diagnostic push
1017 #pragma GCC diagnostic ignored "-Wfloat-equal"
1018 /* Any real that can be converted losslessly to an integer and back may also be considered an integer */
1019 if (rt
== JSON_VARIANT_REAL
&& type
== JSON_VARIANT_INTEGER
)
1020 return (long double) (intmax_t) v
->value
.real
== v
->value
.real
;
1021 if (rt
== JSON_VARIANT_REAL
&& type
== JSON_VARIANT_UNSIGNED
)
1022 return (long double) (uintmax_t) v
->value
.real
== v
->value
.real
;
1023 #pragma GCC diagnostic pop
1028 size_t json_variant_elements(JsonVariant
*v
) {
1031 if (v
== JSON_VARIANT_MAGIC_EMPTY_ARRAY
||
1032 v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
1034 if (!json_variant_is_regular(v
))
1036 if (!IN_SET(v
->type
, JSON_VARIANT_ARRAY
, JSON_VARIANT_OBJECT
))
1038 if (v
->is_reference
)
1039 return json_variant_elements(v
->reference
);
1041 return v
->n_elements
;
1044 log_debug("Number of elements in non-array/non-object JSON variant requested, returning 0.");
1048 JsonVariant
*json_variant_by_index(JsonVariant
*v
, size_t idx
) {
1051 if (v
== JSON_VARIANT_MAGIC_EMPTY_ARRAY
||
1052 v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
1054 if (!json_variant_is_regular(v
))
1056 if (!IN_SET(v
->type
, JSON_VARIANT_ARRAY
, JSON_VARIANT_OBJECT
))
1058 if (v
->is_reference
)
1059 return json_variant_by_index(v
->reference
, idx
);
1060 if (idx
>= v
->n_elements
)
1063 return json_variant_conservative_normalize(v
+ 1 + idx
);
1066 log_debug("Element in non-array/non-object JSON variant requested by index, returning NULL.");
1070 JsonVariant
*json_variant_by_key_full(JsonVariant
*v
, const char *key
, JsonVariant
**ret_key
) {
1077 if (v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
1079 if (!json_variant_is_regular(v
))
1081 if (v
->type
!= JSON_VARIANT_OBJECT
)
1083 if (v
->is_reference
)
1084 return json_variant_by_key(v
->reference
, key
);
1086 for (i
= 0; i
< v
->n_elements
; i
+= 2) {
1089 p
= json_variant_dereference(v
+ 1 + i
);
1091 if (!json_variant_has_type(p
, JSON_VARIANT_STRING
))
1094 if (streq(json_variant_string(p
), key
)) {
1097 *ret_key
= json_variant_conservative_normalize(v
+ 1 + i
);
1099 return json_variant_conservative_normalize(v
+ 1 + i
+ 1);
1110 log_debug("Element in non-object JSON variant requested by key, returning NULL.");
1117 JsonVariant
*json_variant_by_key(JsonVariant
*v
, const char *key
) {
1118 return json_variant_by_key_full(v
, key
, NULL
);
1121 bool json_variant_equal(JsonVariant
*a
, JsonVariant
*b
) {
1124 a
= json_variant_normalize(a
);
1125 b
= json_variant_normalize(b
);
1130 t
= json_variant_type(a
);
1131 if (!json_variant_has_type(b
, t
))
1136 case JSON_VARIANT_STRING
:
1137 return streq(json_variant_string(a
), json_variant_string(b
));
1139 case JSON_VARIANT_INTEGER
:
1140 return json_variant_integer(a
) == json_variant_integer(b
);
1142 case JSON_VARIANT_UNSIGNED
:
1143 return json_variant_unsigned(a
) == json_variant_unsigned(b
);
1145 case JSON_VARIANT_REAL
:
1146 #pragma GCC diagnostic push
1147 #pragma GCC diagnostic ignored "-Wfloat-equal"
1148 return json_variant_real(a
) == json_variant_real(b
);
1149 #pragma GCC diagnostic pop
1151 case JSON_VARIANT_BOOLEAN
:
1152 return json_variant_boolean(a
) == json_variant_boolean(b
);
1154 case JSON_VARIANT_NULL
:
1157 case JSON_VARIANT_ARRAY
: {
1160 n
= json_variant_elements(a
);
1161 if (n
!= json_variant_elements(b
))
1164 for (i
= 0; i
< n
; i
++) {
1165 if (!json_variant_equal(json_variant_by_index(a
, i
), json_variant_by_index(b
, i
)))
1172 case JSON_VARIANT_OBJECT
: {
1175 n
= json_variant_elements(a
);
1176 if (n
!= json_variant_elements(b
))
1179 /* Iterate through all keys in 'a' */
1180 for (i
= 0; i
< n
; i
+= 2) {
1184 /* Match them against all keys in 'b' */
1185 for (j
= 0; j
< n
; j
+= 2) {
1188 key_b
= json_variant_by_index(b
, j
);
1190 /* During the first iteration unmark everything */
1192 key_b
->is_marked
= false;
1193 else if (key_b
->is_marked
) /* In later iterations if we already marked something, don't bother with it again */
1199 if (json_variant_equal(json_variant_by_index(a
, i
), key_b
) &&
1200 json_variant_equal(json_variant_by_index(a
, i
+1), json_variant_by_index(b
, j
+1))) {
1201 /* Key and values match! */
1202 key_b
->is_marked
= found
= true;
1204 /* In the first iteration we continue the inner loop since we want to mark
1205 * everything, otherwise exit the loop quickly after we found what we were
1220 assert_not_reached("Unknown variant type.");
1224 int json_variant_get_source(JsonVariant
*v
, const char **ret_source
, unsigned *ret_line
, unsigned *ret_column
) {
1225 assert_return(v
, -EINVAL
);
1228 *ret_source
= json_variant_is_regular(v
) && v
->source
? v
->source
->name
: NULL
;
1231 *ret_line
= json_variant_is_regular(v
) ? v
->line
: 0;
1234 *ret_column
= json_variant_is_regular(v
) ? v
->column
: 0;
1239 static int print_source(FILE *f
, JsonVariant
*v
, unsigned flags
, bool whitespace
) {
1242 if (!FLAGS_SET(flags
, JSON_FORMAT_SOURCE
|JSON_FORMAT_PRETTY
))
1245 if (!json_variant_is_regular(v
))
1248 if (!v
->source
&& v
->line
== 0 && v
->column
== 0)
1251 /* The max width we need to format the line numbers for this source file */
1252 w
= (v
->source
&& v
->source
->max_line
> 0) ?
1253 DECIMAL_STR_WIDTH(v
->source
->max_line
) :
1254 DECIMAL_STR_MAX(unsigned)-1;
1255 k
= (v
->source
&& v
->source
->max_column
> 0) ?
1256 DECIMAL_STR_WIDTH(v
->source
->max_column
) :
1257 DECIMAL_STR_MAX(unsigned) -1;
1262 n
= 1 + (v
->source
? strlen(v
->source
->name
) : 0) +
1263 ((v
->source
&& (v
->line
> 0 || v
->column
> 0)) ? 1 : 0) +
1264 (v
->line
> 0 ? w
: 0) +
1265 (((v
->source
|| v
->line
> 0) && v
->column
> 0) ? 1 : 0) +
1266 (v
->column
> 0 ? k
: 0) +
1269 for (i
= 0; i
< n
; i
++)
1275 fputs(v
->source
->name
, f
);
1276 if (v
->source
&& (v
->line
> 0 || v
->column
> 0))
1279 fprintf(f
, "%*u", (int) w
, v
->line
);
1280 if ((v
->source
|| v
->line
> 0) || v
->column
> 0)
1283 fprintf(f
, "%*u", (int) k
, v
->column
);
1292 static int json_format(FILE *f
, JsonVariant
*v
, unsigned flags
, const char *prefix
) {
1298 switch (json_variant_type(v
)) {
1300 case JSON_VARIANT_REAL
: {
1303 loc
= newlocale(LC_NUMERIC_MASK
, "C", (locale_t
) 0);
1304 if (loc
== (locale_t
) 0)
1307 if (flags
& JSON_FORMAT_COLOR
)
1308 fputs(ANSI_HIGHLIGHT_BLUE
, f
);
1310 fprintf(f
, "%.*Le", DECIMAL_DIG
, json_variant_real(v
));
1312 if (flags
& JSON_FORMAT_COLOR
)
1313 fputs(ANSI_NORMAL
, f
);
1319 case JSON_VARIANT_INTEGER
:
1320 if (flags
& JSON_FORMAT_COLOR
)
1321 fputs(ANSI_HIGHLIGHT_BLUE
, f
);
1323 fprintf(f
, "%" PRIdMAX
, json_variant_integer(v
));
1325 if (flags
& JSON_FORMAT_COLOR
)
1326 fputs(ANSI_NORMAL
, f
);
1329 case JSON_VARIANT_UNSIGNED
:
1330 if (flags
& JSON_FORMAT_COLOR
)
1331 fputs(ANSI_HIGHLIGHT_BLUE
, f
);
1333 fprintf(f
, "%" PRIuMAX
, json_variant_unsigned(v
));
1335 if (flags
& JSON_FORMAT_COLOR
)
1336 fputs(ANSI_NORMAL
, f
);
1339 case JSON_VARIANT_BOOLEAN
:
1341 if (flags
& JSON_FORMAT_COLOR
)
1342 fputs(ANSI_HIGHLIGHT
, f
);
1344 if (json_variant_boolean(v
))
1349 if (flags
& JSON_FORMAT_COLOR
)
1350 fputs(ANSI_NORMAL
, f
);
1354 case JSON_VARIANT_NULL
:
1355 if (flags
& JSON_FORMAT_COLOR
)
1356 fputs(ANSI_HIGHLIGHT
, f
);
1360 if (flags
& JSON_FORMAT_COLOR
)
1361 fputs(ANSI_NORMAL
, f
);
1364 case JSON_VARIANT_STRING
: {
1369 if (flags
& JSON_FORMAT_COLOR
)
1370 fputs(ANSI_GREEN
, f
);
1372 for (q
= json_variant_string(v
); *q
; q
++) {
1409 if ((signed char) *q
>= 0 && *q
< ' ')
1410 fprintf(f
, "\\u%04x", *q
);
1417 if (flags
& JSON_FORMAT_COLOR
)
1418 fputs(ANSI_NORMAL
, f
);
1424 case JSON_VARIANT_ARRAY
: {
1427 n
= json_variant_elements(v
);
1432 _cleanup_free_
char *joined
= NULL
;
1433 const char *prefix2
;
1435 if (flags
& JSON_FORMAT_PRETTY
) {
1436 joined
= strjoin(strempty(prefix
), "\t");
1443 prefix2
= strempty(prefix
);
1447 for (i
= 0; i
< n
; i
++) {
1450 assert_se(e
= json_variant_by_index(v
, i
));
1453 if (flags
& JSON_FORMAT_PRETTY
)
1459 if (flags
& JSON_FORMAT_PRETTY
) {
1460 print_source(f
, e
, flags
, false);
1464 r
= json_format(f
, e
, flags
, prefix2
);
1469 if (flags
& JSON_FORMAT_PRETTY
) {
1471 print_source(f
, v
, flags
, true);
1472 fputs(strempty(prefix
), f
);
1480 case JSON_VARIANT_OBJECT
: {
1483 n
= json_variant_elements(v
);
1488 _cleanup_free_
char *joined
= NULL
;
1489 const char *prefix2
;
1491 if (flags
& JSON_FORMAT_PRETTY
) {
1492 joined
= strjoin(strempty(prefix
), "\t");
1499 prefix2
= strempty(prefix
);
1503 for (i
= 0; i
< n
; i
+= 2) {
1506 e
= json_variant_by_index(v
, i
);
1509 if (flags
& JSON_FORMAT_PRETTY
)
1515 if (flags
& JSON_FORMAT_PRETTY
) {
1516 print_source(f
, e
, flags
, false);
1520 r
= json_format(f
, e
, flags
, prefix2
);
1524 fputs(flags
& JSON_FORMAT_PRETTY
? " : " : ":", f
);
1526 r
= json_format(f
, json_variant_by_index(v
, i
+1), flags
, prefix2
);
1531 if (flags
& JSON_FORMAT_PRETTY
) {
1533 print_source(f
, v
, flags
, true);
1534 fputs(strempty(prefix
), f
);
1543 assert_not_reached("Unexpected variant type.");
1549 int json_variant_format(JsonVariant
*v
, unsigned flags
, char **ret
) {
1550 _cleanup_free_
char *s
= NULL
;
1554 assert_return(v
, -EINVAL
);
1555 assert_return(ret
, -EINVAL
);
1558 _cleanup_fclose_
FILE *f
= NULL
;
1560 f
= open_memstream(&s
, &sz
);
1564 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
1566 json_variant_dump(v
, flags
, f
, NULL
);
1568 r
= fflush_and_check(f
);
1579 void json_variant_dump(JsonVariant
*v
, unsigned flags
, FILE *f
, const char *prefix
) {
1586 print_source(f
, v
, flags
, false);
1588 if (flags
& JSON_FORMAT_SSE
)
1590 if (flags
& JSON_FORMAT_SEQ
)
1591 fputc('\x1e', f
); /* ASCII Record Separator */
1593 json_format(f
, v
, flags
, prefix
);
1595 if (flags
& (JSON_FORMAT_PRETTY
|JSON_FORMAT_SEQ
|JSON_FORMAT_SSE
|JSON_FORMAT_NEWLINE
))
1597 if (flags
& JSON_FORMAT_SSE
)
1598 fputc('\n', f
); /* In case of SSE add a second newline */
1601 static int json_variant_copy(JsonVariant
**nv
, JsonVariant
*v
) {
1611 /* Let's copy the simple types literally, and the larger types by references */
1612 t
= json_variant_type(v
);
1614 case JSON_VARIANT_INTEGER
:
1615 k
= sizeof(intmax_t);
1616 value
.integer
= json_variant_integer(v
);
1620 case JSON_VARIANT_UNSIGNED
:
1621 k
= sizeof(uintmax_t);
1622 value
.unsig
= json_variant_unsigned(v
);
1626 case JSON_VARIANT_REAL
:
1627 k
= sizeof(long double);
1628 value
.real
= json_variant_real(v
);
1632 case JSON_VARIANT_BOOLEAN
:
1634 value
.boolean
= json_variant_boolean(v
);
1638 case JSON_VARIANT_NULL
:
1643 case JSON_VARIANT_STRING
:
1644 source
= json_variant_string(v
);
1645 k
= strnlen(source
, INLINE_STRING_MAX
+ 1);
1646 if (k
<= INLINE_STRING_MAX
) {
1654 /* Everything else copy by reference */
1656 c
= malloc0(offsetof(JsonVariant
, reference
) + sizeof(JsonVariant
*));
1662 c
->is_reference
= true;
1663 c
->reference
= json_variant_ref(json_variant_normalize(v
));
1669 c
= malloc0(offsetof(JsonVariant
, value
) + k
);
1676 memcpy_safe(&c
->value
, source
, k
);
1682 static bool json_single_ref(JsonVariant
*v
) {
1684 /* Checks whether the caller is the single owner of the object, i.e. can get away with changing it */
1686 if (!json_variant_is_regular(v
))
1690 return json_single_ref(v
->parent
);
1692 assert(v
->n_ref
> 0);
1693 return v
->n_ref
== 1;
1696 static int json_variant_set_source(JsonVariant
**v
, JsonSource
*source
, unsigned line
, unsigned column
) {
1702 /* Patch in source and line/column number. Tries to do this in-place if the caller is the sole referencer of
1703 * the object. If not, allocates a new object, possibly a surrogate for the original one */
1708 if (source
&& line
> source
->max_line
)
1709 source
->max_line
= line
;
1710 if (source
&& column
> source
->max_column
)
1711 source
->max_column
= column
;
1713 if (!json_variant_is_regular(*v
)) {
1715 if (!source
&& line
== 0 && column
== 0)
1719 if (json_source_equal((*v
)->source
, source
) &&
1720 (*v
)->line
== line
&&
1721 (*v
)->column
== column
)
1724 if (json_single_ref(*v
)) { /* Sole reference? */
1725 json_source_unref((*v
)->source
);
1726 (*v
)->source
= json_source_ref(source
);
1728 (*v
)->column
= column
;
1733 r
= json_variant_copy(&w
, *v
);
1737 assert(json_variant_is_regular(w
));
1738 assert(!w
->is_embedded
);
1739 assert(w
->n_ref
== 1);
1742 w
->source
= json_source_ref(source
);
1746 json_variant_unref(*v
);
1752 static void inc_lines_columns(unsigned *line
, unsigned *column
, const char *s
, size_t n
) {
1755 assert(s
|| n
== 0);
1762 } else if ((signed char) *s
>= 0 && *s
< 127) /* Process ASCII chars quickly */
1767 w
= utf8_encoded_valid_unichar(s
);
1768 if (w
< 0) /* count invalid unichars as normal characters */
1770 else if ((size_t) w
> n
) /* never read more than the specified number of characters */
1785 static int unhex_ucs2(const char *c
, uint16_t *ret
) {
1792 aa
= unhexchar(c
[0]);
1796 bb
= unhexchar(c
[1]);
1800 cc
= unhexchar(c
[2]);
1804 dd
= unhexchar(c
[3]);
1808 x
= ((uint16_t) aa
<< 12) |
1809 ((uint16_t) bb
<< 8) |
1810 ((uint16_t) cc
<< 4) |
1821 static int json_parse_string(const char **p
, char **ret
) {
1822 _cleanup_free_
char *s
= NULL
;
1823 size_t n
= 0, allocated
= 0;
1844 /* Check for control characters 0x00..0x1f */
1845 if (*c
> 0 && *c
< ' ')
1848 /* Check for control character 0x7f */
1863 return JSON_TOKEN_STRING
;
1873 if (IN_SET(*c
, '"', '\\', '/'))
1885 else if (*c
== 'u') {
1889 r
= unhex_ucs2(c
+ 1, &x
);
1895 if (!GREEDY_REALLOC(s
, allocated
, n
+ 5))
1898 if (!utf16_is_surrogate(x
))
1899 n
+= utf8_encode_unichar(s
+ n
, (char32_t
) x
);
1900 else if (utf16_is_trailing_surrogate(x
))
1905 if (c
[0] != '\\' || c
[1] != 'u')
1908 r
= unhex_ucs2(c
+ 2, &y
);
1914 if (!utf16_is_trailing_surrogate(y
))
1917 n
+= utf8_encode_unichar(s
+ n
, utf16_surrogate_pair_to_unichar(x
, y
));
1924 if (!GREEDY_REALLOC(s
, allocated
, n
+ 2))
1932 len
= utf8_encoded_valid_unichar(c
);
1936 if (!GREEDY_REALLOC(s
, allocated
, n
+ len
+ 1))
1939 memcpy(s
+ n
, c
, len
);
1945 static int json_parse_number(const char **p
, JsonValue
*ret
) {
1946 bool negative
= false, exponent_negative
= false, is_real
= false;
1947 long double x
= 0.0, y
= 0.0, exponent
= 0.0, shift
= 1.0;
1966 if (!strchr("123456789", *c
) || *c
== 0)
1973 if (i
< INTMAX_MIN
/ 10) /* overflow */
1976 intmax_t t
= 10 * i
;
1978 if (t
< INTMAX_MIN
+ (*c
- '0')) /* overflow */
1984 if (u
> UINTMAX_MAX
/ 10) /* overflow */
1987 uintmax_t t
= 10 * u
;
1989 if (t
> UINTMAX_MAX
- (*c
- '0')) /* overflow */
1997 x
= 10.0 * x
+ (*c
- '0');
2000 } while (strchr("0123456789", *c
) && *c
!= 0);
2007 if (!strchr("0123456789", *c
) || *c
== 0)
2011 y
= 10.0 * y
+ (*c
- '0');
2012 shift
= 10.0 * shift
;
2014 } while (strchr("0123456789", *c
) && *c
!= 0);
2017 if (IN_SET(*c
, 'e', 'E')) {
2022 exponent_negative
= true;
2024 } else if (*c
== '+')
2027 if (!strchr("0123456789", *c
) || *c
== 0)
2031 exponent
= 10.0 * exponent
+ (*c
- '0');
2033 } while (strchr("0123456789", *c
) && *c
!= 0);
2039 ret
->real
= ((negative
? -1.0 : 1.0) * (x
+ (y
/ shift
))) * exp10l((exponent_negative
? -1.0 : 1.0) * exponent
);
2040 return JSON_TOKEN_REAL
;
2041 } else if (negative
) {
2043 return JSON_TOKEN_INTEGER
;
2046 return JSON_TOKEN_UNSIGNED
;
2053 JsonValue
*ret_value
,
2054 unsigned *ret_line
, /* 'ret_line' returns the line at the beginning of this token */
2055 unsigned *ret_column
,
2057 unsigned *line
, /* 'line' is used as a line state, it always reflect the line we are at after the token was read */
2060 unsigned start_line
, start_column
;
2061 const char *start
, *c
;
2081 t
= PTR_TO_INT(*state
);
2082 if (t
== STATE_NULL
) {
2088 /* Skip over the whitespace */
2089 n
= strspn(*p
, WHITESPACE
);
2090 inc_lines_columns(line
, column
, *p
, n
);
2093 /* Remember where we started processing this token */
2096 start_column
= *column
;
2100 *ret_value
= JSON_VALUE_NULL
;
2111 *state
= INT_TO_PTR(STATE_VALUE
);
2112 r
= JSON_TOKEN_OBJECT_OPEN
;
2115 } else if (*c
== '}') {
2117 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2118 r
= JSON_TOKEN_OBJECT_CLOSE
;
2121 } else if (*c
== '[') {
2123 *state
= INT_TO_PTR(STATE_VALUE
);
2124 r
= JSON_TOKEN_ARRAY_OPEN
;
2127 } else if (*c
== ']') {
2129 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2130 r
= JSON_TOKEN_ARRAY_CLOSE
;
2133 } else if (*c
== '"') {
2135 r
= json_parse_string(&c
, ret_string
);
2139 *ret_value
= JSON_VALUE_NULL
;
2140 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2143 } else if (strchr("-0123456789", *c
)) {
2145 r
= json_parse_number(&c
, ret_value
);
2150 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2153 } else if (startswith(c
, "true")) {
2155 ret_value
->boolean
= true;
2157 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2158 r
= JSON_TOKEN_BOOLEAN
;
2161 } else if (startswith(c
, "false")) {
2163 ret_value
->boolean
= false;
2165 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2166 r
= JSON_TOKEN_BOOLEAN
;
2169 } else if (startswith(c
, "null")) {
2171 *ret_value
= JSON_VALUE_NULL
;
2173 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2174 r
= JSON_TOKEN_NULL
;
2181 case STATE_VALUE_POST
:
2185 *state
= INT_TO_PTR(STATE_VALUE
);
2186 r
= JSON_TOKEN_COLON
;
2189 } else if (*c
== ',') {
2191 *state
= INT_TO_PTR(STATE_VALUE
);
2192 r
= JSON_TOKEN_COMMA
;
2195 } else if (*c
== '}') {
2197 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2198 r
= JSON_TOKEN_OBJECT_CLOSE
;
2201 } else if (*c
== ']') {
2203 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2204 r
= JSON_TOKEN_ARRAY_CLOSE
;
2211 assert_not_reached("Unexpected tokenizer state");
2216 *ret_value
= JSON_VALUE_NULL
;
2219 inc_lines_columns(line
, column
, start
, c
- start
);
2222 *ret_line
= start_line
;
2223 *ret_column
= start_column
;
2228 typedef enum JsonExpect
{
2229 /* The following values are used by json_parse() */
2232 EXPECT_OBJECT_FIRST_KEY
,
2233 EXPECT_OBJECT_NEXT_KEY
,
2234 EXPECT_OBJECT_COLON
,
2235 EXPECT_OBJECT_VALUE
,
2236 EXPECT_OBJECT_COMMA
,
2237 EXPECT_ARRAY_FIRST_ELEMENT
,
2238 EXPECT_ARRAY_NEXT_ELEMENT
,
2241 /* And these are used by json_build() */
2242 EXPECT_ARRAY_ELEMENT
,
2246 typedef struct JsonStack
{
2248 JsonVariant
**elements
;
2249 size_t n_elements
, n_elements_allocated
;
2250 unsigned line_before
;
2251 unsigned column_before
;
2254 static void json_stack_release(JsonStack
*s
) {
2257 json_variant_unref_many(s
->elements
, s
->n_elements
);
2258 s
->elements
= mfree(s
->elements
);
2261 static int json_parse_internal(
2267 bool continue_end
) {
2269 size_t n_stack
= 1, n_stack_allocated
= 0, i
;
2270 unsigned line_buffer
= 0, column_buffer
= 0;
2271 void *tokenizer_state
= NULL
;
2272 JsonStack
*stack
= NULL
;
2276 assert_return(input
, -EINVAL
);
2277 assert_return(ret
, -EINVAL
);
2281 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
))
2284 stack
[0] = (JsonStack
) {
2285 .expect
= EXPECT_TOPLEVEL
,
2289 line
= &line_buffer
;
2291 column
= &column_buffer
;
2294 _cleanup_free_
char *string
= NULL
;
2295 unsigned line_token
, column_token
;
2296 JsonVariant
*add
= NULL
;
2301 assert(n_stack
> 0);
2302 current
= stack
+ n_stack
- 1;
2304 if (continue_end
&& current
->expect
== EXPECT_END
)
2307 token
= json_tokenize(&p
, &string
, &value
, &line_token
, &column_token
, &tokenizer_state
, line
, column
);
2315 case JSON_TOKEN_END
:
2316 if (current
->expect
!= EXPECT_END
) {
2321 assert(current
->n_elements
== 1);
2322 assert(n_stack
== 1);
2325 case JSON_TOKEN_COLON
:
2327 if (current
->expect
!= EXPECT_OBJECT_COLON
) {
2332 current
->expect
= EXPECT_OBJECT_VALUE
;
2335 case JSON_TOKEN_COMMA
:
2337 if (current
->expect
== EXPECT_OBJECT_COMMA
)
2338 current
->expect
= EXPECT_OBJECT_NEXT_KEY
;
2339 else if (current
->expect
== EXPECT_ARRAY_COMMA
)
2340 current
->expect
= EXPECT_ARRAY_NEXT_ELEMENT
;
2348 case JSON_TOKEN_OBJECT_OPEN
:
2350 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2355 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
2359 current
= stack
+ n_stack
- 1;
2361 /* Prepare the expect for when we return from the child */
2362 if (current
->expect
== EXPECT_TOPLEVEL
)
2363 current
->expect
= EXPECT_END
;
2364 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2365 current
->expect
= EXPECT_OBJECT_COMMA
;
2367 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2368 current
->expect
= EXPECT_ARRAY_COMMA
;
2371 stack
[n_stack
++] = (JsonStack
) {
2372 .expect
= EXPECT_OBJECT_FIRST_KEY
,
2373 .line_before
= line_token
,
2374 .column_before
= column_token
,
2377 current
= stack
+ n_stack
- 1;
2380 case JSON_TOKEN_OBJECT_CLOSE
:
2381 if (!IN_SET(current
->expect
, EXPECT_OBJECT_FIRST_KEY
, EXPECT_OBJECT_COMMA
)) {
2386 assert(n_stack
> 1);
2388 r
= json_variant_new_object(&add
, current
->elements
, current
->n_elements
);
2392 line_token
= current
->line_before
;
2393 column_token
= current
->column_before
;
2395 json_stack_release(current
);
2396 n_stack
--, current
--;
2400 case JSON_TOKEN_ARRAY_OPEN
:
2401 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2406 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
2410 current
= stack
+ n_stack
- 1;
2412 /* Prepare the expect for when we return from the child */
2413 if (current
->expect
== EXPECT_TOPLEVEL
)
2414 current
->expect
= EXPECT_END
;
2415 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2416 current
->expect
= EXPECT_OBJECT_COMMA
;
2418 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2419 current
->expect
= EXPECT_ARRAY_COMMA
;
2422 stack
[n_stack
++] = (JsonStack
) {
2423 .expect
= EXPECT_ARRAY_FIRST_ELEMENT
,
2424 .line_before
= line_token
,
2425 .column_before
= column_token
,
2430 case JSON_TOKEN_ARRAY_CLOSE
:
2431 if (!IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_COMMA
)) {
2436 assert(n_stack
> 1);
2438 r
= json_variant_new_array(&add
, current
->elements
, current
->n_elements
);
2442 line_token
= current
->line_before
;
2443 column_token
= current
->column_before
;
2445 json_stack_release(current
);
2446 n_stack
--, current
--;
2449 case JSON_TOKEN_STRING
:
2450 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
= json_variant_new_string(&add
, string
);
2459 if (current
->expect
== EXPECT_TOPLEVEL
)
2460 current
->expect
= EXPECT_END
;
2461 else if (IN_SET(current
->expect
, EXPECT_OBJECT_FIRST_KEY
, EXPECT_OBJECT_NEXT_KEY
))
2462 current
->expect
= EXPECT_OBJECT_COLON
;
2463 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2464 current
->expect
= EXPECT_OBJECT_COMMA
;
2466 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2467 current
->expect
= EXPECT_ARRAY_COMMA
;
2472 case JSON_TOKEN_REAL
:
2473 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2478 r
= json_variant_new_real(&add
, value
.real
);
2482 if (current
->expect
== EXPECT_TOPLEVEL
)
2483 current
->expect
= EXPECT_END
;
2484 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2485 current
->expect
= EXPECT_OBJECT_COMMA
;
2487 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2488 current
->expect
= EXPECT_ARRAY_COMMA
;
2493 case JSON_TOKEN_INTEGER
:
2494 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2499 r
= json_variant_new_integer(&add
, value
.integer
);
2503 if (current
->expect
== EXPECT_TOPLEVEL
)
2504 current
->expect
= EXPECT_END
;
2505 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2506 current
->expect
= EXPECT_OBJECT_COMMA
;
2508 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2509 current
->expect
= EXPECT_ARRAY_COMMA
;
2514 case JSON_TOKEN_UNSIGNED
:
2515 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2520 r
= json_variant_new_unsigned(&add
, value
.unsig
);
2524 if (current
->expect
== EXPECT_TOPLEVEL
)
2525 current
->expect
= EXPECT_END
;
2526 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2527 current
->expect
= EXPECT_OBJECT_COMMA
;
2529 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2530 current
->expect
= EXPECT_ARRAY_COMMA
;
2535 case JSON_TOKEN_BOOLEAN
:
2536 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2541 r
= json_variant_new_boolean(&add
, value
.boolean
);
2545 if (current
->expect
== EXPECT_TOPLEVEL
)
2546 current
->expect
= EXPECT_END
;
2547 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2548 current
->expect
= EXPECT_OBJECT_COMMA
;
2550 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2551 current
->expect
= EXPECT_ARRAY_COMMA
;
2556 case JSON_TOKEN_NULL
:
2557 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2562 r
= json_variant_new_null(&add
);
2566 if (current
->expect
== EXPECT_TOPLEVEL
)
2567 current
->expect
= EXPECT_END
;
2568 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2569 current
->expect
= EXPECT_OBJECT_COMMA
;
2571 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2572 current
->expect
= EXPECT_ARRAY_COMMA
;
2578 assert_not_reached("Unexpected token");
2582 (void) json_variant_set_source(&add
, source
, line_token
, column_token
);
2584 if (!GREEDY_REALLOC(current
->elements
, current
->n_elements_allocated
, current
->n_elements
+ 1)) {
2589 current
->elements
[current
->n_elements
++] = add
;
2594 assert(n_stack
== 1);
2595 assert(stack
[0].n_elements
== 1);
2597 *ret
= json_variant_ref(stack
[0].elements
[0]);
2602 for (i
= 0; i
< n_stack
; i
++)
2603 json_stack_release(stack
+ i
);
2610 int json_parse(const char *input
, JsonVariant
**ret
, unsigned *ret_line
, unsigned *ret_column
) {
2611 return json_parse_internal(&input
, NULL
, ret
, ret_line
, ret_column
, false);
2614 int json_parse_continue(const char **p
, JsonVariant
**ret
, unsigned *ret_line
, unsigned *ret_column
) {
2615 return json_parse_internal(p
, NULL
, ret
, ret_line
, ret_column
, true);
2618 int json_parse_file(FILE *f
, const char *path
, JsonVariant
**ret
, unsigned *ret_line
, unsigned *ret_column
) {
2619 _cleanup_(json_source_unrefp
) JsonSource
*source
= NULL
;
2620 _cleanup_free_
char *text
= NULL
;
2625 r
= read_full_stream(f
, &text
, NULL
);
2627 r
= read_full_file(path
, &text
, NULL
);
2634 source
= json_source_new(path
);
2640 return json_parse_internal(&p
, source
, ret
, ret_line
, ret_column
, false);
2643 int json_buildv(JsonVariant
**ret
, va_list ap
) {
2644 JsonStack
*stack
= NULL
;
2645 size_t n_stack
= 1, n_stack_allocated
= 0, i
;
2648 assert_return(ret
, -EINVAL
);
2650 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
))
2653 stack
[0] = (JsonStack
) {
2654 .expect
= EXPECT_TOPLEVEL
,
2658 _cleanup_(json_variant_unrefp
) JsonVariant
*add
= NULL
;
2662 assert(n_stack
> 0);
2663 current
= stack
+ n_stack
- 1;
2665 if (current
->expect
== EXPECT_END
)
2668 command
= va_arg(ap
, int);
2672 case _JSON_BUILD_STRING
: {
2675 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2680 p
= va_arg(ap
, const char *);
2682 r
= json_variant_new_string(&add
, p
);
2686 if (current
->expect
== EXPECT_TOPLEVEL
)
2687 current
->expect
= EXPECT_END
;
2688 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2689 current
->expect
= EXPECT_OBJECT_KEY
;
2691 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2696 case _JSON_BUILD_INTEGER
: {
2699 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2704 j
= va_arg(ap
, intmax_t);
2706 r
= json_variant_new_integer(&add
, j
);
2710 if (current
->expect
== EXPECT_TOPLEVEL
)
2711 current
->expect
= EXPECT_END
;
2712 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2713 current
->expect
= EXPECT_OBJECT_KEY
;
2715 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2720 case _JSON_BUILD_UNSIGNED
: {
2723 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2728 j
= va_arg(ap
, uintmax_t);
2730 r
= json_variant_new_unsigned(&add
, j
);
2734 if (current
->expect
== EXPECT_TOPLEVEL
)
2735 current
->expect
= EXPECT_END
;
2736 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2737 current
->expect
= EXPECT_OBJECT_KEY
;
2739 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2744 case _JSON_BUILD_REAL
: {
2747 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2752 d
= va_arg(ap
, long double);
2754 r
= json_variant_new_real(&add
, d
);
2758 if (current
->expect
== EXPECT_TOPLEVEL
)
2759 current
->expect
= EXPECT_END
;
2760 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2761 current
->expect
= EXPECT_OBJECT_KEY
;
2763 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2768 case _JSON_BUILD_BOOLEAN
: {
2771 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2776 b
= va_arg(ap
, int);
2778 r
= json_variant_new_boolean(&add
, b
);
2782 if (current
->expect
== EXPECT_TOPLEVEL
)
2783 current
->expect
= EXPECT_END
;
2784 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2785 current
->expect
= EXPECT_OBJECT_KEY
;
2787 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2792 case _JSON_BUILD_NULL
:
2794 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2799 r
= json_variant_new_null(&add
);
2803 if (current
->expect
== EXPECT_TOPLEVEL
)
2804 current
->expect
= EXPECT_END
;
2805 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2806 current
->expect
= EXPECT_OBJECT_KEY
;
2808 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2812 case _JSON_BUILD_VARIANT
:
2814 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2819 add
= va_arg(ap
, JsonVariant
*);
2821 add
= JSON_VARIANT_MAGIC_NULL
;
2823 json_variant_ref(add
);
2825 if (current
->expect
== EXPECT_TOPLEVEL
)
2826 current
->expect
= EXPECT_END
;
2827 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2828 current
->expect
= EXPECT_OBJECT_KEY
;
2830 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2834 case _JSON_BUILD_LITERAL
: {
2837 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2842 l
= va_arg(ap
, const char *);
2845 add
= JSON_VARIANT_MAGIC_NULL
;
2847 r
= json_parse(l
, &add
, NULL
, NULL
);
2852 if (current
->expect
== EXPECT_TOPLEVEL
)
2853 current
->expect
= EXPECT_END
;
2854 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2855 current
->expect
= EXPECT_OBJECT_KEY
;
2857 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2862 case _JSON_BUILD_ARRAY_BEGIN
:
2864 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2869 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
2873 current
= stack
+ n_stack
- 1;
2875 if (current
->expect
== EXPECT_TOPLEVEL
)
2876 current
->expect
= EXPECT_END
;
2877 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2878 current
->expect
= EXPECT_OBJECT_KEY
;
2880 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2882 stack
[n_stack
++] = (JsonStack
) {
2883 .expect
= EXPECT_ARRAY_ELEMENT
,
2888 case _JSON_BUILD_ARRAY_END
:
2889 if (current
->expect
!= EXPECT_ARRAY_ELEMENT
) {
2894 assert(n_stack
> 1);
2896 r
= json_variant_new_array(&add
, current
->elements
, current
->n_elements
);
2900 json_stack_release(current
);
2901 n_stack
--, current
--;
2905 case _JSON_BUILD_STRV
: {
2908 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2913 l
= va_arg(ap
, char **);
2915 r
= json_variant_new_array_strv(&add
, l
);
2919 if (current
->expect
== EXPECT_TOPLEVEL
)
2920 current
->expect
= EXPECT_END
;
2921 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2922 current
->expect
= EXPECT_OBJECT_KEY
;
2924 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2929 case _JSON_BUILD_OBJECT_BEGIN
:
2931 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2936 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
2940 current
= stack
+ n_stack
- 1;
2942 if (current
->expect
== EXPECT_TOPLEVEL
)
2943 current
->expect
= EXPECT_END
;
2944 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2945 current
->expect
= EXPECT_OBJECT_KEY
;
2947 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2949 stack
[n_stack
++] = (JsonStack
) {
2950 .expect
= EXPECT_OBJECT_KEY
,
2955 case _JSON_BUILD_OBJECT_END
:
2957 if (current
->expect
!= EXPECT_OBJECT_KEY
) {
2962 assert(n_stack
> 1);
2964 r
= json_variant_new_object(&add
, current
->elements
, current
->n_elements
);
2968 json_stack_release(current
);
2969 n_stack
--, current
--;
2973 case _JSON_BUILD_PAIR
: {
2976 if (current
->expect
!= EXPECT_OBJECT_KEY
) {
2981 n
= va_arg(ap
, const char *);
2983 r
= json_variant_new_string(&add
, n
);
2987 current
->expect
= EXPECT_OBJECT_VALUE
;
2992 if (!GREEDY_REALLOC(current
->elements
, current
->n_elements_allocated
, current
->n_elements
+ 1)) {
2997 current
->elements
[current
->n_elements
++] = TAKE_PTR(add
);
3002 assert(n_stack
== 1);
3003 assert(stack
[0].n_elements
== 1);
3005 *ret
= json_variant_ref(stack
[0].elements
[0]);
3009 for (i
= 0; i
< n_stack
; i
++)
3010 json_stack_release(stack
+ i
);
3019 int json_build(JsonVariant
**ret
, ...) {
3024 r
= json_buildv(ret
, ap
);
3030 int json_log_internal(
3031 JsonVariant
*variant
,
3037 const char *format
, ...) {
3041 unsigned source_line
, source_column
;
3042 char buffer
[LINE_MAX
];
3052 va_start(ap
, format
);
3053 (void) vsnprintf(buffer
, sizeof buffer
, format
, ap
);
3057 r
= json_variant_get_source(variant
, &source
, &source_line
, &source_column
);
3066 if (source
&& source_line
> 0 && source_column
> 0)
3067 return log_struct_internal(
3068 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD
, level
),
3071 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR
,
3072 "CONFIG_FILE=%s", source
,
3073 "CONFIG_LINE=%u", source_line
,
3074 "CONFIG_COLUMN=%u", source_column
,
3075 LOG_MESSAGE("%s:%u: %s", source
, line
, buffer
),
3078 return log_struct_internal(
3079 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD
, level
),
3082 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR
,
3083 LOG_MESSAGE("%s", buffer
),
3087 int json_dispatch(JsonVariant
*v
, const JsonDispatch table
[], JsonDispatchCallback bad
, JsonDispatchFlags flags
, void *userdata
) {
3088 const JsonDispatch
*p
;
3093 if (!json_variant_is_object(v
)) {
3094 json_log(v
, flags
, 0, "JSON variant is not an object.");
3096 if (flags
& JSON_PERMISSIVE
)
3102 for (p
= table
, m
= 0; p
->name
; p
++)
3105 found
= newa0(bool, m
);
3107 n
= json_variant_elements(v
);
3108 for (i
= 0; i
< n
; i
+= 2) {
3109 JsonVariant
*key
, *value
;
3111 assert_se(key
= json_variant_by_index(v
, i
));
3112 assert_se(value
= json_variant_by_index(v
, i
+1));
3114 for (p
= table
; p
->name
; p
++)
3115 if (p
->name
== (const char*) -1 ||
3116 streq_ptr(json_variant_string(key
), p
->name
))
3119 if (p
->name
) { /* Found a matching entry! :-) */
3120 JsonDispatchFlags merged_flags
;
3122 merged_flags
= flags
| p
->flags
;
3124 if (p
->type
!= _JSON_VARIANT_TYPE_INVALID
&&
3125 !json_variant_has_type(value
, p
->type
)) {
3127 json_log(value
, merged_flags
, 0,
3128 "Object field '%s' has wrong type %s, expected %s.", json_variant_string(key
),
3129 json_variant_type_to_string(json_variant_type(value
)), json_variant_type_to_string(p
->type
));
3131 if (merged_flags
& JSON_PERMISSIVE
)
3137 if (found
[p
-table
]) {
3138 json_log(value
, merged_flags
, 0, "Duplicate object field '%s'.", json_variant_string(key
));
3140 if (merged_flags
& JSON_PERMISSIVE
)
3146 found
[p
-table
] = true;
3149 r
= p
->callback(json_variant_string(key
), value
, merged_flags
, (uint8_t*) userdata
+ p
->offset
);
3151 if (merged_flags
& JSON_PERMISSIVE
)
3160 } else { /* Didn't find a matching entry! :-( */
3163 r
= bad(json_variant_string(key
), value
, flags
, userdata
);
3165 if (flags
& JSON_PERMISSIVE
)
3173 json_log(value
, flags
, 0, "Unexpected object field '%s'.", json_variant_string(key
));
3175 if (flags
& JSON_PERMISSIVE
)
3178 return -EADDRNOTAVAIL
;
3183 for (p
= table
; p
->name
; p
++) {
3184 JsonDispatchFlags merged_flags
= p
->flags
| flags
;
3186 if ((merged_flags
& JSON_MANDATORY
) && !found
[p
-table
]) {
3187 json_log(v
, merged_flags
, 0, "Missing object field '%s'.", p
->name
);
3189 if ((merged_flags
& JSON_PERMISSIVE
))
3199 int json_dispatch_boolean(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3205 if (!json_variant_is_boolean(variant
)) {
3206 json_log(variant
, flags
, 0, "JSON field '%s' is not a boolean.", strna(name
));
3210 *b
= json_variant_boolean(variant
);
3214 int json_dispatch_tristate(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3220 if (!json_variant_is_boolean(variant
)) {
3221 json_log(variant
, flags
, 0, "JSON field '%s' is not a boolean.", strna(name
));
3225 *b
= json_variant_boolean(variant
);
3229 int json_dispatch_integer(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3230 intmax_t *i
= userdata
;
3235 if (!json_variant_is_integer(variant
)) {
3236 json_log(variant
, flags
, 0, "JSON field '%s' is not an integer.", strna(name
));
3240 *i
= json_variant_integer(variant
);
3244 int json_dispatch_unsigned(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3245 uintmax_t *u
= userdata
;
3250 if (!json_variant_is_unsigned(variant
)) {
3251 json_log(variant
, flags
, 0, "JSON field '%s' is not an unsigned integer.", strna(name
));
3255 *u
= json_variant_unsigned(variant
);
3259 int json_dispatch_uint32(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3260 uint32_t *u
= userdata
;
3265 if (!json_variant_is_unsigned(variant
)) {
3266 json_log(variant
, flags
, 0, "JSON field '%s' is not an unsigned integer.", strna(name
));
3270 if (json_variant_unsigned(variant
) > UINT32_MAX
) {
3271 json_log(variant
, flags
, 0, "JSON field '%s' out of bounds.", strna(name
));
3275 *u
= (uint32_t) json_variant_unsigned(variant
);
3279 int json_dispatch_int32(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3280 int32_t *i
= userdata
;
3285 if (!json_variant_is_integer(variant
)) {
3286 json_log(variant
, flags
, 0, "JSON field '%s' is not an integer.", strna(name
));
3290 if (json_variant_integer(variant
) < INT32_MIN
|| json_variant_integer(variant
) > INT32_MAX
) {
3291 json_log(variant
, flags
, 0, "JSON field '%s' out of bounds.", strna(name
));
3295 *i
= (int32_t) json_variant_integer(variant
);
3299 int json_dispatch_string(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3300 char **s
= userdata
;
3306 if (json_variant_is_null(variant
)) {
3311 if (!json_variant_is_string(variant
)) {
3312 json_log(variant
, flags
, 0, "JSON field '%s' is not a string.", strna(name
));
3316 r
= free_and_strdup(s
, json_variant_string(variant
));
3318 return json_log(variant
, flags
, r
, "Failed to allocate string: %m");
3323 int json_dispatch_strv(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3324 _cleanup_strv_free_
char **l
= NULL
;
3325 char ***s
= userdata
;
3332 if (json_variant_is_null(variant
)) {
3337 if (!json_variant_is_array(variant
)) {
3338 json_log(variant
, 0, flags
, "JSON field '%s' is not an array.", strna(name
));
3342 for (i
= 0; i
< json_variant_elements(variant
); i
++) {
3345 assert_se(e
= json_variant_by_index(variant
, i
));
3347 if (!json_variant_is_string(e
)) {
3348 json_log(e
, 0, flags
, "JSON array element is not a string.");
3352 r
= strv_extend(&l
, json_variant_string(e
));
3354 return json_log(variant
, flags
, r
, "Failed to append array element: %m");
3357 strv_free_and_replace(*s
, l
);
3361 int json_dispatch_variant(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3362 JsonVariant
**p
= userdata
;
3367 json_variant_unref(*p
);
3368 *p
= json_variant_ref(variant
);
3373 static const char* const json_variant_type_table
[_JSON_VARIANT_TYPE_MAX
] = {
3374 [JSON_VARIANT_STRING
] = "string",
3375 [JSON_VARIANT_INTEGER
] = "integer",
3376 [JSON_VARIANT_UNSIGNED
] = "unsigned",
3377 [JSON_VARIANT_REAL
] = "real",
3378 [JSON_VARIANT_NUMBER
] = "number",
3379 [JSON_VARIANT_BOOLEAN
] = "boolean",
3380 [JSON_VARIANT_ARRAY
] = "array",
3381 [JSON_VARIANT_OBJECT
] = "object",
3382 [JSON_VARIANT_NULL
] = "null",
3385 DEFINE_STRING_TABLE_LOOKUP(json_variant_type
, JsonVariantType
);