# HG changeset patch # User Mike Becker # Date 1728235061 -7200 # Node ID ec1f2015ec793fa654e375b8bc28a449d9fb03a1 # Parent ff8ad2c9e1bd4a76065d7fa7d1c7ae8cb0401fc9 add cxTreeSetParent() diff -r ff8ad2c9e1bd -r ec1f2015ec79 src/cx/tree.h --- 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. diff -r ff8ad2c9e1bd -r ec1f2015ec79 src/tree.c --- 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, diff -r ff8ad2c9e1bd -r ec1f2015ec79 tests/test_tree.c --- 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);