LCOV - code coverage report
Current view: top level - shared - json.h (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 17 28 60.7 %
Date: 2019-08-22 15:41:25 Functions: 9 12 75.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : #pragma once
       3             : 
       4             : #include <stdbool.h>
       5             : #include <stddef.h>
       6             : #include <stdint.h>
       7             : #include <stdio.h>
       8             : 
       9             : #include "macro.h"
      10             : #include "string-util.h"
      11             : #include "log.h"
      12             : 
      13             : /*
      14             :   In case you wonder why we have our own JSON implementation, here are a couple of reasons why this implementation has
      15             :   benefits over various other implementations:
      16             : 
      17             :   - We need support for 64bit signed and unsigned integers, i.e. the full 64,5bit range of -9223372036854775808…18446744073709551615
      18             :   - All our variants are immutable after creation
      19             :   - Special values such as true, false, zero, null, empty strings, empty array, empty objects require zero dynamic memory
      20             :   - Progressive parsing
      21             :   - Our integer/real type implicitly converts, but only if that's safe and loss-lessly possible
      22             :   - There's a "builder" for putting together objects easily in varargs function calls
      23             :   - There's a "dispatcher" for mapping objects to C data structures
      24             :   - Every variant optionally carries parsing location information, which simplifies debugging and parse log error generation
      25             :   - Formatter has color, line, column support
      26             : 
      27             :   Limitations:
      28             :   - Doesn't allow embedded NUL in strings
      29             :   - Can't store integers outside of the -9223372036854775808…18446744073709551615 range (it will use 'long double' for
      30             :     values outside this range, which is lossy)
      31             :   - Can't store negative zero (will be treated identical to positive zero, and not retained across serialization)
      32             :   - Can't store non-integer numbers that can't be stored in "long double" losslessly
      33             :   - Allows creation and parsing of objects with duplicate keys. The "dispatcher" will refuse them however. This means
      34             :     we can parse and pass around such objects, but will carefully refuse them when we convert them into our own data.
      35             : 
      36             :   (These limitations should be pretty much in line with those of other JSON implementations, in fact might be less
      37             :   limiting in most cases even.)
      38             : */
      39             : 
      40             : typedef struct JsonVariant JsonVariant;
      41             : 
      42             : typedef enum JsonVariantType {
      43             :         JSON_VARIANT_STRING,
      44             :         JSON_VARIANT_INTEGER,
      45             :         JSON_VARIANT_UNSIGNED,
      46             :         JSON_VARIANT_REAL,
      47             :         JSON_VARIANT_NUMBER, /* This a pseudo-type: we can never create variants of this type, but we use it as wildcard check for the above three types */
      48             :         JSON_VARIANT_BOOLEAN,
      49             :         JSON_VARIANT_ARRAY,
      50             :         JSON_VARIANT_OBJECT,
      51             :         JSON_VARIANT_NULL,
      52             :         _JSON_VARIANT_TYPE_MAX,
      53             :         _JSON_VARIANT_TYPE_INVALID = -1
      54             : } JsonVariantType;
      55             : 
      56             : int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n);
      57             : int json_variant_new_integer(JsonVariant **ret, intmax_t i);
      58             : int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u);
      59             : int json_variant_new_real(JsonVariant **ret, long double d);
      60             : int json_variant_new_boolean(JsonVariant **ret, bool b);
      61             : int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n);
      62             : int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n);
      63             : int json_variant_new_array_strv(JsonVariant **ret, char **l);
      64             : int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n);
      65             : int json_variant_new_null(JsonVariant **ret);
      66             : 
      67        2445 : static inline int json_variant_new_string(JsonVariant **ret, const char *s) {
      68        2445 :         return json_variant_new_stringn(ret, s, (size_t) -1);
      69             : }
      70             : 
      71             : JsonVariant *json_variant_ref(JsonVariant *v);
      72             : JsonVariant *json_variant_unref(JsonVariant *v);
      73             : void json_variant_unref_many(JsonVariant **array, size_t n);
      74             : 
      75       20823 : DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref);
      76             : 
      77             : const char *json_variant_string(JsonVariant *v);
      78             : intmax_t json_variant_integer(JsonVariant *v);
      79             : uintmax_t json_variant_unsigned(JsonVariant *v);
      80             : long double json_variant_real(JsonVariant *v);
      81             : bool json_variant_boolean(JsonVariant *v);
      82             : 
      83             : JsonVariantType json_variant_type(JsonVariant *v);
      84             : bool json_variant_has_type(JsonVariant *v, JsonVariantType type);
      85             : 
      86        4123 : static inline bool json_variant_is_string(JsonVariant *v) {
      87        4123 :         return json_variant_has_type(v, JSON_VARIANT_STRING);
      88             : }
      89             : 
      90          13 : static inline bool json_variant_is_integer(JsonVariant *v) {
      91          13 :         return json_variant_has_type(v, JSON_VARIANT_INTEGER);
      92             : }
      93             : 
      94          13 : static inline bool json_variant_is_unsigned(JsonVariant *v) {
      95          13 :         return json_variant_has_type(v, JSON_VARIANT_UNSIGNED);
      96             : }
      97             : 
      98          13 : static inline bool json_variant_is_real(JsonVariant *v) {
      99          13 :         return json_variant_has_type(v, JSON_VARIANT_REAL);
     100             : }
     101             : 
     102          13 : static inline bool json_variant_is_number(JsonVariant *v) {
     103          13 :         return json_variant_has_type(v, JSON_VARIANT_NUMBER);
     104             : }
     105             : 
     106         130 : static inline bool json_variant_is_boolean(JsonVariant *v) {
     107         130 :         return json_variant_has_type(v, JSON_VARIANT_BOOLEAN);
     108             : }
     109             : 
     110           0 : static inline bool json_variant_is_array(JsonVariant *v) {
     111           0 :         return json_variant_has_type(v, JSON_VARIANT_ARRAY);
     112             : }
     113             : 
     114        1284 : static inline bool json_variant_is_object(JsonVariant *v) {
     115        1284 :         return json_variant_has_type(v, JSON_VARIANT_OBJECT);
     116             : }
     117             : 
     118           0 : static inline bool json_variant_is_null(JsonVariant *v) {
     119           0 :         return json_variant_has_type(v, JSON_VARIANT_NULL);
     120             : }
     121             : 
     122             : bool json_variant_is_negative(JsonVariant *v);
     123             : 
     124             : size_t json_variant_elements(JsonVariant *v);
     125             : JsonVariant *json_variant_by_index(JsonVariant *v, size_t index);
     126             : JsonVariant *json_variant_by_key(JsonVariant *v, const char *key);
     127             : JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key);
     128             : 
     129             : bool json_variant_equal(JsonVariant *a, JsonVariant *b);
     130             : 
     131             : struct json_variant_foreach_state {
     132             :         JsonVariant *variant;
     133             :         size_t idx;
     134             : };
     135             : 
     136             : #define JSON_VARIANT_ARRAY_FOREACH(i, v)                                \
     137             :         for (struct json_variant_foreach_state _state = { (v), 0 };     \
     138             :              json_variant_is_array(_state.variant) &&                   \
     139             :                      _state.idx < json_variant_elements(_state.variant) && \
     140             :                      ({ i = json_variant_by_index(_state.variant, _state.idx); \
     141             :                              true; });                                  \
     142             :              _state.idx++)
     143             : 
     144             : #define JSON_VARIANT_OBJECT_FOREACH(k, e, v)                            \
     145             :         for (struct json_variant_foreach_state _state = { (v), 0 };     \
     146             :              json_variant_is_object(_state.variant) &&                  \
     147             :                      _state.idx < json_variant_elements(_state.variant) && \
     148             :                      ({ k = json_variant_string(json_variant_by_index(_state.variant, _state.idx)); \
     149             :                              e = json_variant_by_index(_state.variant, _state.idx + 1); \
     150             :                              true; });                                  \
     151             :              _state.idx += 2)
     152             : 
     153             : int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column);
     154             : 
     155             : typedef enum JsonFormatFlags {
     156             :         JSON_FORMAT_NEWLINE    = 1 << 0, /* suffix with newline */
     157             :         JSON_FORMAT_PRETTY     = 1 << 1, /* add internal whitespace to appeal to human readers */
     158             :         JSON_FORMAT_COLOR      = 1 << 2, /* insert ANSI color sequences */
     159             :         JSON_FORMAT_COLOR_AUTO = 1 << 3, /* insert ANSI color sequences if colors_enabled() says so */
     160             :         JSON_FORMAT_SOURCE     = 1 << 4, /* prefix with source filename/line/column */
     161             :         JSON_FORMAT_SSE        = 1 << 5, /* prefix/suffix with W3C server-sent events */
     162             :         JSON_FORMAT_SEQ        = 1 << 6, /* prefix/suffix with RFC 7464 application/json-seq */
     163             : } JsonFormatFlags;
     164             : 
     165             : int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret);
     166             : void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix);
     167             : 
     168             : int json_parse(const char *string, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
     169             : int json_parse_continue(const char **p, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
     170             : int json_parse_file(FILE *f, const char *path, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
     171             : 
     172             : enum {
     173             :         _JSON_BUILD_STRING,
     174             :         _JSON_BUILD_INTEGER,
     175             :         _JSON_BUILD_UNSIGNED,
     176             :         _JSON_BUILD_REAL,
     177             :         _JSON_BUILD_BOOLEAN,
     178             :         _JSON_BUILD_ARRAY_BEGIN,
     179             :         _JSON_BUILD_ARRAY_END,
     180             :         _JSON_BUILD_OBJECT_BEGIN,
     181             :         _JSON_BUILD_OBJECT_END,
     182             :         _JSON_BUILD_PAIR,
     183             :         _JSON_BUILD_PAIR_CONDITION,
     184             :         _JSON_BUILD_NULL,
     185             :         _JSON_BUILD_VARIANT,
     186             :         _JSON_BUILD_LITERAL,
     187             :         _JSON_BUILD_STRV,
     188             :         _JSON_BUILD_MAX,
     189             : };
     190             : 
     191             : #define JSON_BUILD_STRING(s) _JSON_BUILD_STRING, ({ const char *_x = s; _x; })
     192             : #define JSON_BUILD_INTEGER(i) _JSON_BUILD_INTEGER, ({ intmax_t _x = i; _x; })
     193             : #define JSON_BUILD_UNSIGNED(u) _JSON_BUILD_UNSIGNED, ({ uintmax_t _x = u; _x; })
     194             : #define JSON_BUILD_REAL(d) _JSON_BUILD_REAL, ({ long double _x = d; _x; })
     195             : #define JSON_BUILD_BOOLEAN(b) _JSON_BUILD_BOOLEAN, ({ bool _x = b; _x; })
     196             : #define JSON_BUILD_ARRAY(...) _JSON_BUILD_ARRAY_BEGIN, __VA_ARGS__, _JSON_BUILD_ARRAY_END
     197             : #define JSON_BUILD_OBJECT(...) _JSON_BUILD_OBJECT_BEGIN, __VA_ARGS__, _JSON_BUILD_OBJECT_END
     198             : #define JSON_BUILD_PAIR(n, ...) _JSON_BUILD_PAIR, ({ const char *_x = n; _x; }), __VA_ARGS__
     199             : #define JSON_BUILD_PAIR_CONDITION(c, n, ...) _JSON_BUILD_PAIR_CONDITION, ({ bool _x = c; _x; }), ({ const char *_x = n; _x; }), __VA_ARGS__
     200             : #define JSON_BUILD_NULL _JSON_BUILD_NULL
     201             : #define JSON_BUILD_VARIANT(v) _JSON_BUILD_VARIANT, ({ JsonVariant *_x = v; _x; })
     202             : #define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, ({ const char *_x = l; _x; })
     203             : #define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, ({ char **_x = l; _x; })
     204             : 
     205             : int json_build(JsonVariant **ret, ...);
     206             : int json_buildv(JsonVariant **ret, va_list ap);
     207             : 
     208             : /* A bitmask of flags used by the dispatch logic. Note that this is a combined bit mask, that is generated from the bit
     209             :  * mask originally passed into json_dispatch(), the individual bitmask associated with the static JsonDispatch callout
     210             :  * entry, as well the bitmask specified for json_log() calls */
     211             : typedef enum JsonDispatchFlags {
     212             :         /* The following three may be set in JsonDispatch's .flags field or the json_dispatch() flags parameter  */
     213             :         JSON_PERMISSIVE = 1 << 0, /* Shall parsing errors be considered fatal for this property? */
     214             :         JSON_MANDATORY  = 1 << 1, /* Should existence of this property be mandatory? */
     215             :         JSON_LOG        = 1 << 2, /* Should the parser log about errors? */
     216             : 
     217             :         /* The following two may be passed into log_json() in addition to the three above */
     218             :         JSON_DEBUG      = 1 << 3, /* Indicates that this log message is a debug message */
     219             :         JSON_WARNING    = 1 << 4, /* Indicates that this log message is a warning message */
     220             : } JsonDispatchFlags;
     221             : 
     222             : typedef int (*JsonDispatchCallback)(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
     223             : 
     224             : typedef struct JsonDispatch {
     225             :         const char *name;
     226             :         JsonVariantType type;
     227             :         JsonDispatchCallback callback;
     228             :         size_t offset;
     229             :         JsonDispatchFlags flags;
     230             : } JsonDispatch;
     231             : 
     232             : int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata);
     233             : 
     234             : int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
     235             : int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
     236             : int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
     237             : int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
     238             : int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
     239             : int json_dispatch_integer(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
     240             : int json_dispatch_unsigned(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
     241             : int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
     242             : int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
     243             : 
     244             : assert_cc(sizeof(uintmax_t) == sizeof(uint64_t));
     245             : #define json_dispatch_uint64 json_dispatch_unsigned
     246             : 
     247             : assert_cc(sizeof(intmax_t) == sizeof(int64_t));
     248             : #define json_dispatch_int64 json_dispatch_integer
     249             : 
     250           0 : static inline int json_dispatch_level(JsonDispatchFlags flags) {
     251             : 
     252             :         /* Did the user request no logging? If so, then never log higher than LOG_DEBUG. Also, if this is marked as
     253             :          * debug message, then also log at debug level. */
     254             : 
     255           0 :         if (!(flags & JSON_LOG) ||
     256           0 :             (flags & JSON_DEBUG))
     257           0 :                 return LOG_DEBUG;
     258             : 
     259             :         /* Are we invoked in permissive mode, or is this explicitly marked as warning message? Then this should be
     260             :          * printed at LOG_WARNING */
     261           0 :         if (flags & (JSON_PERMISSIVE|JSON_WARNING))
     262           0 :                 return LOG_WARNING;
     263             : 
     264             :         /* Otherwise it's an error. */
     265           0 :         return LOG_ERR;
     266             : }
     267             : 
     268             : int json_log_internal(JsonVariant *variant, int level, int error, const char *file, int line, const char *func, const char *format, ...)  _printf_(7, 8);
     269             : 
     270             : #define json_log(variant, flags, error, ...)                            \
     271             :         ({                                                              \
     272             :                 int _level = json_dispatch_level(flags), _e = (error);  \
     273             :                 (log_get_max_level() >= LOG_PRI(_level))                \
     274             :                         ? json_log_internal(variant, _level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
     275             :                         : -ERRNO_VALUE(_e);                             \
     276             :         })
     277             : 
     278             : #define JSON_VARIANT_STRING_CONST(x) _JSON_VARIANT_STRING_CONST(UNIQ, (x))
     279             : 
     280             : #define _JSON_VARIANT_STRING_CONST(xq, x)                               \
     281             :         ({                                                              \
     282             :                 _align_(2) static const char UNIQ_T(json_string_const, xq)[] = (x); \
     283             :                 assert((((uintptr_t) UNIQ_T(json_string_const, xq)) & 1) == 0); \
     284             :                 (JsonVariant*) ((uintptr_t) UNIQ_T(json_string_const, xq) + 1); \
     285             :         })
     286             : 
     287             : const char *json_variant_type_to_string(JsonVariantType t);
     288             : JsonVariantType json_variant_type_from_string(const char *s);

Generated by: LCOV version 1.14