Loading...
Searching...
No Matches
simplify.h
Go to the documentation of this file.
/* Simple Plugin API */
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
/* SPDX-License-Identifier: MIT */
#ifndef SPA_POD_SIMPLIFY_H
#define SPA_POD_SIMPLIFY_H
#ifdef __cplusplus
extern "C" {
#endif
#include <errno.h>
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <spa/param/props.h>
#include <spa/pod/iter.h>
#include <spa/pod/builder.h>
#include <spa/pod/dynamic.h>
#include <spa/pod/compare.h>
#include <spa/debug/pod.h>
#ifndef SPA_API_POD_SIMPLIFY
#ifdef SPA_API_IMPL
#define SPA_API_POD_SIMPLIFY SPA_API_IMPL
#else
#define SPA_API_POD_SIMPLIFY static inline
#endif
#endif
SPA_API_POD_SIMPLIFY int
spa_pod_simplify_merge(struct spa_pod_builder *b, const struct spa_pod *pod1, const struct spa_pod *pod2)
{
const struct spa_pod_object *o1, *o2;
const struct spa_pod_prop *p1, *p2;
struct spa_pod_frame f[2];
int res = 0, count = 0;
if (!spa_pod_is_object(pod1) ||
!spa_pod_is_object(pod2))
return -ENOTSUP;
o1 = (const struct spa_pod_object*) pod1;
o2 = (const struct spa_pod_object*) pod2;
spa_pod_builder_push_object(b, &f[0], o1->body.type, o1->body.id);
p2 = NULL;
SPA_POD_OBJECT_FOREACH(o1, p1) {
p2 = spa_pod_object_find_prop(o2, p2, p1->key);
if (p2 == NULL)
goto error_enoent;
if (spa_pod_compare(&p1->value, &p2->value) == 0) {
spa_pod_builder_raw_padded(b, p1, SPA_POD_PROP_SIZE(p1));
}
else {
uint32_t i, n_vals1, n_vals2, choice1, choice2, size;
const struct spa_pod *vals1, *vals2;
void *alt1, *alt2, *a1, *a2;
count++;
if (count > 1)
goto error_einval;
vals1 = spa_pod_get_values(&p1->value, &n_vals1, &choice1);
vals2 = spa_pod_get_values(&p2->value, &n_vals2, &choice2);
if (vals1->type != vals2->type || n_vals1 < 1 || n_vals2 < 1)
goto error_einval;
size = vals1->size;
alt1 = SPA_POD_BODY(vals1);
alt2 = SPA_POD_BODY(vals2);
if ((choice1 == SPA_CHOICE_None && choice2 == SPA_CHOICE_None) ||
(choice1 == SPA_CHOICE_None && choice2 == SPA_CHOICE_Enum) ||
(choice1 == SPA_CHOICE_Enum && choice2 == SPA_CHOICE_None) ||
(choice1 == SPA_CHOICE_Enum && choice2 == SPA_CHOICE_Enum)) {
spa_pod_builder_prop(b, p1->key, p1->flags);
spa_pod_builder_push_choice(b, &f[1], SPA_CHOICE_Enum, 0);
spa_pod_builder_child(b, size, vals1->type);
for (i = 0, a1 = alt1; i < n_vals1; i++, a1 = SPA_PTROFF(a1,size,void)) {
if (i == 0 && n_vals1 == 1)
spa_pod_builder_raw(b, a1, size);
spa_pod_builder_raw(b, a1, size);
}
for (i = 0, a2 = alt2; i < n_vals2; i++, a2 = SPA_PTROFF(a2,size,void)) {
spa_pod_builder_raw(b, a2, size);
}
spa_pod_builder_pop(b, &f[1]);
} else {
goto error_einval;
}
}
}
p1 = NULL;
SPA_POD_OBJECT_FOREACH(o2, p2) {
p1 = spa_pod_object_find_prop(o1, p1, p2->key);
if (p1 == NULL)
goto error_enoent;
}
done:
spa_pod_builder_pop(b, &f[0]);
return res;
error_einval:
res = -EINVAL;
goto done;
error_enoent:
res = -ENOENT;
goto done;
}
SPA_API_POD_SIMPLIFY int
spa_pod_simplify_struct(struct spa_pod_builder *b, const struct spa_pod *pod, uint32_t pod_size)
{
struct spa_pod *p1 = NULL, *p2;
struct spa_pod_frame f;
struct spa_pod_builder_state state;
uint32_t p1offs;
spa_pod_builder_push_struct(b, &f);
SPA_POD_STRUCT_FOREACH(pod, p2) {
spa_pod_builder_get_state(b, &state);
if (p1 == NULL || spa_pod_simplify_merge(b, p1, p2) < 0) {
spa_pod_builder_reset(b, &state);
spa_pod_builder_raw_padded(b, p2, SPA_POD_SIZE(p2));
p1offs = state.offset;
p1 = SPA_PTROFF(b->data, p1offs, struct spa_pod);
} else {
void *pnew = SPA_PTROFF(b->data, state.offset, void);
p1 = SPA_PTROFF(b->data, p1offs, struct spa_pod);
spa_pod_builder_remove(b, SPA_POD_SIZE(p1));
memmove(p1, pnew, SPA_POD_SIZE(pnew));
}
}
spa_pod_builder_pop(b, &f);
return 0;
}
SPA_API_POD_SIMPLIFY int
spa_pod_simplify(struct spa_pod_builder *b, struct spa_pod **result, const struct spa_pod *pod)
{
int res = 0;
struct spa_pod_builder_state state;
spa_return_val_if_fail(pod != NULL, -EINVAL);
spa_return_val_if_fail(b != NULL, -EINVAL);
spa_pod_builder_get_state(b, &state);
if (!spa_pod_is_struct(pod)) {
res = spa_pod_builder_raw_padded(b, pod, SPA_POD_SIZE(pod));
} else {
struct spa_pod_dynamic_builder db;
spa_pod_dynamic_builder_continue(&db, b);
res = spa_pod_simplify_struct(&db.b, pod, SPA_POD_SIZE(pod));
if (res >= 0)
res = spa_pod_builder_raw_padded(b, db.b.data, db.b.state.offset);
spa_pod_dynamic_builder_clean(&db);
}
if (res >= 0 && result) {
*result = (struct spa_pod*)spa_pod_builder_deref(b, state.offset);
if (*result == NULL)
res = -ENOSPC;
}
return res;
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* SPA_POD_SIMPLIFY_H */
builder.h
spa/pod/builder.h
compare.h
spa/pod/compare.h
pod.h
spa/debug/pod.h
res
uint32_t int int res
Definition core.h:433
spa_pod_builder_pop
SPA_API_POD_BUILDER void * spa_pod_builder_pop(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
Definition builder.h:213
spa_pod_builder_push_choice
SPA_API_POD_BUILDER int spa_pod_builder_push_choice(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t type, uint32_t flags)
Definition builder.h:446
spa_pod_simplify_merge
SPA_API_POD_SIMPLIFY int spa_pod_simplify_merge(struct spa_pod_builder *b, const struct spa_pod *pod1, const struct spa_pod *pod2)
Definition simplify.h:46
spa_pod_compare
SPA_API_POD_COMPARE int spa_pod_compare(const struct spa_pod *pod1, const struct spa_pod *pod2)
Definition compare.h:97
spa_pod_builder_child
SPA_API_POD_BUILDER int spa_pod_builder_child(struct spa_pod_builder *builder, uint32_t size, uint32_t type)
Definition builder.h:268
spa_pod_get_values
SPA_API_POD_ITER struct spa_pod * spa_pod_get_values(const struct spa_pod *pod, uint32_t *n_vals, uint32_t *choice)
Definition iter.h:229
spa_pod_is_struct
SPA_API_POD_BODY int spa_pod_is_struct(const struct spa_pod *pod)
Definition body.h:423
spa_pod_builder_get_state
SPA_API_POD_BUILDER void spa_pod_builder_get_state(struct spa_pod_builder *builder, struct spa_pod_builder_state *state)
Definition builder.h:75
spa_pod_object_find_prop
SPA_API_POD_ITER const struct spa_pod_prop * spa_pod_object_find_prop(const struct spa_pod_object *pod, const struct spa_pod_prop *start, uint32_t key)
Definition iter.h:254
SPA_POD_OBJECT_FOREACH
#define SPA_POD_OBJECT_FOREACH(obj, iter)
Definition iter.h:118
SPA_POD_BODY
#define SPA_POD_BODY(pod)
Definition pod.h:44
spa_pod_is_object
SPA_API_POD_BODY int spa_pod_is_object(const struct spa_pod *pod)
Definition body.h:428
spa_pod_builder_push_struct
SPA_API_POD_BUILDER int spa_pod_builder_push_struct(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
Definition builder.h:462
spa_pod_builder_deref
SPA_API_POD_BUILDER struct spa_pod * spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t offset)
Definition builder.h:121
spa_pod_builder_push_object
SPA_API_POD_BUILDER int spa_pod_builder_push_object(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t type, uint32_t id)
Definition builder.h:475
spa_pod_builder_remove
SPA_API_POD_BUILDER void spa_pod_builder_remove(struct spa_pod_builder *builder, uint32_t size)
Definition builder.h:187
spa_pod_builder_reset
SPA_API_POD_BUILDER void spa_pod_builder_reset(struct spa_pod_builder *builder, struct spa_pod_builder_state *state)
Definition builder.h:93
spa_pod_simplify
SPA_API_POD_SIMPLIFY int spa_pod_simplify(struct spa_pod_builder *b, struct spa_pod **result, const struct spa_pod *pod)
Definition simplify.h:157
SPA_POD_STRUCT_FOREACH
#define SPA_POD_STRUCT_FOREACH(obj, iter)
Definition iter.h:110
SPA_POD_PROP_SIZE
#define SPA_POD_PROP_SIZE(prop)
Definition pod.h:224
spa_pod_builder_raw
SPA_API_POD_BUILDER int spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size)
Definition builder.h:150
spa_pod_builder_raw_padded
SPA_API_POD_BUILDER int spa_pod_builder_raw_padded(struct spa_pod_builder *builder, const void *data, uint32_t size)
Definition builder.h:205
spa_pod_simplify_struct
SPA_API_POD_SIMPLIFY int spa_pod_simplify_struct(struct spa_pod_builder *b, const struct spa_pod *pod, uint32_t pod_size)
Definition simplify.h:130
SPA_POD_SIZE
#define SPA_POD_SIZE(pod)
Definition pod.h:35
spa_pod_builder_prop
SPA_API_POD_BUILDER int spa_pod_builder_prop(struct spa_pod_builder *builder, uint32_t key, uint32_t flags)
Definition builder.h:490
SPA_CHOICE_None
@ SPA_CHOICE_None
no choice, first value is current
Definition pod.h:161
SPA_CHOICE_Enum
@ SPA_CHOICE_Enum
list: default, alternative,...
Definition pod.h:164
spa_return_val_if_fail
#define spa_return_val_if_fail(expr, val)
Definition defs.h:460
SPA_PTROFF
#define SPA_PTROFF(ptr_, offset_, type_)
Return the address (buffer + offset) as pointer of type.
Definition defs.h:222
iter.h
spa/pod/iter.h
props.h
SPA_API_POD_SIMPLIFY
#define SPA_API_POD_SIMPLIFY
Definition simplify.h:36
string.h
spa/utils/string.h
spa_pod_builder_state
Definition builder.h:42
spa_pod_builder
Definition builder.h:63
spa_pod_builder::data
void * data
Definition builder.h:64
spa_pod_dynamic_builder
Definition dynamic.h:29
spa_pod_dynamic_builder::b
struct spa_pod_builder b
Definition dynamic.h:30
spa_pod_frame
Definition body.h:38
spa_pod_object_body::type
uint32_t type
one of enum spa_type
Definition pod.h:197
spa_pod_object_body::id
uint32_t id
id of the object, depends on the object type
Definition pod.h:198
spa_pod_object
Definition pod.h:202
spa_pod_object::body
struct spa_pod_object_body body
Definition pod.h:204
spa_pod_prop
Definition pod.h:227
spa_pod_prop::key
uint32_t key
key of property, list of valid keys depends on the object type
Definition pod.h:228
spa_pod_prop::flags
uint32_t flags
flags for property
Definition pod.h:248
spa_pod_prop::value
struct spa_pod value
Definition pod.h:249
spa_pod
Definition pod.h:57
spa_pod::type
uint32_t type
Definition pod.h:59
spa_pod::size
uint32_t size
Definition pod.h:58