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