add cxTreeSetParent() default tip

Sun, 06 Oct 2024 19:17:41 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 06 Oct 2024 19:17:41 +0200
changeset 918
ec1f2015ec79
parent 917
ff8ad2c9e1bd

add cxTreeSetParent()

src/cx/tree.h file | annotate | diff | comparison | revisions
src/tree.c file | annotate | diff | comparison | revisions
tests/test_tree.c file | annotate | diff | comparison | revisions
--- a/src/cx/tree.h	Sun Oct 06 19:02:32 2024 +0200
+++ b/src/cx/tree.h	Sun Oct 06 19:17:41 2024 +0200
@@ -1157,8 +1157,29 @@
 }
 
 /**
+ * Sets the (new) parent of the specified child.
+ *
+ * If the \p child is not already member of the tree, this function behaves
+ * as #cxTreeAddChildNode().
+ *
+ * @param tree the tree
+ * @param parent the (new) parent of the child
+ * @param child the node to add
+ * @see cxTreeAddChildNode()
+ */
+__attribute__((__nonnull__))
+void cxTreeSetParent(
+        CxTree *tree,
+        void *parent,
+        void *child
+);
+
+/**
  * Adds a new node to the tree.
  *
+ * If the \p child is already member of the tree, the behavior is undefined.
+ * Use #cxTreeSetParent() if you want to move a subtree to another location.
+ *
  * \attention The node may be externally created, but MUST obey the same rules
  * as if it was created by the tree itself with #cxTreeAddChild() (e.g. use
  * the same allocator).
@@ -1166,15 +1187,14 @@
  * @param tree the tree
  * @param parent the parent of the node to add
  * @param child the node to add
+ * @see cxTreeSetParent()
  */
 __attribute__((__nonnull__))
-static inline void cxTreeAddChildNode(
+void cxTreeAddChildNode(
         CxTree *tree,
         void *parent,
-        void *child) {
-    cx_tree_link(parent, child, cx_tree_node_layout(tree));
-    tree->size++;
-}
+        void *child
+);
 
 /**
  * Creates a new node and adds it to the tree.
--- a/src/tree.c	Sun Oct 06 19:02:32 2024 +0200
+++ b/src/tree.c	Sun Oct 06 19:17:41 2024 +0200
@@ -823,6 +823,27 @@
     return tree;
 }
 
+void cxTreeSetParent(
+        CxTree *tree,
+        void *parent,
+        void *child
+) {
+    size_t loc_parent = tree->loc_parent;
+    if (tree_parent(child) == NULL) {
+        tree->size++;
+    }
+    cx_tree_link(parent, child, cx_tree_node_layout(tree));
+}
+
+void cxTreeAddChildNode(
+        CxTree *tree,
+        void *parent,
+        void *child
+) {
+    cx_tree_link(parent, child, cx_tree_node_layout(tree));
+    tree->size++;
+}
+
 int cxTreeAddChild(
         CxTree *tree,
         void *parent,
--- a/tests/test_tree.c	Sun Oct 06 19:02:32 2024 +0200
+++ b/tests/test_tree.c	Sun Oct 06 19:17:41 2024 +0200
@@ -1675,6 +1675,38 @@
     cxTreeDestroy(tree);
 }
 
+CX_TEST(test_tree_high_set_parent) {
+    tree_node root = {0}, child1 = {0}, child2 = {0}, child3 = {0};
+    CxTree *tree = cxTreeCreateWrapped(cxDefaultAllocator, &root, tree_node_layout);
+    CX_TEST_DO {
+        cxTreeSetParent(tree, &root, &child1);
+        cxTreeSetParent(tree, &root, &child2);
+        cxTreeSetParent(tree, &child1, &child3);
+        CX_TEST_ASSERT(cxTreeDepth(tree) == 3);
+        CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &root) == 3);
+        CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child1) == 2);
+        CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child2) == 1);
+        CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child3) == 1);
+
+        cxTreeSetParent(tree, &child2, &child3);
+        CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &root) == 3);
+        CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child1) == 1);
+        CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child2) == 2);
+        CX_TEST_ASSERT(cxTreeSubtreeDepth(tree, &child3) == 1);
+
+        CxTree *empty = cxTreeCreate(
+                cxDefaultAllocator,
+                tree_node_file_create_hl,
+                tree_node_file_search,
+                tree_node_file_search_data,
+                tree_node_file_layout
+        );
+        CX_TEST_ASSERT(cxTreeDepth(empty) == 0);
+        cxTreeDestroy(empty);
+    }
+    cxTreeDestroy(tree);
+}
+
 CX_TEST(test_tree_high_insert_one) {
     CxTestingAllocator talloc;
     cx_testing_allocator_init(&talloc);
@@ -2032,6 +2064,7 @@
     cx_test_register(suite, test_tree_high_create_simple);
     cx_test_register(suite, test_tree_high_create_wrapped);
     cx_test_register(suite, test_tree_high_tree_depth);
+    cx_test_register(suite, test_tree_high_set_parent);
     cx_test_register(suite, test_tree_high_insert_one);
     cx_test_register(suite, test_tree_high_insert_many);
     cx_test_register(suite, test_tree_high_add_find_remove_nodes);

mercurial