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