# HG changeset patch # User Mike Becker # Date 1727889100 -7200 # Node ID 109567325fe7a8b9a728475e09cea357852e44a2 # Parent 793fe631e87753cea697f59ca992a6a7583213cb add functions to link/unlink nodes manually relates to #166 diff -r 793fe631e877 -r 109567325fe7 src/cx/tree.h --- a/src/cx/tree.h Mon Sep 30 19:19:44 2024 +0200 +++ b/src/cx/tree.h Wed Oct 02 19:11:40 2024 +0200 @@ -794,6 +794,16 @@ offsetof(struct cx_tree_node_base_s, next) /** + * Macro for obtaining the node pointer layout for a specific tree. + */ +#define cx_tree_node_layout(tree) \ + (tree)->loc_parent,\ + (tree)->loc_children,\ + (tree)->loc_last_child,\ + (tree)->loc_prev, \ + (tree)->loc_next + +/** * The class definition for arbitrary trees. */ struct cx_tree_class_s { @@ -1099,6 +1109,68 @@ return tree->cl->visitor(tree); } +/** + * Adds a new node to the tree. + * + * \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). + * + * @param tree the tree + * @param parent the parent of the node to add + * @param child the node to add + */ +__attribute__((__nonnull__)) +static inline void cxTreeAddChildNode( + CxTree *tree, + void *parent, + void *child) { + cx_tree_link(parent, child, cx_tree_node_layout(tree)); + tree->size++; +} + +/** + * Creates a new node and adds it to the tree. + * + * With this function you can decide where exactly the new node shall be added. + * If you specified an appropriate search function, you may want to consider + * leaving this task to the tree by using #cxTreeInsert(). + * + * Be aware that adding nodes at arbitrary locations in the tree might cause + * wrong or undesired results when subsequently invoking #cxTreeInsert() and + * the invariant imposed by the search function does not hold any longer. + * + * @param tree the tree + * @param parent the parent node of the new node + * @param data the data that will be submitted to the create function + * @return zero when the new node was created, non-zero on allocation failure + * @see cxTreeInsert() + */ +__attribute__((__nonnull__)) +int cxTreeAddChild( + CxTree *tree, + void *parent, + const void *data +); + +/** + * Removes a node from the tree. + * + * If the node is not part of the tree, the behavior is undefined. + * + * \note The destructor function, if any, will \em not be invoked. + * + * @param tree the tree + * @param node the node to remove + */ +__attribute__((__nonnull__)) +static inline void cxTreeRemove( + CxTree *tree, + void *node) { + cx_tree_unlink(node, cx_tree_node_layout(tree)); + tree->size--; +} + #ifdef __cplusplus } // extern "C" #endif diff -r 793fe631e877 -r 109567325fe7 src/tree.c --- a/src/tree.c Mon Sep 30 19:19:44 2024 +0200 +++ b/src/tree.c Wed Oct 02 19:11:40 2024 +0200 @@ -666,3 +666,15 @@ loc_prev, loc_next); } + +int cxTreeAddChild( + CxTree *tree, + void *parent, + const void *data) { + void *node = tree->node_create(data, tree); + if (node == NULL) return 1; + cx_tree_zero_pointers(node, cx_tree_node_layout(tree)); + cx_tree_link(parent, node, cx_tree_node_layout(tree)); + tree->size++; + return 0; +}