LCOV - code coverage report
Current view: top level - shared - json.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 1380 1918 71.9 %
Date: 2019-08-22 15:41:25 Functions: 59 75 78.7 %

          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);

Generated by: LCOV version 1.14