]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/shared/json.h
json: Introduce JSON_BUILD_STRING_SET
[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
7314084a
YW
12#include "ether-addr-util.h"
13#include "in-addr-util.h"
14#include "log.h"
cd0b6c53
LP
15#include "macro.h"
16#include "string-util.h"
7314084a
YW
17#include "strv.h"
18#include "time-util.h"
cd0b6c53
LP
19
20/*
21 In case you wonder why we have our own JSON implementation, here are a couple of reasons why this implementation has
5238e957 22 benefits over various other implementations:
cd0b6c53 23
da890466 24 - We need support for 64-bit signed and unsigned integers, i.e. the full 64,5bit range of -9223372036854775808…18446744073709551615
cd0b6c53
LP
25 - All our variants are immutable after creation
26 - Special values such as true, false, zero, null, empty strings, empty array, empty objects require zero dynamic memory
27 - Progressive parsing
28 - Our integer/real type implicitly converts, but only if that's safe and loss-lessly possible
29 - There's a "builder" for putting together objects easily in varargs function calls
30 - There's a "dispatcher" for mapping objects to C data structures
31 - Every variant optionally carries parsing location information, which simplifies debugging and parse log error generation
32 - Formatter has color, line, column support
33
34 Limitations:
35 - Doesn't allow embedded NUL in strings
337712e7 36 - Can't store integers outside of the -9223372036854775808…18446744073709551615 range (it will use 'double' for
cd0b6c53
LP
37 values outside this range, which is lossy)
38 - Can't store negative zero (will be treated identical to positive zero, and not retained across serialization)
337712e7 39 - Can't store non-integer numbers that can't be stored in "double" losslessly
cd0b6c53
LP
40 - Allows creation and parsing of objects with duplicate keys. The "dispatcher" will refuse them however. This means
41 we can parse and pass around such objects, but will carefully refuse them when we convert them into our own data.
42
43 (These limitations should be pretty much in line with those of other JSON implementations, in fact might be less
44 limiting in most cases even.)
45*/
46
47typedef struct JsonVariant JsonVariant;
48
49typedef enum JsonVariantType {
50 JSON_VARIANT_STRING,
51 JSON_VARIANT_INTEGER,
52 JSON_VARIANT_UNSIGNED,
53 JSON_VARIANT_REAL,
54 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 */
55 JSON_VARIANT_BOOLEAN,
56 JSON_VARIANT_ARRAY,
57 JSON_VARIANT_OBJECT,
58 JSON_VARIANT_NULL,
59 _JSON_VARIANT_TYPE_MAX,
2d93c20e 60 _JSON_VARIANT_TYPE_INVALID = -EINVAL,
cd0b6c53
LP
61} JsonVariantType;
62
63int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n);
cc164891 64int json_variant_new_base64(JsonVariant **ret, const void *p, size_t n);
84738d86 65int json_variant_new_base32hex(JsonVariant **ret, const void *p, size_t n);
2d64d2b9 66int json_variant_new_hex(JsonVariant **ret, const void *p, size_t n);
84738d86 67int json_variant_new_octescape(JsonVariant **ret, const void *p, size_t n);
718ca772
ZJS
68int json_variant_new_integer(JsonVariant **ret, int64_t i);
69int json_variant_new_unsigned(JsonVariant **ret, uint64_t u);
337712e7 70int json_variant_new_real(JsonVariant **ret, double d);
cd0b6c53
LP
71int json_variant_new_boolean(JsonVariant **ret, bool b);
72int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n);
73int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n);
74int json_variant_new_array_strv(JsonVariant **ret, char **l);
75int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n);
76int json_variant_new_null(JsonVariant **ret);
0b9481cf 77int json_variant_new_id128(JsonVariant **ret, sd_id128_t id);
9bc4156c 78int json_variant_new_uuid(JsonVariant **ret, sd_id128_t id);
cd0b6c53
LP
79
80static inline int json_variant_new_string(JsonVariant **ret, const char *s) {
f5fbe71d 81 return json_variant_new_stringn(ret, s, SIZE_MAX);
cd0b6c53
LP
82}
83
84JsonVariant *json_variant_ref(JsonVariant *v);
85JsonVariant *json_variant_unref(JsonVariant *v);
86void json_variant_unref_many(JsonVariant **array, size_t n);
87
ce913e0e
ZJS
88#define JSON_VARIANT_REPLACE(v, q) \
89 do { \
90 typeof(v)* _v = &(v); \
91 typeof(q) _q = (q); \
92 json_variant_unref(*_v); \
93 *_v = _q; \
94 } while(0)
95
cd0b6c53
LP
96DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref);
97
98const char *json_variant_string(JsonVariant *v);
718ca772
ZJS
99int64_t json_variant_integer(JsonVariant *v);
100uint64_t json_variant_unsigned(JsonVariant *v);
337712e7 101double json_variant_real(JsonVariant *v);
cd0b6c53
LP
102bool json_variant_boolean(JsonVariant *v);
103
104JsonVariantType json_variant_type(JsonVariant *v);
105bool json_variant_has_type(JsonVariant *v, JsonVariantType type);
106
107static inline bool json_variant_is_string(JsonVariant *v) {
108 return json_variant_has_type(v, JSON_VARIANT_STRING);
109}
110
111static inline bool json_variant_is_integer(JsonVariant *v) {
112 return json_variant_has_type(v, JSON_VARIANT_INTEGER);
113}
114
115static inline bool json_variant_is_unsigned(JsonVariant *v) {
116 return json_variant_has_type(v, JSON_VARIANT_UNSIGNED);
117}
118
119static inline bool json_variant_is_real(JsonVariant *v) {
120 return json_variant_has_type(v, JSON_VARIANT_REAL);
121}
122
123static inline bool json_variant_is_number(JsonVariant *v) {
124 return json_variant_has_type(v, JSON_VARIANT_NUMBER);
125}
126
127static inline bool json_variant_is_boolean(JsonVariant *v) {
128 return json_variant_has_type(v, JSON_VARIANT_BOOLEAN);
129}
130
131static inline bool json_variant_is_array(JsonVariant *v) {
132 return json_variant_has_type(v, JSON_VARIANT_ARRAY);
133}
134
135static inline bool json_variant_is_object(JsonVariant *v) {
136 return json_variant_has_type(v, JSON_VARIANT_OBJECT);
137}
138
139static inline bool json_variant_is_null(JsonVariant *v) {
140 return json_variant_has_type(v, JSON_VARIANT_NULL);
141}
142
143bool json_variant_is_negative(JsonVariant *v);
e787b211
LP
144bool json_variant_is_blank_object(JsonVariant *v);
145bool json_variant_is_blank_array(JsonVariant *v);
b7fc90a2
LP
146bool json_variant_is_normalized(JsonVariant *v);
147bool json_variant_is_sorted(JsonVariant *v);
cd0b6c53
LP
148
149size_t json_variant_elements(JsonVariant *v);
150JsonVariant *json_variant_by_index(JsonVariant *v, size_t index);
151JsonVariant *json_variant_by_key(JsonVariant *v, const char *key);
152JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key);
153
154bool json_variant_equal(JsonVariant *a, JsonVariant *b);
155
83bc6cb7 156void json_variant_sensitive(JsonVariant *v);
94600eeb 157bool json_variant_is_sensitive(JsonVariant *v);
83bc6cb7 158
cd0b6c53
LP
159struct json_variant_foreach_state {
160 JsonVariant *variant;
161 size_t idx;
162};
163
fec7a9e0
YW
164#define _JSON_VARIANT_ARRAY_FOREACH(i, v, state) \
165 for (struct json_variant_foreach_state state = { (v), 0 }; \
166 json_variant_is_array(state.variant) && \
167 state.idx < json_variant_elements(state.variant) && \
168 ({ i = json_variant_by_index(state.variant, state.idx); \
169 true; }); \
170 state.idx++)
cd0b6c53 171#define JSON_VARIANT_ARRAY_FOREACH(i, v) \
fec7a9e0
YW
172 _JSON_VARIANT_ARRAY_FOREACH(i, v, UNIQ_T(state, UNIQ))
173
174#define _JSON_VARIANT_OBJECT_FOREACH(k, e, v, state) \
175 for (struct json_variant_foreach_state state = { (v), 0 }; \
176 json_variant_is_object(state.variant) && \
177 state.idx < json_variant_elements(state.variant) && \
178 ({ k = json_variant_string(json_variant_by_index(state.variant, state.idx)); \
179 e = json_variant_by_index(state.variant, state.idx + 1); \
cd0b6c53 180 true; }); \
fec7a9e0 181 state.idx += 2)
cd0b6c53 182#define JSON_VARIANT_OBJECT_FOREACH(k, e, v) \
fec7a9e0 183 _JSON_VARIANT_OBJECT_FOREACH(k, e, v, UNIQ_T(state, UNIQ))
cd0b6c53
LP
184
185int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column);
186
897f099b 187typedef enum JsonFormatFlags {
2d814304
LP
188 JSON_FORMAT_NEWLINE = 1 << 0, /* suffix with newline */
189 JSON_FORMAT_PRETTY = 1 << 1, /* add internal whitespace to appeal to human readers */
190 JSON_FORMAT_PRETTY_AUTO = 1 << 2, /* same, but only if connected to a tty (and JSON_FORMAT_NEWLINE otherwise) */
191 JSON_FORMAT_COLOR = 1 << 3, /* insert ANSI color sequences */
192 JSON_FORMAT_COLOR_AUTO = 1 << 4, /* insert ANSI color sequences if colors_enabled() says so */
193 JSON_FORMAT_SOURCE = 1 << 5, /* prefix with source filename/line/column */
194 JSON_FORMAT_SSE = 1 << 6, /* prefix/suffix with W3C server-sent events */
195 JSON_FORMAT_SEQ = 1 << 7, /* prefix/suffix with RFC 7464 application/json-seq */
196 JSON_FORMAT_FLUSH = 1 << 8, /* call fflush() after dumping JSON */
c3f0bff9
ZJS
197 JSON_FORMAT_EMPTY_ARRAY = 1 << 9, /* output "[]" for empty input */
198 JSON_FORMAT_OFF = 1 << 10, /* make json_variant_format() fail with -ENOEXEC */
897f099b 199} JsonFormatFlags;
cd0b6c53 200
897f099b 201int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret);
7922ead5 202int json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix);
cd0b6c53 203
f2ff34ff
LP
204int json_variant_filter(JsonVariant **v, char **to_remove);
205
78a41236 206int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *value);
f5fc7732 207int json_variant_set_fieldb(JsonVariant **v, const char *field, ...);
15f1fb3e 208int json_variant_set_field_string(JsonVariant **v, const char *field, const char *value);
718ca772
ZJS
209int json_variant_set_field_integer(JsonVariant **v, const char *field, int64_t value);
210int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uint64_t value);
a832b08e 211int json_variant_set_field_boolean(JsonVariant **v, const char *field, bool b);
0b9481cf 212int json_variant_set_field_strv(JsonVariant **v, const char *field, char **l);
78a41236 213
eafa923f
DDM
214static inline int json_variant_set_field_non_null(JsonVariant **v, const char *field, JsonVariant *value) {
215 return value && !json_variant_is_null(value) ? json_variant_set_field(v, field, value) : 0;
216}
217
3bb326c5
LP
218JsonVariant *json_variant_find(JsonVariant *haystack, JsonVariant *needle);
219
21e21511 220int json_variant_append_array(JsonVariant **v, JsonVariant *element);
3218794f 221int json_variant_append_arrayb(JsonVariant **v, ...);
3bb326c5 222int json_variant_append_array_nodup(JsonVariant **v, JsonVariant *element);
21e21511 223
e931768e
LP
224int json_variant_merge_object(JsonVariant **v, JsonVariant *m);
225int json_variant_merge_objectb(JsonVariant **v, ...);
ca409a59 226
22f14d6b
LP
227int json_variant_strv(JsonVariant *v, char ***ret);
228
b7fc90a2
LP
229int json_variant_sort(JsonVariant **v);
230int json_variant_normalize(JsonVariant **v);
231
d642f640
LP
232typedef enum JsonParseFlags {
233 JSON_PARSE_SENSITIVE = 1 << 0, /* mark variant as "sensitive", i.e. something containing secret key material or such */
234} JsonParseFlags;
f325aaf3 235
b0eeb945
ZJS
236int json_parse_with_source(const char *string, const char *source, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
237int json_parse_with_source_continue(const char **p, const char *source, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
238
239static inline int json_parse(const char *string, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
240 return json_parse_with_source(string, NULL, flags, ret, ret_line, ret_column);
241}
242static inline int json_parse_continue(const char **p, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
243 return json_parse_with_source_continue(p, NULL, flags, ret, ret_line, ret_column);
244}
245
d642f640
LP
246int json_parse_file_at(FILE *f, int dir_fd, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column);
247
248static inline int json_parse_file(FILE *f, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) {
249 return json_parse_file_at(f, AT_FDCWD, path, flags, ret, ret_line, ret_column);
f325aaf3 250}
cd0b6c53
LP
251
252enum {
253 _JSON_BUILD_STRING,
254 _JSON_BUILD_INTEGER,
255 _JSON_BUILD_UNSIGNED,
256 _JSON_BUILD_REAL,
257 _JSON_BUILD_BOOLEAN,
258 _JSON_BUILD_ARRAY_BEGIN,
259 _JSON_BUILD_ARRAY_END,
260 _JSON_BUILD_OBJECT_BEGIN,
261 _JSON_BUILD_OBJECT_END,
262 _JSON_BUILD_PAIR,
319a4f27 263 _JSON_BUILD_PAIR_CONDITION,
cd0b6c53
LP
264 _JSON_BUILD_NULL,
265 _JSON_BUILD_VARIANT,
e4defdc4 266 _JSON_BUILD_VARIANT_ARRAY,
cd0b6c53
LP
267 _JSON_BUILD_LITERAL,
268 _JSON_BUILD_STRV,
08e29ac7 269 _JSON_BUILD_STRV_ENV_PAIR,
886b0c93 270 _JSON_BUILD_BASE64,
84738d86 271 _JSON_BUILD_BASE32HEX,
2d64d2b9 272 _JSON_BUILD_HEX,
84738d86 273 _JSON_BUILD_OCTESCAPE,
0b9481cf 274 _JSON_BUILD_ID128,
9bc4156c 275 _JSON_BUILD_UUID,
0710343c 276 _JSON_BUILD_BYTE_ARRAY,
7314084a 277 _JSON_BUILD_HW_ADDR,
a636a058 278 _JSON_BUILD_STRING_SET,
7314084a
YW
279 _JSON_BUILD_PAIR_UNSIGNED_NON_ZERO,
280 _JSON_BUILD_PAIR_FINITE_USEC,
281 _JSON_BUILD_PAIR_STRING_NON_EMPTY,
282 _JSON_BUILD_PAIR_STRV_NON_EMPTY,
283 _JSON_BUILD_PAIR_VARIANT_NON_NULL,
284 _JSON_BUILD_PAIR_VARIANT_ARRAY_NON_EMPTY,
285 _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL,
286 _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL,
287 _JSON_BUILD_PAIR_IN_ADDR_NON_NULL,
288 _JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL,
289 _JSON_BUILD_PAIR_HW_ADDR_NON_NULL,
cd0b6c53
LP
290 _JSON_BUILD_MAX,
291};
292
3e4ca394 293#define JSON_BUILD_STRING(s) _JSON_BUILD_STRING, (const char*) { s }
718ca772
ZJS
294#define JSON_BUILD_INTEGER(i) _JSON_BUILD_INTEGER, (int64_t) { i }
295#define JSON_BUILD_UNSIGNED(u) _JSON_BUILD_UNSIGNED, (uint64_t) { u }
337712e7 296#define JSON_BUILD_REAL(d) _JSON_BUILD_REAL, (double) { d }
3e4ca394 297#define JSON_BUILD_BOOLEAN(b) _JSON_BUILD_BOOLEAN, (bool) { b }
cd0b6c53 298#define JSON_BUILD_ARRAY(...) _JSON_BUILD_ARRAY_BEGIN, __VA_ARGS__, _JSON_BUILD_ARRAY_END
aafa52ab 299#define JSON_BUILD_EMPTY_ARRAY _JSON_BUILD_ARRAY_BEGIN, _JSON_BUILD_ARRAY_END
cd0b6c53 300#define JSON_BUILD_OBJECT(...) _JSON_BUILD_OBJECT_BEGIN, __VA_ARGS__, _JSON_BUILD_OBJECT_END
aafa52ab 301#define JSON_BUILD_EMPTY_OBJECT _JSON_BUILD_OBJECT_BEGIN, _JSON_BUILD_OBJECT_END
3e4ca394
LP
302#define JSON_BUILD_PAIR(n, ...) _JSON_BUILD_PAIR, (const char*) { n }, __VA_ARGS__
303#define JSON_BUILD_PAIR_CONDITION(c, n, ...) _JSON_BUILD_PAIR_CONDITION, (bool) { c }, (const char*) { n }, __VA_ARGS__
cd0b6c53 304#define JSON_BUILD_NULL _JSON_BUILD_NULL
3e4ca394
LP
305#define JSON_BUILD_VARIANT(v) _JSON_BUILD_VARIANT, (JsonVariant*) { v }
306#define JSON_BUILD_VARIANT_ARRAY(v, n) _JSON_BUILD_VARIANT_ARRAY, (JsonVariant **) { v }, (size_t) { n }
307#define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, (const char*) { l }
308#define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, (char**) { l }
08e29ac7 309#define JSON_BUILD_STRV_ENV_PAIR(l) _JSON_BUILD_STRV_ENV_PAIR, (char**) { l }
3e4ca394 310#define JSON_BUILD_BASE64(p, n) _JSON_BUILD_BASE64, (const void*) { p }, (size_t) { n }
84738d86 311#define JSON_BUILD_BASE32HEX(p, n) _JSON_BUILD_BASE32HEX, (const void*) { p }, (size_t) { n }
3e4ca394 312#define JSON_BUILD_HEX(p, n) _JSON_BUILD_HEX, (const void*) { p }, (size_t) { n }
84738d86 313#define JSON_BUILD_OCTESCAPE(p, n) _JSON_BUILD_OCTESCAPE, (const void*) { p }, (size_t) { n }
3e4ca394 314#define JSON_BUILD_ID128(id) _JSON_BUILD_ID128, (const sd_id128_t*) { &(id) }
9bc4156c 315#define JSON_BUILD_UUID(id) _JSON_BUILD_UUID, (const sd_id128_t*) { &(id) }
3e4ca394 316#define JSON_BUILD_BYTE_ARRAY(v, n) _JSON_BUILD_BYTE_ARRAY, (const void*) { v }, (size_t) { n }
0cdf6b14 317#define JSON_BUILD_CONST_STRING(s) _JSON_BUILD_VARIANT, JSON_VARIANT_STRING_CONST(s)
7314084a
YW
318#define JSON_BUILD_IN4_ADDR(v) JSON_BUILD_BYTE_ARRAY((const struct in_addr*) { v }, sizeof(struct in_addr))
319#define JSON_BUILD_IN6_ADDR(v) JSON_BUILD_BYTE_ARRAY((const struct in6_addr*) { v }, sizeof(struct in6_addr))
320#define JSON_BUILD_IN_ADDR(v, f) JSON_BUILD_BYTE_ARRAY(((const union in_addr_union*) { v })->bytes, FAMILY_ADDRESS_SIZE_SAFE(f))
321#define JSON_BUILD_ETHER_ADDR(v) JSON_BUILD_BYTE_ARRAY(((const struct ether_addr*) { v })->ether_addr_octet, sizeof(struct ether_addr))
322#define JSON_BUILD_HW_ADDR(v) _JSON_BUILD_HW_ADDR, (const struct hw_addr_data*) { v }
a636a058 323#define JSON_BUILD_STRING_SET(s) _JSON_BUILD_STRING_SET, (Set *) { s }
7314084a
YW
324
325#define JSON_BUILD_PAIR_STRING(name, s) JSON_BUILD_PAIR(name, JSON_BUILD_STRING(s))
326#define JSON_BUILD_PAIR_INTEGER(name, i) JSON_BUILD_PAIR(name, JSON_BUILD_INTEGER(i))
327#define JSON_BUILD_PAIR_UNSIGNED(name, u) JSON_BUILD_PAIR(name, JSON_BUILD_UNSIGNED(u))
328#define JSON_BUILD_PAIR_REAL(name, d) JSON_BUILD_PAIR(name, JSON_BUILD_REAL(d))
329#define JSON_BUILD_PAIR_BOOLEAN(name, b) JSON_BUILD_PAIR(name, JSON_BUILD_BOOLEAN(b))
330#define JSON_BUILD_PAIR_ARRAY(name, ...) JSON_BUILD_PAIR(name, JSON_BUILD_ARRAY(__VA_ARGS__))
331#define JSON_BUILD_PAIR_EMPTY_ARRAY(name) JSON_BUILD_PAIR(name, JSON_BUILD_EMPTY_ARRAY)
332#define JSON_BUILD_PAIR_OBJECT(name, ...) JSON_BUILD_PAIR(name, JSON_BUILD_OBJECT(__VA_ARGS__))
333#define JSON_BUILD_PAIR_EMPTY_OBJECT(name) JSON_BUILD_PAIR(name, JSON_BUILD_EMPTY_OBJECT)
334#define JSON_BUILD_PAIR_NULL(name) JSON_BUILD_PAIR(name, JSON_BUILD_NULL)
335#define JSON_BUILD_PAIR_VARIANT(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_VARIANT(v))
336#define JSON_BUILD_PAIR_VARIANT_ARRAY(name, v, n) JSON_BUILD_PAIR(name, JSON_BUILD_VARIANT_ARRAY(v, n))
337#define JSON_BUILD_PAIR_LITERAL(name, l) JSON_BUILD_PAIR(name, JSON_BUILD_LITERAL(l))
338#define JSON_BUILD_PAIR_STRV(name, l) JSON_BUILD_PAIR(name, JSON_BUILD_STRV(l))
339#define JSON_BUILD_PAIR_BASE64(name, p, n) JSON_BUILD_PAIR(name, JSON_BUILD_BASE64(p, n))
340#define JSON_BUILD_PAIR_HEX(name, p, n) JSON_BUILD_PAIR(name, JSON_BUILD_HEX(p, n))
341#define JSON_BUILD_PAIR_ID128(name, id) JSON_BUILD_PAIR(name, JSON_BUILD_ID128(id))
9bc4156c 342#define JSON_BUILD_PAIR_UUID(name, id) JSON_BUILD_PAIR(name, JSON_BUILD_UUID(id))
7314084a
YW
343#define JSON_BUILD_PAIR_BYTE_ARRAY(name, v, n) JSON_BUILD_PAIR(name, JSON_BUILD_BYTE_ARRAY(v, n))
344#define JSON_BUILD_PAIR_IN4_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_IN4_ADDR(v))
345#define JSON_BUILD_PAIR_IN6_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_IN6_ADDR(v))
346#define JSON_BUILD_PAIR_IN_ADDR(name, v, f) JSON_BUILD_PAIR(name, JSON_BUILD_IN_ADDR(v, f))
347#define JSON_BUILD_PAIR_ETHER_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_ETHER_ADDR(v))
348#define JSON_BUILD_PAIR_HW_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_HW_ADDR(v))
a636a058 349#define JSON_BUILD_PAIR_STRING_SET(name, s) JSON_BUILD_PAIR(name, JSON_BUILD_STRING_SET(s))
7314084a
YW
350
351#define JSON_BUILD_PAIR_UNSIGNED_NON_ZERO(name, u) _JSON_BUILD_PAIR_UNSIGNED_NON_ZERO, (const char*) { name }, (uint64_t) { u }
352#define JSON_BUILD_PAIR_FINITE_USEC(name, u) _JSON_BUILD_PAIR_FINITE_USEC, (const char*) { name }, (usec_t) { u }
353#define JSON_BUILD_PAIR_STRING_NON_EMPTY(name, s) _JSON_BUILD_PAIR_STRING_NON_EMPTY, (const char*) { name }, (const char*) { s }
354#define JSON_BUILD_PAIR_STRV_NON_EMPTY(name, l) _JSON_BUILD_PAIR_STRV_NON_EMPTY, (const char*) { name }, (char**) { l }
355#define JSON_BUILD_PAIR_VARIANT_NON_NULL(name, v) _JSON_BUILD_PAIR_VARIANT_NON_NULL, (const char*) { name }, (JsonVariant*) { v }
356#define JSON_BUILD_PAIR_IN4_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL, (const char*) { name }, (const struct in_addr*) { v }
357#define JSON_BUILD_PAIR_IN6_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL, (const char*) { name }, (const struct in6_addr*) { v }
358#define JSON_BUILD_PAIR_IN_ADDR_NON_NULL(name, v, f) _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, (const char*) { name }, (const union in_addr_union*) { v }, (int) { f }
359#define JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL, (const char*) { name }, (const struct ether_addr*) { v }
360#define JSON_BUILD_PAIR_HW_ADDR_NON_NULL(name, v) _JSON_BUILD_PAIR_HW_ADDR_NON_NULL, (const char*) { name }, (const struct hw_addr_data*) { v }
cd0b6c53
LP
361
362int json_build(JsonVariant **ret, ...);
363int json_buildv(JsonVariant **ret, va_list ap);
364
365/* A bitmask of flags used by the dispatch logic. Note that this is a combined bit mask, that is generated from the bit
366 * mask originally passed into json_dispatch(), the individual bitmask associated with the static JsonDispatch callout
367 * entry, as well the bitmask specified for json_log() calls */
368typedef enum JsonDispatchFlags {
369 /* The following three may be set in JsonDispatch's .flags field or the json_dispatch() flags parameter */
370 JSON_PERMISSIVE = 1 << 0, /* Shall parsing errors be considered fatal for this property? */
5238e957 371 JSON_MANDATORY = 1 << 1, /* Should existence of this property be mandatory? */
cd0b6c53 372 JSON_LOG = 1 << 2, /* Should the parser log about errors? */
ba23dbf1 373 JSON_SAFE = 1 << 3, /* Don't accept "unsafe" strings in json_dispatch_string() + json_dispatch_string() */
7a8867ab 374 JSON_RELAX = 1 << 4, /* Use relaxed user name checking in json_dispatch_user_group_name */
cd0b6c53 375
680f2fb3
ZJS
376 /* The following two may be passed into log_json() in addition to those above */
377 JSON_DEBUG = 1 << 5, /* Indicates that this log message is a debug message */
378 JSON_WARNING = 1 << 6, /* Indicates that this log message is a warning message */
cd0b6c53
LP
379} JsonDispatchFlags;
380
381typedef int (*JsonDispatchCallback)(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
382
383typedef struct JsonDispatch {
384 const char *name;
385 JsonVariantType type;
386 JsonDispatchCallback callback;
387 size_t offset;
388 JsonDispatchFlags flags;
389} JsonDispatch;
390
391int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata);
392
393int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
19a209cc 394int json_dispatch_const_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
cd0b6c53
LP
395int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
396int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
397int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
398int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
6b9f63cb 399int json_dispatch_variant_noref(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
718ca772
ZJS
400int json_dispatch_int64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
401int json_dispatch_uint64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
cd0b6c53
LP
402int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
403int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
e085625f
LP
404int json_dispatch_uint16(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
405int json_dispatch_int16(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
a42ef715
LP
406int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
407int json_dispatch_user_group_name(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
408int json_dispatch_id128(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
409int json_dispatch_unsupported(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata);
cd0b6c53 410
b97e3e3d
LP
411assert_cc(sizeof(uint32_t) == sizeof(unsigned));
412#define json_dispatch_uint json_dispatch_uint32
413
414assert_cc(sizeof(int32_t) == sizeof(int));
415#define json_dispatch_int json_dispatch_int32
416
cd0b6c53
LP
417static inline int json_dispatch_level(JsonDispatchFlags flags) {
418
419 /* Did the user request no logging? If so, then never log higher than LOG_DEBUG. Also, if this is marked as
420 * debug message, then also log at debug level. */
421
422 if (!(flags & JSON_LOG) ||
423 (flags & JSON_DEBUG))
424 return LOG_DEBUG;
425
426 /* Are we invoked in permissive mode, or is this explicitly marked as warning message? Then this should be
427 * printed at LOG_WARNING */
428 if (flags & (JSON_PERMISSIVE|JSON_WARNING))
429 return LOG_WARNING;
430
431 /* Otherwise it's an error. */
432 return LOG_ERR;
433}
434
435int json_log_internal(JsonVariant *variant, int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(7, 8);
436
19130626 437#define json_log(variant, flags, error, ...) \
cd0b6c53 438 ({ \
19130626 439 int _level = json_dispatch_level(flags), _e = (error); \
cd0b6c53 440 (log_get_max_level() >= LOG_PRI(_level)) \
62c6bbbc 441 ? json_log_internal(variant, _level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \
19130626 442 : -ERRNO_VALUE(_e); \
cd0b6c53
LP
443 })
444
0ac0787e
LP
445#define json_log_oom(variant, flags) \
446 json_log(variant, flags, SYNTHETIC_ERRNO(ENOMEM), "Out of memory.")
447
d520d519
LP
448#define JSON_VARIANT_STRING_CONST(x) _JSON_VARIANT_STRING_CONST(UNIQ, (x))
449
90b365ce 450#define _JSON_VARIANT_STRING_CONST(xq, x) \
d520d519 451 ({ \
90b365ce 452 _align_(2) static const char UNIQ_T(json_string_const, xq)[] = (x); \
d520d519
LP
453 assert((((uintptr_t) UNIQ_T(json_string_const, xq)) & 1) == 0); \
454 (JsonVariant*) ((uintptr_t) UNIQ_T(json_string_const, xq) + 1); \
455 })
456
faca141c 457int json_variant_unbase64(JsonVariant *v, void **ret, size_t *ret_size);
2d64d2b9 458int json_variant_unhex(JsonVariant *v, void **ret, size_t *ret_size);
faca141c 459
cd0b6c53
LP
460const char *json_variant_type_to_string(JsonVariantType t);
461JsonVariantType json_variant_type_from_string(const char *s);