PipeWire 1.5.84
Loading...
Searching...
No Matches
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
15extern "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
30
32 uint32_t offset;
33 uint32_t flags;
34 struct spa_pod_frame *frame;
35};
36
37struct 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}})
47 const void *data, uint32_t size)
49 *parser = SPA_POD_PARSER_INIT(data, size);
50}
51
53 const struct spa_pod *pod)
59 const struct spa_pod *pod, const void *body)
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}
76{
77 *state = parser->state;
78}
79
81spa_pod_parser_reset(struct spa_pod_parser *parser, struct spa_pod_parser_state *state)
82{
83 parser->state = *state;
84}
85
87spa_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)
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
111spa_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}
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;
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}
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}
159SPA_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}
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);
182
184 struct spa_pod_frame *frame)
185{
186 parser->state.offset = frame->offset;
187}
188
190 struct spa_pod_frame *frame)
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)
213 return res;
214}
215
216SPA_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)
225 return res;
226}
227
228SPA_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)
237 return res;
238}
239
240SPA_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)
249 return res;
250}
251
252SPA_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)
261 return res;
262}
263
264SPA_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)
273 return res;
274}
275
276SPA_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)
285 return res;
286}
287
288SPA_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)
297 return res;
298}
299
300SPA_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)
309 return res;
310}
311
312SPA_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)
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)
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)
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;
357
358SPA_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;
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
507SPA_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':
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}
572SPA_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) \
750do { \
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
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);
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})
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; \
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})
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__)
917/**
918 * \}
919 */
920
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_PARSER struct spa_pod * spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t size)
Definition parser.h:119
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_PARSER struct spa_pod * spa_pod_parser_next(struct spa_pod_parser *parser)
Definition parser.h:181
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 struct spa_pod * spa_pod_parser_current(struct spa_pod_parser *parser)
Definition parser.h:158
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 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_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_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame)
Definition parser.h:128
#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 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