| 39 #include "common.h" |
39 #include "common.h" |
| 40 |
40 |
| 41 #include "collection.h" |
41 #include "collection.h" |
| 42 |
42 |
| 43 /** |
43 /** |
| 44 * A depth-first tree iterator. |
44 * An element in a visitor queue. |
| 45 * |
45 */ |
| 46 * This iterator is not position-aware in a strict sense, as it does not assume |
46 struct cx_tree_visitor_queue_s { |
| 47 * a particular order of elements in the tree. However, the iterator keeps track |
47 /** |
| 48 * of the number of nodes it has passed in a counter-variable. |
48 * The tree node to visit. |
| 49 * Each node, regardless of the number of passes, is counted only once. |
49 */ |
| 50 * |
50 void *node; |
| 51 * @note Objects that are pointed to by an iterator are mutable through that |
51 /** |
| 52 * iterator. However, if the |
52 * The depth of the node. |
| 53 * underlying data structure is mutated by other means than this iterator (e.g., |
53 * The first visited node has depth 1. |
| 54 * elements added or removed), the iterator becomes invalid (regardless of what |
54 */ |
| 55 * cxIteratorValid() returns). |
55 size_t depth; |
| 56 * |
56 /** |
| 57 * @see CxIterator |
57 * The next element in the queue or @c NULL. |
| 58 */ |
58 */ |
| 59 typedef struct cx_tree_iterator_s { |
59 struct cx_tree_visitor_queue_s *next; |
| |
60 }; |
| |
61 |
| |
62 typedef struct cx_tree_combined_iterator_s { |
| 60 /** |
63 /** |
| 61 * Base members. |
64 * Base members. |
| 62 */ |
65 */ |
| 63 CX_ITERATOR_BASE; |
66 CX_ITERATOR_BASE; |
| 64 /** |
67 /** |
| 65 * Indicates whether the subtree below the current node shall be skipped. |
|
| 66 */ |
|
| 67 bool skip; |
|
| 68 /** |
|
| 69 * Set to true, when the iterator shall visit a node again |
|
| 70 * when all its children have been processed. |
|
| 71 */ |
|
| 72 bool visit_on_exit; |
|
| 73 /** |
|
| 74 * True, if this iterator is currently leaving the node. |
|
| 75 */ |
|
| 76 bool exiting; |
|
| 77 /** |
|
| 78 * Offset in the node struct for the children linked list. |
68 * Offset in the node struct for the children linked list. |
| 79 */ |
69 */ |
| 80 ptrdiff_t loc_children; |
70 ptrdiff_t loc_children; |
| 81 /** |
71 /** |
| 82 * Offset in the node struct for the next pointer. |
72 * Offset in the node struct for the next pointer. |
| 83 */ |
73 */ |
| 84 ptrdiff_t loc_next; |
74 ptrdiff_t loc_next; |
| 85 /** |
75 /** |
| 86 * The total number of distinct nodes that have been passed so far. |
76 * The total number of distinct nodes that have been passed so far. |
| 87 * This includes the current node. |
77 * This includes the currently visited node. |
| 88 */ |
78 */ |
| 89 size_t counter; |
79 size_t counter; |
| |
80 /** |
| |
81 * The current depth in the tree. |
| |
82 */ |
| |
83 size_t depth; |
| 90 /** |
84 /** |
| 91 * The currently observed node. |
85 * The currently observed node. |
| 92 * |
86 * |
| 93 * This is the same what cxIteratorCurrent() would return. |
87 * This is the same what cxIteratorCurrent() would return. |
| 94 */ |
88 */ |
| 95 void *node; |
89 void *node; |
| 96 /** |
90 /** |
| 97 * Stores a copy of the pointer to the successor of the visited node. |
91 * Memory for BFS or DFS-specific data. |
| 98 * Allows freeing a node on exit without corrupting the iteration. |
92 */ |
| 99 */ |
|
| 100 void *node_next; |
|
| 101 /** |
|
| 102 * Internal stack. |
|
| 103 * Will be automatically freed once the iterator becomes invalid. |
|
| 104 * |
|
| 105 * If you want to discard the iterator before, you need to manually |
|
| 106 * call cxTreeIteratorDispose(). |
|
| 107 */ |
|
| 108 void **stack; |
|
| 109 /** |
|
| 110 * Internal capacity of the stack. |
|
| 111 */ |
|
| 112 size_t stack_capacity; |
|
| 113 union { |
93 union { |
| 114 /** |
94 struct { |
| 115 * Internal stack size. |
95 /** |
| 116 */ |
96 * Stores a copy of the pointer to the successor of the visited node. |
| 117 size_t stack_size; |
97 * Allows freeing a node on exit without corrupting the iteration. |
| 118 /** |
98 */ |
| 119 * The current depth in the tree. |
99 void *node_next; |
| 120 * The node with which the iteration starts has depth 1. |
100 /** |
| 121 */ |
101 * Internal stack. |
| 122 size_t depth; |
102 * Will be automatically freed once the iterator becomes invalid. |
| |
103 * |
| |
104 * If you want to discard the iterator before, you need to manually |
| |
105 * call cxTreeIteratorDispose(). |
| |
106 */ |
| |
107 void **stack; |
| |
108 /** |
| |
109 * Internal capacity of the stack. |
| |
110 */ |
| |
111 size_t stack_capacity; |
| |
112 }; |
| |
113 struct { |
| |
114 /** |
| |
115 * The next element in the visitor queue. |
| |
116 */ |
| |
117 struct cx_tree_visitor_queue_s *queue_next; |
| |
118 /** |
| |
119 * The last element in the visitor queue. |
| |
120 */ |
| |
121 struct cx_tree_visitor_queue_s *queue_last; |
| |
122 }; |
| 123 }; |
123 }; |
| |
124 /** |
| |
125 * Indicates whether the subtree below the current node shall be skipped. |
| |
126 */ |
| |
127 bool skip; |
| |
128 /** |
| |
129 * Set to true, when the iterator shall visit a node again |
| |
130 * when all its children have been processed. |
| |
131 */ |
| |
132 bool visit_on_exit; |
| |
133 /** |
| |
134 * True, if this iterator is currently leaving the node. |
| |
135 */ |
| |
136 bool exiting; |
| |
137 /** |
| |
138 * Indicates whether the @c iterator (true) or the @c visitor (false) aspect is active. |
| |
139 */ |
| |
140 bool use_dfs; |
| 124 } CxTreeIterator; |
141 } CxTreeIterator; |
| 125 |
|
| 126 /** |
|
| 127 * An element in a visitor queue. |
|
| 128 */ |
|
| 129 struct cx_tree_visitor_queue_s { |
|
| 130 /** |
|
| 131 * The tree node to visit. |
|
| 132 */ |
|
| 133 void *node; |
|
| 134 /** |
|
| 135 * The depth of the node. |
|
| 136 * The first visited node has depth 1. |
|
| 137 */ |
|
| 138 size_t depth; |
|
| 139 /** |
|
| 140 * The next element in the queue or @c NULL. |
|
| 141 */ |
|
| 142 struct cx_tree_visitor_queue_s *next; |
|
| 143 }; |
|
| 144 |
|
| 145 /** |
|
| 146 * A breadth-first tree iterator. |
|
| 147 * |
|
| 148 * This iterator needs to maintain a visitor queue that will be automatically |
|
| 149 * freed once the iterator becomes invalid. |
|
| 150 * If you want to discard the iterator before, you MUST manually call |
|
| 151 * cxTreeVisitorDispose(). |
|
| 152 * |
|
| 153 * This iterator is not position-aware in a strict sense, as it does not assume |
|
| 154 * a particular order of elements in the tree. However, the iterator keeps track |
|
| 155 * of the number of nodes it has passed in a counter-variable. |
|
| 156 * Each node, regardless of the number of passes, is counted only once. |
|
| 157 * |
|
| 158 * @note Objects that are pointed to by an iterator are mutable through that |
|
| 159 * iterator. However, if the |
|
| 160 * underlying data structure is mutated by other means than this iterator (e.g., |
|
| 161 * elements added or removed), the iterator becomes invalid (regardless of what |
|
| 162 * cxIteratorValid() returns). |
|
| 163 * |
|
| 164 * @see CxIterator |
|
| 165 */ |
|
| 166 typedef struct cx_tree_visitor_s { |
|
| 167 /** |
|
| 168 * Base members. |
|
| 169 */ |
|
| 170 CX_ITERATOR_BASE; |
|
| 171 /** |
|
| 172 * Indicates whether the subtree below the current node shall be skipped. |
|
| 173 */ |
|
| 174 bool skip; |
|
| 175 /** |
|
| 176 * Offset in the node struct for the children linked list. |
|
| 177 */ |
|
| 178 ptrdiff_t loc_children; |
|
| 179 /** |
|
| 180 * Offset in the node struct for the next pointer. |
|
| 181 */ |
|
| 182 ptrdiff_t loc_next; |
|
| 183 /** |
|
| 184 * The total number of distinct nodes that have been passed so far. |
|
| 185 * This includes the currently visited node. |
|
| 186 */ |
|
| 187 size_t counter; |
|
| 188 /** |
|
| 189 * The currently observed node. |
|
| 190 * |
|
| 191 * This is the same what cxIteratorCurrent() would return. |
|
| 192 */ |
|
| 193 void *node; |
|
| 194 /** |
|
| 195 * The current depth in the tree. |
|
| 196 */ |
|
| 197 size_t depth; |
|
| 198 /** |
|
| 199 * The next element in the visitor queue. |
|
| 200 */ |
|
| 201 struct cx_tree_visitor_queue_s *queue_next; |
|
| 202 /** |
|
| 203 * The last element in the visitor queue. |
|
| 204 */ |
|
| 205 struct cx_tree_visitor_queue_s *queue_last; |
|
| 206 } CxTreeVisitor; |
|
| 207 |
142 |
| 208 /** |
143 /** |
| 209 * Releases internal memory of the given tree iterator. |
144 * Releases internal memory of the given tree iterator. |
| 210 * @param iter the iterator |
145 * @param iter the iterator |
| 211 */ |
146 */ |
| 212 CX_EXTERN CX_NONNULL |
147 CX_EXTERN CX_NONNULL |
| 213 void cxTreeIteratorDispose(CxTreeIterator *iter); |
148 void cxTreeIteratorDispose(CxTreeIterator *iter); |
| 214 |
149 |
| 215 /** |
150 /** |
| 216 * Releases internal memory of the given tree visitor. |
|
| 217 * @param visitor the visitor |
|
| 218 */ |
|
| 219 CX_EXTERN CX_NONNULL |
|
| 220 void cxTreeVisitorDispose(CxTreeVisitor *visitor); |
|
| 221 |
|
| 222 /** |
|
| 223 * Advises the iterator to skip the subtree below the current node and |
151 * Advises the iterator to skip the subtree below the current node and |
| 224 * also continues the current loop. |
152 * also continues the current loop. |
| 225 * |
153 * |
| 226 * @param iterator (@c CxTreeIterator) the iterator |
154 * @param iterator (@c CxTreeIterator) the iterator |
| 227 */ |
155 */ |
| 228 #define cxTreeIteratorContinue(iterator) (iterator).skip = true; continue |
156 #define cxTreeIteratorContinue(iterator) (iterator).skip = true; continue |
| 229 |
|
| 230 /** |
|
| 231 * Advises the visitor to skip the subtree below the current node and |
|
| 232 * also continues the current loop. |
|
| 233 * |
|
| 234 * @param visitor (@c CxTreeVisitor) the visitor |
|
| 235 */ |
|
| 236 #define cxTreeVisitorContinue(visitor) cxTreeIteratorContinue(visitor) |
|
| 237 |
157 |
| 238 /** |
158 /** |
| 239 * Links a node to a (new) parent. |
159 * Links a node to a (new) parent. |
| 240 * |
160 * |
| 241 * If the node already has a parent, it is unlinked, first. |
161 * If the node already has a parent, it is unlinked, first. |
| 305 * |
225 * |
| 306 * @return 0 if the node contains the data, |
226 * @return 0 if the node contains the data, |
| 307 * positive if one of the children might contain the data, |
227 * positive if one of the children might contain the data, |
| 308 * negative if neither the node nor the children contains the data |
228 * negative if neither the node nor the children contains the data |
| 309 */ |
229 */ |
| 310 typedef int (*cx_tree_search_data_func)(const void *node, const void *data); |
230 typedef int (*cx_tree_search_func)(const void *node, const void *data); |
| 311 |
|
| 312 |
|
| 313 /** |
|
| 314 * Function pointer for a search function. |
|
| 315 * |
|
| 316 * A function of this kind shall check if the specified @p node |
|
| 317 * contains the same @p data as @p new_node or if one of the children might |
|
| 318 * contain the data. |
|
| 319 * |
|
| 320 * The function should use the returned integer to indicate how close the |
|
| 321 * match is, where a negative number means that it does not match at all. |
|
| 322 * Zero means exact match and a positive number is an implementation defined |
|
| 323 * measure for the distance to an exact match. |
|
| 324 * |
|
| 325 * For example, consider a tree that stores file path information. |
|
| 326 * A node which is describing a parent directory of a searched file shall |
|
| 327 * return a positive number to indicate that a child node might contain the |
|
| 328 * searched item. On the other hand, if the node denotes a path that is not a |
|
| 329 * prefix of the searched filename, the function would return -1 to indicate |
|
| 330 * that the search does not need to be continued in that branch. |
|
| 331 * |
|
| 332 * @param node the node that is currently investigated |
|
| 333 * @param new_node a new node with the information which is searched |
|
| 334 * |
|
| 335 * @return 0 if @p node contains the same data as @p new_node, |
|
| 336 * positive if one of the children might contain the data, |
|
| 337 * negative if neither the node nor the children contains the data |
|
| 338 */ |
|
| 339 typedef int (*cx_tree_search_func)(const void *node, const void *new_node); |
|
| 340 |
231 |
| 341 /** |
232 /** |
| 342 * Searches for data in a tree. |
233 * Searches for data in a tree. |
| 343 * |
234 * |
| 344 * When the data cannot be found exactly, the search function might return the |
235 * When the data cannot be found exactly, the search function might return the |
| 345 * closest result, which might be a good starting point for adding a new node |
236 * closest result, which might be a good starting point for adding a new node |
| 346 * to the tree (see also #cx_tree_add()). |
237 * to the tree. |
| 347 * |
238 * |
| 348 * Depending on the tree structure, it is not necessarily guaranteed that the |
239 * Depending on the tree structure, it is not necessarily guaranteed that the |
| 349 * "closest" match is uniquely defined. This function will search for a node |
240 * "closest" match is uniquely defined. This function will search for a node |
| 350 * with the best match according to the @p sfunc (meaning: the return value of |
241 * with the best match according to the @p sfunc (meaning: the return value of |
| 351 * @p sfunc which is closest to zero). If that is also ambiguous, an arbitrary |
242 * @p sfunc which is closest to zero). If that is also ambiguous, an arbitrary |
| 352 * node matching the criteria is returned. |
243 * node matching the criteria is returned. |
| 353 * |
244 * |
| 354 * @param root the root node |
245 * @param root the root node |
| 355 * @param depth the maximum depth (zero=indefinite, one=just root) |
246 * @param max_depth the maximum depth (zero=indefinite, one=just root) |
| 356 * @param data the data to search for |
247 * @param data the data to search for |
| 357 * @param sfunc the search function |
248 * @param sfunc the search function |
| 358 * @param result where the result shall be stored |
249 * @param result where the result shall be stored |
| 359 * @param loc_children offset in the node struct for the children linked list |
250 * @param loc_children offset in the node struct for the children linked list |
| 360 * @param loc_next offset in the node struct for the next pointer |
251 * @param loc_next offset in the node struct for the next pointer |
| 361 * @return zero if the node was found exactly, positive if a node was found that |
252 * @return zero if the node was found exactly, positive if a node was found that |
| 362 * could contain the node (but doesn't right now), negative if the tree does not |
253 * could contain the node (but doesn't right now), negative if the tree does not |
| 363 * contain any node that might be related to the searched data |
254 * contain any node that might be related to the searched data |
| 364 */ |
255 */ |
| 365 CX_EXTERN CX_NONNULL CX_ACCESS_W(5) |
256 CX_EXTERN CX_NONNULL_ARG(4, 5) CX_ACCESS_W(5) |
| 366 int cx_tree_search_data(const void *root, size_t depth, |
257 int cx_tree_search(const void *root, size_t max_depth, |
| 367 const void *data, cx_tree_search_data_func sfunc, |
258 const void *data, cx_tree_search_func sfunc, void **result, |
| 368 void **result, ptrdiff_t loc_children, ptrdiff_t loc_next); |
259 ptrdiff_t loc_children, ptrdiff_t loc_next); |
| 369 |
|
| 370 /** |
|
| 371 * Searches for a node in a tree. |
|
| 372 * |
|
| 373 * When no node with the same data can be found, the search function might |
|
| 374 * return the closest result, which might be a good starting point for adding the |
|
| 375 * new node to the tree (see also #cx_tree_add()). |
|
| 376 * |
|
| 377 * Depending on the tree structure, it is not necessarily guaranteed that the |
|
| 378 * "closest" match is uniquely defined. This function will search for a node |
|
| 379 * with the best match according to the @p sfunc (meaning: the return value of |
|
| 380 * @p sfunc which is closest to zero). If that is also ambiguous, an arbitrary |
|
| 381 * node matching the criteria is returned. |
|
| 382 * |
|
| 383 * @param root the root node |
|
| 384 * @param depth the maximum depth (zero=indefinite, one=just root) |
|
| 385 * @param node the node to search for |
|
| 386 * @param sfunc the search function |
|
| 387 * @param result where the result shall be stored |
|
| 388 * @param loc_children offset in the node struct for the children linked list |
|
| 389 * @param loc_next offset in the node struct for the next pointer |
|
| 390 * @return zero if the node was found exactly, positive if a node was found that |
|
| 391 * could contain the node (but doesn't right now), negative if the tree does not |
|
| 392 * contain any node that might be related to the searched data |
|
| 393 */ |
|
| 394 CX_EXTERN CX_NONNULL CX_ACCESS_W(5) |
|
| 395 int cx_tree_search(const void *root, size_t depth, |
|
| 396 const void *node, cx_tree_search_func sfunc, |
|
| 397 void **result, ptrdiff_t loc_children, ptrdiff_t loc_next); |
|
| 398 |
260 |
| 399 /** |
261 /** |
| 400 * Creates a depth-first iterator for a tree with the specified root node. |
262 * Creates a depth-first iterator for a tree with the specified root node. |
| 401 * |
263 * |
| 402 * @note A tree iterator needs to maintain a stack of visited nodes, which is |
264 * @note A tree iterator needs to maintain a stack of visited nodes, which is |
| 425 * |
287 * |
| 426 * @note A tree visitor needs to maintain a queue of to-be visited nodes, which |
288 * @note A tree visitor needs to maintain a queue of to-be visited nodes, which |
| 427 * is allocated using the cxDefaultAllocator. |
289 * is allocated using the cxDefaultAllocator. |
| 428 * When the visitor becomes invalid, this memory is automatically released. |
290 * When the visitor becomes invalid, this memory is automatically released. |
| 429 * However, if you wish to cancel the iteration before the visitor becomes |
291 * However, if you wish to cancel the iteration before the visitor becomes |
| 430 * invalid by itself, you MUST call cxTreeVisitorDispose() manually to release |
292 * invalid by itself, you MUST call cxTreeIteratorDispose() manually to release |
| 431 * the memory. |
293 * the memory. |
| 432 * |
294 * |
| 433 * @remark The returned iterator does not support cxIteratorFlagRemoval(). |
295 * @remark The returned iterator does not support cxIteratorFlagRemoval(). |
| 434 * |
296 * |
| 435 * @param root the root node |
297 * @param root the root node |
| 436 * @param loc_children offset in the node struct for the children linked list |
298 * @param loc_children offset in the node struct for the children linked list |
| 437 * @param loc_next offset in the node struct for the next pointer |
299 * @param loc_next offset in the node struct for the next pointer |
| 438 * @return the new tree visitor |
300 * @return the new tree visitor |
| 439 * @see cxTreeVisitorDispose() |
301 * @see cxTreeIteratorDispose() |
| 440 */ |
302 */ |
| 441 CX_EXTERN CX_NODISCARD |
303 CX_EXTERN CX_NODISCARD |
| 442 CxTreeVisitor cx_tree_visitor(void *root, |
304 CxTreeIterator cx_tree_visitor(void *root, |
| 443 ptrdiff_t loc_children, ptrdiff_t loc_next); |
305 ptrdiff_t loc_children, ptrdiff_t loc_next); |
| 444 |
|
| 445 /** |
|
| 446 * Describes a function that creates a tree node from the specified data. |
|
| 447 * The first argument points to the data the node shall contain, and |
|
| 448 * the second argument may be used for additional data (e.g., an allocator). |
|
| 449 * Functions of this type shall either return a new pointer to a newly |
|
| 450 * created node or @c NULL when allocation fails. |
|
| 451 * |
|
| 452 * @note the function may leave the node pointers in the struct uninitialized. |
|
| 453 * The caller is responsible to set them according to the intended use case. |
|
| 454 */ |
|
| 455 typedef void *(*cx_tree_node_create_func)(const void *, void *); |
|
| 456 |
|
| 457 /** |
|
| 458 * The local search depth for a new subtree when adding multiple elements. |
|
| 459 * The default value is 3. |
|
| 460 * This variable is used by #cx_tree_add_array() and #cx_tree_add_iter() to |
|
| 461 * implement optimized insertion of multiple elements into a tree. |
|
| 462 */ |
|
| 463 CX_EXPORT extern unsigned int cx_tree_add_look_around_depth; |
|
| 464 |
|
| 465 /** |
|
| 466 * Adds multiple elements efficiently to a tree. |
|
| 467 * |
|
| 468 * Once an element cannot be added to the tree, this function returns, leaving |
|
| 469 * the iterator in a valid state pointing to the element that could not be |
|
| 470 * added. |
|
| 471 * Also, the pointer of the created node will be stored to @p failed. |
|
| 472 * The integer returned by this function denotes the number of elements obtained |
|
| 473 * from the @p iter that have been successfully processed. |
|
| 474 * When all elements could be processed, a @c NULL pointer will be written to |
|
| 475 * @p failed. |
|
| 476 * |
|
| 477 * The advantage of this function compared to multiple invocations of |
|
| 478 * #cx_tree_add() is that the search for the insert locations is not always |
|
| 479 * started from the root node. |
|
| 480 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes |
|
| 481 * of the current insert location before starting from the root node again. |
|
| 482 * When the variable is set to zero, only the last found location is checked |
|
| 483 * again. |
|
| 484 * |
|
| 485 * Refer to the documentation of #cx_tree_add() for more details. |
|
| 486 * |
|
| 487 * @param iter a pointer to an arbitrary iterator |
|
| 488 * @param num the maximum number of elements to obtain from the iterator |
|
| 489 * @param sfunc a search function |
|
| 490 * @param cfunc a node creation function |
|
| 491 * @param cdata optional additional data |
|
| 492 * @param root the root node of the tree |
|
| 493 * @param failed location where the pointer to a failed node shall be stored |
|
| 494 * @param loc_parent offset in the node struct for the parent pointer |
|
| 495 * @param loc_children offset in the node struct for the children linked list |
|
| 496 * @param loc_last_child optional offset in the node struct for the pointer to |
|
| 497 * the last child in the linked list (negative if there is no such pointer) |
|
| 498 * @param loc_prev optional offset in the node struct for the prev pointer |
|
| 499 * @param loc_next offset in the node struct for the next pointer |
|
| 500 * @return the number of nodes created and added |
|
| 501 * @see cx_tree_add() |
|
| 502 */ |
|
| 503 CX_EXTERN CX_NONNULL_ARG(1, 3, 4, 6, 7) CX_ACCESS_W(6) |
|
| 504 size_t cx_tree_add_iter(struct cx_iterator_base_s *iter, size_t num, |
|
| 505 cx_tree_search_func sfunc, cx_tree_node_create_func cfunc, |
|
| 506 void *cdata, void **failed, void *root, |
|
| 507 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, |
|
| 508 ptrdiff_t loc_prev, ptrdiff_t loc_next); |
|
| 509 |
|
| 510 /** |
|
| 511 * Adds multiple elements efficiently to a tree. |
|
| 512 * |
|
| 513 * Once an element cannot be added to the tree, this function returns, storing |
|
| 514 * the pointer of the created node to @p failed. |
|
| 515 * The integer returned by this function denotes the number of elements from |
|
| 516 * the @p src array that have been successfully processed. |
|
| 517 * When all elements could be processed, a @c NULL pointer will be written to |
|
| 518 * @p failed. |
|
| 519 * |
|
| 520 * The advantage of this function compared to multiple invocations of |
|
| 521 * #cx_tree_add() is that the search for the insert locations is not always |
|
| 522 * started from the root node. |
|
| 523 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes |
|
| 524 * of the current insert location before starting from the root node again. |
|
| 525 * When the variable is set to zero, only the last found location is checked |
|
| 526 * again. |
|
| 527 * |
|
| 528 * Refer to the documentation of #cx_tree_add() for more details. |
|
| 529 * |
|
| 530 * @param src a pointer to the source data array |
|
| 531 * @param num the number of elements in the @p src array |
|
| 532 * @param elem_size the size of each element in the @p src array |
|
| 533 * @param sfunc a search function |
|
| 534 * @param cfunc a node creation function |
|
| 535 * @param cdata optional additional data |
|
| 536 * @param failed location where the pointer to a failed node shall be stored |
|
| 537 * @param root the root node of the tree |
|
| 538 * @param loc_parent offset in the node struct for the parent pointer |
|
| 539 * @param loc_children offset in the node struct for the children linked list |
|
| 540 * @param loc_last_child optional offset in the node struct for the pointer to |
|
| 541 * the last child in the linked list (negative if there is no such pointer) |
|
| 542 * @param loc_prev optional offset in the node struct for the prev pointer |
|
| 543 * @param loc_next offset in the node struct for the next pointer |
|
| 544 * @return the number of array elements successfully processed |
|
| 545 * @see cx_tree_add() |
|
| 546 */ |
|
| 547 CX_EXTERN CX_NONNULL_ARG(1, 4, 5, 7, 8) CX_ACCESS_W(7) |
|
| 548 size_t cx_tree_add_array(const void *src, size_t num, size_t elem_size, |
|
| 549 cx_tree_search_func sfunc, cx_tree_node_create_func cfunc, |
|
| 550 void *cdata, void **failed, void *root, |
|
| 551 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, |
|
| 552 ptrdiff_t loc_prev, ptrdiff_t loc_next); |
|
| 553 |
|
| 554 /** |
|
| 555 * Adds data to a tree. |
|
| 556 * |
|
| 557 * An adequate location where to add the new tree node is searched with the |
|
| 558 * specified @p sfunc. |
|
| 559 * |
|
| 560 * When a location is found, the @p cfunc will be invoked with @p cdata. |
|
| 561 * |
|
| 562 * The node returned by @p cfunc will be linked into the tree. |
|
| 563 * When @p sfunc returns a positive integer, the new node will be linked as a |
|
| 564 * child. The other children (now siblings of the new node) are then checked |
|
| 565 * with @p sfunc, whether they could be children of the new node and re-linked |
|
| 566 * accordingly. |
|
| 567 * |
|
| 568 * When @p sfunc returns zero and the found node has a parent, the new |
|
| 569 * node will be added as a sibling - otherwise, the new node will be added |
|
| 570 * as a child. |
|
| 571 * |
|
| 572 * When @p sfunc returns a negative value, the new node will not be added to |
|
| 573 * the tree, and this function returns a non-zero value. |
|
| 574 * The caller should check if @p cnode contains a node pointer and deal with the |
|
| 575 * node that could not be added. |
|
| 576 * |
|
| 577 * This function also returns a non-zero value when @p cfunc tries to allocate |
|
| 578 * a new node but fails to do so. In that case, the pointer stored to @p cnode |
|
| 579 * will be @c NULL. |
|
| 580 * |
|
| 581 * Multiple elements can be added more efficiently with |
|
| 582 * #cx_tree_add_array() or #cx_tree_add_iter(). |
|
| 583 * |
|
| 584 * @param src a pointer to the data |
|
| 585 * @param sfunc a search function |
|
| 586 * @param cfunc a node creation function |
|
| 587 * @param cdata optional additional data |
|
| 588 * @param cnode the location where a pointer to the new node is stored |
|
| 589 * @param root the root node of the tree |
|
| 590 * @param loc_parent offset in the node struct for the parent pointer |
|
| 591 * @param loc_children offset in the node struct for the children linked list |
|
| 592 * @param loc_last_child optional offset in the node struct for the pointer to |
|
| 593 * the last child in the linked list (negative if there is no such pointer) |
|
| 594 * @param loc_prev optional offset in the node struct for the prev pointer |
|
| 595 * @param loc_next offset in the node struct for the next pointer |
|
| 596 * @return zero when a new node was created and added to the tree, |
|
| 597 * non-zero otherwise |
|
| 598 */ |
|
| 599 CX_EXTERN CX_NONNULL_ARG(1, 2, 3, 5, 6) CX_ACCESS_W(5) |
|
| 600 int cx_tree_add(const void *src, |
|
| 601 cx_tree_search_func sfunc, cx_tree_node_create_func cfunc, |
|
| 602 void *cdata, void **cnode, void *root, |
|
| 603 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, |
|
| 604 ptrdiff_t loc_prev, ptrdiff_t loc_next); |
|
| 605 |
|
| 606 |
|
| 607 /** |
|
| 608 * Tree class type. |
|
| 609 */ |
|
| 610 typedef struct cx_tree_class_s cx_tree_class; |
|
| 611 |
306 |
| 612 /** |
307 /** |
| 613 * Base structure that can be used for tree nodes in a #CxTree. |
308 * Base structure that can be used for tree nodes in a #CxTree. |
| 614 */ |
309 */ |
| 615 struct cx_tree_node_base_s { |
310 struct cx_tree_node_base_s { |
| 695 |
370 |
| 696 /** |
371 /** |
| 697 * Offset in the node struct for the next sibling pointer. |
372 * Offset in the node struct for the next sibling pointer. |
| 698 */ |
373 */ |
| 699 ptrdiff_t loc_next; |
374 ptrdiff_t loc_next; |
| 700 }; |
375 |
| |
376 /** |
| |
377 * Offset in the node struct where the payload is located. |
| |
378 */ |
| |
379 ptrdiff_t loc_data; |
| |
380 } CxTree; |
| 701 |
381 |
| 702 /** |
382 /** |
| 703 * Macro to roll out the #cx_tree_node_base_s structure with a custom |
383 * Macro to roll out the #cx_tree_node_base_s structure with a custom |
| 704 * node type. |
384 * node type. |
| 705 * |
385 * |
| 706 * Must be used as the first member in your custom tree struct. |
386 * Must be used as the first member in your custom tree struct. |
| 707 * |
387 * |
| 708 * @param type the data type for the nodes |
388 * @param type the data type for the nodes |
| 709 */ |
389 */ |
| 710 #define CX_TREE_NODE_BASE(type) \ |
390 #define CX_TREE_NODE(type) \ |
| 711 type *parent; \ |
391 type *parent; \ |
| 712 type *children;\ |
392 type *children;\ |
| 713 type *last_child;\ |
393 type *last_child;\ |
| 714 type *prev;\ |
394 type *prev;\ |
| 715 type *next |
395 type *next |
| 716 |
396 |
| 717 /** |
397 /** |
| 718 * Macro for specifying the layout of a base node tree. |
398 * Macro for specifying the layout of a tree node. |
| 719 * |
399 * |
| 720 * When your tree uses #CX_TREE_NODE_BASE, you can use this |
400 * When your tree uses #CX_TREE_NODE, you can use this |
| 721 * macro in all tree functions that expect the layout parameters |
401 * macro in all tree functions that expect the layout parameters |
| 722 * @c loc_parent, @c loc_children, @c loc_last_child, @c loc_prev, |
402 * @c loc_parent, @c loc_children, @c loc_last_child, @c loc_prev, |
| 723 * and @c loc_next. |
403 * and @c loc_next. |
| 724 */ |
404 * @param struct_name the name of the node structure |
| 725 #define cx_tree_node_base_layout \ |
405 */ |
| 726 offsetof(struct cx_tree_node_base_s, parent),\ |
406 #define cx_tree_node_layout(struct_name) \ |
| 727 offsetof(struct cx_tree_node_base_s, children),\ |
407 offsetof(struct_name, parent),\ |
| 728 offsetof(struct cx_tree_node_base_s, last_child),\ |
408 offsetof(struct_name, children),\ |
| 729 offsetof(struct cx_tree_node_base_s, prev), \ |
409 offsetof(struct_name, last_child),\ |
| 730 offsetof(struct cx_tree_node_base_s, next) |
410 offsetof(struct_name, prev), \ |
| 731 |
411 offsetof(struct_name, next) |
| 732 /** |
|
| 733 * The class definition for arbitrary trees. |
|
| 734 */ |
|
| 735 struct cx_tree_class_s { |
|
| 736 /** |
|
| 737 * Member function for inserting a single element. |
|
| 738 * |
|
| 739 * Implementations SHALL NOT simply invoke @p insert_many as this comes |
|
| 740 * with too much overhead. |
|
| 741 */ |
|
| 742 int (*insert_element)(struct cx_tree_s *tree, const void *data); |
|
| 743 |
|
| 744 /** |
|
| 745 * Member function for inserting multiple elements. |
|
| 746 * |
|
| 747 * Implementations SHALL avoid performing a full search in the tree for |
|
| 748 * every element even though the source data MAY be unsorted. |
|
| 749 */ |
|
| 750 size_t (*insert_many)(struct cx_tree_s *tree, struct cx_iterator_base_s *iter, size_t n); |
|
| 751 |
|
| 752 /** |
|
| 753 * Member function for finding a node. |
|
| 754 */ |
|
| 755 void *(*find)(struct cx_tree_s *tree, const void *subtree, const void *data, size_t depth); |
|
| 756 }; |
|
| 757 |
|
| 758 /** |
|
| 759 * Common type for all tree implementations. |
|
| 760 */ |
|
| 761 typedef struct cx_tree_s CxTree; |
|
| 762 |
|
| 763 |
412 |
| 764 /** |
413 /** |
| 765 * Destroys a node and its subtree. |
414 * Destroys a node and its subtree. |
| 766 * |
415 * |
| 767 * It is guaranteed that the simple destructor is invoked before |
416 * It is guaranteed that the simple destructor is invoked before |
| 823 */ |
477 */ |
| 824 CX_EXTERN |
478 CX_EXTERN |
| 825 void cxTreeFree(CxTree *tree); |
479 void cxTreeFree(CxTree *tree); |
| 826 |
480 |
| 827 /** |
481 /** |
| 828 * Creates a new tree structure based on the specified layout. |
482 * Creates a new tree. |
| 829 * |
483 * |
| 830 * The specified @p allocator will be used for creating the tree struct |
484 * The specified @p allocator will be used for creating the tree struct |
| 831 * and SHALL be used by @p create_func to allocate memory for the nodes. |
485 * @em and the nodes. |
| 832 * |
486 * |
| 833 * @note This function will also register an advanced destructor which |
487 * @param allocator the allocator to use |
| 834 * will free the nodes with the allocator's free() method. |
|
| 835 * |
|
| 836 * @param allocator the allocator that shall be used |
|
| 837 * (if @c NULL, the cxDefaultAllocator will be used) |
|
| 838 * @param create_func a function that creates new nodes |
|
| 839 * @param search_func a function that compares two nodes |
|
| 840 * @param search_data_func a function that compares a node with data |
|
| 841 * @param loc_parent offset in the node struct for the parent pointer |
|
| 842 * @param loc_children offset in the node struct for the children linked list |
|
| 843 * @param loc_last_child optional offset in the node struct for the pointer to |
|
| 844 * the last child in the linked list (negative if there is no such pointer) |
|
| 845 * @param loc_prev optional offset in the node struct for the prev pointer |
|
| 846 * @param loc_next offset in the node struct for the next pointer |
|
| 847 * @return the new tree |
|
| 848 * @see cxTreeCreateSimple() |
|
| 849 * @see cxTreeCreateWrapped() |
|
| 850 */ |
|
| 851 CX_EXTERN CX_NONNULL_ARG(2, 3, 4) CX_NODISCARD CX_MALLOC CX_DEALLOC(cxTreeFree, 1) |
|
| 852 CxTree *cxTreeCreate(const CxAllocator *allocator, cx_tree_node_create_func create_func, |
|
| 853 cx_tree_search_func search_func, cx_tree_search_data_func search_data_func, |
|
| 854 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, |
|
| 855 ptrdiff_t loc_prev, ptrdiff_t loc_next); |
|
| 856 |
|
| 857 /** |
|
| 858 * Creates a new tree structure based on a default layout. |
|
| 859 * |
|
| 860 * Nodes created by @p create_func MUST contain #cx_tree_node_base_s as the first |
|
| 861 * member (or at least respect the default offsets specified in the tree |
|
| 862 * struct), and they MUST be allocated with the specified allocator. |
|
| 863 * |
|
| 864 * @note This function will also register an advanced destructor which |
|
| 865 * will free the nodes with the allocator's free() method. |
|
| 866 * |
|
| 867 * @param allocator (@c CxAllocator*) the allocator that shall be used |
|
| 868 * @param create_func (@c cx_tree_node_create_func) a function that creates new nodes |
|
| 869 * @param search_func (@c cx_tree_search_func) a function that compares two nodes |
|
| 870 * @param search_data_func (@c cx_tree_search_data_func) a function that compares a node with data |
|
| 871 * @return (@c CxTree*) the new tree |
|
| 872 * @see cxTreeCreate() |
|
| 873 */ |
|
| 874 #define cxTreeCreateSimple(allocator, create_func, search_func, search_data_func) \ |
|
| 875 cxTreeCreate(allocator, create_func, search_func, search_data_func, cx_tree_node_base_layout) |
|
| 876 |
|
| 877 /** |
|
| 878 * Creates a new tree structure based on an existing tree. |
|
| 879 * |
|
| 880 * The specified @p allocator will be used for creating the tree struct. |
|
| 881 * |
|
| 882 * @attention This function will create an incompletely defined tree structure |
|
| 883 * where neither the create function, the search function, nor a destructor |
|
| 884 * will be set. If you wish to use any of this functionality for the wrapped |
|
| 885 * tree, you need to specify those functions afterward. |
|
| 886 * |
|
| 887 * @param allocator the allocator that was used for nodes of the wrapped tree |
|
| 888 * (if @c NULL, the cxDefaultAllocator is assumed) |
488 * (if @c NULL, the cxDefaultAllocator is assumed) |
| 889 * @param root the root node of the tree that shall be wrapped |
489 * @param node_size the complete size of one node |
| |
490 * @param elem_size the size of the payload stored in the node |
| |
491 * (@c CX_STORE_POINTERS is also supported) |
| |
492 * @param root an optional already existing root node |
| |
493 * @param loc_data optional offset in the node struct for the payload |
| |
494 * (when negative, cxTreeAddData() is not supported) |
| 890 * @param loc_parent offset in the node struct for the parent pointer |
495 * @param loc_parent offset in the node struct for the parent pointer |
| 891 * @param loc_children offset in the node struct for the children linked list |
496 * @param loc_children offset in the node struct for the children linked list |
| 892 * @param loc_last_child optional offset in the node struct for the pointer to |
497 * @param loc_last_child optional offset in the node struct for the pointer to |
| 893 * the last child in the linked list (negative if there is no such pointer) |
498 * the last child in the linked list (negative if there is no such pointer) |
| 894 * @param loc_prev optional offset in the node struct for the prev pointer |
499 * @param loc_prev optional offset in the node struct for the prev pointer |
| 895 * @param loc_next offset in the node struct for the next pointer |
500 * @param loc_next offset in the node struct for the next pointer |
| 896 * @return the new tree |
501 * @return the new tree |
| 897 * @see cxTreeCreate() |
502 * @see cxTreeCreate() |
| 898 */ |
503 */ |
| 899 CX_EXTERN CX_NONNULL_ARG(2) CX_NODISCARD CX_MALLOC CX_DEALLOC(cxTreeFree, 1) |
504 CX_EXTERN CX_NODISCARD CX_MALLOC CX_DEALLOC(cxTreeFree, 1) |
| 900 CxTree *cxTreeCreateWrapped(const CxAllocator *allocator, void *root, |
505 CxTree *cxTreeCreate(const CxAllocator *allocator, |
| |
506 size_t node_size, size_t elem_size, void *root, ptrdiff_t loc_data, |
| 901 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, |
507 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, |
| 902 ptrdiff_t loc_prev, ptrdiff_t loc_next); |
508 ptrdiff_t loc_prev, ptrdiff_t loc_next); |
| 903 |
509 |
| 904 /** |
510 /** |
| 905 * Inserts data into the tree. |
|
| 906 * |
|
| 907 * @remark For this function to work, the tree needs specified search and |
|
| 908 * create functions, which might not be available for wrapped trees |
|
| 909 * (see #cxTreeCreateWrapped()). |
|
| 910 * |
|
| 911 * @param tree the tree |
|
| 912 * @param data the data to insert |
|
| 913 * @retval zero success |
|
| 914 * @retval non-zero failure |
|
| 915 */ |
|
| 916 CX_EXTERN CX_NONNULL |
|
| 917 int cxTreeInsert(CxTree *tree, const void *data); |
|
| 918 |
|
| 919 /** |
|
| 920 * Inserts elements provided by an iterator efficiently into the tree. |
|
| 921 * |
|
| 922 * @remark For this function to work, the tree needs specified search and |
|
| 923 * create functions, which might not be available for wrapped trees |
|
| 924 * (see #cxTreeCreateWrapped()). |
|
| 925 * |
|
| 926 * @param tree the tree |
|
| 927 * @param iter the iterator providing the elements |
|
| 928 * @param n the maximum number of elements to insert |
|
| 929 * @return the number of elements that could be successfully inserted |
|
| 930 */ |
|
| 931 CX_EXTERN CX_NONNULL |
|
| 932 size_t cxTreeInsertIter(CxTree *tree, CxIteratorBase *iter, size_t n); |
|
| 933 |
|
| 934 /** |
|
| 935 * Inserts an array of data efficiently into the tree. |
|
| 936 * |
|
| 937 * @remark For this function to work, the tree needs specified search and |
|
| 938 * create functions, which might not be available for wrapped trees |
|
| 939 * (see #cxTreeCreateWrapped()). |
|
| 940 * |
|
| 941 * @param tree the tree |
|
| 942 * @param data the array of data to insert |
|
| 943 * @param elem_size the size of each element in the array |
|
| 944 * @param n the number of elements in the array |
|
| 945 * @return the number of elements that could be successfully inserted |
|
| 946 */ |
|
| 947 CX_EXTERN CX_NONNULL |
|
| 948 size_t cxTreeInsertArray(CxTree *tree, const void *data, size_t elem_size, size_t n); |
|
| 949 |
|
| 950 /** |
|
| 951 * Searches the data in the specified tree. |
|
| 952 * |
|
| 953 * @remark For this function to work, the tree needs a specified @c search_data |
|
| 954 * function, which might not be available wrapped trees |
|
| 955 * (see #cxTreeCreateWrapped()). |
|
| 956 * |
|
| 957 * @param tree the tree |
|
| 958 * @param data the data to search for |
|
| 959 * @return the first matching node, or @c NULL when the data cannot be found |
|
| 960 */ |
|
| 961 CX_EXTERN CX_NONNULL CX_NODISCARD |
|
| 962 void *cxTreeFind(CxTree *tree, const void *data); |
|
| 963 |
|
| 964 /** |
|
| 965 * Searches the data in the specified subtree. |
511 * Searches the data in the specified subtree. |
| 966 * |
512 * |
| 967 * When @p max_depth is zero, the depth is not limited. |
513 * When @p max_depth is zero, the depth is not limited. |
| 968 * The @p subtree_root itself is on depth 1 and its children have depth 2. |
514 * The @p subtree_root itself is on depth 1 and its children have depth 2. |
| 969 * |
515 * |
| 970 * @note When @p subtree_root is not part of the @p tree, the behavior is |
516 * @note When @p subtree_root is not @c NULL and not part of the @p tree, |
| 971 * undefined. |
517 * the behavior is undefined. |
| 972 * |
518 * |
| 973 * @remark For this function to work, the tree needs a specified @c search_data |
519 * @attention When @p loc_data is not available, this function immediately returns |
| 974 * function, which might not be the case for wrapped trees |
520 * @c NULL. |
| 975 * (see #cxTreeCreateWrapped()). |
|
| 976 * |
521 * |
| 977 * @param tree the tree |
522 * @param tree the tree |
| 978 * @param data the data to search for |
523 * @param data the data to search for |
| 979 * @param subtree_root the node where to start |
524 * @param subtree_root the node where to start (@c NULL to start from root) |
| |
525 * @param max_depth the maximum search depth |
| |
526 * @param use_dfs @c true when depth-first search should be used; |
| |
527 * @c false when breadth-first search should be used |
| |
528 * @return the first matching node, or @c NULL when the data cannot be found |
| |
529 * @see cxTreeFind() |
| |
530 */ |
| |
531 CX_EXTERN CX_NONNULL_ARG(1, 2) CX_NODISCARD |
| |
532 void *cxTreeFindInSubtree(CxTree *tree, const void *data, void *subtree_root, |
| |
533 size_t max_depth, bool use_dfs); |
| |
534 |
| |
535 /** |
| |
536 * Searches the data in the specified tree. |
| |
537 * |
| |
538 * @attention When @p loc_data is not available, this function immediately returns |
| |
539 * @c NULL. |
| |
540 * |
| |
541 * @param tree the tree |
| |
542 * @param data the data to search for |
| |
543 * @param use_dfs @c true when depth-first search should be used; |
| |
544 * @c false when breadth-first search should be used |
| |
545 * @return the first matching node, or @c NULL when the data cannot be found |
| |
546 * @see cxTreeFindInSubtree() |
| |
547 * @see cxTreeFindFast() |
| |
548 */ |
| |
549 CX_INLINE CX_NONNULL CX_NODISCARD |
| |
550 void *cxTreeFind(CxTree *tree, const void *data, bool use_dfs) { |
| |
551 if (tree->root == NULL) return NULL; |
| |
552 return cxTreeFindInSubtree(tree, data, tree->root, 0, use_dfs); |
| |
553 } |
| |
554 |
| |
555 /** |
| |
556 * Performs an efficient depth-first search in a branch of the specified tree. |
| |
557 * |
| |
558 * When @p max_depth is zero, the depth is not limited. |
| |
559 * The @p subtree_root itself is on depth 1 and its children have depth 2. |
| |
560 * |
| |
561 * @note When @p subtree_root is not @c NULL and not part of the @p tree, |
| |
562 * the behavior is undefined. |
| |
563 * |
| |
564 * @param tree the tree |
| |
565 * @param data the data to search for |
| |
566 * @param sfunc the search function |
| |
567 * @param subtree_root the node where to start (@c NULL to start from root) |
| 980 * @param max_depth the maximum search depth |
568 * @param max_depth the maximum search depth |
| 981 * @return the first matching node, or @c NULL when the data cannot be found |
569 * @return the first matching node, or @c NULL when the data cannot be found |
| |
570 * @see cxTreeFindInSubtree() |
| 982 */ |
571 */ |
| 983 CX_EXTERN CX_NONNULL CX_NODISCARD |
572 CX_EXTERN CX_NONNULL CX_NODISCARD |
| 984 void *cxTreeFindInSubtree(CxTree *tree, const void *data, void *subtree_root, size_t max_depth); |
573 void *cxTreeFindFastInSubtree(CxTree *tree, const void *data, |
| |
574 cx_tree_search_func sfunc, void *subtree_root, size_t max_depth); |
| |
575 |
| |
576 /** |
| |
577 * Performs an efficient depth-first search in the tree. |
| |
578 * |
| |
579 * @param tree the tree |
| |
580 * @param data the data to search for |
| |
581 * @param sfunc the search function |
| |
582 * @return the first matching node, or @c NULL when the data cannot be found |
| |
583 * @see cxTreeFind() |
| |
584 */ |
| |
585 CX_INLINE CX_NONNULL CX_NODISCARD |
| |
586 void *cxTreeFindFast(CxTree *tree, const void *data, cx_tree_search_func sfunc) { |
| |
587 return cxTreeFindFastInSubtree(tree, data, sfunc, tree->root, 0); |
| |
588 } |
| 985 |
589 |
| 986 /** |
590 /** |
| 987 * Determines the size of the specified subtree. |
591 * Determines the size of the specified subtree. |
| 988 * |
592 * |
| 989 * @param tree the tree |
593 * @param tree the tree |
| 1090 * |
694 * |
| 1091 * If the @p child is already a member of the tree, the behavior is undefined. |
695 * If the @p child is already a member of the tree, the behavior is undefined. |
| 1092 * Use #cxTreeSetParent() if you want to move a subtree to another location. |
696 * Use #cxTreeSetParent() if you want to move a subtree to another location. |
| 1093 * |
697 * |
| 1094 * @attention The node may be externally created, but MUST obey the same rules |
698 * @attention The node may be externally created, but MUST obey the same rules |
| 1095 * as if it was created by the tree itself with #cxTreeAddChild() (e.g., use |
699 * as if it was created by the tree itself with #cxTreeAddData() (e.g., use |
| 1096 * the same allocator). |
700 * the tree's allocator). |
| 1097 * |
701 * |
| 1098 * @param tree the tree |
702 * @param tree the tree |
| 1099 * @param parent the parent of the node to add |
703 * @param parent the parent of the node to add |
| 1100 * @param child the node to add |
704 * @param child the node to add |
| 1101 * @see cxTreeSetParent() |
705 * @see cxTreeSetParent() |
| |
706 * @see cxTreeAddData() |
| 1102 */ |
707 */ |
| 1103 CX_EXTERN CX_NONNULL |
708 CX_EXTERN CX_NONNULL |
| 1104 void cxTreeAddChildNode(CxTree *tree, void *parent, void *child); |
709 void cxTreeAddNode(CxTree *tree, void *parent, void *child); |
| 1105 |
710 |
| 1106 /** |
711 /** |
| 1107 * Creates a new node and adds it to the tree. |
712 * Creates a new node and adds it to the tree. |
| 1108 * |
|
| 1109 * With this function you can decide where exactly the new node shall be added. |
|
| 1110 * If you specified an appropriate search function, you may want to consider |
|
| 1111 * leaving this task to the tree by using #cxTreeInsert(). |
|
| 1112 * |
|
| 1113 * Be aware that adding nodes at arbitrary locations in the tree might cause |
|
| 1114 * wrong or undesired results when subsequently invoking #cxTreeInsert(), and |
|
| 1115 * the invariant imposed by the search function does not hold any longer. |
|
| 1116 * |
713 * |
| 1117 * @param tree the tree |
714 * @param tree the tree |
| 1118 * @param parent the parent node of the new node |
715 * @param parent the parent node of the new node |
| 1119 * @param data the data that will be submitted to the create function |
716 * @param data the data that will be submitted to the create function |
| 1120 * @return zero when the new node was created, non-zero on allocation failure |
717 * @return the added node or @c NULL when the allocation failed |
| 1121 * @see cxTreeInsert() |
718 * @see cxTreeAdd() |
| 1122 */ |
719 */ |
| 1123 CX_EXTERN CX_NONNULL |
720 CX_EXTERN CX_NONNULL |
| 1124 int cxTreeAddChild(CxTree *tree, void *parent, const void *data); |
721 void *cxTreeAddData(CxTree *tree, void *parent, const void *data); |
| |
722 |
| |
723 CX_EXTERN CX_NODISCARD |
| |
724 void *cxTreeCreateRoot(CxTree *tree); |
| |
725 |
| |
726 CX_EXTERN CX_NODISCARD |
| |
727 void *cxTreeCreateRootData(CxTree *tree, const void *data); |
| |
728 |
| |
729 CX_EXTERN CX_NONNULL_ARG(1) CX_NODISCARD |
| |
730 void *cxTreeSetRoot(CxTree *tree, void *new_root); |
| 1125 |
731 |
| 1126 /** |
732 /** |
| 1127 * A function that is invoked when a node needs to be re-linked to a new parent. |
733 * A function that is invoked when a node needs to be re-linked to a new parent. |
| 1128 * |
734 * |
| 1129 * When a node is re-linked, sometimes the contents need to be updated. |
735 * When a node is re-linked, sometimes the contents need to be updated. |