summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2020-08-05 20:25:24 +0200
committerWim Taymans <wtaymans@redhat.com>2020-09-17 19:37:04 +0200
commitc651d9d469f2eff3921fd4fcf946b8c6eb517587 (patch)
tree32ac4d893c4a64806f2c174e1914eb002b24f008
parent7b96e9e8529f686da0f01202bde8d3a45ecf6d6e (diff)
tree: support iterating Structstree
-rw-r--r--src/tools/tree.c61
1 files changed, 60 insertions, 1 deletions
diff --git a/src/tools/tree.c b/src/tools/tree.c
index 6ccb0dcc..2316d989 100644
--- a/src/tools/tree.c
+++ b/src/tools/tree.c
@@ -567,6 +567,63 @@ static inline void ot_set_pod_array(struct ot_node *node, const struct spa_type_
node->extra[4].i = (size - sizeof(struct spa_pod_array_body)) / b->child.size;
}
+/* struct */
+static const struct spa_pod *find_nth_field(void *body, uint32_t size, uint32_t nth)
+{
+ const struct spa_pod *p;
+ SPA_POD_FOREACH(body, size, p)
+ if (nth-- == 0)
+ return p;
+ return NULL;
+}
+
+static int ot_pod_struct_iterate(struct ot_node *node, const struct ot_key *key, struct ot_node *sub)
+{
+ int32_t index, n_items = node->extra[4].i;
+ void *body = (void*)node->extra[1].p;
+ uint32_t size = node->extra[2].i;
+ const struct spa_type_info *info = node->extra[3].cp;
+ const struct spa_pod *p;
+ int res;
+
+ if ((index = key->index) < 0)
+ index += n_items;
+ if (index < 0 || index >= n_items)
+ return 0;
+ if ((p = find_nth_field(body, size, index)) == NULL)
+ return 0;
+
+ res = ot_pod_set_value(sub, info, key->index, NULL,
+ p->type,
+ SPA_POD_CONTENTS(struct spa_pod, p),
+ p->size);
+ sub->parent = node;
+ return res;
+}
+
+static inline void ot_set_pod_struct(struct ot_node *node, const struct spa_type_info *info,
+ int32_t x, const char *k, uint32_t type, void *body, uint32_t size)
+{
+ const struct spa_pod *p;
+ bool simple = true;
+
+ ot_set_array(node, x, k, ot_pod_struct_iterate);
+ node->extra[0].i = type;
+ node->extra[1].p = body;
+ node->extra[2].i = size;
+ node->extra[3].cp = info;
+ node->extra[4].i = 0;
+ SPA_POD_FOREACH(body, size, p) {
+ node->extra[4].i++;
+ if (p->type > SPA_TYPE_String)
+ simple = false;
+ }
+ if (node->extra[4].i < 3 && simple)
+ node->flags |= NODE_FLAG_FLAT;
+}
+
+/* pod array */
+
/* pod */
static int ot_pod_set_value(struct ot_node *node, const struct spa_type_info *info,
int32_t x, const char *k, uint32_t type, void *body, uint32_t size)
@@ -611,9 +668,11 @@ static int ot_pod_set_value(struct ot_node *node, const struct spa_type_info *in
case SPA_TYPE_Object:
ot_set_pod_object(node, x, k, type, body, size);
break;
+ case SPA_TYPE_Struct:
+ ot_set_pod_struct(node, info, x, k, type, body, size);
+ break;
case SPA_TYPE_Pointer:
case SPA_TYPE_Bitmap:
- case SPA_TYPE_Struct:
case SPA_TYPE_Sequence:
case SPA_TYPE_Bytes:
case SPA_TYPE_None: