]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/json.h
tree-wide: use PROJECT_FILE instead of __FILE__
[thirdparty/systemd.git] / src / shared / json.h
CommitLineData
cd0b6c53 1/* SPDX-License-Identifier: LGPL-2.1+ */
cd0b6c53
LP
2#pragma once
3
4#include <stdbool.h>
5#include <stddef.h>
6#include <stdint.h>
ca78ad1d 7#include <stdio.h>
cd0b6c53
LP
8
9#include "macro.h"
10#include "string-util.h"
ca78ad1d 11#include "log.h"
cd0b6c53
LP
12
13/*
14 In case you wonder why we have our own JSON implementation, here are a couple of reasons why this implementation has
5238e957 15 benefits over various other implementations:
cd0b6c53
LP
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
40typedef struct JsonVariant JsonVariant;
41
42typedef 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
56int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n);
57int json_variant_new_integer(JsonVariant **ret, intmax_t i);
58int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u);
59int json_variant_new_real(JsonVariant **ret, long double d);
60int json_variant_new_boolean(JsonVariant **ret, bool b);
61int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n);
62int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n);
63int json_variant_new_array_strv(JsonVariant **ret, char **l);
64int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n);
65int json_variant_new_null(JsonVariant **ret);
66
67static inline int json_variant_new_string(JsonVariant **ret, const char *s) {
cbb3092c 68 return json_variant_new_stringn(ret, s, (size_t) -1);
cd0b6c53
LP
69}
70
71JsonVariant *json_variant_ref(JsonVariant *v);
72JsonVariant *json_variant_unref(JsonVariant *v);
73void json_variant_unref_many(JsonVariant **array, size_t n);
74
75DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref);
76
77const char *json_variant_string(JsonVariant *v);
78intmax_t json_variant_integer(JsonVariant *v);
79uintmax_t json_variant_unsigned(JsonVariant *v);
80long double json_variant_real(JsonVariant *v);
81bool json_variant_boolean(JsonVariant *v);
82
83JsonVariantType json_variant_type(JsonVariant *v);
84bool json_variant_has_type(JsonVariant *v, JsonVariantType type);
85
86static inline bool json_variant_is_string(JsonVariant *v) {
87 return json_variant_has_type(v, JSON_VARIANT_STRING);
88}
89
90static inline bool json_variant_is_integer(JsonVariant *v) {
91 return json_variant_has_type(v, JSON_VARIANT_INTEGER);
92}
93
94static inline bool json_variant_is_unsigned(JsonVariant *v) {
95 return json_variant_has_type(v, JSON_VARIANT_UNSIGNED);
96}
97
98static inline bool json_variant_is_real(JsonVariant *v) {
99 return json_variant_has_type(v, JSON_VARIANT_REAL);
100}
101
102static inline bool json_variant_is_number(JsonVariant *v) {
103 return json_variant_has_type(v, JSON_VARIANT_NUMBER);
104}
105
106static inline bool json_variant_is_boolean(JsonVariant *v) {
107 return json_variant_has_type(v, JSON_VARIANT_BOOLEAN);
108}
109
110static inline bool json_variant_is_array(JsonVariant *v) {
111 return json_variant_has_type(v, JSON_VARIANT_ARRAY);
112}
113
114static inline bool json_variant_is_object(JsonVariant *v) {
115 return json_variant_has_type(v, JSON_VARIANT_OBJECT);
116}
117
118static inline bool json_variant_is_null(JsonVariant *v) {
119 return json_variant_has_type(v, JSON_VARIANT_NULL);
120}
121
122bool json_variant_is_negative(JsonVariant *v);
123
124size_t json_variant_elements(JsonVariant *v);
125JsonVariant *json_variant_by_index(JsonVariant *v, size_t index);
126JsonVariant *json_variant_by_key(JsonVariant *v, const char *key);
127JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key);
128
129bool json_variant_equal(JsonVariant *a, JsonVariant *b);
130
131struct 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 }; \
1b266e3c
LP
138 json_variant_is_array(_state.variant) && \
139 _state.idx < json_variant_elements(_state.variant) && \
cd0b6c53
LP
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 }; \
1b266e3c
LP
146 json_variant_is_object(_state.variant) && \
147 _state.idx < json_variant_elements(_state.variant) && \
33d60b8d 148 ({ k = json_variant_string(json_variant_by_index(_state.variant, _state.idx)); \
cd0b6c53
LP
149 e = json_variant_by_index(_state.variant, _state.idx + 1); \
150 true; }); \
151 _state.idx += 2)
152
153int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column);
154
897f099b 155typedef enum JsonFormatFlags {
ab91733c
LP
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 */
6af022fe 159 JSON_FORMAT_COLOR_AUTO = 1 << 3, /* insert ANSI color sequences if colors_enabled() says so */
ab91733c
LP
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 */
897f099b 163} JsonFormatFlags;
cd0b6c53 164
897f099b
LP
165int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret);
166void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix);
cd0b6c53
LP
167
168int json_parse(const char *string, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
169int json_parse_continue(const char **p, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
170int json_parse_file(FILE *f, const char *path, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
171
172enum {
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,
319a4f27 183 _JSON_BUILD_PAIR_CONDITION,
cd0b6c53
LP
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__
319a4f27 199#define JSON_BUILD_PAIR_CONDITION(c, n, ...) _JSON_BUILD_PAIR_CONDITION, ({ bool _x = c; _x; }), ({ const char *_x = n; _x; }), __VA_ARGS__
cd0b6c53
LP
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
205int json_build(JsonVariant **ret, ...);
206int 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 */
211typedef 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? */
5238e957 214 JSON_MANDATORY = 1 << 1, /* Should existence of this property be mandatory? */
cd0b6c53
LP
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
222typedef int (*JsonDispatchCallback)(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
223
224typedef struct JsonDispatch {
225 const char *name;
226 JsonVariantType type;
227 JsonDispatchCallback callback;
228 size_t offset;
229 JsonDispatchFlags flags;
230} JsonDispatch;
231
232int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata);
233
234int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
235int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
236int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
237int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
238int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
239int json_dispatch_integer(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
240int json_dispatch_unsigned(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
241int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
242int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
243
244assert_cc(sizeof(uintmax_t) == sizeof(uint64_t))
245#define json_dispatch_uint64 json_dispatch_unsigned
246
247assert_cc(sizeof(intmax_t) == sizeof(int64_t))
248#define json_dispatch_int64 json_dispatch_integer
249
250static 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 if (!(flags & JSON_LOG) ||
256 (flags & JSON_DEBUG))
257 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 if (flags & (JSON_PERMISSIVE|JSON_WARNING))
262 return LOG_WARNING;
263
264 /* Otherwise it's an error. */
265 return LOG_ERR;
266}
267
268int json_log_internal(JsonVariant *variant, int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(7, 8);
269
19130626 270#define json_log(variant, flags, error, ...) \
cd0b6c53 271 ({ \
19130626 272 int _level = json_dispatch_level(flags), _e = (error); \
cd0b6c53 273 (log_get_max_level() >= LOG_PRI(_level)) \
62c6bbbc 274 ? json_log_internal(variant, _level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
19130626 275 : -ERRNO_VALUE(_e); \
cd0b6c53
LP
276 })
277
d520d519
LP
278#define JSON_VARIANT_STRING_CONST(x) _JSON_VARIANT_STRING_CONST(UNIQ, (x))
279
90b365ce 280#define _JSON_VARIANT_STRING_CONST(xq, x) \
d520d519 281 ({ \
90b365ce 282 _align_(2) static const char UNIQ_T(json_string_const, xq)[] = (x); \
d520d519
LP
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
cd0b6c53
LP
287const char *json_variant_type_to_string(JsonVariantType t);
288JsonVariantType json_variant_type_from_string(const char *s);