diff options
author | Wim Taymans <wtaymans@redhat.com> | 2020-08-05 20:25:24 +0200 |
---|---|---|
committer | Wim Taymans <wtaymans@redhat.com> | 2020-09-17 19:37:04 +0200 |
commit | c651d9d469f2eff3921fd4fcf946b8c6eb517587 (patch) | |
tree | 32ac4d893c4a64806f2c174e1914eb002b24f008 | |
parent | 7b96e9e8529f686da0f01202bde8d3a45ecf6d6e (diff) |
tree: support iterating Structstree
-rw-r--r-- | src/tools/tree.c | 61 |
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: |