]>
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 | ||
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 | ||
43 | typedef struct JsonVariant JsonVariant; | |
44 | ||
45 | typedef 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 | ||
59 | int json_variant_new_stringn(JsonVariant **ret, const char *s, size_t n); | |
cc164891 | 60 | int json_variant_new_base64(JsonVariant **ret, const void *p, size_t n); |
cd0b6c53 LP |
61 | int json_variant_new_integer(JsonVariant **ret, intmax_t i); |
62 | int json_variant_new_unsigned(JsonVariant **ret, uintmax_t u); | |
63 | int json_variant_new_real(JsonVariant **ret, long double d); | |
64 | int json_variant_new_boolean(JsonVariant **ret, bool b); | |
65 | int json_variant_new_array(JsonVariant **ret, JsonVariant **array, size_t n); | |
66 | int json_variant_new_array_bytes(JsonVariant **ret, const void *p, size_t n); | |
67 | int json_variant_new_array_strv(JsonVariant **ret, char **l); | |
68 | int json_variant_new_object(JsonVariant **ret, JsonVariant **array, size_t n); | |
69 | int json_variant_new_null(JsonVariant **ret); | |
0b9481cf | 70 | int json_variant_new_id128(JsonVariant **ret, sd_id128_t id); |
cd0b6c53 LP |
71 | |
72 | static 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 | ||
76 | JsonVariant *json_variant_ref(JsonVariant *v); | |
77 | JsonVariant *json_variant_unref(JsonVariant *v); | |
78 | void json_variant_unref_many(JsonVariant **array, size_t n); | |
79 | ||
80 | DEFINE_TRIVIAL_CLEANUP_FUNC(JsonVariant *, json_variant_unref); | |
81 | ||
82 | const char *json_variant_string(JsonVariant *v); | |
83 | intmax_t json_variant_integer(JsonVariant *v); | |
84 | uintmax_t json_variant_unsigned(JsonVariant *v); | |
85 | long double json_variant_real(JsonVariant *v); | |
86 | bool json_variant_boolean(JsonVariant *v); | |
87 | ||
88 | JsonVariantType json_variant_type(JsonVariant *v); | |
89 | bool json_variant_has_type(JsonVariant *v, JsonVariantType type); | |
90 | ||
91 | static inline bool json_variant_is_string(JsonVariant *v) { | |
92 | return json_variant_has_type(v, JSON_VARIANT_STRING); | |
93 | } | |
94 | ||
95 | static inline bool json_variant_is_integer(JsonVariant *v) { | |
96 | return json_variant_has_type(v, JSON_VARIANT_INTEGER); | |
97 | } | |
98 | ||
99 | static inline bool json_variant_is_unsigned(JsonVariant *v) { | |
100 | return json_variant_has_type(v, JSON_VARIANT_UNSIGNED); | |
101 | } | |
102 | ||
103 | static inline bool json_variant_is_real(JsonVariant *v) { | |
104 | return json_variant_has_type(v, JSON_VARIANT_REAL); | |
105 | } | |
106 | ||
107 | static inline bool json_variant_is_number(JsonVariant *v) { | |
108 | return json_variant_has_type(v, JSON_VARIANT_NUMBER); | |
109 | } | |
110 | ||
111 | static inline bool json_variant_is_boolean(JsonVariant *v) { | |
112 | return json_variant_has_type(v, JSON_VARIANT_BOOLEAN); | |
113 | } | |
114 | ||
115 | static inline bool json_variant_is_array(JsonVariant *v) { | |
116 | return json_variant_has_type(v, JSON_VARIANT_ARRAY); | |
117 | } | |
118 | ||
119 | static inline bool json_variant_is_object(JsonVariant *v) { | |
120 | return json_variant_has_type(v, JSON_VARIANT_OBJECT); | |
121 | } | |
122 | ||
123 | static inline bool json_variant_is_null(JsonVariant *v) { | |
124 | return json_variant_has_type(v, JSON_VARIANT_NULL); | |
125 | } | |
126 | ||
127 | bool json_variant_is_negative(JsonVariant *v); | |
e787b211 LP |
128 | bool json_variant_is_blank_object(JsonVariant *v); |
129 | bool json_variant_is_blank_array(JsonVariant *v); | |
b7fc90a2 LP |
130 | bool json_variant_is_normalized(JsonVariant *v); |
131 | bool json_variant_is_sorted(JsonVariant *v); | |
cd0b6c53 LP |
132 | |
133 | size_t json_variant_elements(JsonVariant *v); | |
134 | JsonVariant *json_variant_by_index(JsonVariant *v, size_t index); | |
135 | JsonVariant *json_variant_by_key(JsonVariant *v, const char *key); | |
136 | JsonVariant *json_variant_by_key_full(JsonVariant *v, const char *key, JsonVariant **ret_key); | |
137 | ||
138 | bool json_variant_equal(JsonVariant *a, JsonVariant *b); | |
139 | ||
83bc6cb7 | 140 | void json_variant_sensitive(JsonVariant *v); |
94600eeb | 141 | bool json_variant_is_sensitive(JsonVariant *v); |
83bc6cb7 | 142 | |
cd0b6c53 LP |
143 | struct 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 | ||
165 | int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column); | |
166 | ||
897f099b | 167 | typedef 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 |
179 | int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret); |
180 | void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix); | |
cd0b6c53 | 181 | |
f2ff34ff LP |
182 | int json_variant_filter(JsonVariant **v, char **to_remove); |
183 | ||
78a41236 | 184 | int json_variant_set_field(JsonVariant **v, const char *field, JsonVariant *value); |
15f1fb3e | 185 | int json_variant_set_field_string(JsonVariant **v, const char *field, const char *value); |
a832b08e | 186 | int json_variant_set_field_integer(JsonVariant **v, const char *field, intmax_t value); |
15f1fb3e | 187 | int json_variant_set_field_unsigned(JsonVariant **v, const char *field, uintmax_t value); |
a832b08e | 188 | int json_variant_set_field_boolean(JsonVariant **v, const char *field, bool b); |
0b9481cf | 189 | int json_variant_set_field_strv(JsonVariant **v, const char *field, char **l); |
78a41236 | 190 | |
21e21511 LP |
191 | int json_variant_append_array(JsonVariant **v, JsonVariant *element); |
192 | ||
ca409a59 LP |
193 | int json_variant_merge(JsonVariant **v, JsonVariant *m); |
194 | ||
22f14d6b LP |
195 | int json_variant_strv(JsonVariant *v, char ***ret); |
196 | ||
b7fc90a2 LP |
197 | int json_variant_sort(JsonVariant **v); |
198 | int json_variant_normalize(JsonVariant **v); | |
199 | ||
d642f640 LP |
200 | typedef 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 |
204 | int json_parse(const char *string, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column); |
205 | int json_parse_continue(const char **p, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column); | |
206 | int json_parse_file_at(FILE *f, int dir_fd, const char *path, JsonParseFlags flags, JsonVariant **ret, unsigned *ret_line, unsigned *ret_column); | |
207 | ||
208 | static 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 | |
212 | enum { | |
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 | |
255 | int json_build(JsonVariant **ret, ...); | |
256 | int 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 */ | |
261 | typedef 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 | ||
274 | typedef int (*JsonDispatchCallback)(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
275 | ||
276 | typedef struct JsonDispatch { | |
277 | const char *name; | |
278 | JsonVariantType type; | |
279 | JsonDispatchCallback callback; | |
280 | size_t offset; | |
281 | JsonDispatchFlags flags; | |
282 | } JsonDispatch; | |
283 | ||
284 | int json_dispatch(JsonVariant *v, const JsonDispatch table[], JsonDispatchCallback bad, JsonDispatchFlags flags, void *userdata); | |
285 | ||
286 | int json_dispatch_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
19a209cc | 287 | int json_dispatch_const_string(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
cd0b6c53 LP |
288 | int json_dispatch_strv(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
289 | int json_dispatch_boolean(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
290 | int json_dispatch_tristate(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
291 | int json_dispatch_variant(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
292 | int json_dispatch_integer(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
293 | int json_dispatch_unsigned(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
294 | int json_dispatch_uint32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
295 | int json_dispatch_int32(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
a42ef715 LP |
296 | int json_dispatch_uid_gid(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); |
297 | int json_dispatch_user_group_name(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
298 | int json_dispatch_id128(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
299 | int json_dispatch_unsupported(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata); | |
cd0b6c53 | 300 | |
ab1a1ba5 | 301 | assert_cc(sizeof(uintmax_t) == sizeof(uint64_t)); |
cd0b6c53 LP |
302 | #define json_dispatch_uint64 json_dispatch_unsigned |
303 | ||
ab1a1ba5 | 304 | assert_cc(sizeof(intmax_t) == sizeof(int64_t)); |
cd0b6c53 LP |
305 | #define json_dispatch_int64 json_dispatch_integer |
306 | ||
b97e3e3d LP |
307 | assert_cc(sizeof(uint32_t) == sizeof(unsigned)); |
308 | #define json_dispatch_uint json_dispatch_uint32 | |
309 | ||
310 | assert_cc(sizeof(int32_t) == sizeof(int)); | |
311 | #define json_dispatch_int json_dispatch_int32 | |
312 | ||
cd0b6c53 LP |
313 | static 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 | ||
331 | int 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 |
353 | int json_variant_unbase64(JsonVariant *v, void **ret, size_t *ret_size); |
354 | ||
cd0b6c53 LP |
355 | const char *json_variant_type_to_string(JsonVariantType t); |
356 | JsonVariantType json_variant_type_from_string(const char *s); |