PipeWire 1.7.0
Loading...
Searching...
No Matches
json-builder.h
Go to the documentation of this file.
1/* Simple Plugin API */
2/* SPDX-FileCopyrightText: Copyright © 2026 Wim Taymans */
3/* SPDX-License-Identifier: MIT */
4
5#ifndef SPA_UTILS_JSON_BUILDER_H
6#define SPA_UTILS_JSON_BUILDER_H
7
8#include <stddef.h>
9#include <stdlib.h>
10#include <stdint.h>
11#include <string.h>
12#include <math.h>
13#include <float.h>
14#include <inttypes.h>
15#include <limits.h>
16
17#include <spa/utils/defs.h>
18#include <spa/utils/ansi.h>
19#include <spa/utils/json.h>
20
21#ifdef __cplusplus
22extern "C" {
23#else
24#include <stdbool.h>
25#endif
26
27#ifndef SPA_API_JSON_BUILDER
28 #ifdef SPA_API_IMPL
29 #define SPA_API_JSON_BUILDER SPA_API_IMPL
30 #else
31 #define SPA_API_JSON_BUILDER static inline
32 #endif
33#endif
34
43
44struct spa_json_builder {
45 FILE *f;
46#define SPA_JSON_BUILDER_FLAG_CLOSE (1<<0)
47#define SPA_JSON_BUILDER_FLAG_INDENT (1<<1)
48#define SPA_JSON_BUILDER_FLAG_SPACE (1<<2)
49#define SPA_JSON_BUILDER_FLAG_PRETTY (SPA_JSON_BUILDER_FLAG_INDENT|SPA_JSON_BUILDER_FLAG_SPACE)
50#define SPA_JSON_BUILDER_FLAG_COLOR (1<<3)
51#define SPA_JSON_BUILDER_FLAG_SIMPLE (1<<4)
52#define SPA_JSON_BUILDER_FLAG_RAW (1<<5)
53 uint32_t flags;
54 uint32_t indent_off;
55 uint32_t level;
56 uint32_t indent;
57 uint32_t count;
58 const char *delim;
59 const char *comma;
60 const char *key_sep;
61#define SPA_JSON_BUILDER_COLOR_NORMAL 0
62#define SPA_JSON_BUILDER_COLOR_KEY 1
63#define SPA_JSON_BUILDER_COLOR_LITERAL 2
64#define SPA_JSON_BUILDER_COLOR_NUMBER 3
65#define SPA_JSON_BUILDER_COLOR_STRING 4
66#define SPA_JSON_BUILDER_COLOR_CONTAINER 5
67 const char *color[8];
68};
75 spa_zero(*b);
76 b->f = f;
77 b->flags = flags;
78 b->indent = 2;
79 b->delim = "";
80 b->comma = simple ? space ? "" : " " : ",";
81 b->key_sep = simple ? space ? " =" : "=" : ":";
82 b->color[0] = (color ? SPA_ANSI_RESET : "");
83 b->color[1] = (color ? SPA_ANSI_BRIGHT_BLUE : "");
84 b->color[2] = (color ? SPA_ANSI_BRIGHT_MAGENTA : "");
85 b->color[3] = (color ? SPA_ANSI_BRIGHT_CYAN : "");
86 b->color[4] = (color ? SPA_ANSI_BRIGHT_GREEN : "");
88 return 0;
89}
92 char **mem, size_t *size, uint32_t flags)
93{
94 FILE *f;
95 spa_zero(*b);
96 if ((f = open_memstream(mem, size)) == NULL)
97 return -errno;
99}
100
102 char *mem, size_t size, uint32_t flags)
103{
104 FILE *f;
105 spa_zero(*b);
106 if ((f = fmemopen(mem, size, "w")) == NULL)
107 return -errno;
109}
110
112{
114 fclose(b->f);
115}
116
118 bool raw, const char *before, const char *val, int size, const char *after)
119{
120 FILE *f = b->f;
121 int i, len;
122 if (raw) {
123 len = fprintf(f, "%s%.*s%s", before, size, val, after) - 1;
124 } else {
125 len = fprintf(f, "%s\"", before);
126 for (i = 0; i < size && val[i]; i++) {
127 char v = val[i];
128 switch (v) {
129 case '\n': len += fprintf(f, "\\n"); break;
130 case '\r': len += fprintf(f, "\\r"); break;
131 case '\b': len += fprintf(f, "\\b"); break;
132 case '\t': len += fprintf(f, "\\t"); break;
133 case '\f': len += fprintf(f, "\\f"); break;
134 case '\\':
135 case '"': len += fprintf(f, "\\%c", v); break;
136 default:
137 if (v > 0 && v < 0x20)
138 len += fprintf(f, "\\u%04x", v);
139 else
140 len += fprintf(f, "%c", v);
141 break;
142 }
143 }
144 len += fprintf(f, "\"%s", after);
145 }
146 return len-1;
147}
148
150void spa_json_builder_add_simple(struct spa_json_builder *b, const char *key, int key_len,
151 char type, const char *val, int val_len)
152{
153 bool indent = b->indent_off == 0 && (b->flags & SPA_JSON_BUILDER_FLAG_INDENT);
154 bool space = b->flags & SPA_JSON_BUILDER_FLAG_SPACE;
155 bool force_raw = b->flags & SPA_JSON_BUILDER_FLAG_RAW;
156 bool raw = true, simple = b->flags & SPA_JSON_BUILDER_FLAG_SIMPLE;
157 int color;
158
159 if (val == NULL || val_len == 0) {
160 val = "null";
161 val_len = 4;
162 type = 'l';
163 }
164 if (type == 0) {
165 if (spa_json_is_container(val, val_len))
166 type = simple ? 'C' : 'S';
167 else if (val_len > 0 && (*val == '}' || *val == ']'))
168 type = 'e';
169 else if (spa_json_is_null(val, val_len) ||
171 type = 'l';
172 else if (spa_json_is_string(val, val_len))
173 type = 's';
174 else if (spa_json_is_json_number(val, val_len))
175 type = 'd';
176 else if (simple && (spa_json_is_float(val, val_len) ||
177 spa_json_is_int(val, val_len)))
178 type = 'd';
179 else
180 type = 'S';
181 }
182 switch (type) {
183 case 'e':
184 b->level -= b->indent;
185 b->delim = "";
186 break;
187 }
188
189 fprintf(b->f, "%s%s%*s", b->delim, b->count == 0 ? "" : indent ? "\n" : space ? " " : "",
190 indent ? b->level : 0, "");
191 if (key) {
192 bool key_raw = force_raw || (simple && spa_json_make_simple_string(&key, &key_len)) ||
193 spa_json_is_string(key, key_len);
195 b->color[1], key, key_len, b->color[0]);
196 fprintf(b->f, "%s%s", b->key_sep, space ? " " : "");
197 }
198 b->delim = b->comma;
199 switch (type) {
200 case 'c':
202 val_len = 1;
203 b->delim = "";
204 b->level += b->indent;
205 if (val[1] == '-') b->indent_off++;
206 break;
207 case 'e':
209 val_len = 1;
210 if (val[1] == '-') b->indent_off--;
211 break;
212 case 'l':
214 break;
215 case 'd':
217 break;
218 case 's':
220 break;
221 case 'C':
223 break;
224 default:
226 raw = force_raw || (simple && spa_json_make_simple_string(&val, &val_len));
227 break;
228 }
229 spa_json_builder_encode_string(b, raw, b->color[color], val, val_len, b->color[0]);
230 b->count++;
231}
232
234 const char *key, const char *val)
235{
236 spa_json_builder_add_simple(b, key, INT_MAX, 'c', val, INT_MAX);
237}
239 const char *val)
240{
241 spa_json_builder_add_simple(b, NULL, 0, 'e', val, INT_MAX);
242}
244 const char *key)
245{
246 spa_json_builder_add_simple(b, key, INT_MAX, 'l', "null", 4);
247}
249 const char *key, bool val)
250{
251 spa_json_builder_add_simple(b, key, INT_MAX, 'l', val ? "true" : "false", INT_MAX);
252}
254 const char *key, int64_t val)
255{
256 char str[128];
257 snprintf(str, sizeof(str), "%" PRIi64, val);
258 spa_json_builder_add_simple(b, key, INT_MAX, 'd', str, INT_MAX);
259}
261 const char *key, uint64_t val)
262{
263 char str[128];
264 snprintf(str, sizeof(str), "%" PRIu64, val);
265 spa_json_builder_add_simple(b, key, INT_MAX, 'd', str, INT_MAX);
266}
268 const char *key, double val)
269{
270 char str[64];
271 spa_json_format_float(str, sizeof(str), (float)val);
272 spa_json_builder_add_simple(b, key, INT_MAX, 'd', str, INT_MAX);
275 const char *key, const char *val)
276{
277 spa_json_builder_add_simple(b, key, INT_MAX, 'S', val, INT_MAX);
278}
281 const char *key, const char *fmt, va_list va)
282{
283 char *val;
284 if (vasprintf(&val, fmt, va) > 0) {
286 free(val);
288}
289
291void spa_json_builder_object_stringf(struct spa_json_builder *b,
292 const char *key, const char *fmt, ...)
293{
294 va_list va;
295 va_start(va, fmt);
297 va_end(va);
298}
301 struct spa_json *it, const char *key, int key_len, const char *val, int len)
302{
303 struct spa_json sub;
305 spa_json_builder_add_simple(b, key, key_len, 'c', "[", 1);
306 spa_json_enter(it, &sub);
307 while ((len = spa_json_next(&sub, &val)) > 0)
308 spa_json_builder_object_value_iter(b, &sub, NULL, 0, val, len);
309 spa_json_builder_pop(b, "]");
311 else if (spa_json_is_object(val, len)) {
312 const char *k;
313 int kl;
314 spa_json_builder_add_simple(b, key, key_len, 'c', "{", 1);
315 spa_json_enter(it, &sub);
316 while ((kl = spa_json_next(&sub, &k)) > 0) {
317 if ((len = spa_json_next(&sub, &val)) < 0)
318 break;
319 spa_json_builder_object_value_iter(b, &sub, k, kl, val, len);
321 spa_json_builder_pop(b, "}");
322 }
323 else {
324 spa_json_builder_add_simple(b, key, key_len, 0, val, len);
325 }
326}
328 bool recurse, const char *key, int key_len, const char *val, int val_len)
329{
330 if (!recurse || val == NULL) {
331 spa_json_builder_add_simple(b, key, key_len, 0, val, val_len);
332 } else {
333 struct spa_json it[1];
334 const char *v;
335 if (spa_json_begin(&it[0], val, val_len, &v) >= 0)
336 spa_json_builder_object_value_iter(b, &it[0], key, key_len, val, val_len);
337 }
338}
340 bool recurse, const char *key, const char *val)
341{
343 val, val ? strlen(val) : 0);
344}
346void spa_json_builder_object_valuef(struct spa_json_builder *b,
347 bool recurse, const char *key, const char *fmt, ...)
348{
349 va_list va;
350 char *val;
351 va_start(va, fmt);
352 if (vasprintf(&val, fmt, va) > 0) {
354 free(val);
355 }
356 va_end(va);
357}
358
360/* array functions */
362 const char *val)
363{
369}
371 bool val)
372{
374}
376 int64_t val)
377{
379}
386 double val)
387{
389}
396void spa_json_builder_array_stringf(struct spa_json_builder *b,
397 const char *fmt, ...)
398{
399 va_list va;
405 bool recurse, const char *val)
406{
408}
410void spa_json_builder_array_valuef(struct spa_json_builder *b, bool recurse, const char *fmt, ...)
411{
412 va_list va;
413 char *val;
414 va_start(va, fmt);
415 if (vasprintf(&val, fmt, va) > 0) {
417 free(val);
418 }
419 va_end(va);
420}
422SPA_API_JSON_BUILDER char *spa_json_builder_reformat(const char *json, uint32_t flags)
423{
425 char *mem;
426 size_t size;
427 int res;
428 if ((res = spa_json_builder_memstream(&b, &mem, &size, flags)) < 0) {
429 errno = -res;
430 return NULL;
431 }
432 spa_json_builder_array_value(&b, true, json);
434 return mem;
435}
436
440
441#ifdef __cplusplus
442} /* extern "C" */
443#endif
444
445#endif /* SPA_UTILS_JSON_BUILDER_H */
spa/utils/ansi.h
spa/utils/defs.h
uint32_t int int res
Definition core.h:433
#define SPA_ANSI_BRIGHT_BLUE
Definition ansi.h:66
#define SPA_ANSI_BRIGHT_GREEN
Definition ansi.h:62
#define SPA_ANSI_BRIGHT_MAGENTA
Definition ansi.h:68
#define SPA_ANSI_RESET
Ansi escape sequences.
Definition ansi.h:33
#define SPA_ANSI_BRIGHT_CYAN
Definition ansi.h:70
#define SPA_ANSI_BRIGHT_YELLOW
Definition ansi.h:64
SPA_API_JSON_BUILDER void spa_json_builder_object_null(struct spa_json_builder *b, const char *key)
Definition json-builder.h:263
SPA_API_JSON_BUILDER int spa_json_builder_file(struct spa_json_builder *b, FILE *f, uint32_t flags)
Definition json-builder.h:90
SPA_API_JSON_BUILDER void spa_json_builder_object_bool(struct spa_json_builder *b, const char *key, bool val)
Definition json-builder.h:268
SPA_API_JSON_BUILDER void spa_json_builder_array_null(struct spa_json_builder *b)
Definition json-builder.h:386
#define SPA_JSON_BUILDER_FLAG_CLOSE
Definition json-builder.h:54
SPA_API_JSON_BUILDER void spa_json_builder_object_value(struct spa_json_builder *b, bool recurse, const char *key, const char *val)
Definition json-builder.h:359
#define SPA_JSON_BUILDER_COLOR_LITERAL
Definition json-builder.h:80
const char const char * fmt
Definition json-builder.h:301
SPA_API_JSON_BUILDER void spa_json_builder_array_int(struct spa_json_builder *b, int64_t val)
Definition json-builder.h:395
SPA_API_JSON_BUILDER int spa_json_builder_encode_string(struct spa_json_builder *b, bool raw, const char *before, const char *val, int size, const char *after)
Definition json-builder.h:137
SPA_API_JSON_BUILDER int spa_json_builder_memstream(struct spa_json_builder *b, char **mem, size_t *size, uint32_t flags)
Definition json-builder.h:111
SPA_API_JSON_BUILDER void spa_json_builder_array_push(struct spa_json_builder *b, const char *val)
Definition json-builder.h:381
bool const char const char char * val
Definition json-builder.h:370
va_end(va)
SPA_API_JSON_BUILDER void spa_json_builder_object_push(struct spa_json_builder *b, const char *key, const char *val)
Definition json-builder.h:253
SPA_API_JSON_BUILDER void spa_json_builder_array_value(struct spa_json_builder *b, bool recurse, const char *val)
Definition json-builder.h:424
SPA_API_JSON_BUILDER void spa_json_builder_object_value_full(struct spa_json_builder *b, bool recurse, const char *key, int key_len, const char *val, int val_len)
Definition json-builder.h:347
SPA_API_JSON_BUILDER int spa_json_builder_membuf(struct spa_json_builder *b, char *mem, size_t size, uint32_t flags)
Definition json-builder.h:121
#define SPA_JSON_BUILDER_FLAG_COLOR
Definition json-builder.h:62
#define SPA_JSON_BUILDER_COLOR_CONTAINER
Definition json-builder.h:86
#define SPA_JSON_BUILDER_FLAG_SPACE
Definition json-builder.h:58
SPA_API_JSON_BUILDER char * spa_json_builder_reformat(const char *json, uint32_t flags)
Definition json-builder.h:442
SPA_API_JSON_BUILDER void spa_json_builder_object_uint(struct spa_json_builder *b, const char *key, uint64_t val)
Definition json-builder.h:280
#define SPA_JSON_BUILDER_FLAG_INDENT
Definition json-builder.h:56
SPA_API_JSON_BUILDER void spa_json_builder_array_string(struct spa_json_builder *b, const char *val)
Definition json-builder.h:410
SPA_API_JSON_BUILDER void spa_json_builder_array_double(struct spa_json_builder *b, double val)
Definition json-builder.h:405
SPA_API_JSON_BUILDER void spa_json_builder_close(struct spa_json_builder *b)
Definition json-builder.h:131
#define SPA_JSON_BUILDER_COLOR_STRING
Definition json-builder.h:84
SPA_API_JSON_BUILDER void spa_json_builder_add_simple(struct spa_json_builder *b, const char *key, int key_len, char type, const char *val, int val_len)
Definition json-builder.h:170
const char const char va_start(va, fmt)
#define SPA_JSON_BUILDER_COLOR_NUMBER
Definition json-builder.h:82
SPA_API_JSON_BUILDER void spa_json_builder_object_value_iter(struct spa_json_builder *b, struct spa_json *it, const char *key, int key_len, const char *val, int len)
Definition json-builder.h:320
#define SPA_JSON_BUILDER_FLAG_RAW
Definition json-builder.h:66
#define SPA_JSON_BUILDER_COLOR_NORMAL
Definition json-builder.h:76
SPA_API_JSON_BUILDER void spa_json_builder_array_uint(struct spa_json_builder *b, uint64_t val)
Definition json-builder.h:400
spa_json_builder_object_stringv(b, key, fmt, va)
const char * key
Definition json-builder.h:301
SPA_API_JSON_BUILDER void spa_json_builder_object_int(struct spa_json_builder *b, const char *key, int64_t val)
Definition json-builder.h:273
SPA_API_JSON_BUILDER void spa_json_builder_object_string(struct spa_json_builder *b, const char *key, const char *val)
Definition json-builder.h:294
bool recurse
Definition json-builder.h:367
SPA_API_JSON_BUILDER void spa_json_builder_array_bool(struct spa_json_builder *b, bool val)
Definition json-builder.h:390
#define SPA_JSON_BUILDER_FLAG_SIMPLE
Definition json-builder.h:64
const char const char va_list va
Definition json-builder.h:302
SPA_API_JSON_BUILDER void spa_json_builder_object_double(struct spa_json_builder *b, const char *key, double val)
Definition json-builder.h:287
SPA_API_JSON_BUILDER void spa_json_builder_pop(struct spa_json_builder *b, const char *val)
Definition json-builder.h:258
SPA_API_JSON_UTILS int spa_json_begin(struct spa_json *iter, const char *data, size_t size, const char **val)
Definition json.h:47
SPA_API_JSON bool spa_json_is_string(const char *val, int len)
Definition json-core.h:548
SPA_API_JSON int spa_json_next(struct spa_json *iter, const char **value)
Get the next token.
Definition json-core.h:101
SPA_API_JSON int spa_json_is_object(const char *val, int len)
Definition json-core.h:420
SPA_API_JSON char * spa_json_format_float(char *str, int size, float val)
Definition json-core.h:458
SPA_API_JSON bool spa_json_is_null(const char *val, int len)
Definition json-core.h:432
SPA_API_JSON bool spa_json_is_bool(const char *val, int len)
Definition json-core.h:533
SPA_API_JSON bool spa_json_is_int(const char *val, int len)
Definition json-core.h:483
SPA_API_JSON bool spa_json_make_simple_string(const char **val, int *len)
Definition json-core.h:562
SPA_API_JSON bool spa_json_is_json_number(const char *val, int len)
Definition json-core.h:489
SPA_API_JSON void spa_json_enter(struct spa_json *iter, struct spa_json *sub)
Definition json-core.h:78
SPA_API_JSON bool spa_json_is_array(const char *val, int len)
Definition json-core.h:426
SPA_API_JSON bool spa_json_is_float(const char *val, int len)
Definition json-core.h:452
SPA_API_JSON int spa_json_is_container(const char *val, int len)
Definition json-core.h:410
#define spa_zero(x)
Definition defs.h:512
#define SPA_PRINTF_FUNC(fmt, arg1)
Definition defs.h:297
#define SPA_API_JSON_BUILDER
Definition json-builder.h:38
spa/utils/json.h
spa/utils/string.h
Definition json-builder.h:51
uint32_t indent
Definition json-builder.h:70
const char * comma
Definition json-builder.h:73
FILE * f
Definition json-builder.h:52
uint32_t count
Definition json-builder.h:71
const char * color[8]
Definition json-builder.h:87
const char * key_sep
Definition json-builder.h:74
const char * delim
Definition json-builder.h:72
uint32_t flags
Definition json-builder.h:67
uint32_t indent_off
Definition json-builder.h:68
uint32_t level
Definition json-builder.h:69
Definition json-core.h:49