ucx/cx/tree.h

changeset 888
af685cc9d623
parent 854
1c8401ece69e
--- a/ucx/cx/tree.h	Sun Aug 31 14:39:13 2025 +0200
+++ b/ucx/cx/tree.h	Sat Nov 08 23:06:11 2025 +0100
@@ -49,12 +49,12 @@
  *
  * This iterator is not position-aware in a strict sense, as it does not assume
  * a particular order of elements in the tree. However, the iterator keeps track
- * of the number of nodes it has passed in a counter variable.
+ * of the number of nodes it has passed in a counter-variable.
  * Each node, regardless of the number of passes, is counted only once.
  *
  * @note Objects that are pointed to by an iterator are mutable through that
  * iterator. However, if the
- * underlying data structure is mutated by other means than this iterator (e.g.
+ * underlying data structure is mutated by other means than this iterator (e.g.,
  * elements added or removed), the iterator becomes invalid (regardless of what
  * cxIteratorValid() returns).
  *
@@ -71,7 +71,7 @@
     bool skip;
     /**
      * Set to true, when the iterator shall visit a node again
-     * when all it's children have been processed.
+     * when all its children have been processed.
      */
     bool visit_on_exit;
     /**
@@ -97,7 +97,7 @@
      */
     void *node;
     /**
-     * Stores a copy of the next pointer of the visited node.
+     * Stores a copy of the pointer to the successor of the visited node.
      * Allows freeing a node on exit without corrupting the iteration.
      */
     void *node_next;
@@ -120,6 +120,7 @@
         size_t stack_size;
         /**
          * The current depth in the tree.
+         * The node with which the iteration starts has depth 1.
          */
         size_t depth;
     };
@@ -135,6 +136,7 @@
     void *node;
     /**
      * The depth of the node.
+     * The first visited node has depth 1.
      */
     size_t depth;
     /**
@@ -153,12 +155,12 @@
  *
  * This iterator is not position-aware in a strict sense, as it does not assume
  * a particular order of elements in the tree. However, the iterator keeps track
- * of the number of nodes it has passed in a counter variable.
+ * of the number of nodes it has passed in a counter-variable.
  * Each node, regardless of the number of passes, is counted only once.
  *
  * @note Objects that are pointed to by an iterator are mutable through that
  * iterator. However, if the
- * underlying data structure is mutated by other means than this iterator (e.g.
+ * underlying data structure is mutated by other means than this iterator (e.g.,
  * elements added or removed), the iterator becomes invalid (regardless of what
  * cxIteratorValid() returns).
  *
@@ -210,24 +212,14 @@
  * @param iter the iterator
  */
 cx_attr_nonnull
-static inline void cxTreeIteratorDispose(CxTreeIterator *iter) {
-    free(iter->stack);
-    iter->stack = NULL;
-}
+CX_EXPORT void cxTreeIteratorDispose(CxTreeIterator *iter);
 
 /**
  * Releases internal memory of the given tree visitor.
  * @param visitor the visitor
  */
 cx_attr_nonnull
-static inline void cxTreeVisitorDispose(CxTreeVisitor *visitor) {
-    struct cx_tree_visitor_queue_s *q = visitor->queue_next;
-    while (q != NULL) {
-        struct cx_tree_visitor_queue_s *next = q->next;
-        free(q);
-        q = next;
-    }
-}
+CX_EXPORT void cxTreeVisitorDispose(CxTreeVisitor *visitor);
 
 /**
  * Advises the iterator to skip the subtree below the current node and
@@ -248,7 +240,7 @@
 /**
  * Links a node to a (new) parent.
  *
- * If the node has already a parent, it is unlinked, first.
+ * If the node already has a parent, it is unlinked, first.
  * If the parent has children already, the node is @em appended to the list
  * of all currently existing children.
  *
@@ -263,16 +255,9 @@
  * @see cx_tree_unlink()
  */
 cx_attr_nonnull
-cx_attr_export
-void cx_tree_link(
-        void *parent,
-        void *node,
-        ptrdiff_t loc_parent,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_last_child,
-        ptrdiff_t loc_prev,
-        ptrdiff_t loc_next
-);
+CX_EXPORT void cx_tree_link(void *parent, void *node,
+        ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child,
+        ptrdiff_t loc_prev, ptrdiff_t loc_next);
 
 /**
  * Unlinks a node from its parent.
@@ -289,15 +274,9 @@
  * @see cx_tree_link()
  */
 cx_attr_nonnull
