]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/json.h
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / shared / json.h
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
cd0b6c53
LP
2#pragma once
3
f325aaf3 4#include <fcntl.h>
cd0b6c53
LP
5#include <stdbool.h>
6#include <stddef.h>
7#include <stdint.h>
ca78ad1d 8#include <stdio.h>
cd0b6c53 9
0b9481cf
LP
10#include "sd-id128.h"
11
cd0b6c53
LP
12#include "macro.h"
13#include "string-util.h"
ca78ad1d 14#include "log.h"
cd0b6c53
LP
15
16/*
17 In case you wonder why we have our own JSON implementation, here are a couple of reasons why this implementation has
5238e957 18 benefits over various other implementations:
cd0b6c53
LP
19
20 - We need support for 64bit signed and unsigned integers, i.e. the full 64,5bit range of -9223372036854775808…18446744073709551615
21 - All our variants are immutable after creation
22 - Special values such as true, false, zero, null, empty strings, empty array, empty objects require zero dynamic memory
23 - Progressive parsing
24 - Our integer/real type implicitly converts, but only if that's safe and loss-lessly possible
25 - There's a "builder" for putting together objects easily in varargs function calls
26 - There's a "dispatcher" for mapping objects to C data structures
27 - Every variant optionally carries parsing location information, which simplifies debugging and parse log error generation
28 - Formatter has color, line, column support
29
30 Limitations:
31 - Doesn't allow embedded NUL in strings
32 - Can't store integers outside of the -9223372036854775808…18446744073709551615 range (it will use 'long double' for
33 values outside this range, which is lossy)
34 - Can't store negative zero (will be treated identical to positive zero, and not retained across serialization)
35 - Can't store non-integer numbers that can't be stored in "long double" losslessly
36 - Allows creation and parsing of objects with duplicate keys. The "dispatcher" will refuse them however. This means
37 we can parse and pass around such objects, but will carefully refuse them when we convert them into our own data.
38
39 (These limitations should be pretty much in line with those of other JSON implementations, in fact might be less
40 limiting in most cases even.)
41*/
42
43typedef struct JsonVariant JsonVariant;
44
45typedef enum JsonVariantType {
46 JSON_VARIANT_STRING,
47 JSON_VARIANT_INTEGER,
48 JSON_VARIANT_UNSIGNED,
49 JSON_VARIANT_REAL,
50 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 */
51 JSON_VARIANT_BOOLEAN,
52 JSON_VARIANT_ARRAY,
53 JSON_VARIANT_OBJECT,
54 JSON_VARIANT_NULL,
55 _JSON_VARIANT_TYPE_MAX,
56 _JSON_VARIANT_TYPE_INVALID = -1
57} JsonVariantType;
58
59int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n);
cc164891 60int json_variant_new_base64(JsonVariant **ret, const void *p, size_t n);
cd0b6c53
LP
61int json_variant_new_integer(JsonVariant **ret, intmax_t i);
62int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u);
63int json_variant_new_real(JsonVariant **ret, long double d);
64int json_variant_new_boolean(JsonVariant **ret, bool b);
65int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n);
66int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n);
67int json_variant_new_array_strv(JsonVariant **ret, char **l);
68int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n);
69int json_variant_new_null(JsonVariant **ret);
0b9481cf 70int json_variant_new_id128(JsonVariant **ret, sd_id128_t id);
cd0b6c53
LP
71
72static inline int json_variant_new_string(JsonVariant **ret, const char *s) {
cbb3092c 73 return json_variant_new_stringn(ret, s, (size_t) -1);
cd0b6c53
LP
74}
75
76JsonVariant *json_variant_ref(JsonVariant *v);
77JsonVariant *json_variant_unref(JsonVariant *v);
78void json_variant_unref_many(JsonVariant **array, size_t n);
79
80DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref);
81
82const char *json_variant_string(JsonVariant *v);
83intmax_t json_variant_integer(JsonVariant *v);
84uintmax_t json_variant_unsigned(JsonVariant *v);
85long double json_variant_real(JsonVariant *v);
86bool json_variant_boolean(JsonVariant *v);
87
88JsonVariantType json_variant_type(JsonVariant *v);
89bool json_variant_has_type(JsonVariant *v, JsonVariantType type);
90
91static inline bool json_variant_is_string(JsonVariant *v) {
92 return json_variant_has_type(v, JSON_VARIANT_STRING);
93}
94
95static inline bool json_variant_is_integer(JsonVariant *v) {
96 return json_variant_has_type(v, JSON_VARIANT_INTEGER);
97}
98
99static inline bool json_variant_is_unsigned(JsonVariant *v) {
100 return json_variant_has_type(v, JSON_VARIANT_UNSIGNED);
101}
102
103static inline bool json_variant_is_real(JsonVariant *v) {
104 return json_variant_has_type(v, JSON_VARIANT_REAL);
105}
106
107static inline bool json_variant_is_number(JsonVariant *v) {
108 return json_variant_has_type(v, JSON_VARIANT_NUMBER);
109}
110
111static inline bool json_variant_is_boolean(JsonVariant *v) {
112 return json_variant_has_type(v, JSON_VARIANT_BOOLEAN);
113}
114
115static inline bool json_variant_is_array(JsonVariant *v) {
116 return json_variant_has_type(v, JSON_VARIANT_ARRAY);
117}
118
119static inline bool json_variant_is_object(JsonVariant *v) {
120 return json_variant_has_type(v, JSON_VARIANT_OBJECT);
121}
122
123static inline bool json_variant_is_null(JsonVariant *v) {
124 return json_variant_has_type(v, JSON_VARIANT_NULL);
125}
126
127bool json_variant_is_negative(JsonVariant *v);
e787b211
LP
128bool json_variant_is_blank_object(JsonVariant *v);
129bool json_variant_is_blank_array(JsonVariant *v);
b7fc90a2
LP
130bool json_variant_is_normalized(JsonVariant *v);
131bool json_variant_is_sorted(JsonVariant *v);
cd0b6c53
LP
132
133size_t json_variant_elements(JsonVariant *v);
134JsonVariant *json_variant_by_index(JsonVariant *v, size_t index);
135JsonVariant *json_variant_by_key(JsonVariant *v, const char *key);
136JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key);
137
138bool json_variant_equal(JsonVariant *a, JsonVariant *b);
139
83bc6cb7 140void json_variant_sensitive(JsonVariant *v);
94600eeb 141bool json_variant_is_sensitive(JsonVariant *v);
83bc6cb7 142
cd0b6c53
LP
143struct json_variant_foreach_state {
144 JsonVariant *variant;
145 size_t idx;
146};
147
148#define JSON_VARIANT_ARRAY_FOREACH(i, v) \
149 for (struct json_variant_foreach_state _state = { (v), 0 }; \
1b266e3c
LP
150 json_variant_is_array(_state.variant) && \
151 _state.idx < json_variant_elements(_state.variant) && \
cd0b6c53
LP
152 ({ i = json_variant_by_index(_state.variant, _state.idx); \
153 true; }); \
154 _state.idx++)
155
156#define JSON_VARIANT_OBJECT_FOREACH(k, e, v) \
157 for (struct json_variant_foreach_state _state = { (v), 0 }; \
1b266e3c
LP
158 json_variant_is_object(_state.variant) && \
159 _state.idx < json_variant_elements(_state.variant) && \
33d60b8d 160 ({ k = json_variant_string(json_variant_by_index(_state.variant, _state.idx)); \
cd0b6c53
LP
161 e = json_variant_by_index(_state.variant, _state.idx + 1); \
162 true; }); \
163 _state.idx += 2)
164
165int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column);
166
897f099b 167typedef enum JsonFormatFlags {
2d814304
LP
168 JSON_FORMAT_NEWLINE = 1 << 0, /* suffix with newline */
169 JSON_FORMAT_PRETTY = 1 << 1, /* add internal whitespace to appeal to human readers */
170 JSON_FORMAT_PRETTY_AUTO = 1 << 2, /* same, but only if connected to a tty (and JSON_FORMAT_NEWLINE otherwise) */
171 JSON_FORMAT_COLOR = 1 << 3, /* insert ANSI color sequences */
172 JSON_FORMAT_COLOR_AUTO = 1 << 4, /* insert ANSI color sequences if colors_enabled() says so */
173 JSON_FORMAT_SOURCE = 1 << 5, /* prefix with source filename/line/column */
174 JSON_FORMAT_SSE = 1 << 6, /* prefix/suffix with W3C server-sent events */
175 JSON_FORMAT_SEQ = 1 << 7, /* prefix/suffix with RFC 7464 application/json-seq */
176 JSON_FORMAT_FLUSH = 1 << 8, /* call fflush() after dumping JSON */
897f099b 177} JsonFormatFlags;
cd0b6c53 178
897f099b
LP
179int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret);
180void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix);
cd0b6c53 181
f2ff34ff
LP
182int json_variant_filter(JsonVariant **v, char **to_remove);
183
78a41236 184int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *value);
15f1fb3e 185int json_variant_set_field_string(JsonVariant **v, const char *field, const char *value);
a832b08e 186int json_variant_set_field_integer(JsonVariant **v, const char *field, intmax_t value);
15f1fb3e 187int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uintmax_t value);
a832b08e 188int json_variant_set_field_boolean(JsonVariant **v, const char *field, bool b);
0b9481cf 189int json_variant_set_field_strv(JsonVariant **v, const char *field, char **l);
78a41236 190
21e21511
LP
191int json_variant_append_array(JsonVariant **v, JsonVariant *element);
192
ca409a59
LP
193int json_variant_merge(JsonVariant **v, JsonVariant *m);
194
22f14d6b
LP
195int json_variant_strv(JsonVariant *v, char ***ret);
196
b7fc90a2
LP
197int json_variant_sort(JsonVariant **v);
198int json_variant_normalize(JsonVariant **v);
199
d642f640
LP
200typedef enum JsonParseFlags {
201 JSON_PARSE_SENSITIVE = 1 << 0, /* mark variant as "sensitive", i.e. something containing secret key material or such */
202} JsonParseFlags;
f325aaf3 203
d642f640
LP
204int json_parse(const char *string, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
205int json_parse_continue(const char **p, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
206int json_parse_file_at(FILE *f, int dir_fd, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
207
208static inline int json_parse_file(FILE *f, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
209 return json_parse_file_at(f, AT_FDCWD, path, flags, ret, ret_line, ret_column);
f325aaf3 210}
cd0b6c53
LP
211
212enum {
213 _JSON_BUILD_STRING,
214 _JSON_BUILD_INTEGER,
215 _JSON_BUILD_UNSIGNED,
216 _JSON_BUILD_REAL,
217 _JSON_BUILD_BOOLEAN,
218 _JSON_BUILD_ARRAY_BEGIN,
219 _JSON_BUILD_ARRAY_END,
220 _JSON_BUILD_OBJECT_BEGIN,
221 _JSON_BUILD_OBJECT_END,
222 _JSON_BUILD_PAIR,
319a4f27 223 _JSON_BUILD_PAIR_CONDITION,
cd0b6c53
LP
224 _JSON_BUILD_NULL,
225 _JSON_BUILD_VARIANT,
e4defdc4 226 _JSON_BUILD_VARIANT_ARRAY,
cd0b6c53
LP
227 _JSON_BUILD_LITERAL,
228 _JSON_BUILD_STRV,
886b0c93 229 _JSON_BUILD_BASE64,
0b9481cf 230 _JSON_BUILD_ID128,
0710343c 231 _JSON_BUILD_BYTE_ARRAY,
cd0b6c53
LP
232 _JSON_BUILD_MAX,
233};
234
235#define JSON_BUILD_STRING(s) _JSON_BUILD_STRING, ({ const char *_x = s; _x; })
236#define JSON_BUILD_INTEGER(i) _JSON_BUILD_INTEGER, ({ intmax_t _x = i; _x; })
237#define JSON_BUILD_UNSIGNED(u) _JSON_BUILD_UNSIGNED, ({ uintmax_t _x = u; _x; })
238#define JSON_BUILD_REAL(d) _JSON_BUILD_REAL, ({ long double _x = d; _x; })
239#define JSON_BUILD_BOOLEAN(b) _JSON_BUILD_BOOLEAN, ({ bool _x = b; _x; })
240#define JSON_BUILD_ARRAY(...) _JSON_BUILD_ARRAY_BEGIN, __VA_ARGS__, _JSON_BUILD_ARRAY_END
aafa52ab 241#define JSON_BUILD_EMPTY_ARRAY _JSON_BUILD_ARRAY_BEGIN, _JSON_BUILD_ARRAY_END
cd0b6c53 242#define JSON_BUILD_OBJECT(...) _JSON_BUILD_OBJECT_BEGIN, __VA_ARGS__, _JSON_BUILD_OBJECT_END
aafa52ab 243#define JSON_BUILD_EMPTY_OBJECT _JSON_BUILD_OBJECT_BEGIN, _JSON_BUILD_OBJECT_END
cd0b6c53 244#define JSON_BUILD_PAIR(n, ...) _JSON_BUILD_PAIR, ({ const char *_x = n; _x; }), __VA_ARGS__
319a4f27 245#define JSON_BUILD_PAIR_CONDITION(c, n, ...) _JSON_BUILD_PAIR_CONDITION, ({ bool _x = c; _x; }), ({ const char *_x = n; _x; }), __VA_ARGS__
cd0b6c53
LP
246#define JSON_BUILD_NULL _JSON_BUILD_NULL
247#define JSON_BUILD_VARIANT(v) _JSON_BUILD_VARIANT, ({ JsonVariant *_x = v; _x; })
e4defdc4 248#define JSON_BUILD_VARIANT_ARRAY(v, n) _JSON_BUILD_VARIANT_ARRAY, ({ JsonVariant **_x = v; _x; }), ({ size_t _y = n; _y; })
cd0b6c53
LP
249#define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, ({ const char *_x = l; _x; })
250#define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, ({ char **_x = l; _x; })
886b0c93 251#define JSON_BUILD_BASE64(p, n) _JSON_BUILD_BASE64, ({ const void *_x = p; _x; }), ({ size_t _y = n; _y; })
0b9481cf 252#define JSON_BUILD_ID128(id) _JSON_BUILD_ID128, ({ sd_id128_t _x = id; _x; })
0710343c 253#define JSON_BUILD_BYTE_ARRAY(v, n) _JSON_BUILD_BYTE_ARRAY, ({ const void *_x = v; _x; }), ({ size_t _y = n; _y; })
cd0b6c53
LP
254
255int json_build(JsonVariant **ret, ...);
256int json_buildv(JsonVariant **ret, va_list ap);
257
258/* A bitmask of flags used by the dispatch logic. Note that this is a combined bit mask, that is generated from the bit
259 * mask originally passed into json_dispatch(), the individual bitmask associated with the static JsonDispatch callout
260 * entry, as well the bitmask specified for json_log() calls */
261typedef enum JsonDispatchFlags {
262 /* The following three may be set in JsonDispatch's .flags field or the json_dispatch() flags parameter */
263 JSON_PERMISSIVE = 1 << 0, /* Shall parsing errors be considered fatal for this property? */
5238e957 264 JSON_MANDATORY = 1 << 1, /* Should existence of this property be mandatory? */
cd0b6c53 265 JSON_LOG = 1 << 2, /* Should the parser log about errors? */
ba23dbf1 266 JSON_SAFE = 1 << 3, /* Don't accept "unsafe" strings in json_dispatch_string() + json_dispatch_string() */
7a8867ab 267 JSON_RELAX = 1 << 4, /* Use relaxed user name checking in json_dispatch_user_group_name */
cd0b6c53
LP
268
269 /* The following two may be passed into log_json() in addition to the three above */
ba23dbf1
LP
270 JSON_DEBUG = 1 << 4, /* Indicates that this log message is a debug message */
271 JSON_WARNING = 1 << 5, /* Indicates that this log message is a warning message */
cd0b6c53
LP
272} JsonDispatchFlags;
273
274typedef int (*JsonDispatchCallback)(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
275
276typedef struct JsonDispatch {
277 const char *name;
278 JsonVariantType type;
279 JsonDispatchCallback callback;
280 size_t offset;
281 JsonDispatchFlags flags;
282} JsonDispatch;
283
284int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata);
285
286int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
19a209cc 287int json_dispatch_const_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
cd0b6c53
LP
288int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
289int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
290int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
291int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
292int json_dispatch_integer(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
293int json_dispatch_unsigned(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
294int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
295int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
a42ef715
LP
296int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
297int json_dispatch_user_group_name(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
298int json_dispatch_id128(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
299int json_dispatch_unsupported(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
cd0b6c53 300
ab1a1ba5 301assert_cc(sizeof(uintmax_t) == sizeof(uint64_t));
cd0b6c53
LP
302#define json_dispatch_uint64 json_dispatch_unsigned
303
ab1a1ba5 304assert_cc(sizeof(intmax_t) == sizeof(int64_t));
cd0b6c53
LP
305#define json_dispatch_int64 json_dispatch_integer
306
b97e3e3d
LP
307assert_cc(sizeof(uint32_t) == sizeof(unsigned));
308#define json_dispatch_uint json_dispatch_uint32
309
310assert_cc(sizeof(int32_t) == sizeof(int));
311#define json_dispatch_int json_dispatch_int32
312
cd0b6c53
LP
313static inline int json_dispatch_level(JsonDispatchFlags flags) {
314
315 /* Did the user request no logging? If so, then never log higher than LOG_DEBUG. Also, if this is marked as
316 * debug message, then also log at debug level. */
317
318 if (!(flags & JSON_LOG) ||
319 (flags & JSON_DEBUG))
320 return LOG_DEBUG;
321
322 /* Are we invoked in permissive mode, or is this explicitly marked as warning message? Then this should be
323 * printed at LOG_WARNING */
324 if (flags & (JSON_PERMISSIVE|JSON_WARNING))
325 return LOG_WARNING;
326
327 /* Otherwise it's an error. */
328 return LOG_ERR;
329}
330
331int json_log_internal(JsonVariant *variant, int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(7, 8);
332
19130626 333#define json_log(variant, flags, error, ...) \
cd0b6c53 334 ({ \
19130626 335 int _level = json_dispatch_level(flags), _e = (error); \
cd0b6c53 336 (log_get_max_level() >= LOG_PRI(_level)) \
62c6bbbc 337 ? json_log_internal(variant, _level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
19130626 338 : -ERRNO_VALUE(_e); \
cd0b6c53
LP
339 })
340
0ac0787e
LP
341#define json_log_oom(variant, flags) \
342 json_log(variant, flags, SYNTHETIC_ERRNO(ENOMEM), "Out of memory.")
343
d520d519
LP
344#define JSON_VARIANT_STRING_CONST(x) _JSON_VARIANT_STRING_CONST(UNIQ, (x))
345
90b365ce 346#define _JSON_VARIANT_STRING_CONST(xq, x) \
d520d519 347 ({ \
90b365ce 348 _align_(2) static const char UNIQ_T(json_string_const, xq)[] = (x); \
d520d519
LP
349 assert((((uintptr_t) UNIQ_T(json_string_const, xq)) & 1) == 0); \
350 (JsonVariant*) ((uintptr_t) UNIQ_T(json_string_const, xq) + 1); \
351 })
352
faca141c
LP
353int json_variant_unbase64(JsonVariant *v, void **ret, size_t *ret_size);
354
cd0b6c53
LP
355const char *json_variant_type_to_string(JsonVariantType t);
356JsonVariantType json_variant_type_from_string(const char *s);