PipeWire 1.5.84
Loading...
Searching...
No Matches
json-core.h
Go to the documentation of this file.
1/* Simple Plugin API */
2/* SPDX-FileCopyrightText: Copyright © 2020 Wim Taymans */
3/* SPDX-License-Identifier: MIT */
4
5#ifndef SPA_UTILS_JSON_H
6#define SPA_UTILS_JSON_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
15#include <spa/utils/defs.h>
16#include <spa/utils/string.h>
17
18#ifdef __cplusplus
19extern "C" {
20#else
21#include <stdbool.h>
22#endif
23
24#ifndef SPA_API_JSON
25 #ifdef SPA_API_IMPL
26 #define SPA_API_JSON SPA_API_IMPL
27 #else
28 #define SPA_API_JSON static inline
29 #endif
30#endif
31
40
41/* a simple JSON compatible tokenizer */
42struct spa_json {
43 const char *cur;
44 const char *end;
45 struct spa_json *parent;
46#define SPA_JSON_ERROR_FLAG 0x100
47 uint32_t state;
48 uint32_t depth;
49};
51#define SPA_JSON_INIT(data,size) ((struct spa_json) { (data), (data)+(size), NULL, 0, 0 })
53SPA_API_JSON void spa_json_init(struct spa_json * iter, const char *data, size_t size)
55 *iter = SPA_JSON_INIT(data, size);
57
58#define SPA_JSON_INIT_RELAX(type,data,size) \
59 ((struct spa_json) { (data), (data)+(size), NULL, (uint32_t)((type) == '[' ? 0x10 : 0x0), 0 })
61SPA_API_JSON void spa_json_init_relax(struct spa_json * iter, char type, const char *data, size_t size)
63 *iter = SPA_JSON_INIT_RELAX(type, data, size);
64}
65
66#define SPA_JSON_ENTER(iter) ((struct spa_json) { (iter)->cur, (iter)->end, (iter), (iter)->state & 0xff0, 0 })
68SPA_API_JSON void spa_json_enter(struct spa_json * iter, struct spa_json * sub)
69{
70 *sub = SPA_JSON_ENTER(iter);
71}
72
73#define SPA_JSON_SAVE(iter) ((struct spa_json) { (iter)->cur, (iter)->end, NULL, (iter)->state, 0 })
74
75SPA_API_JSON void spa_json_save(struct spa_json * iter, struct spa_json * save)
77 *save = SPA_JSON_SAVE(iter);
79
80#define SPA_JSON_START(iter,p) ((struct spa_json) { (p), (iter)->end, NULL, 0, 0 })
81
82SPA_API_JSON void spa_json_start(struct spa_json * iter, struct spa_json * sub, const char *pos)
83{
84 *sub = SPA_JSON_START(iter,pos);
85}
89SPA_API_JSON int spa_json_next(struct spa_json * iter, const char **value)
90{
91 int utf8_remain = 0, err = 0;
92 enum {
93 __NONE, __STRUCT, __BARE, __STRING, __UTF8, __ESC, __COMMENT,
94 __ARRAY_FLAG = 0x10, /* in array context */
95 __PREV_ARRAY_FLAG = 0x20, /* depth=0 array context flag */
96 __KEY_FLAG = 0x40, /* inside object key */
97 __SUB_FLAG = 0x80, /* not at top-level */
98 __FLAGS = 0xff0,
99 __ERROR_SYSTEM = SPA_JSON_ERROR_FLAG,
100 __ERROR_INVALID_ARRAY_SEPARATOR,
101 __ERROR_EXPECTED_OBJECT_KEY,
102 __ERROR_EXPECTED_OBJECT_VALUE,
103 __ERROR_TOO_DEEP_NESTING,
104 __ERROR_EXPECTED_ARRAY_CLOSE,
105 __ERROR_EXPECTED_OBJECT_CLOSE,
106 __ERROR_MISMATCHED_BRACKET,
107 __ERROR_ESCAPE_NOT_ALLOWED,
108 __ERROR_CHARACTERS_NOT_ALLOWED,
109 __ERROR_INVALID_ESCAPE,
110 __ERROR_INVALID_STATE,
111 __ERROR_UNFINISHED_STRING,
112 };
113 uint64_t array_stack[8] = {0}; /* array context flags of depths 1...512 */
114
115 *value = iter->cur;
116
117 if (iter->state & SPA_JSON_ERROR_FLAG)
118 return -1;
119
120 for (; iter->cur < iter->end; iter->cur++) {
121 unsigned char cur = (unsigned char)*iter->cur;
122 uint32_t flag;
123
124#define _SPA_ERROR(reason) { err = __ERROR_ ## reason; goto error; }
125 again:
126 flag = iter->state & __FLAGS;
127 switch (iter->state & ~__FLAGS) {
128 case __NONE:
129 flag &= ~(__KEY_FLAG | __PREV_ARRAY_FLAG);
130 iter->state = __STRUCT | flag;
131 iter->depth = 0;
132 goto again;
133 case __STRUCT:
134 switch (cur) {
135 case '\0': case '\t': case ' ': case '\r': case '\n': case ',':
136 continue;
137 case ':': case '=':
138 if (flag & __ARRAY_FLAG)
139 _SPA_ERROR(INVALID_ARRAY_SEPARATOR);
140 if (!(flag & __KEY_FLAG))
141 _SPA_ERROR(EXPECTED_OBJECT_KEY);
142 iter->state |= __SUB_FLAG;
143 continue;
144 case '#':
145 iter->state = __COMMENT | flag;
146 continue;
147 case '"':
148 if (flag & __KEY_FLAG)
149 flag |= __SUB_FLAG;
150 if (!(flag & __ARRAY_FLAG))
151 SPA_FLAG_UPDATE(flag, __KEY_FLAG, !(flag & __KEY_FLAG));
152 *value = iter->cur;
153 iter->state = __STRING | flag;
154 continue;
155 case '[': case '{':
156 if (!(flag & __ARRAY_FLAG)) {
157 /* At top-level we may be either in object context
158 * or in single-item context, and then we need to
159 * accept array/object here.
160 */
161 if ((iter->state & __SUB_FLAG) && !(flag & __KEY_FLAG))
162 _SPA_ERROR(EXPECTED_OBJECT_KEY);
163 SPA_FLAG_CLEAR(flag, __KEY_FLAG);
164 }
165 iter->state = __STRUCT | __SUB_FLAG | flag;
166 SPA_FLAG_UPDATE(iter->state, __ARRAY_FLAG, cur == '[');
167
168 /* We need to remember previous array state across calls
169 * for depth=0, so store that in state. Others bits go to
170 * temporary stack.
171 */
172 if (iter->depth == 0) {
173 SPA_FLAG_UPDATE(iter->state, __PREV_ARRAY_FLAG, flag & __ARRAY_FLAG);
174 } else if (((iter->depth-1) >> 6) < SPA_N_ELEMENTS(array_stack)) {
175 uint64_t mask = 1ULL << ((iter->depth-1) & 0x3f);
176 SPA_FLAG_UPDATE(array_stack[(iter->depth-1) >> 6], mask, flag & __ARRAY_FLAG);
177 } else {
178 /* too deep */
179 _SPA_ERROR(TOO_DEEP_NESTING);
180 }
181
182 *value = iter->cur;
183 if (++iter->depth > 1)
184 continue;
185 iter->cur++;
186 return 1;
187 case '}': case ']':
188 if ((flag & __ARRAY_FLAG) && cur != ']')
189 _SPA_ERROR(EXPECTED_ARRAY_CLOSE);
190 if (!(flag & __ARRAY_FLAG) && cur != '}')
191 _SPA_ERROR(EXPECTED_OBJECT_CLOSE);
192 if (flag & __KEY_FLAG) {
193 /* incomplete key-value pair */
194 _SPA_ERROR(EXPECTED_OBJECT_VALUE);
195 }
196 iter->state = __STRUCT | __SUB_FLAG | flag;
197 if (iter->depth == 0) {
198 if (iter->parent)
199 iter->parent->cur = iter->cur;
200 else
201 _SPA_ERROR(MISMATCHED_BRACKET);
202 return 0;
203 }
204 --iter->depth;
205 if (iter->depth == 0) {
206 SPA_FLAG_UPDATE(iter->state, __ARRAY_FLAG, flag & __PREV_ARRAY_FLAG);
207 } else if (((iter->depth-1) >> 6) < SPA_N_ELEMENTS(array_stack)) {
208 uint64_t mask = 1ULL << ((iter->depth-1) & 0x3f);
209 SPA_FLAG_UPDATE(iter->state, __ARRAY_FLAG,
210 SPA_FLAG_IS_SET(array_stack[(iter->depth-1) >> 6], mask));
211 } else {
212 /* too deep */
213 _SPA_ERROR(TOO_DEEP_NESTING);
214 }
215 continue;
216 case '\\':
217 /* disallow bare escape */
218 _SPA_ERROR(ESCAPE_NOT_ALLOWED);
219 default:
220 /* allow bare ascii */
221 if (!(cur >= 32 && cur <= 126))
222 _SPA_ERROR(CHARACTERS_NOT_ALLOWED);
223 if (flag & __KEY_FLAG)
224 flag |= __SUB_FLAG;
225 if (!(flag & __ARRAY_FLAG))
226 SPA_FLAG_UPDATE(flag, __KEY_FLAG, !(flag & __KEY_FLAG));
227 *value = iter->cur;
228 iter->state = __BARE | flag;
229 }
230 continue;
231 case __BARE:
232 switch (cur) {
233 case '\0':
234 case '\t': case ' ': case '\r': case '\n':
235 case '"': case '#':
236 case ':': case ',': case '=': case ']': case '}':
237 iter->state = __STRUCT | flag;
238 if (iter->depth > 0)
239 goto again;
240 return iter->cur - *value;
241 case '\\':
242 /* disallow bare escape */
243 _SPA_ERROR(ESCAPE_NOT_ALLOWED);
244 default:
245 /* allow bare ascii */
246 if (cur >= 32 && cur <= 126)
247 continue;
248 }
249 _SPA_ERROR(CHARACTERS_NOT_ALLOWED);
250 case __STRING:
251 switch (cur) {
252 case '\\':
253 iter->state = __ESC | flag;
254 continue;
255 case '"':
256 iter->state = __STRUCT | flag;
257 if (iter->depth > 0)
258 continue;
259 return ++iter->cur - *value;
260 case 240 ... 247:
261 utf8_remain++;
263 case 224 ... 239:
264 utf8_remain++;
266 case 192 ... 223:
267 utf8_remain++;
268 iter->state = __UTF8 | flag;
269 continue;
270 default:
271 if (cur >= 32 && cur <= 127)
272 continue;
273 }
274 _SPA_ERROR(CHARACTERS_NOT_ALLOWED);
275 case __UTF8:
276 switch (cur) {
277 case 128 ... 191:
278 if (--utf8_remain == 0)
279 iter->state = __STRING | flag;
280 continue;
281 default:
282 break;
283 }
284 _SPA_ERROR(CHARACTERS_NOT_ALLOWED);
285 case __ESC:
286 switch (cur) {
287 case '"': case '\\': case '/': case 'b': case 'f':
288 case 'n': case 'r': case 't': case 'u':
289 iter->state = __STRING | flag;
290 continue;
291 default:
292 break;
293 }
294 _SPA_ERROR(INVALID_ESCAPE);
295 case __COMMENT:
296 switch (cur) {
297 case '\n': case '\r':
298 iter->state = __STRUCT | flag;
299 break;
300 default:
301 break;
302 }
303 break;
304 default:
305 _SPA_ERROR(INVALID_STATE);
306 }
307
308 }
309 if (iter->depth != 0 || iter->parent)
310 _SPA_ERROR(MISMATCHED_BRACKET);
311
312 switch (iter->state & ~__FLAGS) {
313 case __STRING: case __UTF8: case __ESC:
314 /* string/escape not closed */
315 _SPA_ERROR(UNFINISHED_STRING);
316 case __COMMENT:
317 /* trailing comment */
318 return 0;
319 default:
320 break;
321 }
322
323 if ((iter->state & __SUB_FLAG) && (iter->state & __KEY_FLAG)) {
324 /* incomplete key-value pair */
325 _SPA_ERROR(EXPECTED_OBJECT_VALUE);
326 }
327
328 if ((iter->state & ~__FLAGS) != __STRUCT) {
329 iter->state = __STRUCT | (iter->state & __FLAGS);
330 return iter->cur - *value;
331 }
332 return 0;
333#undef _SPA_ERROR
334
335error:
336 iter->state = err;
337 while (iter->parent) {
338 if (iter->parent->state & SPA_JSON_ERROR_FLAG)
339 break;
340 iter->parent->state = err;
341 iter->parent->cur = iter->cur;
342 iter = iter->parent;
343 }
344 return -1;
345}
346
352SPA_API_JSON bool spa_json_get_error(struct spa_json *iter, const char *start,
353 struct spa_error_location *loc)
354{
355 static const char *reasons[] = {
356 "System error",
357 "Invalid array separator",
358 "Expected object key",
359 "Expected object value",
360 "Too deep nesting",
361 "Expected array close bracket",
362 "Expected object close brace",
363 "Mismatched bracket",
364 "Escape not allowed",
365 "Character not allowed",
366 "Invalid escape",
367 "Invalid state",
368 "Unfinished string",
369 "Expected key separator",
370 };
371
372 if (!(iter->state & SPA_JSON_ERROR_FLAG))
373 return false;
374
375 if (loc) {
376 int linepos = 1, colpos = 1, code;
377 const char *p, *l;
378
379 for (l = p = start; p && p != iter->cur; ++p) {
380 if (*p == '\n') {
381 linepos++;
382 colpos = 1;
383 l = p+1;
384 } else {
385 colpos++;
386 }
387 }
388 code = SPA_CLAMP(iter->state & 0xff, 0u, SPA_N_ELEMENTS(reasons)-1);
389 loc->line = linepos;
390 loc->col = colpos;
391 loc->location = l;
392 loc->len = SPA_PTRDIFF(iter->end, loc->location) / sizeof(char);
393 loc->reason = code == 0 ? strerror(errno) : reasons[code];
394 }
395 return true;
396}
397
398SPA_API_JSON int spa_json_is_container(const char *val, int len)
399{
400 return len > 0 && (*val == '{' || *val == '[');
401}
402
403/* object */
404SPA_API_JSON int spa_json_is_object(const char *val, int len)
405{
406 return len > 0 && *val == '{';
407}
408
409/* array */
410SPA_API_JSON bool spa_json_is_array(const char *val, int len)
411{
412 return len > 0 && *val == '[';
413}
414
415/* null */
416SPA_API_JSON bool spa_json_is_null(const char *val, int len)
417{
418 return len == 4 && strncmp(val, "null", 4) == 0;
419}
420
421/* float */
422SPA_API_JSON int spa_json_parse_float(const char *val, int len, float *result)
423{
424 char buf[96];
425 char *end;
426 int pos;
427
428 if (len <= 0 || len >= (int)sizeof(buf))
429 return 0;
430
431 for (pos = 0; pos < len; ++pos) {
432 switch (val[pos]) {
433 case '+': case '-': case '0' ... '9': case '.': case 'e': case 'E': break;
434 default: return 0;
435 }
436 }
437
438 memcpy(buf, val, len);
439 buf[len] = '\0';
440
441 *result = spa_strtof(buf, &end);
442 return len > 0 && end == buf + len;
443}
444
445SPA_API_JSON bool spa_json_is_float(const char *val, int len)
446{
447 float dummy;
448 return spa_json_parse_float(val, len, &dummy);
449}
450
451SPA_API_JSON char *spa_json_format_float(char *str, int size, float val)
452{
453 if (SPA_UNLIKELY(!isnormal(val))) {
454 if (isinf(val))
455 val = signbit(val) ? FLT_MIN : FLT_MAX;
456 else
457 val = 0.0f;
458 }
459 return spa_dtoa(str, size, val);
460}
461
462/* int */
463SPA_API_JSON int spa_json_parse_int(const char *val, int len, int *result)
464{
465 char buf[64];
466 char *end;
467
468 if (len <= 0 || len >= (int)sizeof(buf))
469 return 0;
470
471 memcpy(buf, val, len);
472 buf[len] = '\0';
473
474 *result = strtol(buf, &end, 0);
475 return len > 0 && end == buf + len;
476}
477SPA_API_JSON bool spa_json_is_int(const char *val, int len)
478{
479 int dummy;
480 return spa_json_parse_int(val, len, &dummy);
481}
482
483/* bool */
484SPA_API_JSON bool spa_json_is_true(const char *val, int len)
485{
486 return len == 4 && strncmp(val, "true", 4) == 0;
487}
488
489SPA_API_JSON bool spa_json_is_false(const char *val, int len)
490{
491 return len == 5 && strncmp(val, "false", 5) == 0;
492}
493
494SPA_API_JSON bool spa_json_is_bool(const char *val, int len)
495{
496 return spa_json_is_true(val, len) || spa_json_is_false(val, len);
497}
498
499SPA_API_JSON int spa_json_parse_bool(const char *val, int len, bool *result)
500{
501 if ((*result = spa_json_is_true(val, len)))
502 return 1;
503 if (!(*result = !spa_json_is_false(val, len)))
504 return 1;
505 return -1;
507
508/* string */
509SPA_API_JSON bool spa_json_is_string(const char *val, int len)
510{
511 return len > 1 && *val == '"';
512}
513
514SPA_API_JSON int spa_json_parse_hex(const char *p, int num, uint32_t *res)
515{
516 int i;
517 *res = 0;
518 for (i = 0; i < num; i++) {
519 char v = p[i];
520 if (v >= '0' && v <= '9')
521 v = v - '0';
522 else if (v >= 'a' && v <= 'f')
523 v = v - 'a' + 10;
524 else if (v >= 'A' && v <= 'F')
525 v = v - 'A' + 10;
526 else
527 return -1;
528 *res = (*res << 4) | v;
529 }
530 return 1;
531}
532
533SPA_API_JSON int spa_json_parse_stringn(const char *val, int len, char *result, int maxlen)
534{
535 const char *p;
536 if (maxlen <= len)
537 return -ENOSPC;
538 if (!spa_json_is_string(val, len)) {
539 if (result != val)
540 memmove(result, val, len);
541 result += len;
542 } else {
543 for (p = val+1; p < val + len; p++) {
544 if (*p == '\\') {
545 p++;
546 if (*p == 'n')
547 *result++ = '\n';
548 else if (*p == 'r')
549 *result++ = '\r';
550 else if (*p == 'b')
551 *result++ = '\b';
552 else if (*p == 't')
553 *result++ = '\t';
554 else if (*p == 'f')
555 *result++ = '\f';
556 else if (*p == 'u') {
557 uint8_t prefix[] = { 0, 0xc0, 0xe0, 0xf0 };
558 uint32_t idx, n, v, cp, enc[] = { 0x80, 0x800, 0x10000 };
559 if (val + len - p < 5 ||
560 spa_json_parse_hex(p+1, 4, &cp) < 0) {
561 *result++ = *p;
562 continue;
563 }
564 p += 4;
565
566 if (cp >= 0xd800 && cp <= 0xdbff) {
567 if (val + len - p < 7 ||
568 p[1] != '\\' || p[2] != 'u' ||
569 spa_json_parse_hex(p+3, 4, &v) < 0 ||
570 v < 0xdc00 || v > 0xdfff)
571 continue;
572 p += 6;
573 cp = 0x010000 + (((cp & 0x3ff) << 10) | (v & 0x3ff));
574 } else if (cp >= 0xdc00 && cp <= 0xdfff)
575 continue;
576
577 for (idx = 0; idx < 3; idx++)
578 if (cp < enc[idx])
579 break;
580 for (n = idx; n > 0; n--, cp >>= 6)
581 result[n] = (cp | 0x80) & 0xbf;
582 *result++ = (cp | prefix[idx]) & 0xff;
583 result += idx;
584 } else
585 *result++ = *p;
586 } else if (*p == '\"') {
587 break;
588 } else
589 *result++ = *p;
590 }
591 }
592 *result = '\0';
593 return 1;
594}
595
596SPA_API_JSON int spa_json_parse_string(const char *val, int len, char *result)
597{
598 return spa_json_parse_stringn(val, len, result, len+1);
599}
600
601SPA_API_JSON int spa_json_encode_string(char *str, int size, const char *val)
602{
603 int len = 0;
604 static const char hex[] = { "0123456789abcdef" };
605#define __PUT(c) { if (len < size) *str++ = c; len++; }
606 __PUT('"');
607 while (*val) {
608 switch (*val) {
609 case '\n':
610 __PUT('\\'); __PUT('n');
611 break;
612 case '\r':
613 __PUT('\\'); __PUT('r');
614 break;
615 case '\b':
616 __PUT('\\'); __PUT('b');
617 break;
618 case '\t':
619 __PUT('\\'); __PUT('t');
620 break;
621 case '\f':
622 __PUT('\\'); __PUT('f');
623 break;
624 case '\\':
625 case '"':
626 __PUT('\\'); __PUT(*val);
627 break;
628 default:
629 if (*val > 0 && *val < 0x20) {
630 __PUT('\\'); __PUT('u');
631 __PUT('0'); __PUT('0');
632 __PUT(hex[((*val)>>4)&0xf]); __PUT(hex[(*val)&0xf]);
633 } else {
634 __PUT(*val);
635 }
636 break;
637 }
638 val++;
639 }
640 __PUT('"');
641 __PUT('\0');
642#undef __PUT
643 return len-1;
644}
645
649
650#ifdef __cplusplus
651} /* extern "C" */
652#endif
653
654#endif /* SPA_UTILS_JSON_H */
spa/utils/defs.h
uint32_t int int res
Definition core.h:433
#define SPA_JSON_SAVE(iter)
Definition json-core.h:84
SPA_API_JSON void spa_json_init(struct spa_json *iter, const char *data, size_t size)
Definition json-core.h:62
SPA_API_JSON bool spa_json_is_string(const char *val, int len)
Definition json-core.h:521
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:416
SPA_API_JSON int spa_json_parse_hex(const char *p, int num, uint32_t *res)
Definition json-core.h:526
SPA_API_JSON int spa_json_parse_float(const char *val, int len, float *result)
Definition json-core.h:434
SPA_API_JSON char * spa_json_format_float(char *str, int size, float val)
Definition json-core.h:463
SPA_API_JSON bool spa_json_get_error(struct spa_json *iter, const char *start, struct spa_error_location *loc)
Return if there was a parse error, and its possible location.
Definition json-core.h:364
SPA_API_JSON int spa_json_parse_int(const char *val, int len, int *result)
Definition json-core.h:475
#define SPA_JSON_INIT_RELAX(type, data, size)
Definition json-core.h:67
SPA_API_JSON bool spa_json_is_null(const char *val, int len)
Definition json-core.h:428
SPA_API_JSON bool spa_json_is_true(const char *val, int len)
Definition json-core.h:496
#define SPA_JSON_INIT(data, size)
Definition json-core.h:60
SPA_API_JSON bool spa_json_is_bool(const char *val, int len)
Definition json-core.h:506
SPA_API_JSON void spa_json_init_relax(struct spa_json *iter, char type, const char *data, size_t size)
Definition json-core.h:70
#define SPA_JSON_ERROR_FLAG
Definition json-core.h:54
SPA_API_JSON int spa_json_parse_bool(const char *val, int len, bool *result)
Definition json-core.h:511
SPA_API_JSON bool spa_json_is_int(const char *val, int len)
Definition json-core.h:489
#define SPA_JSON_ENTER(iter)
Definition json-core.h:76
SPA_API_JSON void spa_json_start(struct spa_json *iter, struct spa_json *sub, const char *pos)
Definition json-core.h:94
SPA_API_JSON int spa_json_parse_stringn(const char *val, int len, char *result, int maxlen)
Definition json-core.h:545
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:422
SPA_API_JSON void spa_json_save(struct spa_json *iter, struct spa_json *save)
Definition json-core.h:86
SPA_API_JSON bool spa_json_is_false(const char *val, int len)
Definition json-core.h:501
SPA_API_JSON int spa_json_parse_string(const char *val, int len, char *result)
Definition json-core.h:608
#define SPA_JSON_START(iter, p)
Definition json-core.h:92
SPA_API_JSON bool spa_json_is_float(const char *val, int len)
Definition json-core.h:457
SPA_API_JSON int spa_json_is_container(const char *val, int len)
Definition json-core.h:410
SPA_API_JSON int spa_json_encode_string(char *str, int size, const char *val)
Definition json-core.h:613
SPA_API_STRING char * spa_dtoa(char *str, size_t size, double val)
Definition string.h:365
SPA_API_STRING float spa_strtof(const char *str, char **endptr)
Convert str to a float in the C locale.
Definition string.h:272
#define SPA_CLAMP(v, low, high)
Definition defs.h:177
#define SPA_FLAG_UPDATE(field, flag, val)
Definition defs.h:104
#define SPA_N_ELEMENTS(arr)
Definition defs.h:143
#define SPA_FLAG_IS_SET(field, flag)
Definition defs.h:90
#define SPA_UNLIKELY(x)
Definition defs.h:398
#define SPA_FALLTHROUGH
SPA_FALLTHROUGH is an annotation to suppress compiler warnings about switch cases that fall through w...
Definition defs.h:84
#define SPA_FLAG_CLEAR(field, flag)
Definition defs.h:94
#define SPA_PTRDIFF(p1, p2)
Definition defs.h:238
#define SPA_API_JSON
Definition json-core.h:35
#define _SPA_ERROR(reason)
#define __PUT(c)
spa/utils/string.h
Definition defs.h:443
int line
Definition defs.h:444
const char * location
Definition defs.h:447
int col
Definition defs.h:445
size_t len
Definition defs.h:446
const char * reason
Definition defs.h:448
Definition json-core.h:49
uint32_t depth
Definition json-core.h:56
const char * cur
Definition json-core.h:50
uint32_t state
Definition json-core.h:55
const char * end
Definition json-core.h:51
struct spa_json * parent
Definition json-core.h:52