-cx_attr_export
-void cx_tree_unlink(
-        void *node,
-        ptrdiff_t loc_parent,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_last_child,
-        ptrdiff_t loc_prev,
-        ptrdiff_t loc_next
-);
+CX_EXPORT void cx_tree_unlink(void *node,
+        ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child,
+        ptrdiff_t loc_prev, ptrdiff_t loc_next);
 
 /**
  * Macro that can be used instead of the magic value for infinite search depth.
@@ -316,8 +295,8 @@
  * Zero means exact match and a positive number is an implementation defined
  * measure for the distance to an exact match.
  *
- * For example if a tree stores file path information, a node that is
- * describing a parent directory of a filename that is searched, shall
+ * For example, consider a tree that stores file path information.
+ * A node which is describing a parent directory of a searched file shall
  * return a positive number to indicate that a child node might contain the
  * searched item. On the other hand, if the node denotes a path that is not a
  * prefix of the searched filename, the function would return -1 to indicate
@@ -328,9 +307,8 @@
  *
  * @return 0 if the node contains the data,
  * positive if one of the children might contain the data,
- * negative if neither the node, nor the children contains the data
+ * negative if neither the node nor the children contains the data
  */
-cx_attr_nonnull
 typedef int (*cx_tree_search_data_func)(const void *node, const void *data);
 
 
@@ -346,8 +324,8 @@
  * Zero means exact match and a positive number is an implementation defined
  * measure for the distance to an exact match.
  *
- * For example if a tree stores file path information, a node that is
- * describing a parent directory of a filename that is searched, shall
+ * For example, consider a tree that stores file path information.
+ * A node which is describing a parent directory of a searched file shall
  * return a positive number to indicate that a child node might contain the
  * searched item. On the other hand, if the node denotes a path that is not a
  * prefix of the searched filename, the function would return -1 to indicate
@@ -358,19 +336,18 @@
  *
  * @return 0 if @p node contains the same data as @p new_node,
  * positive if one of the children might contain the data,
- * negative if neither the node, nor the children contains the data
+ * negative if neither the node nor the children contains the data
  */
-cx_attr_nonnull
 typedef int (*cx_tree_search_func)(const void *node, const void *new_node);
 
 /**
  * Searches for data in a tree.
  *
- * When the data cannot be found exactly, the search function might return a
- * closest result which might be a good starting point for adding a new node
+ * When the data cannot be found exactly, the search function might return the
+ * closest result, which might be a good starting point for adding a new node
  * to the tree (see also #cx_tree_add()).
  *
- * Depending on the tree structure it is not necessarily guaranteed that the
+ * Depending on the tree structure, it is not necessarily guaranteed that the
  * "closest" match is uniquely defined. This function will search for a node
  * with the best match according to the @p sfunc (meaning: the return value of
  * @p sfunc which is closest to zero). If that is also ambiguous, an arbitrary
@@ -387,27 +364,19 @@
  * could contain the node (but doesn't right now), negative if the tree does not
  * contain any node that might be related to the searched data
  */
-cx_attr_nonnull
-cx_attr_access_w(5)
-cx_attr_export
-int cx_tree_search_data(
-        const void *root,
-        size_t depth,
-        const void *data,
-        cx_tree_search_data_func sfunc,
-        void **result,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_next
-);
+cx_attr_nonnull cx_attr_access_w(5)
+CX_EXPORT int cx_tree_search_data(const void *root, size_t depth,
+        const void *data, cx_tree_search_data_func sfunc,
+        void **result, ptrdiff_t loc_children, ptrdiff_t loc_next);
 
 /**
  * Searches for a node in a tree.
  *
  * When no node with the same data can be found, the search function might
- * return a closest result which might be a good starting point for adding the
+ * return the closest result, which might be a good starting point for adding the
  * new node to the tree (see also #cx_tree_add()).
  *
- * Depending on the tree structure it is not necessarily guaranteed that the
+ * Depending on the tree structure, it is not necessarily guaranteed that the
  * "closest" match is uniquely defined. This function will search for a node
  * with the best match according to the @p sfunc (meaning: the return value of
  * @p sfunc which is closest to zero). If that is also ambiguous, an arbitrary
@@ -424,24 +393,16 @@
  * could contain the node (but doesn't right now), negative if the tree does not
  * contain any node that might be related to the searched data
  */
