1 /* SPDX-License-Identifier: LGPL-2.1+ */
10 #include "sd-messages.h"
12 #include "alloc-util.h"
13 #include "errno-util.h"
17 #include "hexdecoct.h"
18 #include "json-internal.h"
21 #include "memory-util.h"
22 #include "string-table.h"
23 #include "string-util.h"
25 #include "terminal-util.h"
28 /* Refuse putting together variants with a larger depth than 4K by default (as a protection against overflowing stacks
29 * if code processes JSON objects recursively. Note that we store the depth in an uint16_t, hence make sure this
31 * The value was 16k, but it was discovered to be too high on llvm/x86-64. See also the issue #10738. */
32 #define DEPTH_MAX (4U*1024U)
33 assert_cc(DEPTH_MAX
<= UINT16_MAX
);
35 typedef struct JsonSource
{
36 /* When we parse from a file or similar, encodes the filename, to indicate the source of a json variant */
43 /* On x86-64 this whole structure should have a size of 6 * 64 bit = 48 bytes */
46 /* We either maintain a reference counter for this variant itself, or we are embedded into an
47 * array/object, in which case only that surrounding object is ref-counted. (If 'embedded' is false,
51 /* If this JsonVariant is part of an array/object, then this field points to the surrounding
52 * JSON_VARIANT_ARRAY/JSON_VARIANT_OBJECT object. (If 'embedded' is true, see below.) */
56 /* If this was parsed from some file or buffer, this stores where from, as well as the source line/column */
58 unsigned line
, column
;
60 JsonVariantType type
:5;
62 /* A marker whether this variant is embedded into in array/object or not. If true, the 'parent' pointer above
63 * is valid. If false, the 'n_ref' field above is valid instead. */
66 /* In some conditions (for example, if this object is part of an array of strings or objects), we don't store
67 * any data inline, but instead simply reference an external object and act as surrogate of it. In that case
68 * this bool is set, and the external object is referenced through the .reference field below. */
71 /* While comparing two arrays, we use this for marking what we already have seen */
74 /* The current 'depth' of the JsonVariant, i.e. how many levels of member variants this has */
78 /* For simple types we store the value in-line. */
81 /* For objects and arrays we store the number of elements immediately following */
84 /* If is_reference as indicated above is set, this is where the reference object is actually stored. */
85 JsonVariant
*reference
;
87 /* Strings are placed immediately after the structure. Note that when this is a JsonVariant embedded
88 * into an array we might encode strings up to INLINE_STRING_LENGTH characters directly inside the
89 * element, while longer strings are stored as references. When this object is not embedded into an
90 * array, but stand-alone we allocate the right size for the whole structure, i.e. the array might be
91 * much larger than INLINE_STRING_LENGTH.
93 * Note that because we want to allocate arrays of the JsonVariant structure we specify [0] here,
94 * rather than the prettier []. If we wouldn't, then this char array would have undefined size, and so
95 * would the union and then the struct this is included in. And of structures with undefined size we
96 * can't allocate arrays (at least not easily). */
101 /* Inside string arrays we have a series of JasonVariant structures one after the other. In this case, strings longer
102 * than INLINE_STRING_MAX are stored as references, and all shorter ones inline. (This means — on x86-64 — strings up
103 * to 15 chars are stored within the array elements, and all others in separate allocations) */
104 #define INLINE_STRING_MAX (sizeof(JsonVariant) - offsetof(JsonVariant, string) - 1U)
106 /* Let's make sure this structure isn't increased in size accidentally. This check is only for our most relevant arch
109 assert_cc(sizeof(JsonVariant
) == 48U);
110 assert_cc(INLINE_STRING_MAX
== 15U);
113 static JsonSource
* json_source_new(const char *name
) {
118 s
= malloc(offsetof(JsonSource
, name
) + strlen(name
) + 1);
125 strcpy(s
->name
, name
);
130 DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(JsonSource
, json_source
, mfree
);
132 static bool json_source_equal(JsonSource
*a
, JsonSource
*b
) {
139 return streq(a
->name
, b
->name
);
142 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonSource
*, json_source_unref
);
144 /* There are four kind of JsonVariant* pointers:
147 * 2. A 'regular' one, i.e. pointing to malloc() memory
148 * 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.
149 * 4. A 'const string' one, i.e. a pointer to a const string.
151 * The four kinds of pointers can be discerned like this:
153 * Detecting #1 is easy, just compare with NULL. Detecting #3 is similarly easy: all magic pointers are below
154 * _JSON_VARIANT_MAGIC_MAX (which is pretty low, within the first memory page, which is special on Linux and other
155 * 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,
156 * otherwise #4. This makes use of the fact that malloc() will return "maximum aligned" memory, which definitely
157 * means the pointer is even. This means we can use the uneven pointers to reference static strings, as long as we
158 * make sure that all static strings used like this are aligned to 2 (or higher), and that we mask the bit on
159 * access. The JSON_VARIANT_STRING_CONST() macro encodes strings as JsonVariant* pointers, with the bit set. */
161 static bool json_variant_is_magic(const JsonVariant
*v
) {
165 return v
< _JSON_VARIANT_MAGIC_MAX
;
168 static bool json_variant_is_const_string(const JsonVariant
*v
) {
170 if (v
< _JSON_VARIANT_MAGIC_MAX
)
173 /* A proper JsonVariant is aligned to whatever malloc() aligns things too, which is definitely not uneven. We
174 * hence use all uneven pointers as indicators for const strings. */
176 return (((uintptr_t) v
) & 1) != 0;
179 static bool json_variant_is_regular(const JsonVariant
*v
) {
181 if (v
< _JSON_VARIANT_MAGIC_MAX
)
184 return (((uintptr_t) v
) & 1) == 0;
187 static JsonVariant
*json_variant_dereference(JsonVariant
*v
) {
189 /* Recursively dereference variants that are references to other variants */
194 if (!json_variant_is_regular(v
))
197 if (!v
->is_reference
)
200 return json_variant_dereference(v
->reference
);
203 static uint16_t json_variant_depth(JsonVariant
*v
) {
205 v
= json_variant_dereference(v
);
209 if (!json_variant_is_regular(v
))
215 static JsonVariant
*json_variant_normalize(JsonVariant
*v
) {
217 /* Converts json variants to their normalized form, i.e. fully dereferenced and wherever possible converted to
218 * the "magic" version if there is one */
223 v
= json_variant_dereference(v
);
225 switch (json_variant_type(v
)) {
227 case JSON_VARIANT_BOOLEAN
:
228 return json_variant_boolean(v
) ? JSON_VARIANT_MAGIC_TRUE
: JSON_VARIANT_MAGIC_FALSE
;
230 case JSON_VARIANT_NULL
:
231 return JSON_VARIANT_MAGIC_NULL
;
233 case JSON_VARIANT_INTEGER
:
234 return json_variant_integer(v
) == 0 ? JSON_VARIANT_MAGIC_ZERO_INTEGER
: v
;
236 case JSON_VARIANT_UNSIGNED
:
237 return json_variant_unsigned(v
) == 0 ? JSON_VARIANT_MAGIC_ZERO_UNSIGNED
: v
;
239 case JSON_VARIANT_REAL
:
240 #pragma GCC diagnostic push
241 #pragma GCC diagnostic ignored "-Wfloat-equal"
242 return json_variant_real(v
) == 0.0 ? JSON_VARIANT_MAGIC_ZERO_REAL
: v
;
243 #pragma GCC diagnostic pop
245 case JSON_VARIANT_STRING
:
246 return isempty(json_variant_string(v
)) ? JSON_VARIANT_MAGIC_EMPTY_STRING
: v
;
248 case JSON_VARIANT_ARRAY
:
249 return json_variant_elements(v
) == 0 ? JSON_VARIANT_MAGIC_EMPTY_ARRAY
: v
;
251 case JSON_VARIANT_OBJECT
:
252 return json_variant_elements(v
) == 0 ? JSON_VARIANT_MAGIC_EMPTY_OBJECT
: v
;
259 static JsonVariant
*json_variant_conservative_normalize(JsonVariant
*v
) {
261 /* Much like json_variant_normalize(), but won't simplify if the variant has a source/line location attached to
262 * it, in order not to lose context */
267 if (!json_variant_is_regular(v
))
270 if (v
->source
|| v
->line
> 0 || v
->column
> 0)
273 return json_variant_normalize(v
);
276 static int json_variant_new(JsonVariant
**ret
, JsonVariantType type
, size_t space
) {
279 assert_return(ret
, -EINVAL
);
281 v
= malloc0(MAX(sizeof(JsonVariant
),
282 offsetof(JsonVariant
, value
) + space
));
293 int json_variant_new_integer(JsonVariant
**ret
, intmax_t i
) {
297 assert_return(ret
, -EINVAL
);
300 *ret
= JSON_VARIANT_MAGIC_ZERO_INTEGER
;
304 r
= json_variant_new(&v
, JSON_VARIANT_INTEGER
, sizeof(i
));
308 v
->value
.integer
= i
;
314 int json_variant_new_unsigned(JsonVariant
**ret
, uintmax_t u
) {
318 assert_return(ret
, -EINVAL
);
320 *ret
= JSON_VARIANT_MAGIC_ZERO_UNSIGNED
;
324 r
= json_variant_new(&v
, JSON_VARIANT_UNSIGNED
, sizeof(u
));
334 int json_variant_new_real(JsonVariant
**ret
, long double d
) {
338 assert_return(ret
, -EINVAL
);
340 #pragma GCC diagnostic push
341 #pragma GCC diagnostic ignored "-Wfloat-equal"
343 #pragma GCC diagnostic pop
344 *ret
= JSON_VARIANT_MAGIC_ZERO_REAL
;
348 r
= json_variant_new(&v
, JSON_VARIANT_REAL
, sizeof(d
));
358 int json_variant_new_boolean(JsonVariant
**ret
, bool b
) {
359 assert_return(ret
, -EINVAL
);
362 *ret
= JSON_VARIANT_MAGIC_TRUE
;
364 *ret
= JSON_VARIANT_MAGIC_FALSE
;
369 int json_variant_new_null(JsonVariant
**ret
) {
370 assert_return(ret
, -EINVAL
);
372 *ret
= JSON_VARIANT_MAGIC_NULL
;
376 int json_variant_new_stringn(JsonVariant
**ret
, const char *s
, size_t n
) {
380 assert_return(ret
, -EINVAL
);
382 assert_return(IN_SET(n
, 0, (size_t) -1), -EINVAL
);
383 return json_variant_new_null(ret
);
385 if (n
== (size_t) -1) /* determine length automatically */
387 else if (memchr(s
, 0, n
)) /* don't allow embedded NUL, as we can't express that in JSON */
390 *ret
= JSON_VARIANT_MAGIC_EMPTY_STRING
;
394 r
= json_variant_new(&v
, JSON_VARIANT_STRING
, n
+ 1);
398 memcpy(v
->string
, s
, n
);
405 static void json_variant_set(JsonVariant
*a
, JsonVariant
*b
) {
408 b
= json_variant_dereference(b
);
410 a
->type
= JSON_VARIANT_NULL
;
414 a
->type
= json_variant_type(b
);
417 case JSON_VARIANT_INTEGER
:
418 a
->value
.integer
= json_variant_integer(b
);
421 case JSON_VARIANT_UNSIGNED
:
422 a
->value
.unsig
= json_variant_unsigned(b
);
425 case JSON_VARIANT_REAL
:
426 a
->value
.real
= json_variant_real(b
);
429 case JSON_VARIANT_BOOLEAN
:
430 a
->value
.boolean
= json_variant_boolean(b
);
433 case JSON_VARIANT_STRING
: {
436 assert_se(s
= json_variant_string(b
));
438 /* Short strings we can store inline */
439 if (strnlen(s
, INLINE_STRING_MAX
+1) <= INLINE_STRING_MAX
) {
440 strcpy(a
->string
, s
);
444 /* For longer strings, use a reference… */
448 case JSON_VARIANT_ARRAY
:
449 case JSON_VARIANT_OBJECT
:
450 a
->is_reference
= true;
451 a
->reference
= json_variant_ref(json_variant_conservative_normalize(b
));
454 case JSON_VARIANT_NULL
:
458 assert_not_reached("Unexpected variant type");
462 static void json_variant_copy_source(JsonVariant
*v
, JsonVariant
*from
) {
466 if (!json_variant_is_regular(from
))
469 v
->line
= from
->line
;
470 v
->column
= from
->column
;
471 v
->source
= json_source_ref(from
->source
);
474 int json_variant_new_array(JsonVariant
**ret
, JsonVariant
**array
, size_t n
) {
475 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
477 assert_return(ret
, -EINVAL
);
479 *ret
= JSON_VARIANT_MAGIC_EMPTY_ARRAY
;
482 assert_return(array
, -EINVAL
);
484 v
= new(JsonVariant
, n
+ 1);
490 .type
= JSON_VARIANT_ARRAY
,
493 for (v
->n_elements
= 0; v
->n_elements
< n
; v
->n_elements
++) {
494 JsonVariant
*w
= v
+ 1 + v
->n_elements
,
495 *c
= array
[v
->n_elements
];
498 d
= json_variant_depth(c
);
499 if (d
>= DEPTH_MAX
) /* Refuse too deep nesting */
509 json_variant_set(w
, c
);
510 json_variant_copy_source(w
, c
);
517 int json_variant_new_array_bytes(JsonVariant
**ret
, const void *p
, size_t n
) {
521 assert_return(ret
, -EINVAL
);
523 *ret
= JSON_VARIANT_MAGIC_EMPTY_ARRAY
;
526 assert_return(p
, -EINVAL
);
528 v
= new(JsonVariant
, n
+ 1);
534 .type
= JSON_VARIANT_ARRAY
,
539 for (i
= 0; i
< n
; i
++) {
540 JsonVariant
*w
= v
+ 1 + i
;
545 .type
= JSON_VARIANT_UNSIGNED
,
546 .value
.unsig
= ((const uint8_t*) p
)[i
],
554 int json_variant_new_array_strv(JsonVariant
**ret
, char **l
) {
555 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
563 *ret
= JSON_VARIANT_MAGIC_EMPTY_ARRAY
;
567 v
= new(JsonVariant
, n
+ 1);
573 .type
= JSON_VARIANT_ARRAY
,
577 for (v
->n_elements
= 0; v
->n_elements
< n
; v
->n_elements
++) {
578 JsonVariant
*w
= v
+ 1 + v
->n_elements
;
584 .type
= JSON_VARIANT_STRING
,
587 k
= strlen(l
[v
->n_elements
]);
589 if (k
> INLINE_STRING_MAX
) {
590 /* If string is too long, store it as reference. */
592 r
= json_variant_new_string(&w
->reference
, l
[v
->n_elements
]);
596 w
->is_reference
= true;
598 memcpy(w
->string
, l
[v
->n_elements
], k
+1);
605 int json_variant_new_object(JsonVariant
**ret
, JsonVariant
**array
, size_t n
) {
606 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
608 assert_return(ret
, -EINVAL
);
610 *ret
= JSON_VARIANT_MAGIC_EMPTY_OBJECT
;
613 assert_return(array
, -EINVAL
);
614 assert_return(n
% 2 == 0, -EINVAL
);
616 v
= new(JsonVariant
, n
+ 1);
622 .type
= JSON_VARIANT_OBJECT
,
625 for (v
->n_elements
= 0; v
->n_elements
< n
; v
->n_elements
++) {
626 JsonVariant
*w
= v
+ 1 + v
->n_elements
,
627 *c
= array
[v
->n_elements
];
630 if ((v
->n_elements
& 1) == 0 &&
631 !json_variant_is_string(c
))
632 return -EINVAL
; /* Every second one needs to be a string, as it is the key name */
634 d
= json_variant_depth(c
);
635 if (d
>= DEPTH_MAX
) /* Refuse too deep nesting */
645 json_variant_set(w
, c
);
646 json_variant_copy_source(w
, c
);
653 static void json_variant_free_inner(JsonVariant
*v
) {
656 if (!json_variant_is_regular(v
))
659 json_source_unref(v
->source
);
661 if (v
->is_reference
) {
662 json_variant_unref(v
->reference
);
666 if (IN_SET(v
->type
, JSON_VARIANT_ARRAY
, JSON_VARIANT_OBJECT
)) {
669 for (i
= 0; i
< v
->n_elements
; i
++)
670 json_variant_free_inner(v
+ 1 + i
);
674 JsonVariant
*json_variant_ref(JsonVariant
*v
) {
677 if (!json_variant_is_regular(v
))
681 json_variant_ref(v
->parent
); /* ref the compounding variant instead */
683 assert(v
->n_ref
> 0);
690 JsonVariant
*json_variant_unref(JsonVariant
*v
) {
693 if (!json_variant_is_regular(v
))
697 json_variant_unref(v
->parent
);
699 assert(v
->n_ref
> 0);
703 json_variant_free_inner(v
);
711 void json_variant_unref_many(JsonVariant
**array
, size_t n
) {
714 assert(array
|| n
== 0);
716 for (i
= 0; i
< n
; i
++)
717 json_variant_unref(array
[i
]);
720 const char *json_variant_string(JsonVariant
*v
) {
723 if (v
== JSON_VARIANT_MAGIC_EMPTY_STRING
)
725 if (json_variant_is_magic(v
))
727 if (json_variant_is_const_string(v
)) {
728 uintptr_t p
= (uintptr_t) v
;
730 assert((p
& 1) != 0);
731 return (const char*) (p
^ 1U);
735 return json_variant_string(v
->reference
);
736 if (v
->type
!= JSON_VARIANT_STRING
)
742 log_debug("Non-string JSON variant requested as string, returning NULL.");
746 bool json_variant_boolean(JsonVariant
*v
) {
749 if (v
== JSON_VARIANT_MAGIC_TRUE
)
751 if (v
== JSON_VARIANT_MAGIC_FALSE
)
753 if (!json_variant_is_regular(v
))
755 if (v
->type
!= JSON_VARIANT_BOOLEAN
)
758 return json_variant_boolean(v
->reference
);
760 return v
->value
.boolean
;
763 log_debug("Non-boolean JSON variant requested as boolean, returning false.");
767 intmax_t json_variant_integer(JsonVariant
*v
) {
770 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
771 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
772 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
774 if (!json_variant_is_regular(v
))
777 return json_variant_integer(v
->reference
);
781 case JSON_VARIANT_INTEGER
:
782 return v
->value
.integer
;
784 case JSON_VARIANT_UNSIGNED
:
785 if (v
->value
.unsig
<= INTMAX_MAX
)
786 return (intmax_t) v
->value
.unsig
;
788 log_debug("Unsigned integer %ju requested as signed integer and out of range, returning 0.", v
->value
.unsig
);
791 case JSON_VARIANT_REAL
: {
794 converted
= (intmax_t) v
->value
.real
;
796 #pragma GCC diagnostic push
797 #pragma GCC diagnostic ignored "-Wfloat-equal"
798 if ((long double) converted
== v
->value
.real
)
799 #pragma GCC diagnostic pop
802 log_debug("Real %Lg requested as integer, and cannot be converted losslessly, returning 0.", v
->value
.real
);
811 log_debug("Non-integer JSON variant requested as integer, returning 0.");
815 uintmax_t json_variant_unsigned(JsonVariant
*v
) {
818 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
819 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
820 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
822 if (!json_variant_is_regular(v
))
825 return json_variant_integer(v
->reference
);
829 case JSON_VARIANT_INTEGER
:
830 if (v
->value
.integer
>= 0)
831 return (uintmax_t) v
->value
.integer
;
833 log_debug("Signed integer %ju requested as unsigned integer and out of range, returning 0.", v
->value
.integer
);
836 case JSON_VARIANT_UNSIGNED
:
837 return v
->value
.unsig
;
839 case JSON_VARIANT_REAL
: {
842 converted
= (uintmax_t) v
->value
.real
;
844 #pragma GCC diagnostic push
845 #pragma GCC diagnostic ignored "-Wfloat-equal"
846 if ((long double) converted
== v
->value
.real
)
847 #pragma GCC diagnostic pop
850 log_debug("Real %Lg requested as unsigned integer, and cannot be converted losslessly, returning 0.", v
->value
.real
);
859 log_debug("Non-integer JSON variant requested as unsigned, returning 0.");
863 long double json_variant_real(JsonVariant
*v
) {
866 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
867 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
868 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
870 if (!json_variant_is_regular(v
))
873 return json_variant_real(v
->reference
);
877 case JSON_VARIANT_REAL
:
878 return v
->value
.real
;
880 case JSON_VARIANT_INTEGER
: {
881 long double converted
;
883 converted
= (long double) v
->value
.integer
;
885 if ((intmax_t) converted
== v
->value
.integer
)
888 log_debug("Signed integer %ji requested as real, and cannot be converted losslessly, returning 0.", v
->value
.integer
);
892 case JSON_VARIANT_UNSIGNED
: {
893 long double converted
;
895 converted
= (long double) v
->value
.unsig
;
897 if ((uintmax_t) converted
== v
->value
.unsig
)
900 log_debug("Unsigned integer %ju requested as real, and cannot be converted losslessly, returning 0.", v
->value
.unsig
);
909 log_debug("Non-integer JSON variant requested as integer, returning 0.");
913 bool json_variant_is_negative(JsonVariant
*v
) {
916 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
917 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
918 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
920 if (!json_variant_is_regular(v
))
923 return json_variant_is_negative(v
->reference
);
925 /* This function is useful as checking whether numbers are negative is pretty complex since we have three types
926 * of numbers. And some JSON code (OCI for example) uses negative numbers to mark "not defined" numeric
931 case JSON_VARIANT_REAL
:
932 return v
->value
.real
< 0;
934 case JSON_VARIANT_INTEGER
:
935 return v
->value
.integer
< 0;
937 case JSON_VARIANT_UNSIGNED
:
945 log_debug("Non-integer JSON variant tested for negativity, returning false.");
949 bool json_variant_is_blank_object(JsonVariant
*v
) {
950 /* Returns true if the specified object is null or empty */
952 json_variant_is_null(v
) ||
953 (json_variant_is_object(v
) && json_variant_elements(v
) == 0);
956 bool json_variant_is_blank_array(JsonVariant
*v
) {
958 json_variant_is_null(v
) ||
959 (json_variant_is_array(v
) && json_variant_elements(v
) == 0);
962 JsonVariantType
json_variant_type(JsonVariant
*v
) {
965 return _JSON_VARIANT_TYPE_INVALID
;
967 if (json_variant_is_const_string(v
))
968 return JSON_VARIANT_STRING
;
970 if (v
== JSON_VARIANT_MAGIC_TRUE
|| v
== JSON_VARIANT_MAGIC_FALSE
)
971 return JSON_VARIANT_BOOLEAN
;
973 if (v
== JSON_VARIANT_MAGIC_NULL
)
974 return JSON_VARIANT_NULL
;
976 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
)
977 return JSON_VARIANT_INTEGER
;
979 if (v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
)
980 return JSON_VARIANT_UNSIGNED
;
982 if (v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
983 return JSON_VARIANT_REAL
;
985 if (v
== JSON_VARIANT_MAGIC_EMPTY_STRING
)
986 return JSON_VARIANT_STRING
;
988 if (v
== JSON_VARIANT_MAGIC_EMPTY_ARRAY
)
989 return JSON_VARIANT_ARRAY
;
991 if (v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
992 return JSON_VARIANT_OBJECT
;
997 bool json_variant_has_type(JsonVariant
*v
, JsonVariantType type
) {
1000 v
= json_variant_dereference(v
);
1004 rt
= json_variant_type(v
);
1008 /* If it's a const string, then it only can be a string, and if it is not, it's not */
1009 if (json_variant_is_const_string(v
))
1012 /* All three magic zeroes qualify as integer, unsigned and as real */
1013 if ((v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
|| v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
|| v
== JSON_VARIANT_MAGIC_ZERO_REAL
) &&
1014 IN_SET(type
, JSON_VARIANT_INTEGER
, JSON_VARIANT_UNSIGNED
, JSON_VARIANT_REAL
, JSON_VARIANT_NUMBER
))
1017 /* All other magic variant types are only equal to themselves */
1018 if (json_variant_is_magic(v
))
1021 /* Handle the "number" pseudo type */
1022 if (type
== JSON_VARIANT_NUMBER
)
1023 return IN_SET(rt
, JSON_VARIANT_INTEGER
, JSON_VARIANT_UNSIGNED
, JSON_VARIANT_REAL
);
1025 /* Integer conversions are OK in many cases */
1026 if (rt
== JSON_VARIANT_INTEGER
&& type
== JSON_VARIANT_UNSIGNED
)
1027 return v
->value
.integer
>= 0;
1028 if (rt
== JSON_VARIANT_UNSIGNED
&& type
== JSON_VARIANT_INTEGER
)
1029 return v
->value
.unsig
<= INTMAX_MAX
;
1031 /* Any integer that can be converted lossley to a real and back may also be considered a real */
1032 if (rt
== JSON_VARIANT_INTEGER
&& type
== JSON_VARIANT_REAL
)
1033 return (intmax_t) (long double) v
->value
.integer
== v
->value
.integer
;
1034 if (rt
== JSON_VARIANT_UNSIGNED
&& type
== JSON_VARIANT_REAL
)
1035 return (uintmax_t) (long double) v
->value
.unsig
== v
->value
.unsig
;
1037 #pragma GCC diagnostic push
1038 #pragma GCC diagnostic ignored "-Wfloat-equal"
1039 /* Any real that can be converted losslessly to an integer and back may also be considered an integer */
1040 if (rt
== JSON_VARIANT_REAL
&& type
== JSON_VARIANT_INTEGER
)
1041 return (long double) (intmax_t) v
->value
.real
== v
->value
.real
;
1042 if (rt
== JSON_VARIANT_REAL
&& type
== JSON_VARIANT_UNSIGNED
)
1043 return (long double) (uintmax_t) v
->value
.real
== v
->value
.real
;
1044 #pragma GCC diagnostic pop
1049 size_t json_variant_elements(JsonVariant
*v
) {
1052 if (v
== JSON_VARIANT_MAGIC_EMPTY_ARRAY
||
1053 v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
1055 if (!json_variant_is_regular(v
))
1057 if (!IN_SET(v
->type
, JSON_VARIANT_ARRAY
, JSON_VARIANT_OBJECT
))
1059 if (v
->is_reference
)
1060 return json_variant_elements(v
->reference
);
1062 return v
->n_elements
;
1065 log_debug("Number of elements in non-array/non-object JSON variant requested, returning 0.");
1069 JsonVariant
*json_variant_by_index(JsonVariant
*v
, size_t idx
) {
1072 if (v
== JSON_VARIANT_MAGIC_EMPTY_ARRAY
||
1073 v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
1075 if (!json_variant_is_regular(v
))
1077 if (!IN_SET(v
->type
, JSON_VARIANT_ARRAY
, JSON_VARIANT_OBJECT
))
1079 if (v
->is_reference
)
1080 return json_variant_by_index(v
->reference
, idx
);
1081 if (idx
>= v
->n_elements
)
1084 return json_variant_conservative_normalize(v
+ 1 + idx
);
1087 log_debug("Element in non-array/non-object JSON variant requested by index, returning NULL.");
1091 JsonVariant
*json_variant_by_key_full(JsonVariant
*v
, const char *key
, JsonVariant
**ret_key
) {
1098 if (v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
1100 if (!json_variant_is_regular(v
))
1102 if (v
->type
!= JSON_VARIANT_OBJECT
)
1104 if (v
->is_reference
)
1105 return json_variant_by_key(v
->reference
, key
);
1107 for (i
= 0; i
< v
->n_elements
; i
+= 2) {
1110 p
= json_variant_dereference(v
+ 1 + i
);
1112 if (!json_variant_has_type(p
, JSON_VARIANT_STRING
))
1115 if (streq(json_variant_string(p
), key
)) {
1118 *ret_key
= json_variant_conservative_normalize(v
+ 1 + i
);
1120 return json_variant_conservative_normalize(v
+ 1 + i
+ 1);
1131 log_debug("Element in non-object JSON variant requested by key, returning NULL.");
1138 JsonVariant
*json_variant_by_key(JsonVariant
*v
, const char *key
) {
1139 return json_variant_by_key_full(v
, key
, NULL
);
1142 bool json_variant_equal(JsonVariant
*a
, JsonVariant
*b
) {
1145 a
= json_variant_normalize(a
);
1146 b
= json_variant_normalize(b
);
1151 t
= json_variant_type(a
);
1152 if (!json_variant_has_type(b
, t
))
1157 case JSON_VARIANT_STRING
:
1158 return streq(json_variant_string(a
), json_variant_string(b
));
1160 case JSON_VARIANT_INTEGER
:
1161 return json_variant_integer(a
) == json_variant_integer(b
);
1163 case JSON_VARIANT_UNSIGNED
:
1164 return json_variant_unsigned(a
) == json_variant_unsigned(b
);
1166 case JSON_VARIANT_REAL
:
1167 #pragma GCC diagnostic push
1168 #pragma GCC diagnostic ignored "-Wfloat-equal"
1169 return json_variant_real(a
) == json_variant_real(b
);
1170 #pragma GCC diagnostic pop
1172 case JSON_VARIANT_BOOLEAN
:
1173 return json_variant_boolean(a
) == json_variant_boolean(b
);
1175 case JSON_VARIANT_NULL
:
1178 case JSON_VARIANT_ARRAY
: {
1181 n
= json_variant_elements(a
);
1182 if (n
!= json_variant_elements(b
))
1185 for (i
= 0; i
< n
; i
++) {
1186 if (!json_variant_equal(json_variant_by_index(a
, i
), json_variant_by_index(b
, i
)))
1193 case JSON_VARIANT_OBJECT
: {
1196 n
= json_variant_elements(a
);
1197 if (n
!= json_variant_elements(b
))
1200 /* Iterate through all keys in 'a' */
1201 for (i
= 0; i
< n
; i
+= 2) {
1205 /* Match them against all keys in 'b' */
1206 for (j
= 0; j
< n
; j
+= 2) {
1209 key_b
= json_variant_by_index(b
, j
);
1211 /* During the first iteration unmark everything */
1213 key_b
->is_marked
= false;
1214 else if (key_b
->is_marked
) /* In later iterations if we already marked something, don't bother with it again */
1220 if (json_variant_equal(json_variant_by_index(a
, i
), key_b
) &&
1221 json_variant_equal(json_variant_by_index(a
, i
+1), json_variant_by_index(b
, j
+1))) {
1222 /* Key and values match! */
1223 key_b
->is_marked
= found
= true;
1225 /* In the first iteration we continue the inner loop since we want to mark
1226 * everything, otherwise exit the loop quickly after we found what we were
1241 assert_not_reached("Unknown variant type.");
1245 int json_variant_get_source(JsonVariant
*v
, const char **ret_source
, unsigned *ret_line
, unsigned *ret_column
) {
1246 assert_return(v
, -EINVAL
);
1249 *ret_source
= json_variant_is_regular(v
) && v
->source
? v
->source
->name
: NULL
;
1252 *ret_line
= json_variant_is_regular(v
) ? v
->line
: 0;
1255 *ret_column
= json_variant_is_regular(v
) ? v
->column
: 0;
1260 static int print_source(FILE *f
, JsonVariant
*v
, JsonFormatFlags flags
, bool whitespace
) {
1263 if (!FLAGS_SET(flags
, JSON_FORMAT_SOURCE
|JSON_FORMAT_PRETTY
))
1266 if (!json_variant_is_regular(v
))
1269 if (!v
->source
&& v
->line
== 0 && v
->column
== 0)
1272 /* The max width we need to format the line numbers for this source file */
1273 w
= (v
->source
&& v
->source
->max_line
> 0) ?
1274 DECIMAL_STR_WIDTH(v
->source
->max_line
) :
1275 DECIMAL_STR_MAX(unsigned)-1;
1276 k
= (v
->source
&& v
->source
->max_column
> 0) ?
1277 DECIMAL_STR_WIDTH(v
->source
->max_column
) :
1278 DECIMAL_STR_MAX(unsigned) -1;
1283 n
= 1 + (v
->source
? strlen(v
->source
->name
) : 0) +
1284 ((v
->source
&& (v
->line
> 0 || v
->column
> 0)) ? 1 : 0) +
1285 (v
->line
> 0 ? w
: 0) +
1286 (((v
->source
|| v
->line
> 0) && v
->column
> 0) ? 1 : 0) +
1287 (v
->column
> 0 ? k
: 0) +
1290 for (i
= 0; i
< n
; i
++)
1296 fputs(v
->source
->name
, f
);
1297 if (v
->source
&& (v
->line
> 0 || v
->column
> 0))
1300 fprintf(f
, "%*u", (int) w
, v
->line
);
1301 if ((v
->source
|| v
->line
> 0) || v
->column
> 0)
1304 fprintf(f
, "%*u", (int) k
, v
->column
);
1313 static int json_format(FILE *f
, JsonVariant
*v
, JsonFormatFlags flags
, const char *prefix
) {
1319 switch (json_variant_type(v
)) {
1321 case JSON_VARIANT_REAL
: {
1324 loc
= newlocale(LC_NUMERIC_MASK
, "C", (locale_t
) 0);
1325 if (loc
== (locale_t
) 0)
1328 if (flags
& JSON_FORMAT_COLOR
)
1329 fputs(ANSI_HIGHLIGHT_BLUE
, f
);
1331 fprintf(f
, "%.*Le", DECIMAL_DIG
, json_variant_real(v
));
1333 if (flags
& JSON_FORMAT_COLOR
)
1334 fputs(ANSI_NORMAL
, f
);
1340 case JSON_VARIANT_INTEGER
:
1341 if (flags
& JSON_FORMAT_COLOR
)
1342 fputs(ANSI_HIGHLIGHT_BLUE
, f
);
1344 fprintf(f
, "%" PRIdMAX
, json_variant_integer(v
));
1346 if (flags
& JSON_FORMAT_COLOR
)
1347 fputs(ANSI_NORMAL
, f
);
1350 case JSON_VARIANT_UNSIGNED
:
1351 if (flags
& JSON_FORMAT_COLOR
)
1352 fputs(ANSI_HIGHLIGHT_BLUE
, f
);
1354 fprintf(f
, "%" PRIuMAX
, json_variant_unsigned(v
));
1356 if (flags
& JSON_FORMAT_COLOR
)
1357 fputs(ANSI_NORMAL
, f
);
1360 case JSON_VARIANT_BOOLEAN
:
1362 if (flags
& JSON_FORMAT_COLOR
)
1363 fputs(ANSI_HIGHLIGHT
, f
);
1365 if (json_variant_boolean(v
))
1370 if (flags
& JSON_FORMAT_COLOR
)
1371 fputs(ANSI_NORMAL
, f
);
1375 case JSON_VARIANT_NULL
:
1376 if (flags
& JSON_FORMAT_COLOR
)
1377 fputs(ANSI_HIGHLIGHT
, f
);
1381 if (flags
& JSON_FORMAT_COLOR
)
1382 fputs(ANSI_NORMAL
, f
);
1385 case JSON_VARIANT_STRING
: {
1390 if (flags
& JSON_FORMAT_COLOR
)
1391 fputs(ANSI_GREEN
, f
);
1393 for (q
= json_variant_string(v
); *q
; q
++) {
1426 if ((signed char) *q
>= 0 && *q
< ' ')
1427 fprintf(f
, "\\u%04x", *q
);
1434 if (flags
& JSON_FORMAT_COLOR
)
1435 fputs(ANSI_NORMAL
, f
);
1441 case JSON_VARIANT_ARRAY
: {
1444 n
= json_variant_elements(v
);
1449 _cleanup_free_
char *joined
= NULL
;
1450 const char *prefix2
;
1452 if (flags
& JSON_FORMAT_PRETTY
) {
1453 joined
= strjoin(strempty(prefix
), "\t");
1460 prefix2
= strempty(prefix
);
1464 for (i
= 0; i
< n
; i
++) {
1467 assert_se(e
= json_variant_by_index(v
, i
));
1470 if (flags
& JSON_FORMAT_PRETTY
)
1476 if (flags
& JSON_FORMAT_PRETTY
) {
1477 print_source(f
, e
, flags
, false);
1481 r
= json_format(f
, e
, flags
, prefix2
);
1486 if (flags
& JSON_FORMAT_PRETTY
) {
1488 print_source(f
, v
, flags
, true);
1489 fputs(strempty(prefix
), f
);
1497 case JSON_VARIANT_OBJECT
: {
1500 n
= json_variant_elements(v
);
1505 _cleanup_free_
char *joined
= NULL
;
1506 const char *prefix2
;
1508 if (flags
& JSON_FORMAT_PRETTY
) {
1509 joined
= strjoin(strempty(prefix
), "\t");
1516 prefix2
= strempty(prefix
);
1520 for (i
= 0; i
< n
; i
+= 2) {
1523 e
= json_variant_by_index(v
, i
);
1526 if (flags
& JSON_FORMAT_PRETTY
)
1532 if (flags
& JSON_FORMAT_PRETTY
) {
1533 print_source(f
, e
, flags
, false);
1537 r
= json_format(f
, e
, flags
, prefix2
);
1541 fputs(flags
& JSON_FORMAT_PRETTY
? " : " : ":", f
);
1543 r
= json_format(f
, json_variant_by_index(v
, i
+1), flags
, prefix2
);
1548 if (flags
& JSON_FORMAT_PRETTY
) {
1550 print_source(f
, v
, flags
, true);
1551 fputs(strempty(prefix
), f
);
1560 assert_not_reached("Unexpected variant type.");
1566 int json_variant_format(JsonVariant
*v
, JsonFormatFlags flags
, char **ret
) {
1567 _cleanup_free_
char *s
= NULL
;
1571 /* Returns the length of the generated string (without the terminating NUL),
1572 * or negative on error. */
1574 assert_return(v
, -EINVAL
);
1575 assert_return(ret
, -EINVAL
);
1578 _cleanup_fclose_
FILE *f
= NULL
;
1580 f
= open_memstream_unlocked(&s
, &sz
);
1584 json_variant_dump(v
, flags
, f
, NULL
);
1586 /* Add terminating 0, so that the output buffer is a valid string. */
1589 r
= fflush_and_check(f
);
1597 return (int) sz
- 1;
1600 void json_variant_dump(JsonVariant
*v
, JsonFormatFlags flags
, FILE *f
, const char *prefix
) {
1607 print_source(f
, v
, flags
, false);
1609 if (((flags
& (JSON_FORMAT_COLOR_AUTO
|JSON_FORMAT_COLOR
)) == JSON_FORMAT_COLOR_AUTO
) && colors_enabled())
1610 flags
|= JSON_FORMAT_COLOR
;
1612 if (flags
& JSON_FORMAT_SSE
)
1614 if (flags
& JSON_FORMAT_SEQ
)
1615 fputc('\x1e', f
); /* ASCII Record Separator */
1617 json_format(f
, v
, flags
, prefix
);
1619 if (flags
& (JSON_FORMAT_PRETTY
|JSON_FORMAT_SEQ
|JSON_FORMAT_SSE
|JSON_FORMAT_NEWLINE
))
1621 if (flags
& JSON_FORMAT_SSE
)
1622 fputc('\n', f
); /* In case of SSE add a second newline */
1625 int json_variant_filter(JsonVariant
**v
, char **to_remove
) {
1626 _cleanup_(json_variant_unrefp
) JsonVariant
*w
= NULL
;
1627 _cleanup_free_ JsonVariant
**array
= NULL
;
1628 size_t i
, n
= 0, k
= 0;
1633 if (json_variant_is_blank_object(*v
))
1635 if (!json_variant_is_object(*v
))
1638 if (strv_isempty(to_remove
))
1641 for (i
= 0; i
< json_variant_elements(*v
); i
+= 2) {
1644 p
= json_variant_by_index(*v
, i
);
1645 if (!json_variant_has_type(p
, JSON_VARIANT_STRING
))
1648 if (strv_contains(to_remove
, json_variant_string(p
))) {
1650 array
= new(JsonVariant
*, json_variant_elements(*v
) - 2);
1654 for (k
= 0; k
< i
; k
++)
1655 array
[k
] = json_variant_by_index(*v
, k
);
1661 array
[k
++] = json_variant_by_index(*v
, i
+ 1);
1668 r
= json_variant_new_object(&w
, array
, k
);
1672 json_variant_unref(*v
);
1678 static int json_variant_copy(JsonVariant
**nv
, JsonVariant
*v
) {
1688 /* Let's copy the simple types literally, and the larger types by references */
1689 t
= json_variant_type(v
);
1691 case JSON_VARIANT_INTEGER
:
1692 k
= sizeof(intmax_t);
1693 value
.integer
= json_variant_integer(v
);
1697 case JSON_VARIANT_UNSIGNED
:
1698 k
= sizeof(uintmax_t);
1699 value
.unsig
= json_variant_unsigned(v
);
1703 case JSON_VARIANT_REAL
:
1704 k
= sizeof(long double);
1705 value
.real
= json_variant_real(v
);
1709 case JSON_VARIANT_BOOLEAN
:
1711 value
.boolean
= json_variant_boolean(v
);
1715 case JSON_VARIANT_NULL
:
1720 case JSON_VARIANT_STRING
:
1721 source
= json_variant_string(v
);
1722 k
= strnlen(source
, INLINE_STRING_MAX
+ 1);
1723 if (k
<= INLINE_STRING_MAX
) {
1731 /* Everything else copy by reference */
1733 c
= malloc0(MAX(sizeof(JsonVariant
),
1734 offsetof(JsonVariant
, reference
) + sizeof(JsonVariant
*)));
1740 c
->is_reference
= true;
1741 c
->reference
= json_variant_ref(json_variant_normalize(v
));
1747 c
= malloc0(MAX(sizeof(JsonVariant
),
1748 offsetof(JsonVariant
, value
) + k
));
1755 memcpy_safe(&c
->value
, source
, k
);
1761 static bool json_single_ref(JsonVariant
*v
) {
1763 /* Checks whether the caller is the single owner of the object, i.e. can get away with changing it */
1765 if (!json_variant_is_regular(v
))
1769 return json_single_ref(v
->parent
);
1771 assert(v
->n_ref
> 0);
1772 return v
->n_ref
== 1;
1775 static int json_variant_set_source(JsonVariant
**v
, JsonSource
*source
, unsigned line
, unsigned column
) {
1781 /* Patch in source and line/column number. Tries to do this in-place if the caller is the sole referencer of
1782 * the object. If not, allocates a new object, possibly a surrogate for the original one */
1787 if (source
&& line
> source
->max_line
)
1788 source
->max_line
= line
;
1789 if (source
&& column
> source
->max_column
)
1790 source
->max_column
= column
;
1792 if (!json_variant_is_regular(*v
)) {
1794 if (!source
&& line
== 0 && column
== 0)
1798 if (json_source_equal((*v
)->source
, source
) &&
1799 (*v
)->line
== line
&&
1800 (*v
)->column
== column
)
1803 if (json_single_ref(*v
)) { /* Sole reference? */
1804 json_source_unref((*v
)->source
);
1805 (*v
)->source
= json_source_ref(source
);
1807 (*v
)->column
= column
;
1812 r
= json_variant_copy(&w
, *v
);
1816 assert(json_variant_is_regular(w
));
1817 assert(!w
->is_embedded
);
1818 assert(w
->n_ref
== 1);
1821 w
->source
= json_source_ref(source
);
1825 json_variant_unref(*v
);
1831 static void inc_lines_columns(unsigned *line
, unsigned *column
, const char *s
, size_t n
) {
1834 assert(s
|| n
== 0);
1840 } else if ((signed char) *s
>= 0 && *s
< 127) /* Process ASCII chars quickly */
1845 w
= utf8_encoded_valid_unichar(s
, n
);
1846 if (w
< 0) /* count invalid unichars as normal characters */
1848 else if ((size_t) w
> n
) /* never read more than the specified number of characters */
1863 static int unhex_ucs2(const char *c
, uint16_t *ret
) {
1870 aa
= unhexchar(c
[0]);
1874 bb
= unhexchar(c
[1]);
1878 cc
= unhexchar(c
[2]);
1882 dd
= unhexchar(c
[3]);
1886 x
= ((uint16_t) aa
<< 12) |
1887 ((uint16_t) bb
<< 8) |
1888 ((uint16_t) cc
<< 4) |
1899 static int json_parse_string(const char **p
, char **ret
) {
1900 _cleanup_free_
char *s
= NULL
;
1901 size_t n
= 0, allocated
= 0;
1922 /* Check for control characters 0x00..0x1f */
1923 if (*c
> 0 && *c
< ' ')
1926 /* Check for control character 0x7f */
1941 return JSON_TOKEN_STRING
;
1951 if (IN_SET(*c
, '"', '\\', '/'))
1963 else if (*c
== 'u') {
1967 r
= unhex_ucs2(c
+ 1, &x
);
1973 if (!GREEDY_REALLOC(s
, allocated
, n
+ 5))
1976 if (!utf16_is_surrogate(x
))
1977 n
+= utf8_encode_unichar(s
+ n
, (char32_t
) x
);
1978 else if (utf16_is_trailing_surrogate(x
))
1983 if (c
[0] != '\\' || c
[1] != 'u')
1986 r
= unhex_ucs2(c
+ 2, &y
);
1992 if (!utf16_is_trailing_surrogate(y
))
1995 n
+= utf8_encode_unichar(s
+ n
, utf16_surrogate_pair_to_unichar(x
, y
));
2002 if (!GREEDY_REALLOC(s
, allocated
, n
+ 2))
2010 len
= utf8_encoded_valid_unichar(c
, (size_t) -1);
2014 if (!GREEDY_REALLOC(s
, allocated
, n
+ len
+ 1))
2017 memcpy(s
+ n
, c
, len
);
2023 static int json_parse_number(const char **p
, JsonValue
*ret
) {
2024 bool negative
= false, exponent_negative
= false, is_real
= false;
2025 long double x
= 0.0, y
= 0.0, exponent
= 0.0, shift
= 1.0;
2044 if (!strchr("123456789", *c
) || *c
== 0)
2051 if (i
< INTMAX_MIN
/ 10) /* overflow */
2054 intmax_t t
= 10 * i
;
2056 if (t
< INTMAX_MIN
+ (*c
- '0')) /* overflow */
2062 if (u
> UINTMAX_MAX
/ 10) /* overflow */
2065 uintmax_t t
= 10 * u
;
2067 if (t
> UINTMAX_MAX
- (*c
- '0')) /* overflow */
2075 x
= 10.0 * x
+ (*c
- '0');
2078 } while (strchr("0123456789", *c
) && *c
!= 0);
2085 if (!strchr("0123456789", *c
) || *c
== 0)
2089 y
= 10.0 * y
+ (*c
- '0');
2090 shift
= 10.0 * shift
;
2092 } while (strchr("0123456789", *c
) && *c
!= 0);
2095 if (IN_SET(*c
, 'e', 'E')) {
2100 exponent_negative
= true;
2102 } else if (*c
== '+')
2105 if (!strchr("0123456789", *c
) || *c
== 0)
2109 exponent
= 10.0 * exponent
+ (*c
- '0');
2111 } while (strchr("0123456789", *c
) && *c
!= 0);
2117 ret
->real
= ((negative
? -1.0 : 1.0) * (x
+ (y
/ shift
))) * exp10l((exponent_negative
? -1.0 : 1.0) * exponent
);
2118 return JSON_TOKEN_REAL
;
2119 } else if (negative
) {
2121 return JSON_TOKEN_INTEGER
;
2124 return JSON_TOKEN_UNSIGNED
;
2131 JsonValue
*ret_value
,
2132 unsigned *ret_line
, /* 'ret_line' returns the line at the beginning of this token */
2133 unsigned *ret_column
,
2135 unsigned *line
, /* 'line' is used as a line state, it always reflect the line we are at after the token was read */
2138 unsigned start_line
, start_column
;
2139 const char *start
, *c
;
2159 t
= PTR_TO_INT(*state
);
2160 if (t
== STATE_NULL
) {
2166 /* Skip over the whitespace */
2167 n
= strspn(*p
, WHITESPACE
);
2168 inc_lines_columns(line
, column
, *p
, n
);
2171 /* Remember where we started processing this token */
2174 start_column
= *column
;
2178 *ret_value
= JSON_VALUE_NULL
;
2189 *state
= INT_TO_PTR(STATE_VALUE
);
2190 r
= JSON_TOKEN_OBJECT_OPEN
;
2193 } else if (*c
== '}') {
2195 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2196 r
= JSON_TOKEN_OBJECT_CLOSE
;
2199 } else if (*c
== '[') {
2201 *state
= INT_TO_PTR(STATE_VALUE
);
2202 r
= JSON_TOKEN_ARRAY_OPEN
;
2205 } else if (*c
== ']') {
2207 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2208 r
= JSON_TOKEN_ARRAY_CLOSE
;
2211 } else if (*c
== '"') {
2213 r
= json_parse_string(&c
, ret_string
);
2217 *ret_value
= JSON_VALUE_NULL
;
2218 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2221 } else if (strchr("-0123456789", *c
)) {
2223 r
= json_parse_number(&c
, ret_value
);
2228 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2231 } else if (startswith(c
, "true")) {
2233 ret_value
->boolean
= true;
2235 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2236 r
= JSON_TOKEN_BOOLEAN
;
2239 } else if (startswith(c
, "false")) {
2241 ret_value
->boolean
= false;
2243 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2244 r
= JSON_TOKEN_BOOLEAN
;
2247 } else if (startswith(c
, "null")) {
2249 *ret_value
= JSON_VALUE_NULL
;
2251 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2252 r
= JSON_TOKEN_NULL
;
2259 case STATE_VALUE_POST
:
2263 *state
= INT_TO_PTR(STATE_VALUE
);
2264 r
= JSON_TOKEN_COLON
;
2267 } else if (*c
== ',') {
2269 *state
= INT_TO_PTR(STATE_VALUE
);
2270 r
= JSON_TOKEN_COMMA
;
2273 } else if (*c
== '}') {
2275 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2276 r
= JSON_TOKEN_OBJECT_CLOSE
;
2279 } else if (*c
== ']') {
2281 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2282 r
= JSON_TOKEN_ARRAY_CLOSE
;
2289 assert_not_reached("Unexpected tokenizer state");
2294 *ret_value
= JSON_VALUE_NULL
;
2297 inc_lines_columns(line
, column
, start
, c
- start
);
2300 *ret_line
= start_line
;
2301 *ret_column
= start_column
;
2306 typedef enum JsonExpect
{
2307 /* The following values are used by json_parse() */
2310 EXPECT_OBJECT_FIRST_KEY
,
2311 EXPECT_OBJECT_NEXT_KEY
,
2312 EXPECT_OBJECT_COLON
,
2313 EXPECT_OBJECT_VALUE
,
2314 EXPECT_OBJECT_COMMA
,
2315 EXPECT_ARRAY_FIRST_ELEMENT
,
2316 EXPECT_ARRAY_NEXT_ELEMENT
,
2319 /* And these are used by json_build() */
2320 EXPECT_ARRAY_ELEMENT
,
2324 typedef struct JsonStack
{
2326 JsonVariant
**elements
;
2327 size_t n_elements
, n_elements_allocated
;
2328 unsigned line_before
;
2329 unsigned column_before
;
2330 size_t n_suppress
; /* When building: if > 0, suppress this many subsequent elements. If == (size_t) -1, suppress all subsequent elements */
2333 static void json_stack_release(JsonStack
*s
) {
2336 json_variant_unref_many(s
->elements
, s
->n_elements
);
2337 s
->elements
= mfree(s
->elements
);
2340 static int json_parse_internal(
2346 bool continue_end
) {
2348 size_t n_stack
= 1, n_stack_allocated
= 0, i
;
2349 unsigned line_buffer
= 0, column_buffer
= 0;
2350 void *tokenizer_state
= NULL
;
2351 JsonStack
*stack
= NULL
;
2355 assert_return(input
, -EINVAL
);
2356 assert_return(ret
, -EINVAL
);
2360 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
))
2363 stack
[0] = (JsonStack
) {
2364 .expect
= EXPECT_TOPLEVEL
,
2368 line
= &line_buffer
;
2370 column
= &column_buffer
;
2373 _cleanup_(json_variant_unrefp
) JsonVariant
*add
= NULL
;
2374 _cleanup_free_
char *string
= NULL
;
2375 unsigned line_token
, column_token
;
2380 assert(n_stack
> 0);
2381 current
= stack
+ n_stack
- 1;
2383 if (continue_end
&& current
->expect
== EXPECT_END
)
2386 token
= json_tokenize(&p
, &string
, &value
, &line_token
, &column_token
, &tokenizer_state
, line
, column
);
2394 case JSON_TOKEN_END
:
2395 if (current
->expect
!= EXPECT_END
) {
2400 assert(current
->n_elements
== 1);
2401 assert(n_stack
== 1);
2404 case JSON_TOKEN_COLON
:
2406 if (current
->expect
!= EXPECT_OBJECT_COLON
) {
2411 current
->expect
= EXPECT_OBJECT_VALUE
;
2414 case JSON_TOKEN_COMMA
:
2416 if (current
->expect
== EXPECT_OBJECT_COMMA
)
2417 current
->expect
= EXPECT_OBJECT_NEXT_KEY
;
2418 else if (current
->expect
== EXPECT_ARRAY_COMMA
)
2419 current
->expect
= EXPECT_ARRAY_NEXT_ELEMENT
;
2427 case JSON_TOKEN_OBJECT_OPEN
:
2429 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2434 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
2438 current
= stack
+ n_stack
- 1;
2440 /* Prepare the expect for when we return from the child */
2441 if (current
->expect
== EXPECT_TOPLEVEL
)
2442 current
->expect
= EXPECT_END
;
2443 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2444 current
->expect
= EXPECT_OBJECT_COMMA
;
2446 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2447 current
->expect
= EXPECT_ARRAY_COMMA
;
2450 stack
[n_stack
++] = (JsonStack
) {
2451 .expect
= EXPECT_OBJECT_FIRST_KEY
,
2452 .line_before
= line_token
,
2453 .column_before
= column_token
,
2456 current
= stack
+ n_stack
- 1;
2459 case JSON_TOKEN_OBJECT_CLOSE
:
2460 if (!IN_SET(current
->expect
, EXPECT_OBJECT_FIRST_KEY
, EXPECT_OBJECT_COMMA
)) {
2465 assert(n_stack
> 1);
2467 r
= json_variant_new_object(&add
, current
->elements
, current
->n_elements
);
2471 line_token
= current
->line_before
;
2472 column_token
= current
->column_before
;
2474 json_stack_release(current
);
2475 n_stack
--, current
--;
2479 case JSON_TOKEN_ARRAY_OPEN
:
2480 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2485 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
2489 current
= stack
+ n_stack
- 1;
2491 /* Prepare the expect for when we return from the child */
2492 if (current
->expect
== EXPECT_TOPLEVEL
)
2493 current
->expect
= EXPECT_END
;
2494 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2495 current
->expect
= EXPECT_OBJECT_COMMA
;
2497 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2498 current
->expect
= EXPECT_ARRAY_COMMA
;
2501 stack
[n_stack
++] = (JsonStack
) {
2502 .expect
= EXPECT_ARRAY_FIRST_ELEMENT
,
2503 .line_before
= line_token
,
2504 .column_before
= column_token
,
2509 case JSON_TOKEN_ARRAY_CLOSE
:
2510 if (!IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_COMMA
)) {
2515 assert(n_stack
> 1);
2517 r
= json_variant_new_array(&add
, current
->elements
, current
->n_elements
);
2521 line_token
= current
->line_before
;
2522 column_token
= current
->column_before
;
2524 json_stack_release(current
);
2525 n_stack
--, current
--;
2528 case JSON_TOKEN_STRING
:
2529 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
)) {
2534 r
= json_variant_new_string(&add
, string
);
2538 if (current
->expect
== EXPECT_TOPLEVEL
)
2539 current
->expect
= EXPECT_END
;
2540 else if (IN_SET(current
->expect
, EXPECT_OBJECT_FIRST_KEY
, EXPECT_OBJECT_NEXT_KEY
))
2541 current
->expect
= EXPECT_OBJECT_COLON
;
2542 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2543 current
->expect
= EXPECT_OBJECT_COMMA
;
2545 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2546 current
->expect
= EXPECT_ARRAY_COMMA
;
2551 case JSON_TOKEN_REAL
:
2552 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2557 r
= json_variant_new_real(&add
, value
.real
);
2561 if (current
->expect
== EXPECT_TOPLEVEL
)
2562 current
->expect
= EXPECT_END
;
2563 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2564 current
->expect
= EXPECT_OBJECT_COMMA
;
2566 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2567 current
->expect
= EXPECT_ARRAY_COMMA
;
2572 case JSON_TOKEN_INTEGER
:
2573 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2578 r
= json_variant_new_integer(&add
, value
.integer
);
2582 if (current
->expect
== EXPECT_TOPLEVEL
)
2583 current
->expect
= EXPECT_END
;
2584 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2585 current
->expect
= EXPECT_OBJECT_COMMA
;
2587 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2588 current
->expect
= EXPECT_ARRAY_COMMA
;
2593 case JSON_TOKEN_UNSIGNED
:
2594 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2599 r
= json_variant_new_unsigned(&add
, value
.unsig
);
2603 if (current
->expect
== EXPECT_TOPLEVEL
)
2604 current
->expect
= EXPECT_END
;
2605 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2606 current
->expect
= EXPECT_OBJECT_COMMA
;
2608 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2609 current
->expect
= EXPECT_ARRAY_COMMA
;
2614 case JSON_TOKEN_BOOLEAN
:
2615 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2620 r
= json_variant_new_boolean(&add
, value
.boolean
);
2624 if (current
->expect
== EXPECT_TOPLEVEL
)
2625 current
->expect
= EXPECT_END
;
2626 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2627 current
->expect
= EXPECT_OBJECT_COMMA
;
2629 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2630 current
->expect
= EXPECT_ARRAY_COMMA
;
2635 case JSON_TOKEN_NULL
:
2636 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2641 r
= json_variant_new_null(&add
);
2645 if (current
->expect
== EXPECT_TOPLEVEL
)
2646 current
->expect
= EXPECT_END
;
2647 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2648 current
->expect
= EXPECT_OBJECT_COMMA
;
2650 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2651 current
->expect
= EXPECT_ARRAY_COMMA
;
2657 assert_not_reached("Unexpected token");
2661 (void) json_variant_set_source(&add
, source
, line_token
, column_token
);
2663 if (!GREEDY_REALLOC(current
->elements
, current
->n_elements_allocated
, current
->n_elements
+ 1)) {
2668 current
->elements
[current
->n_elements
++] = TAKE_PTR(add
);
2673 assert(n_stack
== 1);
2674 assert(stack
[0].n_elements
== 1);
2676 *ret
= json_variant_ref(stack
[0].elements
[0]);
2681 for (i
= 0; i
< n_stack
; i
++)
2682 json_stack_release(stack
+ i
);
2689 int json_parse(const char *input
, JsonVariant
**ret
, unsigned *ret_line
, unsigned *ret_column
) {
2690 return json_parse_internal(&input
, NULL
, ret
, ret_line
, ret_column
, false);
2693 int json_parse_continue(const char **p
, JsonVariant
**ret
, unsigned *ret_line
, unsigned *ret_column
) {
2694 return json_parse_internal(p
, NULL
, ret
, ret_line
, ret_column
, true);
2697 int json_parse_file(FILE *f
, const char *path
, JsonVariant
**ret
, unsigned *ret_line
, unsigned *ret_column
) {
2698 _cleanup_(json_source_unrefp
) JsonSource
*source
= NULL
;
2699 _cleanup_free_
char *text
= NULL
;
2704 r
= read_full_stream(f
, &text
, NULL
);
2706 r
= read_full_file(path
, &text
, NULL
);
2713 source
= json_source_new(path
);
2719 return json_parse_internal(&p
, source
, ret
, ret_line
, ret_column
, false);
2722 int json_buildv(JsonVariant
**ret
, va_list ap
) {
2723 JsonStack
*stack
= NULL
;
2724 size_t n_stack
= 1, n_stack_allocated
= 0, i
;
2727 assert_return(ret
, -EINVAL
);
2729 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
))
2732 stack
[0] = (JsonStack
) {
2733 .expect
= EXPECT_TOPLEVEL
,
2737 _cleanup_(json_variant_unrefp
) JsonVariant
*add
= NULL
;
2738 size_t n_subtract
= 0; /* how much to subtract from current->n_suppress, i.e. how many elements would
2739 * have been added to the current variant */
2743 assert(n_stack
> 0);
2744 current
= stack
+ n_stack
- 1;
2746 if (current
->expect
== EXPECT_END
)
2749 command
= va_arg(ap
, int);
2753 case _JSON_BUILD_STRING
: {
2756 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2761 p
= va_arg(ap
, const char *);
2763 if (current
->n_suppress
== 0) {
2764 r
= json_variant_new_string(&add
, p
);
2771 if (current
->expect
== EXPECT_TOPLEVEL
)
2772 current
->expect
= EXPECT_END
;
2773 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2774 current
->expect
= EXPECT_OBJECT_KEY
;
2776 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2781 case _JSON_BUILD_INTEGER
: {
2784 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2789 j
= va_arg(ap
, intmax_t);
2791 if (current
->n_suppress
== 0) {
2792 r
= json_variant_new_integer(&add
, j
);
2799 if (current
->expect
== EXPECT_TOPLEVEL
)
2800 current
->expect
= EXPECT_END
;
2801 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2802 current
->expect
= EXPECT_OBJECT_KEY
;
2804 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2809 case _JSON_BUILD_UNSIGNED
: {
2812 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2817 j
= va_arg(ap
, uintmax_t);
2819 if (current
->n_suppress
== 0) {
2820 r
= json_variant_new_unsigned(&add
, j
);
2827 if (current
->expect
== EXPECT_TOPLEVEL
)
2828 current
->expect
= EXPECT_END
;
2829 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2830 current
->expect
= EXPECT_OBJECT_KEY
;
2832 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2837 case _JSON_BUILD_REAL
: {
2840 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2845 d
= va_arg(ap
, long double);
2847 if (current
->n_suppress
== 0) {
2848 r
= json_variant_new_real(&add
, d
);
2855 if (current
->expect
== EXPECT_TOPLEVEL
)
2856 current
->expect
= EXPECT_END
;
2857 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2858 current
->expect
= EXPECT_OBJECT_KEY
;
2860 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2865 case _JSON_BUILD_BOOLEAN
: {
2868 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2873 b
= va_arg(ap
, int);
2875 if (current
->n_suppress
== 0) {
2876 r
= json_variant_new_boolean(&add
, b
);
2883 if (current
->expect
== EXPECT_TOPLEVEL
)
2884 current
->expect
= EXPECT_END
;
2885 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2886 current
->expect
= EXPECT_OBJECT_KEY
;
2888 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2893 case _JSON_BUILD_NULL
:
2895 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2900 if (current
->n_suppress
== 0) {
2901 r
= json_variant_new_null(&add
);
2908 if (current
->expect
== EXPECT_TOPLEVEL
)
2909 current
->expect
= EXPECT_END
;
2910 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2911 current
->expect
= EXPECT_OBJECT_KEY
;
2913 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2917 case _JSON_BUILD_VARIANT
:
2919 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2924 /* Note that we don't care for current->n_suppress here, after all the variant is already
2925 * allocated anyway... */
2926 add
= va_arg(ap
, JsonVariant
*);
2928 add
= JSON_VARIANT_MAGIC_NULL
;
2930 json_variant_ref(add
);
2934 if (current
->expect
== EXPECT_TOPLEVEL
)
2935 current
->expect
= EXPECT_END
;
2936 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2937 current
->expect
= EXPECT_OBJECT_KEY
;
2939 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2943 case _JSON_BUILD_LITERAL
: {
2946 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2951 l
= va_arg(ap
, const char *);
2954 /* Note that we don't care for current->n_suppress here, we should generate parsing
2955 * errors even in suppressed object properties */
2957 r
= json_parse(l
, &add
, NULL
, NULL
);
2961 add
= JSON_VARIANT_MAGIC_NULL
;
2965 if (current
->expect
== EXPECT_TOPLEVEL
)
2966 current
->expect
= EXPECT_END
;
2967 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2968 current
->expect
= EXPECT_OBJECT_KEY
;
2970 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2975 case _JSON_BUILD_ARRAY_BEGIN
:
2977 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
2982 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
2986 current
= stack
+ n_stack
- 1;
2988 if (current
->expect
== EXPECT_TOPLEVEL
)
2989 current
->expect
= EXPECT_END
;
2990 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2991 current
->expect
= EXPECT_OBJECT_KEY
;
2993 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
2995 stack
[n_stack
++] = (JsonStack
) {
2996 .expect
= EXPECT_ARRAY_ELEMENT
,
2997 .n_suppress
= current
->n_suppress
!= 0 ? (size_t) -1 : 0, /* if we shall suppress the
2998 * new array, then we should
2999 * also suppress all array
3005 case _JSON_BUILD_ARRAY_END
:
3006 if (current
->expect
!= EXPECT_ARRAY_ELEMENT
) {
3011 assert(n_stack
> 1);
3013 if (current
->n_suppress
== 0) {
3014 r
= json_variant_new_array(&add
, current
->elements
, current
->n_elements
);
3021 json_stack_release(current
);
3022 n_stack
--, current
--;
3026 case _JSON_BUILD_STRV
: {
3029 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3034 l
= va_arg(ap
, char **);
3036 if (current
->n_suppress
== 0) {
3037 r
= json_variant_new_array_strv(&add
, l
);
3044 if (current
->expect
== EXPECT_TOPLEVEL
)
3045 current
->expect
= EXPECT_END
;
3046 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3047 current
->expect
= EXPECT_OBJECT_KEY
;
3049 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3054 case _JSON_BUILD_OBJECT_BEGIN
:
3056 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3061 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
3065 current
= stack
+ n_stack
- 1;
3067 if (current
->expect
== EXPECT_TOPLEVEL
)
3068 current
->expect
= EXPECT_END
;
3069 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3070 current
->expect
= EXPECT_OBJECT_KEY
;
3072 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3074 stack
[n_stack
++] = (JsonStack
) {
3075 .expect
= EXPECT_OBJECT_KEY
,
3076 .n_suppress
= current
->n_suppress
!= 0 ? (size_t) -1 : 0, /* if we shall suppress the
3077 * new object, then we should
3078 * also suppress all object
3084 case _JSON_BUILD_OBJECT_END
:
3086 if (current
->expect
!= EXPECT_OBJECT_KEY
) {
3091 assert(n_stack
> 1);
3093 if (current
->n_suppress
== 0) {
3094 r
= json_variant_new_object(&add
, current
->elements
, current
->n_elements
);
3101 json_stack_release(current
);
3102 n_stack
--, current
--;
3106 case _JSON_BUILD_PAIR
: {
3109 if (current
->expect
!= EXPECT_OBJECT_KEY
) {
3114 n
= va_arg(ap
, const char *);
3116 if (current
->n_suppress
== 0) {
3117 r
= json_variant_new_string(&add
, n
);
3124 current
->expect
= EXPECT_OBJECT_VALUE
;
3128 case _JSON_BUILD_PAIR_CONDITION
: {
3132 if (current
->expect
!= EXPECT_OBJECT_KEY
) {
3137 b
= va_arg(ap
, int);
3138 n
= va_arg(ap
, const char *);
3140 if (b
&& current
->n_suppress
== 0) {
3141 r
= json_variant_new_string(&add
, n
);
3146 n_subtract
= 1; /* we generated one item */
3148 if (!b
&& current
->n_suppress
!= (size_t) -1)
3149 current
->n_suppress
+= 2; /* Suppress this one and the next item */
3151 current
->expect
= EXPECT_OBJECT_VALUE
;
3155 /* If a variant was generated, add it to our current variant, but only if we are not supposed to suppress additions */
3156 if (add
&& current
->n_suppress
== 0) {
3157 if (!GREEDY_REALLOC(current
->elements
, current
->n_elements_allocated
, current
->n_elements
+ 1)) {
3162 current
->elements
[current
->n_elements
++] = TAKE_PTR(add
);
3165 /* If we are supposed to suppress items, let's subtract how many items where generated from that
3166 * counter. Except if the counter is (size_t) -1, i.e. we shall suppress an infinite number of elements
3167 * on this stack level */
3168 if (current
->n_suppress
!= (size_t) -1) {
3169 if (current
->n_suppress
<= n_subtract
) /* Saturated */
3170 current
->n_suppress
= 0;
3172 current
->n_suppress
-= n_subtract
;
3177 assert(n_stack
== 1);
3178 assert(stack
[0].n_elements
== 1);
3180 *ret
= json_variant_ref(stack
[0].elements
[0]);
3184 for (i
= 0; i
< n_stack
; i
++)
3185 json_stack_release(stack
+ i
);
3192 int json_build(JsonVariant
**ret
, ...) {
3197 r
= json_buildv(ret
, ap
);
3203 int json_log_internal(
3204 JsonVariant
*variant
,
3210 const char *format
, ...) {
3214 unsigned source_line
, source_column
;
3215 char buffer
[LINE_MAX
];
3220 errno
= ERRNO_VALUE(error
);
3222 va_start(ap
, format
);
3223 (void) vsnprintf(buffer
, sizeof buffer
, format
, ap
);
3227 r
= json_variant_get_source(variant
, &source
, &source_line
, &source_column
);
3236 if (source
&& source_line
> 0 && source_column
> 0)
3237 return log_struct_internal(
3238 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD
, level
),
3241 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR
,
3242 "CONFIG_FILE=%s", source
,
3243 "CONFIG_LINE=%u", source_line
,
3244 "CONFIG_COLUMN=%u", source_column
,
3245 LOG_MESSAGE("%s:%u:%u: %s", source
, source_line
, source_column
, buffer
),
3248 return log_struct_internal(
3249 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD
, level
),
3252 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR
,
3253 LOG_MESSAGE("%s", buffer
),
3257 int json_dispatch(JsonVariant
*v
, const JsonDispatch table
[], JsonDispatchCallback bad
, JsonDispatchFlags flags
, void *userdata
) {
3258 const JsonDispatch
*p
;
3263 if (!json_variant_is_object(v
)) {
3264 json_log(v
, flags
, 0, "JSON variant is not an object.");
3266 if (flags
& JSON_PERMISSIVE
)
3272 for (p
= table
, m
= 0; p
->name
; p
++)
3275 found
= newa0(bool, m
);
3277 n
= json_variant_elements(v
);
3278 for (i
= 0; i
< n
; i
+= 2) {
3279 JsonVariant
*key
, *value
;
3281 assert_se(key
= json_variant_by_index(v
, i
));
3282 assert_se(value
= json_variant_by_index(v
, i
+1));
3284 for (p
= table
; p
->name
; p
++)
3285 if (p
->name
== (const char*) -1 ||
3286 streq_ptr(json_variant_string(key
), p
->name
))
3289 if (p
->name
) { /* Found a matching entry! :-) */
3290 JsonDispatchFlags merged_flags
;
3292 merged_flags
= flags
| p
->flags
;
3294 if (p
->type
!= _JSON_VARIANT_TYPE_INVALID
&&
3295 !json_variant_has_type(value
, p
->type
)) {
3297 json_log(value
, merged_flags
, 0,
3298 "Object field '%s' has wrong type %s, expected %s.", json_variant_string(key
),
3299 json_variant_type_to_string(json_variant_type(value
)), json_variant_type_to_string(p
->type
));
3301 if (merged_flags
& JSON_PERMISSIVE
)
3307 if (found
[p
-table
]) {
3308 json_log(value
, merged_flags
, 0, "Duplicate object field '%s'.", json_variant_string(key
));
3310 if (merged_flags
& JSON_PERMISSIVE
)
3316 found
[p
-table
] = true;
3319 r
= p
->callback(json_variant_string(key
), value
, merged_flags
, (uint8_t*) userdata
+ p
->offset
);
3321 if (merged_flags
& JSON_PERMISSIVE
)
3330 } else { /* Didn't find a matching entry! :-( */
3333 r
= bad(json_variant_string(key
), value
, flags
, userdata
);
3335 if (flags
& JSON_PERMISSIVE
)
3343 json_log(value
, flags
, 0, "Unexpected object field '%s'.", json_variant_string(key
));
3345 if (flags
& JSON_PERMISSIVE
)
3348 return -EADDRNOTAVAIL
;
3353 for (p
= table
; p
->name
; p
++) {
3354 JsonDispatchFlags merged_flags
= p
->flags
| flags
;
3356 if ((merged_flags
& JSON_MANDATORY
) && !found
[p
-table
]) {
3357 json_log(v
, merged_flags
, 0, "Missing object field '%s'.", p
->name
);
3359 if ((merged_flags
& JSON_PERMISSIVE
))
3369 int json_dispatch_boolean(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3375 if (!json_variant_is_boolean(variant
))
3376 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not a boolean.", strna(name
));
3378 *b
= json_variant_boolean(variant
);
3382 int json_dispatch_tristate(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3388 if (!json_variant_is_boolean(variant
))
3389 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not a boolean.", strna(name
));
3391 *b
= json_variant_boolean(variant
);
3395 int json_dispatch_integer(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3396 intmax_t *i
= userdata
;
3401 if (!json_variant_is_integer(variant
))
3402 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not an integer.", strna(name
));
3404 *i
= json_variant_integer(variant
);
3408 int json_dispatch_unsigned(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3409 uintmax_t *u
= userdata
;
3414 if (!json_variant_is_unsigned(variant
))
3415 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not an unsigned integer.", strna(name
));
3417 *u
= json_variant_unsigned(variant
);
3421 int json_dispatch_uint32(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3422 uint32_t *u
= userdata
;
3427 if (!json_variant_is_unsigned(variant
))
3428 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not an unsigned integer.", strna(name
));
3430 if (json_variant_unsigned(variant
) > UINT32_MAX
)
3431 return json_log(variant
, flags
, SYNTHETIC_ERRNO(ERANGE
), "JSON field '%s' out of bounds.", strna(name
));
3433 *u
= (uint32_t) json_variant_unsigned(variant
);
3437 int json_dispatch_int32(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3438 int32_t *i
= userdata
;
3443 if (!json_variant_is_integer(variant
))
3444 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not an integer.", strna(name
));
3446 if (json_variant_integer(variant
) < INT32_MIN
|| json_variant_integer(variant
) > INT32_MAX
)
3447 return json_log(variant
, flags
, SYNTHETIC_ERRNO(ERANGE
), "JSON field '%s' out of bounds.", strna(name
));
3449 *i
= (int32_t) json_variant_integer(variant
);
3453 int json_dispatch_string(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3454 char **s
= userdata
;
3460 if (json_variant_is_null(variant
)) {
3465 if (!json_variant_is_string(variant
))
3466 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not a string.", strna(name
));
3468 r
= free_and_strdup(s
, json_variant_string(variant
));
3470 return json_log(variant
, flags
, r
, "Failed to allocate string: %m");
3475 int json_dispatch_strv(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3476 _cleanup_strv_free_
char **l
= NULL
;
3477 char ***s
= userdata
;
3484 if (json_variant_is_null(variant
)) {
3489 /* Let's be flexible here: accept a single string in place of a single-item array */
3490 if (json_variant_is_string(variant
)) {
3491 l
= strv_new(json_variant_string(variant
));
3495 strv_free_and_replace(*s
, l
);
3499 if (!json_variant_is_array(variant
))
3500 return json_log(variant
, SYNTHETIC_ERRNO(EINVAL
), flags
, "JSON field '%s' is not an array.", strna(name
));
3502 JSON_VARIANT_ARRAY_FOREACH(e
, variant
) {
3503 if (!json_variant_is_string(e
))
3504 return json_log(e
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON array element is not a string.");
3506 r
= strv_extend(&l
, json_variant_string(e
));
3508 return json_log(e
, flags
, r
, "Failed to append array element: %m");
3511 strv_free_and_replace(*s
, l
);
3515 int json_dispatch_variant(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3516 JsonVariant
**p
= userdata
;
3521 json_variant_unref(*p
);
3522 *p
= json_variant_ref(variant
);
3527 static const char* const json_variant_type_table
[_JSON_VARIANT_TYPE_MAX
] = {
3528 [JSON_VARIANT_STRING
] = "string",
3529 [JSON_VARIANT_INTEGER
] = "integer",
3530 [JSON_VARIANT_UNSIGNED
] = "unsigned",
3531 [JSON_VARIANT_REAL
] = "real",
3532 [JSON_VARIANT_NUMBER
] = "number",
3533 [JSON_VARIANT_BOOLEAN
] = "boolean",
3534 [JSON_VARIANT_ARRAY
] = "array",
3535 [JSON_VARIANT_OBJECT
] = "object",
3536 [JSON_VARIANT_NULL
] = "null",
3539 DEFINE_STRING_TABLE_LOOKUP(json_variant_type
, JsonVariantType
);