Branch data 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 : 9780 : static inline int json_variant_new_string(JsonVariant **ret, const char *s) {
68 : 9780 : 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 [ + + ]: 81890 : 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 : 16492 : static inline bool json_variant_is_string(JsonVariant *v) {
87 : 16492 : return json_variant_has_type(v, JSON_VARIANT_STRING);
88 : : }
89 : :
90 : 52 : static inline bool json_variant_is_integer(JsonVariant *v) {
91 : 52 : return json_variant_has_type(v, JSON_VARIANT_INTEGER);
92 : : }
93 : :
94 : 52 : static inline bool json_variant_is_unsigned(JsonVariant *v) {
95 : 52 : return json_variant_has_type(v, JSON_VARIANT_UNSIGNED);
96 : : }
97 : :
98 : 52 : static inline bool json_variant_is_real(JsonVariant *v) {
99 : 52 : return json_variant_has_type(v, JSON_VARIANT_REAL);
100 : : }
101 : :
102 : 52 : static inline bool json_variant_is_number(JsonVariant *v) {
103 : 52 : return json_variant_has_type(v, JSON_VARIANT_NUMBER);
104 : : }
105 : :
106 : 520 : static inline bool json_variant_is_boolean(JsonVariant *v) {
107 : 520 : 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 : 5136 : static inline bool json_variant_is_object(JsonVariant *v) {
115 : 5136 : 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);
|