-cx_attr_nonnull
-cx_attr_access_w(5)
-cx_attr_export
-int cx_tree_search(
-        const void *root,
-        size_t depth,
-        const void *node,
-        cx_tree_search_func sfunc,
-        void **result,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_next
-);
+cx_attr_nonnull cx_attr_access_w(5)
+CX_EXPORT int cx_tree_search(const void *root, size_t depth,
+        const void *node, cx_tree_search_func sfunc,
+        void **result, ptrdiff_t loc_children, ptrdiff_t loc_next);
 
 /**
  * Creates a depth-first iterator for a tree with the specified root node.
  *
  * @note A tree iterator needs to maintain a stack of visited nodes, which is
- * allocated using stdlib malloc().
+ * allocated using the cxDefaultAllocator.
  * When the iterator becomes invalid, this memory is automatically released.
  * However, if you wish to cancel the iteration before the iterator becomes
  * invalid by itself, you MUST call cxTreeIteratorDispose() manually to release
@@ -458,19 +419,14 @@
  * @see cxTreeIteratorDispose()
  */
 cx_attr_nodiscard
-cx_attr_export
-CxTreeIterator cx_tree_iterator(
-        void *root,
-        bool visit_on_exit,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_next
-);
+CX_EXPORT CxTreeIterator cx_tree_iterator(void *root, bool visit_on_exit,
+        ptrdiff_t loc_children, ptrdiff_t loc_next);
 
 /**
  * Creates a breadth-first iterator for a tree with the specified root node.
  *
- * @note A tree visitor needs to maintain a queue of to be visited nodes, which
- * is allocated using stdlib malloc().
+ * @note A tree visitor needs to maintain a queue of to-be visited nodes, which
+ * is allocated using the cxDefaultAllocator.
  * When the visitor becomes invalid, this memory is automatically released.
  * However, if you wish to cancel the iteration before the visitor becomes
  * invalid by itself, you MUST call cxTreeVisitorDispose() manually to release
@@ -485,24 +441,19 @@
  * @see cxTreeVisitorDispose()
  */
 cx_attr_nodiscard
-cx_attr_export
-CxTreeVisitor cx_tree_visitor(
-        void *root,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_next
-);
+CX_EXPORT CxTreeVisitor cx_tree_visitor(void *root,
+        ptrdiff_t loc_children, ptrdiff_t loc_next);
 
 /**
  * Describes a function that creates a tree node from the specified data.
- * The first argument points to the data the node shall contain and
- * the second argument may be used for additional data (e.g. an allocator).
+ * The first argument points to the data the node shall contain, and
+ * the second argument may be used for additional data (e.g., an allocator).
  * Functions of this type shall either return a new pointer to a newly
  * created node or @c NULL when allocation fails.
  *
  * @note the function may leave the node pointers in the struct uninitialized.
  * The caller is responsible to set them according to the intended use case.
  */
-cx_attr_nonnull_arg(1)
 typedef void *(*cx_tree_node_create_func)(const void *, void *);
 
 /**
@@ -511,8 +462,7 @@
  * This variable is used by #cx_tree_add_array() and #cx_tree_add_iter() to
  * implement optimized insertion of multiple elements into a tree.
  */
-cx_attr_export
-extern unsigned int cx_tree_add_look_around_depth;
+CX_EXPORT extern unsigned int cx_tree_add_look_around_depth;
 
 /**
  * Adds multiple elements efficiently to a tree.
@@ -552,23 +502,12 @@
  * @return the number of nodes created and added
  * @see cx_tree_add()
  */
-cx_attr_nonnull_arg(1, 3, 4, 6, 7)
-cx_attr_access_w(6)
-cx_attr_export
-size_t cx_tree_add_iter(
-        struct cx_iterator_base_s *iter,
-        size_t num,
-        cx_tree_search_func sfunc,
-        cx_tree_node_create_func cfunc,
-        void *cdata,
-        void **failed,
-        void *root,
-        ptrdiff_t loc_parent,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_last_child,
-        ptrdiff_t loc_prev,
-        ptrdiff_t loc_next
-);
+cx_attr_nonnull_arg(1, 3, 4, 6, 7) cx_attr_access_w(6)
+CX_EXPORT size_t cx_tree_add_iter(struct cx_iterator_base_s *iter, size_t num,
+        cx_tree_search_func sfunc, cx_tree_node_create_func cfunc,
+        void *cdata, void **failed, void *root,
+        ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child,
+        ptrdiff_t loc_prev, ptrdiff_t loc_next);
 
 /**
  * Adds multiple elements efficiently to a tree.
@@ -607,24 +546,12 @@
  * @return the number of array elements successfully processed
  * @see cx_tree_add()
  */
