PipeWire: spa/utils/json.h Source File

PipeWire 1.2.7

Loading...
Searching...
No Matches
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};
41
42#define SPA_JSON_INIT(data,size) ((struct spa_json) { (data), (data)+(size), 0, 0, 0 })
43
44 static inline void spa_json_init(struct spa_json * iter, const char *data, size_t size)
45{
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 })
49
50static inline void spa_json_enter(struct spa_json * iter, struct spa_json * sub)
51{
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 })
56
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++;
232 SPA_FALLTHROUGH;
233 case 224 ... 239:
234 utf8_remain++;
235 SPA_FALLTHROUGH;
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
381static inline int spa_json_container_len(struct spa_json *iter, const char *value, int len SPA_UNUSED)
382{
383 const char *val;
384 struct spa_json sub;
385 int res;
386 spa_json_enter(iter, &sub);
387 while ((res = spa_json_next(&sub, &val)) > 0);
388 if (res < 0)
389 return 0;
390 return sub.cur + 1 - value;
391}
392
393/* object */
394static inline int spa_json_is_object(const char *val, int len)
395{
396 return len > 0 && *val == '{';
397}
398static inline int spa_json_enter_object(struct spa_json *iter, struct spa_json *sub)
399{
400 return spa_json_enter_container(iter, sub, '{');
401}
402
403/* array */
404static inline bool spa_json_is_array(const char *val, int len)
405{
406 return len > 0 && *val == '[';
407}
408static inline int spa_json_enter_array(struct spa_json *iter, struct spa_json *sub)
409{
410 return spa_json_enter_container(iter, sub, '[');
411}
412
413/* null */
414static inline bool spa_json_is_null(const char *val, int len)
415{
416 return len == 4 && strncmp(val, "null", 4) == 0;
417}
418
419/* float */
420static inline int spa_json_parse_float(const char *val, int len, float *result)
421{
422 char buf[96];
423 char *end;
424 int pos;
425
426 if (len <= 0 || len >= (int)sizeof(buf))
427 return 0;
428
429 for (pos = 0; pos < len; ++pos) {
430 switch (val[pos]) {
431 case '+': case '-': case '0' ... '9': case '.': case 'e': case 'E': break;
432 default: return 0;
433 }
434 }
435
436 memcpy(buf, val, len);
437 buf[len] = '\0';
438
439 *result = spa_strtof(buf, &end);
440 return len > 0 && end == buf + len;
441}
442
443static inline bool spa_json_is_float(const char *val, int len)
444{
445 float dummy;
446 return spa_json_parse_float(val, len, &dummy);
447}
448static inline int spa_json_get_float(struct spa_json *iter, float *res)
449{
450 const char *value;
451 int len;
452 if ((len = spa_json_next(iter, &value)) <= 0)
453 return len;
454 return spa_json_parse_float(value, len, res);
455}
456
457 static inline char *spa_json_format_float(char *str, int size, float val)
458{
459 if (SPA_UNLIKELY(!isnormal(val))) {
460 if (isinf(val))
461 val = signbit(val) ? FLT_MIN : FLT_MAX;
462 else
463 val = 0.0f;
464 }
465 return spa_dtoa(str, size, val);
466}
467
468/* int */
469static inline int spa_json_parse_int(const char *val, int len, int *result)
470{
471 char buf[64];
472 char *end;
473
474 if (len <= 0 || len >= (int)sizeof(buf))
475 return 0;
476
477 memcpy(buf, val, len);
478 buf[len] = '\0';
479
480 *result = strtol(buf, &end, 0);
481 return len > 0 && end == buf + len;
482}
483static inline bool spa_json_is_int(const char *val, int len)
484{
485 int dummy;
486 return spa_json_parse_int(val, len, &dummy);
487}
488static inline int spa_json_get_int(struct spa_json *iter, int *res)
489{
490 const char *value;
491 int len;
492 if ((len = spa_json_next(iter, &value)) <= 0)
493 return len;
494 return spa_json_parse_int(value, len, res);
495}
496
497/* bool */
498static inline bool spa_json_is_true(const char *val, int len)
499{
500 return len == 4 && strncmp(val, "true", 4) == 0;
501}
502
503static inline bool spa_json_is_false(const char *val, int len)
504{
505 return len == 5 && strncmp(val, "false", 5) == 0;
506}
507
508static inline bool spa_json_is_bool(const char *val, int len)
509{
510 return spa_json_is_true(val, len) || spa_json_is_false(val, len);
511}
512
513static inline int spa_json_parse_bool(const char *val, int len, bool *result)
514{
515 if ((*result = spa_json_is_true(val, len)))
516 return 1;
517 if (!(*result = !spa_json_is_false(val, len)))
518 return 1;
519 return -1;
520}
521static inline int spa_json_get_bool(struct spa_json *iter, bool *res)
522{
523 const char *value;
524 int len;
525 if ((len = spa_json_next(iter, &value)) <= 0)
526 return len;
527 return spa_json_parse_bool(value, len, res);
528}
529
530/* string */
531static inline bool spa_json_is_string(const char *val, int len)
532{
533 return len > 1 && *val == '"';
534}
535
536static inline int spa_json_parse_hex(const char *p, int num, uint32_t *res)
537{
538 int i;
539 *res = 0;
540 for (i = 0; i < num; i++) {
541 char v = p[i];
542 if (v >= '0' && v <= '9')
543 v = v - '0';
544 else if (v >= 'a' && v <= 'f')
545 v = v - 'a' + 10;
546 else if (v >= 'A' && v <= 'F')
547 v = v - 'A' + 10;
548 else
549 return -1;
550 *res = (*res << 4) | v;
551 }
552 return 1;
553}
554
555static inline int spa_json_parse_stringn(const char *val, int len, char *result, int maxlen)
556{
557 const char *p;
558 if (maxlen <= len)
559 return -1;
560 if (!spa_json_is_string(val, len)) {
561 if (result != val)
562 memmove(result, val, len);
563 result += len;
564 } else {
565 for (p = val+1; p < val + len; p++) {
566 if (*p == '\\') {
567 p++;
568 if (*p == 'n')
569 *result++ = '\n';
570 else if (*p == 'r')
571 *result++ = '\r';
572 else if (*p == 'b')
573 *result++ = '\b';
574 else if (*p == 't')
575 *result++ = '\t';
576 else if (*p == 'f')
577 *result++ = '\f';
578 else if (*p == 'u') {
579 uint8_t prefix[] = { 0, 0xc0, 0xe0, 0xf0 };
580 uint32_t idx, n, v, cp, enc[] = { 0x80, 0x800, 0x10000 };
581 if (val + len - p < 5 ||
582 spa_json_parse_hex(p+1, 4, &cp) < 0) {
583 *result++ = *p;
584 continue;
585 }
586 p += 4;
587
588 if (cp >= 0xd800 && cp <= 0xdbff) {
589 if (val + len - p < 7 ||
590 p[1] != '\\' || p[2] != 'u' ||
591 spa_json_parse_hex(p+3, 4, &v) < 0 ||
592 v < 0xdc00 || v > 0xdfff)
593 continue;
594 p += 6;
595 cp = 0x010000 + (((cp & 0x3ff) << 10) | (v & 0x3ff));
596 } else if (cp >= 0xdc00 && cp <= 0xdfff)
597 continue;
598
599 for (idx = 0; idx < 3; idx++)
600 if (cp < enc[idx])
601 break;
602 for (n = idx; n > 0; n--, cp >>= 6)
603 result[n] = (cp | 0x80) & 0xbf;
604 *result++ = (cp | prefix[idx]) & 0xff;
605 result += idx;
606 } else
607 *result++ = *p;
608 } else if (*p == '\"') {
609 break;
610 } else
611 *result++ = *p;
612 }
613 }
614 *result = '\0';
615 return 1;
616}
617
618static inline int spa_json_parse_string(const char *val, int len, char *result)
619{
620 return spa_json_parse_stringn(val, len, result, len+1);
621}
622
623static inline int spa_json_get_string(struct spa_json *iter, char *res, int maxlen)
624{
625 const char *value;
626 int len;
627 if ((len = spa_json_next(iter, &value)) <= 0)
628 return len;
629 return spa_json_parse_stringn(value, len, res, maxlen);
630}
631
632 static inline int spa_json_encode_string(char *str, int size, const char *val)
633{
634 int len = 0;
635 static const char hex[] = { "0123456789abcdef" };
636#define __PUT(c) { if (len < size) *str++ = c; len++; }
637 __PUT('"');
638 while (*val) {
639 switch (*val) {
640 case '\n':
641 __PUT('\\'); __PUT('n');
642 break;
643 case '\r':
644 __PUT('\\'); __PUT('r');
645 break;
646 case '\b':
647 __PUT('\\'); __PUT('b');
648 break;
649 case '\t':
650 __PUT('\\'); __PUT('t');
651 break;
652 case '\f':
653 __PUT('\\'); __PUT('f');
654 break;
655 case '\\':
656 case '"':
657 __PUT('\\'); __PUT(*val);
658 break;
659 default:
660 if (*val > 0 && *val < 0x20) {
661 __PUT('\\'); __PUT('u');
662 __PUT('0'); __PUT('0');
663 __PUT(hex[((*val)>>4)&0xf]); __PUT(hex[(*val)&0xf]);
664 } else {
665 __PUT(*val);
666 }
667 break;
668 }
669 val++;
670 }
671 __PUT('"');
672 __PUT('\0');
673#undef __PUT
674 return len-1;
675}
676
681#ifdef __cplusplus
682} /* extern "C" */
683#endif
684
685#endif /* SPA_UTILS_JSON_H */
defs.h
spa/utils/defs.h
spa_json_is_string
static bool spa_json_is_string(const char *val, int len)
Definition json.h:540
spa_json_is_float
static bool spa_json_is_float(const char *val, int len)
Definition json.h:452
spa_json_parse_float
static int spa_json_parse_float(const char *val, int len, float *result)
Definition json.h:429
spa_json_is_true
static bool spa_json_is_true(const char *val, int len)
Definition json.h:507
spa_json_parse_stringn
static int spa_json_parse_stringn(const char *val, int len, char *result, int maxlen)
Definition json.h:564
spa_json_enter_container
static int spa_json_enter_container(struct spa_json *iter, struct spa_json *sub, char type)
Definition json.h:368
spa_json_enter
static void spa_json_enter(struct spa_json *iter, struct spa_json *sub)
Definition json.h:58
spa_json_parse_hex
static int spa_json_parse_hex(const char *p, int num, uint32_t *res)
Definition json.h:545
spa_json_is_false
static bool spa_json_is_false(const char *val, int len)
Definition json.h:512
spa_json_get_int
static int spa_json_get_int(struct spa_json *iter, int *res)
Definition json.h:497
spa_json_parse_bool
static int spa_json_parse_bool(const char *val, int len, bool *result)
Definition json.h:522
spa_json_enter_object
static int spa_json_enter_object(struct spa_json *iter, struct spa_json *sub)
Definition json.h:407
spa_json_get_string
static int spa_json_get_string(struct spa_json *iter, char *res, int maxlen)
Definition json.h:632
spa_json_is_bool
static bool spa_json_is_bool(const char *val, int len)
Definition json.h:517
SPA_JSON_INIT
#define SPA_JSON_INIT(data, size)
Definition json.h:49
spa_json_get_error
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
SPA_JSON_ERROR_FLAG
#define SPA_JSON_ERROR_FLAG
Definition json.h:43
spa_json_format_float
static char * spa_json_format_float(char *str, int size, float val)
Definition json.h:466
spa_json_is_array
static bool spa_json_is_array(const char *val, int len)
Definition json.h:413
spa_json_get_bool
static int spa_json_get_bool(struct spa_json *iter, bool *res)
Definition json.h:530
spa_json_is_null
static bool spa_json_is_null(const char *val, int len)
Definition json.h:423
SPA_JSON_ENTER
#define SPA_JSON_ENTER(iter)
Definition json.h:56
spa_json_encode_string
static int spa_json_encode_string(char *str, int size, const char *val)
Definition json.h:641
spa_json_parse_int
static int spa_json_parse_int(const char *val, int len, int *result)
Definition json.h:478
spa_json_next
static int spa_json_next(struct spa_json *iter, const char **value)
Get the next token.
Definition json.h:68
spa_json_is_container
static int spa_json_is_container(const char *val, int len)
Definition json.h:380
spa_json_init
static void spa_json_init(struct spa_json *iter, const char *data, size_t size)
Definition json.h:51
spa_json_is_int
static bool spa_json_is_int(const char *val, int len)
Definition json.h:492
spa_json_enter_array
static int spa_json_enter_array(struct spa_json *iter, struct spa_json *sub)
Definition json.h:417
spa_json_get_float
static int spa_json_get_float(struct spa_json *iter, float *res)
Definition json.h:457
spa_json_is_object
static int spa_json_is_object(const char *val, int len)
Definition json.h:403
spa_json_parse_string
static int spa_json_parse_string(const char *val, int len, char *result)
Definition json.h:627
spa_json_container_len
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:390
spa_strtof
static float spa_strtof(const char *str, char **endptr)
Convert str to a float in the C locale.
Definition string.h:261
spa_dtoa
static char * spa_dtoa(char *str, size_t size, double val)
Definition string.h:354
SPA_UNUSED
#define SPA_UNUSED
Definition defs.h:307
SPA_CLAMP
#define SPA_CLAMP(v, low, high)
Definition defs.h:177
SPA_FLAG_UPDATE
#define SPA_FLAG_UPDATE(field, flag, val)
Definition defs.h:104
SPA_N_ELEMENTS
#define SPA_N_ELEMENTS(arr)
Definition defs.h:143
SPA_FLAG_IS_SET
#define SPA_FLAG_IS_SET(field, flag)
Definition defs.h:90
SPA_UNLIKELY
#define SPA_UNLIKELY(x)
Definition defs.h:369
SPA_FALLTHROUGH
#define SPA_FALLTHROUGH
SPA_FALLTHROUGH is an annotation to suppress compiler warnings about switch cases that fall through w...
Definition defs.h:84
SPA_FLAG_CLEAR
#define SPA_FLAG_CLEAR(field, flag)
Definition defs.h:94
SPA_PTRDIFF
#define SPA_PTRDIFF(p1, p2)
Definition defs.h:238
_SPA_ERROR
#define _SPA_ERROR(reason)
__PUT
#define __PUT(c)
string.h
spa/utils/string.h
spa_error_location
Definition defs.h:414
spa_error_location::line
int line
Definition defs.h:415
spa_error_location::location
const char * location
Definition defs.h:418
spa_error_location::col
int col
Definition defs.h:416
spa_error_location::len
size_t len
Definition defs.h:417
spa_error_location::reason
const char * reason
Definition defs.h:419
spa_json
Definition json.h:38
spa_json::depth
uint32_t depth
Definition json.h:45
spa_json::cur
const char * cur
Definition json.h:39
spa_json::state
uint32_t state
Definition json.h:44
spa_json::end
const char * end
Definition json.h:40
spa_json::parent
struct spa_json * parent
Definition json.h:41