commit 43586db89f5b69a8463a76c54106e3616ff660ef
parent 0cbd04e7dd94dee74ffe7458f0ae4f9ff817699e
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Thu, 17 Nov 2016 14:08:27 +0100
Add node_search_tree API and test.
Diffstat:
4 files changed, 126 insertions(+), 0 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -98,6 +98,7 @@ if(NOT NO_TEST)
new_test(test_sanim_node)
new_test(test_sanim_node_transform)
new_test(test_sanim_node_pivot)
+ new_test(test_sanim_search)
new_test(test_sanim_visit)
endif()
diff --git a/src/sanim.h b/src/sanim.h
@@ -178,6 +178,16 @@ sanim_node_visit_tree
res_T (*visitor)(
const struct sanim_node* n, const double transform[12], void* data));
+/* Visit the (sub)tree starting at node and call cmp on the nodes
+ * Stop if found is set to non-zero or if a call to cmp return is not RES_OK */
+SANIM_API res_T
+sanim_node_search_tree
+ (const struct sanim_node* node,
+ void* data,
+ res_T(*cmp)(
+ const struct sanim_node* n, void* data, int* found),
+ int* found);
+
SANIM_API res_T
sanim_node_track_me
(const struct sanim_node* node,
diff --git a/src/sanim_node.c b/src/sanim_node.c
@@ -1055,6 +1055,32 @@ sanim_node_visit_tree
}
res_T
+sanim_node_search_tree
+ (const struct sanim_node* node,
+ void* data,
+ res_T(*cmp)(
+ const struct sanim_node* n, void* data, int* found),
+ int* found)
+{
+ size_t count, i;
+ struct sanim_node* const* children;
+ res_T res = RES_OK;
+ if (!node || !node->data || !cmp || !found) return RES_BAD_ARG;
+
+ res = cmp(node, data, found);
+ if (*found || res != RES_OK) return res;
+
+ count = darray_children_size_get(&node->data->children);
+ children = darray_children_data_get(&node->data->children);
+ for (i = 0; i < count; i++) {
+ struct sanim_node* child = children[i];
+ res = sanim_node_search_tree(child, data, cmp, found);
+ if (*found || res != RES_OK) return res;
+ }
+ return RES_OK;
+}
+
+res_T
sanim_node_track_me
(const struct sanim_node* node,
struct sanim_tracking* tracking)
diff --git a/src/test_sanim_search.c b/src/test_sanim_search.c
@@ -0,0 +1,89 @@
+
+/* Copyright (C) CNRS 2016
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "sanim.h"
+#include "test_sanim_utils.h"
+
+#include <rsys/double33.h>
+
+struct data {
+ struct my_type * result;
+};
+
+static res_T
+search(const struct sanim_node* n, void* data_, int* found)
+{
+ int pivot;
+ ASSERT(n && found);
+ if (!data_) return RES_BAD_ARG;
+ SANIM(node_is_pivot(n, &pivot));
+ if (pivot) {
+ struct my_type* node;
+ struct data* data = data_;
+ node = CONTAINER_OF(n, struct my_type, node);
+ data->result = node;
+ *found = 1;
+ }
+ return RES_OK;
+}
+
+int
+main(int argc, char** argv)
+{
+ struct mem_allocator allocator;
+ struct my_type *t1, *t2, *t3;
+ struct sanim_pivot pivot = SANIM_PIVOT_NULL;
+ struct sanim_tracking tracking = SANIM_TRACKING_NULL;
+ struct data data;
+ int found = 0;
+ (void) argc, (void) argv;
+
+ mem_init_proxy_allocator(&allocator, &mem_default_allocator);
+
+ tracking.policy = TRACKING_SUN;
+ pivot.type = PIVOT_SINGLE_AXIS;
+ d3(pivot.data.pivot1.ref_normal, 0, 0, 1);
+
+ /* ref_normal not in the YZ plane */
+ CHECK(my_type_create(&allocator, &t1), RES_OK);
+ CHECK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2), RES_OK);
+ CHECK(my_type_create(&allocator, &t3), RES_OK);
+
+ CHECK(my_type_add_child(t1, t2), RES_OK);
+ CHECK(my_type_add_child(t2, t3), RES_OK);
+
+ data.result = NULL;
+
+ CHECK(sanim_node_search_tree(NULL, &data, search, &found), RES_BAD_ARG);
+ CHECK(sanim_node_search_tree(&t1->node, NULL, search, &found), RES_BAD_ARG);
+ CHECK(sanim_node_search_tree(&t1->node, &data, NULL, &found), RES_BAD_ARG);
+ CHECK(sanim_node_search_tree(&t1->node, &data, search, NULL), RES_BAD_ARG);
+ CHECK(sanim_node_search_tree(&t1->node, &data, search, &found), RES_OK);
+ CHECK(data.result, t2);
+
+ data.result = NULL;
+ CHECK(sanim_node_search_tree(&t3->node, &data, search, &found), RES_OK);
+ CHECK(data.result, NULL);
+
+ /* release memory */
+ CHECK(my_type_ref_put(t1), RES_OK);
+ CHECK(my_type_ref_put(t2), RES_OK);
+ CHECK(my_type_ref_put(t3), RES_OK);
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHECK(mem_allocated_size(), 0);
+ return 0;
+}