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