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
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 (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 */
469 static 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 }
483 static 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 }
488 static 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 */
498 static inline bool spa_json_is_true(const char *val, int len)
499 {
500  return len == 4 && strncmp(val, "true", 4) == 0;
501 }
502 
503 static inline bool spa_json_is_false(const char *val, int len)
504 {
505  return len == 5 && strncmp(val, "false", 5) == 0;
506 }
507 
508 static 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 
513 static 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 }
521 static 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 */
531 static inline bool spa_json_is_string(const char *val, int len)
532 {
533  return len > 1 && *val == '"';
534 }
535 
536 static 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 
555 static 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 
618 static 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 
623 static 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 */
spa/utils/defs.h
static bool spa_json_is_string(const char *val, int len)
Definition: json.h:540
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:507
static int spa_json_parse_stringn(const char *val, int len, char *result, int maxlen)
Definition: json.h:564
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:545
static bool spa_json_is_false(const char *val, int len)
Definition: json.h:512
static int spa_json_get_int(struct spa_json *iter, int *res)
Definition: json.h:497
static int spa_json_parse_bool(const char *val, int len, bool *result)
Definition: json.h:522
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:632
static bool spa_json_is_bool(const char *val, int len)
Definition: json.h:517
#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:530
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:641
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:478
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:492
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:627
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