-cx_attr_nonnull_arg(1, 4, 5, 7, 8)
-cx_attr_access_w(7)
-cx_attr_export
-size_t cx_tree_add_array(
-        const void *src,
-        size_t num,
-        size_t elem_size,
-        cx_tree_search_func sfunc,
-        cx_tree_node_create_func cfunc,
-        void *cdata,
-        void **failed,
-        void *root,
-        ptrdiff_t loc_parent,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_last_child,
-        ptrdiff_t loc_prev,
-        ptrdiff_t loc_next
-);
+cx_attr_nonnull_arg(1, 4, 5, 7, 8) cx_attr_access_w(7)
+CX_EXPORT size_t cx_tree_add_array(const void *src, size_t num, size_t elem_size,
+        cx_tree_search_func sfunc, cx_tree_node_create_func cfunc,
+        void *cdata, void **failed, void *root,
+        ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child,
+        ptrdiff_t loc_prev, ptrdiff_t loc_next);
 
 /**
  * Adds data to a tree.
@@ -635,17 +562,17 @@
  * When a location is found, the @p cfunc will be invoked with @p cdata.
  *
  * The node returned by @p cfunc will be linked into the tree.
- * When @p sfunc returned a positive integer, the new node will be linked as a
+ * When @p sfunc returns a positive integer, the new node will be linked as a
  * child. The other children (now siblings of the new node) are then checked
  * with @p sfunc, whether they could be children of the new node and re-linked
  * accordingly.
  *
- * When @p sfunc returned zero and the found node has a parent, the new
- * node will be added as sibling - otherwise, the new node will be added
+ * When @p sfunc returns zero and the found node has a parent, the new
+ * node will be added as a sibling - otherwise, the new node will be added
  * as a child.
  *
- * When @p sfunc returned a negative value, the new node will not be added to
- * the tree and this function returns a non-zero value.
+ * When @p sfunc returns a negative value, the new node will not be added to
+ * the tree, and this function returns a non-zero value.
  * The caller should check if @p cnode contains a node pointer and deal with the
  * node that could not be added.
  *
@@ -671,22 +598,12 @@
  * @return zero when a new node was created and added to the tree,
  * non-zero otherwise
  */
-cx_attr_nonnull_arg(1, 2, 3, 5, 6)
-cx_attr_access_w(5)
-cx_attr_export
-int cx_tree_add(
-        const void *src,
-        cx_tree_search_func sfunc,
-        cx_tree_node_create_func cfunc,
-        void *cdata,
-        void **cnode,
-        void *root,
-        ptrdiff_t loc_parent,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_last_child,
-        ptrdiff_t loc_prev,
-        ptrdiff_t loc_next
-);
+cx_attr_nonnull_arg(1, 2, 3, 5, 6) cx_attr_access_w(5)
+CX_EXPORT int cx_tree_add(const void *src,
+        cx_tree_search_func sfunc, cx_tree_node_create_func cfunc,
+        void *cdata, void **cnode, void *root,
+        ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child,
+        ptrdiff_t loc_prev, ptrdiff_t loc_next);
 
 
 /**
@@ -745,9 +662,9 @@
      * A function to create new nodes.
      *
      * Invocations to this function will receive a pointer to this tree
-     * structure as second argument.
+     * structure as the second argument.
      *
-     * Nodes MAY use #cx_tree_node_base_s as base layout, but do not need to.
+     * Nodes MAY use #cx_tree_node_base_s as the base layout, but do not need to.
      */
     cx_tree_node_create_func node_create;
 
@@ -812,7 +729,7 @@
  * Macro to roll out the #cx_tree_node_base_s structure with a custom
  * node type.
  *
- * Must be used as first member in your custom tree struct.
+ * Must be used as the first member in your custom tree struct.
  *
  * @param type the data type for the nodes
  */
