PipeWire  1.6.4
simplify.h
Go to the documentation of this file.
1 /* Simple Plugin API */
2 /* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
3 /* SPDX-License-Identifier: MIT */
4 
5 #ifndef SPA_POD_SIMPLIFY_H
6 #define SPA_POD_SIMPLIFY_H
7 
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 
12 #include <errno.h>
13 #include <stdint.h>
14 #include <stddef.h>
15 #include <stdio.h>
16 #include <string.h>
17 
18 #include <spa/param/props.h>
19 #include <spa/pod/iter.h>
20 #include <spa/pod/builder.h>
21 #include <spa/pod/dynamic.h>
22 #include <spa/pod/compare.h>
23 #include <spa/debug/pod.h>
24 
25 #ifndef SPA_API_POD_SIMPLIFY
26  #ifdef SPA_API_IMPL
27  #define SPA_API_POD_SIMPLIFY SPA_API_IMPL
28  #else
29  #define SPA_API_POD_SIMPLIFY static inline
30  #endif
31 #endif
32 
39 spa_pod_simplify_merge(struct spa_pod_builder *b, const struct spa_pod *pod1, const struct spa_pod *pod2)
40 {
41  const struct spa_pod_object *o1, *o2;
42  const struct spa_pod_prop *p1, *p2;
43  struct spa_pod_frame f[2];
44  int res = 0, count = 0;
45 
46  if (!spa_pod_is_object(pod1) ||
47  !spa_pod_is_object(pod2))
48  return -ENOTSUP;
49 
50  o1 = (const struct spa_pod_object*) pod1;
51  o2 = (const struct spa_pod_object*) pod2;
52 
53  spa_pod_builder_push_object(b, &f[0], o1->body.type, o1->body.id);
54  p2 = NULL;
55  SPA_POD_OBJECT_FOREACH(o1, p1) {
56  p2 = spa_pod_object_find_prop(o2, p2, p1->key);
57  if (p2 == NULL)
58  goto error_enoent;
59 
60  if (spa_pod_compare(&p1->value, &p2->value) == 0) {
62  }
63  else {
64  uint32_t i, n_vals1, n_vals2, choice1, choice2, size;
65  const struct spa_pod *vals1, *vals2;
66  void *alt1, *alt2, *a1, *a2;
67 
68  count++;
69  if (count > 1)
70  goto error_einval;
71 
72  vals1 = spa_pod_get_values(&p1->value, &n_vals1, &choice1);
73  vals2 = spa_pod_get_values(&p2->value, &n_vals2, &choice2);
74 
75  if (vals1->type != vals2->type || n_vals1 < 1 || n_vals2 < 1)
76  goto error_einval;
77 
78  size = vals1->size;
79 
80  alt1 = SPA_POD_BODY(vals1);
81  alt2 = SPA_POD_BODY(vals2);
82 
83  if ((choice1 == SPA_CHOICE_None && choice2 == SPA_CHOICE_None) ||
84  (choice1 == SPA_CHOICE_None && choice2 == SPA_CHOICE_Enum) ||
85  (choice1 == SPA_CHOICE_Enum && choice2 == SPA_CHOICE_None) ||
86  (choice1 == SPA_CHOICE_Enum && choice2 == SPA_CHOICE_Enum)) {
87  spa_pod_builder_prop(b, p1->key, p1->flags);
89  spa_pod_builder_child(b, size, vals1->type);
90  for (i = 0, a1 = alt1; i < n_vals1; i++, a1 = SPA_PTROFF(a1,size,void)) {
91  if (i == 0 && n_vals1 == 1)
92  spa_pod_builder_raw(b, a1, size);
93  spa_pod_builder_raw(b, a1, size);
94  }
95  for (i = 0, a2 = alt2; i < n_vals2; i++, a2 = SPA_PTROFF(a2,size,void)) {
96  spa_pod_builder_raw(b, a2, size);
97  }
98  spa_pod_builder_pop(b, &f[1]);
99  } else {
100  goto error_einval;
101  }
102  }
103  }
104  p1 = NULL;
105  SPA_POD_OBJECT_FOREACH(o2, p2) {
106  p1 = spa_pod_object_find_prop(o1, p1, p2->key);
107  if (p1 == NULL)
108  goto error_enoent;
109  }
110 done:
111  spa_pod_builder_pop(b, &f[0]);
112  return res;
113 
114 error_einval:
115  res = -EINVAL;
116  goto done;
117 error_enoent:
118  res = -ENOENT;
119  goto done;
120 }
121 
123 spa_pod_simplify_struct(struct spa_pod_builder *b, const struct spa_pod *pod, uint32_t pod_size)
124 {
125  struct spa_pod *p1 = NULL, *p2;
126  struct spa_pod_frame f;
127  struct spa_pod_builder_state state;
128  uint32_t p1offs;
129 
131  SPA_POD_STRUCT_FOREACH(pod, p2) {
132  spa_pod_builder_get_state(b, &state);
133  if (p1 == NULL || spa_pod_simplify_merge(b, p1, p2) < 0) {
134  spa_pod_builder_reset(b, &state);
136  p1offs = state.offset;
137  p1 = SPA_PTROFF(b->data, p1offs, struct spa_pod);
138  } else {
139  void *pnew = SPA_PTROFF(b->data, state.offset, void);
140  p1 = SPA_PTROFF(b->data, p1offs, struct spa_pod);
142  memmove(p1, pnew, SPA_POD_SIZE(pnew));
143  }
144  }
145  spa_pod_builder_pop(b, &f);
146  return 0;
147 }
148 
150 spa_pod_simplify(struct spa_pod_builder *b, struct spa_pod **result, const struct spa_pod *pod)
151 {
152  int res = 0;
153  struct spa_pod_builder_state state;
154 
155  spa_return_val_if_fail(pod != NULL, -EINVAL);
156  spa_return_val_if_fail(b != NULL, -EINVAL);
157 
158  spa_pod_builder_get_state(b, &state);
159 
160  if (!spa_pod_is_struct(pod)) {
162  } else {
163  struct spa_pod_dynamic_builder db;
164  spa_pod_dynamic_builder_continue(&db, b);
165  res = spa_pod_simplify_struct(&db.b, pod, SPA_POD_SIZE(pod));
166  if (res >= 0)
167  res = spa_pod_builder_raw_padded(b, db.b.data, db.b.state.offset);
168  spa_pod_dynamic_builder_clean(&db);
169  }
170 
171  if (res >= 0 && result) {
172  *result = (struct spa_pod*)spa_pod_builder_deref(b, state.offset);
173  if (*result == NULL)
174  res = -ENOSPC;
175  }
176  return res;
177 }
178 
183 #ifdef __cplusplus
184 } /* extern "C" */
185 #endif
186 
187 #endif /* SPA_POD_SIMPLIFY_H */
spa/pod/builder.h
spa/pod/compare.h
spa/debug/pod.h
uint32_t int int res
Definition: core.h:433
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_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_API_POD_COMPARE int spa_pod_compare(const struct spa_pod *pod1, const struct spa_pod *pod2)
Definition: compare.h:97
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_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_API_POD_BODY int spa_pod_is_struct(const struct spa_pod *pod)
Definition: body.h:423
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_API_POD_BUILDER struct spa_pod * spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t offset)
Definition: builder.h:121
#define SPA_POD_OBJECT_FOREACH(obj, iter)
Definition: iter.h:118
#define SPA_POD_BODY(pod)
Definition: pod.h:44
SPA_API_POD_BODY int spa_pod_is_object(const struct spa_pod *pod)
Definition: body.h:428
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_API_POD_BUILDER int spa_pod_builder_push_struct(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
Definition: builder.h:462
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_API_POD_BUILDER void spa_pod_builder_remove(struct spa_pod_builder *builder, uint32_t size)
Definition: builder.h:187
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_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
#define SPA_POD_STRUCT_FOREACH(obj, iter)
Definition: iter.h:110
#define SPA_POD_PROP_SIZE(prop)
Definition: pod.h:224
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_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_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_API_POD_BUILDER void * spa_pod_builder_pop(struct spa_pod_builder *builder, struct spa_pod_frame *frame)
Definition: builder.h:213
#define SPA_POD_SIZE(pod)
Definition: pod.h:35
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
no choice, first value is current
Definition: pod.h:161
@ SPA_CHOICE_Enum
list: default, alternative,...
Definition: pod.h:164
#define spa_return_val_if_fail(expr, val)
Definition: defs.h:460
#define SPA_PTROFF(ptr_, offset_, type_)
Return the address (buffer + offset) as pointer of type.
Definition: defs.h:222
spa/pod/iter.h
#define SPA_API_POD_SIMPLIFY
Definition: simplify.h:36
spa/utils/string.h
Definition: builder.h:42
Definition: builder.h:63
void * data
Definition: builder.h:64
Definition: dynamic.h:29
struct spa_pod_builder b
Definition: dynamic.h:30
Definition: body.h:38
uint32_t type
one of enum spa_type
Definition: pod.h:197
uint32_t id
id of the object, depends on the object type
Definition: pod.h:198
Definition: pod.h:202
struct spa_pod_object_body body
Definition: pod.h:204
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
Definition: pod.h:57
uint32_t type
Definition: pod.h:59
uint32_t size
Definition: pod.h:58