PipeWire  1.6.4
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
19 extern "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 
41 /* a simple JSON compatible tokenizer */
42 struct 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 };
50 
51 #define SPA_JSON_INIT(data,size) ((struct spa_json) { (data), (data)+(size), NULL, 0, 0 })
52 
53 SPA_API_JSON void spa_json_init(struct spa_json * iter, const char *data, size_t size)
54 {
55  *iter = SPA_JSON_INIT(data, size);
56 }
57 
58 #define SPA_JSON_INIT_RELAX(type,data,size) \
59  ((struct spa_json) { (data), (data)+(size), NULL, (uint32_t)((type) == '[' ? 0x10 : 0x0), 0 })
60 
61 SPA_API_JSON void spa_json_init_relax(struct spa_json * iter, char type, const char *data, size_t size)
62 {
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 })
67 
68 SPA_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 
75 SPA_API_JSON void spa_json_save(struct spa_json * iter, struct spa_json * save)
76 {
77  *save = SPA_JSON_SAVE(iter);
78 }
79 
80 #define SPA_JSON_START(iter,p) ((struct spa_json) { (p), (iter)->end, NULL, 0, 0 })
81 
82 SPA_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 }
86 
89 SPA_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 '#':
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 
335 error:
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 
352 SPA_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 
398 SPA_API_JSON int spa_json_is_container(const char *val, int len)
399 {
400  return len > 0 && (*val == '{' || *val == '[');
401 }
402 
403 /* object */
404 SPA_API_JSON int spa_json_is_object(const char *val, int len)
405 {
406  return len > 0 && *val == '{';
407 }
408 
409 /* array */
410 SPA_API_JSON bool spa_json_is_array(const char *val, int len)
411 {
412  return len > 0 && *val == '[';
413 }
414 
415 /* null */
416 SPA_API_JSON bool spa_json_is_null(const char *val, int len)
417 {
418  return len == 4 && strncmp(val, "null", 4) == 0;
419 }
420 
421 /* float */
422 SPA_API_JSON int spa_json_parse_float(const char *val, int len, float *result)
423 {
424  char buf[96];
425  char *end;
426  int pos;
427 
428  if (len <= 0 || len >= (int)sizeof(buf))
429  return 0;
430 
431  for (pos = 0; pos < len; ++pos) {
432  switch (val[pos]) {
433  case '+': case '-': case '0' ... '9': case '.': case 'e': case 'E': break;
434  default: return 0;
435  }
436  }
437 
438  memcpy(buf, val, len);
439  buf[len] = '\0';
440 
441  *result = spa_strtof(buf, &end);
442  return len > 0 && end == buf + len;
443 }
444 
445 SPA_API_JSON bool spa_json_is_float(const char *val, int len)
446 {
447  float dummy;
448  return spa_json_parse_float(val, len, &dummy);
449 }
450 
451 SPA_API_JSON char *spa_json_format_float(char *str, int size, float val)
452 {
453  if (SPA_UNLIKELY(!isnormal(val))) {
454  if (isinf(val))
455  val = signbit(val) ? FLT_MIN : FLT_MAX;
456  else
457  val = 0.0f;
458  }
459  return spa_dtoa(str, size, val);
460 }
461 
462 /* int */
463 SPA_API_JSON int spa_json_parse_int(const char *val, int len, int *result)
464 {
465  char buf[64];
466  char *end;
467 
468  if (len <= 0 || len >= (int)sizeof(buf))
469  return 0;
470 
471  memcpy(buf, val, len);
472  buf[len] = '\0';
473 
474  *result = strtol(buf, &end, 0);
475  return len > 0 && end == buf + len;
476 }
477 SPA_API_JSON bool spa_json_is_int(const char *val, int len)
478 {
479  int dummy;
480  return spa_json_parse_int(val, len, &dummy);
481 }
482 
483 /* bool */
484 SPA_API_JSON bool spa_json_is_true(const char *val, int len)
485 {
486  return len == 4 && strncmp(val, "true", 4) == 0;
487 }
488 
489 SPA_API_JSON bool spa_json_is_false(const char *val, int len)
490 {
491  return len == 5 && strncmp(val, "false", 5) == 0;
492 }
493 
494 SPA_API_JSON bool spa_json_is_bool(const char *val, int len)
495 {
496  return spa_json_is_true(val, len) || spa_json_is_false(val, len);
497 }
498 
499 SPA_API_JSON int spa_json_parse_bool(const char *val, int len, bool *result)
500 {
501  if ((*result = spa_json_is_true(val, len)))
502  return 1;
503  if (!(*result = !spa_json_is_false(val, len)))
504  return 1;
505  return -1;
506 }
507 
508 /* string */
509 SPA_API_JSON bool spa_json_is_string(const char *val, int len)
510 {
511  return len > 1 && *val == '"';
512 }
513 
514 SPA_API_JSON int spa_json_parse_hex(const char *p, int num, uint32_t *res)
515 {
516  int i;
517  *res = 0;
518  for (i = 0; i < num; i++) {
519  char v = p[i];
520  if (v >= '0' && v <= '9')
521  v = v - '0';
522  else if (v >= 'a' && v <= 'f')
523  v = v - 'a' + 10;
524  else if (v >= 'A' && v <= 'F')
525  v = v - 'A' + 10;
526  else
527  return -1;
528  *res = (*res << 4) | v;
529  }
530  return 1;
531 }
532 
533 SPA_API_JSON int spa_json_parse_stringn(const char *val, int len, char *result, int maxlen)
534 {
535  const char *p;
536  if (maxlen <= len)
537  return -ENOSPC;
538  if (!spa_json_is_string(val, len)) {
539  if (result != val)
540  memmove(result, val, len);
541  result += len;
542  } else {
543  for (p = val+1; p < val + len; p++) {
544  if (*p == '\\') {
545  p++;
546  if (*p == 'n')
547  *result++ = '\n';
548  else if (*p == 'r')
549  *result++ = '\r';
550  else if (*p == 'b')
551  *result++ = '\b';
552  else if (*p == 't')
553  *result++ = '\t';
554  else if (*p == 'f')
555  *result++ = '\f';
556  else if (*p == 'u') {
557  uint8_t prefix[] = { 0, 0xc0, 0xe0, 0xf0 };
558  uint32_t idx, n, v, cp, enc[] = { 0x80, 0x800, 0x10000 };
559  if (val + len - p < 5 ||
560  spa_json_parse_hex(p+1, 4, &cp) < 0) {
561  *result++ = *p;
562  continue;
563  }
564  p += 4;
565 
566  if (cp >= 0xd800 && cp <= 0xdbff) {
567  if (val + len - p < 7 ||
568  p[1] != '\\' || p[2] != 'u' ||
569  spa_json_parse_hex(p+3, 4, &v) < 0 ||
570  v < 0xdc00 || v > 0xdfff)
571  continue;
572  p += 6;
573  cp = 0x010000 + (((cp & 0x3ff) << 10) | (v & 0x3ff));
574  } else if (cp >= 0xdc00 && cp <= 0xdfff)
575  continue;
576 
577  for (idx = 0; idx < 3; idx++)
578  if (cp < enc[idx])
579  break;
580  for (n = idx; n > 0; n--, cp >>= 6)
581  result[n] = (cp | 0x80) & 0xbf;
582  *result++ = (cp | prefix[idx]) & 0xff;
583  result += idx;
584  } else
585  *result++ = *p;
586  } else if (*p == '\"') {
587  break;
588  } else
589  *result++ = *p;
590  }
591  }
592  *result = '\0';
593  return 1;
594 }
595 
596 SPA_API_JSON int spa_json_parse_string(const char *val, int len, char *result)
597 {
598  return spa_json_parse_stringn(val, len, result, len+1);
599 }
600 
601 SPA_API_JSON int spa_json_encode_string(char *str, int size, const char *val)
602 {
603  int len = 0;
604  static const char hex[] = { "0123456789abcdef" };
605 #define __PUT(c) { if (len < size) *str++ = c; len++; }
606  __PUT('"');
607  while (*val) {
608  switch (*val) {
609  case '\n':
610  __PUT('\\'); __PUT('n');
611  break;
612  case '\r':
613  __PUT('\\'); __PUT('r');
614  break;
615  case '\b':
616  __PUT('\\'); __PUT('b');
617  break;
618  case '\t':
619  __PUT('\\'); __PUT('t');
620  break;
621  case '\f':
622  __PUT('\\'); __PUT('f');
623  break;
624  case '\\':
625  case '"':
626  __PUT('\\'); __PUT(*val);
627  break;
628  default:
629  if (*val > 0 && *val < 0x20) {
630  __PUT('\\'); __PUT('u');
631  __PUT('0'); __PUT('0');
632  __PUT(hex[((*val)>>4)&0xf]); __PUT(hex[(*val)&0xf]);
633  } else {
634  __PUT(*val);
635  }
636  break;
637  }
638  val++;
639  }
640  __PUT('"');
641  __PUT('\0');
642 #undef __PUT
643  return len-1;
644 }
645 
650 #ifdef __cplusplus
651 } /* extern "C" */
652 #endif
653 
654 #endif /* SPA_UTILS_JSON_H */
spa/utils/defs.h
uint32_t int int res
Definition: core.h:433
#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:521
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_object(const char *val, int len)
Definition: json-core.h:416
SPA_API_JSON int spa_json_parse_hex(const char *p, int num, uint32_t *res)
Definition: json-core.h:526
SPA_API_JSON int spa_json_parse_float(const char *val, int len, float *result)
Definition: json-core.h:434
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:475
#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:428
SPA_API_JSON bool spa_json_is_true(const char *val, int len)
Definition: json-core.h:496
#define SPA_JSON_INIT(data, size)
Definition: json-core.h:60
SPA_API_JSON char * spa_json_format_float(char *str, int size, float val)
Definition: json-core.h:463
SPA_API_JSON bool spa_json_is_bool(const char *val, int len)
Definition: json-core.h:506
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:511
SPA_API_JSON bool spa_json_is_int(const char *val, int len)
Definition: json-core.h:489
#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:545
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:422
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:501
SPA_API_JSON int spa_json_parse_string(const char *val, int len, char *result)
Definition: json-core.h:608
#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:457
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:613
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