mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
pod-builder: make more generic builder
Make a vararg based builder that produces much smaller code. Catch demarshal errors. Simplify array handling
This commit is contained in:
parent
f92b68c3c3
commit
78a3cd61b8
9 changed files with 862 additions and 637 deletions
|
|
@ -39,6 +39,8 @@ typedef struct _SpaPODBuilder {
|
|||
uint32_t offset;
|
||||
SpaPODFrame *stack;
|
||||
uint32_t (*write) (struct _SpaPODBuilder *builder, uint32_t ref, const void *data, uint32_t size);
|
||||
bool in_array;
|
||||
bool first;
|
||||
} SpaPODBuilder;
|
||||
|
||||
#define SPA_POD_BUILDER_DEREF(b,ref,type) SPA_MEMBER ((b)->data, (ref), type)
|
||||
|
|
@ -54,23 +56,6 @@ spa_pod_builder_init (SpaPODBuilder *builder,
|
|||
builder->stack = NULL;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
spa_pod_builder_in_array (SpaPODBuilder *builder, bool *first)
|
||||
{
|
||||
SpaPODFrame *f;
|
||||
if ((f = builder->stack)) {
|
||||
if (f->pod.type == SPA_POD_TYPE_ARRAY) {
|
||||
*first = f->pod.size == 0;
|
||||
return true;
|
||||
}
|
||||
if (f->pod.type == SPA_POD_TYPE_PROP) {
|
||||
*first = f->pod.size == (sizeof (SpaPODPropBody) - sizeof(SpaPOD));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
spa_pod_builder_push (SpaPODBuilder *builder,
|
||||
SpaPODFrame *frame,
|
||||
|
|
@ -81,6 +66,8 @@ spa_pod_builder_push (SpaPODBuilder *builder,
|
|||
frame->pod = *pod;
|
||||
frame->ref = ref;
|
||||
builder->stack = frame;
|
||||
builder->in_array = builder->first = (pod->type == SPA_POD_TYPE_ARRAY ||
|
||||
pod->type == SPA_POD_TYPE_PROP);
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
|
@ -110,6 +97,8 @@ spa_pod_builder_pop (SpaPODBuilder *builder,
|
|||
memcpy (builder->data + frame->ref, &frame->pod, sizeof(SpaPOD));
|
||||
}
|
||||
builder->stack = frame->parent;
|
||||
builder->in_array = (builder->stack && (builder->stack->pod.type == SPA_POD_TYPE_ARRAY ||
|
||||
builder->stack->pod.type == SPA_POD_TYPE_PROP));
|
||||
spa_pod_builder_advance (builder, SPA_ROUND_UP_N(builder->offset, 8) - builder->offset, false);
|
||||
}
|
||||
|
||||
|
|
@ -143,29 +132,21 @@ spa_pod_builder_string_body (SpaPODBuilder *builder,
|
|||
return out;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
spa_pod_builder_pod (SpaPODBuilder *builder, uint32_t size, uint32_t type)
|
||||
{
|
||||
const SpaPOD p = { size, type };
|
||||
return spa_pod_builder_raw (builder, &p, sizeof (p), false);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
spa_pod_builder_primitive (SpaPODBuilder *builder, const SpaPOD *p)
|
||||
{
|
||||
const void *data;
|
||||
uint32_t size;
|
||||
bool in_array, first = false;
|
||||
|
||||
in_array = spa_pod_builder_in_array (builder, &first);
|
||||
if (in_array && !first) {
|
||||
if (builder->in_array && !builder->first) {
|
||||
data = SPA_POD_BODY_CONST (p);
|
||||
size = SPA_POD_BODY_SIZE (p);
|
||||
} else {
|
||||
data = p;
|
||||
size = SPA_POD_SIZE (p);
|
||||
builder->first = false;
|
||||
}
|
||||
return spa_pod_builder_raw (builder, data, size, !in_array);
|
||||
return spa_pod_builder_raw (builder, data, size, !builder->in_array);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
|
|
@ -348,12 +329,8 @@ spa_pod_builder_propv (SpaPODBuilder *builder,
|
|||
spa_pod_builder_double (builder, va_arg (args, double));
|
||||
break;
|
||||
case SPA_POD_TYPE_STRING:
|
||||
{
|
||||
const char *str = va_arg (args, char *);
|
||||
uint32_t len = va_arg (args, uint32_t);
|
||||
spa_pod_builder_string_len (builder, str, len);
|
||||
spa_pod_builder_string (builder, va_arg (args, char *));
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_RECTANGLE:
|
||||
{
|
||||
uint32_t width = va_arg (args, uint32_t), height = va_arg (args, uint32_t);
|
||||
|
|
@ -414,6 +391,122 @@ spa_pod_builder_prop (SpaPODBuilder *builder,
|
|||
va_end (args);
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_pod_builder_addv (SpaPODBuilder *builder,
|
||||
uint32_t type,
|
||||
va_list args)
|
||||
{
|
||||
uint32_t n_values = 0;
|
||||
while (type != 0) {
|
||||
switch (type) {
|
||||
case SPA_POD_TYPE_INVALID:
|
||||
break;
|
||||
case SPA_POD_TYPE_BOOL:
|
||||
spa_pod_builder_bool (builder, va_arg (args, int));
|
||||
break;
|
||||
case SPA_POD_TYPE_URI:
|
||||
spa_pod_builder_uri (builder, va_arg (args, int32_t));
|
||||
break;
|
||||
case SPA_POD_TYPE_INT:
|
||||
spa_pod_builder_int (builder, va_arg (args, int32_t));
|
||||
break;
|
||||
case SPA_POD_TYPE_LONG:
|
||||
spa_pod_builder_long (builder, va_arg (args, int64_t));
|
||||
break;
|
||||
case SPA_POD_TYPE_FLOAT:
|
||||
spa_pod_builder_float (builder, va_arg (args, double));
|
||||
break;
|
||||
case SPA_POD_TYPE_DOUBLE:
|
||||
spa_pod_builder_double (builder, va_arg (args, double));
|
||||
break;
|
||||
case SPA_POD_TYPE_STRING:
|
||||
spa_pod_builder_string (builder, va_arg (args, char *));
|
||||
break;
|
||||
case SPA_POD_TYPE_RECTANGLE:
|
||||
{
|
||||
uint32_t width = va_arg (args, uint32_t), height = va_arg (args, uint32_t);
|
||||
spa_pod_builder_rectangle (builder, width, height);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_FRACTION:
|
||||
{
|
||||
uint32_t num = va_arg (args, uint32_t), denom = va_arg (args, uint32_t);
|
||||
spa_pod_builder_fraction (builder, num, denom);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_BITMASK:
|
||||
break;
|
||||
case SPA_POD_TYPE_ARRAY:
|
||||
{
|
||||
SpaPODFrame *f = va_arg (args, SpaPODFrame *);
|
||||
spa_pod_builder_push_array (builder, f);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_STRUCT:
|
||||
{
|
||||
SpaPODFrame *f = va_arg (args, SpaPODFrame *);
|
||||
spa_pod_builder_push_struct (builder, f);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_OBJECT:
|
||||
{
|
||||
SpaPODFrame *f = va_arg (args, SpaPODFrame *);
|
||||
uint32_t id = va_arg (args, uint32_t);
|
||||
uint32_t type = va_arg (args, uint32_t);
|
||||
spa_pod_builder_push_object (builder, f, id, type);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_PROP:
|
||||
{
|
||||
SpaPODFrame *f = va_arg (args, SpaPODFrame *);
|
||||
uint32_t key = va_arg (args, uint32_t);
|
||||
uint32_t flags = va_arg (args, uint32_t);
|
||||
type = va_arg (args, uint32_t);
|
||||
n_values = va_arg (args, uint32_t);
|
||||
spa_pod_builder_push_prop (builder, f, key, flags);
|
||||
break;
|
||||
}
|
||||
case -SPA_POD_TYPE_ARRAY:
|
||||
case -SPA_POD_TYPE_STRUCT:
|
||||
case -SPA_POD_TYPE_OBJECT:
|
||||
case -SPA_POD_TYPE_PROP:
|
||||
{
|
||||
SpaPODFrame *f = va_arg (args, SpaPODFrame *);
|
||||
spa_pod_builder_pop (builder, f);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_BYTES:
|
||||
{
|
||||
void *value = va_arg (args, void *);
|
||||
uint32_t size = va_arg (args, uint32_t);
|
||||
spa_pod_builder_bytes (builder, value, size);
|
||||
break;
|
||||
}
|
||||
case SPA_POD_TYPE_POD:
|
||||
{
|
||||
SpaPOD *value = va_arg (args, SpaPOD *);
|
||||
spa_pod_builder_raw (builder, value, SPA_POD_SIZE (value), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n_values > 0)
|
||||
n_values--;
|
||||
else
|
||||
type = va_arg (args, uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_pod_builder_add (SpaPODBuilder *builder,
|
||||
uint32_t type, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start (args, type);
|
||||
spa_pod_builder_addv (builder, type, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -48,7 +48,8 @@ typedef enum {
|
|||
SPA_POD_TYPE_STRUCT,
|
||||
SPA_POD_TYPE_OBJECT,
|
||||
SPA_POD_TYPE_PROP,
|
||||
SPA_POD_TYPE_BYTES
|
||||
SPA_POD_TYPE_BYTES,
|
||||
SPA_POD_TYPE_POD
|
||||
} SpaPODType;
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -71,16 +72,6 @@ typedef struct {
|
|||
int32_t value;
|
||||
} SpaPODInt;
|
||||
|
||||
static inline bool
|
||||
spa_pod_get_int (SpaPOD **pod, int32_t *val)
|
||||
{
|
||||
if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_INT)
|
||||
return false;
|
||||
*val = ((SpaPODInt *)(*pod))->value;
|
||||
*pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef SpaPODInt SpaPODBool;
|
||||
typedef SpaPODInt SpaPODURI;
|
||||
|
||||
|
|
@ -89,16 +80,6 @@ typedef struct {
|
|||
int64_t value;
|
||||
} SpaPODLong;
|
||||
|
||||
static inline bool
|
||||
spa_pod_get_long (SpaPOD **pod, int64_t *val)
|
||||
{
|
||||
if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_LONG)
|
||||
return false;
|
||||
*val = ((SpaPODLong *)*pod)->value;
|
||||
*pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
SpaPOD pod;
|
||||
float value;
|
||||
|
|
@ -114,16 +95,6 @@ typedef struct {
|
|||
/* value here */
|
||||
} SpaPODString;
|
||||
|
||||
static inline bool
|
||||
spa_pod_get_string (SpaPOD **pod, const char **val)
|
||||
{
|
||||
if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_STRING)
|
||||
return false;
|
||||
*val = SPA_POD_CONTENTS (SpaPODString, *pod);
|
||||
*pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
SpaPOD pod;
|
||||
/* value here */
|
||||
|
|
@ -159,16 +130,6 @@ typedef struct {
|
|||
/* one or more SpaPOD follow */
|
||||
} SpaPODStruct;
|
||||
|
||||
static inline bool
|
||||
spa_pod_get_struct (SpaPOD **pod, SpaPOD **val)
|
||||
{
|
||||
if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_STRUCT)
|
||||
return false;
|
||||
*val = *pod;
|
||||
*pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t key;
|
||||
#define SPA_POD_PROP_RANGE_NONE 0
|
||||
|
|
@ -207,28 +168,6 @@ typedef struct {
|
|||
SpaPODObjectBody body;
|
||||
} SpaPODObject;
|
||||
|
||||
static inline bool
|
||||
spa_pod_get_object (SpaPOD **pod, const SpaPOD **val)
|
||||
{
|
||||
if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_OBJECT)
|
||||
return false;
|
||||
*val = *pod;
|
||||
*pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
spa_pod_get_bytes (SpaPOD **pod, const void **val, uint32_t *size)
|
||||
{
|
||||
if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_BYTES)
|
||||
return false;
|
||||
*val = SPA_POD_CONTENTS (SpaPODBytes, *pod);
|
||||
*size = SPA_POD_SIZE (*pod);
|
||||
*pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#define SPA_POD_ARRAY_BODY_FOREACH(body, _size, iter) \
|
||||
for ((iter) = SPA_MEMBER ((body), sizeof(SpaPODArrayBody), __typeof__(*(iter))); \
|
||||
(iter) < SPA_MEMBER ((body), (_size), __typeof__(*(iter))); \
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ static const struct _test_format {
|
|||
SPA_POD_TYPE_PROP } ,
|
||||
{ SPA_PROP_ID_VIDEO_SIZE, SPA_POD_PROP_RANGE_MIN_MAX | SPA_POD_PROP_FLAG_UNSET,
|
||||
{ sizeof (SpaRectangle), SPA_POD_TYPE_RECTANGLE } }, },
|
||||
{ { 320, 240 },
|
||||
{ { 320, 243 },
|
||||
{ 1, 1 },
|
||||
{ INT32_MAX, INT32_MAX } },
|
||||
|
||||
|
|
@ -125,8 +125,7 @@ main (int argc, char *argv[])
|
|||
SpaFormat *fmt;
|
||||
off_t o;
|
||||
|
||||
b.data = buffer;
|
||||
b.size = 1024;
|
||||
spa_pod_builder_init (&b, buffer, sizeof (buffer));
|
||||
|
||||
fmt = SPA_MEMBER (buffer, spa_pod_builder_push_format (&b, &frame[0],
|
||||
SPA_MEDIA_TYPE_VIDEO,
|
||||
|
|
@ -159,9 +158,7 @@ main (int argc, char *argv[])
|
|||
|
||||
spa_debug_pod (&fmt->pod);
|
||||
|
||||
memset (&b, 0, sizeof(b));
|
||||
b.data = buffer;
|
||||
b.size = 1024;
|
||||
spa_pod_builder_init (&b, buffer, sizeof (buffer));
|
||||
|
||||
o = spa_pod_builder_format (&b, SPA_MEDIA_TYPE_VIDEO, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_TYPE_INT,
|
||||
|
|
@ -171,7 +168,7 @@ main (int argc, char *argv[])
|
|||
SPA_VIDEO_FORMAT_I420,
|
||||
SPA_VIDEO_FORMAT_YUY2,
|
||||
SPA_PROP_ID_VIDEO_SIZE , SPA_POD_TYPE_RECTANGLE,
|
||||
320, 240,
|
||||
320, 241,
|
||||
SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
1, 1,
|
||||
|
|
@ -187,6 +184,44 @@ main (int argc, char *argv[])
|
|||
spa_debug_pod (&fmt->pod);
|
||||
spa_debug_format (fmt);
|
||||
|
||||
spa_pod_builder_init (&b, buffer, sizeof (buffer));
|
||||
|
||||
spa_pod_builder_add (&b,
|
||||
SPA_POD_TYPE_OBJECT, &frame[0], 0, 0,
|
||||
SPA_POD_TYPE_INT, SPA_MEDIA_TYPE_VIDEO,
|
||||
SPA_POD_TYPE_INT, SPA_MEDIA_SUBTYPE_RAW,
|
||||
SPA_POD_TYPE_PROP, &frame[1],
|
||||
SPA_PROP_ID_VIDEO_FORMAT, SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_POD_PROP_RANGE_ENUM,
|
||||
SPA_POD_TYPE_INT, 3,
|
||||
SPA_VIDEO_FORMAT_I420,
|
||||
SPA_VIDEO_FORMAT_I420,
|
||||
SPA_VIDEO_FORMAT_YUY2,
|
||||
-SPA_POD_TYPE_PROP, &frame[1],
|
||||
SPA_POD_TYPE_PROP, &frame[1],
|
||||
SPA_PROP_ID_VIDEO_SIZE, SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
SPA_POD_TYPE_RECTANGLE, 3,
|
||||
320, 242,
|
||||
1, 1,
|
||||
INT32_MAX, INT32_MAX,
|
||||
-SPA_POD_TYPE_PROP, &frame[1],
|
||||
SPA_POD_TYPE_PROP, &frame[1],
|
||||
SPA_PROP_ID_VIDEO_FRAMERATE, SPA_POD_PROP_FLAG_UNSET |
|
||||
SPA_POD_PROP_RANGE_MIN_MAX,
|
||||
SPA_POD_TYPE_FRACTION, 3,
|
||||
25, 1,
|
||||
0, 1,
|
||||
INT32_MAX, 1,
|
||||
-SPA_POD_TYPE_PROP, &frame[1],
|
||||
-SPA_POD_TYPE_OBJECT, &frame[0],
|
||||
0);
|
||||
spa_pod_builder_pop (&b, &frame[0]);
|
||||
|
||||
fmt = SPA_MEMBER (buffer, o, SpaFormat);
|
||||
spa_debug_pod (&fmt->pod);
|
||||
spa_debug_format (fmt);
|
||||
|
||||
spa_debug_pod (&test_format.fmt.pod);
|
||||
spa_debug_format (&test_format.fmt);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue