]>
Commit | Line | Data |
---|---|---|
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 | ||
47 | typedef struct JsonVariant JsonVariant; | |
48 | ||
49 | typedef 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 | ||
63 | int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n); | |
cc164891 | 64 | int json_variant_new_base64(JsonVariant **ret, const void *p, size_t n); |
84738d86 | 65 | int json_variant_new_base32hex(JsonVariant **ret, const void *p, size_t n); |
2d64d2b9 | 66 | int json_variant_new_hex(JsonVariant **ret, const void *p, size_t n); |
84738d86 | 67 | int json_variant_new_octescape(JsonVariant **ret, const void *p, size_t n); |
718ca772 ZJS |
68 | int json_variant_new_integer(JsonVariant **ret, int64_t i); |
69 | int json_variant_new_unsigned(JsonVariant **ret, uint64_t u); | |
337712e7 | 70 | int json_variant_new_real(JsonVariant **ret, double d); |
cd0b6c53 LP |
71 | int json_variant_new_boolean(JsonVariant **ret, bool b); |
72 | int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n); | |
73 | int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n); | |
74 | int json_variant_new_array_strv(JsonVariant **ret, char **l); | |
75 | int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n); | |
76 | int json_variant_new_null(JsonVariant **ret); | |
0b9481cf | 77 | int json_variant_new_id128(JsonVariant **ret, sd_id128_t id); |
9bc4156c | 78 | int json_variant_new_uuid(JsonVariant **ret, sd_id128_t id); |
cd0b6c53 LP |
79 | |
80 | static 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 | ||
84 | JsonVariant *json_variant_ref(JsonVariant *v); | |
85 | JsonVariant *json_variant_unref(JsonVariant *v); | |
86 | void 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 |
96 | DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref); |
97 | ||
98 | const char *json_variant_string(JsonVariant *v); | |
718ca772 ZJS |
99 | int64_t json_variant_integer(JsonVariant *v); |
100 | uint64_t json_variant_unsigned(JsonVariant *v); | |
337712e7 | 101 | double json_variant_real(JsonVariant *v); |
cd0b6c53 LP |
102 | bool json_variant_boolean(JsonVariant *v); |
103 | ||
104 | JsonVariantType json_variant_type(JsonVariant *v); | |
105 | bool json_variant_has_type(JsonVariant *v, JsonVariantType type); | |
106 | ||
107 | static inline bool json_variant_is_string(JsonVariant *v) { | |
108 | return json_variant_has_type(v, JSON_VARIANT_STRING); | |
109 | } | |
110 | ||
111 | static inline bool json_variant_is_integer(JsonVariant *v) { | |
112 | return json_variant_has_type(v, JSON_VARIANT_INTEGER); | |
113 | } | |
114 | ||
115 | static inline bool json_variant_is_unsigned(JsonVariant *v) { | |
116 | return json_variant_has_type(v, JSON_VARIANT_UNSIGNED); | |
117 | } | |
118 | ||
119 | static inline bool json_variant_is_real(JsonVariant *v) { | |
120 | return json_variant_has_type(v, JSON_VARIANT_REAL); | |
121 | } | |
122 | ||
123 | static inline bool json_variant_is_number(JsonVariant *v) { | |
124 | return json_variant_has_type(v, JSON_VARIANT_NUMBER); | |
125 | } | |
126 | ||
127 | static inline bool json_variant_is_boolean(JsonVariant *v) { | |
128 | return json_variant_has_type(v, JSON_VARIANT_BOOLEAN); | |
129 | } | |
130 | ||
131 | static inline bool json_variant_is_array(JsonVariant *v) { | |
132 | return json_variant_has_type(v, JSON_VARIANT_ARRAY); | |
133 | } | |
134 | ||
135 | static inline bool json_variant_is_object(JsonVariant *v) { | |
136 | return json_variant_has_type(v, JSON_VARIANT_OBJECT); | |
137 | } | |
138 | ||
139 | static inline bool json_variant_is_null(JsonVariant *v) { | |
140 | return json_variant_has_type(v, JSON_VARIANT_NULL); | |
141 | } | |
142 | ||
143 | bool json_variant_is_negative(JsonVariant *v); | |
e787b211 LP |
144 | bool json_variant_is_blank_object(JsonVariant *v); |
145 | bool json_variant_is_blank_array(JsonVariant *v); | |
b7fc90a2 LP |
146 | bool json_variant_is_normalized(JsonVariant *v); |
147 | bool json_variant_is_sorted(JsonVariant *v); | |
cd0b6c53 LP |
148 | |
149 | size_t json_variant_elements(JsonVariant *v); | |
150 | JsonVariant *json_variant_by_index(JsonVariant *v, size_t index); | |
151 | JsonVariant *json_variant_by_key(JsonVariant *v, const char *key); | |
152 | JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key); | |
153 | ||
154 | bool json_variant_equal(JsonVariant *a, JsonVariant *b); | |
155 | ||
83bc6cb7 | 156 | void json_variant_sensitive(JsonVariant *v); |
94600eeb | 157 | bool json_variant_is_sensitive(JsonVariant *v); |
c609338b | 158 | bool json_variant_is_sensitive_recursive(JsonVariant *v); |
83bc6cb7 | 159 | |
cd0b6c53 LP |
160 | struct json_variant_foreach_state { |
161 | JsonVariant *variant; | |
162 | size_t idx; | |
163 | }; | |
164 | ||
fec7a9e0 YW |
165 | #define _JSON_VARIANT_ARRAY_FOREACH(i, v, state) \ |
166 | for (struct json_variant_foreach_state state = { (v), 0 }; \ | |
167 | json_variant_is_array(state.variant) && \ | |
168 | state.idx < json_variant_elements(state.variant) && \ | |
169 | ({ i = json_variant_by_index(state.variant, state.idx); \ | |
170 | true; }); \ | |
171 | state.idx++) | |
cd0b6c53 | 172 | #define JSON_VARIANT_ARRAY_FOREACH(i, v) \ |
fec7a9e0 YW |
173 | _JSON_VARIANT_ARRAY_FOREACH(i, v, UNIQ_T(state, UNIQ)) |
174 | ||
175 | #define _JSON_VARIANT_OBJECT_FOREACH(k, e, v, state) \ | |
176 | for (struct json_variant_foreach_state state = { (v), 0 }; \ | |
177 | json_variant_is_object(state.variant) && \ | |
178 | state.idx < json_variant_elements(state.variant) && \ | |
179 | ({ k = json_variant_string(json_variant_by_index(state.variant, state.idx)); \ | |
180 | e = json_variant_by_index(state.variant, state.idx + 1); \ | |
cd0b6c53 | 181 | true; }); \ |
fec7a9e0 | 182 | state.idx += 2) |
cd0b6c53 | 183 | #define JSON_VARIANT_OBJECT_FOREACH(k, e, v) \ |
fec7a9e0 | 184 | _JSON_VARIANT_OBJECT_FOREACH(k, e, v, UNIQ_T(state, UNIQ)) |
cd0b6c53 LP |
185 | |
186 | int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column); | |
187 | ||
897f099b | 188 | typedef enum JsonFormatFlags { |
fa9a6db4 LB |
189 | JSON_FORMAT_NEWLINE = 1 << 0, /* suffix with newline */ |
190 | JSON_FORMAT_PRETTY = 1 << 1, /* add internal whitespace to appeal to human readers */ | |
191 | JSON_FORMAT_PRETTY_AUTO = 1 << 2, /* same, but only if connected to a tty (and JSON_FORMAT_NEWLINE otherwise) */ | |
192 | JSON_FORMAT_COLOR = 1 << 3, /* insert ANSI color sequences */ | |
193 | JSON_FORMAT_COLOR_AUTO = 1 << 4, /* insert ANSI color sequences if colors_enabled() says so */ | |
194 | JSON_FORMAT_SOURCE = 1 << 5, /* prefix with source filename/line/column */ | |
195 | JSON_FORMAT_SSE = 1 << 6, /* prefix/suffix with W3C server-sent events */ | |
196 | JSON_FORMAT_SEQ = 1 << 7, /* prefix/suffix with RFC 7464 application/json-seq */ | |
197 | JSON_FORMAT_FLUSH = 1 << 8, /* call fflush() after dumping JSON */ | |
198 | JSON_FORMAT_EMPTY_ARRAY = 1 << 9, /* output "[]" for empty input */ | |
199 | JSON_FORMAT_OFF = 1 << 10, /* make json_variant_format() fail with -ENOEXEC */ | |
99128971 | 200 | JSON_FORMAT_CENSOR_SENSITIVE = 1 << 11, /* Replace all sensitive elements with the string "<sensitive data>" */ |
897f099b | 201 | } JsonFormatFlags; |
cd0b6c53 | 202 | |
897f099b | 203 | int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret); |
7922ead5 | 204 | int json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix); |
cd0b6c53 | 205 | |
f2ff34ff LP |
206 | int json_variant_filter(JsonVariant **v, char **to_remove); |
207 | ||
78a41236 | 208 | int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *value); |
f5fc7732 | 209 | int json_variant_set_fieldb(JsonVariant **v, const char *field, ...); |
15f1fb3e | 210 | int json_variant_set_field_string(JsonVariant **v, const char *field, const char *value); |
718ca772 ZJS |
211 | int json_variant_set_field_integer(JsonVariant **v, const char *field, int64_t value); |
212 | int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uint64_t value); | |
a832b08e | 213 | int json_variant_set_field_boolean(JsonVariant **v, const char *field, bool b); |
0b9481cf | 214 | int json_variant_set_field_strv(JsonVariant **v, const char *field, char **l); |
78a41236 | 215 | |
eafa923f DDM |
216 | static inline int json_variant_set_field_non_null(JsonVariant **v, const char *field, JsonVariant *value) { |
217 | return value && !json_variant_is_null(value) ? json_variant_set_field(v, field, value) : 0; | |
218 | } | |
219 | ||
3bb326c5 LP |
220 | JsonVariant *json_variant_find(JsonVariant *haystack, JsonVariant *needle); |
221 | ||
21e21511 | 222 | int json_variant_append_array(JsonVariant **v, JsonVariant *element); |
3218794f | 223 | int json_variant_append_arrayb(JsonVariant **v, ...); |
3bb326c5 | 224 | int json_variant_append_array_nodup(JsonVariant **v, JsonVariant *element); |
21e21511 | 225 | |
e931768e LP |
226 | int json_variant_merge_object(JsonVariant **v, JsonVariant *m); |
227 | int json_variant_merge_objectb(JsonVariant **v, ...); | |
ca409a59 | 228 | |
22f14d6b LP |
229 | int json_variant_strv(JsonVariant *v, char ***ret); |
230 | ||
b7fc90a2 LP |
231 | int json_variant_sort(JsonVariant **v); |
232 | int json_variant_normalize(JsonVariant **v); | |
233 | ||
d642f640 LP |
234 | typedef enum JsonParseFlags { |
235 | JSON_PARSE_SENSITIVE = 1 << 0, /* mark variant as "sensitive", i.e. something containing secret key material or such */ | |
236 | } JsonParseFlags; | |
f325aaf3 | 237 | |
b0eeb945 ZJS |
238 | int json_parse_with_source(const char *string, const char *source, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column); |
239 | int json_parse_with_source_continue(const char **p, const char *source, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column); | |
240 | ||
241 | static inline int json_parse(const char *string, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) { | |
242 | return json_parse_with_source(string, NULL, flags, ret, ret_line, ret_column); | |
243 | } | |
244 | static inline int json_parse_continue(const char **p, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) { | |
245 | return json_parse_with_source_continue(p, NULL, flags, ret, ret_line, ret_column); | |
246 | } | |
247 | ||
d642f640 LP |
248 | int json_parse_file_at(FILE *f, int dir_fd, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column); |
249 | ||
250 | static inline int json_parse_file(FILE *f, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column) { | |
251 | return json_parse_file_at(f, AT_FDCWD, path, flags, ret, ret_line, ret_column); | |
f325aaf3 | 252 | } |
cd0b6c53 LP |
253 | |
254 | enum { | |
255 | _JSON_BUILD_STRING, | |
256 | _JSON_BUILD_INTEGER, | |
257 | _JSON_BUILD_UNSIGNED, | |
258 | _JSON_BUILD_REAL, | |
259 | _JSON_BUILD_BOOLEAN, | |
260 | _JSON_BUILD_ARRAY_BEGIN, | |
261 | _JSON_BUILD_ARRAY_END, | |
262 | _JSON_BUILD_OBJECT_BEGIN, | |
263 | _JSON_BUILD_OBJECT_END, | |
264 | _JSON_BUILD_PAIR, | |
319a4f27 | 265 | _JSON_BUILD_PAIR_CONDITION, |
cd0b6c53 LP |
266 | _JSON_BUILD_NULL, |
267 | _JSON_BUILD_VARIANT, | |
e4defdc4 | 268 | _JSON_BUILD_VARIANT_ARRAY, |
cd0b6c53 LP |
269 | _JSON_BUILD_LITERAL, |
270 | _JSON_BUILD_STRV, | |
08e29ac7 | 271 | _JSON_BUILD_STRV_ENV_PAIR, |
886b0c93 | 272 | _JSON_BUILD_BASE64, |
03427720 | 273 | _JSON_BUILD_IOVEC_BASE64, |
84738d86 | 274 | _JSON_BUILD_BASE32HEX, |
2d64d2b9 | 275 | _JSON_BUILD_HEX, |
b22f0a50 | 276 | _JSON_BUILD_IOVEC_HEX, |
84738d86 | 277 | _JSON_BUILD_OCTESCAPE, |
0b9481cf | 278 | _JSON_BUILD_ID128, |
9bc4156c | 279 | _JSON_BUILD_UUID, |
0710343c | 280 | _JSON_BUILD_BYTE_ARRAY, |
7314084a | 281 | _JSON_BUILD_HW_ADDR, |
a636a058 | 282 | _JSON_BUILD_STRING_SET, |
8eb735b8 | 283 | _JSON_BUILD_CALLBACK, |
7314084a YW |
284 | _JSON_BUILD_PAIR_UNSIGNED_NON_ZERO, |
285 | _JSON_BUILD_PAIR_FINITE_USEC, | |
286 | _JSON_BUILD_PAIR_STRING_NON_EMPTY, | |
287 | _JSON_BUILD_PAIR_STRV_NON_EMPTY, | |
288 | _JSON_BUILD_PAIR_VARIANT_NON_NULL, | |
289 | _JSON_BUILD_PAIR_VARIANT_ARRAY_NON_EMPTY, | |
290 | _JSON_BUILD_PAIR_IN4_ADDR_NON_NULL, | |
291 | _JSON_BUILD_PAIR_IN6_ADDR_NON_NULL, | |
292 | _JSON_BUILD_PAIR_IN_ADDR_NON_NULL, | |
293 | _JSON_BUILD_PAIR_ETHER_ADDR_NON_NULL, | |
294 | _JSON_BUILD_PAIR_HW_ADDR_NON_NULL, | |
cd0b6c53 LP |
295 | _JSON_BUILD_MAX, |
296 | }; | |
297 | ||
8eb735b8 DDM |
298 | typedef int (*JsonBuildCallback)(JsonVariant **ret, const char *name, void *userdata); |
299 | ||
3e4ca394 | 300 | #define JSON_BUILD_STRING(s) _JSON_BUILD_STRING, (const char*) { s } |
718ca772 ZJS |
301 | #define JSON_BUILD_INTEGER(i) _JSON_BUILD_INTEGER, (int64_t) { i } |
302 | #define JSON_BUILD_UNSIGNED(u) _JSON_BUILD_UNSIGNED, (uint64_t) { u } | |
337712e7 | 303 | #define JSON_BUILD_REAL(d) _JSON_BUILD_REAL, (double) { d } |
3e4ca394 | 304 | #define JSON_BUILD_BOOLEAN(b) _JSON_BUILD_BOOLEAN, (bool) { b } |
cd0b6c53 | 305 | #define JSON_BUILD_ARRAY(...) _JSON_BUILD_ARRAY_BEGIN, __VA_ARGS__, _JSON_BUILD_ARRAY_END |
aafa52ab | 306 | #define JSON_BUILD_EMPTY_ARRAY _JSON_BUILD_ARRAY_BEGIN, _JSON_BUILD_ARRAY_END |
cd0b6c53 | 307 | #define JSON_BUILD_OBJECT(...) _JSON_BUILD_OBJECT_BEGIN, __VA_ARGS__, _JSON_BUILD_OBJECT_END |
aafa52ab | 308 | #define JSON_BUILD_EMPTY_OBJECT _JSON_BUILD_OBJECT_BEGIN, _JSON_BUILD_OBJECT_END |
3e4ca394 LP |
309 | #define JSON_BUILD_PAIR(n, ...) _JSON_BUILD_PAIR, (const char*) { n }, __VA_ARGS__ |
310 | #define JSON_BUILD_PAIR_CONDITION(c, n, ...) _JSON_BUILD_PAIR_CONDITION, (bool) { c }, (const char*) { n }, __VA_ARGS__ | |
cd0b6c53 | 311 | #define JSON_BUILD_NULL _JSON_BUILD_NULL |
3e4ca394 LP |
312 | #define JSON_BUILD_VARIANT(v) _JSON_BUILD_VARIANT, (JsonVariant*) { v } |
313 | #define JSON_BUILD_VARIANT_ARRAY(v, n) _JSON_BUILD_VARIANT_ARRAY, (JsonVariant **) { v }, (size_t) { n } | |
314 | #define JSON_BUILD_LITERAL(l) _JSON_BUILD_LITERAL, (const char*) { l } | |
315 | #define JSON_BUILD_STRV(l) _JSON_BUILD_STRV, (char**) { l } | |
08e29ac7 | 316 | #define JSON_BUILD_STRV_ENV_PAIR(l) _JSON_BUILD_STRV_ENV_PAIR, (char**) { l } |
3e4ca394 | 317 | #define JSON_BUILD_BASE64(p, n) _JSON_BUILD_BASE64, (const void*) { p }, (size_t) { n } |
03427720 | 318 | #define JSON_BUILD_IOVEC_BASE64(iov) _JSON_BUILD_IOVEC_BASE64, (const struct iovec*) { iov } |
84738d86 | 319 | #define JSON_BUILD_BASE32HEX(p, n) _JSON_BUILD_BASE32HEX, (const void*) { p }, (size_t) { n } |
3e4ca394 | 320 | #define JSON_BUILD_HEX(p, n) _JSON_BUILD_HEX, (const void*) { p }, (size_t) { n } |
b22f0a50 | 321 | #define JSON_BUILD_IOVEC_HEX(iov) _JSON_BUILD_IOVEC_HEX, (const struct iovec*) { iov } |
84738d86 | 322 | #define JSON_BUILD_OCTESCAPE(p, n) _JSON_BUILD_OCTESCAPE, (const void*) { p }, (size_t) { n } |
3e4ca394 | 323 | #define JSON_BUILD_ID128(id) _JSON_BUILD_ID128, (const sd_id128_t*) { &(id) } |
9bc4156c | 324 | #define JSON_BUILD_UUID(id) _JSON_BUILD_UUID, (const sd_id128_t*) { &(id) } |
3e4ca394 | 325 | #define JSON_BUILD_BYTE_ARRAY(v, n) _JSON_BUILD_BYTE_ARRAY, (const void*) { v }, (size_t) { n } |
0cdf6b14 | 326 | #define JSON_BUILD_CONST_STRING(s) _JSON_BUILD_VARIANT, JSON_VARIANT_STRING_CONST(s) |
7314084a YW |
327 | #define JSON_BUILD_IN4_ADDR(v) JSON_BUILD_BYTE_ARRAY((const struct in_addr*) { v }, sizeof(struct in_addr)) |
328 | #define JSON_BUILD_IN6_ADDR(v) JSON_BUILD_BYTE_ARRAY((const struct in6_addr*) { v }, sizeof(struct in6_addr)) | |
329 | #define JSON_BUILD_IN_ADDR(v, f) JSON_BUILD_BYTE_ARRAY(((const union in_addr_union*) { v })->bytes, FAMILY_ADDRESS_SIZE_SAFE(f)) | |
330 | #define JSON_BUILD_ETHER_ADDR(v) JSON_BUILD_BYTE_ARRAY(((const struct ether_addr*) { v })->ether_addr_octet, sizeof(struct ether_addr)) | |
331 | #define JSON_BUILD_HW_ADDR(v) _JSON_BUILD_HW_ADDR, (const struct hw_addr_data*) { v } | |
a636a058 | 332 | #define JSON_BUILD_STRING_SET(s) _JSON_BUILD_STRING_SET, (Set *) { s } |
8eb735b8 | 333 | #define JSON_BUILD_CALLBACK(c, u) _JSON_BUILD_CALLBACK, (JsonBuildCallback) { c }, (void*) { u } |
7314084a YW |
334 | |
335 | #define JSON_BUILD_PAIR_STRING(name, s) JSON_BUILD_PAIR(name, JSON_BUILD_STRING(s)) | |
336 | #define JSON_BUILD_PAIR_INTEGER(name, i) JSON_BUILD_PAIR(name, JSON_BUILD_INTEGER(i)) | |
337 | #define JSON_BUILD_PAIR_UNSIGNED(name, u) JSON_BUILD_PAIR(name, JSON_BUILD_UNSIGNED(u)) | |
338 | #define JSON_BUILD_PAIR_REAL(name, d) JSON_BUILD_PAIR(name, JSON_BUILD_REAL(d)) | |
339 | #define JSON_BUILD_PAIR_BOOLEAN(name, b) JSON_BUILD_PAIR(name, JSON_BUILD_BOOLEAN(b)) | |
340 | #define JSON_BUILD_PAIR_ARRAY(name, ...) JSON_BUILD_PAIR(name, JSON_BUILD_ARRAY(__VA_ARGS__)) | |
341 | #define JSON_BUILD_PAIR_EMPTY_ARRAY(name) JSON_BUILD_PAIR(name, JSON_BUILD_EMPTY_ARRAY) | |
342 | #define JSON_BUILD_PAIR_OBJECT(name, ...) JSON_BUILD_PAIR(name, JSON_BUILD_OBJECT(__VA_ARGS__)) | |
343 | #define JSON_BUILD_PAIR_EMPTY_OBJECT(name) JSON_BUILD_PAIR(name, JSON_BUILD_EMPTY_OBJECT) | |
344 | #define JSON_BUILD_PAIR_NULL(name) JSON_BUILD_PAIR(name, JSON_BUILD_NULL) | |
345 | #define JSON_BUILD_PAIR_VARIANT(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_VARIANT(v)) | |
346 | #define JSON_BUILD_PAIR_VARIANT_ARRAY(name, v, n) JSON_BUILD_PAIR(name, JSON_BUILD_VARIANT_ARRAY(v, n)) | |
347 | #define JSON_BUILD_PAIR_LITERAL(name, l) JSON_BUILD_PAIR(name, JSON_BUILD_LITERAL(l)) | |
348 | #define JSON_BUILD_PAIR_STRV(name, l) JSON_BUILD_PAIR(name, JSON_BUILD_STRV(l)) | |
349 | #define JSON_BUILD_PAIR_BASE64(name, p, n) JSON_BUILD_PAIR(name, JSON_BUILD_BASE64(p, n)) | |
03427720 | 350 | #define JSON_BUILD_PAIR_IOVEC_BASE64(name, iov) JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_BASE64(iov)) |
7314084a | 351 | #define JSON_BUILD_PAIR_HEX(name, p, n) JSON_BUILD_PAIR(name, JSON_BUILD_HEX(p, n)) |
b22f0a50 | 352 | #define JSON_BUILD_PAIR_IOVEC_HEX(name, iov) JSON_BUILD_PAIR(name, JSON_BUILD_IOVEC_HEX(iov)) |
7314084a | 353 | #define JSON_BUILD_PAIR_ID128(name, id) JSON_BUILD_PAIR(name, JSON_BUILD_ID128(id)) |
9bc4156c | 354 | #define JSON_BUILD_PAIR_UUID(name, id) JSON_BUILD_PAIR(name, JSON_BUILD_UUID(id)) |
7314084a YW |
355 | #define JSON_BUILD_PAIR_BYTE_ARRAY(name, v, n) JSON_BUILD_PAIR(name, JSON_BUILD_BYTE_ARRAY(v, n)) |
356 | #define JSON_BUILD_PAIR_IN4_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_IN4_ADDR(v)) | |
357 | #define JSON_BUILD_PAIR_IN6_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_IN6_ADDR(v)) | |
358 | #define JSON_BUILD_PAIR_IN_ADDR(name, v, f) JSON_BUILD_PAIR(name, JSON_BUILD_IN_ADDR(v, f)) | |
359 | #define JSON_BUILD_PAIR_ETHER_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_ETHER_ADDR(v)) | |
360 | #define JSON_BUILD_PAIR_HW_ADDR(name, v) JSON_BUILD_PAIR(name, JSON_BUILD_HW_ADDR(v)) | |
a636a058 | 361 | #define JSON_BUILD_PAIR_STRING_SET(name, s) JSON_BUILD_PAIR(name, JSON_BUILD_STRING_SET(s)) |
8eb735b8 | 362 | #define JSON_BUILD_PAIR_CALLBACK(name, c, u) JSON_BUILD_PAIR(name, JSON_BUILD_CALLBACK(c, u)) |
7314084a YW |
363 | |
364 | #define JSON_BUILD_PAIR_UNSIGNED_NON_ZERO(name, u) _JSON_BUILD_PAIR_UNSIGNED_NON_ZERO, (const char*) { name }, (uint64_t) { u } | |
365 | #define JSON_BUILD_PAIR_FINITE_USEC(name, u) _JSON_BUILD_PAIR_FINITE_USEC, (const char*) { name }, (usec_t) { u } | |
366 | #define JSON_BUILD_PAIR_STRING_NON_EMPTY(name, s) _JSON_BUILD_PAIR_STRING_NON_EMPTY, (const char*) { name }, (const char*) { s } | |
367 | #define JSON_BUILD_PAIR_STRV_NON_EMPTY(name, l) _JSON_BUILD_PAIR_STRV_NON_EMPTY, (const char*) { name }, (char**) { l } | |
368 | #define JSON_BUILD_PAIR_VARIANT_NON_NULL(name, v) _JSON_BUILD_PAIR_VARIANT_NON_NULL, (const char*) { name }, (JsonVariant*) { v } | |
369 | #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 } | |
370 | #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 } | |
371 | #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 } | |
372 | #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 } | |
373 | #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 |
374 | |
375 | int json_build(JsonVariant **ret, ...); | |
376 | int json_buildv(JsonVariant **ret, va_list ap); | |
377 | ||
378 | /* A bitmask of flags used by the dispatch logic. Note that this is a combined bit mask, that is generated from the bit | |
379 | * mask originally passed into json_dispatch(), the individual bitmask associated with the static JsonDispatch callout | |
380 | * entry, as well the bitmask specified for json_log() calls */ | |
381 | typedef enum JsonDispatchFlags { | |
382 | /* The following three may be set in JsonDispatch's .flags field or the json_dispatch() flags parameter */ | |
a617fd90 LP |
383 | JSON_PERMISSIVE = 1 << 0, /* Shall parsing errors be considered fatal for this field or object? */ |
384 | JSON_MANDATORY = 1 << 1, /* Should existence of this property be mandatory? */ | |
385 | JSON_LOG = 1 << 2, /* Should the parser log about errors? */ | |
386 | JSON_SAFE = 1 << 3, /* Don't accept "unsafe" strings in json_dispatch_string() + json_dispatch_string() */ | |
387 | JSON_RELAX = 1 << 4, /* Use relaxed user name checking in json_dispatch_user_group_name */ | |
388 | JSON_ALLOW_EXTENSIONS = 1 << 5, /* Subset of JSON_PERMISSIVE: allow additional fields, but no other permissive handling */ | |
cd0b6c53 | 389 | |
680f2fb3 | 390 | /* The following two may be passed into log_json() in addition to those above */ |
a617fd90 LP |
391 | JSON_DEBUG = 1 << 6, /* Indicates that this log message is a debug message */ |
392 | JSON_WARNING = 1 << 7, /* Indicates that this log message is a warning message */ | |
cd0b6c53 LP |
393 | } JsonDispatchFlags; |
394 | ||
395 | typedef int (*JsonDispatchCallback)(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
396 | ||
397 | typedef struct JsonDispatch { | |
398 | const char *name; | |
399 | JsonVariantType type; | |
400 | JsonDispatchCallback callback; | |
401 | size_t offset; | |
402 | JsonDispatchFlags flags; | |
403 | } JsonDispatch; | |
404 | ||
f1b622a0 LP |
405 | int json_dispatch_full(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata, const char **reterr_bad_field); |
406 | ||
407 | static inline int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchFlags flags, void *userdata) { | |
408 | return json_dispatch_full(v, table, NULL, flags, userdata, NULL); | |
409 | } | |
cd0b6c53 LP |
410 | |
411 | int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
19a209cc | 412 | int json_dispatch_const_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
cd0b6c53 LP |
413 | int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
414 | int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
415 | int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
416 | int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
6b9f63cb | 417 | int json_dispatch_variant_noref(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
718ca772 ZJS |
418 | int json_dispatch_int64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
419 | int json_dispatch_uint64(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
cd0b6c53 LP |
420 | int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
421 | int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
e085625f LP |
422 | int json_dispatch_uint16(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
423 | int json_dispatch_int16(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
6b67cf80 YW |
424 | int json_dispatch_int8(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
425 | int json_dispatch_uint8(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
a42ef715 LP |
426 | int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
427 | int json_dispatch_user_group_name(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
8fcf504b | 428 | int json_dispatch_absolute_path(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
a42ef715 LP |
429 | int json_dispatch_id128(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
430 | int json_dispatch_unsupported(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
03427720 | 431 | int json_dispatch_unbase64_iovec(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
72278e62 YW |
432 | int json_dispatch_byte_array_iovec(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
433 | int json_dispatch_in_addr(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
cd0b6c53 | 434 | |
b97e3e3d LP |
435 | assert_cc(sizeof(uint32_t) == sizeof(unsigned)); |
436 | #define json_dispatch_uint json_dispatch_uint32 | |
437 | ||
438 | assert_cc(sizeof(int32_t) == sizeof(int)); | |
439 | #define json_dispatch_int json_dispatch_int32 | |
440 | ||
dda66296 LP |
441 | #define JSON_DISPATCH_ENUM_DEFINE(name, type, func) \ |
442 | int name(const char *n, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) { \ | |
443 | type *c = ASSERT_PTR(userdata); \ | |
444 | \ | |
445 | assert(variant); \ | |
446 | \ | |
447 | if (json_variant_is_null(variant)) { \ | |
448 | *c = (type) -EINVAL; \ | |
449 | return 0; \ | |
450 | } \ | |
451 | \ | |
452 | if (!json_variant_is_string(variant)) \ | |
453 | return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(n)); \ | |
454 | \ | |
455 | type cc = func(json_variant_string(variant)); \ | |
456 | if (cc < 0) \ | |
457 | return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "Value of JSON field '%s' not recognized.", strna(n)); \ | |
458 | \ | |
459 | *c = cc; \ | |
460 | return 0; \ | |
461 | } | |
462 | ||
cd0b6c53 LP |
463 | static inline int json_dispatch_level(JsonDispatchFlags flags) { |
464 | ||
465 | /* Did the user request no logging? If so, then never log higher than LOG_DEBUG. Also, if this is marked as | |
466 | * debug message, then also log at debug level. */ | |
467 | ||
468 | if (!(flags & JSON_LOG) || | |
469 | (flags & JSON_DEBUG)) | |
470 | return LOG_DEBUG; | |
471 | ||
472 | /* Are we invoked in permissive mode, or is this explicitly marked as warning message? Then this should be | |
473 | * printed at LOG_WARNING */ | |
474 | if (flags & (JSON_PERMISSIVE|JSON_WARNING)) | |
475 | return LOG_WARNING; | |
476 | ||
477 | /* Otherwise it's an error. */ | |
478 | return LOG_ERR; | |
479 | } | |
480 | ||
481 | int json_log_internal(JsonVariant *variant, int level, int error, const char *file, int line, const char *func, const char *format, ...) _printf_(7, 8); | |
482 | ||
19130626 | 483 | #define json_log(variant, flags, error, ...) \ |
cd0b6c53 | 484 | ({ \ |
19130626 | 485 | int _level = json_dispatch_level(flags), _e = (error); \ |
cd0b6c53 | 486 | (log_get_max_level() >= LOG_PRI(_level)) \ |
62c6bbbc | 487 | ? json_log_internal(variant, _level, _e, PROJECT_FILE, __LINE__, __func__, __VA_ARGS__) \ |
19130626 | 488 | : -ERRNO_VALUE(_e); \ |
cd0b6c53 LP |
489 | }) |
490 | ||
0ac0787e LP |
491 | #define json_log_oom(variant, flags) \ |
492 | json_log(variant, flags, SYNTHETIC_ERRNO(ENOMEM), "Out of memory.") | |
493 | ||
d520d519 LP |
494 | #define JSON_VARIANT_STRING_CONST(x) _JSON_VARIANT_STRING_CONST(UNIQ, (x)) |
495 | ||
90b365ce | 496 | #define _JSON_VARIANT_STRING_CONST(xq, x) \ |
d520d519 | 497 | ({ \ |
90b365ce | 498 | _align_(2) static const char UNIQ_T(json_string_const, xq)[] = (x); \ |
d520d519 LP |
499 | assert((((uintptr_t) UNIQ_T(json_string_const, xq)) & 1) == 0); \ |
500 | (JsonVariant*) ((uintptr_t) UNIQ_T(json_string_const, xq) + 1); \ | |
501 | }) | |
502 | ||
faca141c | 503 | int json_variant_unbase64(JsonVariant *v, void **ret, size_t *ret_size); |
2d64d2b9 | 504 | int json_variant_unhex(JsonVariant *v, void **ret, size_t *ret_size); |
faca141c | 505 | |
b22f0a50 LP |
506 | static inline int json_variant_unbase64_iovec(JsonVariant *v, struct iovec *ret) { |
507 | return json_variant_unbase64(v, ret ? &ret->iov_base : NULL, ret ? &ret->iov_len : NULL); | |
508 | } | |
509 | ||
510 | static inline int json_variant_unhex_iovec(JsonVariant *v, struct iovec *ret) { | |
511 | return json_variant_unhex(v, ret ? &ret->iov_base : NULL, ret ? &ret->iov_len : NULL); | |
512 | } | |
513 | ||
cd0b6c53 LP |
514 | const char *json_variant_type_to_string(JsonVariantType t); |
515 | JsonVariantType json_variant_type_from_string(const char *s); |