PipeWire 1.7.0
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 '#': 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}
402SPA_API_JSON int spa_json_is_container_end(const char *val, int len)
403{
404 return len > 0 && (*val == '}' || *val == ']');
405}
406
407/* object */
408SPA_API_JSON int spa_json_is_object(const char *val, int len)
409{
410 return len > 0 && *val == '{';
411}
412
413/* array */
414SPA_API_JSON bool spa_json_is_array(const char *val, int len)
415{
416 return len > 0 && *val == '[';
417}
418
419/* null */
420SPA_API_JSON bool spa_json_is_null(const char *val, int len)
421{
422 return len == 4 && strncmp(val, "null", 4) == 0;
423}
424
425/* float */
426SPA_API_JSON int spa_json_parse_float(const char *val, int len, float *result)
427{
428 char buf[96], *end;
429
430 if (len <= 0 || len >= (int)sizeof(buf))
431 return 0;
433 memcpy(buf, val, len);
434 buf[len] = '\0';
435
436 *result = spa_strtof(buf, &end);
437 return len > 0 && end == buf + len;
439
440SPA_API_JSON bool spa_json_is_float(const char *val, int len)
441{
442 float dummy;
443 return spa_json_parse_float(val, len, &dummy);
444}
445
446SPA_API_JSON char *spa_json_format_float(char *str, int size, float val)
447{
448 if (SPA_UNLIKELY(!isnormal(val))) {
449 if (isinf(val))
450 val = signbit(val) ? FLT_MIN : FLT_MAX;
451 else
452 val = 0.0f;
453 }
454 return spa_dtoa(str, size, val);
455}
456
457/* int */
458SPA_API_JSON int spa_json_parse_int(const char *val, int len, int *result)
459{
460 char buf[64], *end;
461
462 if (len <= 0 || len >= (int)sizeof(buf))
463 return 0;
464
465 memcpy(buf, val, len);
466 buf[len] = '\0';
467
468 *result = strtol(buf, &end, 0);
469 return len > 0 && end == buf + len;
471SPA_API_JSON bool spa_json_is_int(const char *val, int len)
472{
473 int dummy;
474 return spa_json_parse_int(val, len, &dummy);
475}
476
477SPA_API_JSON bool spa_json_is_json_number(const char *val, int len)
478{
479 static const int8_t trans[9][7] = {
480 /* '1-9' '0' '-' '+' '.' 'eE' other */
481 /* 0 */ {-1, -1, -1, -1, 6, 7, -1 }, /* after '0' */
482 /* 1 */ { 1, 1, -1, -1, 6, 7, -1 }, /* in integer */
483 /* 2 */ { 2, 2, -1, -1, -1, 7, -1 }, /* in fraction */
484 /* 3 */ { 3, 3, -1, -1, -1, -1, -1 }, /* in exponent */
485 /* 4 */ { 1, 0, 5, -1, -1, -1, -1 }, /* start */
486 /* 5 */ { 1, 0, -1, -1, -1, -1, -1 }, /* after '-' */
487 /* 6 */ { 2, 2, -1, -1, -1, -1, -1 }, /* after '.' */
488 /* 7 */ { 3, 3, 8, 8, -1, -1, -1 }, /* after 'e'/'E' */
489 /* 8 */ { 3, 3, -1, -1, -1, -1, -1 }, /* after exp sign */
490 };
491 static const int8_t char_class[128] = {
492 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, /* 0-15 */
493 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, /* 16-31 */
494 6,6,6,6,6,6,6,6,6,6,6,3,6,2,4,6, /* 32-47: + - . */
495 1,0,0,0,0,0,0,0,0,0,6,6,6,6,6,6, /* 48-63: 0-9 */
496 6,6,6,6,6,5,6,6,6,6,6,6,6,6,6,6, /* 64-79: E */
497 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, /* 80-95 */
498 6,6,6,6,6,5,6,6,6,6,6,6,6,6,6,6, /* 96-111: e */
499 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, /* 112-127 */
500 };
501 int i, state = 4;
502
503 for (i = 0; i < len; i++) {
504 if ((state = trans[state][char_class[val[i]&0x7f]]) < 0)
505 return false;
506 }
507 return state < 4;
508}
509
510/* bool */
511SPA_API_JSON bool spa_json_is_true(const char *val, int len)
512{
513 return len == 4 && strncmp(val, "true", 4) == 0;
514}
515
516SPA_API_JSON bool spa_json_is_false(const char *val, int len)
517{
518 return len == 5 && strncmp(val, "false", 5) == 0;
519}
520
521SPA_API_JSON bool spa_json_is_bool(const char *val, int len)
522{
524}
525
526SPA_API_JSON int spa_json_parse_bool(const char *val, int len, bool *result)
527{
528 if ((*result = spa_json_is_true(val, len)))
529 return 1;
530 if (!(*result = !spa_json_is_false(val, len)))
531 return 1;
532 return -1;
534
535/* string */
536SPA_API_JSON bool spa_json_is_string(const char *val, int len)
537{
538 return len > 1 && *val == '"';
539}
540SPA_API_JSON bool spa_json_is_simple_string(const char *val, int size)
541{
542 int i;
543 static const char *REJECT = "\"\\'=:,{}[]()#";
544 for (i = 0; i < size && val[i]; i++) {
545 if (val[i] <= 0x20 || strchr(REJECT, val[i]) != NULL)
546 return false;
547 }
548 return true;
549}
550SPA_API_JSON bool spa_json_make_simple_string(const char **val, int *len)
551{
552 int i, l = *len;
553 const char *v = *val;
554 static const char *REJECT = "\"\\'=:,{}[]()#";
555 int trimmed = 0, bad = 0;
556 for (i = 0; i < l && v[i]; i++) {
557 if (i == 0 && v[0] == '\"')
558 trimmed++;
559 else if ((i+1 == l || !v[i+1]) && v[i] == '\"')
560 trimmed++;
561 else if (v[i] <= 0x20 || strchr(REJECT, v[i]) != NULL)
562 bad++;
563 }
564 if (trimmed == 0 && bad == 0 && i > 0)
565 return true;
566 else if (trimmed == 2) {
567 if (bad == 0 && i > 2 &&
568 !spa_json_is_null(&v[1], i-2) &&
569 !spa_json_is_bool(&v[1], i-2) &&
570 !spa_json_is_float(&v[1], i-2) &&
571 !spa_json_is_container(&v[1], i-2) &&
572 !spa_json_is_container_end(&v[1], i-2)) {
573 (*len) = i-2;
574 (*val)++;
575 }
576 return true;
577 }
578 return false;
579}
580
581SPA_API_JSON int spa_json_parse_hex(const char *p, int num, uint32_t *res)
582{
583 int i;
584 *res = 0;
585 for (i = 0; i < num; i++) {
586 char v = p[i];
587 if (v >= '0' && v <= '9')
588 v = v - '0';
589 else if (v >= 'a' && v <= 'f')
590 v = v - 'a' + 10;
591 else if (v >= 'A' && v <= 'F')
592 v = v - 'A' + 10;
593 else
594 return -1;
595 *res = (*res << 4) | v;
596 }
597 return 1;
598}
599
600SPA_API_JSON int spa_json_parse_stringn(const char *val, int len, char *result, int maxlen)
601{
602 const char *p;
603 if (maxlen <= len)
604 return -ENOSPC;
605 if (!spa_json_is_string(val, len)) {
606 if (result != val)
607 memmove(result, val, len);
608 result += len;
609 } else {
610 for (p = val+1; p < val + len; p++) {
611 if (*p == '\\') {
612 p++;
613 if (*p == 'n')
614 *result++ = '\n';
615 else if (*p == 'r')
616 *result++ = '\r';
617 else if (*p == 'b')
618 *result++ = '\b';
619 else if (*p == 't')
620 *result++ = '\t';
621 else if (*p == 'f')
622 *result++ = '\f';
623 else if (*p == 'u') {
624 uint8_t prefix[] = { 0, 0xc0, 0xe0, 0xf0 };
625 uint32_t idx, n, v, cp, enc[] = { 0x80, 0x800, 0x10000 };
626 if (val + len - p < 5 ||
627 spa_json_parse_hex(p+1, 4, &cp) < 0) {
628 *result++ = *p;
629 continue;
630 }
631 p += 4;
632
633 if (cp >= 0xd800 && cp <= 0xdbff) {
634 if (val + len - p < 7 ||
635 p[1] != '\\' || p[2] != 'u' ||
636 spa_json_parse_hex(p+3, 4, &v) < 0 ||
637 v < 0xdc00 || v > 0xdfff)
638 continue;
639 p += 6;
640 cp = 0x010000 + (((cp & 0x3ff) << 10) | (v & 0x3ff));
641 } else if (cp >= 0xdc00 && cp <= 0xdfff)
642 continue;
643
644 for (idx = 0; idx < 3; idx++)
645 if (cp < enc[idx])
646 break;
647 for (n = idx; n > 0; n--, cp >>= 6)
648 result[n] = (cp | 0x80) & 0xbf;
649 *result++ = (cp | prefix[idx]) & 0xff;
650 result += idx;
651 } else
652 *result++ = *p;
653 } else if (*p == '\"') {
654 break;
655 } else
656 *result++ = *p;
657 }
658 }
659 *result = '\0';
660 return 1;
661}
662
663SPA_API_JSON int spa_json_parse_string(const char *val, int len, char *result)
664{
665 return spa_json_parse_stringn(val, len, result, len+1);
666}
667
668SPA_API_JSON int spa_json_encode_string(char *str, int size, const char *val)
669{
670 int len = 0;
671 static const char hex[] = { "0123456789abcdef" };
672#define __PUT(c) { if (len < size) *str++ = c; len++; }
673 __PUT('"');
674 while (*val) {
675 switch (*val) {
676 case '\n':
677 __PUT('\\'); __PUT('n');
678 break;
679 case '\r':
680 __PUT('\\'); __PUT('r');
681 break;
682 case '\b':
683 __PUT('\\'); __PUT('b');
684 break;
685 case '\t':
686 __PUT('\\'); __PUT('t');
687 break;
688 case '\f':
689 __PUT('\\'); __PUT('f');
690 break;
691 case '\\':
692 case '"':
693 __PUT('\\'); __PUT(*val);
694 break;
695 default:
696 if (*val > 0 && *val < 0x20) {
697 __PUT('\\'); __PUT('u');
698 __PUT('0'); __PUT('0');
699 __PUT(hex[((*val)>>4)&0xf]); __PUT(hex[(*val)&0xf]);
700 } else {
701 __PUT(*val);
702 }
703 break;
704 }
705 val++;
706 }
707 __PUT('"');
708 __PUT('\0');
709#undef __PUT
710 return len-1;
711}
712
716
717#ifdef __cplusplus
718} /* extern "C" */
719#endif
720
721#endif /* SPA_UTILS_JSON_H */
spa/utils/defs.h
uint32_t int int res
Definition core.h:433
bool const char const char char * val
Definition json-builder.h:370
#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: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_container_end(const char *val, int len)
Definition json-core.h:414
SPA_API_JSON int spa_json_is_object(const char *val, int len)
Definition json-core.h:420
SPA_API_JSON int spa_json_parse_hex(const char *p, int num, uint32_t *res)
Definition json-core.h:593
SPA_API_JSON int spa_json_parse_float(const char *val, int len, float *result)
Definition json-core.h:438
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_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:470
#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:432
SPA_API_JSON bool spa_json_is_true(const char *val, int len)
Definition json-core.h:523
#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:533
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:538
SPA_API_JSON bool spa_json_is_int(const char *val, int len)
Definition json-core.h:483
#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:612
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_simple_string(const char *val, int size)
Definition json-core.h:552
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:528
SPA_API_JSON int spa_json_parse_string(const char *val, int len, char *result)
Definition json-core.h:675
#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:452
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:680
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