PipeWire  1.2.6
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
9 extern "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 */
33 struct 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 
50 static 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 
59 static 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 
296 error:
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 
313 static 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 
359 static 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 
371 static inline int spa_json_is_container(const char *val, int len)
372 {
373  return len > 0 && (*val == '{' || *val == '[');
374 }
375 
381 static 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 */
394 static inline int spa_json_is_object(const char *val, int len)
395 {
396  return len > 0 && *val == '{';
397 }
398 static 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 */
404 static inline bool spa_json_is_array(const char *val, int len)
405 {
406  return len > 0 && *val == '[';
407 }
408 static 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 */
414 static 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 */
420 static 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 
443 static 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 }
448 static 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 (val == INFINITY)
461  val = FLT_MAX;
462  else if (val == -INFINITY)
463  val = FLT_MIN;
464  else
465  val = 0.0f;
466  }
467  return spa_dtoa(str, size, val);
468 }
469 
470 /* int */
471 static inline int spa_json_parse_int(const char *val, int len, int *result)
472 {
473  char buf[64];
474  char *end;
475 
476  if (len <= 0 || len >= (int)sizeof(buf))
477  return 0;
478 
479  memcpy(buf, val, len);
480  buf[len] = '\0';
481 
482  *result = strtol(buf, &end, 0);
483  return len > 0 && end == buf + len;
484 }
485 static inline bool spa_json_is_int(const char *val, int len)
486 {
487  int dummy;
488  return spa_json_parse_int(val, len, &dummy);
489 }
490 static inline int spa_json_get_int(struct spa_json *iter, int *res)
491 {
492  const char *value;
493  int len;
494  if ((len = spa_json_next(iter, &value)) <= 0)
495  return len;
496  return spa_json_parse_int(value, len, res);
497 }
498 
499 /* bool */
500 static inline bool spa_json_is_true(const char *val, int len)
501 {
502  return len == 4 && strncmp(val, "true", 4) == 0;
503 }
504 
505 static inline bool spa_json_is_false(const char *val, int len)
506 {
507  return len == 5 && strncmp(val, "false", 5) == 0;
508 }
509 
510 static inline bool spa_json_is_bool(const char *val, int len)
511 {
512  return spa_json_is_true(val, len) || spa_json_is_false(val, len);
513 }
514 
515 static inline int spa_json_parse_bool(const char *val, int len, bool *result)
516 {
517  if ((*result = spa_json_is_true(val, len)))
518  return 1;
519  if (!(*result = !spa_json_is_false(val, len)))
520  return 1;
521  return -1;
522 }
523 static inline int spa_json_get_bool(struct spa_json *iter, bool *res)
524 {
525  const char *value;
526  int len;
527  if ((len = spa_json_next(iter, &value)) <= 0)
528  return len;
529  return spa_json_parse_bool(value, len, res);
530 }
531 
532 /* string */
533 static inline bool spa_json_is_string(const char *val, int len)
534 {
535  return len > 1 && *val == '"';
536 }
537 
538 static inline int spa_json_parse_hex(const char *p, int num, uint32_t *res)
539 {
540  int i;
541  *res = 0;
542  for (i = 0; i < num; i++) {
543  char v = p[i];
544  if (v >= '0' && v <= '9')
545  v = v - '0';
546  else if (v >= 'a' && v <= 'f')
547  v = v - 'a' + 10;
548  else if (v >= 'A' && v <= 'F')
549  v = v - 'A' + 10;
550  else
551  return -1;
552  *res = (*res << 4) | v;
553  }
554  return 1;
555 }
556 
557 static inline int spa_json_parse_stringn(const char *val, int len, char *result, int maxlen)
558 {
559  const char *p;
560  if (maxlen <= len)
561  return -1;
562  if (!spa_json_is_string(val, len)) {
563  if (result != val)
564  memmove(result, val, len);
565  result += len;
566  } else {
567  for (p = val+1; p < val + len; p++) {
568  if (*p == '\\') {
569  p++;
570  if (*p == 'n')
571  *result++ = '\n';
572  else if (*p == 'r')
573  *result++ = '\r';
574  else if (*p == 'b')
575  *result++ = '\b';
576  else if (*p == 't')
577  *result++ = '\t';
578  else if (*p == 'f')
579  *result++ = '\f';
580  else if (*p == 'u') {
581  uint8_t prefix[] = { 0, 0xc0, 0xe0, 0xf0 };
582  uint32_t idx, n, v, cp, enc[] = { 0x80, 0x800, 0x10000 };
583  if (val + len - p < 5 ||
584  spa_json_parse_hex(p+1, 4, &cp) < 0) {
585  *result++ = *p;
586  continue;
587  }
588  p += 4;
589 
590  if (cp >= 0xd800 && cp <= 0xdbff) {
591  if (val + len - p < 7 ||
592  p[1] != '\\' || p[2] != 'u' ||
593  spa_json_parse_hex(p+3, 4, &v) < 0 ||
594  v < 0xdc00 || v > 0xdfff)
595  continue;
596  p += 6;
597  cp = 0x010000 + (((cp & 0x3ff) << 10) | (v & 0x3ff));
598  } else if (cp >= 0xdc00 && cp <= 0xdfff)
599  continue;
600 
601  for (idx = 0; idx < 3; idx++)
602  if (cp < enc[idx])
603  break;
604  for (n = idx; n > 0; n--, cp >>= 6)
605  result[n] = (cp | 0x80) & 0xbf;
606  *result++ = (cp | prefix[idx]) & 0xff;
607  result += idx;
608  } else
609  *result++ = *p;
610  } else if (*p == '\"') {
611  break;
612  } else
613  *result++ = *p;
614  }
615  }
616  *result = '\0';
617  return 1;
618 }
619 
620 static inline int spa_json_parse_string(const char *val, int len, char *result)
621 {
622  return spa_json_parse_stringn(val, len, result, len+1);
623 }
624 
625 static inline int spa_json_get_string(struct spa_json *iter, char *res, int maxlen)
626 {
627  const char *value;
628  int len;
629  if ((len = spa_json_next(iter, &value)) <= 0)
630  return len;
631  return spa_json_parse_stringn(value, len, res, maxlen);
632 }
633 
634 static inline int spa_json_encode_string(char *str, int size, const char *val)
635 {
636  int len = 0;
637  static const char hex[] = { "0123456789abcdef" };
638 #define __PUT(c) { if (len < size) *str++ = c; len++; }
639  __PUT('"');
640  while (*val) {
641  switch (*val) {
642  case '\n':
643  __PUT('\\'); __PUT('n');
644  break;
645  case '\r':
646  __PUT('\\'); __PUT('r');
647  break;
648  case '\b':
649  __PUT('\\'); __PUT('b');
650  break;
651  case '\t':
652  __PUT('\\'); __PUT('t');
653  break;
654  case '\f':
655  __PUT('\\'); __PUT('f');
656  break;
657  case '\\':
658  case '"':
659  __PUT('\\'); __PUT(*val);
660  break;
661  default:
662  if (*val > 0 && *val < 0x20) {
663  __PUT('\\'); __PUT('u');
664  __PUT('0'); __PUT('0');
665  __PUT(hex[((*val)>>4)&0xf]); __PUT(hex[(*val)&0xf]);
666  } else {
667  __PUT(*val);
668  }
669  break;
670  }
671  val++;
672  }
673  __PUT('"');
674  __PUT('\0');
675 #undef __PUT
676  return len-1;
677 }
678 
683 #ifdef __cplusplus
684 } /* extern "C" */
685 #endif
686 
687 #endif /* SPA_UTILS_JSON_H */
spa/utils/defs.h
static bool spa_json_is_string(const char *val, int len)
Definition: json.h:542
static bool spa_json_is_float(const char *val, int len)
Definition: json.h:452
static int spa_json_parse_float(const char *val, int len, float *result)
Definition: json.h:429
static bool spa_json_is_true(const char *val, int len)
Definition: json.h:509
static int spa_json_parse_stringn(const char *val, int len, char *result, int maxlen)
Definition: json.h:566
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:547
static bool spa_json_is_false(const char *val, int len)
Definition: json.h:514
static int spa_json_get_int(struct spa_json *iter, int *res)
Definition: json.h:499
static int spa_json_parse_bool(const char *val, int len, bool *result)
Definition: json.h:524
static int spa_json_enter_object(struct spa_json *iter, struct spa_json *sub)
Definition: json.h:407
static int spa_json_get_string(struct spa_json *iter, char *res, int maxlen)
Definition: json.h:634
static bool spa_json_is_bool(const char *val, int len)
Definition: json.h:519
#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 bool spa_json_is_array(const char *val, int len)
Definition: json.h:413
static int spa_json_get_bool(struct spa_json *iter, bool *res)
Definition: json.h:532
static bool spa_json_is_null(const char *val, int len)
Definition: json.h:423
#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:643
static char * spa_json_format_float(char *str, int size, float val)
Definition: json.h:466
static int spa_json_parse_int(const char *val, int len, int *result)
Definition: json.h:480
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:494
static int spa_json_enter_array(struct spa_json *iter, struct spa_json *sub)
Definition: json.h:417
static int spa_json_get_float(struct spa_json *iter, float *res)
Definition: json.h:457
static int spa_json_is_object(const char *val, int len)
Definition: json.h:403
static int spa_json_parse_string(const char *val, int len, char *result)
Definition: json.h:629
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
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