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 /* Erase from memory when freeing */
77 /* If this is an object the fields are strictly ordered by name */
80 /* If in addition to this object all objects referenced by it are also ordered strictly by name */
83 /* The current 'depth' of the JsonVariant, i.e. how many levels of member variants this has */
87 /* For simple types we store the value in-line. */
90 /* For objects and arrays we store the number of elements immediately following */
93 /* If is_reference as indicated above is set, this is where the reference object is actually stored. */
94 JsonVariant
*reference
;
96 /* Strings are placed immediately after the structure. Note that when this is a JsonVariant embedded
97 * into an array we might encode strings up to INLINE_STRING_LENGTH characters directly inside the
98 * element, while longer strings are stored as references. When this object is not embedded into an
99 * array, but stand-alone we allocate the right size for the whole structure, i.e. the array might be
100 * much larger than INLINE_STRING_LENGTH.
102 * Note that because we want to allocate arrays of the JsonVariant structure we specify [0] here,
103 * rather than the prettier []. If we wouldn't, then this char array would have undefined size, and so
104 * would the union and then the struct this is included in. And of structures with undefined size we
105 * can't allocate arrays (at least not easily). */
110 /* Inside string arrays we have a series of JasonVariant structures one after the other. In this case, strings longer
111 * than INLINE_STRING_MAX are stored as references, and all shorter ones inline. (This means — on x86-64 — strings up
112 * to 15 chars are stored within the array elements, and all others in separate allocations) */
113 #define INLINE_STRING_MAX (sizeof(JsonVariant) - offsetof(JsonVariant, string) - 1U)
115 /* Let's make sure this structure isn't increased in size accidentally. This check is only for our most relevant arch
118 assert_cc(sizeof(JsonVariant
) == 48U);
119 assert_cc(INLINE_STRING_MAX
== 15U);
122 static JsonSource
* json_source_new(const char *name
) {
127 s
= malloc(offsetof(JsonSource
, name
) + strlen(name
) + 1);
134 strcpy(s
->name
, name
);
139 DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(JsonSource
, json_source
, mfree
);
141 static bool json_source_equal(JsonSource
*a
, JsonSource
*b
) {
148 return streq(a
->name
, b
->name
);
151 DEFINE_TRIVIAL_CLEANUP_FUNC(JsonSource
*, json_source_unref
);
153 /* There are four kind of JsonVariant* pointers:
156 * 2. A 'regular' one, i.e. pointing to malloc() memory
157 * 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.
158 * 4. A 'const string' one, i.e. a pointer to a const string.
160 * The four kinds of pointers can be discerned like this:
162 * Detecting #1 is easy, just compare with NULL. Detecting #3 is similarly easy: all magic pointers are below
163 * _JSON_VARIANT_MAGIC_MAX (which is pretty low, within the first memory page, which is special on Linux and other
164 * 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,
165 * otherwise #4. This makes use of the fact that malloc() will return "maximum aligned" memory, which definitely
166 * means the pointer is even. This means we can use the uneven pointers to reference static strings, as long as we
167 * make sure that all static strings used like this are aligned to 2 (or higher), and that we mask the bit on
168 * access. The JSON_VARIANT_STRING_CONST() macro encodes strings as JsonVariant* pointers, with the bit set. */
170 static bool json_variant_is_magic(const JsonVariant
*v
) {
174 return v
< _JSON_VARIANT_MAGIC_MAX
;
177 static bool json_variant_is_const_string(const JsonVariant
*v
) {
179 if (v
< _JSON_VARIANT_MAGIC_MAX
)
182 /* A proper JsonVariant is aligned to whatever malloc() aligns things too, which is definitely not uneven. We
183 * hence use all uneven pointers as indicators for const strings. */
185 return (((uintptr_t) v
) & 1) != 0;
188 static bool json_variant_is_regular(const JsonVariant
*v
) {
190 if (v
< _JSON_VARIANT_MAGIC_MAX
)
193 return (((uintptr_t) v
) & 1) == 0;
196 static JsonVariant
*json_variant_dereference(JsonVariant
*v
) {
198 /* Recursively dereference variants that are references to other variants */
203 if (!json_variant_is_regular(v
))
206 if (!v
->is_reference
)
209 return json_variant_dereference(v
->reference
);
212 static uint16_t json_variant_depth(JsonVariant
*v
) {
214 v
= json_variant_dereference(v
);
218 if (!json_variant_is_regular(v
))
224 static JsonVariant
*json_variant_formalize(JsonVariant
*v
) {
226 /* Converts json variant pointers to their normalized form, i.e. fully dereferenced and wherever
227 * possible converted to the "magic" version if there is one */
232 v
= json_variant_dereference(v
);
234 switch (json_variant_type(v
)) {
236 case JSON_VARIANT_BOOLEAN
:
237 return json_variant_boolean(v
) ? JSON_VARIANT_MAGIC_TRUE
: JSON_VARIANT_MAGIC_FALSE
;
239 case JSON_VARIANT_NULL
:
240 return JSON_VARIANT_MAGIC_NULL
;
242 case JSON_VARIANT_INTEGER
:
243 return json_variant_integer(v
) == 0 ? JSON_VARIANT_MAGIC_ZERO_INTEGER
: v
;
245 case JSON_VARIANT_UNSIGNED
:
246 return json_variant_unsigned(v
) == 0 ? JSON_VARIANT_MAGIC_ZERO_UNSIGNED
: v
;
248 case JSON_VARIANT_REAL
:
249 #pragma GCC diagnostic push
250 #pragma GCC diagnostic ignored "-Wfloat-equal"
251 return json_variant_real(v
) == 0.0 ? JSON_VARIANT_MAGIC_ZERO_REAL
: v
;
252 #pragma GCC diagnostic pop
254 case JSON_VARIANT_STRING
:
255 return isempty(json_variant_string(v
)) ? JSON_VARIANT_MAGIC_EMPTY_STRING
: v
;
257 case JSON_VARIANT_ARRAY
:
258 return json_variant_elements(v
) == 0 ? JSON_VARIANT_MAGIC_EMPTY_ARRAY
: v
;
260 case JSON_VARIANT_OBJECT
:
261 return json_variant_elements(v
) == 0 ? JSON_VARIANT_MAGIC_EMPTY_OBJECT
: v
;
268 static JsonVariant
*json_variant_conservative_formalize(JsonVariant
*v
) {
270 /* Much like json_variant_formalize(), but won't simplify if the variant has a source/line location attached to
271 * it, in order not to lose context */
276 if (!json_variant_is_regular(v
))
279 if (v
->source
|| v
->line
> 0 || v
->column
> 0)
282 return json_variant_formalize(v
);
285 static int json_variant_new(JsonVariant
**ret
, JsonVariantType type
, size_t space
) {
288 assert_return(ret
, -EINVAL
);
290 v
= malloc0(MAX(sizeof(JsonVariant
),
291 offsetof(JsonVariant
, value
) + space
));
302 int json_variant_new_integer(JsonVariant
**ret
, intmax_t i
) {
306 assert_return(ret
, -EINVAL
);
309 *ret
= JSON_VARIANT_MAGIC_ZERO_INTEGER
;
313 r
= json_variant_new(&v
, JSON_VARIANT_INTEGER
, sizeof(i
));
317 v
->value
.integer
= i
;
323 int json_variant_new_unsigned(JsonVariant
**ret
, uintmax_t u
) {
327 assert_return(ret
, -EINVAL
);
329 *ret
= JSON_VARIANT_MAGIC_ZERO_UNSIGNED
;
333 r
= json_variant_new(&v
, JSON_VARIANT_UNSIGNED
, sizeof(u
));
343 int json_variant_new_real(JsonVariant
**ret
, long double d
) {
347 assert_return(ret
, -EINVAL
);
349 #pragma GCC diagnostic push
350 #pragma GCC diagnostic ignored "-Wfloat-equal"
352 #pragma GCC diagnostic pop
353 *ret
= JSON_VARIANT_MAGIC_ZERO_REAL
;
357 r
= json_variant_new(&v
, JSON_VARIANT_REAL
, sizeof(d
));
367 int json_variant_new_boolean(JsonVariant
**ret
, bool b
) {
368 assert_return(ret
, -EINVAL
);
371 *ret
= JSON_VARIANT_MAGIC_TRUE
;
373 *ret
= JSON_VARIANT_MAGIC_FALSE
;
378 int json_variant_new_null(JsonVariant
**ret
) {
379 assert_return(ret
, -EINVAL
);
381 *ret
= JSON_VARIANT_MAGIC_NULL
;
385 int json_variant_new_stringn(JsonVariant
**ret
, const char *s
, size_t n
) {
389 assert_return(ret
, -EINVAL
);
391 assert_return(IN_SET(n
, 0, (size_t) -1), -EINVAL
);
392 return json_variant_new_null(ret
);
394 if (n
== (size_t) -1) /* determine length automatically */
396 else if (memchr(s
, 0, n
)) /* don't allow embedded NUL, as we can't express that in JSON */
399 *ret
= JSON_VARIANT_MAGIC_EMPTY_STRING
;
403 r
= json_variant_new(&v
, JSON_VARIANT_STRING
, n
+ 1);
407 memcpy(v
->string
, s
, n
);
414 int json_variant_new_base64(JsonVariant
**ret
, const void *p
, size_t n
) {
415 _cleanup_free_
char *s
= NULL
;
418 assert_return(ret
, -EINVAL
);
419 assert_return(n
== 0 || p
, -EINVAL
);
421 k
= base64mem(p
, n
, &s
);
425 return json_variant_new_stringn(ret
, s
, k
);
428 static void json_variant_set(JsonVariant
*a
, JsonVariant
*b
) {
431 b
= json_variant_dereference(b
);
433 a
->type
= JSON_VARIANT_NULL
;
437 a
->type
= json_variant_type(b
);
440 case JSON_VARIANT_INTEGER
:
441 a
->value
.integer
= json_variant_integer(b
);
444 case JSON_VARIANT_UNSIGNED
:
445 a
->value
.unsig
= json_variant_unsigned(b
);
448 case JSON_VARIANT_REAL
:
449 a
->value
.real
= json_variant_real(b
);
452 case JSON_VARIANT_BOOLEAN
:
453 a
->value
.boolean
= json_variant_boolean(b
);
456 case JSON_VARIANT_STRING
: {
459 assert_se(s
= json_variant_string(b
));
461 /* Short strings we can store inline */
462 if (strnlen(s
, INLINE_STRING_MAX
+1) <= INLINE_STRING_MAX
) {
463 strcpy(a
->string
, s
);
467 /* For longer strings, use a reference… */
471 case JSON_VARIANT_ARRAY
:
472 case JSON_VARIANT_OBJECT
:
473 a
->is_reference
= true;
474 a
->reference
= json_variant_ref(json_variant_conservative_formalize(b
));
477 case JSON_VARIANT_NULL
:
481 assert_not_reached("Unexpected variant type");
485 static void json_variant_copy_source(JsonVariant
*v
, JsonVariant
*from
) {
489 if (!json_variant_is_regular(from
))
492 v
->line
= from
->line
;
493 v
->column
= from
->column
;
494 v
->source
= json_source_ref(from
->source
);
497 int json_variant_new_array(JsonVariant
**ret
, JsonVariant
**array
, size_t n
) {
498 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
499 bool normalized
= true;
501 assert_return(ret
, -EINVAL
);
503 *ret
= JSON_VARIANT_MAGIC_EMPTY_ARRAY
;
506 assert_return(array
, -EINVAL
);
508 v
= new(JsonVariant
, n
+ 1);
514 .type
= JSON_VARIANT_ARRAY
,
517 for (v
->n_elements
= 0; v
->n_elements
< n
; v
->n_elements
++) {
518 JsonVariant
*w
= v
+ 1 + v
->n_elements
,
519 *c
= array
[v
->n_elements
];
522 d
= json_variant_depth(c
);
523 if (d
>= DEPTH_MAX
) /* Refuse too deep nesting */
533 json_variant_set(w
, c
);
534 json_variant_copy_source(w
, c
);
536 if (!json_variant_is_normalized(c
))
540 v
->normalized
= normalized
;
546 int json_variant_new_array_bytes(JsonVariant
**ret
, const void *p
, size_t n
) {
550 assert_return(ret
, -EINVAL
);
552 *ret
= JSON_VARIANT_MAGIC_EMPTY_ARRAY
;
555 assert_return(p
, -EINVAL
);
557 v
= new(JsonVariant
, n
+ 1);
563 .type
= JSON_VARIANT_ARRAY
,
568 for (i
= 0; i
< n
; i
++) {
569 JsonVariant
*w
= v
+ 1 + i
;
574 .type
= JSON_VARIANT_UNSIGNED
,
575 .value
.unsig
= ((const uint8_t*) p
)[i
],
579 v
->normalized
= true;
585 int json_variant_new_array_strv(JsonVariant
**ret
, char **l
) {
586 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
594 *ret
= JSON_VARIANT_MAGIC_EMPTY_ARRAY
;
598 v
= new(JsonVariant
, n
+ 1);
604 .type
= JSON_VARIANT_ARRAY
,
608 for (v
->n_elements
= 0; v
->n_elements
< n
; v
->n_elements
++) {
609 JsonVariant
*w
= v
+ 1 + v
->n_elements
;
615 .type
= JSON_VARIANT_STRING
,
618 k
= strlen(l
[v
->n_elements
]);
620 if (k
> INLINE_STRING_MAX
) {
621 /* If string is too long, store it as reference. */
623 r
= json_variant_new_string(&w
->reference
, l
[v
->n_elements
]);
627 w
->is_reference
= true;
629 memcpy(w
->string
, l
[v
->n_elements
], k
+1);
632 v
->normalized
= true;
638 int json_variant_new_object(JsonVariant
**ret
, JsonVariant
**array
, size_t n
) {
639 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
640 const char *prev
= NULL
;
641 bool sorted
= true, normalized
= true;
643 assert_return(ret
, -EINVAL
);
645 *ret
= JSON_VARIANT_MAGIC_EMPTY_OBJECT
;
648 assert_return(array
, -EINVAL
);
649 assert_return(n
% 2 == 0, -EINVAL
);
651 v
= new(JsonVariant
, n
+ 1);
657 .type
= JSON_VARIANT_OBJECT
,
660 for (v
->n_elements
= 0; v
->n_elements
< n
; v
->n_elements
++) {
661 JsonVariant
*w
= v
+ 1 + v
->n_elements
,
662 *c
= array
[v
->n_elements
];
665 if ((v
->n_elements
& 1) == 0) {
668 if (!json_variant_is_string(c
))
669 return -EINVAL
; /* Every second one needs to be a string, as it is the key name */
671 assert_se(k
= json_variant_string(c
));
673 if (prev
&& strcmp(k
, prev
) <= 0)
674 sorted
= normalized
= false;
677 } else if (!json_variant_is_normalized(c
))
680 d
= json_variant_depth(c
);
681 if (d
>= DEPTH_MAX
) /* Refuse too deep nesting */
691 json_variant_set(w
, c
);
692 json_variant_copy_source(w
, c
);
695 v
->normalized
= normalized
;
702 static size_t json_variant_size(JsonVariant
* v
) {
704 if (!json_variant_is_regular(v
))
708 return offsetof(JsonVariant
, reference
) + sizeof(JsonVariant
*);
712 case JSON_VARIANT_STRING
:
713 return offsetof(JsonVariant
, string
) + strlen(v
->string
) + 1;
715 case JSON_VARIANT_REAL
:
716 return offsetof(JsonVariant
, value
) + sizeof(long double);
718 case JSON_VARIANT_UNSIGNED
:
719 return offsetof(JsonVariant
, value
) + sizeof(uintmax_t);
721 case JSON_VARIANT_INTEGER
:
722 return offsetof(JsonVariant
, value
) + sizeof(intmax_t);
724 case JSON_VARIANT_BOOLEAN
:
725 return offsetof(JsonVariant
, value
) + sizeof(bool);
727 case JSON_VARIANT_ARRAY
:
728 case JSON_VARIANT_OBJECT
:
729 return offsetof(JsonVariant
, n_elements
) + sizeof(size_t);
731 case JSON_VARIANT_NULL
:
732 return offsetof(JsonVariant
, value
);
735 assert_not_reached("unexpected type");
739 static void json_variant_free_inner(JsonVariant
*v
, bool force_sensitive
) {
744 if (!json_variant_is_regular(v
))
747 json_source_unref(v
->source
);
749 sensitive
= v
->sensitive
|| force_sensitive
;
751 if (v
->is_reference
) {
753 json_variant_sensitive(v
->reference
);
755 json_variant_unref(v
->reference
);
759 if (IN_SET(v
->type
, JSON_VARIANT_ARRAY
, JSON_VARIANT_OBJECT
)) {
762 for (i
= 0; i
< v
->n_elements
; i
++)
763 json_variant_free_inner(v
+ 1 + i
, sensitive
);
767 explicit_bzero_safe(v
, json_variant_size(v
));
770 JsonVariant
*json_variant_ref(JsonVariant
*v
) {
773 if (!json_variant_is_regular(v
))
777 json_variant_ref(v
->parent
); /* ref the compounding variant instead */
779 assert(v
->n_ref
> 0);
786 JsonVariant
*json_variant_unref(JsonVariant
*v
) {
789 if (!json_variant_is_regular(v
))
793 json_variant_unref(v
->parent
);
795 assert(v
->n_ref
> 0);
799 json_variant_free_inner(v
, false);
807 void json_variant_unref_many(JsonVariant
**array
, size_t n
) {
810 assert(array
|| n
== 0);
812 for (i
= 0; i
< n
; i
++)
813 json_variant_unref(array
[i
]);
816 const char *json_variant_string(JsonVariant
*v
) {
819 if (v
== JSON_VARIANT_MAGIC_EMPTY_STRING
)
821 if (json_variant_is_magic(v
))
823 if (json_variant_is_const_string(v
)) {
824 uintptr_t p
= (uintptr_t) v
;
826 assert((p
& 1) != 0);
827 return (const char*) (p
^ 1U);
831 return json_variant_string(v
->reference
);
832 if (v
->type
!= JSON_VARIANT_STRING
)
838 log_debug("Non-string JSON variant requested as string, returning NULL.");
842 bool json_variant_boolean(JsonVariant
*v
) {
845 if (v
== JSON_VARIANT_MAGIC_TRUE
)
847 if (v
== JSON_VARIANT_MAGIC_FALSE
)
849 if (!json_variant_is_regular(v
))
851 if (v
->type
!= JSON_VARIANT_BOOLEAN
)
854 return json_variant_boolean(v
->reference
);
856 return v
->value
.boolean
;
859 log_debug("Non-boolean JSON variant requested as boolean, returning false.");
863 intmax_t json_variant_integer(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_integer(v
->reference
);
877 case JSON_VARIANT_INTEGER
:
878 return v
->value
.integer
;
880 case JSON_VARIANT_UNSIGNED
:
881 if (v
->value
.unsig
<= INTMAX_MAX
)
882 return (intmax_t) v
->value
.unsig
;
884 log_debug("Unsigned integer %ju requested as signed integer and out of range, returning 0.", v
->value
.unsig
);
887 case JSON_VARIANT_REAL
: {
890 converted
= (intmax_t) v
->value
.real
;
892 #pragma GCC diagnostic push
893 #pragma GCC diagnostic ignored "-Wfloat-equal"
894 if ((long double) converted
== v
->value
.real
)
895 #pragma GCC diagnostic pop
898 log_debug("Real %Lg requested as integer, and cannot be converted losslessly, returning 0.", v
->value
.real
);
907 log_debug("Non-integer JSON variant requested as integer, returning 0.");
911 uintmax_t json_variant_unsigned(JsonVariant
*v
) {
914 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
915 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
916 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
918 if (!json_variant_is_regular(v
))
921 return json_variant_integer(v
->reference
);
925 case JSON_VARIANT_INTEGER
:
926 if (v
->value
.integer
>= 0)
927 return (uintmax_t) v
->value
.integer
;
929 log_debug("Signed integer %ju requested as unsigned integer and out of range, returning 0.", v
->value
.integer
);
932 case JSON_VARIANT_UNSIGNED
:
933 return v
->value
.unsig
;
935 case JSON_VARIANT_REAL
: {
938 converted
= (uintmax_t) v
->value
.real
;
940 #pragma GCC diagnostic push
941 #pragma GCC diagnostic ignored "-Wfloat-equal"
942 if ((long double) converted
== v
->value
.real
)
943 #pragma GCC diagnostic pop
946 log_debug("Real %Lg requested as unsigned integer, and cannot be converted losslessly, returning 0.", v
->value
.real
);
955 log_debug("Non-integer JSON variant requested as unsigned, returning 0.");
959 long double json_variant_real(JsonVariant
*v
) {
962 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
963 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
964 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
966 if (!json_variant_is_regular(v
))
969 return json_variant_real(v
->reference
);
973 case JSON_VARIANT_REAL
:
974 return v
->value
.real
;
976 case JSON_VARIANT_INTEGER
: {
977 long double converted
;
979 converted
= (long double) v
->value
.integer
;
981 if ((intmax_t) converted
== v
->value
.integer
)
984 log_debug("Signed integer %ji requested as real, and cannot be converted losslessly, returning 0.", v
->value
.integer
);
988 case JSON_VARIANT_UNSIGNED
: {
989 long double converted
;
991 converted
= (long double) v
->value
.unsig
;
993 if ((uintmax_t) converted
== v
->value
.unsig
)
996 log_debug("Unsigned integer %ju requested as real, and cannot be converted losslessly, returning 0.", v
->value
.unsig
);
1005 log_debug("Non-integer JSON variant requested as integer, returning 0.");
1009 bool json_variant_is_negative(JsonVariant
*v
) {
1012 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
||
1013 v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
||
1014 v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
1016 if (!json_variant_is_regular(v
))
1018 if (v
->is_reference
)
1019 return json_variant_is_negative(v
->reference
);
1021 /* This function is useful as checking whether numbers are negative is pretty complex since we have three types
1022 * of numbers. And some JSON code (OCI for example) uses negative numbers to mark "not defined" numeric
1027 case JSON_VARIANT_REAL
:
1028 return v
->value
.real
< 0;
1030 case JSON_VARIANT_INTEGER
:
1031 return v
->value
.integer
< 0;
1033 case JSON_VARIANT_UNSIGNED
:
1041 log_debug("Non-integer JSON variant tested for negativity, returning false.");
1045 bool json_variant_is_blank_object(JsonVariant
*v
) {
1046 /* Returns true if the specified object is null or empty */
1048 json_variant_is_null(v
) ||
1049 (json_variant_is_object(v
) && json_variant_elements(v
) == 0);
1052 bool json_variant_is_blank_array(JsonVariant
*v
) {
1054 json_variant_is_null(v
) ||
1055 (json_variant_is_array(v
) && json_variant_elements(v
) == 0);
1058 JsonVariantType
json_variant_type(JsonVariant
*v
) {
1061 return _JSON_VARIANT_TYPE_INVALID
;
1063 if (json_variant_is_const_string(v
))
1064 return JSON_VARIANT_STRING
;
1066 if (v
== JSON_VARIANT_MAGIC_TRUE
|| v
== JSON_VARIANT_MAGIC_FALSE
)
1067 return JSON_VARIANT_BOOLEAN
;
1069 if (v
== JSON_VARIANT_MAGIC_NULL
)
1070 return JSON_VARIANT_NULL
;
1072 if (v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
)
1073 return JSON_VARIANT_INTEGER
;
1075 if (v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
)
1076 return JSON_VARIANT_UNSIGNED
;
1078 if (v
== JSON_VARIANT_MAGIC_ZERO_REAL
)
1079 return JSON_VARIANT_REAL
;
1081 if (v
== JSON_VARIANT_MAGIC_EMPTY_STRING
)
1082 return JSON_VARIANT_STRING
;
1084 if (v
== JSON_VARIANT_MAGIC_EMPTY_ARRAY
)
1085 return JSON_VARIANT_ARRAY
;
1087 if (v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
1088 return JSON_VARIANT_OBJECT
;
1093 bool json_variant_has_type(JsonVariant
*v
, JsonVariantType type
) {
1096 v
= json_variant_dereference(v
);
1100 rt
= json_variant_type(v
);
1104 /* If it's a const string, then it only can be a string, and if it is not, it's not */
1105 if (json_variant_is_const_string(v
))
1108 /* All three magic zeroes qualify as integer, unsigned and as real */
1109 if ((v
== JSON_VARIANT_MAGIC_ZERO_INTEGER
|| v
== JSON_VARIANT_MAGIC_ZERO_UNSIGNED
|| v
== JSON_VARIANT_MAGIC_ZERO_REAL
) &&
1110 IN_SET(type
, JSON_VARIANT_INTEGER
, JSON_VARIANT_UNSIGNED
, JSON_VARIANT_REAL
, JSON_VARIANT_NUMBER
))
1113 /* All other magic variant types are only equal to themselves */
1114 if (json_variant_is_magic(v
))
1117 /* Handle the "number" pseudo type */
1118 if (type
== JSON_VARIANT_NUMBER
)
1119 return IN_SET(rt
, JSON_VARIANT_INTEGER
, JSON_VARIANT_UNSIGNED
, JSON_VARIANT_REAL
);
1121 /* Integer conversions are OK in many cases */
1122 if (rt
== JSON_VARIANT_INTEGER
&& type
== JSON_VARIANT_UNSIGNED
)
1123 return v
->value
.integer
>= 0;
1124 if (rt
== JSON_VARIANT_UNSIGNED
&& type
== JSON_VARIANT_INTEGER
)
1125 return v
->value
.unsig
<= INTMAX_MAX
;
1127 /* Any integer that can be converted lossley to a real and back may also be considered a real */
1128 if (rt
== JSON_VARIANT_INTEGER
&& type
== JSON_VARIANT_REAL
)
1129 return (intmax_t) (long double) v
->value
.integer
== v
->value
.integer
;
1130 if (rt
== JSON_VARIANT_UNSIGNED
&& type
== JSON_VARIANT_REAL
)
1131 return (uintmax_t) (long double) v
->value
.unsig
== v
->value
.unsig
;
1133 #pragma GCC diagnostic push
1134 #pragma GCC diagnostic ignored "-Wfloat-equal"
1135 /* Any real that can be converted losslessly to an integer and back may also be considered an integer */
1136 if (rt
== JSON_VARIANT_REAL
&& type
== JSON_VARIANT_INTEGER
)
1137 return (long double) (intmax_t) v
->value
.real
== v
->value
.real
;
1138 if (rt
== JSON_VARIANT_REAL
&& type
== JSON_VARIANT_UNSIGNED
)
1139 return (long double) (uintmax_t) v
->value
.real
== v
->value
.real
;
1140 #pragma GCC diagnostic pop
1145 size_t json_variant_elements(JsonVariant
*v
) {
1148 if (v
== JSON_VARIANT_MAGIC_EMPTY_ARRAY
||
1149 v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
1151 if (!json_variant_is_regular(v
))
1153 if (!IN_SET(v
->type
, JSON_VARIANT_ARRAY
, JSON_VARIANT_OBJECT
))
1155 if (v
->is_reference
)
1156 return json_variant_elements(v
->reference
);
1158 return v
->n_elements
;
1161 log_debug("Number of elements in non-array/non-object JSON variant requested, returning 0.");
1165 JsonVariant
*json_variant_by_index(JsonVariant
*v
, size_t idx
) {
1168 if (v
== JSON_VARIANT_MAGIC_EMPTY_ARRAY
||
1169 v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
1171 if (!json_variant_is_regular(v
))
1173 if (!IN_SET(v
->type
, JSON_VARIANT_ARRAY
, JSON_VARIANT_OBJECT
))
1175 if (v
->is_reference
)
1176 return json_variant_by_index(v
->reference
, idx
);
1177 if (idx
>= v
->n_elements
)
1180 return json_variant_conservative_formalize(v
+ 1 + idx
);
1183 log_debug("Element in non-array/non-object JSON variant requested by index, returning NULL.");
1187 JsonVariant
*json_variant_by_key_full(JsonVariant
*v
, const char *key
, JsonVariant
**ret_key
) {
1194 if (v
== JSON_VARIANT_MAGIC_EMPTY_OBJECT
)
1196 if (!json_variant_is_regular(v
))
1198 if (v
->type
!= JSON_VARIANT_OBJECT
)
1200 if (v
->is_reference
)
1201 return json_variant_by_key(v
->reference
, key
);
1204 size_t a
= 0, b
= v
->n_elements
/2;
1206 /* If the variant is sorted we can use bisection to find the entry we need in O(log(n)) time */
1214 p
= json_variant_dereference(v
+ 1 + i
*2);
1216 assert_se(f
= json_variant_string(p
));
1221 *ret_key
= json_variant_conservative_formalize(v
+ 1 + i
*2);
1223 return json_variant_conservative_formalize(v
+ 1 + i
*2 + 1);
1233 /* The variant is not sorted, hence search for the field linearly */
1234 for (i
= 0; i
< v
->n_elements
; i
+= 2) {
1237 p
= json_variant_dereference(v
+ 1 + i
);
1239 if (!json_variant_has_type(p
, JSON_VARIANT_STRING
))
1242 if (streq(json_variant_string(p
), key
)) {
1245 *ret_key
= json_variant_conservative_formalize(v
+ 1 + i
);
1247 return json_variant_conservative_formalize(v
+ 1 + i
+ 1);
1258 log_debug("Element in non-object JSON variant requested by key, returning NULL.");
1265 JsonVariant
*json_variant_by_key(JsonVariant
*v
, const char *key
) {
1266 return json_variant_by_key_full(v
, key
, NULL
);
1269 bool json_variant_equal(JsonVariant
*a
, JsonVariant
*b
) {
1272 a
= json_variant_formalize(a
);
1273 b
= json_variant_formalize(b
);
1278 t
= json_variant_type(a
);
1279 if (!json_variant_has_type(b
, t
))
1284 case JSON_VARIANT_STRING
:
1285 return streq(json_variant_string(a
), json_variant_string(b
));
1287 case JSON_VARIANT_INTEGER
:
1288 return json_variant_integer(a
) == json_variant_integer(b
);
1290 case JSON_VARIANT_UNSIGNED
:
1291 return json_variant_unsigned(a
) == json_variant_unsigned(b
);
1293 case JSON_VARIANT_REAL
:
1294 #pragma GCC diagnostic push
1295 #pragma GCC diagnostic ignored "-Wfloat-equal"
1296 return json_variant_real(a
) == json_variant_real(b
);
1297 #pragma GCC diagnostic pop
1299 case JSON_VARIANT_BOOLEAN
:
1300 return json_variant_boolean(a
) == json_variant_boolean(b
);
1302 case JSON_VARIANT_NULL
:
1305 case JSON_VARIANT_ARRAY
: {
1308 n
= json_variant_elements(a
);
1309 if (n
!= json_variant_elements(b
))
1312 for (i
= 0; i
< n
; i
++) {
1313 if (!json_variant_equal(json_variant_by_index(a
, i
), json_variant_by_index(b
, i
)))
1320 case JSON_VARIANT_OBJECT
: {
1323 n
= json_variant_elements(a
);
1324 if (n
!= json_variant_elements(b
))
1327 /* Iterate through all keys in 'a' */
1328 for (i
= 0; i
< n
; i
+= 2) {
1332 /* Match them against all keys in 'b' */
1333 for (j
= 0; j
< n
; j
+= 2) {
1336 key_b
= json_variant_by_index(b
, j
);
1338 /* During the first iteration unmark everything */
1340 key_b
->is_marked
= false;
1341 else if (key_b
->is_marked
) /* In later iterations if we already marked something, don't bother with it again */
1347 if (json_variant_equal(json_variant_by_index(a
, i
), key_b
) &&
1348 json_variant_equal(json_variant_by_index(a
, i
+1), json_variant_by_index(b
, j
+1))) {
1349 /* Key and values match! */
1350 key_b
->is_marked
= found
= true;
1352 /* In the first iteration we continue the inner loop since we want to mark
1353 * everything, otherwise exit the loop quickly after we found what we were
1368 assert_not_reached("Unknown variant type.");
1372 void json_variant_sensitive(JsonVariant
*v
) {
1375 /* Marks a variant as "sensitive", so that it is erased from memory when it is destroyed. This is a
1376 * one-way operation: as soon as it is marked this way it remains marked this way until it's
1377 * destoryed. A magic variant is never sensitive though, even when asked, since it's too
1378 * basic. Similar, const string variant are never sensitive either, after all they are included in
1379 * the source code as they are, which is not suitable for inclusion of secrets.
1381 * Note that this flag has a recursive effect: when we destroy an object or array we'll propagate the
1382 * flag to all contained variants. And if those are then destroyed this is propagated further down,
1385 v
= json_variant_formalize(v
);
1386 if (!json_variant_is_regular(v
))
1389 v
->sensitive
= true;
1392 int json_variant_get_source(JsonVariant
*v
, const char **ret_source
, unsigned *ret_line
, unsigned *ret_column
) {
1393 assert_return(v
, -EINVAL
);
1396 *ret_source
= json_variant_is_regular(v
) && v
->source
? v
->source
->name
: NULL
;
1399 *ret_line
= json_variant_is_regular(v
) ? v
->line
: 0;
1402 *ret_column
= json_variant_is_regular(v
) ? v
->column
: 0;
1407 static int print_source(FILE *f
, JsonVariant
*v
, JsonFormatFlags flags
, bool whitespace
) {
1410 if (!FLAGS_SET(flags
, JSON_FORMAT_SOURCE
|JSON_FORMAT_PRETTY
))
1413 if (!json_variant_is_regular(v
))
1416 if (!v
->source
&& v
->line
== 0 && v
->column
== 0)
1419 /* The max width we need to format the line numbers for this source file */
1420 w
= (v
->source
&& v
->source
->max_line
> 0) ?
1421 DECIMAL_STR_WIDTH(v
->source
->max_line
) :
1422 DECIMAL_STR_MAX(unsigned)-1;
1423 k
= (v
->source
&& v
->source
->max_column
> 0) ?
1424 DECIMAL_STR_WIDTH(v
->source
->max_column
) :
1425 DECIMAL_STR_MAX(unsigned) -1;
1430 n
= 1 + (v
->source
? strlen(v
->source
->name
) : 0) +
1431 ((v
->source
&& (v
->line
> 0 || v
->column
> 0)) ? 1 : 0) +
1432 (v
->line
> 0 ? w
: 0) +
1433 (((v
->source
|| v
->line
> 0) && v
->column
> 0) ? 1 : 0) +
1434 (v
->column
> 0 ? k
: 0) +
1437 for (i
= 0; i
< n
; i
++)
1443 fputs(v
->source
->name
, f
);
1444 if (v
->source
&& (v
->line
> 0 || v
->column
> 0))
1447 fprintf(f
, "%*u", (int) w
, v
->line
);
1448 if ((v
->source
|| v
->line
> 0) || v
->column
> 0)
1451 fprintf(f
, "%*u", (int) k
, v
->column
);
1460 static int json_format(FILE *f
, JsonVariant
*v
, JsonFormatFlags flags
, const char *prefix
) {
1466 switch (json_variant_type(v
)) {
1468 case JSON_VARIANT_REAL
: {
1471 loc
= newlocale(LC_NUMERIC_MASK
, "C", (locale_t
) 0);
1472 if (loc
== (locale_t
) 0)
1475 if (flags
& JSON_FORMAT_COLOR
)
1476 fputs(ANSI_HIGHLIGHT_BLUE
, f
);
1478 fprintf(f
, "%.*Le", DECIMAL_DIG
, json_variant_real(v
));
1480 if (flags
& JSON_FORMAT_COLOR
)
1481 fputs(ANSI_NORMAL
, f
);
1487 case JSON_VARIANT_INTEGER
:
1488 if (flags
& JSON_FORMAT_COLOR
)
1489 fputs(ANSI_HIGHLIGHT_BLUE
, f
);
1491 fprintf(f
, "%" PRIdMAX
, json_variant_integer(v
));
1493 if (flags
& JSON_FORMAT_COLOR
)
1494 fputs(ANSI_NORMAL
, f
);
1497 case JSON_VARIANT_UNSIGNED
:
1498 if (flags
& JSON_FORMAT_COLOR
)
1499 fputs(ANSI_HIGHLIGHT_BLUE
, f
);
1501 fprintf(f
, "%" PRIuMAX
, json_variant_unsigned(v
));
1503 if (flags
& JSON_FORMAT_COLOR
)
1504 fputs(ANSI_NORMAL
, f
);
1507 case JSON_VARIANT_BOOLEAN
:
1509 if (flags
& JSON_FORMAT_COLOR
)
1510 fputs(ANSI_HIGHLIGHT
, f
);
1512 if (json_variant_boolean(v
))
1517 if (flags
& JSON_FORMAT_COLOR
)
1518 fputs(ANSI_NORMAL
, f
);
1522 case JSON_VARIANT_NULL
:
1523 if (flags
& JSON_FORMAT_COLOR
)
1524 fputs(ANSI_HIGHLIGHT
, f
);
1528 if (flags
& JSON_FORMAT_COLOR
)
1529 fputs(ANSI_NORMAL
, f
);
1532 case JSON_VARIANT_STRING
: {
1537 if (flags
& JSON_FORMAT_COLOR
)
1538 fputs(ANSI_GREEN
, f
);
1540 for (q
= json_variant_string(v
); *q
; q
++) {
1573 if ((signed char) *q
>= 0 && *q
< ' ')
1574 fprintf(f
, "\\u%04x", *q
);
1581 if (flags
& JSON_FORMAT_COLOR
)
1582 fputs(ANSI_NORMAL
, f
);
1588 case JSON_VARIANT_ARRAY
: {
1591 n
= json_variant_elements(v
);
1596 _cleanup_free_
char *joined
= NULL
;
1597 const char *prefix2
;
1599 if (flags
& JSON_FORMAT_PRETTY
) {
1600 joined
= strjoin(strempty(prefix
), "\t");
1607 prefix2
= strempty(prefix
);
1611 for (i
= 0; i
< n
; i
++) {
1614 assert_se(e
= json_variant_by_index(v
, i
));
1617 if (flags
& JSON_FORMAT_PRETTY
)
1623 if (flags
& JSON_FORMAT_PRETTY
) {
1624 print_source(f
, e
, flags
, false);
1628 r
= json_format(f
, e
, flags
, prefix2
);
1633 if (flags
& JSON_FORMAT_PRETTY
) {
1635 print_source(f
, v
, flags
, true);
1636 fputs(strempty(prefix
), f
);
1644 case JSON_VARIANT_OBJECT
: {
1647 n
= json_variant_elements(v
);
1652 _cleanup_free_
char *joined
= NULL
;
1653 const char *prefix2
;
1655 if (flags
& JSON_FORMAT_PRETTY
) {
1656 joined
= strjoin(strempty(prefix
), "\t");
1663 prefix2
= strempty(prefix
);
1667 for (i
= 0; i
< n
; i
+= 2) {
1670 e
= json_variant_by_index(v
, i
);
1673 if (flags
& JSON_FORMAT_PRETTY
)
1679 if (flags
& JSON_FORMAT_PRETTY
) {
1680 print_source(f
, e
, flags
, false);
1684 r
= json_format(f
, e
, flags
, prefix2
);
1688 fputs(flags
& JSON_FORMAT_PRETTY
? " : " : ":", f
);
1690 r
= json_format(f
, json_variant_by_index(v
, i
+1), flags
, prefix2
);
1695 if (flags
& JSON_FORMAT_PRETTY
) {
1697 print_source(f
, v
, flags
, true);
1698 fputs(strempty(prefix
), f
);
1707 assert_not_reached("Unexpected variant type.");
1713 int json_variant_format(JsonVariant
*v
, JsonFormatFlags flags
, char **ret
) {
1714 _cleanup_free_
char *s
= NULL
;
1718 /* Returns the length of the generated string (without the terminating NUL),
1719 * or negative on error. */
1721 assert_return(v
, -EINVAL
);
1722 assert_return(ret
, -EINVAL
);
1725 _cleanup_fclose_
FILE *f
= NULL
;
1727 f
= open_memstream_unlocked(&s
, &sz
);
1731 json_variant_dump(v
, flags
, f
, NULL
);
1733 /* Add terminating 0, so that the output buffer is a valid string. */
1736 r
= fflush_and_check(f
);
1744 return (int) sz
- 1;
1747 void json_variant_dump(JsonVariant
*v
, JsonFormatFlags flags
, FILE *f
, const char *prefix
) {
1754 print_source(f
, v
, flags
, false);
1756 if (((flags
& (JSON_FORMAT_COLOR_AUTO
|JSON_FORMAT_COLOR
)) == JSON_FORMAT_COLOR_AUTO
) && colors_enabled())
1757 flags
|= JSON_FORMAT_COLOR
;
1759 if (flags
& JSON_FORMAT_SSE
)
1761 if (flags
& JSON_FORMAT_SEQ
)
1762 fputc('\x1e', f
); /* ASCII Record Separator */
1764 json_format(f
, v
, flags
, prefix
);
1766 if (flags
& (JSON_FORMAT_PRETTY
|JSON_FORMAT_SEQ
|JSON_FORMAT_SSE
|JSON_FORMAT_NEWLINE
))
1768 if (flags
& JSON_FORMAT_SSE
)
1769 fputc('\n', f
); /* In case of SSE add a second newline */
1771 if (flags
& JSON_FORMAT_FLUSH
)
1775 int json_variant_filter(JsonVariant
**v
, char **to_remove
) {
1776 _cleanup_(json_variant_unrefp
) JsonVariant
*w
= NULL
;
1777 _cleanup_free_ JsonVariant
**array
= NULL
;
1778 size_t i
, n
= 0, k
= 0;
1783 if (json_variant_is_blank_object(*v
))
1785 if (!json_variant_is_object(*v
))
1788 if (strv_isempty(to_remove
))
1791 for (i
= 0; i
< json_variant_elements(*v
); i
+= 2) {
1794 p
= json_variant_by_index(*v
, i
);
1795 if (!json_variant_has_type(p
, JSON_VARIANT_STRING
))
1798 if (strv_contains(to_remove
, json_variant_string(p
))) {
1800 array
= new(JsonVariant
*, json_variant_elements(*v
) - 2);
1804 for (k
= 0; k
< i
; k
++)
1805 array
[k
] = json_variant_by_index(*v
, k
);
1811 array
[k
++] = json_variant_by_index(*v
, i
+ 1);
1818 r
= json_variant_new_object(&w
, array
, k
);
1822 json_variant_unref(*v
);
1828 int json_variant_set_field(JsonVariant
**v
, const char *field
, JsonVariant
*value
) {
1829 _cleanup_(json_variant_unrefp
) JsonVariant
*field_variant
= NULL
, *w
= NULL
;
1830 _cleanup_free_ JsonVariant
**array
= NULL
;
1837 if (json_variant_is_blank_object(*v
)) {
1838 array
= new(JsonVariant
*, 2);
1843 if (!json_variant_is_object(*v
))
1846 for (i
= 0; i
< json_variant_elements(*v
); i
+= 2) {
1849 p
= json_variant_by_index(*v
, i
);
1850 if (!json_variant_is_string(p
))
1853 if (streq(json_variant_string(p
), field
)) {
1856 array
= new(JsonVariant
*, json_variant_elements(*v
));
1860 for (k
= 0; k
< i
; k
++)
1861 array
[k
] = json_variant_by_index(*v
, k
);
1866 array
[k
++] = json_variant_by_index(*v
, i
+ 1);
1871 array
= new(JsonVariant
*, json_variant_elements(*v
) + 2);
1875 for (k
= 0; k
< json_variant_elements(*v
); k
++)
1876 array
[k
] = json_variant_by_index(*v
, k
);
1880 r
= json_variant_new_string(&field_variant
, field
);
1884 array
[k
++] = field_variant
;
1887 r
= json_variant_new_object(&w
, array
, k
);
1891 json_variant_unref(*v
);
1897 int json_variant_set_field_string(JsonVariant
**v
, const char *field
, const char *value
) {
1898 _cleanup_(json_variant_unrefp
) JsonVariant
*m
= NULL
;
1901 r
= json_variant_new_string(&m
, value
);
1905 return json_variant_set_field(v
, field
, m
);
1908 int json_variant_set_field_unsigned(JsonVariant
**v
, const char *field
, uintmax_t u
) {
1909 _cleanup_(json_variant_unrefp
) JsonVariant
*m
= NULL
;
1912 r
= json_variant_new_unsigned(&m
, u
);
1916 return json_variant_set_field(v
, field
, m
);
1919 int json_variant_merge(JsonVariant
**v
, JsonVariant
*m
) {
1920 _cleanup_(json_variant_unrefp
) JsonVariant
*w
= NULL
;
1921 _cleanup_free_ JsonVariant
**array
= NULL
;
1922 size_t v_elements
, m_elements
, i
, k
;
1923 bool v_blank
, m_blank
;
1926 m
= json_variant_dereference(m
);
1928 v_blank
= json_variant_is_blank_object(*v
);
1929 m_blank
= json_variant_is_blank_object(m
);
1931 if (!v_blank
&& !json_variant_is_object(*v
))
1933 if (!m_blank
&& !json_variant_is_object(m
))
1937 return 0; /* nothing to do */
1940 json_variant_unref(*v
);
1941 *v
= json_variant_ref(m
);
1945 v_elements
= json_variant_elements(*v
);
1946 m_elements
= json_variant_elements(m
);
1947 if (v_elements
> SIZE_MAX
- m_elements
) /* overflow check */
1950 array
= new(JsonVariant
*, v_elements
+ m_elements
);
1955 for (i
= 0; i
< v_elements
; i
+= 2) {
1958 u
= json_variant_by_index(*v
, i
);
1959 if (!json_variant_is_string(u
))
1962 if (json_variant_by_key(m
, json_variant_string(u
)))
1963 continue; /* skip if exists in second variant */
1966 array
[k
++] = json_variant_by_index(*v
, i
+ 1);
1969 for (i
= 0; i
< m_elements
; i
++)
1970 array
[k
++] = json_variant_by_index(m
, i
);
1972 r
= json_variant_new_object(&w
, array
, k
);
1976 json_variant_unref(*v
);
1982 int json_variant_append_array(JsonVariant
**v
, JsonVariant
*element
) {
1983 _cleanup_(json_variant_unrefp
) JsonVariant
*nv
= NULL
;
1991 if (!*v
|| json_variant_is_null(*v
))
1993 else if (!json_variant_is_array(*v
))
1996 blank
= json_variant_elements(*v
) == 0;
1999 r
= json_variant_new_array(&nv
, (JsonVariant
*[]) { element
}, 1);
2001 _cleanup_free_ JsonVariant
**array
= NULL
;
2004 array
= new(JsonVariant
*, json_variant_elements(*v
) + 1);
2008 for (i
= 0; i
< json_variant_elements(*v
); i
++)
2009 array
[i
] = json_variant_by_index(*v
, i
);
2013 r
= json_variant_new_array(&nv
, array
, i
+ 1);
2019 json_variant_unref(*v
);
2025 int json_variant_strv(JsonVariant
*v
, char ***ret
) {
2033 if (!v
|| json_variant_is_null(v
)) {
2042 if (!json_variant_is_array(v
))
2045 sensitive
= v
->sensitive
;
2047 n
= json_variant_elements(v
);
2048 l
= new(char*, n
+1);
2052 for (i
= 0; i
< n
; i
++) {
2055 assert_se(e
= json_variant_by_index(v
, i
));
2056 sensitive
= sensitive
|| e
->sensitive
;
2058 if (!json_variant_is_string(e
)) {
2064 l
[i
] = strdup(json_variant_string(e
));
2085 static int json_variant_copy(JsonVariant
**nv
, JsonVariant
*v
) {
2095 /* Let's copy the simple types literally, and the larger types by references */
2096 t
= json_variant_type(v
);
2098 case JSON_VARIANT_INTEGER
:
2099 k
= sizeof(intmax_t);
2100 value
.integer
= json_variant_integer(v
);
2104 case JSON_VARIANT_UNSIGNED
:
2105 k
= sizeof(uintmax_t);
2106 value
.unsig
= json_variant_unsigned(v
);
2110 case JSON_VARIANT_REAL
:
2111 k
= sizeof(long double);
2112 value
.real
= json_variant_real(v
);
2116 case JSON_VARIANT_BOOLEAN
:
2118 value
.boolean
= json_variant_boolean(v
);
2122 case JSON_VARIANT_NULL
:
2127 case JSON_VARIANT_STRING
:
2128 source
= json_variant_string(v
);
2129 k
= strnlen(source
, INLINE_STRING_MAX
+ 1);
2130 if (k
<= INLINE_STRING_MAX
) {
2138 /* Everything else copy by reference */
2140 c
= malloc0(MAX(sizeof(JsonVariant
),
2141 offsetof(JsonVariant
, reference
) + sizeof(JsonVariant
*)));
2147 c
->is_reference
= true;
2148 c
->reference
= json_variant_ref(json_variant_formalize(v
));
2154 c
= malloc0(MAX(sizeof(JsonVariant
),
2155 offsetof(JsonVariant
, value
) + k
));
2162 memcpy_safe(&c
->value
, source
, k
);
2168 static bool json_single_ref(JsonVariant
*v
) {
2170 /* Checks whether the caller is the single owner of the object, i.e. can get away with changing it */
2172 if (!json_variant_is_regular(v
))
2176 return json_single_ref(v
->parent
);
2178 assert(v
->n_ref
> 0);
2179 return v
->n_ref
== 1;
2182 static int json_variant_set_source(JsonVariant
**v
, JsonSource
*source
, unsigned line
, unsigned column
) {
2188 /* Patch in source and line/column number. Tries to do this in-place if the caller is the sole referencer of
2189 * the object. If not, allocates a new object, possibly a surrogate for the original one */
2194 if (source
&& line
> source
->max_line
)
2195 source
->max_line
= line
;
2196 if (source
&& column
> source
->max_column
)
2197 source
->max_column
= column
;
2199 if (!json_variant_is_regular(*v
)) {
2201 if (!source
&& line
== 0 && column
== 0)
2205 if (json_source_equal((*v
)->source
, source
) &&
2206 (*v
)->line
== line
&&
2207 (*v
)->column
== column
)
2210 if (json_single_ref(*v
)) { /* Sole reference? */
2211 json_source_unref((*v
)->source
);
2212 (*v
)->source
= json_source_ref(source
);
2214 (*v
)->column
= column
;
2219 r
= json_variant_copy(&w
, *v
);
2223 assert(json_variant_is_regular(w
));
2224 assert(!w
->is_embedded
);
2225 assert(w
->n_ref
== 1);
2228 w
->source
= json_source_ref(source
);
2232 json_variant_unref(*v
);
2238 static void inc_lines_columns(unsigned *line
, unsigned *column
, const char *s
, size_t n
) {
2241 assert(s
|| n
== 0);
2247 } else if ((signed char) *s
>= 0 && *s
< 127) /* Process ASCII chars quickly */
2252 w
= utf8_encoded_valid_unichar(s
, n
);
2253 if (w
< 0) /* count invalid unichars as normal characters */
2255 else if ((size_t) w
> n
) /* never read more than the specified number of characters */
2270 static int unhex_ucs2(const char *c
, uint16_t *ret
) {
2277 aa
= unhexchar(c
[0]);
2281 bb
= unhexchar(c
[1]);
2285 cc
= unhexchar(c
[2]);
2289 dd
= unhexchar(c
[3]);
2293 x
= ((uint16_t) aa
<< 12) |
2294 ((uint16_t) bb
<< 8) |
2295 ((uint16_t) cc
<< 4) |
2306 static int json_parse_string(const char **p
, char **ret
) {
2307 _cleanup_free_
char *s
= NULL
;
2308 size_t n
= 0, allocated
= 0;
2329 /* Check for control characters 0x00..0x1f */
2330 if (*c
> 0 && *c
< ' ')
2333 /* Check for control character 0x7f */
2348 return JSON_TOKEN_STRING
;
2358 if (IN_SET(*c
, '"', '\\', '/'))
2370 else if (*c
== 'u') {
2374 r
= unhex_ucs2(c
+ 1, &x
);
2380 if (!GREEDY_REALLOC(s
, allocated
, n
+ 5))
2383 if (!utf16_is_surrogate(x
))
2384 n
+= utf8_encode_unichar(s
+ n
, (char32_t
) x
);
2385 else if (utf16_is_trailing_surrogate(x
))
2390 if (c
[0] != '\\' || c
[1] != 'u')
2393 r
= unhex_ucs2(c
+ 2, &y
);
2399 if (!utf16_is_trailing_surrogate(y
))
2402 n
+= utf8_encode_unichar(s
+ n
, utf16_surrogate_pair_to_unichar(x
, y
));
2409 if (!GREEDY_REALLOC(s
, allocated
, n
+ 2))
2417 len
= utf8_encoded_valid_unichar(c
, (size_t) -1);
2421 if (!GREEDY_REALLOC(s
, allocated
, n
+ len
+ 1))
2424 memcpy(s
+ n
, c
, len
);
2430 static int json_parse_number(const char **p
, JsonValue
*ret
) {
2431 bool negative
= false, exponent_negative
= false, is_real
= false;
2432 long double x
= 0.0, y
= 0.0, exponent
= 0.0, shift
= 1.0;
2451 if (!strchr("123456789", *c
) || *c
== 0)
2458 if (i
< INTMAX_MIN
/ 10) /* overflow */
2461 intmax_t t
= 10 * i
;
2463 if (t
< INTMAX_MIN
+ (*c
- '0')) /* overflow */
2469 if (u
> UINTMAX_MAX
/ 10) /* overflow */
2472 uintmax_t t
= 10 * u
;
2474 if (t
> UINTMAX_MAX
- (*c
- '0')) /* overflow */
2482 x
= 10.0 * x
+ (*c
- '0');
2485 } while (strchr("0123456789", *c
) && *c
!= 0);
2492 if (!strchr("0123456789", *c
) || *c
== 0)
2496 y
= 10.0 * y
+ (*c
- '0');
2497 shift
= 10.0 * shift
;
2499 } while (strchr("0123456789", *c
) && *c
!= 0);
2502 if (IN_SET(*c
, 'e', 'E')) {
2507 exponent_negative
= true;
2509 } else if (*c
== '+')
2512 if (!strchr("0123456789", *c
) || *c
== 0)
2516 exponent
= 10.0 * exponent
+ (*c
- '0');
2518 } while (strchr("0123456789", *c
) && *c
!= 0);
2524 ret
->real
= ((negative
? -1.0 : 1.0) * (x
+ (y
/ shift
))) * exp10l((exponent_negative
? -1.0 : 1.0) * exponent
);
2525 return JSON_TOKEN_REAL
;
2526 } else if (negative
) {
2528 return JSON_TOKEN_INTEGER
;
2531 return JSON_TOKEN_UNSIGNED
;
2538 JsonValue
*ret_value
,
2539 unsigned *ret_line
, /* 'ret_line' returns the line at the beginning of this token */
2540 unsigned *ret_column
,
2542 unsigned *line
, /* 'line' is used as a line state, it always reflect the line we are at after the token was read */
2545 unsigned start_line
, start_column
;
2546 const char *start
, *c
;
2566 t
= PTR_TO_INT(*state
);
2567 if (t
== STATE_NULL
) {
2573 /* Skip over the whitespace */
2574 n
= strspn(*p
, WHITESPACE
);
2575 inc_lines_columns(line
, column
, *p
, n
);
2578 /* Remember where we started processing this token */
2581 start_column
= *column
;
2585 *ret_value
= JSON_VALUE_NULL
;
2596 *state
= INT_TO_PTR(STATE_VALUE
);
2597 r
= JSON_TOKEN_OBJECT_OPEN
;
2600 } else if (*c
== '}') {
2602 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2603 r
= JSON_TOKEN_OBJECT_CLOSE
;
2606 } else if (*c
== '[') {
2608 *state
= INT_TO_PTR(STATE_VALUE
);
2609 r
= JSON_TOKEN_ARRAY_OPEN
;
2612 } else if (*c
== ']') {
2614 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2615 r
= JSON_TOKEN_ARRAY_CLOSE
;
2618 } else if (*c
== '"') {
2620 r
= json_parse_string(&c
, ret_string
);
2624 *ret_value
= JSON_VALUE_NULL
;
2625 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2628 } else if (strchr("-0123456789", *c
)) {
2630 r
= json_parse_number(&c
, ret_value
);
2635 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2638 } else if (startswith(c
, "true")) {
2640 ret_value
->boolean
= true;
2642 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2643 r
= JSON_TOKEN_BOOLEAN
;
2646 } else if (startswith(c
, "false")) {
2648 ret_value
->boolean
= false;
2650 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2651 r
= JSON_TOKEN_BOOLEAN
;
2654 } else if (startswith(c
, "null")) {
2656 *ret_value
= JSON_VALUE_NULL
;
2658 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2659 r
= JSON_TOKEN_NULL
;
2666 case STATE_VALUE_POST
:
2670 *state
= INT_TO_PTR(STATE_VALUE
);
2671 r
= JSON_TOKEN_COLON
;
2674 } else if (*c
== ',') {
2676 *state
= INT_TO_PTR(STATE_VALUE
);
2677 r
= JSON_TOKEN_COMMA
;
2680 } else if (*c
== '}') {
2682 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2683 r
= JSON_TOKEN_OBJECT_CLOSE
;
2686 } else if (*c
== ']') {
2688 *state
= INT_TO_PTR(STATE_VALUE_POST
);
2689 r
= JSON_TOKEN_ARRAY_CLOSE
;
2696 assert_not_reached("Unexpected tokenizer state");
2701 *ret_value
= JSON_VALUE_NULL
;
2704 inc_lines_columns(line
, column
, start
, c
- start
);
2707 *ret_line
= start_line
;
2708 *ret_column
= start_column
;
2713 typedef enum JsonExpect
{
2714 /* The following values are used by json_parse() */
2717 EXPECT_OBJECT_FIRST_KEY
,
2718 EXPECT_OBJECT_NEXT_KEY
,
2719 EXPECT_OBJECT_COLON
,
2720 EXPECT_OBJECT_VALUE
,
2721 EXPECT_OBJECT_COMMA
,
2722 EXPECT_ARRAY_FIRST_ELEMENT
,
2723 EXPECT_ARRAY_NEXT_ELEMENT
,
2726 /* And these are used by json_build() */
2727 EXPECT_ARRAY_ELEMENT
,
2731 typedef struct JsonStack
{
2733 JsonVariant
**elements
;
2734 size_t n_elements
, n_elements_allocated
;
2735 unsigned line_before
;
2736 unsigned column_before
;
2737 size_t n_suppress
; /* When building: if > 0, suppress this many subsequent elements. If == (size_t) -1, suppress all subsequent elements */
2740 static void json_stack_release(JsonStack
*s
) {
2743 json_variant_unref_many(s
->elements
, s
->n_elements
);
2744 s
->elements
= mfree(s
->elements
);
2747 static int json_parse_internal(
2750 JsonParseFlags flags
,
2754 bool continue_end
) {
2756 size_t n_stack
= 1, n_stack_allocated
= 0, i
;
2757 unsigned line_buffer
= 0, column_buffer
= 0;
2758 void *tokenizer_state
= NULL
;
2759 JsonStack
*stack
= NULL
;
2763 assert_return(input
, -EINVAL
);
2764 assert_return(ret
, -EINVAL
);
2768 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
))
2771 stack
[0] = (JsonStack
) {
2772 .expect
= EXPECT_TOPLEVEL
,
2776 line
= &line_buffer
;
2778 column
= &column_buffer
;
2781 _cleanup_(json_variant_unrefp
) JsonVariant
*add
= NULL
;
2782 _cleanup_free_
char *string
= NULL
;
2783 unsigned line_token
, column_token
;
2788 assert(n_stack
> 0);
2789 current
= stack
+ n_stack
- 1;
2791 if (continue_end
&& current
->expect
== EXPECT_END
)
2794 token
= json_tokenize(&p
, &string
, &value
, &line_token
, &column_token
, &tokenizer_state
, line
, column
);
2802 case JSON_TOKEN_END
:
2803 if (current
->expect
!= EXPECT_END
) {
2808 assert(current
->n_elements
== 1);
2809 assert(n_stack
== 1);
2812 case JSON_TOKEN_COLON
:
2814 if (current
->expect
!= EXPECT_OBJECT_COLON
) {
2819 current
->expect
= EXPECT_OBJECT_VALUE
;
2822 case JSON_TOKEN_COMMA
:
2824 if (current
->expect
== EXPECT_OBJECT_COMMA
)
2825 current
->expect
= EXPECT_OBJECT_NEXT_KEY
;
2826 else if (current
->expect
== EXPECT_ARRAY_COMMA
)
2827 current
->expect
= EXPECT_ARRAY_NEXT_ELEMENT
;
2835 case JSON_TOKEN_OBJECT_OPEN
:
2837 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2842 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
2846 current
= stack
+ n_stack
- 1;
2848 /* Prepare the expect for when we return from the child */
2849 if (current
->expect
== EXPECT_TOPLEVEL
)
2850 current
->expect
= EXPECT_END
;
2851 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2852 current
->expect
= EXPECT_OBJECT_COMMA
;
2854 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2855 current
->expect
= EXPECT_ARRAY_COMMA
;
2858 stack
[n_stack
++] = (JsonStack
) {
2859 .expect
= EXPECT_OBJECT_FIRST_KEY
,
2860 .line_before
= line_token
,
2861 .column_before
= column_token
,
2864 current
= stack
+ n_stack
- 1;
2867 case JSON_TOKEN_OBJECT_CLOSE
:
2868 if (!IN_SET(current
->expect
, EXPECT_OBJECT_FIRST_KEY
, EXPECT_OBJECT_COMMA
)) {
2873 assert(n_stack
> 1);
2875 r
= json_variant_new_object(&add
, current
->elements
, current
->n_elements
);
2879 line_token
= current
->line_before
;
2880 column_token
= current
->column_before
;
2882 json_stack_release(current
);
2883 n_stack
--, current
--;
2887 case JSON_TOKEN_ARRAY_OPEN
:
2888 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2893 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
2897 current
= stack
+ n_stack
- 1;
2899 /* Prepare the expect for when we return from the child */
2900 if (current
->expect
== EXPECT_TOPLEVEL
)
2901 current
->expect
= EXPECT_END
;
2902 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2903 current
->expect
= EXPECT_OBJECT_COMMA
;
2905 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2906 current
->expect
= EXPECT_ARRAY_COMMA
;
2909 stack
[n_stack
++] = (JsonStack
) {
2910 .expect
= EXPECT_ARRAY_FIRST_ELEMENT
,
2911 .line_before
= line_token
,
2912 .column_before
= column_token
,
2917 case JSON_TOKEN_ARRAY_CLOSE
:
2918 if (!IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_COMMA
)) {
2923 assert(n_stack
> 1);
2925 r
= json_variant_new_array(&add
, current
->elements
, current
->n_elements
);
2929 line_token
= current
->line_before
;
2930 column_token
= current
->column_before
;
2932 json_stack_release(current
);
2933 n_stack
--, current
--;
2936 case JSON_TOKEN_STRING
:
2937 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
)) {
2942 r
= json_variant_new_string(&add
, string
);
2946 if (current
->expect
== EXPECT_TOPLEVEL
)
2947 current
->expect
= EXPECT_END
;
2948 else if (IN_SET(current
->expect
, EXPECT_OBJECT_FIRST_KEY
, EXPECT_OBJECT_NEXT_KEY
))
2949 current
->expect
= EXPECT_OBJECT_COLON
;
2950 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2951 current
->expect
= EXPECT_OBJECT_COMMA
;
2953 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2954 current
->expect
= EXPECT_ARRAY_COMMA
;
2959 case JSON_TOKEN_REAL
:
2960 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2965 r
= json_variant_new_real(&add
, value
.real
);
2969 if (current
->expect
== EXPECT_TOPLEVEL
)
2970 current
->expect
= EXPECT_END
;
2971 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2972 current
->expect
= EXPECT_OBJECT_COMMA
;
2974 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2975 current
->expect
= EXPECT_ARRAY_COMMA
;
2980 case JSON_TOKEN_INTEGER
:
2981 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
2986 r
= json_variant_new_integer(&add
, value
.integer
);
2990 if (current
->expect
== EXPECT_TOPLEVEL
)
2991 current
->expect
= EXPECT_END
;
2992 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
2993 current
->expect
= EXPECT_OBJECT_COMMA
;
2995 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
2996 current
->expect
= EXPECT_ARRAY_COMMA
;
3001 case JSON_TOKEN_UNSIGNED
:
3002 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
3007 r
= json_variant_new_unsigned(&add
, value
.unsig
);
3011 if (current
->expect
== EXPECT_TOPLEVEL
)
3012 current
->expect
= EXPECT_END
;
3013 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3014 current
->expect
= EXPECT_OBJECT_COMMA
;
3016 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
3017 current
->expect
= EXPECT_ARRAY_COMMA
;
3022 case JSON_TOKEN_BOOLEAN
:
3023 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
3028 r
= json_variant_new_boolean(&add
, value
.boolean
);
3032 if (current
->expect
== EXPECT_TOPLEVEL
)
3033 current
->expect
= EXPECT_END
;
3034 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3035 current
->expect
= EXPECT_OBJECT_COMMA
;
3037 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
3038 current
->expect
= EXPECT_ARRAY_COMMA
;
3043 case JSON_TOKEN_NULL
:
3044 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
)) {
3049 r
= json_variant_new_null(&add
);
3053 if (current
->expect
== EXPECT_TOPLEVEL
)
3054 current
->expect
= EXPECT_END
;
3055 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3056 current
->expect
= EXPECT_OBJECT_COMMA
;
3058 assert(IN_SET(current
->expect
, EXPECT_ARRAY_FIRST_ELEMENT
, EXPECT_ARRAY_NEXT_ELEMENT
));
3059 current
->expect
= EXPECT_ARRAY_COMMA
;
3065 assert_not_reached("Unexpected token");
3069 /* If we are asked to make this parsed object sensitive, then let's apply this
3070 * immediately after allocating each variant, so that when we abort half-way
3071 * everything we already allocated that is then freed is correctly marked. */
3072 if (FLAGS_SET(flags
, JSON_PARSE_SENSITIVE
))
3073 json_variant_sensitive(add
);
3075 (void) json_variant_set_source(&add
, source
, line_token
, column_token
);
3077 if (!GREEDY_REALLOC(current
->elements
, current
->n_elements_allocated
, current
->n_elements
+ 1)) {
3082 current
->elements
[current
->n_elements
++] = TAKE_PTR(add
);
3087 assert(n_stack
== 1);
3088 assert(stack
[0].n_elements
== 1);
3090 *ret
= json_variant_ref(stack
[0].elements
[0]);
3095 for (i
= 0; i
< n_stack
; i
++)
3096 json_stack_release(stack
+ i
);
3103 int json_parse(const char *input
, JsonParseFlags flags
, JsonVariant
**ret
, unsigned *ret_line
, unsigned *ret_column
) {
3104 return json_parse_internal(&input
, NULL
, flags
, ret
, ret_line
, ret_column
, false);
3107 int json_parse_continue(const char **p
, JsonParseFlags flags
, JsonVariant
**ret
, unsigned *ret_line
, unsigned *ret_column
) {
3108 return json_parse_internal(p
, NULL
, flags
, ret
, ret_line
, ret_column
, true);
3111 int json_parse_file_at(FILE *f
, int dir_fd
, const char *path
, JsonParseFlags flags
, JsonVariant
**ret
, unsigned *ret_line
, unsigned *ret_column
) {
3112 _cleanup_(json_source_unrefp
) JsonSource
*source
= NULL
;
3113 _cleanup_free_
char *text
= NULL
;
3118 r
= read_full_stream(f
, &text
, NULL
);
3120 r
= read_full_file_full(dir_fd
, path
, 0, &text
, NULL
);
3127 source
= json_source_new(path
);
3133 return json_parse_internal(&p
, source
, flags
, ret
, ret_line
, ret_column
, false);
3136 int json_buildv(JsonVariant
**ret
, va_list ap
) {
3137 JsonStack
*stack
= NULL
;
3138 size_t n_stack
= 1, n_stack_allocated
= 0, i
;
3141 assert_return(ret
, -EINVAL
);
3143 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
))
3146 stack
[0] = (JsonStack
) {
3147 .expect
= EXPECT_TOPLEVEL
,
3151 _cleanup_(json_variant_unrefp
) JsonVariant
*add
= NULL
;
3152 size_t n_subtract
= 0; /* how much to subtract from current->n_suppress, i.e. how many elements would
3153 * have been added to the current variant */
3157 assert(n_stack
> 0);
3158 current
= stack
+ n_stack
- 1;
3160 if (current
->expect
== EXPECT_END
)
3163 command
= va_arg(ap
, int);
3167 case _JSON_BUILD_STRING
: {
3170 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3175 p
= va_arg(ap
, const char *);
3177 if (current
->n_suppress
== 0) {
3178 r
= json_variant_new_string(&add
, p
);
3185 if (current
->expect
== EXPECT_TOPLEVEL
)
3186 current
->expect
= EXPECT_END
;
3187 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3188 current
->expect
= EXPECT_OBJECT_KEY
;
3190 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3195 case _JSON_BUILD_INTEGER
: {
3198 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3203 j
= va_arg(ap
, intmax_t);
3205 if (current
->n_suppress
== 0) {
3206 r
= json_variant_new_integer(&add
, j
);
3213 if (current
->expect
== EXPECT_TOPLEVEL
)
3214 current
->expect
= EXPECT_END
;
3215 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3216 current
->expect
= EXPECT_OBJECT_KEY
;
3218 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3223 case _JSON_BUILD_UNSIGNED
: {
3226 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3231 j
= va_arg(ap
, uintmax_t);
3233 if (current
->n_suppress
== 0) {
3234 r
= json_variant_new_unsigned(&add
, j
);
3241 if (current
->expect
== EXPECT_TOPLEVEL
)
3242 current
->expect
= EXPECT_END
;
3243 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3244 current
->expect
= EXPECT_OBJECT_KEY
;
3246 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3251 case _JSON_BUILD_REAL
: {
3254 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3259 d
= va_arg(ap
, long double);
3261 if (current
->n_suppress
== 0) {
3262 r
= json_variant_new_real(&add
, d
);
3269 if (current
->expect
== EXPECT_TOPLEVEL
)
3270 current
->expect
= EXPECT_END
;
3271 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3272 current
->expect
= EXPECT_OBJECT_KEY
;
3274 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3279 case _JSON_BUILD_BOOLEAN
: {
3282 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3287 b
= va_arg(ap
, int);
3289 if (current
->n_suppress
== 0) {
3290 r
= json_variant_new_boolean(&add
, b
);
3297 if (current
->expect
== EXPECT_TOPLEVEL
)
3298 current
->expect
= EXPECT_END
;
3299 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3300 current
->expect
= EXPECT_OBJECT_KEY
;
3302 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3307 case _JSON_BUILD_NULL
:
3309 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3314 if (current
->n_suppress
== 0) {
3315 r
= json_variant_new_null(&add
);
3322 if (current
->expect
== EXPECT_TOPLEVEL
)
3323 current
->expect
= EXPECT_END
;
3324 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3325 current
->expect
= EXPECT_OBJECT_KEY
;
3327 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3331 case _JSON_BUILD_VARIANT
:
3333 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3338 /* Note that we don't care for current->n_suppress here, after all the variant is already
3339 * allocated anyway... */
3340 add
= va_arg(ap
, JsonVariant
*);
3342 add
= JSON_VARIANT_MAGIC_NULL
;
3344 json_variant_ref(add
);
3348 if (current
->expect
== EXPECT_TOPLEVEL
)
3349 current
->expect
= EXPECT_END
;
3350 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3351 current
->expect
= EXPECT_OBJECT_KEY
;
3353 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3357 case _JSON_BUILD_LITERAL
: {
3360 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3365 l
= va_arg(ap
, const char *);
3368 /* Note that we don't care for current->n_suppress here, we should generate parsing
3369 * errors even in suppressed object properties */
3371 r
= json_parse(l
, 0, &add
, NULL
, NULL
);
3375 add
= JSON_VARIANT_MAGIC_NULL
;
3379 if (current
->expect
== EXPECT_TOPLEVEL
)
3380 current
->expect
= EXPECT_END
;
3381 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3382 current
->expect
= EXPECT_OBJECT_KEY
;
3384 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3389 case _JSON_BUILD_ARRAY_BEGIN
:
3391 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3396 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
3400 current
= stack
+ n_stack
- 1;
3402 if (current
->expect
== EXPECT_TOPLEVEL
)
3403 current
->expect
= EXPECT_END
;
3404 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3405 current
->expect
= EXPECT_OBJECT_KEY
;
3407 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3409 stack
[n_stack
++] = (JsonStack
) {
3410 .expect
= EXPECT_ARRAY_ELEMENT
,
3411 .n_suppress
= current
->n_suppress
!= 0 ? (size_t) -1 : 0, /* if we shall suppress the
3412 * new array, then we should
3413 * also suppress all array
3419 case _JSON_BUILD_ARRAY_END
:
3420 if (current
->expect
!= EXPECT_ARRAY_ELEMENT
) {
3425 assert(n_stack
> 1);
3427 if (current
->n_suppress
== 0) {
3428 r
= json_variant_new_array(&add
, current
->elements
, current
->n_elements
);
3435 json_stack_release(current
);
3436 n_stack
--, current
--;
3440 case _JSON_BUILD_STRV
: {
3443 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3448 l
= va_arg(ap
, char **);
3450 if (current
->n_suppress
== 0) {
3451 r
= json_variant_new_array_strv(&add
, l
);
3458 if (current
->expect
== EXPECT_TOPLEVEL
)
3459 current
->expect
= EXPECT_END
;
3460 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3461 current
->expect
= EXPECT_OBJECT_KEY
;
3463 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3468 case _JSON_BUILD_BASE64
: {
3472 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3477 p
= va_arg(ap
, const void *);
3478 n
= va_arg(ap
, size_t);
3480 if (current
->n_suppress
== 0) {
3481 r
= json_variant_new_base64(&add
, p
, n
);
3488 if (current
->expect
== EXPECT_TOPLEVEL
)
3489 current
->expect
= EXPECT_END
;
3490 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3491 current
->expect
= EXPECT_OBJECT_KEY
;
3493 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3498 case _JSON_BUILD_OBJECT_BEGIN
:
3500 if (!IN_SET(current
->expect
, EXPECT_TOPLEVEL
, EXPECT_OBJECT_VALUE
, EXPECT_ARRAY_ELEMENT
)) {
3505 if (!GREEDY_REALLOC(stack
, n_stack_allocated
, n_stack
+1)) {
3509 current
= stack
+ n_stack
- 1;
3511 if (current
->expect
== EXPECT_TOPLEVEL
)
3512 current
->expect
= EXPECT_END
;
3513 else if (current
->expect
== EXPECT_OBJECT_VALUE
)
3514 current
->expect
= EXPECT_OBJECT_KEY
;
3516 assert(current
->expect
== EXPECT_ARRAY_ELEMENT
);
3518 stack
[n_stack
++] = (JsonStack
) {
3519 .expect
= EXPECT_OBJECT_KEY
,
3520 .n_suppress
= current
->n_suppress
!= 0 ? (size_t) -1 : 0, /* if we shall suppress the
3521 * new object, then we should
3522 * also suppress all object
3528 case _JSON_BUILD_OBJECT_END
:
3530 if (current
->expect
!= EXPECT_OBJECT_KEY
) {
3535 assert(n_stack
> 1);
3537 if (current
->n_suppress
== 0) {
3538 r
= json_variant_new_object(&add
, current
->elements
, current
->n_elements
);
3545 json_stack_release(current
);
3546 n_stack
--, current
--;
3550 case _JSON_BUILD_PAIR
: {
3553 if (current
->expect
!= EXPECT_OBJECT_KEY
) {
3558 n
= va_arg(ap
, const char *);
3560 if (current
->n_suppress
== 0) {
3561 r
= json_variant_new_string(&add
, n
);
3568 current
->expect
= EXPECT_OBJECT_VALUE
;
3572 case _JSON_BUILD_PAIR_CONDITION
: {
3576 if (current
->expect
!= EXPECT_OBJECT_KEY
) {
3581 b
= va_arg(ap
, int);
3582 n
= va_arg(ap
, const char *);
3584 if (b
&& current
->n_suppress
== 0) {
3585 r
= json_variant_new_string(&add
, n
);
3590 n_subtract
= 1; /* we generated one item */
3592 if (!b
&& current
->n_suppress
!= (size_t) -1)
3593 current
->n_suppress
+= 2; /* Suppress this one and the next item */
3595 current
->expect
= EXPECT_OBJECT_VALUE
;
3599 /* If a variant was generated, add it to our current variant, but only if we are not supposed to suppress additions */
3600 if (add
&& current
->n_suppress
== 0) {
3601 if (!GREEDY_REALLOC(current
->elements
, current
->n_elements_allocated
, current
->n_elements
+ 1)) {
3606 current
->elements
[current
->n_elements
++] = TAKE_PTR(add
);
3609 /* If we are supposed to suppress items, let's subtract how many items where generated from that
3610 * counter. Except if the counter is (size_t) -1, i.e. we shall suppress an infinite number of elements
3611 * on this stack level */
3612 if (current
->n_suppress
!= (size_t) -1) {
3613 if (current
->n_suppress
<= n_subtract
) /* Saturated */
3614 current
->n_suppress
= 0;
3616 current
->n_suppress
-= n_subtract
;
3621 assert(n_stack
== 1);
3622 assert(stack
[0].n_elements
== 1);
3624 *ret
= json_variant_ref(stack
[0].elements
[0]);
3628 for (i
= 0; i
< n_stack
; i
++)
3629 json_stack_release(stack
+ i
);
3636 int json_build(JsonVariant
**ret
, ...) {
3641 r
= json_buildv(ret
, ap
);
3647 int json_log_internal(
3648 JsonVariant
*variant
,
3654 const char *format
, ...) {
3658 unsigned source_line
, source_column
;
3659 char buffer
[LINE_MAX
];
3664 errno
= ERRNO_VALUE(error
);
3666 va_start(ap
, format
);
3667 (void) vsnprintf(buffer
, sizeof buffer
, format
, ap
);
3671 r
= json_variant_get_source(variant
, &source
, &source_line
, &source_column
);
3680 if (source
&& source_line
> 0 && source_column
> 0)
3681 return log_struct_internal(
3682 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD
, level
),
3685 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR
,
3686 "CONFIG_FILE=%s", source
,
3687 "CONFIG_LINE=%u", source_line
,
3688 "CONFIG_COLUMN=%u", source_column
,
3689 LOG_MESSAGE("%s:%u:%u: %s", source
, source_line
, source_column
, buffer
),
3692 return log_struct_internal(
3693 LOG_REALM_PLUS_LEVEL(LOG_REALM_SYSTEMD
, level
),
3696 "MESSAGE_ID=" SD_MESSAGE_INVALID_CONFIGURATION_STR
,
3697 LOG_MESSAGE("%s", buffer
),
3701 int json_dispatch(JsonVariant
*v
, const JsonDispatch table
[], JsonDispatchCallback bad
, JsonDispatchFlags flags
, void *userdata
) {
3702 const JsonDispatch
*p
;
3707 if (!json_variant_is_object(v
)) {
3708 json_log(v
, flags
, 0, "JSON variant is not an object.");
3710 if (flags
& JSON_PERMISSIVE
)
3716 for (p
= table
, m
= 0; p
->name
; p
++)
3719 found
= newa0(bool, m
);
3721 n
= json_variant_elements(v
);
3722 for (i
= 0; i
< n
; i
+= 2) {
3723 JsonVariant
*key
, *value
;
3725 assert_se(key
= json_variant_by_index(v
, i
));
3726 assert_se(value
= json_variant_by_index(v
, i
+1));
3728 for (p
= table
; p
->name
; p
++)
3729 if (p
->name
== (const char*) -1 ||
3730 streq_ptr(json_variant_string(key
), p
->name
))
3733 if (p
->name
) { /* Found a matching entry! :-) */
3734 JsonDispatchFlags merged_flags
;
3736 merged_flags
= flags
| p
->flags
;
3738 if (p
->type
!= _JSON_VARIANT_TYPE_INVALID
&&
3739 !json_variant_has_type(value
, p
->type
)) {
3741 json_log(value
, merged_flags
, 0,
3742 "Object field '%s' has wrong type %s, expected %s.", json_variant_string(key
),
3743 json_variant_type_to_string(json_variant_type(value
)), json_variant_type_to_string(p
->type
));
3745 if (merged_flags
& JSON_PERMISSIVE
)
3751 if (found
[p
-table
]) {
3752 json_log(value
, merged_flags
, 0, "Duplicate object field '%s'.", json_variant_string(key
));
3754 if (merged_flags
& JSON_PERMISSIVE
)
3760 found
[p
-table
] = true;
3763 r
= p
->callback(json_variant_string(key
), value
, merged_flags
, (uint8_t*) userdata
+ p
->offset
);
3765 if (merged_flags
& JSON_PERMISSIVE
)
3774 } else { /* Didn't find a matching entry! :-( */
3777 r
= bad(json_variant_string(key
), value
, flags
, userdata
);
3779 if (flags
& JSON_PERMISSIVE
)
3787 json_log(value
, flags
, 0, "Unexpected object field '%s'.", json_variant_string(key
));
3789 if (flags
& JSON_PERMISSIVE
)
3792 return -EADDRNOTAVAIL
;
3797 for (p
= table
; p
->name
; p
++) {
3798 JsonDispatchFlags merged_flags
= p
->flags
| flags
;
3800 if ((merged_flags
& JSON_MANDATORY
) && !found
[p
-table
]) {
3801 json_log(v
, merged_flags
, 0, "Missing object field '%s'.", p
->name
);
3803 if ((merged_flags
& JSON_PERMISSIVE
))
3813 int json_dispatch_boolean(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3819 if (!json_variant_is_boolean(variant
))
3820 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not a boolean.", strna(name
));
3822 *b
= json_variant_boolean(variant
);
3826 int json_dispatch_tristate(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3832 if (json_variant_is_null(variant
)) {
3837 if (!json_variant_is_boolean(variant
))
3838 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not a boolean.", strna(name
));
3840 *b
= json_variant_boolean(variant
);
3844 int json_dispatch_integer(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3845 intmax_t *i
= userdata
;
3850 if (!json_variant_is_integer(variant
))
3851 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not an integer.", strna(name
));
3853 *i
= json_variant_integer(variant
);
3857 int json_dispatch_unsigned(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3858 uintmax_t *u
= userdata
;
3863 if (!json_variant_is_unsigned(variant
))
3864 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not an unsigned integer.", strna(name
));
3866 *u
= json_variant_unsigned(variant
);
3870 int json_dispatch_uint32(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3871 uint32_t *u
= userdata
;
3876 if (!json_variant_is_unsigned(variant
))
3877 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not an unsigned integer.", strna(name
));
3879 if (json_variant_unsigned(variant
) > UINT32_MAX
)
3880 return json_log(variant
, flags
, SYNTHETIC_ERRNO(ERANGE
), "JSON field '%s' out of bounds.", strna(name
));
3882 *u
= (uint32_t) json_variant_unsigned(variant
);
3886 int json_dispatch_int32(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3887 int32_t *i
= userdata
;
3892 if (!json_variant_is_integer(variant
))
3893 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not an integer.", strna(name
));
3895 if (json_variant_integer(variant
) < INT32_MIN
|| json_variant_integer(variant
) > INT32_MAX
)
3896 return json_log(variant
, flags
, SYNTHETIC_ERRNO(ERANGE
), "JSON field '%s' out of bounds.", strna(name
));
3898 *i
= (int32_t) json_variant_integer(variant
);
3902 int json_dispatch_string(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3903 char **s
= userdata
;
3909 if (json_variant_is_null(variant
)) {
3914 if (!json_variant_is_string(variant
))
3915 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' is not a string.", strna(name
));
3917 if ((flags
& JSON_SAFE
) && !string_is_safe(json_variant_string(variant
)))
3918 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' contains unsafe characters, refusing.", strna(name
));
3920 r
= free_and_strdup(s
, json_variant_string(variant
));
3922 return json_log(variant
, flags
, r
, "Failed to allocate string: %m");
3927 int json_dispatch_strv(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3928 _cleanup_strv_free_
char **l
= NULL
;
3929 char ***s
= userdata
;
3936 if (json_variant_is_null(variant
)) {
3941 /* Let's be flexible here: accept a single string in place of a single-item array */
3942 if (json_variant_is_string(variant
)) {
3943 if ((flags
& JSON_SAFE
) && !string_is_safe(json_variant_string(variant
)))
3944 return json_log(variant
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' contains unsafe characters, refusing.", strna(name
));
3946 l
= strv_new(json_variant_string(variant
));
3950 strv_free_and_replace(*s
, l
);
3954 if (!json_variant_is_array(variant
))
3955 return json_log(variant
, SYNTHETIC_ERRNO(EINVAL
), flags
, "JSON field '%s' is not an array.", strna(name
));
3957 JSON_VARIANT_ARRAY_FOREACH(e
, variant
) {
3958 if (!json_variant_is_string(e
))
3959 return json_log(e
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON array element is not a string.");
3961 if ((flags
& JSON_SAFE
) && !string_is_safe(json_variant_string(e
)))
3962 return json_log(e
, flags
, SYNTHETIC_ERRNO(EINVAL
), "JSON field '%s' contains unsafe characters, refusing.", strna(name
));
3964 r
= strv_extend(&l
, json_variant_string(e
));
3966 return json_log(e
, flags
, r
, "Failed to append array element: %m");
3969 strv_free_and_replace(*s
, l
);
3973 int json_dispatch_variant(const char *name
, JsonVariant
*variant
, JsonDispatchFlags flags
, void *userdata
) {
3974 JsonVariant
**p
= userdata
;
3979 json_variant_unref(*p
);
3980 *p
= json_variant_ref(variant
);
3985 static int json_cmp_strings(const void *x
, const void *y
) {
3986 JsonVariant
*const *a
= x
, *const *b
= y
;
3988 if (!json_variant_is_string(*a
) || !json_variant_is_string(*b
))
3991 return strcmp(json_variant_string(*a
), json_variant_string(*b
));
3994 int json_variant_sort(JsonVariant
**v
) {
3995 _cleanup_free_ JsonVariant
**a
= NULL
;
3996 JsonVariant
*n
= NULL
;
4002 if (json_variant_is_sorted(*v
))
4005 if (!json_variant_is_object(*v
))
4006 return -EMEDIUMTYPE
;
4008 /* Sorts they key/value pairs in an object variant */
4010 m
= json_variant_elements(*v
);
4011 a
= new(JsonVariant
*, m
);
4015 for (i
= 0; i
< m
; i
++)
4016 a
[i
] = json_variant_by_index(*v
, i
);
4018 qsort(a
, m
/2, sizeof(JsonVariant
*)*2, json_cmp_strings
);
4020 r
= json_variant_new_object(&n
, a
, m
);
4023 if (!n
->sorted
) /* Check if this worked. This will fail if there are multiple identical keys used. */
4026 json_variant_unref(*v
);
4032 int json_variant_normalize(JsonVariant
**v
) {
4033 _cleanup_free_ JsonVariant
**a
= NULL
;
4034 JsonVariant
*n
= NULL
;
4040 if (json_variant_is_normalized(*v
))
4043 if (!json_variant_is_object(*v
) && !json_variant_is_array(*v
))
4044 return -EMEDIUMTYPE
;
4046 /* Sorts the key/value pairs in an object variant anywhere down the tree in the specified variant */
4048 m
= json_variant_elements(*v
);
4049 a
= new(JsonVariant
*, m
);
4053 for (i
= 0; i
< m
; i
++) {
4054 a
[i
] = json_variant_ref(json_variant_by_index(*v
, i
));
4056 r
= json_variant_normalize(a
+ i
);
4061 qsort(a
, m
/2, sizeof(JsonVariant
*)*2, json_cmp_strings
);
4063 if (json_variant_is_object(*v
))
4064 r
= json_variant_new_object(&n
, a
, m
);
4066 assert(json_variant_is_array(*v
));
4067 r
= json_variant_new_array(&n
, a
, m
);
4071 if (!n
->normalized
) { /* Let's see if normalization worked. It will fail if there are multiple
4072 * identical keys used in the same object anywhere, or if there are floating
4073 * point numbers used (see below) */
4078 json_variant_unref(*v
);
4084 for (j
= 0; j
< i
; j
++)
4085 json_variant_unref(a
[j
]);
4090 bool json_variant_is_normalized(JsonVariant
*v
) {
4092 /* For now, let's consider anything containing numbers not expressible as integers as
4093 * non-normalized. That's because we cannot sensibly compare them due to accuracy issues, nor even
4094 * store them if they are too large. */
4095 if (json_variant_is_real(v
) && !json_variant_is_integer(v
) && !json_variant_is_unsigned(v
))
4098 /* The concept only applies to variants that include other variants, i.e. objects and arrays. All
4099 * others are normalized anyway. */
4100 if (!json_variant_is_object(v
) && !json_variant_is_array(v
))
4103 /* Empty objects/arrays don't include any other variant, hence are always normalized too */
4104 if (json_variant_elements(v
) == 0)
4107 return v
->normalized
; /* For everything else there's an explicit boolean we maintain */
4110 bool json_variant_is_sorted(JsonVariant
*v
) {
4112 /* Returns true if all key/value pairs of an object are properly sorted. Note that this only applies
4113 * to objects, not arrays. */
4115 if (!json_variant_is_object(v
))
4117 if (json_variant_elements(v
) <= 1)
4123 int json_variant_unbase64(JsonVariant
*v
, void **ret
, size_t *ret_size
) {
4125 if (!json_variant_is_string(v
))
4128 return unbase64mem(json_variant_string(v
), (size_t) -1, ret
, ret_size
);
4131 static const char* const json_variant_type_table
[_JSON_VARIANT_TYPE_MAX
] = {
4132 [JSON_VARIANT_STRING
] = "string",
4133 [JSON_VARIANT_INTEGER
] = "integer",
4134 [JSON_VARIANT_UNSIGNED
] = "unsigned",
4135 [JSON_VARIANT_REAL
] = "real",
4136 [JSON_VARIANT_NUMBER
] = "number",
4137 [JSON_VARIANT_BOOLEAN
] = "boolean",
4138 [JSON_VARIANT_ARRAY
] = "array",
4139 [JSON_VARIANT_OBJECT
] = "object",
4140 [JSON_VARIANT_NULL
] = "null",
4143 DEFINE_STRING_TABLE_LOOKUP(json_variant_type
, JsonVariantType
);