LCOV - code coverage report
Current view: top level - shared - json.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 1380 1918 71.9 %
Date: 2019-08-23 13:36:53 Functions: 59 75 78.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 934 1656 56.4 %

           Branch data     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                 :          4 : static JsonSource* json_source_new(const char *name) {
     115                 :            :         JsonSource *s;
     116                 :            : 
     117         [ -  + ]:          4 :         assert(name);
     118                 :            : 
     119                 :          4 :         s = malloc(offsetof(JsonSource, name) + strlen(name) + 1);
     120         [ -  + ]:          4 :         if (!s)
     121                 :          0 :                 return NULL;
     122                 :            : 
     123                 :          4 :         *s = (JsonSource) {
     124                 :            :                 .n_ref = 1,
     125                 :            :         };
     126                 :          4 :         strcpy(s->name, name);
     127                 :            : 
     128                 :          4 :         return s;
     129                 :            : }
     130                 :            : 
     131   [ +  +  -  +  :     114640 : DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(JsonSource, json_source, mfree);
                   +  + ]
     132                 :            : 
     133                 :       4772 : static bool json_source_equal(JsonSource *a, JsonSource *b) {
     134         [ +  + ]:       4772 :         if (a == b)
     135                 :       4704 :                 return true;
     136                 :            : 
     137   [ -  +  #  # ]:         68 :         if (!a || !b)
     138                 :         68 :                 return false;
     139                 :            : 
     140                 :          0 :         return streq(a->name, b->name);
     141                 :            : }
     142                 :            : 
     143         [ +  - ]:          4 : 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                 :      51668 : static bool json_variant_is_magic(const JsonVariant *v) {
     163         [ -  + ]:      51668 :         if (!v)
     164                 :          0 :                 return false;
     165                 :            : 
     166                 :      51668 :         return v < _JSON_VARIANT_MAGIC_MAX;
     167                 :            : }
     168                 :            : 
     169                 :     210448 : static bool json_variant_is_const_string(const JsonVariant *v) {
     170                 :            : 
     171         [ +  + ]:     210448 :         if (v < _JSON_VARIANT_MAGIC_MAX)
     172                 :       4112 :                 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                 :     206336 :         return (((uintptr_t) v) & 1) != 0;
     178                 :            : }
     179                 :            : 
     180                 :     597752 : static bool json_variant_is_regular(const JsonVariant *v) {
     181                 :            : 
     182         [ +  + ]:     597752 :         if (v < _JSON_VARIANT_MAGIC_MAX)
     183                 :       8688 :                 return false;
     184                 :            : 
     185                 :     589064 :         return (((uintptr_t) v) & 1) == 0;
     186                 :            : }
     187                 :            : 
     188                 :     179072 : static JsonVariant *json_variant_dereference(JsonVariant *v) {
     189                 :            : 
     190                 :            :         /* Recursively dereference variants that are references to other variants */
     191                 :            : 
     192         [ -  + ]:     179072 :         if (!v)
     193                 :          0 :                 return NULL;
     194                 :            : 
     195         [ +  + ]:     179072 :         if (!json_variant_is_regular(v))
     196                 :      27620 :                 return v;
     197                 :            : 
     198         [ +  + ]:     151452 :         if (!v->is_reference)
     199                 :     132400 :                 return v;
     200                 :            : 
     201                 :      19052 :         return json_variant_dereference(v->reference);
     202                 :            : }
     203                 :            : 
     204                 :      40500 : static uint16_t json_variant_depth(JsonVariant *v) {
     205                 :            : 
     206                 :      40500 :         v = json_variant_dereference(v);
     207         [ -  + ]:      40500 :         if (!v)
     208                 :          0 :                 return 0;
     209                 :            : 
     210         [ +  + ]:      40500 :         if (!json_variant_is_regular(v))
     211                 :       9592 :                 return 0;
     212                 :            : 
     213                 :      30908 :         return v->depth;
     214                 :            : }
     215                 :            : 
     216                 :      55852 : 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         [ -  + ]:      55852 :         if (!v)
     222                 :          0 :                 return NULL;
     223                 :            : 
     224                 :      55852 :         v = json_variant_dereference(v);
     225                 :            : 
     226   [ +  +  +  +  :      55852 :         switch (json_variant_type(v)) {
             +  +  +  +  
                      - ]
     227                 :            : 
     228                 :       1352 :         case JSON_VARIANT_BOOLEAN:
     229         [ +  - ]:       1352 :                 return json_variant_boolean(v) ? JSON_VARIANT_MAGIC_TRUE : JSON_VARIANT_MAGIC_FALSE;
     230                 :            : 
     231                 :        112 :         case JSON_VARIANT_NULL:
     232                 :        112 :                 return JSON_VARIANT_MAGIC_NULL;
     233                 :            : 
     234                 :       1512 :         case JSON_VARIANT_INTEGER:
     235         [ +  + ]:       1512 :                 return json_variant_integer(v) == 0 ? JSON_VARIANT_MAGIC_ZERO_INTEGER : v;
     236                 :            : 
     237                 :        204 :         case JSON_VARIANT_UNSIGNED:
     238         [ +  + ]:        204 :                 return json_variant_unsigned(v) == 0 ? JSON_VARIANT_MAGIC_ZERO_UNSIGNED : v;
     239                 :            : 
     240                 :       1364 :         case JSON_VARIANT_REAL:
     241                 :            : #pragma GCC diagnostic push
     242                 :            : #pragma GCC diagnostic ignored "-Wfloat-equal"
     243         [ +  + ]:       1364 :                 return json_variant_real(v) == 0.0 ? JSON_VARIANT_MAGIC_ZERO_REAL : v;
     244                 :            : #pragma GCC diagnostic pop
     245                 :            : 
     246                 :      15568 :         case JSON_VARIANT_STRING:
     247         [ +  - ]:      15568 :                 return isempty(json_variant_string(v)) ? JSON_VARIANT_MAGIC_EMPTY_STRING : v;
     248                 :            : 
     249                 :      16488 :         case JSON_VARIANT_ARRAY:
     250         [ +  - ]:      16488 :                 return json_variant_elements(v) == 0 ? JSON_VARIANT_MAGIC_EMPTY_ARRAY : v;
     251                 :            : 
     252                 :      19252 :         case JSON_VARIANT_OBJECT:
     253         [ +  + ]:      19252 :                 return json_variant_elements(v) == 0 ? JSON_VARIANT_MAGIC_EMPTY_OBJECT : v;
     254                 :            : 
     255                 :          0 :         default:
     256                 :          0 :                 return v;
     257                 :            :         }
     258                 :            : }
     259                 :            : 
     260                 :      59728 : 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         [ -  + ]:      59728 :         if (!v)
     266                 :          0 :                 return NULL;
     267                 :            : 
     268         [ +  + ]:      59728 :         if (!json_variant_is_regular(v))
     269                 :         12 :                 return v;
     270                 :            : 
     271   [ +  +  +  +  :      59716 :         if (v->source || v->line > 0 || v->column > 0)
                   -  + ]
     272                 :       6216 :                 return v;
     273                 :            : 
     274                 :      53500 :         return json_variant_normalize(v);
     275                 :            : }
     276                 :            : 
     277                 :      11804 : static int json_variant_new(JsonVariant **ret, JsonVariantType type, size_t space) {
     278                 :            :         JsonVariant *v;
     279                 :            : 
     280   [ -  +  -  + ]:      11804 :         assert_return(ret, -EINVAL);
     281                 :            : 
     282                 :      11804 :         v = malloc0(MAX(sizeof(JsonVariant),
     283                 :            :                         offsetof(JsonVariant, value) + space));
     284         [ -  + ]:      11804 :         if (!v)
     285                 :          0 :                 return -ENOMEM;
     286                 :            : 
     287                 :      11804 :         v->n_ref = 1;
     288                 :      11804 :         v->type = type;
     289                 :            : 
     290                 :      11804 :         *ret = v;
     291                 :      11804 :         return 0;
     292                 :            : }
     293                 :            : 
     294                 :       1384 : int json_variant_new_integer(JsonVariant **ret, intmax_t i) {
     295                 :            :         JsonVariant *v;
     296                 :            :         int r;
     297                 :            : 
     298   [ -  +  -  + ]:       1384 :         assert_return(ret, -EINVAL);
     299                 :            : 
     300         [ +  + ]:       1384 :         if (i == 0) {
     301                 :         20 :                 *ret = JSON_VARIANT_MAGIC_ZERO_INTEGER;
     302                 :         20 :                 return 0;
     303                 :            :         }
     304                 :            : 
     305                 :       1364 :         r = json_variant_new(&v, JSON_VARIANT_INTEGER, sizeof(i));
     306         [ -  + ]:       1364 :         if (r < 0)
     307                 :          0 :                 return r;
     308                 :            : 
     309                 :       1364 :         v->value.integer = i;
     310                 :       1364 :         *ret = v;
     311                 :            : 
     312                 :       1364 :         return 0;
     313                 :            : }
     314                 :            : 
     315                 :        640 : int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u) {
     316                 :            :         JsonVariant *v;
     317                 :            :         int r;
     318                 :            : 
     319   [ -  +  -  + ]:        640 :         assert_return(ret, -EINVAL);
     320         [ +  + ]:        640 :         if (u == 0) {
     321                 :         16 :                 *ret = JSON_VARIANT_MAGIC_ZERO_UNSIGNED;
     322                 :         16 :                 return 0;
     323                 :            :         }
     324                 :            : 
     325                 :        624 :         r = json_variant_new(&v, JSON_VARIANT_UNSIGNED, sizeof(u));
     326         [ -  + ]:        624 :         if (r < 0)
     327                 :          0 :                 return r;
     328                 :            : 
     329                 :        624 :         v->value.unsig = u;
     330                 :        624 :         *ret = v;
     331                 :            : 
     332                 :        624 :         return 0;
     333                 :            : }
     334                 :            : 
     335                 :        176 : int json_variant_new_real(JsonVariant **ret, long double d) {
     336                 :            :         JsonVariant *v;
     337                 :            :         int r;
     338                 :            : 
     339   [ -  +  -  + ]:        176 :         assert_return(ret, -EINVAL);
     340                 :            : 
     341                 :            : #pragma GCC diagnostic push
     342                 :            : #pragma GCC diagnostic ignored "-Wfloat-equal"
     343         [ +  + ]:        176 :         if (d == 0.0) {
     344                 :            : #pragma GCC diagnostic pop
     345                 :        136 :                 *ret = JSON_VARIANT_MAGIC_ZERO_REAL;
     346                 :        136 :                 return 0;
     347                 :            :         }
     348                 :            : 
     349                 :         40 :         r = json_variant_new(&v, JSON_VARIANT_REAL, sizeof(d));
     350         [ -  + ]:         40 :         if (r < 0)
     351                 :          0 :                 return r;
     352                 :            : 
     353                 :         40 :         v->value.real = d;
     354                 :         40 :         *ret = v;
     355                 :            : 
     356                 :         40 :         return 0;
     357                 :            : }
     358                 :            : 
     359                 :       1872 : int json_variant_new_boolean(JsonVariant **ret, bool b) {
     360   [ -  +  -  + ]:       1872 :         assert_return(ret, -EINVAL);
     361                 :            : 
     362         [ +  + ]:       1872 :         if (b)
     363                 :       1868 :                 *ret = JSON_VARIANT_MAGIC_TRUE;
     364                 :            :         else
     365                 :          4 :                 *ret = JSON_VARIANT_MAGIC_FALSE;
     366                 :            : 
     367                 :       1872 :         return 0;
     368                 :            : }
     369                 :            : 
     370                 :         56 : int json_variant_new_null(JsonVariant **ret) {
     371   [ -  +  -  + ]:         56 :         assert_return(ret, -EINVAL);
     372                 :            : 
     373                 :         56 :         *ret = JSON_VARIANT_MAGIC_NULL;
     374                 :         56 :         return 0;
     375                 :            : }
     376                 :            : 
     377                 :       9780 : int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n) {
     378                 :            :         JsonVariant *v;
     379                 :            :         int r;
     380                 :            : 
     381   [ -  +  -  + ]:       9780 :         assert_return(ret, -EINVAL);
     382         [ +  + ]:       9780 :         if (!s) {
     383   [ +  -  -  +  :          4 :                 assert_return(IN_SET(n, 0, (size_t) -1), -EINVAL);
                   -  + ]
     384                 :          4 :                 return json_variant_new_null(ret);
     385                 :            :         }
     386         [ +  - ]:       9776 :         if (n == (size_t) -1) /* determine length automatically */
     387                 :       9776 :                 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         [ -  + ]:       9776 :         if (n == 0) {
     391                 :          0 :                 *ret = JSON_VARIANT_MAGIC_EMPTY_STRING;
     392                 :          0 :                 return 0;
     393                 :            :         }
     394                 :            : 
     395                 :       9776 :         r = json_variant_new(&v, JSON_VARIANT_STRING, n + 1);
     396         [ -  + ]:       9776 :         if (r < 0)
     397                 :          0 :                 return r;
     398                 :            : 
     399                 :       9776 :         memcpy(v->string, s, n);
     400                 :       9776 :         v->string[n] = 0;
     401                 :            : 
     402                 :       9776 :         *ret = v;
     403                 :       9776 :         return 0;
     404                 :            : }
     405                 :            : 
     406                 :      40496 : static void json_variant_set(JsonVariant *a, JsonVariant *b) {
     407         [ -  + ]:      40496 :         assert(a);
     408                 :            : 
     409                 :      40496 :         b = json_variant_dereference(b);
     410         [ -  + ]:      40496 :         if (!b) {
     411                 :          0 :                 a->type = JSON_VARIANT_NULL;
     412                 :          0 :                 return;
     413                 :            :         }
     414                 :            : 
     415                 :      40496 :         a->type = json_variant_type(b);
     416   [ +  +  +  +  :      40496 :         switch (a->type) {
             +  +  +  - ]
     417                 :            : 
     418                 :       1384 :         case JSON_VARIANT_INTEGER:
     419                 :       1384 :                 a->value.integer = json_variant_integer(b);
     420                 :       1384 :                 break;
     421                 :            : 
     422                 :        640 :         case JSON_VARIANT_UNSIGNED:
     423                 :        640 :                 a->value.unsig = json_variant_unsigned(b);
     424                 :        640 :                 break;
     425                 :            : 
     426                 :        168 :         case JSON_VARIANT_REAL:
     427                 :        168 :                 a->value.real = json_variant_real(b);
     428                 :        168 :                 break;
     429                 :            : 
     430                 :       1872 :         case JSON_VARIANT_BOOLEAN:
     431                 :       1872 :                 a->value.boolean = json_variant_boolean(b);
     432                 :       1872 :                 break;
     433                 :            : 
     434                 :      17972 :         case JSON_VARIANT_STRING: {
     435                 :            :                 const char *s;
     436                 :            : 
     437         [ -  + ]:      17972 :                 assert_se(s = json_variant_string(b));
     438                 :            : 
     439                 :            :                 /* Short strings we can store inline */
     440         [ +  + ]:      17972 :                 if (strnlen(s, INLINE_STRING_MAX+1) <= INLINE_STRING_MAX) {
     441                 :      17904 :                         strcpy(a->string, s);
     442                 :      17904 :                         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                 :      18464 :                 a->is_reference = true;
     452                 :      18464 :                 a->reference = json_variant_ref(json_variant_conservative_normalize(b));
     453                 :      18464 :                 break;
     454                 :            : 
     455                 :         64 :         case JSON_VARIANT_NULL:
     456                 :         64 :                 break;
     457                 :            : 
     458                 :          0 :         default:
     459                 :          0 :                 assert_not_reached("Unexpected variant type");
     460                 :            :         }
     461                 :            : }
     462                 :            : 
     463                 :      40496 : static void json_variant_copy_source(JsonVariant *v, JsonVariant *from) {
     464         [ -  + ]:      40496 :         assert(v);
     465         [ -  + ]:      40496 :         assert(from);
     466                 :            : 
     467         [ +  + ]:      40496 :         if (!json_variant_is_regular(from))
     468                 :       9584 :                 return;
     469                 :            : 
     470                 :      30912 :         v->line = from->line;
     471                 :      30912 :         v->column = from->column;
     472                 :      30912 :         v->source = json_source_ref(from->source);
     473                 :            : }
     474                 :            : 
     475                 :       8268 : int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n) {
     476                 :       8268 :         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
     477                 :            : 
     478   [ -  +  -  + ]:       8268 :         assert_return(ret, -EINVAL);
     479         [ -  + ]:       8268 :         if (n == 0) {
     480                 :          0 :                 *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY;
     481                 :          0 :                 return 0;
     482                 :            :         }
     483   [ -  +  -  + ]:       8268 :         assert_return(array, -EINVAL);
     484                 :            : 
     485                 :       8268 :         v = new(JsonVariant, n + 1);
     486         [ -  + ]:       8268 :         if (!v)
     487                 :          0 :                 return -ENOMEM;
     488                 :            : 
     489                 :       8268 :         *v = (JsonVariant) {
     490                 :            :                 .n_ref = 1,
     491                 :            :                 .type = JSON_VARIANT_ARRAY,
     492                 :            :         };
     493                 :            : 
     494         [ +  + ]:      16856 :         for (v->n_elements = 0; v->n_elements < n; v->n_elements++) {
     495                 :       8588 :                 JsonVariant *w = v + 1 + v->n_elements,
     496                 :       8588 :                         *c = array[v->n_elements];
     497                 :            :                 uint16_t d;
     498                 :            : 
     499                 :       8588 :                 d = json_variant_depth(c);
     500         [ -  + ]:       8588 :                 if (d >= DEPTH_MAX) /* Refuse too deep nesting */
     501                 :          0 :                         return -ELNRNG;
     502         [ +  + ]:       8588 :                 if (d >= v->depth)
     503                 :       8280 :                         v->depth = d + 1;
     504                 :            : 
     505                 :       8588 :                 *w = (JsonVariant) {
     506                 :            :                         .is_embedded = true,
     507                 :            :                         .parent = v,
     508                 :            :                 };
     509                 :            : 
     510                 :       8588 :                 json_variant_set(w, c);
     511                 :       8588 :                 json_variant_copy_source(w, c);
     512                 :            :         }
     513                 :            : 
     514                 :       8268 :         *ret = TAKE_PTR(v);
     515                 :       8268 :         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                 :          4 : int json_variant_new_array_strv(JsonVariant **ret, char **l) {
     556                 :          4 :         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
     557                 :            :         size_t n;
     558                 :            :         int r;
     559                 :            : 
     560         [ -  + ]:          4 :         assert(ret);
     561                 :            : 
     562                 :          4 :         n = strv_length(l);
     563         [ -  + ]:          4 :         if (n == 0) {
     564                 :          0 :                 *ret = JSON_VARIANT_MAGIC_EMPTY_ARRAY;
     565                 :          0 :                 return 0;
     566                 :            :         }
     567                 :            : 
     568                 :          4 :         v = new(JsonVariant, n + 1);
     569         [ -  + ]:          4 :         if (!v)
     570                 :          0 :                 return -ENOMEM;
     571                 :            : 
     572                 :          4 :         *v = (JsonVariant) {
     573                 :            :                 .n_ref = 1,
     574                 :            :                 .type = JSON_VARIANT_ARRAY,
     575                 :            :                 .depth = 1,
     576                 :            :         };
     577                 :            : 
     578         [ +  + ]:         20 :         for (v->n_elements = 0; v->n_elements < n; v->n_elements++) {
     579                 :         16 :                 JsonVariant *w = v + 1 + v->n_elements;
     580                 :            :                 size_t k;
     581                 :            : 
     582                 :         16 :                 *w = (JsonVariant) {
     583                 :            :                         .is_embedded = true,
     584                 :            :                         .parent = v,
     585                 :            :                         .type = JSON_VARIANT_STRING,
     586                 :            :                 };
     587                 :            : 
     588                 :         16 :                 k = strlen(l[v->n_elements]);
     589                 :            : 
     590         [ -  + ]:         16 :                 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                 :         16 :                         memcpy(w->string, l[v->n_elements], k+1);
     600                 :            :         }
     601                 :            : 
     602                 :          4 :         *ret = TAKE_PTR(v);
     603                 :          4 :         return 0;
     604                 :            : }
     605                 :            : 
     606                 :      12116 : int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n) {
     607                 :      12116 :         _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
     608                 :            : 
     609   [ -  +  -  + ]:      12116 :         assert_return(ret, -EINVAL);
     610         [ +  + ]:      12116 :         if (n == 0) {
     611                 :         12 :                 *ret = JSON_VARIANT_MAGIC_EMPTY_OBJECT;
     612                 :         12 :                 return 0;
     613                 :            :         }
     614   [ -  +  -  + ]:      12104 :         assert_return(array, -EINVAL);
     615   [ -  +  -  + ]:      12104 :         assert_return(n % 2 == 0, -EINVAL);
     616                 :            : 
     617                 :      12104 :         v = new(JsonVariant, n + 1);
     618         [ -  + ]:      12104 :         if (!v)
     619                 :          0 :                 return -ENOMEM;
     620                 :            : 
     621                 :      12104 :         *v = (JsonVariant) {
     622                 :            :                 .n_ref = 1,
     623                 :            :                 .type = JSON_VARIANT_OBJECT,
     624                 :            :         };
     625                 :            : 
     626         [ +  + ]:      44012 :         for (v->n_elements = 0; v->n_elements < n; v->n_elements++) {
     627                 :      31912 :                 JsonVariant *w = v + 1 + v->n_elements,
     628                 :      31912 :                         *c = array[v->n_elements];
     629                 :            :                 uint16_t d;
     630                 :            : 
     631         [ +  + ]:      31912 :                 if ((v->n_elements & 1) == 0 &&
     632         [ -  + ]:      15956 :                     !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                 :      31912 :                 d = json_variant_depth(c);
     636         [ +  + ]:      31912 :                 if (d >= DEPTH_MAX) /* Refuse too deep nesting */
     637                 :          4 :                         return -ELNRNG;
     638         [ +  + ]:      31908 :                 if (d >= v->depth)
     639                 :      22240 :                         v->depth = d + 1;
     640                 :            : 
     641                 :      31908 :                 *w = (JsonVariant) {
     642                 :            :                         .is_embedded = true,
     643                 :            :                         .parent = v,
     644                 :            :                 };
     645                 :            : 
     646                 :      31908 :                 json_variant_set(w, c);
     647                 :      31908 :                 json_variant_copy_source(w, c);
     648                 :            :         }
     649                 :            : 
     650                 :      12100 :         *ret = TAKE_PTR(v);
     651                 :      12100 :         return 0;
     652                 :            : }
     653                 :            : 
     654                 :      73436 : static void json_variant_free_inner(JsonVariant *v) {
     655         [ -  + ]:      73436 :         assert(v);
     656                 :            : 
     657         [ -  + ]:      73436 :         if (!json_variant_is_regular(v))
     658                 :          0 :                 return;
     659                 :            : 
     660                 :      73436 :         json_source_unref(v->source);
     661                 :            : 
     662         [ +  + ]:      73436 :         if (v->is_reference) {
     663                 :      18472 :                 json_variant_unref(v->reference);
     664                 :      18472 :                 return;
     665                 :            :         }
     666                 :            : 
     667   [ +  +  +  + ]:      54964 :         if (IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT)) {
     668                 :            :                 size_t i;
     669                 :            : 
     670         [ +  + ]:      60888 :                 for (i = 0; i < v->n_elements; i++)
     671                 :      40512 :                         json_variant_free_inner(v + 1 + i);
     672                 :            :         }
     673                 :            : }
     674                 :            : 
     675                 :      24308 : JsonVariant *json_variant_ref(JsonVariant *v) {
     676         [ -  + ]:      24308 :         if (!v)
     677                 :          0 :                 return NULL;
     678         [ +  + ]:      24308 :         if (!json_variant_is_regular(v))
     679                 :         32 :                 return v;
     680                 :            : 
     681         [ +  + ]:      24276 :         if (v->is_embedded)
     682                 :        544 :                 json_variant_ref(v->parent); /* ref the compounding variant instead */
     683                 :            :         else {
     684         [ -  + ]:      23732 :                 assert(v->n_ref > 0);
     685                 :      23732 :                 v->n_ref++;
     686                 :            :         }
     687                 :            : 
     688                 :      24276 :         return v;
     689                 :            : }
     690                 :            : 
     691                 :      66824 : JsonVariant *json_variant_unref(JsonVariant *v) {
     692         [ +  + ]:      66824 :         if (!v)
     693                 :       7472 :                 return NULL;
     694         [ +  + ]:      59352 :         if (!json_variant_is_regular(v))
     695                 :       2152 :                 return NULL;
     696                 :            : 
     697         [ +  + ]:      57200 :         if (v->is_embedded)
     698                 :        544 :                 json_variant_unref(v->parent);
     699                 :            :         else {
     700         [ -  + ]:      56656 :                 assert(v->n_ref > 0);
     701                 :      56656 :                 v->n_ref--;
     702                 :            : 
     703         [ +  + ]:      56656 :                 if (v->n_ref == 0) {
     704                 :      32924 :                         json_variant_free_inner(v);
     705                 :      32924 :                         free(v);
     706                 :            :                 }
     707                 :            :         }
     708                 :            : 
     709                 :      57200 :         return NULL;
     710                 :            : }
     711                 :            : 
     712                 :       7368 : void json_variant_unref_many(JsonVariant **array, size_t n) {
     713                 :            :         size_t i;
     714                 :            : 
     715   [ +  +  -  + ]:       7368 :         assert(array || n == 0);
     716                 :            : 
     717         [ +  + ]:      26656 :         for (i = 0; i < n; i++)
     718                 :      19288 :                 json_variant_unref(array[i]);
     719                 :       7368 : }
     720                 :            : 
     721                 :      51484 : const char *json_variant_string(JsonVariant *v) {
     722         [ +  + ]:      51484 :         if (!v)
     723                 :          4 :                 return NULL;
     724         [ -  + ]:      51480 :         if (v == JSON_VARIANT_MAGIC_EMPTY_STRING)
     725                 :          0 :                 return "";
     726         [ -  + ]:      51480 :         if (json_variant_is_magic(v))
     727                 :          0 :                 goto mismatch;
     728         [ +  + ]:      51480 :         if (json_variant_is_const_string(v)) {
     729                 :       8208 :                 uintptr_t p = (uintptr_t) v;
     730                 :            : 
     731         [ -  + ]:       8208 :                 assert((p & 1) != 0);
     732                 :       8208 :                 return (const char*) (p ^ 1U);
     733                 :            :         }
     734                 :            : 
     735         [ +  + ]:      43272 :         if (v->is_reference)
     736                 :         56 :                 return json_variant_string(v->reference);
     737         [ -  + ]:      43216 :         if (v->type != JSON_VARIANT_STRING)
     738                 :          0 :                 goto mismatch;
     739                 :            : 
     740                 :      43216 :         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                 :       5632 : bool json_variant_boolean(JsonVariant *v) {
     748         [ -  + ]:       5632 :         if (!v)
     749                 :          0 :                 goto mismatch;
     750         [ +  + ]:       5632 :         if (v == JSON_VARIANT_MAGIC_TRUE)
     751                 :       3212 :                 return true;
     752         [ +  + ]:       2420 :         if (v == JSON_VARIANT_MAGIC_FALSE)
     753                 :          4 :                 return false;
     754         [ -  + ]:       2416 :         if (!json_variant_is_regular(v))
     755                 :          0 :                 goto mismatch;
     756         [ -  + ]:       2416 :         if (v->type != JSON_VARIANT_BOOLEAN)
     757                 :          0 :                 goto mismatch;
     758         [ -  + ]:       2416 :         if (v->is_reference)
     759                 :          0 :                 return json_variant_boolean(v->reference);
     760                 :            : 
     761                 :       2416 :         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                 :       4500 : intmax_t json_variant_integer(JsonVariant *v) {
     769         [ -  + ]:       4500 :         if (!v)
     770                 :          0 :                 goto mismatch;
     771   [ +  +  +  + ]:       4500 :         if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
     772         [ +  + ]:       4416 :             v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
     773                 :            :             v == JSON_VARIANT_MAGIC_ZERO_REAL)
     774                 :        132 :                 return 0;
     775         [ -  + ]:       4368 :         if (!json_variant_is_regular(v))
     776                 :          0 :                 goto mismatch;
     777         [ -  + ]:       4368 :         if (v->is_reference)
     778                 :          0 :                 return json_variant_integer(v->reference);
     779                 :            : 
     780   [ +  +  +  - ]:       4368 :         switch (v->type) {
     781                 :            : 
     782                 :       4268 :         case JSON_VARIANT_INTEGER:
     783                 :       4268 :                 return v->value.integer;
     784                 :            : 
     785                 :         52 :         case JSON_VARIANT_UNSIGNED:
     786         [ +  - ]:         52 :                 if (v->value.unsig <= INTMAX_MAX)
     787                 :         52 :                         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                 :         48 :         case JSON_VARIANT_REAL: {
     793                 :            :                 intmax_t converted;
     794                 :            : 
     795                 :         48 :                 converted = (intmax_t) v->value.real;
     796                 :            : 
     797                 :            : #pragma GCC diagnostic push
     798                 :            : #pragma GCC diagnostic ignored "-Wfloat-equal"
     799                 :         48 :                 if ((long double) converted == v->value.real)
     800                 :            : #pragma GCC diagnostic pop
     801                 :         48 :                         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                 :       1252 : uintmax_t json_variant_unsigned(JsonVariant *v) {
     817         [ -  + ]:       1252 :         if (!v)
     818                 :          0 :                 goto mismatch;
     819   [ +  +  +  + ]:       1252 :         if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
     820         [ +  + ]:       1184 :             v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
     821                 :            :             v == JSON_VARIANT_MAGIC_ZERO_REAL)
     822                 :        112 :                 return 0;
     823         [ -  + ]:       1140 :         if (!json_variant_is_regular(v))
     824                 :          0 :                 goto mismatch;
     825         [ -  + ]:       1140 :         if (v->is_reference)
     826                 :          0 :                 return json_variant_integer(v->reference);
     827                 :            : 
     828   [ +  +  +  - ]:       1140 :         switch (v->type) {
     829                 :            : 
     830                 :          4 :         case JSON_VARIANT_INTEGER:
     831         [ +  - ]:          4 :                 if (v->value.integer >= 0)
     832                 :          4 :                         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                 :       1092 :         case JSON_VARIANT_UNSIGNED:
     838                 :       1092 :                 return v->value.unsig;
     839                 :            : 
     840                 :         44 :         case JSON_VARIANT_REAL: {
     841                 :            :                 uintmax_t converted;
     842                 :            : 
     843                 :         44 :                 converted = (uintmax_t) v->value.real;
     844                 :            : 
     845                 :            : #pragma GCC diagnostic push
     846                 :            : #pragma GCC diagnostic ignored "-Wfloat-equal"
     847                 :         44 :                 if ((long double) converted == v->value.real)
     848                 :            : #pragma GCC diagnostic pop
     849                 :         44 :                         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                 :       2132 : long double json_variant_real(JsonVariant *v) {
     865         [ -  + ]:       2132 :         if (!v)
     866                 :          0 :                 return 0.0;
     867   [ +  +  +  + ]:       2132 :         if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
     868         [ +  + ]:       2044 :             v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
     869                 :            :             v == JSON_VARIANT_MAGIC_ZERO_REAL)
     870                 :        316 :                 return 0.0;
     871         [ -  + ]:       1816 :         if (!json_variant_is_regular(v))
     872                 :          0 :                 goto mismatch;
     873         [ -  + ]:       1816 :         if (v->is_reference)
     874                 :          0 :                 return json_variant_real(v->reference);
     875                 :            : 
     876   [ +  +  +  - ]:       1816 :         switch (v->type) {
     877                 :            : 
     878                 :       1804 :         case JSON_VARIANT_REAL:
     879                 :       1804 :                 return v->value.real;
     880                 :            : 
     881                 :          8 :         case JSON_VARIANT_INTEGER: {
     882                 :            :                 long double converted;
     883                 :            : 
     884                 :          8 :                 converted = (long double) v->value.integer;
     885                 :            : 
     886         [ +  - ]:          8 :                 if ((intmax_t) converted == v->value.integer)
     887                 :          8 :                         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                 :          4 :         case JSON_VARIANT_UNSIGNED: {
     894                 :            :                 long double converted;
     895                 :            : 
     896                 :          4 :                 converted = (long double) v->value.unsig;
     897                 :            : 
     898         [ +  - ]:          4 :                 if ((uintmax_t) converted == v->value.unsig)
     899                 :          4 :                         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                 :         52 : bool json_variant_is_negative(JsonVariant *v) {
     915         [ -  + ]:         52 :         if (!v)
     916                 :          0 :                 goto mismatch;
     917   [ +  -  +  - ]:         52 :         if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER ||
     918         [ -  + ]:         52 :             v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED ||
     919                 :            :             v == JSON_VARIANT_MAGIC_ZERO_REAL)
     920                 :          0 :                 return false;
     921         [ -  + ]:         52 :         if (!json_variant_is_regular(v))
     922                 :          0 :                 goto mismatch;
     923         [ -  + ]:         52 :         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   [ +  +  +  - ]:         52 :         switch (v->type) {
     931                 :            : 
     932                 :         44 :         case JSON_VARIANT_REAL:
     933                 :         44 :                 return v->value.real < 0;
     934                 :            : 
     935                 :          4 :         case JSON_VARIANT_INTEGER:
     936                 :          4 :                 return v->value.integer < 0;
     937                 :            : 
     938                 :          4 :         case JSON_VARIANT_UNSIGNED:
     939                 :          4 :                 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                 :     158592 : JsonVariantType json_variant_type(JsonVariant *v) {
     951                 :            : 
     952         [ -  + ]:     158592 :         if (!v)
     953                 :          0 :                 return _JSON_VARIANT_TYPE_INVALID;
     954                 :            : 
     955         [ +  + ]:     158592 :         if (json_variant_is_const_string(v))
     956                 :      16404 :                 return JSON_VARIANT_STRING;
     957                 :            : 
     958   [ +  +  +  + ]:     142188 :         if (v == JSON_VARIANT_MAGIC_TRUE || v == JSON_VARIANT_MAGIC_FALSE)
     959                 :       3216 :                 return JSON_VARIANT_BOOLEAN;
     960                 :            : 
     961         [ +  + ]:     138972 :         if (v == JSON_VARIANT_MAGIC_NULL)
     962                 :        104 :                 return JSON_VARIANT_NULL;
     963                 :            : 
     964         [ +  + ]:     138868 :         if (v == JSON_VARIANT_MAGIC_ZERO_INTEGER)
     965                 :        128 :                 return JSON_VARIANT_INTEGER;
     966                 :            : 
     967         [ +  + ]:     138740 :         if (v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED)
     968                 :        112 :                 return JSON_VARIANT_UNSIGNED;
     969                 :            : 
     970         [ +  + ]:     138628 :         if (v == JSON_VARIANT_MAGIC_ZERO_REAL)
     971                 :        320 :                 return JSON_VARIANT_REAL;
     972                 :            : 
     973         [ -  + ]:     138308 :         if (v == JSON_VARIANT_MAGIC_EMPTY_STRING)
     974                 :          0 :                 return JSON_VARIANT_STRING;
     975                 :            : 
     976         [ -  + ]:     138308 :         if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY)
     977                 :          0 :                 return JSON_VARIANT_ARRAY;
     978                 :            : 
     979         [ +  + ]:     138308 :         if (v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
     980                 :         44 :                 return JSON_VARIANT_OBJECT;
     981                 :            : 
     982                 :     138264 :         return v->type;
     983                 :            : }
     984                 :            : 
     985                 :      23072 : bool json_variant_has_type(JsonVariant *v, JsonVariantType type) {
     986                 :            :         JsonVariantType rt;
     987                 :            : 
     988                 :      23072 :         v = json_variant_dereference(v);
     989         [ -  + ]:      23072 :         if (!v)
     990                 :          0 :                 return false;
     991                 :            : 
     992                 :      23072 :         rt = json_variant_type(v);
     993         [ +  + ]:      23072 :         if (rt == type)
     994                 :      22696 :                 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         [ -  + ]:        376 :         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   [ +  +  +  +  :        376 :         if ((v == JSON_VARIANT_MAGIC_ZERO_INTEGER || v == JSON_VARIANT_MAGIC_ZERO_UNSIGNED || v == JSON_VARIANT_MAGIC_ZERO_REAL) &&
                   +  + ]
    1002   [ +  -  +  - ]:        188 :             IN_SET(type, JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL, JSON_VARIANT_NUMBER))
    1003                 :        188 :                 return true;
    1004                 :            : 
    1005                 :            :         /* All other magic variant types are only equal to themselves */
    1006         [ -  + ]:        188 :         if (json_variant_is_magic(v))
    1007                 :          0 :                 return false;
    1008                 :            : 
    1009                 :            :         /* Handle the "number" pseudo type */
    1010         [ +  + ]:        188 :         if (type == JSON_VARIANT_NUMBER)
    1011         [ +  - ]:         52 :                 return IN_SET(rt, JSON_VARIANT_INTEGER, JSON_VARIANT_UNSIGNED, JSON_VARIANT_REAL);
    1012                 :            : 
    1013                 :            :         /* Integer conversions are OK in many cases */
    1014   [ +  +  +  + ]:        136 :         if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_UNSIGNED)
    1015                 :          4 :                 return v->value.integer >= 0;
    1016   [ +  +  +  + ]:        132 :         if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_INTEGER)
    1017                 :         28 :                 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   [ +  +  +  - ]:        104 :         if (rt == JSON_VARIANT_INTEGER && type == JSON_VARIANT_REAL)
    1021                 :          8 :                 return (intmax_t) (long double) v->value.integer == v->value.integer;
    1022   [ +  +  +  - ]:         96 :         if (rt == JSON_VARIANT_UNSIGNED && type == JSON_VARIANT_REAL)
    1023                 :          4 :                 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   [ +  -  +  + ]:         92 :         if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_INTEGER)
    1029                 :         48 :                 return (long double) (intmax_t) v->value.real == v->value.real;
    1030   [ +  -  +  - ]:         44 :         if (rt == JSON_VARIANT_REAL && type == JSON_VARIANT_UNSIGNED)
    1031                 :         44 :                 return (long double) (uintmax_t) v->value.real == v->value.real;
    1032                 :            : #pragma GCC diagnostic pop
    1033                 :            : 
    1034                 :          0 :         return false;
    1035                 :            : }
    1036                 :            : 
    1037                 :      58348 : size_t json_variant_elements(JsonVariant *v) {
    1038         [ -  + ]:      58348 :         if (!v)
    1039                 :          0 :                 return 0;
    1040   [ +  -  +  + ]:      58348 :         if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY ||
    1041                 :            :             v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
    1042                 :         24 :                 return 0;
    1043         [ -  + ]:      58324 :         if (!json_variant_is_regular(v))
    1044                 :          0 :                 goto mismatch;
    1045   [ +  -  -  + ]:      58324 :         if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT))
    1046                 :          0 :                 goto mismatch;
    1047         [ +  + ]:      58324 :         if (v->is_reference)
    1048                 :        132 :                 return json_variant_elements(v->reference);
    1049                 :            : 
    1050                 :      58192 :         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                 :      41528 : JsonVariant *json_variant_by_index(JsonVariant *v, size_t idx) {
    1058         [ -  + ]:      41528 :         if (!v)
    1059                 :          0 :                 return NULL;
    1060   [ +  -  -  + ]:      41528 :         if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY ||
    1061                 :            :             v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
    1062                 :          0 :                 return NULL;
    1063         [ -  + ]:      41528 :         if (!json_variant_is_regular(v))
    1064                 :          0 :                 goto mismatch;
    1065   [ +  -  -  + ]:      41528 :         if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT))
    1066                 :          0 :                 goto mismatch;
    1067         [ +  + ]:      41528 :         if (v->is_reference)
    1068                 :        332 :                 return json_variant_by_index(v->reference, idx);
    1069         [ -  + ]:      41196 :         if (idx >= v->n_elements)
    1070                 :          0 :                 return NULL;
    1071                 :            : 
    1072                 :      41196 :         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                 :        108 : JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key) {
    1080                 :            :         size_t i;
    1081                 :            : 
    1082         [ -  + ]:        108 :         if (!v)
    1083                 :          0 :                 goto not_found;
    1084         [ -  + ]:        108 :         if (!key)
    1085                 :          0 :                 goto not_found;
    1086         [ -  + ]:        108 :         if (v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
    1087                 :          0 :                 goto not_found;
    1088         [ -  + ]:        108 :         if (!json_variant_is_regular(v))
    1089                 :          0 :                 goto mismatch;
    1090         [ -  + ]:        108 :         if (v->type != JSON_VARIANT_OBJECT)
    1091                 :          0 :                 goto mismatch;
    1092         [ +  + ]:        108 :         if (v->is_reference)
    1093                 :         36 :                 return json_variant_by_key(v->reference, key);
    1094                 :            : 
    1095         [ +  + ]:        104 :         for (i = 0; i < v->n_elements; i += 2) {
    1096                 :            :                 JsonVariant *p;
    1097                 :            : 
    1098                 :        100 :                 p = json_variant_dereference(v + 1 + i);
    1099                 :            : 
    1100         [ -  + ]:        100 :                 if (!json_variant_has_type(p, JSON_VARIANT_STRING))
    1101                 :          0 :                         continue;
    1102                 :            : 
    1103         [ +  + ]:        100 :                 if (streq(json_variant_string(p), key)) {
    1104                 :            : 
    1105         [ -  + ]:         68 :                         if (ret_key)
    1106                 :          0 :                                 *ret_key = json_variant_conservative_normalize(v + 1 + i);
    1107                 :            : 
    1108                 :         68 :                         return json_variant_conservative_normalize(v + 1 + i + 1);
    1109                 :            :                 }
    1110                 :            :         }
    1111                 :            : 
    1112                 :          4 : not_found:
    1113         [ -  + ]:          4 :         if (ret_key)
    1114                 :          0 :                 *ret_key = NULL;
    1115                 :            : 
    1116                 :          4 :         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                 :        108 : JsonVariant *json_variant_by_key(JsonVariant *v, const char *key) {
    1127                 :        108 :         return json_variant_by_key_full(v, key, NULL);
    1128                 :            : }
    1129                 :            : 
    1130                 :       1172 : bool json_variant_equal(JsonVariant *a, JsonVariant *b) {
    1131                 :            :         JsonVariantType t;
    1132                 :            : 
    1133                 :       1172 :         a = json_variant_normalize(a);
    1134                 :       1172 :         b = json_variant_normalize(b);
    1135                 :            : 
    1136         [ +  + ]:       1172 :         if (a == b)
    1137                 :        640 :                 return true;
    1138                 :            : 
    1139                 :        532 :         t = json_variant_type(a);
    1140         [ -  + ]:        532 :         if (!json_variant_has_type(b, t))
    1141                 :          0 :                 return false;
    1142                 :            : 
    1143   [ +  +  +  +  :        532 :         switch (t) {
             -  -  +  +  
                      - ]
    1144                 :            : 
    1145                 :        184 :         case JSON_VARIANT_STRING:
    1146                 :        184 :                 return streq(json_variant_string(a), json_variant_string(b));
    1147                 :            : 
    1148                 :         60 :         case JSON_VARIANT_INTEGER:
    1149                 :         60 :                 return json_variant_integer(a) == json_variant_integer(b);
    1150                 :            : 
    1151                 :         88 :         case JSON_VARIANT_UNSIGNED:
    1152                 :         88 :                 return json_variant_unsigned(a) == json_variant_unsigned(b);
    1153                 :            : 
    1154                 :        100 :         case JSON_VARIANT_REAL:
    1155                 :            : #pragma GCC diagnostic push
    1156                 :            : #pragma GCC diagnostic ignored "-Wfloat-equal"
    1157                 :        100 :                 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                 :         44 :         case JSON_VARIANT_ARRAY: {
    1167                 :            :                 size_t i, n;
    1168                 :            : 
    1169                 :         44 :                 n = json_variant_elements(a);
    1170         [ -  + ]:         44 :                 if (n != json_variant_elements(b))
    1171                 :          0 :                         return false;
    1172                 :            : 
    1173         [ +  + ]:        276 :                 for (i = 0; i < n; i++) {
    1174         [ -  + ]:        232 :                         if (!json_variant_equal(json_variant_by_index(a, i), json_variant_by_index(b, i)))
    1175                 :          0 :                                 return false;
    1176                 :            :                 }
    1177                 :            : 
    1178                 :         44 :                 return true;
    1179                 :            :         }
    1180                 :            : 
    1181                 :         56 :         case JSON_VARIANT_OBJECT: {
    1182                 :            :                 size_t i, n;
    1183                 :            : 
    1184                 :         56 :                 n = json_variant_elements(a);
    1185         [ -  + ]:         56 :                 if (n != json_variant_elements(b))
    1186                 :          0 :                         return false;
    1187                 :            : 
    1188                 :            :                 /* Iterate through all keys in 'a' */
    1189         [ +  + ]:        156 :                 for (i = 0; i < n; i += 2) {
    1190                 :        100 :                         bool found = false;
    1191                 :            :                         size_t j;
    1192                 :            : 
    1193                 :            :                         /* Match them against all keys in 'b' */
    1194         [ +  + ]:        252 :                         for (j = 0; j < n; j += 2) {
    1195                 :            :                                 JsonVariant *key_b;
    1196                 :            : 
    1197                 :        196 :                                 key_b = json_variant_by_index(b, j);
    1198                 :            : 
    1199                 :            :                                 /* During the first iteration unmark everything */
    1200         [ +  + ]:        196 :                                 if (i == 0)
    1201                 :        100 :                                         key_b->is_marked = false;
    1202         [ +  + ]:         96 :                                 else if (key_b->is_marked) /* In later iterations if we already marked something, don't bother with it again */
    1203                 :         52 :                                         continue;
    1204                 :            : 
    1205         [ +  + ]:        144 :                                 if (found)
    1206                 :         36 :                                         continue;
    1207                 :            : 
    1208   [ +  +  +  - ]:        208 :                                 if (json_variant_equal(json_variant_by_index(a, i), key_b) &&
    1209                 :        100 :                                     json_variant_equal(json_variant_by_index(a, i+1), json_variant_by_index(b, j+1))) {
    1210                 :            :                                         /* Key and values match! */
    1211                 :        100 :                                         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         [ +  + ]:        100 :                                         if (i != 0)
    1217                 :         44 :                                                 break;
    1218                 :            :                                 }
    1219                 :            :                         }
    1220                 :            : 
    1221         [ -  + ]:        100 :                         if (!found)
    1222                 :          0 :                                 return false;
    1223                 :            :                 }
    1224                 :            : 
    1225                 :         56 :                 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                 :       1836 : static int print_source(FILE *f, JsonVariant *v, JsonFormatFlags flags, bool whitespace) {
    1249                 :            :         size_t w, k;
    1250                 :            : 
    1251         [ +  + ]:       1836 :         if (!FLAGS_SET(flags, JSON_FORMAT_SOURCE|JSON_FORMAT_PRETTY))
    1252                 :       1760 :                 return 0;
    1253                 :            : 
    1254         [ -  + ]:         76 :         if (!json_variant_is_regular(v))
    1255                 :          0 :                 return 0;
    1256                 :            : 
    1257   [ -  +  #  #  :         76 :         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         [ +  - ]:         76 :         w = (v->source && v->source->max_line > 0) ?
    1262   [ +  -  +  + ]:        228 :                 DECIMAL_STR_WIDTH(v->source->max_line) :
    1263                 :            :                 DECIMAL_STR_MAX(unsigned)-1;
    1264         [ +  - ]:         76 :         k = (v->source && v->source->max_column > 0) ?
    1265   [ +  -  +  + ]:        228 :                 DECIMAL_STR_WIDTH(v->source->max_column) :
    1266                 :            :                 DECIMAL_STR_MAX(unsigned) -1;
    1267                 :            : 
    1268         [ +  + ]:         76 :         if (whitespace) {
    1269                 :            :                 size_t i, n;
    1270                 :            : 
    1271         [ +  - ]:         16 :                 n = 1 + (v->source ? strlen(v->source->name) : 0) +
    1272   [ +  -  -  +  :         16 :                         ((v->source && (v->line > 0 || v->column > 0)) ? 1 : 0) +
                   #  # ]
    1273         [ +  - ]:         16 :                         (v->line > 0 ? w : 0) +
    1274   [ -  +  #  #  :         16 :                         (((v->source || v->line > 0) && v->column > 0) ? 1 : 0) +
                   +  - ]
    1275         [ +  - ]:         16 :                         (v->column > 0 ? k : 0) +
    1276                 :            :                         2;
    1277                 :            : 
    1278         [ +  + ]:        240 :                 for (i = 0; i < n; i++)
    1279                 :        224 :                         fputc(' ', f);
    1280                 :            :         } else {
    1281                 :         60 :                 fputc('[', f);
    1282                 :            : 
    1283         [ +  - ]:         60 :                 if (v->source)
    1284                 :         60 :                         fputs(v->source->name, f);
    1285   [ +  -  -  +  :         60 :                 if (v->source && (v->line > 0 || v->column > 0))
                   #  # ]
    1286                 :         60 :                         fputc(':', f);
    1287         [ +  - ]:         60 :                 if (v->line > 0)
    1288                 :         60 :                         fprintf(f, "%*u", (int) w, v->line);
    1289   [ -  +  #  #  :         60 :                 if ((v->source || v->line > 0) || v->column > 0)
                   #  # ]
    1290                 :         60 :                         fputc(':', f);
    1291         [ +  - ]:         60 :                 if (v->column > 0)
    1292                 :         60 :                         fprintf(f, "%*u", (int) k, v->column);
    1293                 :            : 
    1294                 :         60 :                 fputc(']', f);
    1295                 :         60 :                 fputc(' ', f);
    1296                 :            :         }
    1297                 :            : 
    1298                 :         76 :         return 0;
    1299                 :            : }
    1300                 :            : 
    1301                 :      37716 : static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const char *prefix) {
    1302                 :            :         int r;
    1303                 :            : 
    1304         [ -  + ]:      37716 :         assert(f);
    1305         [ -  + ]:      37716 :         assert(v);
    1306                 :            : 
    1307   [ +  +  +  +  :      37716 :         switch (json_variant_type(v)) {
             +  +  +  +  
                      - ]
    1308                 :            : 
    1309                 :        212 :         case JSON_VARIANT_REAL: {
    1310                 :            :                 locale_t loc;
    1311                 :            : 
    1312                 :        212 :                 loc = newlocale(LC_NUMERIC_MASK, "C", (locale_t) 0);
    1313         [ -  + ]:        212 :                 if (loc == (locale_t) 0)
    1314                 :          0 :                         return -errno;
    1315                 :            : 
    1316         [ +  + ]:        212 :                 if (flags & JSON_FORMAT_COLOR)
    1317                 :        100 :                         fputs(ANSI_HIGHLIGHT_BLUE, f);
    1318                 :            : 
    1319                 :        212 :                 fprintf(f, "%.*Le", DECIMAL_DIG, json_variant_real(v));
    1320                 :            : 
    1321         [ +  + ]:        212 :                 if (flags & JSON_FORMAT_COLOR)
    1322                 :        100 :                         fputs(ANSI_NORMAL, f);
    1323                 :            : 
    1324                 :        212 :                 freelocale(loc);
    1325                 :        212 :                 break;
    1326                 :            :         }
    1327                 :            : 
    1328                 :       1376 :         case JSON_VARIANT_INTEGER:
    1329         [ +  + ]:       1376 :                 if (flags & JSON_FORMAT_COLOR)
    1330                 :          8 :                         fputs(ANSI_HIGHLIGHT_BLUE, f);
    1331                 :            : 
    1332                 :       1376 :                 fprintf(f, "%" PRIdMAX, json_variant_integer(v));
    1333                 :            : 
    1334         [ +  + ]:       1376 :                 if (flags & JSON_FORMAT_COLOR)
    1335                 :          8 :                         fputs(ANSI_NORMAL, f);
    1336                 :       1376 :                 break;
    1337                 :            : 
    1338                 :        144 :         case JSON_VARIANT_UNSIGNED:
    1339         [ +  + ]:        144 :                 if (flags & JSON_FORMAT_COLOR)
    1340                 :         72 :                         fputs(ANSI_HIGHLIGHT_BLUE, f);
    1341                 :            : 
    1342                 :        144 :                 fprintf(f, "%" PRIuMAX, json_variant_unsigned(v));
    1343                 :            : 
    1344         [ +  + ]:        144 :                 if (flags & JSON_FORMAT_COLOR)
    1345                 :         72 :                         fputs(ANSI_NORMAL, f);
    1346                 :        144 :                 break;
    1347                 :            : 
    1348                 :       1356 :         case JSON_VARIANT_BOOLEAN:
    1349                 :            : 
    1350         [ +  + ]:       1356 :                 if (flags & JSON_FORMAT_COLOR)
    1351                 :          8 :                         fputs(ANSI_HIGHLIGHT, f);
    1352                 :            : 
    1353         [ +  + ]:       1356 :                 if (json_variant_boolean(v))
    1354                 :       1348 :                         fputs("true", f);
    1355                 :            :                 else
    1356                 :          8 :                         fputs("false", f);
    1357                 :            : 
    1358         [ +  + ]:       1356 :                 if (flags & JSON_FORMAT_COLOR)
    1359                 :          8 :                         fputs(ANSI_NORMAL, f);
    1360                 :            : 
    1361                 :       1356 :                 break;
    1362                 :            : 
    1363                 :         52 :         case JSON_VARIANT_NULL:
    1364         [ +  + ]:         52 :                 if (flags & JSON_FORMAT_COLOR)
    1365                 :         16 :                         fputs(ANSI_HIGHLIGHT, f);
    1366                 :            : 
    1367                 :         52 :                 fputs("null", f);
    1368                 :            : 
    1369         [ +  + ]:         52 :                 if (flags & JSON_FORMAT_COLOR)
    1370                 :         16 :                         fputs(ANSI_NORMAL, f);
    1371                 :         52 :                 break;
    1372                 :            : 
    1373                 :      15260 :         case JSON_VARIANT_STRING: {
    1374                 :            :                 const char *q;
    1375                 :            : 
    1376                 :      15260 :                 fputc('"', f);
    1377                 :            : 
    1378         [ +  + ]:      15260 :                 if (flags & JSON_FORMAT_COLOR)
    1379                 :        120 :                         fputs(ANSI_GREEN, f);
    1380                 :            : 
    1381         [ +  + ]:      95020 :                 for (q = json_variant_string(v); *q; q++) {
    1382                 :            : 
    1383   [ +  -  -  -  :      79760 :                         switch (*q) {
             -  -  -  + ]
    1384                 :            : 
    1385                 :         96 :                         case '"':
    1386                 :         96 :                                 fputs("\\\"", f);
    1387                 :         96 :                                 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                 :      79664 :                         default:
    1414   [ +  +  -  + ]:      79664 :                                 if ((signed char) *q >= 0 && *q < ' ')
    1415                 :          0 :                                         fprintf(f, "\\u%04x", *q);
    1416                 :            :                                 else
    1417                 :      79664 :                                         fputc(*q, f);
    1418                 :      79664 :                                 break;
    1419                 :            :                         }
    1420                 :            :                 }
    1421                 :            : 
    1422         [ +  + ]:      15260 :                 if (flags & JSON_FORMAT_COLOR)
    1423                 :        120 :                         fputs(ANSI_NORMAL, f);
    1424                 :            : 
    1425                 :      15260 :                 fputc('"', f);
    1426                 :      15260 :                 break;
    1427                 :            :         }
    1428                 :            : 
    1429                 :       8284 :         case JSON_VARIANT_ARRAY: {
    1430                 :            :                 size_t i, n;
    1431                 :            : 
    1432                 :       8284 :                 n = json_variant_elements(v);
    1433                 :            : 
    1434         [ -  + ]:       8284 :                 if (n == 0)
    1435                 :          0 :                         fputs("[]", f);
    1436                 :            :                 else {
    1437         [ +  - ]:       8284 :                         _cleanup_free_ char *joined = NULL;
    1438                 :            :                         const char *prefix2;
    1439                 :            : 
    1440         [ +  + ]:       8284 :                         if (flags & JSON_FORMAT_PRETTY) {
    1441                 :         40 :                                 joined = strjoin(strempty(prefix), "\t");
    1442         [ -  + ]:         40 :                                 if (!joined)
    1443                 :          0 :                                         return -ENOMEM;
    1444                 :            : 
    1445                 :         40 :                                 prefix2 = joined;
    1446                 :         40 :                                 fputs("[\n", f);
    1447                 :            :                         } else {
    1448                 :       8244 :                                 prefix2 = strempty(prefix);
    1449                 :       8244 :                                 fputc('[', f);
    1450                 :            :                         }
    1451                 :            : 
    1452         [ +  + ]:      16956 :                         for (i = 0; i < n; i++) {
    1453                 :            :                                 JsonVariant *e;
    1454                 :            : 
    1455         [ -  + ]:       8672 :                                 assert_se(e = json_variant_by_index(v, i));
    1456                 :            : 
    1457         [ +  + ]:       8672 :                                 if (i > 0) {
    1458         [ +  + ]:        388 :                                         if (flags & JSON_FORMAT_PRETTY)
    1459                 :        172 :                                                 fputs(",\n", f);
    1460                 :            :                                         else
    1461                 :        216 :                                                 fputc(',', f);
    1462                 :            :                                 }
    1463                 :            : 
    1464         [ +  + ]:       8672 :                                 if (flags & JSON_FORMAT_PRETTY) {
    1465                 :        212 :                                         print_source(f, e, flags, false);
    1466                 :        212 :                                         fputs(prefix2, f);
    1467                 :            :                                 }
    1468                 :            : 
    1469                 :       8672 :                                 r = json_format(f, e, flags, prefix2);
    1470         [ -  + ]:       8672 :                                 if (r < 0)
    1471                 :          0 :                                         return r;
    1472                 :            :                         }
    1473                 :            : 
    1474         [ +  + ]:       8284 :                         if (flags & JSON_FORMAT_PRETTY) {
    1475                 :         40 :                                 fputc('\n', f);
    1476                 :         40 :                                 print_source(f, v, flags, true);
    1477                 :         40 :                                 fputs(strempty(prefix), f);
    1478                 :            :                         }
    1479                 :            : 
    1480                 :       8284 :                         fputc(']', f);
    1481                 :            :                 }
    1482                 :       8284 :                 break;
    1483                 :            :         }
    1484                 :            : 
    1485                 :      11032 :         case JSON_VARIANT_OBJECT: {
    1486                 :            :                 size_t i, n;
    1487                 :            : 
    1488                 :      11032 :                 n = json_variant_elements(v);
    1489                 :            : 
    1490         [ +  + ]:      11032 :                 if (n == 0)
    1491                 :         12 :                         fputs("{}", f);
    1492                 :            :                 else {
    1493         [ +  - ]:      11020 :                         _cleanup_free_ char *joined = NULL;
    1494                 :            :                         const char *prefix2;
    1495                 :            : 
    1496         [ +  + ]:      11020 :                         if (flags & JSON_FORMAT_PRETTY) {
    1497                 :         48 :                                 joined = strjoin(strempty(prefix), "\t");
    1498         [ -  + ]:         48 :                                 if (!joined)
    1499                 :          0 :                                         return -ENOMEM;
    1500                 :            : 
    1501                 :         48 :                                 prefix2 = joined;
    1502                 :         48 :                                 fputs("{\n", f);
    1503                 :            :                         } else {
    1504                 :      10972 :                                 prefix2 = strempty(prefix);
    1505                 :      10972 :                                 fputc('{', f);
    1506                 :            :                         }
    1507                 :            : 
    1508         [ +  + ]:      24816 :                         for (i = 0; i < n; i += 2) {
    1509                 :            :                                 JsonVariant *e;
    1510                 :            : 
    1511                 :      13796 :                                 e = json_variant_by_index(v, i);
    1512                 :            : 
    1513         [ +  + ]:      13796 :                                 if (i > 0) {
    1514         [ +  + ]:       2776 :                                         if (flags & JSON_FORMAT_PRETTY)
    1515                 :         36 :                                                 fputs(",\n", f);
    1516                 :            :                                         else
    1517                 :       2740 :                                                 fputc(',', f);
    1518                 :            :                                 }
    1519                 :            : 
    1520         [ +  + ]:      13796 :                                 if (flags & JSON_FORMAT_PRETTY) {
    1521                 :         84 :                                         print_source(f, e, flags, false);
    1522                 :         84 :                                         fputs(prefix2, f);
    1523                 :            :                                 }
    1524                 :            : 
    1525                 :      13796 :                                 r = json_format(f, e, flags, prefix2);
    1526         [ -  + ]:      13796 :                                 if (r < 0)
    1527                 :          0 :                                         return r;
    1528                 :            : 
    1529         [ +  + ]:      13796 :                                 fputs(flags & JSON_FORMAT_PRETTY ? " : " : ":", f);
    1530                 :            : 
    1531                 :      13796 :                                 r = json_format(f, json_variant_by_index(v, i+1), flags, prefix2);
    1532         [ -  + ]:      13796 :                                 if (r < 0)
    1533                 :          0 :                                         return r;
    1534                 :            :                         }
    1535                 :            : 
    1536         [ +  + ]:      11020 :                         if (flags & JSON_FORMAT_PRETTY) {
    1537                 :         48 :                                 fputc('\n', f);
    1538                 :         48 :                                 print_source(f, v, flags, true);
    1539                 :         48 :                                 fputs(strempty(prefix), f);
    1540                 :            :                         }
    1541                 :            : 
    1542                 :      11020 :                         fputc('}', f);
    1543                 :            :                 }
    1544                 :      11032 :                 break;
    1545                 :            :         }
    1546                 :            : 
    1547                 :          0 :         default:
    1548                 :          0 :                 assert_not_reached("Unexpected variant type.");
    1549                 :            :         }
    1550                 :            : 
    1551                 :      37716 :         return 0;
    1552                 :            : }
    1553                 :            : 
    1554                 :       1440 : int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) {
    1555                 :       1440 :         _cleanup_free_ char *s = NULL;
    1556                 :       1440 :         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   [ -  +  -  + ]:       1440 :         assert_return(v, -EINVAL);
    1563   [ -  +  -  + ]:       1440 :         assert_return(ret, -EINVAL);
    1564                 :            : 
    1565                 :            :         {
    1566         [ +  - ]:       1440 :                 _cleanup_fclose_ FILE *f = NULL;
    1567                 :            : 
    1568                 :       1440 :                 f = open_memstream_unlocked(&s, &sz);
    1569         [ -  + ]:       1440 :                 if (!f)
    1570                 :          0 :                         return -ENOMEM;
    1571                 :            : 
    1572                 :       1440 :                 json_variant_dump(v, flags, f, NULL);
    1573                 :            : 
    1574                 :            :                 /* Add terminating 0, so that the output buffer is a valid string. */
    1575                 :       1440 :                 fputc('\0', f);
    1576                 :            : 
    1577                 :       1440 :                 r = fflush_and_check(f);
    1578                 :            :         }
    1579         [ -  + ]:       1440 :         if (r < 0)
    1580                 :          0 :                 return r;
    1581                 :            : 
    1582         [ -  + ]:       1440 :         assert(s);
    1583                 :       1440 :         *ret = TAKE_PTR(s);
    1584         [ -  + ]:       1440 :         assert(sz > 0);
    1585                 :       1440 :         return (int) sz - 1;
    1586                 :            : }
    1587                 :            : 
    1588                 :       1452 : void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix) {
    1589         [ -  + ]:       1452 :         if (!v)
    1590                 :          0 :                 return;
    1591                 :            : 
    1592         [ -  + ]:       1452 :         if (!f)
    1593                 :          0 :                 f = stdout;
    1594                 :            : 
    1595                 :       1452 :         print_source(f, v, flags, false);
    1596                 :            : 
    1597   [ -  +  #  # ]:       1452 :         if (((flags & (JSON_FORMAT_COLOR_AUTO|JSON_FORMAT_COLOR)) == JSON_FORMAT_COLOR_AUTO) && colors_enabled())
    1598                 :          0 :                 flags |= JSON_FORMAT_COLOR;
    1599                 :            : 
    1600         [ -  + ]:       1452 :         if (flags & JSON_FORMAT_SSE)
    1601                 :          0 :                 fputs("data: ", f);
    1602         [ -  + ]:       1452 :         if (flags & JSON_FORMAT_SEQ)
    1603                 :          0 :                 fputc('\x1e', f); /* ASCII Record Separator */
    1604                 :            : 
    1605                 :       1452 :         json_format(f, v, flags, prefix);
    1606                 :            : 
    1607         [ +  + ]:       1452 :         if (flags & (JSON_FORMAT_PRETTY|JSON_FORMAT_SEQ|JSON_FORMAT_SSE|JSON_FORMAT_NEWLINE))
    1608                 :         36 :                 fputc('\n', f);
    1609         [ -  + ]:       1452 :         if (flags & JSON_FORMAT_SSE)
    1610                 :          0 :                 fputc('\n', f); /* In case of SSE add a second newline */
    1611                 :            : }
    1612                 :            : 
    1613                 :        744 : 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         [ -  + ]:        744 :         assert(nv);
    1621         [ -  + ]:        744 :         assert(v);
    1622                 :            : 
    1623                 :            :         /* Let's copy the simple types literally, and the larger types by references */
    1624                 :        744 :         t = json_variant_type(v);
    1625   [ +  +  +  +  :        744 :         switch (t) {
                +  -  + ]
    1626                 :         12 :         case JSON_VARIANT_INTEGER:
    1627                 :         12 :                 k = sizeof(intmax_t);
    1628                 :         12 :                 value.integer = json_variant_integer(v);
    1629                 :         12 :                 source = &value;
    1630                 :         12 :                 break;
    1631                 :            : 
    1632                 :         16 :         case JSON_VARIANT_UNSIGNED:
    1633                 :         16 :                 k = sizeof(uintmax_t);
    1634                 :         16 :                 value.unsig = json_variant_unsigned(v);
    1635                 :         16 :                 source = &value;
    1636                 :         16 :                 break;
    1637                 :            : 
    1638                 :        132 :         case JSON_VARIANT_REAL:
    1639                 :        132 :                 k = sizeof(long double);
    1640                 :        132 :                 value.real = json_variant_real(v);
    1641                 :        132 :                 source = &value;
    1642                 :        132 :                 break;
    1643                 :            : 
    1644                 :        532 :         case JSON_VARIANT_BOOLEAN:
    1645                 :        532 :                 k = sizeof(bool);
    1646                 :        532 :                 value.boolean = json_variant_boolean(v);
    1647                 :        532 :                 source = &value;
    1648                 :        532 :                 break;
    1649                 :            : 
    1650                 :         44 :         case JSON_VARIANT_NULL:
    1651                 :         44 :                 k = 0;
    1652                 :         44 :                 source = NULL;
    1653                 :         44 :                 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                 :          8 :                 c = malloc0(MAX(sizeof(JsonVariant),
    1669                 :            :                                 offsetof(JsonVariant, reference) + sizeof(JsonVariant*)));
    1670         [ -  + ]:          8 :                 if (!c)
    1671                 :          0 :                         return -ENOMEM;
    1672                 :            : 
    1673                 :          8 :                 c->n_ref = 1;
    1674                 :          8 :                 c->type = t;
    1675                 :          8 :                 c->is_reference = true;
    1676                 :          8 :                 c->reference = json_variant_ref(json_variant_normalize(v));
    1677                 :            : 
    1678                 :          8 :                 *nv = c;
    1679                 :          8 :                 return 0;
    1680                 :            :         }
    1681                 :            : 
    1682                 :        736 :         c = malloc0(MAX(sizeof(JsonVariant),
    1683                 :            :                         offsetof(JsonVariant, value) + k));
    1684         [ -  + ]:        736 :         if (!c)
    1685                 :          0 :                 return -ENOMEM;
    1686                 :            : 
    1687                 :        736 :         c->n_ref = 1;
    1688                 :        736 :         c->type = t;
    1689                 :            : 
    1690                 :        736 :         memcpy_safe(&c->value, source, k);
    1691                 :            : 
    1692                 :        736 :         *nv = c;
    1693                 :        736 :         return 0;
    1694                 :            : }
    1695                 :            : 
    1696                 :       4772 : 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         [ -  + ]:       4772 :         if (!json_variant_is_regular(v))
    1701                 :          0 :                 return false;
    1702                 :            : 
    1703         [ -  + ]:       4772 :         if (v->is_embedded)
    1704                 :          0 :                 return json_single_ref(v->parent);
    1705                 :            : 
    1706         [ -  + ]:       4772 :         assert(v->n_ref > 0);
    1707                 :       4772 :         return v->n_ref == 1;
    1708                 :            : }
    1709                 :            : 
    1710                 :       5516 : static int json_variant_set_source(JsonVariant **v, JsonSource *source, unsigned line, unsigned column) {
    1711                 :            :         JsonVariant *w;
    1712                 :            :         int r;
    1713                 :            : 
    1714         [ -  + ]:       5516 :         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         [ -  + ]:       5516 :         if (!*v)
    1720                 :          0 :                 return 0;
    1721                 :            : 
    1722   [ +  +  +  + ]:       5516 :         if (source && line > source->max_line)
    1723                 :         32 :                 source->max_line = line;
    1724   [ +  +  +  + ]:       5516 :         if (source && column > source->max_column)
    1725                 :         24 :                 source->max_column = column;
    1726                 :            : 
    1727         [ +  + ]:       5516 :         if (!json_variant_is_regular(*v)) {
    1728                 :            : 
    1729   [ +  +  -  +  :        744 :                 if (!source && line == 0 && column == 0)
                   #  # ]
    1730                 :          0 :                         return 0;
    1731                 :            : 
    1732                 :            :         } else {
    1733         [ +  + ]:       4772 :                 if (json_source_equal((*v)->source, source) &&
    1734         [ -  + ]:       4704 :                     (*v)->line == line &&
    1735         [ #  # ]:          0 :                     (*v)->column == column)
    1736                 :          0 :                         return 0;
    1737                 :            : 
    1738         [ +  - ]:       4772 :                 if (json_single_ref(*v)) { /* Sole reference? */
    1739                 :       4772 :                         json_source_unref((*v)->source);
    1740                 :       4772 :                         (*v)->source = json_source_ref(source);
    1741                 :       4772 :                         (*v)->line = line;
    1742                 :       4772 :                         (*v)->column = column;
    1743                 :       4772 :                         return 1;
    1744                 :            :                 }
    1745                 :            :         }
    1746                 :            : 
    1747                 :        744 :         r = json_variant_copy(&w, *v);
    1748         [ -  + ]:        744 :         if (r < 0)
    1749                 :          0 :                 return r;
    1750                 :            : 
    1751         [ -  + ]:        744 :         assert(json_variant_is_regular(w));
    1752         [ -  + ]:        744 :         assert(!w->is_embedded);
    1753         [ -  + ]:        744 :         assert(w->n_ref == 1);
    1754         [ -  + ]:        744 :         assert(!w->source);
    1755                 :            : 
    1756                 :        744 :         w->source = json_source_ref(source);
    1757                 :        744 :         w->line = line;
    1758                 :        744 :         w->column = column;
    1759                 :            : 
    1760                 :        744 :         json_variant_unref(*v);
    1761                 :        744 :         *v = w;
    1762                 :            : 
    1763                 :        744 :         return 1;
    1764                 :            : }
    1765                 :            : 
    1766                 :      22752 : static void inc_lines_columns(unsigned *line, unsigned *column, const char *s, size_t n) {
    1767         [ -  + ]:      22752 :         assert(line);
    1768         [ -  + ]:      22752 :         assert(column);
    1769   [ -  +  #  # ]:      22752 :         assert(s || n == 0);
    1770                 :            : 
    1771         [ +  + ]:      64616 :         while (n > 0) {
    1772         [ +  + ]:      41864 :                 if (*s == '\n') {
    1773                 :         72 :                         (*line)++;
    1774                 :         72 :                         *column = 1;
    1775   [ +  +  +  - ]:      41792 :                 } else if ((signed char) *s >= 0 && *s < 127) /* Process ASCII chars quickly */
    1776                 :      41780 :                         (*column)++;
    1777                 :            :                 else {
    1778                 :            :                         int w;
    1779                 :            : 
    1780                 :         12 :                         w = utf8_encoded_valid_unichar(s, n);
    1781         [ -  + ]:         12 :                         if (w < 0) /* count invalid unichars as normal characters */
    1782                 :          0 :                                 w = 1;
    1783         [ -  + ]:         12 :                         else if ((size_t) w > n) /* never read more than the specified number of characters */
    1784                 :          0 :                                 w = (int) n;
    1785                 :            : 
    1786                 :         12 :                         (*column)++;
    1787                 :            : 
    1788                 :         12 :                         s += w;
    1789                 :         12 :                         n -= w;
    1790                 :         12 :                         continue;
    1791                 :            :                 }
    1792                 :            : 
    1793                 :      41852 :                 s++;
    1794                 :      41852 :                 n--;
    1795                 :            :         }
    1796                 :      22752 : }
    1797                 :            : 
    1798                 :        336 : static int unhex_ucs2(const char *c, uint16_t *ret) {
    1799                 :            :         int aa, bb, cc, dd;
    1800                 :            :         uint16_t x;
    1801                 :            : 
    1802         [ -  + ]:        336 :         assert(c);
    1803         [ -  + ]:        336 :         assert(ret);
    1804                 :            : 
    1805                 :        336 :         aa = unhexchar(c[0]);
    1806         [ -  + ]:        336 :         if (aa < 0)
    1807                 :          0 :                 return -EINVAL;
    1808                 :            : 
    1809                 :        336 :         bb = unhexchar(c[1]);
    1810         [ +  + ]:        336 :         if (bb < 0)
    1811                 :          4 :                 return -EINVAL;
    1812                 :            : 
    1813                 :        332 :         cc = unhexchar(c[2]);
    1814         [ -  + ]:        332 :         if (cc < 0)
    1815                 :          0 :                 return -EINVAL;
    1816                 :            : 
    1817                 :        332 :         dd = unhexchar(c[3]);
    1818         [ -  + ]:        332 :         if (dd < 0)
    1819                 :          0 :                 return -EINVAL;
    1820                 :            : 
    1821                 :        996 :         x =     ((uint16_t) aa << 12) |
    1822                 :        664 :                 ((uint16_t) bb << 8) |
    1823                 :        664 :                 ((uint16_t) cc << 4) |
    1824                 :        332 :                 ((uint16_t) dd);
    1825                 :            : 
    1826         [ -  + ]:        332 :         if (x <= 0)
    1827                 :          0 :                 return -EINVAL;
    1828                 :            : 
    1829                 :        332 :         *ret = x;
    1830                 :            : 
    1831                 :        332 :         return 0;
    1832                 :            : }
    1833                 :            : 
    1834                 :       2944 : static int json_parse_string(const char **p, char **ret) {
    1835                 :       2944 :         _cleanup_free_ char *s = NULL;
    1836                 :       2944 :         size_t n = 0, allocated = 0;
    1837                 :            :         const char *c;
    1838                 :            : 
    1839         [ -  + ]:       2944 :         assert(p);
    1840         [ -  + ]:       2944 :         assert(*p);
    1841         [ -  + ]:       2944 :         assert(ret);
    1842                 :            : 
    1843                 :       2944 :         c = *p;
    1844                 :            : 
    1845         [ -  + ]:       2944 :         if (*c != '"')
    1846                 :          0 :                 return -EINVAL;
    1847                 :            : 
    1848                 :       2944 :         c++;
    1849                 :            : 
    1850                 :      22272 :         for (;;) {
    1851                 :            :                 int len;
    1852                 :            : 
    1853                 :            :                 /* Check for EOF */
    1854         [ -  + ]:      25216 :                 if (*c == 0)
    1855                 :          0 :                         return -EINVAL;
    1856                 :            : 
    1857                 :            :                 /* Check for control characters 0x00..0x1f */
    1858   [ +  +  -  + ]:      25216 :                 if (*c > 0 && *c < ' ')
    1859                 :          0 :                         return -EINVAL;
    1860                 :            : 
    1861                 :            :                 /* Check for control character 0x7f */
    1862         [ -  + ]:      25216 :                 if (*c == 0x7f)
    1863                 :          0 :                         return -EINVAL;
    1864                 :            : 
    1865         [ +  + ]:      25216 :                 if (*c == '"') {
    1866         [ +  + ]:       2932 :                         if (!s) {
    1867                 :          4 :                                 s = strdup("");
    1868         [ -  + ]:          4 :                                 if (!s)
    1869                 :          0 :                                         return -ENOMEM;
    1870                 :            :                         } else
    1871                 :       2928 :                                 s[n] = 0;
    1872                 :            : 
    1873                 :       2932 :                         *p = c + 1;
    1874                 :            : 
    1875                 :       2932 :                         *ret = TAKE_PTR(s);
    1876                 :       2932 :                         return JSON_TOKEN_STRING;
    1877                 :            :                 }
    1878                 :            : 
    1879         [ +  + ]:      22284 :                 if (*c == '\\') {
    1880                 :        252 :                         char ch = 0;
    1881                 :        252 :                         c++;
    1882                 :            : 
    1883         [ -  + ]:        252 :                         if (*c == 0)
    1884                 :          0 :                                 return -EINVAL;
    1885                 :            : 
    1886   [ +  +  +  + ]:        252 :                         if (IN_SET(*c, '"', '\\', '/'))
    1887                 :         72 :                                 ch = *c;
    1888         [ -  + ]:        180 :                         else if (*c == 'b')
    1889                 :          0 :                                 ch = '\b';
    1890         [ -  + ]:        180 :                         else if (*c == 'f')
    1891                 :          0 :                                 ch = '\f';
    1892         [ +  + ]:        180 :                         else if (*c == 'n')
    1893                 :          4 :                                 ch = '\n';
    1894         [ -  + ]:        176 :                         else if (*c == 'r')
    1895                 :          0 :                                 ch = '\r';
    1896         [ -  + ]:        176 :                         else if (*c == 't')
    1897                 :          0 :                                 ch = '\t';
    1898         [ +  - ]:        176 :                         else if (*c == 'u') {
    1899                 :            :                                 char16_t x;
    1900                 :            :                                 int r;
    1901                 :            : 
    1902                 :        176 :                                 r = unhex_ucs2(c + 1, &x);
    1903         [ +  + ]:        176 :                                 if (r < 0)
    1904                 :         12 :                                         return r;
    1905                 :            : 
    1906                 :        172 :                                 c += 5;
    1907                 :            : 
    1908         [ -  + ]:        172 :                                 if (!GREEDY_REALLOC(s, allocated, n + 5))
    1909                 :          0 :                                         return -ENOMEM;
    1910                 :            : 
    1911         [ +  + ]:        172 :                                 if (!utf16_is_surrogate(x))
    1912                 :          4 :                                         n += utf8_encode_unichar(s + n, (char32_t) x);
    1913         [ +  + ]:        168 :                                 else if (utf16_is_trailing_surrogate(x))
    1914                 :          4 :                                         return -EINVAL;
    1915                 :            :                                 else {
    1916                 :            :                                         char16_t y;
    1917                 :            : 
    1918   [ +  +  -  + ]:        164 :                                         if (c[0] != '\\' || c[1] != 'u')
    1919                 :          4 :                                                 return -EINVAL;
    1920                 :            : 
    1921                 :        160 :                                         r = unhex_ucs2(c + 2, &y);
    1922         [ -  + ]:        160 :                                         if (r < 0)
    1923                 :          0 :                                                 return r;
    1924                 :            : 
    1925                 :        160 :                                         c += 6;
    1926                 :            : 
    1927         [ -  + ]:        160 :                                         if (!utf16_is_trailing_surrogate(y))
    1928                 :          0 :                                                 return -EINVAL;
    1929                 :            : 
    1930                 :        160 :                                         n += utf8_encode_unichar(s + n, utf16_surrogate_pair_to_unichar(x, y));
    1931                 :            :                                 }
    1932                 :            : 
    1933                 :        164 :                                 continue;
    1934                 :            :                         } else
    1935                 :          0 :                                 return -EINVAL;
    1936                 :            : 
    1937         [ -  + ]:         76 :                         if (!GREEDY_REALLOC(s, allocated, n + 2))
    1938                 :          0 :                                 return -ENOMEM;
    1939                 :            : 
    1940                 :         76 :                         s[n++] = ch;
    1941                 :         76 :                         c ++;
    1942                 :         76 :                         continue;
    1943                 :            :                 }
    1944                 :            : 
    1945                 :      22032 :                 len = utf8_encoded_valid_unichar(c, (size_t) -1);
    1946         [ -  + ]:      22032 :                 if (len < 0)
    1947                 :          0 :                         return len;
    1948                 :            : 
    1949         [ -  + ]:      22032 :                 if (!GREEDY_REALLOC(s, allocated, n + len + 1))
    1950                 :          0 :                         return -ENOMEM;
    1951                 :            : 
    1952                 :      22032 :                 memcpy(s + n, c, len);
    1953                 :      22032 :                 n += len;
    1954                 :      22032 :                 c += len;
    1955                 :            :         }
    1956                 :            : }
    1957                 :            : 
    1958                 :        872 : static int json_parse_number(const char **p, JsonValue *ret) {
    1959                 :        872 :         bool negative = false, exponent_negative = false, is_real = false;
    1960                 :        872 :         long double x = 0.0, y = 0.0, exponent = 0.0, shift = 1.0;
    1961                 :        872 :         intmax_t i = 0;
    1962                 :        872 :         uintmax_t u = 0;
    1963                 :            :         const char *c;
    1964                 :            : 
    1965         [ -  + ]:        872 :         assert(p);
    1966         [ -  + ]:        872 :         assert(*p);
    1967         [ -  + ]:        872 :         assert(ret);
    1968                 :            : 
    1969                 :        872 :         c = *p;
    1970                 :            : 
    1971         [ +  + ]:        872 :         if (*c == '-') {
    1972                 :        100 :                 negative = true;
    1973                 :        100 :                 c++;
    1974                 :            :         }
    1975                 :            : 
    1976         [ +  + ]:        872 :         if (*c == '0')
    1977                 :        172 :                 c++;
    1978                 :            :         else {
    1979   [ +  -  -  + ]:        700 :                 if (!strchr("123456789", *c) || *c == 0)
    1980                 :          0 :                         return -EINVAL;
    1981                 :            : 
    1982                 :            :                 do {
    1983         [ +  - ]:       1652 :                         if (!is_real) {
    1984         [ +  + ]:       1652 :                                 if (negative) {
    1985                 :            : 
    1986         [ -  + ]:        192 :                                         if (i < INTMAX_MIN / 10) /* overflow */
    1987                 :          0 :                                                 is_real = true;
    1988                 :            :                                         else {
    1989                 :        192 :                                                 intmax_t t = 10 * i;
    1990                 :            : 
    1991         [ +  + ]:        192 :                                                 if (t < INTMAX_MIN + (*c - '0')) /* overflow */
    1992                 :          4 :                                                         is_real = true;
    1993                 :            :                                                 else
    1994                 :        188 :                                                         i = t - (*c - '0');
    1995                 :            :                                         }
    1996                 :            :                                 } else {
    1997         [ -  + ]:       1460 :                                         if (u > UINTMAX_MAX / 10) /* overflow */
    1998                 :          0 :                                                 is_real = true;
    1999                 :            :                                         else {
    2000                 :       1460 :                                                 uintmax_t t = 10 * u;
    2001                 :            : 
    2002         [ +  + ]:       1460 :                                                 if (t > UINTMAX_MAX - (*c - '0')) /* overflow */
    2003                 :          4 :                                                         is_real = true;
    2004                 :            :                                                 else
    2005                 :       1456 :                                                         u = t + (*c - '0');
    2006                 :            :                                         }
    2007                 :            :                                 }
    2008                 :            :                         }
    2009                 :            : 
    2010                 :       1652 :                         x = 10.0 * x + (*c - '0');
    2011                 :            : 
    2012                 :       1652 :                         c++;
    2013   [ +  +  +  + ]:       1652 :                 } while (strchr("0123456789", *c) && *c != 0);
    2014                 :            :         }
    2015                 :            : 
    2016         [ +  + ]:        872 :         if (*c == '.') {
    2017                 :         80 :                 is_real = true;
    2018                 :         80 :                 c++;
    2019                 :            : 
    2020   [ +  -  -  + ]:         80 :                 if (!strchr("0123456789", *c) || *c == 0)
    2021                 :          0 :                         return -EINVAL;
    2022                 :            : 
    2023                 :            :                 do {
    2024                 :        308 :                         y = 10.0 * y + (*c - '0');
    2025                 :        308 :                         shift = 10.0 * shift;
    2026                 :        308 :                         c++;
    2027   [ +  +  +  + ]:        308 :                 } while (strchr("0123456789", *c) && *c != 0);
    2028                 :            :         }
    2029                 :            : 
    2030   [ +  +  +  + ]:        872 :         if (IN_SET(*c, 'e', 'E')) {
    2031                 :        100 :                 is_real = true;
    2032                 :        100 :                 c++;
    2033                 :            : 
    2034         [ +  + ]:        100 :                 if (*c == '-') {
    2035                 :         28 :                         exponent_negative = true;
    2036                 :         28 :                         c++;
    2037         [ +  + ]:         72 :                 } else if (*c == '+')
    2038                 :         32 :                         c++;
    2039                 :            : 
    2040   [ +  -  -  + ]:        100 :                 if (!strchr("0123456789", *c) || *c == 0)
    2041                 :          0 :                         return -EINVAL;
    2042                 :            : 
    2043                 :            :                 do {
    2044                 :        156 :                         exponent = 10.0 * exponent + (*c - '0');
    2045                 :        156 :                         c++;
    2046   [ +  +  +  + ]:        156 :                 } while (strchr("0123456789", *c) && *c != 0);
    2047                 :            :         }
    2048                 :            : 
    2049                 :        872 :         *p = c;
    2050                 :            : 
    2051         [ +  + ]:        872 :         if (is_real) {
    2052   [ +  +  +  + ]:        180 :                 ret->real = ((negative ? -1.0 : 1.0) * (x + (y / shift))) * exp10l((exponent_negative ? -1.0 : 1.0) * exponent);
    2053                 :        180 :                 return JSON_TOKEN_REAL;
    2054         [ +  + ]:        692 :         } else if (negative) {
    2055                 :         32 :                 ret->integer = i;
    2056                 :         32 :                 return JSON_TOKEN_INTEGER;
    2057                 :            :         } else  {
    2058                 :        660 :                 ret->unsig = u;
    2059                 :        660 :                 return JSON_TOKEN_UNSIGNED;
    2060                 :            :         }
    2061                 :            : }
    2062                 :            : 
    2063                 :      11384 : 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         [ -  + ]:      11384 :         assert(p);
    2085         [ -  + ]:      11384 :         assert(*p);
    2086         [ -  + ]:      11384 :         assert(ret_string);
    2087         [ -  + ]:      11384 :         assert(ret_value);
    2088         [ -  + ]:      11384 :         assert(ret_line);
    2089         [ -  + ]:      11384 :         assert(ret_column);
    2090         [ -  + ]:      11384 :         assert(line);
    2091         [ -  + ]:      11384 :         assert(column);
    2092         [ -  + ]:      11384 :         assert(state);
    2093                 :            : 
    2094                 :      11384 :         t = PTR_TO_INT(*state);
    2095         [ +  + ]:      11384 :         if (t == STATE_NULL) {
    2096                 :        748 :                 *line = 1;
    2097                 :        748 :                 *column = 1;
    2098                 :        748 :                 t = STATE_VALUE;
    2099                 :            :         }
    2100                 :            : 
    2101                 :            :         /* Skip over the whitespace */
    2102                 :      11384 :         n = strspn(*p, WHITESPACE);
    2103                 :      11384 :         inc_lines_columns(line, column, *p, n);
    2104                 :      11384 :         c = *p + n;
    2105                 :            : 
    2106                 :            :         /* Remember where we started processing this token */
    2107                 :      11384 :         start = c;
    2108                 :      11384 :         start_line = *line;
    2109                 :      11384 :         start_column = *column;
    2110                 :            : 
    2111         [ +  + ]:      11384 :         if (*c == 0) {
    2112                 :        732 :                 *ret_string = NULL;
    2113                 :        732 :                 *ret_value = JSON_VALUE_NULL;
    2114                 :        732 :                 r = JSON_TOKEN_END;
    2115                 :        732 :                 goto finish;
    2116                 :            :         }
    2117                 :            : 
    2118      [ +  +  - ]:      10652 :         switch (t) {
    2119                 :            : 
    2120                 :       5708 :         case STATE_VALUE:
    2121                 :            : 
    2122         [ +  + ]:       5708 :                 if (*c == '{') {
    2123                 :       1184 :                         c++;
    2124                 :       1184 :                         *state = INT_TO_PTR(STATE_VALUE);
    2125                 :       1184 :                         r = JSON_TOKEN_OBJECT_OPEN;
    2126                 :       1184 :                         goto null_return;
    2127                 :            : 
    2128         [ +  + ]:       4524 :                 } else if (*c == '}') {
    2129                 :         16 :                         c++;
    2130                 :         16 :                         *state = INT_TO_PTR(STATE_VALUE_POST);
    2131                 :         16 :                         r = JSON_TOKEN_OBJECT_CLOSE;
    2132                 :         16 :                         goto null_return;
    2133                 :            : 
    2134         [ +  + ]:       4508 :                 } else if (*c == '[') {
    2135                 :         84 :                         c++;
    2136                 :         84 :                         *state = INT_TO_PTR(STATE_VALUE);
    2137                 :         84 :                         r = JSON_TOKEN_ARRAY_OPEN;
    2138                 :         84 :                         goto null_return;
    2139                 :            : 
    2140         [ +  + ]:       4424 :                 } else if (*c == ']') {
    2141                 :          8 :                         c++;
    2142                 :          8 :                         *state = INT_TO_PTR(STATE_VALUE_POST);
    2143                 :          8 :                         r = JSON_TOKEN_ARRAY_CLOSE;
    2144                 :          8 :                         goto null_return;
    2145                 :            : 
    2146         [ +  + ]:       4416 :                 } else if (*c == '"') {
    2147                 :            : 
    2148                 :       2944 :                         r = json_parse_string(&c, ret_string);
    2149         [ +  + ]:       2944 :                         if (r < 0)
    2150                 :         12 :                                 return r;
    2151                 :            : 
    2152                 :       2932 :                         *ret_value = JSON_VALUE_NULL;
    2153                 :       2932 :                         *state = INT_TO_PTR(STATE_VALUE_POST);
    2154                 :       2932 :                         goto finish;
    2155                 :            : 
    2156         [ +  + ]:       1472 :                 } else if (strchr("-0123456789", *c)) {
    2157                 :            : 
    2158                 :        872 :                         r = json_parse_number(&c, ret_value);
    2159         [ -  + ]:        872 :                         if (r < 0)
    2160                 :          0 :                                 return r;
    2161                 :            : 
    2162                 :        872 :                         *ret_string = NULL;
    2163                 :        872 :                         *state = INT_TO_PTR(STATE_VALUE_POST);
    2164                 :        872 :                         goto finish;
    2165                 :            : 
    2166         [ +  + ]:        600 :                 } else if (startswith(c, "true")) {
    2167                 :        536 :                         *ret_string = NULL;
    2168                 :        536 :                         ret_value->boolean = true;
    2169                 :        536 :                         c += 4;
    2170                 :        536 :                         *state = INT_TO_PTR(STATE_VALUE_POST);
    2171                 :        536 :                         r = JSON_TOKEN_BOOLEAN;
    2172                 :        536 :                         goto finish;
    2173                 :            : 
    2174         [ +  + ]:         64 :                 } else if (startswith(c, "false")) {
    2175                 :         12 :                         *ret_string = NULL;
    2176                 :         12 :                         ret_value->boolean = false;
    2177                 :         12 :                         c += 5;
    2178                 :         12 :                         *state = INT_TO_PTR(STATE_VALUE_POST);
    2179                 :         12 :                         r = JSON_TOKEN_BOOLEAN;
    2180                 :         12 :                         goto finish;
    2181                 :            : 
    2182         [ +  + ]:         52 :                 } else if (startswith(c, "null")) {
    2183                 :         48 :                         *ret_string = NULL;
    2184                 :         48 :                         *ret_value = JSON_VALUE_NULL;
    2185                 :         48 :                         c += 4;
    2186                 :         48 :                         *state = INT_TO_PTR(STATE_VALUE_POST);
    2187                 :         48 :                         r = JSON_TOKEN_NULL;
    2188                 :         48 :                         goto finish;
    2189                 :            : 
    2190                 :            :                 }
    2191                 :            : 
    2192                 :          4 :                 return -EINVAL;
    2193                 :            : 
    2194                 :       4944 :         case STATE_VALUE_POST:
    2195                 :            : 
    2196         [ +  + ]:       4944 :                 if (*c == ':') {
    2197                 :       2284 :                         c++;
    2198                 :       2284 :                         *state = INT_TO_PTR(STATE_VALUE);
    2199                 :       2284 :                         r = JSON_TOKEN_COLON;
    2200                 :       2284 :                         goto null_return;
    2201                 :            : 
    2202         [ +  + ]:       2660 :                 } else if (*c == ',') {
    2203                 :       1416 :                         c++;
    2204                 :       1416 :                         *state = INT_TO_PTR(STATE_VALUE);
    2205                 :       1416 :                         r = JSON_TOKEN_COMMA;
    2206                 :       1416 :                         goto null_return;
    2207                 :            : 
    2208         [ +  + ]:       1244 :                 } else if (*c == '}') {
    2209                 :       1168 :                         c++;
    2210                 :       1168 :                         *state = INT_TO_PTR(STATE_VALUE_POST);
    2211                 :       1168 :                         r = JSON_TOKEN_OBJECT_CLOSE;
    2212                 :       1168 :                         goto null_return;
    2213                 :            : 
    2214         [ +  - ]:         76 :                 } else if (*c == ']') {
    2215                 :         76 :                         c++;
    2216                 :         76 :                         *state = INT_TO_PTR(STATE_VALUE_POST);
    2217                 :         76 :                         r = JSON_TOKEN_ARRAY_CLOSE;
    2218                 :         76 :                         goto null_return;
    2219                 :            :                 }
    2220                 :            : 
    2221                 :          0 :                 return -EINVAL;
    2222                 :            : 
    2223                 :          0 :         default:
    2224                 :          0 :                 assert_not_reached("Unexpected tokenizer state");
    2225                 :            :         }
    2226                 :            : 
    2227                 :       6236 : null_return:
    2228                 :       6236 :         *ret_string = NULL;
    2229                 :       6236 :         *ret_value = JSON_VALUE_NULL;
    2230                 :            : 
    2231                 :      11368 : finish:
    2232                 :      11368 :         inc_lines_columns(line, column, start, c - start);
    2233                 :      11368 :         *p = c;
    2234                 :            : 
    2235                 :      11368 :         *ret_line = start_line;
    2236                 :      11368 :         *ret_column = start_column;
    2237                 :            : 
    2238                 :      11368 :         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                 :       7368 : static void json_stack_release(JsonStack *s) {
    2269         [ -  + ]:       7368 :         assert(s);
    2270                 :            : 
    2271                 :       7368 :         json_variant_unref_many(s->elements, s->n_elements);
    2272                 :       7368 :         s->elements = mfree(s->elements);
    2273                 :       7368 : }
    2274                 :            : 
    2275                 :        608 : 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                 :        608 :         size_t n_stack = 1, n_stack_allocated = 0, i;
    2284                 :        608 :         unsigned line_buffer = 0, column_buffer = 0;
    2285                 :        608 :         void *tokenizer_state = NULL;
    2286                 :        608 :         JsonStack *stack = NULL;
    2287                 :            :         const char *p;
    2288                 :            :         int r;
    2289                 :            : 
    2290   [ -  +  -  + ]:        608 :         assert_return(input, -EINVAL);
    2291   [ -  +  -  + ]:        608 :         assert_return(ret, -EINVAL);
    2292                 :            : 
    2293                 :        608 :         p = *input;
    2294                 :            : 
    2295         [ -  + ]:        608 :         if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack))
    2296                 :          0 :                 return -ENOMEM;
    2297                 :            : 
    2298                 :        608 :         stack[0] = (JsonStack) {
    2299                 :            :                 .expect = EXPECT_TOPLEVEL,
    2300                 :            :         };
    2301                 :            : 
    2302         [ +  - ]:        608 :         if (!line)
    2303                 :        608 :                 line = &line_buffer;
    2304         [ +  - ]:        608 :         if (!column)
    2305                 :        608 :                 column = &column_buffer;
    2306                 :            : 
    2307                 :      10432 :         for (;;) {
    2308      [ +  +  - ]:      11040 :                 _cleanup_(json_variant_unrefp) JsonVariant *add = NULL;
    2309      [ +  +  - ]:      11040 :                 _cleanup_free_ char *string = NULL;
    2310                 :            :                 unsigned line_token, column_token;
    2311                 :            :                 JsonStack *current;
    2312                 :            :                 JsonValue value;
    2313                 :            :                 int token;
    2314                 :            : 
    2315         [ -  + ]:      11040 :                 assert(n_stack > 0);
    2316                 :      11040 :                 current = stack + n_stack - 1;
    2317                 :            : 
    2318   [ -  +  #  # ]:      11040 :                 if (continue_end && current->expect == EXPECT_END)
    2319                 :          0 :                         goto done;
    2320                 :            : 
    2321                 :      11040 :                 token = json_tokenize(&p, &string, &value, &line_token, &column_token, &tokenizer_state, line, column);
    2322         [ -  + ]:      11040 :                 if (token < 0) {
    2323                 :          0 :                         r = token;
    2324                 :          0 :                         goto finish;
    2325                 :            :                 }
    2326                 :            : 
    2327   [ +  +  +  +  :      11040 :                 switch (token) {
          +  +  +  +  +  
             +  +  +  +  
                      - ]
    2328                 :            : 
    2329                 :        608 :                 case JSON_TOKEN_END:
    2330         [ -  + ]:        608 :                         if (current->expect != EXPECT_END) {
    2331                 :          0 :                                 r = -EINVAL;
    2332                 :          0 :                                 goto finish;
    2333                 :            :                         }
    2334                 :            : 
    2335         [ -  + ]:        608 :                         assert(current->n_elements == 1);
    2336         [ -  + ]:        608 :                         assert(n_stack == 1);
    2337                 :        608 :                         goto done;
    2338                 :            : 
    2339                 :       2276 :                 case JSON_TOKEN_COLON:
    2340                 :            : 
    2341         [ -  + ]:       2276 :                         if (current->expect != EXPECT_OBJECT_COLON) {
    2342                 :          0 :                                 r = -EINVAL;
    2343                 :          0 :                                 goto finish;
    2344                 :            :                         }
    2345                 :            : 
    2346                 :       2276 :                         current->expect = EXPECT_OBJECT_VALUE;
    2347                 :       2276 :                         break;
    2348                 :            : 
    2349                 :       1404 :                 case JSON_TOKEN_COMMA:
    2350                 :            : 
    2351         [ +  + ]:       1404 :                         if (current->expect == EXPECT_OBJECT_COMMA)
    2352                 :       1116 :                                 current->expect = EXPECT_OBJECT_NEXT_KEY;
    2353         [ +  - ]:        288 :                         else if (current->expect == EXPECT_ARRAY_COMMA)
    2354                 :        288 :                                 current->expect = EXPECT_ARRAY_NEXT_ELEMENT;
    2355                 :            :                         else {
    2356                 :          0 :                                 r = -EINVAL;
    2357                 :          0 :                                 goto finish;
    2358                 :            :                         }
    2359                 :            : 
    2360                 :       1404 :                         break;
    2361                 :            : 
    2362                 :       1168 :                 case JSON_TOKEN_OBJECT_OPEN:
    2363                 :            : 
    2364   [ +  -  -  + ]:       1168 :                         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         [ -  + ]:       1168 :                         if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
    2370                 :          0 :                                 r = -ENOMEM;
    2371                 :          0 :                                 goto finish;
    2372                 :            :                         }
    2373                 :       1168 :                         current = stack + n_stack - 1;
    2374                 :            : 
    2375                 :            :                         /* Prepare the expect for when we return from the child */
    2376         [ +  + ]:       1168 :                         if (current->expect == EXPECT_TOPLEVEL)
    2377                 :        584 :                                 current->expect = EXPECT_END;
    2378         [ +  + ]:        584 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2379                 :        564 :                                 current->expect = EXPECT_OBJECT_COMMA;
    2380                 :            :                         else {
    2381   [ +  -  -  + ]:         20 :                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
    2382                 :         20 :                                 current->expect = EXPECT_ARRAY_COMMA;
    2383                 :            :                         }
    2384                 :            : 
    2385                 :       1168 :                         stack[n_stack++] = (JsonStack) {
    2386                 :            :                                 .expect = EXPECT_OBJECT_FIRST_KEY,
    2387                 :            :                                 .line_before = line_token,
    2388                 :            :                                 .column_before = column_token,
    2389                 :            :                         };
    2390                 :            : 
    2391                 :       1168 :                         current = stack + n_stack - 1;
    2392                 :       1168 :                         break;
    2393                 :            : 
    2394                 :       1168 :                 case JSON_TOKEN_OBJECT_CLOSE:
    2395   [ +  -  -  + ]:       1168 :                         if (!IN_SET(current->expect, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_COMMA)) {
    2396                 :          0 :                                 r = -EINVAL;
    2397                 :          0 :                                 goto finish;
    2398                 :            :                         }
    2399                 :            : 
    2400         [ -  + ]:       1168 :                         assert(n_stack > 1);
    2401                 :            : 
    2402                 :       1168 :                         r = json_variant_new_object(&add, current->elements, current->n_elements);
    2403         [ -  + ]:       1168 :                         if (r < 0)
    2404                 :          0 :                                 goto finish;
    2405                 :            : 
    2406                 :       1168 :                         line_token = current->line_before;
    2407                 :       1168 :                         column_token = current->column_before;
    2408                 :            : 
    2409                 :       1168 :                         json_stack_release(current);
    2410                 :       1168 :                         n_stack--, current--;
    2411                 :            : 
    2412                 :       1168 :                         break;
    2413                 :            : 
    2414                 :         68 :                 case JSON_TOKEN_ARRAY_OPEN:
    2415   [ +  -  -  + ]:         68 :                         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         [ -  + ]:         68 :                         if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
    2421                 :          0 :                                 r = -ENOMEM;
    2422                 :          0 :                                 goto finish;
    2423                 :            :                         }
    2424                 :         68 :                         current = stack + n_stack - 1;
    2425                 :            : 
    2426                 :            :                         /* Prepare the expect for when we return from the child */
    2427         [ +  + ]:         68 :                         if (current->expect == EXPECT_TOPLEVEL)
    2428                 :         16 :                                 current->expect = EXPECT_END;
    2429         [ +  + ]:         52 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2430                 :         44 :                                 current->expect = EXPECT_OBJECT_COMMA;
    2431                 :            :                         else {
    2432   [ +  -  -  + ]:          8 :                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
    2433                 :          8 :                                 current->expect = EXPECT_ARRAY_COMMA;
    2434                 :            :                         }
    2435                 :            : 
    2436                 :         68 :                         stack[n_stack++] = (JsonStack) {
    2437                 :            :                                 .expect = EXPECT_ARRAY_FIRST_ELEMENT,
    2438                 :            :                                 .line_before = line_token,
    2439                 :            :                                 .column_before = column_token,
    2440                 :            :                         };
    2441                 :            : 
    2442                 :         68 :                         break;
    2443                 :            : 
    2444                 :         68 :                 case JSON_TOKEN_ARRAY_CLOSE:
    2445   [ +  -  -  + ]:         68 :                         if (!IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_COMMA)) {
    2446                 :          0 :                                 r = -EINVAL;
    2447                 :          0 :                                 goto finish;
    2448                 :            :                         }
    2449                 :            : 
    2450         [ -  + ]:         68 :                         assert(n_stack > 1);
    2451                 :            : 
    2452                 :         68 :                         r = json_variant_new_array(&add, current->elements, current->n_elements);
    2453         [ -  + ]:         68 :                         if (r < 0)
    2454                 :          0 :                                 goto finish;
    2455                 :            : 
    2456                 :         68 :                         line_token = current->line_before;
    2457                 :         68 :                         column_token = current->column_before;
    2458                 :            : 
    2459                 :         68 :                         json_stack_release(current);
    2460                 :         68 :                         n_stack--, current--;
    2461                 :         68 :                         break;
    2462                 :            : 
    2463                 :       2896 :                 case JSON_TOKEN_STRING:
    2464   [ +  -  -  + ]:       2896 :                         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                 :       2896 :                         r = json_variant_new_string(&add, string);
    2470         [ -  + ]:       2896 :                         if (r < 0)
    2471                 :          0 :                                 goto finish;
    2472                 :            : 
    2473         [ +  + ]:       2896 :                         if (current->expect == EXPECT_TOPLEVEL)
    2474                 :          4 :                                 current->expect = EXPECT_END;
    2475   [ +  +  +  + ]:       2892 :                         else if (IN_SET(current->expect, EXPECT_OBJECT_FIRST_KEY, EXPECT_OBJECT_NEXT_KEY))
    2476                 :       2276 :                                 current->expect = EXPECT_OBJECT_COLON;
    2477         [ +  + ]:        616 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2478                 :        568 :                                 current->expect = EXPECT_OBJECT_COMMA;
    2479                 :            :                         else {
    2480   [ +  -  -  + ]:         48 :                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
    2481                 :         48 :                                 current->expect = EXPECT_ARRAY_COMMA;
    2482                 :            :                         }
    2483                 :            : 
    2484                 :       2896 :                         break;
    2485                 :            : 
    2486                 :        156 :                 case JSON_TOKEN_REAL:
    2487   [ +  -  -  + ]:        156 :                         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                 :        156 :                         r = json_variant_new_real(&add, value.real);
    2493         [ -  + ]:        156 :                         if (r < 0)
    2494                 :          0 :                                 goto finish;
    2495                 :            : 
    2496         [ +  + ]:        156 :                         if (current->expect == EXPECT_TOPLEVEL)
    2497                 :          4 :                                 current->expect = EXPECT_END;
    2498         [ +  + ]:        152 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2499                 :         16 :                                 current->expect = EXPECT_OBJECT_COMMA;
    2500                 :            :                         else {
    2501   [ +  -  -  + ]:        136 :                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
    2502                 :        136 :                                 current->expect = EXPECT_ARRAY_COMMA;
    2503                 :            :                         }
    2504                 :            : 
    2505                 :        156 :                         break;
    2506                 :            : 
    2507                 :         12 :                 case JSON_TOKEN_INTEGER:
    2508   [ +  -  -  + ]:         12 :                         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                 :         12 :                         r = json_variant_new_integer(&add, value.integer);
    2514         [ -  + ]:         12 :                         if (r < 0)
    2515                 :          0 :                                 goto finish;
    2516                 :            : 
    2517         [ -  + ]:         12 :                         if (current->expect == EXPECT_TOPLEVEL)
    2518                 :          0 :                                 current->expect = EXPECT_END;
    2519         [ -  + ]:         12 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2520                 :          0 :                                 current->expect = EXPECT_OBJECT_COMMA;
    2521                 :            :                         else {
    2522   [ +  -  -  + ]:         12 :                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
    2523                 :         12 :                                 current->expect = EXPECT_ARRAY_COMMA;
    2524                 :            :                         }
    2525                 :            : 
    2526                 :         12 :                         break;
    2527                 :            : 
    2528                 :        640 :                 case JSON_TOKEN_UNSIGNED:
    2529   [ +  -  -  + ]:        640 :                         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                 :        640 :                         r = json_variant_new_unsigned(&add, value.unsig);
    2535         [ -  + ]:        640 :                         if (r < 0)
    2536                 :          0 :                                 goto finish;
    2537                 :            : 
    2538         [ -  + ]:        640 :                         if (current->expect == EXPECT_TOPLEVEL)
    2539                 :          0 :                                 current->expect = EXPECT_END;
    2540         [ +  + ]:        640 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2541                 :        544 :                                 current->expect = EXPECT_OBJECT_COMMA;
    2542                 :            :                         else {
    2543   [ +  -  -  + ]:         96 :                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
    2544                 :         96 :                                 current->expect = EXPECT_ARRAY_COMMA;
    2545                 :            :                         }
    2546                 :            : 
    2547                 :        640 :                         break;
    2548                 :            : 
    2549                 :        532 :                 case JSON_TOKEN_BOOLEAN:
    2550   [ +  -  -  + ]:        532 :                         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                 :        532 :                         r = json_variant_new_boolean(&add, value.boolean);
    2556         [ -  + ]:        532 :                         if (r < 0)
    2557                 :          0 :                                 goto finish;
    2558                 :            : 
    2559         [ -  + ]:        532 :                         if (current->expect == EXPECT_TOPLEVEL)
    2560                 :          0 :                                 current->expect = EXPECT_END;
    2561         [ +  + ]:        532 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2562                 :        524 :                                 current->expect = EXPECT_OBJECT_COMMA;
    2563                 :            :                         else {
    2564   [ +  -  -  + ]:          8 :                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
    2565                 :          8 :                                 current->expect = EXPECT_ARRAY_COMMA;
    2566                 :            :                         }
    2567                 :            : 
    2568                 :        532 :                         break;
    2569                 :            : 
    2570                 :         44 :                 case JSON_TOKEN_NULL:
    2571   [ +  -  -  + ]:         44 :                         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                 :         44 :                         r = json_variant_new_null(&add);
    2577         [ -  + ]:         44 :                         if (r < 0)
    2578                 :          0 :                                 goto finish;
    2579                 :            : 
    2580         [ -  + ]:         44 :                         if (current->expect == EXPECT_TOPLEVEL)
    2581                 :          0 :                                 current->expect = EXPECT_END;
    2582         [ +  + ]:         44 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2583                 :         16 :                                 current->expect = EXPECT_OBJECT_COMMA;
    2584                 :            :                         else {
    2585   [ +  -  -  + ]:         28 :                                 assert(IN_SET(current->expect, EXPECT_ARRAY_FIRST_ELEMENT, EXPECT_ARRAY_NEXT_ELEMENT));
    2586                 :         28 :                                 current->expect = EXPECT_ARRAY_COMMA;
    2587                 :            :                         }
    2588                 :            : 
    2589                 :         44 :                         break;
    2590                 :            : 
    2591                 :          0 :                 default:
    2592                 :          0 :                         assert_not_reached("Unexpected token");
    2593                 :            :                 }
    2594                 :            : 
    2595         [ +  + ]:      10432 :                 if (add) {
    2596                 :       5516 :                         (void) json_variant_set_source(&add, source, line_token, column_token);
    2597                 :            : 
    2598         [ -  + ]:       5516 :                         if (!GREEDY_REALLOC(current->elements, current->n_elements_allocated, current->n_elements + 1)) {
    2599                 :          0 :                                 r = -ENOMEM;
    2600                 :          0 :                                 goto finish;
    2601                 :            :                         }
    2602                 :            : 
    2603                 :       5516 :                         current->elements[current->n_elements++] = TAKE_PTR(add);
    2604                 :            :                 }
    2605                 :            :         }
    2606                 :            : 
    2607                 :        608 : done:
    2608         [ -  + ]:        608 :         assert(n_stack == 1);
    2609         [ -  + ]:        608 :         assert(stack[0].n_elements == 1);
    2610                 :            : 
    2611                 :        608 :         *ret = json_variant_ref(stack[0].elements[0]);
    2612                 :        608 :         *input = p;
    2613                 :        608 :         r = 0;
    2614                 :            : 
    2615                 :        608 : finish:
    2616         [ +  + ]:       1216 :         for (i = 0; i < n_stack; i++)
    2617                 :        608 :                 json_stack_release(stack + i);
    2618                 :            : 
    2619                 :        608 :         free(stack);
    2620                 :            : 
    2621                 :        608 :         return r;
    2622                 :            : }
    2623                 :            : 
    2624                 :        604 : int json_parse(const char *input, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
    2625                 :        604 :         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                 :          4 : int json_parse_file(FILE *f, const char *path, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
    2633                 :          4 :         _cleanup_(json_source_unrefp) JsonSource *source = NULL;
    2634                 :          4 :         _cleanup_free_ char *text = NULL;
    2635                 :            :         const char *p;
    2636                 :            :         int r;
    2637                 :            : 
    2638         [ +  - ]:          4 :         if (f)
    2639                 :          4 :                 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         [ -  + ]:          4 :         if (r < 0)
    2645                 :          0 :                 return r;
    2646                 :            : 
    2647         [ +  - ]:          4 :         if (path) {
    2648                 :          4 :                 source = json_source_new(path);
    2649         [ -  + ]:          4 :                 if (!source)
    2650                 :          0 :                         return -ENOMEM;
    2651                 :            :         }
    2652                 :            : 
    2653                 :          4 :         p = text;
    2654                 :          4 :         return json_parse_internal(&p, source, ret, ret_line, ret_column, false);
    2655                 :            : }
    2656                 :            : 
    2657                 :       2764 : int json_buildv(JsonVariant **ret, va_list ap) {
    2658                 :       2764 :         JsonStack *stack = NULL;
    2659                 :       2764 :         size_t n_stack = 1, n_stack_allocated = 0, i;
    2660                 :            :         int r;
    2661                 :            : 
    2662   [ -  +  -  + ]:       2764 :         assert_return(ret, -EINVAL);
    2663                 :            : 
    2664         [ -  + ]:       2764 :         if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack))
    2665                 :          0 :                 return -ENOMEM;
    2666                 :            : 
    2667                 :       2764 :         stack[0] = (JsonStack) {
    2668                 :            :                 .expect = EXPECT_TOPLEVEL,
    2669                 :            :         };
    2670                 :            : 
    2671                 :      16560 :         for (;;) {
    2672      [ +  +  - ]:      19324 :                 _cleanup_(json_variant_unrefp) JsonVariant *add = NULL;
    2673                 :      19324 :                 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         [ -  + ]:      19324 :                 assert(n_stack > 0);
    2679                 :      19324 :                 current = stack + n_stack - 1;
    2680                 :            : 
    2681         [ +  + ]:      19324 :                 if (current->expect == EXPECT_END)
    2682                 :       2764 :                         goto done;
    2683                 :            : 
    2684                 :      16560 :                 command = va_arg(ap, int);
    2685                 :            : 
    2686   [ +  +  -  +  :      16560 :                 switch (command) {
          +  +  +  +  +  
          +  +  +  +  +  
                   +  - ]
    2687                 :            : 
    2688                 :       1416 :                 case _JSON_BUILD_STRING: {
    2689                 :            :                         const char *p;
    2690                 :            : 
    2691   [ +  -  -  + ]:       1416 :                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
    2692                 :          0 :                                 r = -EINVAL;
    2693                 :          0 :                                 goto finish;
    2694                 :            :                         }
    2695                 :            : 
    2696                 :       1416 :                         p = va_arg(ap, const char *);
    2697                 :            : 
    2698         [ +  + ]:       1416 :                         if (current->n_suppress == 0) {
    2699                 :       1400 :                                 r = json_variant_new_string(&add, p);
    2700         [ -  + ]:       1400 :                                 if (r < 0)
    2701                 :          0 :                                         goto finish;
    2702                 :            :                         }
    2703                 :            : 
    2704                 :       1416 :                         n_subtract = 1;
    2705                 :            : 
    2706         [ +  + ]:       1416 :                         if (current->expect == EXPECT_TOPLEVEL)
    2707                 :          8 :                                 current->expect = EXPECT_END;
    2708         [ +  + ]:       1408 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2709                 :       1392 :                                 current->expect = EXPECT_OBJECT_KEY;
    2710                 :            :                         else
    2711         [ -  + ]:         16 :                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
    2712                 :            : 
    2713                 :       1416 :                         break;
    2714                 :            :                 }
    2715                 :            : 
    2716                 :       1372 :                 case _JSON_BUILD_INTEGER: {
    2717                 :            :                         intmax_t j;
    2718                 :            : 
    2719   [ +  -  -  + ]:       1372 :                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
    2720                 :          0 :                                 r = -EINVAL;
    2721                 :          0 :                                 goto finish;
    2722                 :            :                         }
    2723                 :            : 
    2724                 :       1372 :                         j = va_arg(ap, intmax_t);
    2725                 :            : 
    2726         [ +  - ]:       1372 :                         if (current->n_suppress == 0) {
    2727                 :       1372 :                                 r = json_variant_new_integer(&add, j);
    2728         [ -  + ]:       1372 :                                 if (r < 0)
    2729                 :          0 :                                         goto finish;
    2730                 :            :                         }
    2731                 :            : 
    2732                 :       1372 :                         n_subtract = 1;
    2733                 :            : 
    2734         [ -  + ]:       1372 :                         if (current->expect == EXPECT_TOPLEVEL)
    2735                 :          0 :                                 current->expect = EXPECT_END;
    2736         [ +  + ]:       1372 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2737                 :       1368 :                                 current->expect = EXPECT_OBJECT_KEY;
    2738                 :            :                         else
    2739         [ -  + ]:          4 :                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
    2740                 :            : 
    2741                 :       1372 :                         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                 :         20 :                 case _JSON_BUILD_REAL: {
    2773                 :            :                         long double d;
    2774                 :            : 
    2775   [ +  -  -  + ]:         20 :                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
    2776                 :          0 :                                 r = -EINVAL;
    2777                 :          0 :                                 goto finish;
    2778                 :            :                         }
    2779                 :            : 
    2780                 :         20 :                         d = va_arg(ap, long double);
    2781                 :            : 
    2782         [ +  - ]:         20 :                         if (current->n_suppress == 0) {
    2783                 :         20 :                                 r = json_variant_new_real(&add, d);
    2784         [ -  + ]:         20 :                                 if (r < 0)
    2785                 :          0 :                                         goto finish;
    2786                 :            :                         }
    2787                 :            : 
    2788                 :         20 :                         n_subtract = 1;
    2789                 :            : 
    2790         [ +  + ]:         20 :                         if (current->expect == EXPECT_TOPLEVEL)
    2791                 :          4 :                                 current->expect = EXPECT_END;
    2792         [ +  - ]:         16 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2793                 :         16 :                                 current->expect = EXPECT_OBJECT_KEY;
    2794                 :            :                         else
    2795         [ #  # ]:          0 :                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
    2796                 :            : 
    2797                 :         20 :                         break;
    2798                 :            :                 }
    2799                 :            : 
    2800                 :       1340 :                 case _JSON_BUILD_BOOLEAN: {
    2801                 :            :                         bool b;
    2802                 :            : 
    2803   [ +  -  -  + ]:       1340 :                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
    2804                 :          0 :                                 r = -EINVAL;
    2805                 :          0 :                                 goto finish;
    2806                 :            :                         }
    2807                 :            : 
    2808                 :       1340 :                         b = va_arg(ap, int);
    2809                 :            : 
    2810         [ +  - ]:       1340 :                         if (current->n_suppress == 0) {
    2811                 :       1340 :                                 r = json_variant_new_boolean(&add, b);
    2812         [ -  + ]:       1340 :                                 if (r < 0)
    2813                 :          0 :                                         goto finish;
    2814                 :            :                         }
    2815                 :            : 
    2816                 :       1340 :                         n_subtract = 1;
    2817                 :            : 
    2818         [ -  + ]:       1340 :                         if (current->expect == EXPECT_TOPLEVEL)
    2819                 :          0 :                                 current->expect = EXPECT_END;
    2820         [ +  - ]:       1340 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2821                 :       1340 :                                 current->expect = EXPECT_OBJECT_KEY;
    2822                 :            :                         else
    2823         [ #  # ]:          0 :                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
    2824                 :            : 
    2825                 :       1340 :                         break;
    2826                 :            :                 }
    2827                 :            : 
    2828                 :          8 :                 case _JSON_BUILD_NULL:
    2829                 :            : 
    2830   [ +  -  -  + ]:          8 :                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
    2831                 :          0 :                                 r = -EINVAL;
    2832                 :          0 :                                 goto finish;
    2833                 :            :                         }
    2834                 :            : 
    2835         [ +  - ]:          8 :                         if (current->n_suppress == 0) {
    2836                 :          8 :                                 r = json_variant_new_null(&add);
    2837         [ -  + ]:          8 :                                 if (r < 0)
    2838                 :          0 :                                         goto finish;
    2839                 :            :                         }
    2840                 :            : 
    2841                 :          8 :                         n_subtract = 1;
    2842                 :            : 
    2843         [ -  + ]:          8 :                         if (current->expect == EXPECT_TOPLEVEL)
    2844                 :          0 :                                 current->expect = EXPECT_END;
    2845         [ +  + ]:          8 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2846                 :          4 :                                 current->expect = EXPECT_OBJECT_KEY;
    2847                 :            :                         else
    2848         [ -  + ]:          4 :                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
    2849                 :            : 
    2850                 :          8 :                         break;
    2851                 :            : 
    2852                 :       1380 :                 case _JSON_BUILD_VARIANT:
    2853                 :            : 
    2854   [ +  -  -  + ]:       1380 :                         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                 :       1380 :                         add = va_arg(ap, JsonVariant*);
    2862         [ +  + ]:       1380 :                         if (!add)
    2863                 :          4 :                                 add = JSON_VARIANT_MAGIC_NULL;
    2864                 :            :                         else
    2865                 :       1376 :                                 json_variant_ref(add);
    2866                 :            : 
    2867                 :       1380 :                         n_subtract = 1;
    2868                 :            : 
    2869         [ +  + ]:       1380 :                         if (current->expect == EXPECT_TOPLEVEL)
    2870                 :          4 :                                 current->expect = EXPECT_END;
    2871         [ +  + ]:       1376 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2872                 :       1364 :                                 current->expect = EXPECT_OBJECT_KEY;
    2873                 :            :                         else
    2874         [ -  + ]:         12 :                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
    2875                 :            : 
    2876                 :       1380 :                         break;
    2877                 :            : 
    2878                 :          8 :                 case _JSON_BUILD_LITERAL: {
    2879                 :            :                         const char *l;
    2880                 :            : 
    2881   [ +  -  -  + ]:          8 :                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
    2882                 :          0 :                                 r = -EINVAL;
    2883                 :          0 :                                 goto finish;
    2884                 :            :                         }
    2885                 :            : 
    2886                 :          8 :                         l = va_arg(ap, const char *);
    2887                 :            : 
    2888         [ +  + ]:          8 :                         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                 :          4 :                                 r = json_parse(l, &add, NULL, NULL);
    2893         [ -  + ]:          4 :                                 if (r < 0)
    2894                 :          0 :                                         goto finish;
    2895                 :            :                         } else
    2896                 :          4 :                                 add = JSON_VARIANT_MAGIC_NULL;
    2897                 :            : 
    2898                 :          8 :                         n_subtract = 1;
    2899                 :            : 
    2900         [ +  + ]:          8 :                         if (current->expect == EXPECT_TOPLEVEL)
    2901                 :          4 :                                 current->expect = EXPECT_END;
    2902         [ -  + ]:          4 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2903                 :          0 :                                 current->expect = EXPECT_OBJECT_KEY;
    2904                 :            :                         else
    2905         [ -  + ]:          4 :                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
    2906                 :            : 
    2907                 :          8 :                         break;
    2908                 :            :                 }
    2909                 :            : 
    2910                 :         12 :                 case _JSON_BUILD_ARRAY_BEGIN:
    2911                 :            : 
    2912   [ +  -  -  + ]:         12 :                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
    2913                 :          0 :                                 r = -EINVAL;
    2914                 :          0 :                                 goto finish;
    2915                 :            :                         }
    2916                 :            : 
    2917         [ -  + ]:         12 :                         if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
    2918                 :          0 :                                 r = -ENOMEM;
    2919                 :          0 :                                 goto finish;
    2920                 :            :                         }
    2921                 :         12 :                         current = stack + n_stack - 1;
    2922                 :            : 
    2923         [ +  + ]:         12 :                         if (current->expect == EXPECT_TOPLEVEL)
    2924                 :          4 :                                 current->expect = EXPECT_END;
    2925         [ +  + ]:          8 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2926                 :          4 :                                 current->expect = EXPECT_OBJECT_KEY;
    2927                 :            :                         else
    2928         [ -  + ]:          4 :                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
    2929                 :            : 
    2930                 :         24 :                         stack[n_stack++] = (JsonStack) {
    2931                 :            :                                 .expect = EXPECT_ARRAY_ELEMENT,
    2932         [ +  + ]:         12 :                                 .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                 :         12 :                         break;
    2939                 :            : 
    2940                 :         12 :                 case _JSON_BUILD_ARRAY_END:
    2941         [ -  + ]:         12 :                         if (current->expect != EXPECT_ARRAY_ELEMENT) {
    2942                 :          0 :                                 r = -EINVAL;
    2943                 :          0 :                                 goto finish;
    2944                 :            :                         }
    2945                 :            : 
    2946         [ -  + ]:         12 :                         assert(n_stack > 1);
    2947                 :            : 
    2948         [ +  + ]:         12 :                         if (current->n_suppress == 0) {
    2949                 :          8 :                                 r = json_variant_new_array(&add, current->elements, current->n_elements);
    2950         [ -  + ]:          8 :                                 if (r < 0)
    2951                 :          0 :                                         goto finish;
    2952                 :            :                         }
    2953                 :            : 
    2954                 :         12 :                         n_subtract = 1;
    2955                 :            : 
    2956                 :         12 :                         json_stack_release(current);
    2957                 :         12 :                         n_stack--, current--;
    2958                 :            : 
    2959                 :         12 :                         break;
    2960                 :            : 
    2961                 :          4 :                 case _JSON_BUILD_STRV: {
    2962                 :            :                         char **l;
    2963                 :            : 
    2964   [ +  -  -  + ]:          4 :                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
    2965                 :          0 :                                 r = -EINVAL;
    2966                 :          0 :                                 goto finish;
    2967                 :            :                         }
    2968                 :            : 
    2969                 :          4 :                         l = va_arg(ap, char **);
    2970                 :            : 
    2971         [ +  - ]:          4 :                         if (current->n_suppress == 0) {
    2972                 :          4 :                                 r = json_variant_new_array_strv(&add, l);
    2973         [ -  + ]:          4 :                                 if (r < 0)
    2974                 :          0 :                                         goto finish;
    2975                 :            :                         }
    2976                 :            : 
    2977                 :          4 :                         n_subtract = 1;
    2978                 :            : 
    2979         [ -  + ]:          4 :                         if (current->expect == EXPECT_TOPLEVEL)
    2980                 :          0 :                                 current->expect = EXPECT_END;
    2981         [ -  + ]:          4 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    2982                 :          0 :                                 current->expect = EXPECT_OBJECT_KEY;
    2983                 :            :                         else
    2984         [ -  + ]:          4 :                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
    2985                 :            : 
    2986                 :          4 :                         break;
    2987                 :            :                 }
    2988                 :            : 
    2989                 :       2748 :                 case _JSON_BUILD_OBJECT_BEGIN:
    2990                 :            : 
    2991   [ +  -  -  + ]:       2748 :                         if (!IN_SET(current->expect, EXPECT_TOPLEVEL, EXPECT_OBJECT_VALUE, EXPECT_ARRAY_ELEMENT)) {
    2992                 :          0 :                                 r = -EINVAL;
    2993                 :          0 :                                 goto finish;
    2994                 :            :                         }
    2995                 :            : 
    2996         [ -  + ]:       2748 :                         if (!GREEDY_REALLOC(stack, n_stack_allocated, n_stack+1)) {
    2997                 :          0 :                                 r = -ENOMEM;
    2998                 :          0 :                                 goto finish;
    2999                 :            :                         }
    3000                 :       2748 :                         current = stack + n_stack - 1;
    3001                 :            : 
    3002         [ +  + ]:       2748 :                         if (current->expect == EXPECT_TOPLEVEL)
    3003                 :       2740 :                                 current->expect = EXPECT_END;
    3004         [ +  + ]:          8 :                         else if (current->expect == EXPECT_OBJECT_VALUE)
    3005                 :          4 :                                 current->expect = EXPECT_OBJECT_KEY;
    3006                 :            :                         else
    3007         [ -  + ]:          4 :                                 assert(current->expect == EXPECT_ARRAY_ELEMENT);
    3008                 :            : 
    3009                 :       5496 :                         stack[n_stack++] = (JsonStack) {
    3010                 :            :                                 .expect = EXPECT_OBJECT_KEY,
    3011         [ -  + ]:       2748 :                                 .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                 :       2748 :                         break;
    3018                 :            : 
    3019                 :       2748 :                 case _JSON_BUILD_OBJECT_END:
    3020                 :            : 
    3021         [ -  + ]:       2748 :                         if (current->expect != EXPECT_OBJECT_KEY) {
    3022                 :          0 :                                 r = -EINVAL;
    3023                 :          0 :                                 goto finish;
    3024                 :            :                         }
    3025                 :            : 
    3026         [ -  + ]:       2748 :                         assert(n_stack > 1);
    3027                 :            : 
    3028         [ +  - ]:       2748 :                         if (current->n_suppress == 0) {
    3029                 :       2748 :                                 r = json_variant_new_object(&add, current->elements, current->n_elements);
    3030         [ -  + ]:       2748 :                                 if (r < 0)
    3031                 :          0 :                                         goto finish;
    3032                 :            :                         }
    3033                 :            : 
    3034                 :       2748 :                         n_subtract = 1;
    3035                 :            : 
    3036                 :       2748 :                         json_stack_release(current);
    3037                 :       2748 :                         n_stack--, current--;
    3038                 :            : 
    3039                 :       2748 :                         break;
    3040                 :            : 
    3041                 :       5480 :                 case _JSON_BUILD_PAIR: {
    3042                 :            :                         const char *n;
    3043                 :            : 
    3044         [ -  + ]:       5480 :                         if (current->expect != EXPECT_OBJECT_KEY) {
    3045                 :          0 :                                 r = -EINVAL;
    3046                 :          0 :                                 goto finish;
    3047                 :            :                         }
    3048                 :            : 
    3049                 :       5480 :                         n = va_arg(ap, const char *);
    3050                 :            : 
    3051         [ +  - ]:       5480 :                         if (current->n_suppress == 0) {
    3052                 :       5480 :                                 r = json_variant_new_string(&add, n);
    3053         [ -  + ]:       5480 :                                 if (r < 0)
    3054                 :          0 :                                         goto finish;
    3055                 :            :                         }
    3056                 :            : 
    3057                 :       5480 :                         n_subtract = 1;
    3058                 :            : 
    3059                 :       5480 :                         current->expect = EXPECT_OBJECT_VALUE;
    3060                 :       5480 :                         break;
    3061                 :            :                 }
    3062                 :            : 
    3063                 :         12 :                 case _JSON_BUILD_PAIR_CONDITION: {
    3064                 :            :                         const char *n;
    3065                 :            :                         bool b;
    3066                 :            : 
    3067         [ -  + ]:         12 :                         if (current->expect != EXPECT_OBJECT_KEY) {
    3068                 :          0 :                                 r = -EINVAL;
    3069                 :          0 :                                 goto finish;
    3070                 :            :                         }
    3071                 :            : 
    3072                 :         12 :                         b = va_arg(ap, int);
    3073                 :         12 :                         n = va_arg(ap, const char *);
    3074                 :            : 
    3075   [ +  +  +  - ]:         12 :                         if (b && current->n_suppress == 0) {
    3076                 :          4 :                                 r = json_variant_new_string(&add, n);
    3077         [ -  + ]:          4 :                                 if (r < 0)
    3078                 :          0 :                                         goto finish;
    3079                 :            :                         }
    3080                 :            : 
    3081                 :         12 :                         n_subtract = 1; /* we generated one item */
    3082                 :            : 
    3083   [ +  +  +  - ]:         12 :                         if (!b && current->n_suppress != (size_t) -1)
    3084                 :          8 :                                 current->n_suppress += 2; /* Suppress this one and the next item */
    3085                 :            : 
    3086                 :         12 :                         current->expect = EXPECT_OBJECT_VALUE;
    3087                 :         12 :                         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   [ +  +  +  - ]:      16560 :                 if (add && current->n_suppress == 0) {
    3092         [ -  + ]:      13772 :                         if (!GREEDY_REALLOC(current->elements, current->n_elements_allocated, current->n_elements + 1)) {
    3093                 :          0 :                                 r = -ENOMEM;
    3094                 :          0 :                                 goto finish;
    3095                 :            :                         }
    3096                 :            : 
    3097                 :      13772 :                         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         [ +  + ]:      16560 :                 if (current->n_suppress != (size_t) -1) {
    3104         [ +  + ]:      16548 :                         if (current->n_suppress <= n_subtract) /* Saturated */
    3105                 :      16536 :                                 current->n_suppress = 0;
    3106                 :            :                         else
    3107                 :         12 :                                 current->n_suppress -= n_subtract;
    3108                 :            :                 }
    3109                 :            :         }
    3110                 :            : 
    3111                 :       2764 : done:
    3112         [ -  + ]:       2764 :         assert(n_stack == 1);
    3113         [ -  + ]:       2764 :         assert(stack[0].n_elements == 1);
    3114                 :            : 
    3115                 :       2764 :         *ret = json_variant_ref(stack[0].elements[0]);
    3116                 :       2764 :         r = 0;
    3117                 :            : 
    3118                 :       2764 : finish:
    3119         [ +  + ]:       5528 :         for (i = 0; i < n_stack; i++)
    3120                 :       2764 :                 json_stack_release(stack + i);
    3121                 :            : 
    3122                 :       2764 :         free(stack);
    3123                 :            : 
    3124                 :       2764 :         return r;
    3125                 :            : }
    3126                 :            : 
    3127                 :       1420 : int json_build(JsonVariant **ret, ...) {
    3128                 :            :         va_list ap;
    3129                 :            :         int r;
    3130                 :            : 
    3131                 :       1420 :         va_start(ap, ret);
    3132                 :       1420 :         r = json_buildv(ret, ap);
    3133                 :       1420 :         va_end(ap);
    3134                 :            : 
    3135                 :       1420 :         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