ucx
UAP Common Extensions
Loading...
Searching...
No Matches
tree.h
Go to the documentation of this file.
1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2024 Mike Becker, Olaf Wintermann All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
36#ifndef UCX_TREE_H
37#define UCX_TREE_H
38
39#include "common.h"
40
41#include "collection.h"
42
43#ifdef __cplusplus
44extern "C" {
45#endif
46
63typedef struct cx_tree_iterator_s {
71 bool skip;
80 bool exiting;
84 ptrdiff_t loc_children;
88 ptrdiff_t loc_next;
92 size_t counter;
98 void *node;
111 void **stack;
116 union {
124 size_t depth;
125 };
127
145
207
213static inline void cxTreeIteratorDispose(CxTreeIterator *iter) {
214 free(iter->stack);
215 iter->stack = NULL;
216}
217
223static inline void cxTreeVisitorDispose(CxTreeVisitor *visitor) {
224 struct cx_tree_visitor_queue_s *q = visitor->queue_next;
225 while (q != NULL) {
226 struct cx_tree_visitor_queue_s *next = q->next;
227 free(q);
228 q = next;
229 }
230}
231
238#define cxTreeIteratorContinue(iterator) (iterator).skip = true; continue
239
246#define cxTreeVisitorContinue(visitor) cxTreeIteratorContinue(visitor)
247
268 void *parent,
269 void *node,
270 ptrdiff_t loc_parent,
271 ptrdiff_t loc_children,
272 ptrdiff_t loc_last_child,
273 ptrdiff_t loc_prev,
274 ptrdiff_t loc_next
275);
276
294 void *node,
295 ptrdiff_t loc_parent,
296 ptrdiff_t loc_children,
297 ptrdiff_t loc_last_child,
298 ptrdiff_t loc_prev,
299 ptrdiff_t loc_next
300);
301
305#define CX_TREE_SEARCH_INFINITE_DEPTH 0
306
334typedef int (*cx_tree_search_data_func)(const void *node, const void *data);
335
336
364typedef int (*cx_tree_search_func)(const void *node, const void *new_node);
365
394 const void *root,
395 size_t depth,
396 const void *data,
398 void **result,
399 ptrdiff_t loc_children,
400 ptrdiff_t loc_next
401);
402
431 const void *root,
432 size_t depth,
433 const void *node,
435 void **result,
436 ptrdiff_t loc_children,
437 ptrdiff_t loc_next
438);
439
463 void *root,
464 bool visit_on_exit,
465 ptrdiff_t loc_children,
466 ptrdiff_t loc_next
467);
468
490 void *root,
491 ptrdiff_t loc_children,
492 ptrdiff_t loc_next
493);
494
506typedef void *(*cx_tree_node_create_func)(const void *, void *);
507
515extern unsigned int cx_tree_add_look_around_depth;
516
555cx_attr_nonnull_arg(1, 3, 4, 6, 7)
559 struct cx_iterator_base_s *iter,
560 size_t num,
563 void *cdata,
564 void **failed,
565 void *root,
566 ptrdiff_t loc_parent,
567 ptrdiff_t loc_children,
568 ptrdiff_t loc_last_child,
569 ptrdiff_t loc_prev,
570 ptrdiff_t loc_next
571);
572
610cx_attr_nonnull_arg(1, 4, 5, 7, 8)
614 const void *src,
615 size_t num,
616 size_t elem_size,
619 void *cdata,
620 void **failed,
621 void *root,
622 ptrdiff_t loc_parent,
623 ptrdiff_t loc_children,
624 ptrdiff_t loc_last_child,
625 ptrdiff_t loc_prev,
626 ptrdiff_t loc_next
627);
628
674cx_attr_nonnull_arg(1, 2, 3, 5, 6)
678 const void *src,
681 void *cdata,
682 void **cnode,
683 void *root,
684 ptrdiff_t loc_parent,
685 ptrdiff_t loc_children,
686 ptrdiff_t loc_last_child,
687 ptrdiff_t loc_prev,
688 ptrdiff_t loc_next
689);
690
691
696
722
810
819#define CX_TREE_NODE_BASE(type) \
820 type *parent; \
821 type *children;\
822 type *last_child;\
823 type *prev;\
824 type *next
825
834#define cx_tree_node_base_layout \
835 offsetof(struct cx_tree_node_base_s, parent),\
836 offsetof(struct cx_tree_node_base_s, children),\
837 offsetof(struct cx_tree_node_base_s, last_child),\
838 offsetof(struct cx_tree_node_base_s, prev), \
839 offsetof(struct cx_tree_node_base_s, next)
840
852 struct cx_tree_s *tree,
853 const void *data
854 );
855
862 size_t (*insert_many)(
863 struct cx_tree_s *tree,
864 struct cx_iterator_base_s *iter,
865 size_t n
866 );
867
871 void *(*find)(
872 struct cx_tree_s *tree,
873 const void *subtree,
874 const void *data,
875 size_t depth
876 );
877};
878
882typedef struct cx_tree_s CxTree;
883
884
908void cxTreeDestroySubtree(CxTree *tree, void *node);
909
910
928#define cxTreeClear(tree) cxTreeDestroySubtree(tree, tree->root)
929
947void cxTreeFree(CxTree *tree);
948
973cx_attr_nonnull_arg(2, 3, 4)
979 const CxAllocator *allocator,
980 cx_tree_node_create_func create_func,
981 cx_tree_search_func search_func,
982 cx_tree_search_data_func search_data_func,
983 ptrdiff_t loc_parent,
984 ptrdiff_t loc_children,
985 ptrdiff_t loc_last_child,
986 ptrdiff_t loc_prev,
987 ptrdiff_t loc_next
988);
989
1007#define cxTreeCreateSimple(\
1008 allocator, create_func, search_func, search_data_func \
1009) cxTreeCreate(allocator, create_func, search_func, search_data_func, \
1010cx_tree_node_base_layout)
1011
1040 const CxAllocator *allocator,
1041 void *root,
1042 ptrdiff_t loc_parent,
1043 ptrdiff_t loc_children,
1044 ptrdiff_t loc_last_child,
1045 ptrdiff_t loc_prev,
1046 ptrdiff_t loc_next
1047);
1048
1062static inline int cxTreeInsert(
1063 CxTree *tree,
1064 const void *data
1065) {
1066 return tree->cl->insert_element(tree, data);
1067}
1068
1082static inline size_t cxTreeInsertIter(
1083 CxTree *tree,
1084 CxIteratorBase *iter,
1085 size_t n
1086) {
1087 return tree->cl->insert_many(tree, iter, n);
1088}
1089
1104static inline size_t cxTreeInsertArray(
1105 CxTree *tree,
1106 const void *data,
1107 size_t elem_size,
1108 size_t n
1109) {
1110 if (n == 0) return 0;
1111 if (n == 1) return 0 == cxTreeInsert(tree, data) ? 1 : 0;
1112 CxIterator iter = cxIterator(data, elem_size, n);
1113 return cxTreeInsertIter(tree, cxIteratorRef(iter), n);
1114}
1115
1129static inline void *cxTreeFind(
1130 CxTree *tree,
1131 const void *data
1132) {
1133 return tree->cl->find(tree, tree->root, data, 0);
1134}
1135
1157static inline void *cxTreeFindInSubtree(
1158 CxTree *tree,
1159 const void *data,
1160 void *subtree_root,
1161 size_t max_depth
1162) {
1163 return tree->cl->find(tree, subtree_root, data, max_depth);
1164}
1165
1176size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root);
1177
1188size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root);
1189
1199size_t cxTreeDepth(CxTree *tree);
1200
1216 CxTree *tree,
1217 void *node,
1218 bool visit_on_exit
1219) {
1220 return cx_tree_iterator(
1221 node, visit_on_exit,
1222 tree->loc_children, tree->loc_next
1223 );
1224}
1225
1238static inline CxTreeVisitor cxTreeVisitSubtree(CxTree *tree, void *node) {
1239 return cx_tree_visitor(
1240 node, tree->loc_children, tree->loc_next
1241 );
1242}
1243
1256 CxTree *tree,
1257 bool visit_on_exit
1258) {
1259 return cxTreeIterateSubtree(tree, tree->root, visit_on_exit);
1260}
1261
1271static inline CxTreeVisitor cxTreeVisit(CxTree *tree) {
1272 return cxTreeVisitSubtree(tree, tree->root);
1273}
1274
1289 CxTree *tree,
1290 void *parent,
1291 void *child
1292);
1293
1312 CxTree *tree,
1313 void *parent,
1314 void *child
1315);
1316
1337 CxTree *tree,
1338 void *parent,
1339 const void *data
1340);
1341
1355typedef void (*cx_tree_relink_func)(
1356 void *node,
1357 const void *old_parent,
1358 const void *new_parent
1359);
1360
1378 CxTree *tree,
1379 void *node,
1380 cx_tree_relink_func relink_func
1381);
1382
1396void cxTreeRemoveSubtree(CxTree *tree, void *node);
1397
1419 CxTree *tree,
1420 void *node,
1421 cx_tree_relink_func relink_func
1422);
1423
1424#ifdef __cplusplus
1425} // extern "C"
1426#endif
1427
1428#endif //UCX_TREE_H
void(* cx_destructor_func2)(void *data, void *memory)
Function pointer type for destructor functions.
Definition allocator.h:129
void(* cx_destructor_func)(void *memory)
Function pointer type for destructor functions.
Definition allocator.h:116
Common definitions for various collection implementations.
Common definitions and feature checks.
#define cx_attr_export
Only used for building Windows DLLs.
Definition common.h:285
#define cx_attr_nonnull
All pointer arguments must be non-NULL.
Definition common.h:136
#define cx_attr_nodiscard
Warn about discarded return value.
Definition common.h:265
#define cx_attr_malloc
The attributed function always returns freshly allocated memory.
Definition common.h:151
#define cx_attr_access_w(...)
Specifies that the function will only write through the given pointer.
Definition common.h:241
#define cx_attr_nonnull_arg(...)
The specified pointer arguments must be non-NULL.
Definition common.h:141
#define cx_attr_dealloc(...)
Not supported in clang.
Definition common.h:167
#define CX_ITERATOR_BASE
Declares base attributes for an iterator.
Definition iterator.h:92
CxIterator cxIterator(const void *array, size_t elem_size, size_t elem_count)
Creates an iterator for the specified plain array.
#define cxIteratorRef(iter)
Obtains a reference to an arbitrary iterator.
Definition iterator.h:197
Structure holding the data for an allocator.
Definition allocator.h:84
Common data for all iterators.
Definition iterator.h:48
Internal iterator struct - use CxIterator.
Definition iterator.h:97
The class definition for arbitrary trees.
Definition tree.h:844
void *(* find)(struct cx_tree_s *tree, const void *subtree, const void *data, size_t depth)
Member function for finding a node.
Definition tree.h:871
size_t(* insert_many)(struct cx_tree_s *tree, struct cx_iterator_base_s *iter, size_t n)
Member function for inserting multiple elements.
Definition tree.h:862
int(* insert_element)(struct cx_tree_s *tree, const void *data)
Member function for inserting a single element.
Definition tree.h:851
A depth-first tree iterator.
Definition tree.h:63
bool skip
Indicates whether the subtree below the current node shall be skipped.
Definition tree.h:71
void ** stack
Internal stack.
Definition tree.h:111
bool visit_on_exit
Set to true, when the iterator shall visit a node again when all it's children have been processed.
Definition tree.h:76
ptrdiff_t loc_next
Offset in the node struct for the next pointer.
Definition tree.h:88
size_t depth
The current depth in the tree.
Definition tree.h:124
void * node_next
Stores a copy of the next pointer of the visited node.
Definition tree.h:103
void * node
The currently observed node.
Definition tree.h:98
size_t stack_size
Internal stack size.
Definition tree.h:120
size_t counter
The total number of distinct nodes that have been passed so far.
Definition tree.h:92
ptrdiff_t loc_children
Offset in the node struct for the children linked list.
Definition tree.h:84
bool exiting
True, if this iterator is currently leaving the node.
Definition tree.h:80
size_t stack_capacity
Internal capacity of the stack.
Definition tree.h:115
Base structure that can be used for tree nodes in a CxTree.
Definition tree.h:700
struct cx_tree_node_base_s * children
Pointer to the first child.
Definition tree.h:708
struct cx_tree_node_base_s * prev
Pointer to the previous sibling.
Definition tree.h:716
struct cx_tree_node_base_s * last_child
Pointer to the last child.
Definition tree.h:712
struct cx_tree_node_base_s * parent
Pointer to the parent.
Definition tree.h:704
struct cx_tree_node_base_s * next
Pointer to the next sibling.
Definition tree.h:720
Structure for holding the base data of a tree.
Definition tree.h:726
ptrdiff_t loc_parent
Offset in the node struct for the parent pointer.
Definition tree.h:787
ptrdiff_t loc_children
Offset in the node struct for the children linked list.
Definition tree.h:792
ptrdiff_t loc_next
Offset in the node struct for the next sibling pointer.
Definition tree.h:808
cx_tree_search_data_func search_data
A function to compare a node with data.
Definition tree.h:777
cx_destructor_func2 advanced_destructor
An optional advanced destructor for the tree nodes.
Definition tree.h:762
cx_tree_node_create_func node_create
A function to create new nodes.
Definition tree.h:752
size_t size
The number of currently stored elements.
Definition tree.h:782
const CxAllocator * allocator
Allocator to allocate new nodes.
Definition tree.h:735
cx_tree_search_func search
A function to compare two nodes.
Definition tree.h:772
ptrdiff_t loc_last_child
Optional offset in the node struct for the pointer to the last child in the linked list (negative if ...
Definition tree.h:798
ptrdiff_t loc_prev
Offset in the node struct for the previous sibling pointer.
Definition tree.h:803
void * destructor_data
The pointer to additional data that is passed to the advanced destructor.
Definition tree.h:767
const cx_tree_class * cl
The tree class definition.
Definition tree.h:730
void * root
A pointer to the root node.
Definition tree.h:742
cx_destructor_func simple_destructor
An optional simple destructor for the tree nodes.
Definition tree.h:757
An element in a visitor queue.
Definition tree.h:131
size_t depth
The depth of the node.
Definition tree.h:139
void * node
The tree node to visit.
Definition tree.h:135
struct cx_tree_visitor_queue_s * next
The next element in the queue or NULL.
Definition tree.h:143
A breadth-first tree iterator.
Definition tree.h:167
ptrdiff_t loc_next
Offset in the node struct for the next pointer.
Definition tree.h:183
struct cx_tree_visitor_queue_s * queue_last
The last element in the visitor queue.
Definition tree.h:205
size_t counter
The total number of distinct nodes that have been passed so far.
Definition tree.h:187
size_t depth
The current depth in the tree.
Definition tree.h:197
bool skip
Indicates whether the subtree below the current node shall be skipped.
Definition tree.h:175
void * node
The currently observed node.
Definition tree.h:193
ptrdiff_t loc_children
Offset in the node struct for the children linked list.
Definition tree.h:179
struct cx_tree_visitor_queue_s * queue_next
The next element in the visitor queue.
Definition tree.h:201
void cxTreeSetParent(CxTree *tree, void *parent, void *child)
Sets the (new) parent of the specified child.
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)
Links a node to a (new) parent.
CxTreeIterator cx_tree_iterator(void *root, bool visit_on_exit, ptrdiff_t loc_children, ptrdiff_t loc_next)
Creates a depth-first iterator for a tree with the specified root node.
void cxTreeAddChildNode(CxTree *tree, void *parent, void *child)
Adds a new node to the tree.
static size_t cxTreeInsertArray(CxTree *tree, const void *data, size_t elem_size, size_t n)
Inserts an array of data efficiently into the tree.
Definition tree.h:1104
int(* cx_tree_search_func)(const void *node, const void *new_node)
Function pointer for a search function.
Definition tree.h:364
unsigned int cx_tree_add_look_around_depth
The local search depth for a new subtree when adding multiple elements.
int cxTreeDestroyNode(CxTree *tree, void *node, cx_tree_relink_func relink_func)
Destroys a node and re-links its children to its former parent.
static CxTreeIterator cxTreeIterate(CxTree *tree, bool visit_on_exit)
Creates a depth-first iterator for the specified tree.
Definition tree.h:1255
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 multiple elements efficiently to a tree.
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)
Searches for a node in a tree.
size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root)
Determines the depth of the specified subtree.
void cxTreeDestroySubtree(CxTree *tree, void *node)
Destroys a node and it's subtree.
void(* cx_tree_relink_func)(void *node, const void *old_parent, const void *new_parent)
A function that is invoked when a node needs to be re-linked to a new parent.
Definition tree.h:1355
int(* cx_tree_search_data_func)(const void *node, const void *data)
Function pointer for a search function.
Definition tree.h:334
size_t cxTreeDepth(CxTree *tree)
Determines the depth of the entire tree.
static void * cxTreeFindInSubtree(CxTree *tree, const void *data, void *subtree_root, size_t max_depth)
Searches the data in the specified subtree.
Definition tree.h:1157
int cxTreeRemoveNode(CxTree *tree, void *node, cx_tree_relink_func relink_func)
Removes a node and re-links its children to its former parent.
static void * cxTreeFind(CxTree *tree, const void *data)
Searches the data in the specified tree.
Definition tree.h:1129
static CxTreeVisitor cxTreeVisit(CxTree *tree)
Creates a breadth-first iterator for the specified tree.
Definition tree.h:1271
struct cx_tree_visitor_s CxTreeVisitor
A breadth-first tree iterator.
static CxTreeVisitor cxTreeVisitSubtree(CxTree *tree, void *node)
Creates a breadth-first iterator for the specified tree starting in node.
Definition tree.h:1238
static CxTreeIterator cxTreeIterateSubtree(CxTree *tree, void *node, bool visit_on_exit)
Creates a depth-first iterator for the specified tree starting in node.
Definition tree.h:1215
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)
Creates a new tree structure based on an existing tree.
void cxTreeFree(CxTree *tree)
Deallocates the tree structure.
size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root)
Determines the size of the specified subtree.
static void cxTreeVisitorDispose(CxTreeVisitor *visitor)
Releases internal memory of the given tree visitor.
Definition tree.h:223
int cxTreeAddChild(CxTree *tree, void *parent, const void *data)
Creates a new node and adds it to the tree.
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)
Unlinks a node from its parent.
void *(* cx_tree_node_create_func)(const void *, void *)
Describes a function that creates a tree node from the specified data.
Definition tree.h:506
static size_t cxTreeInsertIter(CxTree *tree, CxIteratorBase *iter, size_t n)
Inserts elements provided by an iterator efficiently into the tree.
Definition tree.h:1082
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.
struct cx_tree_iterator_s CxTreeIterator
A depth-first tree iterator.
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 data in a tree.
CxTreeVisitor cx_tree_visitor(void *root, ptrdiff_t loc_children, ptrdiff_t loc_next)
Creates a breadth-first iterator for a tree with the specified root node.
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)
Adds data to a tree.
static void cxTreeIteratorDispose(CxTreeIterator *iter)
Releases internal memory of the given tree iterator.
Definition tree.h:213
static int cxTreeInsert(CxTree *tree, const void *data)
Inserts data into the tree.
Definition tree.h:1062
void cxTreeRemoveSubtree(CxTree *tree, void *node)
Removes a node and it's subtree from the tree.
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 the specified layout.