@@ -848,32 +765,20 @@
      * Implementations SHALL NOT simply invoke @p insert_many as this comes
      * with too much overhead.
      */
-    int (*insert_element)(
-            struct cx_tree_s *tree,
-            const void *data
-    );
+    int (*insert_element)(struct cx_tree_s *tree, const void *data);
 
     /**
      * Member function for inserting multiple elements.
      *
-     * Implementations SHALL avoid to perform a full search in the tree for
+     * Implementations SHALL avoid performing a full search in the tree for
      * every element even though the source data MAY be unsorted.
      */
-    size_t (*insert_many)(
-            struct cx_tree_s *tree,
-            struct cx_iterator_base_s *iter,
-            size_t n
-    );
+    size_t (*insert_many)(struct cx_tree_s *tree, struct cx_iterator_base_s *iter, size_t n);
 
     /**
      * Member function for finding a node.
      */
-    void *(*find)(
-            struct cx_tree_s *tree,
-            const void *subtree,
-            const void *data,
-            size_t depth
-    );
+    void *(*find)(struct cx_tree_s *tree, const void *subtree, const void *data, size_t depth);
 };
 
 /**
@@ -883,7 +788,7 @@
 
 
 /**
- * Destroys a node and it's subtree.
+ * Destroys a node and its subtree.
  *
  * It is guaranteed that the simple destructor is invoked before
  * the advanced destructor, starting with the leaf nodes of the subtree.
@@ -904,8 +809,7 @@
  * @see cxTreeFree()
  */
 cx_attr_nonnull
-cx_attr_export
-void cxTreeDestroySubtree(CxTree *tree, void *node);
+CX_EXPORT void cxTreeDestroySubtree(CxTree *tree, void *node);
 
 
 /**
@@ -919,7 +823,7 @@
  *
  * @attention Be careful when calling this function when no destructor function
  * is registered that actually frees the memory of nodes. In that case you will
- * need a reference to the (former) root node of the tree somewhere or
+ * need a reference to the (former) root node of the tree somewhere, or
  * otherwise you will be leaking memory.
  *
  * @param tree the tree
@@ -943,8 +847,7 @@
  *
  * @param tree the tree to free
  */
-cx_attr_export
-void cxTreeFree(CxTree *tree);
+CX_EXPORT void cxTreeFree(CxTree *tree);
 
 /**
  * Creates a new tree structure based on the specified layout.
@@ -956,7 +859,7 @@
  * will free the nodes with the allocator's free() method.
  *
  * @param allocator the allocator that shall be used
- * (if @c NULL, a default stdlib allocator will be used)
+ * (if @c NULL, the cxDefaultAllocator will be used)
  * @param create_func a function that creates new nodes
  * @param search_func a function that compares two nodes
  * @param search_data_func a function that compares a node with data
@@ -970,29 +873,18 @@
  * @see cxTreeCreateSimple()
  * @see cxTreeCreateWrapped()
  */
-cx_attr_nonnull_arg(2, 3, 4)
-cx_attr_nodiscard
-cx_attr_malloc
-cx_attr_dealloc(cxTreeFree, 1)
-cx_attr_export
-CxTree *cxTreeCreate(
-        const CxAllocator *allocator,
-        cx_tree_node_create_func create_func,
-        cx_tree_search_func search_func,
-        cx_tree_search_data_func search_data_func,
-        ptrdiff_t loc_parent,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_last_child,
-        ptrdiff_t loc_prev,
-        ptrdiff_t loc_next
-);
+cx_attr_nonnull_arg(2, 3, 4) cx_attr_nodiscard  cx_attr_malloc cx_attr_dealloc(cxTreeFree, 1)
+CX_EXPORT CxTree *cxTreeCreate(const CxAllocator *allocator, cx_tree_node_create_func create_func,
+        cx_tree_search_func search_func, cx_tree_search_data_func search_data_func,
+        ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child,
+        ptrdiff_t loc_prev, ptrdiff_t loc_next);
 
 /**
  * Creates a new tree structure based on a default layout.
  *
- * Nodes created by @p create_func MUST contain #cx_tree_node_base_s as first
+ * Nodes created by @p create_func MUST contain #cx_tree_node_base_s as the first
  * member (or at least respect the default offsets specified in the tree
- * struct) and they MUST be allocated with the specified allocator.
+ * struct), and they MUST be allocated with the specified allocator.
  *
  * @note This function will also register an advanced destructor which
  * will free the nodes with the allocator's free() method.
@@ -1004,10 +896,8 @@
  * @return (@c CxTree*) the new tree
  * @see cxTreeCreate()
  */
-#define cxTreeCreateSimple(\
-    allocator, create_func, search_func, search_data_func \
-) cxTreeCreate(allocator, create_func, search_func, search_data_func, \
-cx_tree_node_base_layout)
+#define cxTreeCreateSimple(allocator, create_func, search_func, search_data_func) \
+        cxTreeCreate(allocator, create_func, search_func, search_data_func, cx_tree_node_base_layout)
 
 /**
  * Creates a new tree structure based on an existing tree.
@@ -1017,10 +907,10 @@
  * @attention This function will create an incompletely defined tree structure
  * where neither the create function, the search function, nor a destructor
  * will be set. If you wish to use any of this functionality for the wrapped
- * tree, you need to specify those functions afterwards.
+ * tree, you need to specify those functions afterward.
  *
  * @param allocator the allocator that was used for nodes of the wrapped tree
- * (if @c NULL, a default stdlib allocator is assumed)
+ * (if @c NULL, the cxDefaultAllocator is assumed)
  * @param root the root node of the tree that shall be wrapped
  * @param loc_parent offset in the node struct for the parent pointer
  * @param loc_children offset in the node struct for the children linked list
@@ -1031,20 +921,10 @@
  * @return the new tree
  * @see cxTreeCreate()
  */
-cx_attr_nonnull_arg(2)
-cx_attr_nodiscard
-cx_attr_malloc
-cx_attr_dealloc(cxTreeFree, 1)
-cx_attr_export
-CxTree *cxTreeCreateWrapped(
-        const CxAllocator *allocator,
-        void *root,
-        ptrdiff_t loc_parent,
-        ptrdiff_t loc_children,
-        ptrdiff_t loc_last_child,
-        ptrdiff_t loc_prev,
-        ptrdiff_t loc_next
-);
+cx_attr_nonnull_arg(2) cx_attr_nodiscard  cx_attr_malloc  cx_attr_dealloc(cxTreeFree, 1)
+CX_EXPORT CxTree *cxTreeCreateWrapped(const CxAllocator *allocator, void *root,
+        ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child,
+        ptrdiff_t loc_prev, ptrdiff_t loc_next);
 
 /**
  * Inserts data into the tree.
@@ -1059,12 +939,7 @@
  * @retval non-zero failure
  */
 cx_attr_nonnull
-static inline int cxTreeInsert(
-        CxTree *tree,
-        const void *data
-) {
-    return tree->cl->insert_element(tree, data);
-}
+CX_EXPORT int cxTreeInsert(CxTree *tree, const void *data);
 
 /**
  * Inserts elements provided by an iterator efficiently into the tree.
@@ -1079,13 +954,7 @@
  * @return the number of elements that could be successfully inserted
  */
 cx_attr_nonnull
-static inline size_t cxTreeInsertIter(
-        CxTree *tree,
-        CxIteratorBase *iter,
-        size_t n
-) {
-    return tree->cl->insert_many(tree, iter, n);
-}
+CX_EXPORT size_t cxTreeInsertIter(CxTree *tree, CxIteratorBase *iter, size_t n);
 
 /**
  * Inserts an array of data efficiently into the tree.
@@ -1101,17 +970,7 @@
  * @return the number of elements that could be successfully inserted
  */
 cx_attr_nonnull
-static inline size_t cxTreeInsertArray(
-        CxTree *tree,
-        const void *data,
-        size_t elem_size,
-        size_t n
-) {
-    if (n == 0) return 0;
-    if (n == 1) return 0 == cxTreeInsert(tree, data) ? 1 : 0;
-    CxIterator iter = cxIterator(data, elem_size, n);
-    return cxTreeInsertIter(tree, cxIteratorRef(iter), n);
-}
+CX_EXPORT size_t cxTreeInsertArray(CxTree *tree, const void *data, size_t elem_size, size_t n);
 
 /**
  * Searches the data in the specified tree.
@@ -1124,14 +983,8 @@
  * @param data the data to search for
  * @return the first matching node, or @c NULL when the data cannot be found
  */
-cx_attr_nonnull
-cx_attr_nodiscard
-static inline void *cxTreeFind(
-        CxTree *tree,
-        const void *data
-) {
-    return tree->cl->find(tree, tree->root, data, 0);
-}
+cx_attr_nonnull cx_attr_nodiscard
+CX_EXPORT void *cxTreeFind(CxTree *tree, const void *data);
 
 /**
  * Searches the data in the specified subtree.
@@ -1152,16 +1005,8 @@
  * @param max_depth the maximum search depth
  * @return the first matching node, or @c NULL when the data cannot be found
  */
-cx_attr_nonnull
-cx_attr_nodiscard
-static inline void *cxTreeFindInSubtree(
-        CxTree *tree,
-        const void *data,
-        void *subtree_root,
-        size_t max_depth
-) {
-    return tree->cl->find(tree, subtree_root, data, max_depth);
-}
+cx_attr_nonnull cx_attr_nodiscard
+CX_EXPORT void *cxTreeFindInSubtree(CxTree *tree, const void *data, void *subtree_root, size_t max_depth);
 
 /**
  * Determines the size of the specified subtree.
@@ -1170,10 +1015,8 @@
  * @param subtree_root the root node of the subtree
  * @return the number of nodes in the specified subtree
  */
-cx_attr_nonnull
-cx_attr_nodiscard
-cx_attr_export
-size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root);
+cx_attr_nonnull cx_attr_nodiscard
+CX_EXPORT size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root);
 
 /**
  * Determines the depth of the specified subtree.
@@ -1182,10 +1025,17 @@
  * @param subtree_root the root node of the subtree
  * @return the tree depth including the @p subtree_root
  */
-cx_attr_nonnull
-cx_attr_nodiscard
-cx_attr_export
-size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root);
+cx_attr_nonnull  cx_attr_nodiscard
+CX_EXPORT size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root);
+
+/**
+ * Determines the size of the entire tree.
+ *
+ * @param tree the tree
+ * @return the tree size, counting the root as one
+ */
+cx_attr_nonnull cx_attr_nodiscard
+CX_EXPORT size_t cxTreeSize(CxTree *tree);
 
 /**
  * Determines the depth of the entire tree.
@@ -1193,10 +1043,8 @@
  * @param tree the tree
  * @return the tree depth, counting the root as one
  */
-cx_attr_nonnull
-cx_attr_nodiscard
-cx_attr_export
-size_t cxTreeDepth(CxTree *tree);
+cx_attr_nonnull cx_attr_nodiscard
+CX_EXPORT size_t cxTreeDepth(CxTree *tree);
 
 /**
  * Creates a depth-first iterator for the specified tree starting in @p node.
@@ -1210,18 +1058,8 @@
  * @return a tree iterator (depth-first)
  * @see cxTreeVisit()
  */
-cx_attr_nonnull
-cx_attr_nodiscard
-static inline CxTreeIterator cxTreeIterateSubtree(
-        CxTree *tree,
-        void *node,
-        bool visit_on_exit
-) {
-    return cx_tree_iterator(
-            node, visit_on_exit,
-            tree->loc_children, tree->loc_next
-    );
-}
+cx_attr_nonnull cx_attr_nodiscard
+CX_EXPORT CxTreeIterator cxTreeIterateSubtree(CxTree *tree, void *node, bool visit_on_exit);
 
 /**
  * Creates a breadth-first iterator for the specified tree starting in @p node.
@@ -1233,13 +1071,8 @@
  * @return a tree visitor (a.k.a. breadth-first iterator)
  * @see cxTreeIterate()
  */
-cx_attr_nonnull
-cx_attr_nodiscard
-static inline CxTreeVisitor cxTreeVisitSubtree(CxTree *tree, void *node) {
-    return cx_tree_visitor(
-            node, tree->loc_children, tree->loc_next
-    );
-}
+cx_attr_nonnull cx_attr_nodiscard
+CX_EXPORT CxTreeVisitor cxTreeVisitSubtree(CxTree *tree, void *node);
 
 /**
  * Creates a depth-first iterator for the specified tree.
@@ -1250,14 +1083,8 @@
  * @return a tree iterator (depth-first)
  * @see cxTreeVisit()
  */
-cx_attr_nonnull
-cx_attr_nodiscard
-static inline CxTreeIterator cxTreeIterate(
-        CxTree *tree,
-        bool visit_on_exit
-) {
-    return cxTreeIterateSubtree(tree, tree->root, visit_on_exit);
-}
+cx_attr_nonnull cx_attr_nodiscard
+CX_EXPORT CxTreeIterator cxTreeIterate(CxTree *tree, bool visit_on_exit);
 
 /**
  * Creates a breadth-first iterator for the specified tree.
@@ -1266,16 +1093,13 @@
  * @return a tree visitor (a.k.a. breadth-first iterator)
  * @see cxTreeIterate()
  */
-cx_attr_nonnull
-cx_attr_nodiscard
-static inline CxTreeVisitor cxTreeVisit(CxTree *tree) {
-    return cxTreeVisitSubtree(tree, tree->root);
-}
+cx_attr_nonnull cx_attr_nodiscard
+CxTreeVisitor cxTreeVisit(CxTree *tree);
 
 /**
  * Sets the (new) parent of the specified child.
  *
- * If the @p child is not already member of the tree, this function behaves
+ * If the @p child is not already a member of the tree, this function behaves
  * as #cxTreeAddChildNode().
  *
  * @param tree the tree
@@ -1284,21 +1108,16 @@
  * @see cxTreeAddChildNode()
  */
 cx_attr_nonnull
-cx_attr_export
-void cxTreeSetParent(
-        CxTree *tree,
-        void *parent,
-        void *child
-);
+CX_EXPORT 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.
+ * If the @p child is already a 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
+ * as if it was created by the tree itself with #cxTreeAddChild() (e.g., use
  * the same allocator).
  *
  * @param tree the tree
@@ -1307,12 +1126,7 @@
  * @see cxTreeSetParent()
  */
 cx_attr_nonnull
-cx_attr_export
-void cxTreeAddChildNode(
-        CxTree *tree,
-        void *parent,
-        void *child
-);
+CX_EXPORT void cxTreeAddChildNode(CxTree *tree, void *parent, void *child);
 
 /**
  * Creates a new node and adds it to the tree.
@@ -1322,7 +1136,7 @@
  * 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
+ * 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
@@ -1332,12 +1146,7 @@
  * @see cxTreeInsert()
  */
 cx_attr_nonnull
-cx_attr_export
-int cxTreeAddChild(
-        CxTree *tree,
-        void *parent,
-        const void *data
-);
+CX_EXPORT int cxTreeAddChild(CxTree *tree, void *parent, const void *data);
 
 /**
  * A function that is invoked when a node needs to be re-linked to a new parent.
@@ -1351,7 +1160,6 @@
  * @param old_parent the old parent of the node
  * @param new_parent the new parent of the node
  */
-cx_attr_nonnull
 typedef void (*cx_tree_relink_func)(
         void *node,
         const void *old_parent,
@@ -1373,15 +1181,10 @@
  * @return zero on success, non-zero if @p node is the root node of the tree
  */
 cx_attr_nonnull_arg(1, 2)
-cx_attr_export
-int cxTreeRemoveNode(
-        CxTree *tree,
-        void *node,
-        cx_tree_relink_func relink_func
-);
+CX_EXPORT int cxTreeRemoveNode(CxTree *tree, void *node, cx_tree_relink_func relink_func);
 
 /**
- * Removes a node and it's subtree from the tree.
+ * Removes a node and its subtree from the tree.
  *
  * If the node is not part of the tree, the behavior is undefined.
  *
@@ -1392,8 +1195,7 @@
  * @param node the node to remove
  */
 cx_attr_nonnull
-cx_attr_export
-void cxTreeRemoveSubtree(CxTree *tree, void *node);
+CX_EXPORT void cxTreeRemoveSubtree(CxTree *tree, void *node);
 
 /**
  * Destroys a node and re-links its children to its former parent.
@@ -1414,12 +1216,7 @@
  * @return zero on success, non-zero if @p node is the root node of the tree
  */
 cx_attr_nonnull_arg(1, 2)
-cx_attr_export
-int cxTreeDestroyNode(
-        CxTree *tree,
-        void *node,
-        cx_tree_relink_func relink_func
-);
+CX_EXPORT int cxTreeDestroyNode(CxTree *tree, void *node, cx_tree_relink_func relink_func);
 
 #ifdef __cplusplus
 } // extern "C"

mercurial