--- a/src/cx/tree.h Sun Dec 28 15:45:39 2025 +0100 +++ b/src/cx/tree.h Sun Dec 28 17:31:20 2025 +0100 @@ -40,10 +40,6 @@ #include "collection.h" -#ifdef __cplusplus -extern "C" { -#endif - /** * A depth-first tree iterator. * @@ -213,15 +209,15 @@ * Releases internal memory of the given tree iterator. * @param iter the iterator */ -cx_attr_nonnull -CX_EXPORT void cxTreeIteratorDispose(CxTreeIterator *iter); +CX_EXTERN CX_NONNULL +void cxTreeIteratorDispose(CxTreeIterator *iter); /** * Releases internal memory of the given tree visitor. * @param visitor the visitor */ -cx_attr_nonnull -CX_EXPORT void cxTreeVisitorDispose(CxTreeVisitor *visitor); +CX_EXTERN CX_NONNULL +void cxTreeVisitorDispose(CxTreeVisitor *visitor); /** * Advises the iterator to skip the subtree below the current node and @@ -256,8 +252,8 @@ * @param loc_next offset in the node struct for the next pointer * @see cx_tree_unlink() */ -cx_attr_nonnull -CX_EXPORT void cx_tree_link(void *parent, void *node, +CX_EXTERN CX_NONNULL +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); @@ -275,8 +271,8 @@ * @param loc_next offset in the node struct for the next pointer * @see cx_tree_link() */ -cx_attr_nonnull -CX_EXPORT void cx_tree_unlink(void *node, +CX_EXTERN CX_NONNULL +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); @@ -366,8 +362,8 @@ * 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_EXPORT int cx_tree_search_data(const void *root, size_t depth, +CX_EXTERN CX_NONNULL CX_ACCESS_W(5) +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); @@ -385,7 +381,7 @@ * node matching the criteria is returned. * * @param root the root node -* @param depth the maximum depth (zero=indefinite, one=just root) + * @param depth the maximum depth (zero=indefinite, one=just root) * @param node the node to search for * @param sfunc the search function * @param result where the result shall be stored @@ -395,8 +391,8 @@ * 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_EXPORT int cx_tree_search(const void *root, size_t depth, +CX_EXTERN CX_NONNULL CX_ACCESS_W(5) +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); @@ -420,8 +416,8 @@ * @return the new tree iterator * @see cxTreeIteratorDispose() */ -cx_attr_nodiscard -CX_EXPORT CxTreeIterator cx_tree_iterator(void *root, bool visit_on_exit, +CX_EXTERN CX_NODISCARD +CxTreeIterator cx_tree_iterator(void *root, bool visit_on_exit, ptrdiff_t loc_children, ptrdiff_t loc_next); /** @@ -442,8 +438,8 @@ * @return the new tree visitor * @see cxTreeVisitorDispose() */ -cx_attr_nodiscard -CX_EXPORT CxTreeVisitor cx_tree_visitor(void *root, +CX_EXTERN CX_NODISCARD +CxTreeVisitor cx_tree_visitor(void *root, ptrdiff_t loc_children, ptrdiff_t loc_next); /** @@ -504,8 +500,8 @@ * @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_EXPORT size_t cx_tree_add_iter(struct cx_iterator_base_s *iter, size_t num, +CX_EXTERN CX_NONNULL_ARG(1, 3, 4, 6, 7) CX_ACCESS_W(6) +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, @@ -548,8 +544,8 @@ * @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_EXPORT size_t cx_tree_add_array(const void *src, size_t num, size_t elem_size, +CX_EXTERN CX_NONNULL_ARG(1, 4, 5, 7, 8) CX_ACCESS_W(7) +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, @@ -600,8 +596,8 @@ * @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_EXPORT int cx_tree_add(const void *src, +CX_EXTERN CX_NONNULL_ARG(1, 2, 3, 5, 6) CX_ACCESS_W(5) +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, @@ -786,8 +782,8 @@ * @param node the node to remove * @see cxTreeFree() */ -cx_attr_nonnull -CX_EXPORT void cxTreeDestroySubtree(CxTree *tree, void *node); +CX_EXTERN CX_NONNULL +void cxTreeDestroySubtree(CxTree *tree, void *node); /** @@ -825,7 +821,8 @@ * * @param tree the tree to free */ -CX_EXPORT void cxTreeFree(CxTree *tree); +CX_EXTERN +void cxTreeFree(CxTree *tree); /** * Creates a new tree structure based on the specified layout. @@ -851,8 +848,8 @@ * @see cxTreeCreateSimple() * @see cxTreeCreateWrapped() */ -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_EXTERN CX_NONNULL_ARG(2, 3, 4) CX_NODISCARD CX_MALLOC CX_DEALLOC(cxTreeFree, 1) +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); @@ -899,8 +896,8 @@ * @return the new tree * @see cxTreeCreate() */ -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, +CX_EXTERN CX_NONNULL_ARG(2) CX_NODISCARD CX_MALLOC CX_DEALLOC(cxTreeFree, 1) +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); @@ -916,8 +913,8 @@ * @retval zero success * @retval non-zero failure */ -cx_attr_nonnull -CX_EXPORT int cxTreeInsert(CxTree *tree, const void *data); +CX_EXTERN CX_NONNULL +int cxTreeInsert(CxTree *tree, const void *data); /** * Inserts elements provided by an iterator efficiently into the tree. @@ -931,8 +928,8 @@ * @param n the maximum number of elements to insert * @return the number of elements that could be successfully inserted */ -cx_attr_nonnull -CX_EXPORT size_t cxTreeInsertIter(CxTree *tree, CxIteratorBase *iter, size_t n); +CX_EXTERN CX_NONNULL +size_t cxTreeInsertIter(CxTree *tree, CxIteratorBase *iter, size_t n); /** * Inserts an array of data efficiently into the tree. @@ -947,8 +944,8 @@ * @param n the number of elements in the array * @return the number of elements that could be successfully inserted */ -cx_attr_nonnull -CX_EXPORT size_t cxTreeInsertArray(CxTree *tree, const void *data, size_t elem_size, size_t n); +CX_EXTERN CX_NONNULL +size_t cxTreeInsertArray(CxTree *tree, const void *data, size_t elem_size, size_t n); /** * Searches the data in the specified tree. @@ -961,8 +958,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 -CX_EXPORT void *cxTreeFind(CxTree *tree, const void *data); +CX_EXTERN CX_NONNULL CX_NODISCARD +void *cxTreeFind(CxTree *tree, const void *data); /** * Searches the data in the specified subtree. @@ -983,8 +980,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 -CX_EXPORT void *cxTreeFindInSubtree(CxTree *tree, const void *data, void *subtree_root, size_t max_depth); +CX_EXTERN CX_NONNULL CX_NODISCARD +void *cxTreeFindInSubtree(CxTree *tree, const void *data, void *subtree_root, size_t max_depth); /** * Determines the size of the specified subtree. @@ -993,8 +990,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_EXPORT size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root); +CX_EXTERN CX_NONNULL CX_NODISCARD +size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root); /** * Determines the depth of the specified subtree. @@ -1003,8 +1000,8 @@ * @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_EXPORT size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root); +CX_EXTERN CX_NONNULL CX_NODISCARD +size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root); /** * Determines the size of the entire tree. @@ -1012,8 +1009,8 @@ * @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); +CX_EXTERN CX_NONNULL CX_NODISCARD +size_t cxTreeSize(CxTree *tree); /** * Determines the depth of the entire tree. @@ -1021,8 +1018,8 @@ * @param tree the tree * @return the tree depth, counting the root as one */ -cx_attr_nonnull cx_attr_nodiscard -CX_EXPORT size_t cxTreeDepth(CxTree *tree); +CX_EXTERN CX_NONNULL CX_NODISCARD +size_t cxTreeDepth(CxTree *tree); /** * Creates a depth-first iterator for the specified tree starting in @p node. @@ -1036,8 +1033,8 @@ * @return a tree iterator (depth-first) * @see cxTreeVisit() */ -cx_attr_nonnull cx_attr_nodiscard -CX_EXPORT CxTreeIterator cxTreeIterateSubtree(CxTree *tree, void *node, bool visit_on_exit); +CX_EXTERN CX_NONNULL CX_NODISCARD +CxTreeIterator cxTreeIterateSubtree(CxTree *tree, void *node, bool visit_on_exit); /** * Creates a breadth-first iterator for the specified tree starting in @p node. @@ -1049,8 +1046,8 @@ * @return a tree visitor (a.k.a. breadth-first iterator) * @see cxTreeIterate() */ -cx_attr_nonnull cx_attr_nodiscard -CX_EXPORT CxTreeVisitor cxTreeVisitSubtree(CxTree *tree, void *node); +CX_EXTERN CX_NONNULL CX_NODISCARD +CxTreeVisitor cxTreeVisitSubtree(CxTree *tree, void *node); /** * Creates a depth-first iterator for the specified tree. @@ -1061,8 +1058,8 @@ * @return a tree iterator (depth-first) * @see cxTreeVisit() */ -cx_attr_nonnull cx_attr_nodiscard -CX_EXPORT CxTreeIterator cxTreeIterate(CxTree *tree, bool visit_on_exit); +CX_EXTERN CX_NONNULL CX_NODISCARD +CxTreeIterator cxTreeIterate(CxTree *tree, bool visit_on_exit); /** * Creates a breadth-first iterator for the specified tree. @@ -1071,8 +1068,8 @@ * @return a tree visitor (a.k.a. breadth-first iterator) * @see cxTreeIterate() */ -cx_attr_nonnull cx_attr_nodiscard -CX_EXPORT CxTreeVisitor cxTreeVisit(CxTree *tree); +CX_EXTERN CX_NONNULL CX_NODISCARD +CxTreeVisitor cxTreeVisit(CxTree *tree); /** * Sets the (new) parent of the specified child. @@ -1085,8 +1082,8 @@ * @param child the node to add * @see cxTreeAddChildNode() */ -cx_attr_nonnull -CX_EXPORT void cxTreeSetParent(CxTree *tree, void *parent, void *child); +CX_EXTERN CX_NONNULL +void cxTreeSetParent(CxTree *tree, void *parent, void *child); /** * Adds a new node to the tree. @@ -1103,8 +1100,8 @@ * @param child the node to add * @see cxTreeSetParent() */ -cx_attr_nonnull -CX_EXPORT void cxTreeAddChildNode(CxTree *tree, void *parent, void *child); +CX_EXTERN CX_NONNULL +void cxTreeAddChildNode(CxTree *tree, void *parent, void *child); /** * Creates a new node and adds it to the tree. @@ -1123,8 +1120,8 @@ * @return zero when the new node was created, non-zero on allocation failure * @see cxTreeInsert() */ -cx_attr_nonnull -CX_EXPORT int cxTreeAddChild(CxTree *tree, void *parent, const void *data); +CX_EXTERN CX_NONNULL +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. @@ -1158,8 +1155,8 @@ * node * @return zero on success, non-zero if @p node is the root node of the tree */ -cx_attr_nonnull_arg(1, 2) -CX_EXPORT int cxTreeRemoveNode(CxTree *tree, void *node, cx_tree_relink_func relink_func); +CX_EXTERN CX_NONNULL_ARG(1, 2) +int cxTreeRemoveNode(CxTree *tree, void *node, cx_tree_relink_func relink_func); /** * Removes a node and its subtree from the tree. @@ -1172,8 +1169,8 @@ * @param tree the tree * @param node the node to remove */ -cx_attr_nonnull -CX_EXPORT void cxTreeRemoveSubtree(CxTree *tree, void *node); +CX_EXTERN CX_NONNULL +void cxTreeRemoveSubtree(CxTree *tree, void *node); /** * Destroys a node and re-links its children to its former parent. @@ -1193,11 +1190,7 @@ * node * @return zero on success, non-zero if @p node is the root node of the tree */ -cx_attr_nonnull_arg(1, 2) -CX_EXPORT int cxTreeDestroyNode(CxTree *tree, void *node, cx_tree_relink_func relink_func); - -#ifdef __cplusplus -} // extern "C" -#endif +CX_EXTERN CX_NONNULL_ARG(1, 2) +int cxTreeDestroyNode(CxTree *tree, void *node, cx_tree_relink_func relink_func); #endif //UCX_TREE_H