PipeWire  1.6.4
parser.h
Go to the documentation of this file.
1 /* Spa */
2 /* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
3 /* SPDX-License-Identifier: MIT */
4 
5 #ifndef SPA_POD_PARSER_H
6 #define SPA_POD_PARSER_H
7 
8 #include <errno.h>
9 #include <stdarg.h>
10 
11 #include <spa/pod/body.h>
12 #include <spa/pod/vararg.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 #ifndef SPA_API_POD_PARSER
19  #ifdef SPA_API_IMPL
20  #define SPA_API_POD_PARSER SPA_API_IMPL
21  #else
22  #define SPA_API_POD_PARSER static inline
23  #endif
24 #endif
25 
31 struct spa_pod_parser_state {
32  uint32_t offset;
33  uint32_t flags;
34  struct spa_pod_frame *frame;
35 };
36 
37 struct spa_pod_parser {
38  const void *data;
39  uint32_t size;
40  uint32_t _padding;
42 };
43 
44 #define SPA_POD_PARSER_INIT(buffer,size) ((struct spa_pod_parser){ (buffer), (size), 0, {0,0,NULL}})
45 
47  const void *data, uint32_t size)
48 {
49  *parser = SPA_POD_PARSER_INIT(data, size);
50 }
51 
53  const struct spa_pod *pod)
54 {
55  spa_pod_parser_init(parser, pod, SPA_POD_SIZE(pod));
56 }
57 
59  const struct spa_pod *pod, const void *body)
60 {
61  spa_pod_parser_init(parser,
62  SPA_PTROFF(body, -sizeof(struct spa_pod), const struct spa_pod),
63  pod->size + sizeof(struct spa_pod));
64 }
66  const void *data, uint32_t maxsize, uint32_t offset, uint32_t size)
67 {
68  size_t offs, sz;
69  offs = SPA_MIN(offset, maxsize);
70  sz = SPA_MIN(maxsize - offs, size);
71  spa_pod_parser_init(parser, SPA_PTROFF(data, offs, void), sz);
72 }
73 
76 {
77  *state = parser->state;
78 }
79 
81 spa_pod_parser_reset(struct spa_pod_parser *parser, struct spa_pod_parser_state *state)
82 {
83  parser->state = *state;
84 }
85 
87 spa_pod_parser_read_header(struct spa_pod_parser *parser, uint32_t offset, uint32_t size,
88  void *header, uint32_t header_size, uint32_t pod_offset, const void **body)
89 {
90  /* Cast to uint64_t to avoid wraparound. */
91  const uint64_t long_offset = (uint64_t)offset + header_size;
92  if (long_offset <= size && (offset & 7) == 0) {
93  struct spa_pod *pod;
94  /* a barrier around the memcpy to make sure it is not moved around or
95  * duplicated after the size check below. We need to work on shared
96  * memory and so there could be updates happening while we read. */
98  memcpy(header, SPA_PTROFF(parser->data, offset, void), header_size);
100  pod = SPA_PTROFF(header, pod_offset, struct spa_pod);
101  /* Check that the size (rounded to the next multiple of 8) is in bounds. */
102  if (long_offset + SPA_ROUND_UP_N((uint64_t)pod->size, SPA_POD_ALIGN) <= size) {
103  *body = SPA_PTROFF(parser->data, long_offset, void);
104  return 0;
105  }
106  }
107  return -EPIPE;
108 }
109 
111 spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t size)
112 {
113  struct spa_pod pod;
114  const void *body;
115  if (spa_pod_parser_read_header(parser, offset, size, &pod, sizeof(pod), 0, &body) < 0)
116  return NULL;
117  return SPA_PTROFF(body, -sizeof(pod), struct spa_pod);
118 }
119 
120 SPA_API_POD_PARSER struct spa_pod *spa_pod_parser_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
121 {
122  return SPA_PTROFF(parser->data, frame->offset, struct spa_pod);
123 }
124 
126  struct spa_pod_frame *frame, const struct spa_pod *pod, uint32_t offset)
127 {
128  frame->pod = *pod;
129  frame->offset = offset;
130  frame->parent = parser->state.frame;
131  frame->flags = parser->state.flags;
132  parser->state.frame = frame;
133 }
134 
136  void *header, uint32_t header_size, uint32_t pod_offset, const void **body)
137 {
138  struct spa_pod_frame *f = parser->state.frame;
139  uint32_t size = f ? f->offset + SPA_POD_SIZE(&f->pod) : parser->size;
140  return spa_pod_parser_read_header(parser, parser->state.offset, size,
141  header, header_size, pod_offset, body);
142 }
143 
145  struct spa_pod *pod, const void **body)
146 {
147  return spa_pod_parser_get_header(parser, pod, sizeof(struct spa_pod), 0, body);
148 }
149 
151 {
152  struct spa_pod pod;
153  const void *body;
154  if (spa_pod_parser_current_body(parser, &pod, &body) < 0)
155  return NULL;
156  return SPA_PTROFF(body, -sizeof(struct spa_pod), struct spa_pod);
157 }
158 
159 SPA_API_POD_PARSER void spa_pod_parser_advance(struct spa_pod_parser *parser, const struct spa_pod *pod)
160 {
162 }
163 
165  struct spa_pod *pod, const void **body)
166 {
167  if (spa_pod_parser_current_body(parser, pod, body) < 0)
168  return -EINVAL;
169  spa_pod_parser_advance(parser, pod);
170  return 0;
171 }
172 
174 {
175  struct spa_pod pod;
176  const void *body;
177  if (spa_pod_parser_current_body(parser, &pod, &body) < 0)
178  return NULL;
179  spa_pod_parser_advance(parser, &pod);
180  return SPA_PTROFF(body, -sizeof(struct spa_pod), struct spa_pod);
181 }
182 
184  struct spa_pod_frame *frame)
185 {
186  parser->state.offset = frame->offset;
187 }
188 
190  struct spa_pod_frame *frame)
191 {
192  spa_pod_parser_restart(parser, frame);
193  parser->state.frame = frame->parent;
194 }
195 
197  struct spa_pod_frame *frame)
198 {
199  spa_pod_parser_unpush(parser, frame);
200  spa_pod_parser_advance(parser, &frame->pod);
201  return 0;
202 }
203 
205 {
206  int res;
207  struct spa_pod pod;
208  const void *body;
209  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
210  return res;
211  if ((res = spa_pod_body_get_bool(&pod, body, value)) >= 0)
212  spa_pod_parser_advance(parser, &pod);
213  return res;
214 }
215 
216 SPA_API_POD_PARSER int spa_pod_parser_get_id(struct spa_pod_parser *parser, uint32_t *value)
217 {
218  int res;
219  struct spa_pod pod;
220  const void *body;
221  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
222  return res;
223  if ((res = spa_pod_body_get_id(&pod, body, value)) >= 0)
224  spa_pod_parser_advance(parser, &pod);
225  return res;
226 }
227 
228 SPA_API_POD_PARSER int spa_pod_parser_get_int(struct spa_pod_parser *parser, int32_t *value)
229 {
230  int res;
231  struct spa_pod pod;
232  const void *body;
233  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
234  return res;
235  if ((res = spa_pod_body_get_int(&pod, body, value)) >= 0)
236  spa_pod_parser_advance(parser, &pod);
237  return res;
238 }
239 
240 SPA_API_POD_PARSER int spa_pod_parser_get_long(struct spa_pod_parser *parser, int64_t *value)
241 {
242  int res;
243  struct spa_pod pod;
244  const void *body;
245  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
246  return res;
247  if ((res = spa_pod_body_get_long(&pod, body, value)) >= 0)
248  spa_pod_parser_advance(parser, &pod);
249  return res;
250 }
251 
252 SPA_API_POD_PARSER int spa_pod_parser_get_float(struct spa_pod_parser *parser, float *value)
253 {
254  int res;
255  struct spa_pod pod;
256  const void *body;
257  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
258  return res;
259  if ((res = spa_pod_body_get_float(&pod, body, value)) >= 0)
260  spa_pod_parser_advance(parser, &pod);
261  return res;
262 }
263 
264 SPA_API_POD_PARSER int spa_pod_parser_get_double(struct spa_pod_parser *parser, double *value)
265 {
266  int res;
267  struct spa_pod pod;
268  const void *body;
269  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
270  return res;
271  if ((res = spa_pod_body_get_double(&pod, body, value)) >= 0)
272  spa_pod_parser_advance(parser, &pod);
273  return res;
274 }
275 
276 SPA_API_POD_PARSER int spa_pod_parser_get_string(struct spa_pod_parser *parser, const char **value)
277 {
278  int res;
279  struct spa_pod pod;
280  const void *body;
281  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
282  return res;
283  if ((res = spa_pod_body_get_string(&pod, body, value)) >= 0)
284  spa_pod_parser_advance(parser, &pod);
285  return res;
286 }
287 
288 SPA_API_POD_PARSER int spa_pod_parser_get_bytes(struct spa_pod_parser *parser, const void **value, uint32_t *len)
289 {
290  int res;
291  struct spa_pod pod;
292  const void *body;
293  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
294  return res;
295  if ((res = spa_pod_body_get_bytes(&pod, body, value, len)) >= 0)
296  spa_pod_parser_advance(parser, &pod);
297  return res;
298 }
299 
300 SPA_API_POD_PARSER int spa_pod_parser_get_pointer(struct spa_pod_parser *parser, uint32_t *type, const void **value)
301 {
302  int res;
303  struct spa_pod pod;
304  const void *body;
305  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
306  return res;
307  if ((res = spa_pod_body_get_pointer(&pod, body, type, value)) >= 0)
308  spa_pod_parser_advance(parser, &pod);
309  return res;
310 }
311 
312 SPA_API_POD_PARSER int spa_pod_parser_get_fd(struct spa_pod_parser *parser, int64_t *value)
313 {
314  int res;
315  struct spa_pod pod;
316  const void *body;
317  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
318  return res;
319  if ((res = spa_pod_body_get_fd(&pod, body, value)) >= 0)
320  spa_pod_parser_advance(parser, &pod);
321  return res;
322 }
323 
325 {
326  int res;
327  struct spa_pod pod;
328  const void *body;
329  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
330  return res;
331  if ((res = spa_pod_body_get_rectangle(&pod, body, value)) >= 0)
332  spa_pod_parser_advance(parser, &pod);
333  return res;
334 }
335 
337 {
338  int res;
339  struct spa_pod pod;
340  const void *body;
341  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
342  return res;
343  if ((res = spa_pod_body_get_fraction(&pod, body, value)) >= 0)
344  spa_pod_parser_advance(parser, &pod);
345  return res;
346 }
347 
349  struct spa_pod *value, const void **body)
350 {
351  int res;
352  if ((res = spa_pod_parser_current_body(parser, value, body)) < 0)
353  return res;
354  spa_pod_parser_advance(parser, value);
355  return 0;
356 }
357 
358 SPA_API_POD_PARSER int spa_pod_parser_get_pod(struct spa_pod_parser *parser, struct spa_pod **value)
359 {
360  int res;
361  struct spa_pod pod;
362  const void *body;
363  if ((res = spa_pod_parser_get_pod_body(parser, &pod, &body)) < 0)
364  return res;
365  *value = SPA_PTROFF(body, -sizeof(struct spa_pod), struct spa_pod);
366  return 0;
367 }
368 
370  struct spa_pod_frame *frame, const struct spa_pod *pod, const void *body)
371 {
372  if (!spa_pod_is_struct(pod))
373  return -EINVAL;
374  spa_pod_parser_init_pod_body(parser, pod, body);
375  spa_pod_parser_push(parser, frame, pod, parser->state.offset);
376  parser->state.offset += sizeof(struct spa_pod_struct);
377  return 0;
378 }
379 
381  struct spa_pod_frame *frame, struct spa_pod *str, const void **str_body)
382 {
383  int res;
384  if ((res = spa_pod_parser_current_body(parser, str, str_body)) < 0)
385  return res;
386  if (!spa_pod_is_struct(str))
387  return -EINVAL;
388  spa_pod_parser_push(parser, frame, str, parser->state.offset);
389  parser->state.offset += sizeof(struct spa_pod_struct);
390  return 0;
391 }
393  struct spa_pod_frame *frame)
394 {
395  struct spa_pod pod;
396  const void *body;
397  return spa_pod_parser_push_struct_body(parser, frame, &pod, &body);
398 }
399 
401  struct spa_pod_frame *frame, const struct spa_pod *pod, const void *body,
402  struct spa_pod_object *object, const void **object_body)
403 {
404  int res;
405  if (!spa_pod_is_object(pod))
406  return -EINVAL;
407  spa_pod_parser_init_pod_body(parser, pod, body);
408  if ((res = spa_pod_body_get_object(pod, body, object, object_body)) < 0)
409  return res;
410  spa_pod_parser_push(parser, frame, pod, parser->state.offset);
411  parser->state.offset += sizeof(struct spa_pod_object);
412  return 0;
413 }
414 
416  struct spa_pod_frame *frame, struct spa_pod_object *object, const void **object_body)
417 {
418  int res;
419  struct spa_pod pod;
420  const void *body;
421  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
422  return res;
423  if ((res = spa_pod_body_get_object(&pod, body, object, object_body)) < 0)
424  return res;
425  spa_pod_parser_push(parser, frame, &pod, parser->state.offset);
426  parser->state.offset += sizeof(struct spa_pod_object);
427  return 0;
428 }
430  struct spa_pod_frame *frame, uint32_t type, uint32_t *id)
431 {
432  int res;
433  struct spa_pod_object obj;
434  const void *obj_body;
435  if ((res = spa_pod_parser_push_object_body(parser, frame, &obj, &obj_body)) < 0)
436  return res;
437  if (type != obj.body.type) {
438  spa_pod_parser_unpush(parser, frame);
439  return -EPROTO;
440  }
441  if (id != NULL)
442  *id = obj.body.id;
443  return 0;
444 }
446  struct spa_pod_prop *prop, const void **body)
447 {
448  int res;
449  if ((res = spa_pod_parser_get_header(parser, prop,
450  sizeof(struct spa_pod_prop),
451  offsetof(struct spa_pod_prop, value), body)) >= 0)
453  return res;
454 }
455 
457  struct spa_pod_frame *frame, struct spa_pod_sequence *seq, const void **seq_body)
458 {
459  int res;
460  struct spa_pod pod;
461  const void *body;
462  if ((res = spa_pod_parser_current_body(parser, &pod, &body)) < 0)
463  return res;
464  if ((res = spa_pod_body_get_sequence(&pod, body, seq, seq_body)) < 0)
465  return res;
466  spa_pod_parser_push(parser, frame, &pod, parser->state.offset);
467  parser->state.offset += sizeof(struct spa_pod_sequence);
468  return 0;
469 }
470 
472  struct spa_pod_control *control, const void **body)
473 {
474  int res;
475  if ((res = spa_pod_parser_get_header(parser, control,
476  sizeof(struct spa_pod_control),
477  offsetof(struct spa_pod_control, value), body)) >= 0)
479  return res;
480 }
481 
483  uint32_t key, struct spa_pod_prop *prop, const void **body)
484 {
485  uint32_t start_offset;
486  struct spa_pod_frame *f = parser->state.frame;
487 
488  if (f == NULL || f->pod.type != SPA_TYPE_Object)
489  return -EINVAL;
490 
491  start_offset = f->offset;
492  while (spa_pod_parser_get_prop_body(parser, prop, body) >= 0) {
493  if (prop->key == key)
494  return 0;
495  }
496  spa_pod_parser_restart(parser, f);
497  parser->state.offset += sizeof(struct spa_pod_object);
498  while (parser->state.offset != start_offset &&
499  spa_pod_parser_get_prop_body(parser, prop, body) >= 0) {
500  if (prop->key == key)
501  return 0;
502  }
503  *body = NULL;
504  return -ENOENT;
505 }
506 
507 SPA_API_POD_PARSER bool spa_pod_parser_body_can_collect(const struct spa_pod *pod, const void *body, char type)
508 {
509  struct spa_pod_choice choice;
510 
511  if (pod == NULL)
512  return false;
513 
514  if (pod->type == SPA_TYPE_Choice) {
516  return false;
517  if (type == 'V' || type == 'W')
518  return true;
519  if (spa_pod_body_get_choice(pod, body, &choice, &body) < 0)
520  return false;
521  if (choice.body.type != SPA_CHOICE_None)
522  return false;
523  pod = &choice.body.child;
524  }
525 
526  switch (type) {
527  case 'P':
528  case 'Q':
529  return true;
530  case 'b':
531  return spa_pod_is_bool(pod);
532  case 'I':
533  return spa_pod_is_id(pod);
534  case 'i':
535  return spa_pod_is_int(pod);
536  case 'l':
537  return spa_pod_is_long(pod);
538  case 'f':
539  return spa_pod_is_float(pod);
540  case 'd':
541  return spa_pod_is_double(pod);
542  case 's':
544  case 'S':
545  return spa_pod_is_string(pod);
546  case 'y':
547  return spa_pod_is_bytes(pod);
548  case 'R':
549  return spa_pod_is_rectangle(pod);
550  case 'F':
551  return spa_pod_is_fraction(pod);
552  case 'B':
553  return spa_pod_is_bitmap(pod);
554  case 'a':
555  return spa_pod_is_array(pod);
556  case 'p':
557  return spa_pod_is_pointer(pod);
558  case 'h':
559  return spa_pod_is_fd(pod);
560  case 'T':
561  case 'U':
563  case 'N':
564  case 'O':
566  case 'V':
567  case 'W':
568  default:
569  return false;
570  }
571 }
572 SPA_API_POD_PARSER bool spa_pod_parser_can_collect(const struct spa_pod *pod, char type)
573 {
575 }
576 
577 #define SPA_POD_PARSER_COLLECT_BODY(_pod,_body,_type,args) \
578 ({ \
579  int res = 0; \
580  struct spa_pod_choice choice; \
581  const struct spa_pod *_p = _pod; \
582  const void *_b = _body; \
583  if (_p->type == SPA_TYPE_Choice && _type != 'V' && _type != 'W') { \
584  if (spa_pod_body_get_choice(_p, _b, &choice, &_b) >= 0 && \
585  choice.body.type == SPA_CHOICE_None) \
586  _p = &choice.body.child; \
587  } \
588  switch (_type) { \
589  case 'b': \
590  { \
591  bool *val = va_arg(args, bool*); \
592  res = spa_pod_body_get_bool(_p, _b, val); \
593  break; \
594  } \
595  case 'I': \
596  { \
597  uint32_t *val = va_arg(args, uint32_t*); \
598  res = spa_pod_body_get_id(_p, _b, val); \
599  break; \
600  } \
601  case 'i': \
602  { \
603  int32_t *val = va_arg(args, int32_t*); \
604  res = spa_pod_body_get_int(_p, _b, val); \
605  break; \
606  } \
607  case 'l': \
608  { \
609  int64_t *val = va_arg(args, int64_t*); \
610  res = spa_pod_body_get_long(_p, _b, val); \
611  break; \
612  } \
613  case 'f': \
614  { \
615  float *val = va_arg(args, float*); \
616  res = spa_pod_body_get_float(_p, _b, val); \
617  break; \
618  } \
619  case 'd': \
620  { \
621  double *val = va_arg(args, double*); \
622  res = spa_pod_body_get_double(_p, _b, val); \
623  break; \
624  } \
625  case 's': \
626  { \
627  const char **dest = va_arg(args, const char**); \
628  if (_p->type == SPA_TYPE_None) \
629  *dest = NULL; \
630  else \
631  res = spa_pod_body_get_string(_p, _b, dest); \
632  break; \
633  } \
634  case 'S': \
635  { \
636  char *dest = va_arg(args, char*); \
637  uint32_t maxlen = va_arg(args, uint32_t); \
638  res = spa_pod_body_copy_string(_p, _b, dest, maxlen); \
639  break; \
640  } \
641  case 'y': \
642  { \
643  const void **value = va_arg(args, const void**); \
644  uint32_t *len = va_arg(args, uint32_t*); \
645  res = spa_pod_body_get_bytes(_p, _b, value, len); \
646  break; \
647  } \
648  case 'R': \
649  { \
650  struct spa_rectangle *val = va_arg(args, struct spa_rectangle*); \
651  res = spa_pod_body_get_rectangle(_p, _b, val); \
652  break; \
653  } \
654  case 'F': \
655  { \
656  struct spa_fraction *val = va_arg(args, struct spa_fraction*); \
657  res = spa_pod_body_get_fraction(_p, _b, val); \
658  break; \
659  } \
660  case 'B': \
661  { \
662  const uint8_t **val = va_arg(args, const uint8_t**); \
663  res = spa_pod_body_get_bitmap(_p, _b, val); \
664  break; \
665  } \
666  case 'a': \
667  { \
668  uint32_t *val_size = va_arg(args, uint32_t*); \
669  uint32_t *val_type = va_arg(args, uint32_t*); \
670  uint32_t *n_values = va_arg(args, uint32_t*); \
671  const void **arr_body = va_arg(args, const void**); \
672  *arr_body = spa_pod_body_get_array_values(_p, _b, \
673  n_values, val_size, val_type); \
674  if (*arr_body == NULL) \
675  res = -EINVAL; \
676  break; \
677  } \
678  case 'p': \
679  { \
680  uint32_t *type = va_arg(args, uint32_t*); \
681  const void **value = va_arg(args, const void**); \
682  res = spa_pod_body_get_pointer(_p, _b, type, value); \
683  break; \
684  } \
685  case 'h': \
686  { \
687  int64_t *val = va_arg(args, int64_t*); \
688  res = spa_pod_body_get_fd(_p, _b, val); \
689  break; \
690  } \
691  default: \
692  { \
693  bool valid = false, do_body = false; \
694  switch (_type) { \
695  case 'Q': \
696  do_body = true; \
697  SPA_FALLTHROUGH; \
698  case 'P': \
699  valid = true; \
700  break; \
701  case 'U': \
702  do_body = true; \
703  SPA_FALLTHROUGH; \
704  case 'T': \
705  valid = spa_pod_is_struct(_p) || spa_pod_is_none(_p); \
706  break; \
707  case 'N': \
708  do_body = true; \
709  SPA_FALLTHROUGH; \
710  case 'O': \
711  valid = spa_pod_is_object(_p) || spa_pod_is_none(_p); \
712  break; \
713  case 'W': \
714  do_body = true; \
715  SPA_FALLTHROUGH; \
716  case 'V': \
717  valid = spa_pod_is_choice(_p) || spa_pod_is_none(_p); \
718  break; \
719  default: \
720  res = -EINVAL; \
721  break; \
722  } \
723  if (res >= 0 && do_body) { \
724  struct spa_pod *p = va_arg(args, struct spa_pod*); \
725  const void **v = va_arg(args, const void **); \
726  if (valid && p && v) { \
727  *p = *_p; \
728  *v = _b; \
729  } \
730  } else if (res >= 0) { \
731  const struct spa_pod **d = va_arg(args, const struct spa_pod**);\
732  if (valid && d) \
733  *d = (_p->type == SPA_TYPE_None) ? \
734  NULL : \
735  SPA_PTROFF((_b), -sizeof(struct spa_pod), \
736  const struct spa_pod); \
737  } \
738  if (!valid) \
739  res = -EINVAL; \
740  break; \
741  } \
742  } \
743  res; \
744 })
745 
746 #define SPA_POD_PARSER_COLLECT(pod,_type,args) \
747  SPA_POD_PARSER_COLLECT_BODY(pod, SPA_POD_BODY_CONST(pod),_type,args)
748 
749 #define SPA_POD_PARSER_SKIP(_type,args) \
750 do { \
751  switch (_type) { \
752  case 'S': \
753  va_arg(args, char*); \
754  va_arg(args, uint32_t); \
755  break; \
756  case 'a': \
757  va_arg(args, void*); \
758  va_arg(args, void*); \
759  SPA_FALLTHROUGH \
760  case 'p': \
761  case 'y': \
762  va_arg(args, void*); \
763  SPA_FALLTHROUGH \
764  case 'b': \
765  case 'I': \
766  case 'i': \
767  case 'l': \
768  case 'f': \
769  case 'd': \
770  case 's': \
771  case 'R': \
772  case 'F': \
773  case 'B': \
774  case 'h': \
775  case 'V': \
776  case 'P': \
777  case 'T': \
778  case 'O': \
779  case 'W': \
780  case 'Q': \
781  case 'U': \
782  case 'N': \
783  va_arg(args, void*); \
784  break; \
785  } \
786 } while(false)
787 
788 SPA_API_POD_PARSER int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args)
789 {
790  struct spa_pod_frame *f = parser->state.frame;
791  int count = 0;
792 
793  if (f == NULL)
794  return -EINVAL;
795 
796  do {
797  bool optional;
798  struct spa_pod pod = (struct spa_pod) { 0, SPA_TYPE_None };
799  const void *body = NULL;
800  const char *format;
801  struct spa_pod_prop prop;
802 
803  if (f->pod.type == SPA_TYPE_Object) {
804  uint32_t key = va_arg(args, uint32_t), *flags = NULL;
805 
806  if (key == 0)
807  break;
808  if (key == SPA_ID_INVALID) {
809  key = va_arg(args, uint32_t);
810  flags = va_arg(args, uint32_t*);
811  }
812  if (spa_pod_parser_object_find_prop(parser, key, &prop, &body) >= 0) {
813  pod = prop.value;
814  if (flags)
815  *flags = prop.flags;
816  }
817  }
818 
819  if ((format = va_arg(args, char *)) == NULL)
820  break;
821 
822  if (f->pod.type == SPA_TYPE_Struct)
823  spa_pod_parser_next_body(parser, &pod, &body);
824 
825  if ((optional = (*format == '?')))
826  format++;
827 
828  if (SPA_POD_PARSER_COLLECT_BODY(&pod, body, *format, args) >= 0) {
829  count++;
830  } else if (!optional) {
831  if (body == NULL)
832  return -ESRCH;
833  else
834  return -EPROTO;
835  }
836  } while (true);
837 
838  return count;
839 }
840 
842 {
843  int res;
844  va_list args;
845 
846  va_start(args, parser);
847  res = spa_pod_parser_getv(parser, args);
848  va_end(args);
849 
850  return res;
851 }
852 
853 #define SPA_POD_OPT_Bool(val) "?" SPA_POD_Bool(val)
854 #define SPA_POD_OPT_Id(val) "?" SPA_POD_Id(val)
855 #define SPA_POD_OPT_Int(val) "?" SPA_POD_Int(val)
856 #define SPA_POD_OPT_Long(val) "?" SPA_POD_Long(val)
857 #define SPA_POD_OPT_Float(val) "?" SPA_POD_Float(val)
858 #define SPA_POD_OPT_Double(val) "?" SPA_POD_Double(val)
859 #define SPA_POD_OPT_String(val) "?" SPA_POD_String(val)
860 #define SPA_POD_OPT_Stringn(val,len) "?" SPA_POD_Stringn(val,len)
861 #define SPA_POD_OPT_Bytes(val,len) "?" SPA_POD_Bytes(val,len)
862 #define SPA_POD_OPT_Rectangle(val) "?" SPA_POD_Rectangle(val)
863 #define SPA_POD_OPT_Fraction(val) "?" SPA_POD_Fraction(val)
864 #define SPA_POD_OPT_Array(csize,ctype,n_vals,vals) "?" SPA_POD_Array(csize,ctype,n_vals,vals)
865 #define SPA_POD_OPT_Pointer(type,val) "?" SPA_POD_Pointer(type,val)
866 #define SPA_POD_OPT_Fd(val) "?" SPA_POD_Fd(val)
867 #define SPA_POD_OPT_Pod(val) "?" SPA_POD_Pod(val)
868 #define SPA_POD_OPT_PodObject(val) "?" SPA_POD_PodObject(val)
869 #define SPA_POD_OPT_PodStruct(val) "?" SPA_POD_PodStruct(val)
870 #define SPA_POD_OPT_PodChoice(val) "?" SPA_POD_PodChoice(val)
871 #define SPA_POD_OPT_PodBody(val,body) "?" SPA_POD_PodBody(val,body)
872 #define SPA_POD_OPT_PodBodyObject(val,body) "?" SPA_POD_PodBodyObject(val,body)
873 #define SPA_POD_OPT_PodBodyStruct(val,body) "?" SPA_POD_PodBodyStruct(val,body)
874 #define SPA_POD_OPT_PodBodyChoice(val,body) "?" SPA_POD_PodBodyChoice(val,body)
875 
876 #define spa_pod_parser_get_object(p,type,id,...) \
877 ({ \
878  struct spa_pod_frame _f; \
879  int _res; \
880  if ((_res = spa_pod_parser_push_object(p, &_f, type, id)) == 0) { \
881  _res = spa_pod_parser_get(p,##__VA_ARGS__, 0); \
882  spa_pod_parser_pop(p, &_f); \
883  } \
884  _res; \
885 })
886 
887 #define spa_pod_parser_get_struct(p,...) \
888 ({ \
889  struct spa_pod_frame _f; \
890  int _res; \
891  if ((_res = spa_pod_parser_push_struct(p, &_f)) == 0) { \
892  _res = spa_pod_parser_get(p,##__VA_ARGS__, NULL); \
893  spa_pod_parser_pop(p, &_f); \
894  } \
895  _res; \
896 })
897 
898 #define spa_pod_body_parse_object(pod,body,type,id,...) \
899 ({ \
900  struct spa_pod_parser _p; \
901  spa_pod_parser_init_pod_body(&_p, pod, body); \
902  spa_pod_parser_get_object(&_p,type,id,##__VA_ARGS__); \
903 })
904 
905 #define spa_pod_parse_object(pod,type,id,...) \
906  spa_pod_body_parse_object(pod,SPA_POD_BODY_CONST(pod),type,id,##__VA_ARGS__)
907 
908 #define spa_pod_body_parse_struct(pod,body,...) \
909 ({ \
910  struct spa_pod_parser _p; \
911  spa_pod_parser_init_pod_body(&_p, pod, body); \
912  spa_pod_parser_get_struct(&_p,##__VA_ARGS__); \
913 })
914 
915 #define spa_pod_parse_struct(pod,...) \
916  spa_pod_body_parse_struct(pod,SPA_POD_BODY_CONST(pod),##__VA_ARGS__)
921 #ifdef __cplusplus
922 } /* extern "C" */
923 #endif
924 
925 #endif /* SPA_POD_PARSER_H */
spa/pod/body.h
uint32_t int int const char va_list args
Definition: core.h:434
va_end(args)
uint32_t int seq
Definition: core.h:432
uint32_t int int res
Definition: core.h:433
va_start(args, message)
SPA_API_POD_PARSER void spa_pod_parser_push(struct spa_pod_parser *parser, struct spa_pod_frame *frame, const struct spa_pod *pod, uint32_t offset)
Definition: parser.h:133
SPA_API_POD_PARSER int spa_pod_parser_get_long(struct spa_pod_parser *parser, int64_t *value)
Definition: parser.h:248
#define SPA_POD_PARSER_COLLECT_BODY(_pod, _body, _type, args)
Definition: parser.h:585
SPA_API_POD_PARSER void spa_pod_parser_init_from_data(struct spa_pod_parser *parser, const void *data, uint32_t maxsize, uint32_t offset, uint32_t size)
Definition: parser.h:73
SPA_API_POD_PARSER int spa_pod_parser_init_struct_body(struct spa_pod_parser *parser, struct spa_pod_frame *frame, const struct spa_pod *pod, const void *body)
Definition: parser.h:377
SPA_API_POD_BODY int spa_pod_is_pointer(const struct spa_pod *pod)
Definition: body.h:277
SPA_API_POD_PARSER int spa_pod_parser_get_int(struct spa_pod_parser *parser, int32_t *value)
Definition: parser.h:236
SPA_API_POD_BODY int spa_pod_is_bitmap(const struct spa_pod *pod)
Definition: body.h:340
SPA_API_POD_PARSER int spa_pod_parser_pop(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
Definition: parser.h:204
SPA_API_POD_BODY int spa_pod_is_fraction(const struct spa_pod *pod)
Definition: body.h:326
SPA_API_POD_PARSER void spa_pod_parser_pod(struct spa_pod_parser *parser, const struct spa_pod *pod)
Definition: parser.h:60
SPA_API_POD_BODY int spa_pod_body_get_pointer(const struct spa_pod *pod, const void *body, uint32_t *type, const void **value)
Definition: body.h:282
SPA_API_POD_PARSER int spa_pod_parser_push_sequence_body(struct spa_pod_parser *parser, struct spa_pod_frame *frame, struct spa_pod_sequence *seq, const void **seq_body)
Definition: parser.h:464
#define SPA_POD_BODY_CONST(pod)
Definition: pod.h:46
SPA_API_POD_PARSER bool spa_pod_parser_body_can_collect(const struct spa_pod *pod, const void *body, char type)
Definition: parser.h:515
SPA_API_POD_BODY int spa_pod_is_double(const struct spa_pod *pod)
Definition: body.h:216
SPA_API_POD_PARSER int spa_pod_parser_get_pointer(struct spa_pod_parser *parser, uint32_t *type, const void **value)
Definition: parser.h:308
SPA_API_POD_BODY int spa_pod_body_get_sequence(const struct spa_pod *pod, const void *body, struct spa_pod_sequence *seq, const void **seq_body)
Definition: body.h:448
SPA_API_POD_BODY int spa_pod_body_get_string(const struct spa_pod *pod, const void *body, const char **value)
Definition: body.h:236
SPA_API_POD_PARSER int spa_pod_parser_get_control_body(struct spa_pod_parser *parser, struct spa_pod_control *control, const void **body)
Definition: parser.h:479
SPA_API_POD_BODY int spa_pod_is_array(const struct spa_pod *pod)
Definition: body.h:353
SPA_API_POD_BODY int spa_pod_is_rectangle(const struct spa_pod *pod)
Definition: body.h:311
SPA_API_POD_PARSER int spa_pod_parser_get_fraction(struct spa_pod_parser *parser, struct spa_fraction *value)
Definition: parser.h:344
SPA_API_POD_BODY int spa_pod_is_struct(const struct spa_pod *pod)
Definition: body.h:423
SPA_API_POD_PARSER void spa_pod_parser_init_pod_body(struct spa_pod_parser *parser, const struct spa_pod *pod, const void *body)
Definition: parser.h:66
SPA_API_POD_BODY int spa_pod_is_int(const struct spa_pod *pod)
Definition: body.h:172
SPA_API_POD_PARSER struct spa_pod * spa_pod_parser_current(struct spa_pod_parser *parser)
Definition: parser.h:158
SPA_API_POD_PARSER void spa_pod_parser_advance(struct spa_pod_parser *parser, const struct spa_pod *pod)
Definition: parser.h:167
SPA_API_POD_BODY int spa_pod_is_fd(const struct spa_pod *pod)
Definition: body.h:295
SPA_API_POD_BODY int spa_pod_body_get_fraction(const struct spa_pod *pod, const void *body, struct spa_fraction *value)
Definition: body.h:330
SPA_API_POD_PARSER int spa_pod_parser_next_body(struct spa_pod_parser *parser, struct spa_pod *pod, const void **body)
Definition: parser.h:172
SPA_API_POD_BODY int spa_pod_is_none(const struct spa_pod *pod)
Definition: body.h:136
SPA_API_POD_PARSER int spa_pod_parser_init_object_body(struct spa_pod_parser *parser, struct spa_pod_frame *frame, const struct spa_pod *pod, const void *body, struct spa_pod_object *object, const void **object_body)
Definition: parser.h:408
SPA_API_POD_PARSER int spa_pod_parser_get_bytes(struct spa_pod_parser *parser, const void **value, uint32_t *len)
Definition: parser.h:296
SPA_API_POD_PARSER void spa_pod_parser_reset(struct spa_pod_parser *parser, struct spa_pod_parser_state *state)
Definition: parser.h:89
SPA_API_POD_PARSER int spa_pod_parser_get_prop_body(struct spa_pod_parser *parser, struct spa_pod_prop *prop, const void **body)
Definition: parser.h:453
SPA_API_POD_BODY int spa_pod_is_object(const struct spa_pod *pod)
Definition: body.h:428
SPA_API_POD_PARSER int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args)
Definition: parser.h:796
SPA_API_POD_PARSER int spa_pod_parser_read_header(struct spa_pod_parser *parser, uint32_t offset, uint32_t size, void *header, uint32_t header_size, uint32_t pod_offset, const void **body)
Definition: parser.h:95
SPA_API_POD_PARSER int spa_pod_parser_push_object(struct spa_pod_parser *parser, struct spa_pod_frame *frame, uint32_t type, uint32_t *id)
Definition: parser.h:437
SPA_API_POD_PARSER int spa_pod_parser_get_double(struct spa_pod_parser *parser, double *value)
Definition: parser.h:272
SPA_API_POD_BODY int spa_pod_is_bool(const struct spa_pod *pod)
Definition: body.h:141
SPA_API_POD_PARSER int spa_pod_parser_object_find_prop(struct spa_pod_parser *parser, uint32_t key, struct spa_pod_prop *prop, const void **body)
Definition: parser.h:490
SPA_API_POD_PARSER struct spa_pod * spa_pod_parser_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
Definition: parser.h:128
SPA_API_POD_BODY int spa_pod_is_id(const struct spa_pod *pod)
Definition: body.h:159
SPA_API_POD_PARSER bool spa_pod_parser_can_collect(const struct spa_pod *pod, char type)
Definition: parser.h:580
SPA_API_POD_PARSER int spa_pod_parser_get_fd(struct spa_pod_parser *parser, int64_t *value)
Definition: parser.h:320
SPA_API_POD_PARSER void spa_pod_parser_unpush(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
Definition: parser.h:197
SPA_API_POD_PARSER int spa_pod_parser_push_object_body(struct spa_pod_parser *parser, struct spa_pod_frame *frame, struct spa_pod_object *object, const void **object_body)
Definition: parser.h:423
SPA_API_POD_PARSER int spa_pod_parser_get_bool(struct spa_pod_parser *parser, bool *value)
Definition: parser.h:212
SPA_API_POD_PARSER int spa_pod_parser_get_pod(struct spa_pod_parser *parser, struct spa_pod **value)
Definition: parser.h:366
SPA_API_POD_PARSER int spa_pod_parser_push_struct(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
Definition: parser.h:400
SPA_API_POD_BODY int spa_pod_body_get_double(const struct spa_pod *pod, const void *body, double *value)
Definition: body.h:221
#define SPA_POD_CONTROL_SIZE(ev)
Definition: pod.h:254
SPA_API_POD_PARSER int spa_pod_parser_get_float(struct spa_pod_parser *parser, float *value)
Definition: parser.h:260
SPA_API_POD_PARSER struct spa_pod * spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t size)
Definition: parser.h:119
#define SPA_POD_PROP_SIZE(prop)
Definition: pod.h:224
SPA_API_POD_BODY int spa_pod_body_get_long(const struct spa_pod *pod, const void *body, int64_t *value)
Definition: body.h:190
SPA_API_POD_BODY int spa_pod_body_get_object(const struct spa_pod *pod, const void *body, struct spa_pod_object *object, const void **object_body)
Definition: body.h:432
SPA_API_POD_PARSER void spa_pod_parser_get_state(struct spa_pod_parser *parser, struct spa_pod_parser_state *state)
Definition: parser.h:83
SPA_API_POD_BODY int spa_pod_is_bytes(const struct spa_pod *pod)
Definition: body.h:262
SPA_API_POD_BODY int spa_pod_body_get_int(const struct spa_pod *pod, const void *body, int32_t *value)
Definition: body.h:177
SPA_API_POD_PARSER int spa_pod_parser_get_string(struct spa_pod_parser *parser, const char **value)
Definition: parser.h:284
SPA_API_POD_BODY int spa_pod_is_string(const struct spa_pod *pod)
Definition: body.h:231
#define SPA_POD_PARSER_INIT(buffer, size)
Definition: parser.h:52
SPA_API_POD_PARSER int spa_pod_parser_current_body(struct spa_pod_parser *parser, struct spa_pod *pod, const void **body)
Definition: parser.h:152
SPA_API_POD_PARSER int spa_pod_parser_get_header(struct spa_pod_parser *parser, void *header, uint32_t header_size, uint32_t pod_offset, const void **body)
Definition: parser.h:143
SPA_API_POD_PARSER int spa_pod_parser_get(struct spa_pod_parser *parser,...)
Definition: parser.h:849
SPA_API_POD_BODY int spa_pod_body_get_float(const struct spa_pod *pod, const void *body, float *value)
Definition: body.h:206
SPA_API_POD_BODY int spa_pod_body_get_rectangle(const struct spa_pod *pod, const void *body, struct spa_rectangle *value)
Definition: body.h:316
SPA_API_POD_BODY int spa_pod_body_get_bool(const struct spa_pod *pod, const void *body, bool *value)
Definition: body.h:151
SPA_API_POD_PARSER void spa_pod_parser_init(struct spa_pod_parser *parser, const void *data, uint32_t size)
Definition: parser.h:54
SPA_API_POD_PARSER int spa_pod_parser_get_pod_body(struct spa_pod_parser *parser, struct spa_pod *value, const void **body)
Definition: parser.h:356
SPA_API_POD_PARSER int spa_pod_parser_get_rectangle(struct spa_pod_parser *parser, struct spa_rectangle *value)
Definition: parser.h:332
SPA_API_POD_PARSER struct spa_pod * spa_pod_parser_next(struct spa_pod_parser *parser)
Definition: parser.h:181
SPA_API_POD_PARSER int spa_pod_parser_push_struct_body(struct spa_pod_parser *parser, struct spa_pod_frame *frame, struct spa_pod *str, const void **str_body)
Definition: parser.h:388
#define SPA_POD_SIZE(pod)
Definition: pod.h:35
#define SPA_POD_ALIGN
Definition: pod.h:26
SPA_API_POD_BODY int spa_pod_body_get_choice(const struct spa_pod *pod, const void *body, struct spa_pod_choice *choice, const void **choice_body)
Definition: body.h:393
SPA_API_POD_PARSER int spa_pod_parser_get_id(struct spa_pod_parser *parser, uint32_t *value)
Definition: parser.h:224
SPA_API_POD_BODY int spa_pod_body_get_fd(const struct spa_pod *pod, const void *body, int64_t *value)
Definition: body.h:300
SPA_API_POD_BODY int spa_pod_is_choice(const struct spa_pod *pod)
Definition: body.h:389
SPA_API_POD_BODY int spa_pod_body_get_id(const struct spa_pod *pod, const void *body, uint32_t *value)
Definition: body.h:164
SPA_API_POD_BODY int spa_pod_is_float(const struct spa_pod *pod)
Definition: body.h:201
SPA_API_POD_PARSER void spa_pod_parser_restart(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
Definition: parser.h:191
SPA_API_POD_BODY int spa_pod_body_get_bytes(const struct spa_pod *pod, const void *body, const void **value, uint32_t *len)
Definition: body.h:267
SPA_API_POD_BODY int spa_pod_is_long(const struct spa_pod *pod)
Definition: body.h:185
@ SPA_CHOICE_None
no choice, first value is current
Definition: pod.h:161
@ SPA_TYPE_Object
Definition: type.h:56
@ SPA_TYPE_None
Definition: type.h:42
@ SPA_TYPE_Choice
Definition: type.h:60
@ SPA_TYPE_Struct
Definition: type.h:55
#define SPA_MIN(a, b)
Definition: defs.h:165
#define SPA_ROUND_UP_N(num, align)
Definition: defs.h:364
#define SPA_ID_INVALID
Definition: defs.h:250
#define SPA_BARRIER
Definition: defs.h:315
#define SPA_PTROFF(ptr_, offset_, type_)
Return the address (buffer + offset) as pointer of type.
Definition: defs.h:222
#define SPA_API_POD_PARSER
Definition: parser.h:29
Definition: defs.h:137
Definition: pod.h:176
struct spa_pod_choice_body body
Definition: pod.h:178
struct spa_pod pod
Definition: pod.h:177
Definition: pod.h:257
Definition: body.h:38
struct spa_pod pod
Definition: body.h:39
uint32_t offset
Definition: body.h:41
struct spa_pod_frame * parent
Definition: body.h:40
uint32_t flags
Definition: body.h:42
Definition: pod.h:202
struct spa_pod pod
Definition: pod.h:203
struct spa_pod_object_body body
Definition: pod.h:204
Definition: parser.h:38
uint32_t offset
Definition: parser.h:39
uint32_t flags
Definition: parser.h:40
struct spa_pod_frame * frame
Definition: parser.h:41
Definition: parser.h:44
uint32_t size
Definition: parser.h:46
struct spa_pod_parser_state state
Definition: parser.h:48
const void * data
Definition: parser.h:45
uint32_t _padding
Definition: parser.h:47
Definition: pod.h:227
uint32_t key
key of property, list of valid keys depends on the object type
Definition: pod.h:228
uint32_t flags
flags for property
Definition: pod.h:248
struct spa_pod value
Definition: pod.h:249
a sequence of timed controls
Definition: pod.h:271
struct spa_pod_sequence_body body
Definition: pod.h:273
Definition: pod.h:186
Definition: pod.h:57
uint32_t type
Definition: pod.h:59
uint32_t size
Definition: pod.h:58
Definition: defs.h:116
spa/pod/vararg.h