mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	pod: handle various ways of making empty array/choice
Make it possible to make empty array/choice Handle empty array/choice Add some tests to make empty arrays/choice objects
This commit is contained in:
		
							parent
							
								
									c913abffef
								
							
						
					
					
						commit
						ebf324590b
					
				
					 4 changed files with 83 additions and 4 deletions
				
			
		| 
						 | 
					@ -168,6 +168,10 @@ static inline void *spa_pod_builder_pop(struct spa_pod_builder *builder, struct
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct spa_pod *pod;
 | 
						struct spa_pod *pod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (SPA_FLAG_IS_SET(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST)) {
 | 
				
			||||||
 | 
							const struct spa_pod p = { 0, SPA_TYPE_None };
 | 
				
			||||||
 | 
							spa_pod_builder_raw(builder, &p, sizeof(p));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if ((pod = (struct spa_pod*)spa_pod_builder_frame(builder, frame)) != NULL)
 | 
						if ((pod = (struct spa_pod*)spa_pod_builder_frame(builder, frame)) != NULL)
 | 
				
			||||||
		*pod = frame->pod;
 | 
							*pod = frame->pod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -209,6 +213,13 @@ static inline int spa_pod_builder_none(struct spa_pod_builder *builder)
 | 
				
			||||||
	return spa_pod_builder_primitive(builder, &p);
 | 
						return spa_pod_builder_primitive(builder, &p);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int spa_pod_builder_child(struct spa_pod_builder *builder, uint32_t size, uint32_t type)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct spa_pod p = SPA_POD_INIT(size,type);
 | 
				
			||||||
 | 
						SPA_FLAG_CLEAR(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST);
 | 
				
			||||||
 | 
						return spa_pod_builder_raw(builder, &p, sizeof(p));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SPA_POD_INIT_Bool(val) (struct spa_pod_bool){ { sizeof(uint32_t), SPA_TYPE_Bool }, val ? 1 : 0, 0 }
 | 
					#define SPA_POD_INIT_Bool(val) (struct spa_pod_bool){ { sizeof(uint32_t), SPA_TYPE_Bool }, val ? 1 : 0, 0 }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int spa_pod_builder_bool(struct spa_pod_builder *builder, bool val)
 | 
					static inline int spa_pod_builder_bool(struct spa_pod_builder *builder, bool val)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -357,8 +357,9 @@ static inline int spa_pod_is_choice(const struct spa_pod *pod)
 | 
				
			||||||
static inline struct spa_pod *spa_pod_get_values(const struct spa_pod *pod, uint32_t *n_vals, uint32_t *choice)
 | 
					static inline struct spa_pod *spa_pod_get_values(const struct spa_pod *pod, uint32_t *n_vals, uint32_t *choice)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (pod->type == SPA_TYPE_Choice) {
 | 
						if (pod->type == SPA_TYPE_Choice) {
 | 
				
			||||||
		*choice = SPA_POD_CHOICE_TYPE(pod);
 | 
							*n_vals = SPA_POD_CHOICE_N_VALUES(pod);
 | 
				
			||||||
		*n_vals = *choice == SPA_CHOICE_None ? 1 : SPA_POD_CHOICE_N_VALUES(pod);
 | 
							if ((*choice = SPA_POD_CHOICE_TYPE(pod)) == SPA_CHOICE_None)
 | 
				
			||||||
 | 
								*n_vals = SPA_MIN(1u, SPA_POD_CHOICE_N_VALUES(pod));
 | 
				
			||||||
		return (struct spa_pod*)SPA_POD_CHOICE_CHILD(pod);
 | 
							return (struct spa_pod*)SPA_POD_CHOICE_CHILD(pod);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		*n_vals = 1;
 | 
							*n_vals = 1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -111,7 +111,7 @@ struct spa_pod_bitmap {
 | 
				
			||||||
#define SPA_POD_ARRAY_CHILD(arr)	(&((struct spa_pod_array*)(arr))->body.child)
 | 
					#define SPA_POD_ARRAY_CHILD(arr)	(&((struct spa_pod_array*)(arr))->body.child)
 | 
				
			||||||
#define SPA_POD_ARRAY_VALUE_TYPE(arr)	(SPA_POD_TYPE(SPA_POD_ARRAY_CHILD(arr)))
 | 
					#define SPA_POD_ARRAY_VALUE_TYPE(arr)	(SPA_POD_TYPE(SPA_POD_ARRAY_CHILD(arr)))
 | 
				
			||||||
#define SPA_POD_ARRAY_VALUE_SIZE(arr)	(SPA_POD_BODY_SIZE(SPA_POD_ARRAY_CHILD(arr)))
 | 
					#define SPA_POD_ARRAY_VALUE_SIZE(arr)	(SPA_POD_BODY_SIZE(SPA_POD_ARRAY_CHILD(arr)))
 | 
				
			||||||
#define SPA_POD_ARRAY_N_VALUES(arr)	((SPA_POD_BODY_SIZE(arr) - sizeof(struct spa_pod_array_body)) / SPA_POD_ARRAY_VALUE_SIZE(arr))
 | 
					#define SPA_POD_ARRAY_N_VALUES(arr)	(SPA_POD_ARRAY_VALUE_SIZE(arr) ? ((SPA_POD_BODY_SIZE(arr) - sizeof(struct spa_pod_array_body)) / SPA_POD_ARRAY_VALUE_SIZE(arr)) : 0)
 | 
				
			||||||
#define SPA_POD_ARRAY_VALUES(arr)	SPA_POD_CONTENTS(struct spa_pod_array, arr)
 | 
					#define SPA_POD_ARRAY_VALUES(arr)	SPA_POD_CONTENTS(struct spa_pod_array, arr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct spa_pod_array_body {
 | 
					struct spa_pod_array_body {
 | 
				
			||||||
| 
						 | 
					@ -129,7 +129,7 @@ struct spa_pod_array {
 | 
				
			||||||
#define SPA_POD_CHOICE_FLAGS(choice)		(((struct spa_pod_choice*)(choice))->body.flags)
 | 
					#define SPA_POD_CHOICE_FLAGS(choice)		(((struct spa_pod_choice*)(choice))->body.flags)
 | 
				
			||||||
#define SPA_POD_CHOICE_VALUE_TYPE(choice)	(SPA_POD_TYPE(SPA_POD_CHOICE_CHILD(choice)))
 | 
					#define SPA_POD_CHOICE_VALUE_TYPE(choice)	(SPA_POD_TYPE(SPA_POD_CHOICE_CHILD(choice)))
 | 
				
			||||||
#define SPA_POD_CHOICE_VALUE_SIZE(choice)	(SPA_POD_BODY_SIZE(SPA_POD_CHOICE_CHILD(choice)))
 | 
					#define SPA_POD_CHOICE_VALUE_SIZE(choice)	(SPA_POD_BODY_SIZE(SPA_POD_CHOICE_CHILD(choice)))
 | 
				
			||||||
#define SPA_POD_CHOICE_N_VALUES(choice)		((SPA_POD_BODY_SIZE(choice) - sizeof(struct spa_pod_choice_body)) / SPA_POD_CHOICE_VALUE_SIZE(choice))
 | 
					#define SPA_POD_CHOICE_N_VALUES(choice)		(SPA_POD_CHOICE_VALUE_SIZE(choice) ? ((SPA_POD_BODY_SIZE(choice) - sizeof(struct spa_pod_choice_body)) / SPA_POD_CHOICE_VALUE_SIZE(choice)) : 0)
 | 
				
			||||||
#define SPA_POD_CHOICE_VALUES(choice)		(SPA_POD_CONTENTS(struct spa_pod_choice, choice))
 | 
					#define SPA_POD_CHOICE_VALUES(choice)		(SPA_POD_CONTENTS(struct spa_pod_choice, choice))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum spa_choice_type {
 | 
					enum spa_choice_type {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -674,6 +674,72 @@ static void test_build(void)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_empty(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						uint8_t buffer[4096];
 | 
				
			||||||
 | 
						struct spa_pod_builder b;
 | 
				
			||||||
 | 
						struct spa_pod *array, *a2, *choice, *ch2;
 | 
				
			||||||
 | 
						struct spa_pod_frame f;
 | 
				
			||||||
 | 
						uint32_t n_vals, ch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* create empty arrays */
 | 
				
			||||||
 | 
						spa_pod_builder_init(&b, buffer, sizeof(buffer));
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_push_array(&b, &f) == 0);
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_child(&b, sizeof(uint32_t), SPA_TYPE_Id) == 0);
 | 
				
			||||||
 | 
						spa_assert((array = spa_pod_builder_pop(&b, &f)) != NULL);
 | 
				
			||||||
 | 
						spa_debug_mem(0, array, 16);
 | 
				
			||||||
 | 
						spa_assert(spa_pod_is_array(array));
 | 
				
			||||||
 | 
						spa_assert((a2 = spa_pod_get_array(array, &n_vals)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(n_vals == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_pod_builder_init(&b, buffer, sizeof(buffer));
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_push_array(&b, &f) == 0);
 | 
				
			||||||
 | 
						spa_assert((array = spa_pod_builder_pop(&b, &f)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(spa_pod_is_array(array));
 | 
				
			||||||
 | 
						spa_assert((a2 = spa_pod_get_array(array, &n_vals)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(n_vals == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_pod_builder_init(&b, buffer, sizeof(buffer));
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_push_array(&b, &f) == 0);
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_none(&b) == 0);
 | 
				
			||||||
 | 
						spa_assert((array = spa_pod_builder_pop(&b, &f)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(spa_pod_is_array(array));
 | 
				
			||||||
 | 
						spa_assert((a2 = spa_pod_get_array(array, &n_vals)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(n_vals == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_pod_builder_init(&b, buffer, sizeof(buffer));
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_array(&b, 4, SPA_TYPE_Id, 0, NULL) == 0);
 | 
				
			||||||
 | 
						array = (struct spa_pod*)buffer;
 | 
				
			||||||
 | 
						spa_assert(spa_pod_is_array(array));
 | 
				
			||||||
 | 
						spa_assert((a2 = spa_pod_get_array(array, &n_vals)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(n_vals == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* create empty choice */
 | 
				
			||||||
 | 
						spa_pod_builder_init(&b, buffer, sizeof(buffer));
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_push_choice(&b, &f, 0, 0) == 0);
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_child(&b, sizeof(uint32_t), SPA_TYPE_Id) == 0);
 | 
				
			||||||
 | 
						spa_assert((choice = spa_pod_builder_pop(&b, &f)) != NULL);
 | 
				
			||||||
 | 
						spa_debug_mem(0, choice, 32);
 | 
				
			||||||
 | 
						spa_assert(spa_pod_is_choice(choice));
 | 
				
			||||||
 | 
						spa_assert((ch2 = spa_pod_get_values(choice, &n_vals, &ch)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(n_vals == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_pod_builder_init(&b, buffer, sizeof(buffer));
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_push_choice(&b, &f, 0, 0) == 0);
 | 
				
			||||||
 | 
						spa_assert((choice = spa_pod_builder_pop(&b, &f)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(spa_pod_is_choice(choice));
 | 
				
			||||||
 | 
						spa_assert((ch2 = spa_pod_get_values(choice, &n_vals, &ch)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(n_vals == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_pod_builder_init(&b, buffer, sizeof(buffer));
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_push_choice(&b, &f, 0, 0) == 0);
 | 
				
			||||||
 | 
						spa_assert(spa_pod_builder_none(&b) == 0);
 | 
				
			||||||
 | 
						spa_assert((choice = spa_pod_builder_pop(&b, &f)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(spa_pod_is_choice(choice));
 | 
				
			||||||
 | 
						spa_assert((ch2 = spa_pod_get_values(choice, &n_vals, &ch)) != NULL);
 | 
				
			||||||
 | 
						spa_assert(n_vals == 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_varargs(void)
 | 
					static void test_varargs(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint8_t buffer[4096];
 | 
						uint8_t buffer[4096];
 | 
				
			||||||
| 
						 | 
					@ -1528,6 +1594,7 @@ int main(int argc, char *argv[])
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	test_abi();
 | 
						test_abi();
 | 
				
			||||||
	test_init();
 | 
						test_init();
 | 
				
			||||||
 | 
						test_empty();
 | 
				
			||||||
	test_build();
 | 
						test_build();
 | 
				
			||||||
	test_varargs();
 | 
						test_varargs();
 | 
				
			||||||
	test_varargs2();
 | 
						test_varargs2();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue