ucx/cx/tree.h

changeset 852
83fdf679df99
parent 816
839fefbdedc7
equal deleted inserted replaced
850:bbe2925eb590 852:83fdf679df99
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 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 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 /** 28 /**
29 * \file tree.h 29 * @file tree.h
30 * \brief Interface for tree implementations. 30 * @brief Interface for tree implementations.
31 * \author Mike Becker 31 * @author Mike Becker
32 * \author Olaf Wintermann 32 * @author Olaf Wintermann
33 * \copyright 2-Clause BSD License 33 * @copyright 2-Clause BSD License
34 */ 34 */
35 35
36 #ifndef UCX_TREE_H 36 #ifndef UCX_TREE_H
37 #define UCX_TREE_H 37 #define UCX_TREE_H
38 38
39 #include "common.h" 39 #include "common.h"
40 40
41 #include "iterator.h" 41 #include "collection.h"
42 42
43 #ifdef __cplusplus 43 #ifdef __cplusplus
44 extern "C" { 44 extern "C" {
45 #endif 45 #endif
46 46
47 /** 47 /**
48 * A depth-first tree iterator. 48 * A depth-first tree iterator.
49 * 49 *
50 * This iterator is not position-aware in a strict sense, as it does not assume a particular order of elements in the 50 * This iterator is not position-aware in a strict sense, as it does not assume
51 * tree. However, the iterator keeps track of the number of nodes it has passed in a counter variable. 51 * a particular order of elements in the tree. However, the iterator keeps track
52 * of the number of nodes it has passed in a counter variable.
52 * Each node, regardless of the number of passes, is counted only once. 53 * Each node, regardless of the number of passes, is counted only once.
53 * 54 *
54 * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the 55 * @note Objects that are pointed to by an iterator are mutable through that
55 * underlying data structure is mutated by other means than this iterator (e.g. elements added or removed), 56 * iterator. However, if the
56 * the iterator becomes invalid (regardless of what cxIteratorValid() returns). 57 * underlying data structure is mutated by other means than this iterator (e.g.
58 * elements added or removed), the iterator becomes invalid (regardless of what
59 * cxIteratorValid() returns).
57 * 60 *
58 * @see CxIterator 61 * @see CxIterator
59 */ 62 */
60 typedef struct cx_tree_iterator_s { 63 typedef struct cx_tree_iterator_s {
61 /** 64 /**
133 /** 136 /**
134 * The depth of the node. 137 * The depth of the node.
135 */ 138 */
136 size_t depth; 139 size_t depth;
137 /** 140 /**
138 * The next element in the queue or \c NULL. 141 * The next element in the queue or @c NULL.
139 */ 142 */
140 struct cx_tree_visitor_queue_s *next; 143 struct cx_tree_visitor_queue_s *next;
141 }; 144 };
142 145
143 /** 146 /**
144 * A breadth-first tree iterator. 147 * A breadth-first tree iterator.
145 * 148 *
146 * This iterator needs to maintain a visitor queue that will be automatically freed once the iterator becomes invalid. 149 * This iterator needs to maintain a visitor queue that will be automatically
147 * If you want to discard the iterator before, you MUST manually call cxTreeVisitorDispose(). 150 * freed once the iterator becomes invalid.
148 * 151 * If you want to discard the iterator before, you MUST manually call
149 * This iterator is not position-aware in a strict sense, as it does not assume a particular order of elements in the 152 * cxTreeVisitorDispose().
150 * tree. However, the iterator keeps track of the number of nodes it has passed in a counter variable. 153 *
154 * This iterator is not position-aware in a strict sense, as it does not assume
155 * a particular order of elements in the tree. However, the iterator keeps track
156 * of the number of nodes it has passed in a counter variable.
151 * Each node, regardless of the number of passes, is counted only once. 157 * Each node, regardless of the number of passes, is counted only once.
152 * 158 *
153 * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the 159 * @note Objects that are pointed to by an iterator are mutable through that
154 * underlying data structure is mutated by other means than this iterator (e.g. elements added or removed), 160 * iterator. However, if the
155 * the iterator becomes invalid (regardless of what cxIteratorValid() returns). 161 * underlying data structure is mutated by other means than this iterator (e.g.
162 * elements added or removed), the iterator becomes invalid (regardless of what
163 * cxIteratorValid() returns).
156 * 164 *
157 * @see CxIterator 165 * @see CxIterator
158 */ 166 */
159 typedef struct cx_tree_visitor_s { 167 typedef struct cx_tree_visitor_s {
160 /** 168 /**
199 207
200 /** 208 /**
201 * Releases internal memory of the given tree iterator. 209 * Releases internal memory of the given tree iterator.
202 * @param iter the iterator 210 * @param iter the iterator
203 */ 211 */
204 __attribute__((__nonnull__)) 212 cx_attr_nonnull
205 static inline void cxTreeIteratorDispose(CxTreeIterator *iter) { 213 static inline void cxTreeIteratorDispose(CxTreeIterator *iter) {
206 free(iter->stack); 214 free(iter->stack);
207 iter->stack = NULL; 215 iter->stack = NULL;
208 } 216 }
209 217
210 /** 218 /**
211 * Releases internal memory of the given tree visitor. 219 * Releases internal memory of the given tree visitor.
212 * @param visitor the visitor 220 * @param visitor the visitor
213 */ 221 */
214 __attribute__((__nonnull__)) 222 cx_attr_nonnull
215 static inline void cxTreeVisitorDispose(CxTreeVisitor *visitor) { 223 static inline void cxTreeVisitorDispose(CxTreeVisitor *visitor) {
216 struct cx_tree_visitor_queue_s *q = visitor->queue_next; 224 struct cx_tree_visitor_queue_s *q = visitor->queue_next;
217 while (q != NULL) { 225 while (q != NULL) {
218 struct cx_tree_visitor_queue_s *next = q->next; 226 struct cx_tree_visitor_queue_s *next = q->next;
219 free(q); 227 free(q);
223 231
224 /** 232 /**
225 * Advises the iterator to skip the subtree below the current node and 233 * Advises the iterator to skip the subtree below the current node and
226 * also continues the current loop. 234 * also continues the current loop.
227 * 235 *
228 * @param iterator the iterator 236 * @param iterator (@c CxTreeIterator) the iterator
229 */ 237 */
230 #define cxTreeIteratorContinue(iterator) (iterator).skip = true; continue 238 #define cxTreeIteratorContinue(iterator) (iterator).skip = true; continue
231 239
232 /** 240 /**
233 * Advises the visitor to skip the subtree below the current node and 241 * Advises the visitor to skip the subtree below the current node and
234 * also continues the current loop. 242 * also continues the current loop.
235 * 243 *
236 * @param visitor the visitor 244 * @param visitor (@c CxTreeVisitor) the visitor
237 */ 245 */
238 #define cxTreeVisitorContinue(visitor) cxTreeIteratorContinue(visitor) 246 #define cxTreeVisitorContinue(visitor) cxTreeIteratorContinue(visitor)
239 247
240 /** 248 /**
241 * Links a node to a (new) parent. 249 * Links a node to a (new) parent.
242 * 250 *
243 * If the node has already a parent, it is unlinked, first. 251 * If the node has already a parent, it is unlinked, first.
244 * If the parent has children already, the node is \em prepended to the list 252 * If the parent has children already, the node is @em appended to the list
245 * of all currently existing children. 253 * of all currently existing children.
246 * 254 *
247 * @param parent the parent node 255 * @param parent the parent node
248 * @param node the node that shall be linked 256 * @param node the node that shall be linked
249 * @param loc_parent offset in the node struct for the parent pointer 257 * @param loc_parent offset in the node struct for the parent pointer
250 * @param loc_children offset in the node struct for the children linked list 258 * @param loc_children offset in the node struct for the children linked list
251 * @param loc_prev offset in the node struct for the prev pointer 259 * @param loc_last_child optional offset in the node struct for the pointer to
260 * the last child in the linked list (negative if there is no such pointer)
261 * @param loc_prev optional offset in the node struct for the prev pointer
252 * @param loc_next offset in the node struct for the next pointer 262 * @param loc_next offset in the node struct for the next pointer
253 * @see cx_tree_unlink() 263 * @see cx_tree_unlink()
254 */ 264 */
255 __attribute__((__nonnull__)) 265 cx_attr_nonnull
256 void cx_tree_link( 266 void cx_tree_link(
257 void * restrict parent, 267 void *parent,
258 void * restrict node, 268 void *node,
259 ptrdiff_t loc_parent, 269 ptrdiff_t loc_parent,
260 ptrdiff_t loc_children, 270 ptrdiff_t loc_children,
271 ptrdiff_t loc_last_child,
261 ptrdiff_t loc_prev, 272 ptrdiff_t loc_prev,
262 ptrdiff_t loc_next 273 ptrdiff_t loc_next
263 ); 274 );
264 275
265 /** 276 /**
268 * If the node has no parent, this function does nothing. 279 * If the node has no parent, this function does nothing.
269 * 280 *
270 * @param node the node that shall be unlinked from its parent 281 * @param node the node that shall be unlinked from its parent
271 * @param loc_parent offset in the node struct for the parent pointer 282 * @param loc_parent offset in the node struct for the parent pointer
272 * @param loc_children offset in the node struct for the children linked list 283 * @param loc_children offset in the node struct for the children linked list
273 * @param loc_prev offset in the node struct for the prev pointer 284 * @param loc_last_child optional offset in the node struct for the pointer to
285 * the last child in the linked list (negative if there is no such pointer)
286 * @param loc_prev optional offset in the node struct for the prev pointer
274 * @param loc_next offset in the node struct for the next pointer 287 * @param loc_next offset in the node struct for the next pointer
275 * @see cx_tree_link() 288 * @see cx_tree_link()
276 */ 289 */
277 __attribute__((__nonnull__)) 290 cx_attr_nonnull
278 void cx_tree_unlink( 291 void cx_tree_unlink(
279 void *node, 292 void *node,
280 ptrdiff_t loc_parent, 293 ptrdiff_t loc_parent,
281 ptrdiff_t loc_children, 294 ptrdiff_t loc_children,
295 ptrdiff_t loc_last_child,
282 ptrdiff_t loc_prev, 296 ptrdiff_t loc_prev,
283 ptrdiff_t loc_next 297 ptrdiff_t loc_next
284 ); 298 );
285 299
286 /** 300 /**
301 * Macro that can be used instead of the magic value for infinite search depth.
302 */
303 #define CX_TREE_SEARCH_INFINITE_DEPTH 0
304
305 /**
287 * Function pointer for a search function. 306 * Function pointer for a search function.
288 * 307 *
289 * A function of this kind shall check if the specified \p node 308 * A function of this kind shall check if the specified @p node
290 * contains the given \p data or if one of the children might contain 309 * contains the given @p data or if one of the children might contain
291 * the data. 310 * the data.
292 * 311 *
293 * The function should use the returned integer to indicate how close the 312 * The function should use the returned integer to indicate how close the
294 * match is, where a negative number means that it does not match at all. 313 * match is, where a negative number means that it does not match at all.
314 * Zero means exact match and a positive number is an implementation defined
315 * measure for the distance to an exact match.
295 * 316 *
296 * For example if a tree stores file path information, a node that is 317 * For example if a tree stores file path information, a node that is
297 * describing a parent directory of a filename that is searched, shall 318 * describing a parent directory of a filename that is searched, shall
298 * return a positive number to indicate that a child node might contain the 319 * return a positive number to indicate that a child node might contain the
299 * searched item. On the other hand, if the node denotes a path that is not a 320 * searched item. On the other hand, if the node denotes a path that is not a
300 * prefix of the searched filename, the function would return -1 to indicate 321 * prefix of the searched filename, the function would return -1 to indicate
301 * that * the search does not need to be continued in that branch. 322 * that the search does not need to be continued in that branch.
302 * 323 *
303 * @param node the node that is currently investigated 324 * @param node the node that is currently investigated
304 * @param data the data that is searched for 325 * @param data the data that is searched for
305 * 326 *
306 * @return 0 if the node contains the data, 327 * @return 0 if the node contains the data,
307 * positive if one of the children might contain the data, 328 * positive if one of the children might contain the data,
308 * negative if neither the node, nor the children contains the data 329 * negative if neither the node, nor the children contains the data
309 */ 330 */
310 typedef int (*cx_tree_search_func)(void const *node, void const* data); 331 cx_attr_nonnull
311 332 typedef int (*cx_tree_search_data_func)(const void *node, const void *data);
333
334
335 /**
336 * Function pointer for a search function.
337 *
338 * A function of this kind shall check if the specified @p node
339 * contains the same @p data as @p new_node or if one of the children might
340 * contain the data.
341 *
342 * The function should use the returned integer to indicate how close the
343 * match is, where a negative number means that it does not match at all.
344 * Zero means exact match and a positive number is an implementation defined
345 * measure for the distance to an exact match.
346 *
347 * For example if a tree stores file path information, a node that is
348 * describing a parent directory of a filename that is searched, shall
349 * return a positive number to indicate that a child node might contain the
350 * searched item. On the other hand, if the node denotes a path that is not a
351 * prefix of the searched filename, the function would return -1 to indicate
352 * that the search does not need to be continued in that branch.
353 *
354 * @param node the node that is currently investigated
355 * @param new_node a new node with the information which is searched
356 *
357 * @return 0 if @p node contains the same data as @p new_node,
358 * positive if one of the children might contain the data,
359 * negative if neither the node, nor the children contains the data
360 */
361 cx_attr_nonnull
362 typedef int (*cx_tree_search_func)(const void *node, const void *new_node);
312 363
313 /** 364 /**
314 * Searches for data in a tree. 365 * Searches for data in a tree.
315 * 366 *
316 * When the data cannot be found exactly, the search function might return a 367 * When the data cannot be found exactly, the search function might return a
317 * closest result which might be a good starting point for adding a new node 368 * closest result which might be a good starting point for adding a new node
318 * to the tree. 369 * to the tree (see also #cx_tree_add()).
319 * 370 *
320 * Depending on the tree structure it is not necessarily guaranteed that the 371 * Depending on the tree structure it is not necessarily guaranteed that the
321 * "closest" match is uniquely defined. This function will search for a node 372 * "closest" match is uniquely defined. This function will search for a node
322 * with the best match according to the \p sfunc (meaning: the return value of 373 * with the best match according to the @p sfunc (meaning: the return value of
323 * \p sfunc which is closest to zero). If that is also ambiguous, an arbitrary 374 * @p sfunc which is closest to zero). If that is also ambiguous, an arbitrary
324 * node matching the criteria is returned. 375 * node matching the criteria is returned.
325 * 376 *
326 * @param root the root node 377 * @param root the root node
378 * @param depth the maximum depth (zero=indefinite, one=just root)
327 * @param data the data to search for 379 * @param data the data to search for
328 * @param sfunc the search function 380 * @param sfunc the search function
329 * @param result where the result shall be stored 381 * @param result where the result shall be stored
330 * @param loc_children offset in the node struct for the children linked list 382 * @param loc_children offset in the node struct for the children linked list
331 * @param loc_next offset in the node struct for the next pointer 383 * @param loc_next offset in the node struct for the next pointer
332 * @return zero if the node was found exactly, positive if a node was found that 384 * @return zero if the node was found exactly, positive if a node was found that
333 * could contain the node (but doesn't right now), negative if the tree does not 385 * could contain the node (but doesn't right now), negative if the tree does not
334 * contain any node that might be related to the searched data 386 * contain any node that might be related to the searched data
335 */ 387 */
336 __attribute__((__nonnull__)) 388 cx_attr_nonnull
389 cx_attr_access_w(5)
390 int cx_tree_search_data(
391 const void *root,
392 size_t depth,
393 const void *data,
394 cx_tree_search_data_func sfunc,
395 void **result,
396 ptrdiff_t loc_children,
397 ptrdiff_t loc_next
398 );
399
400 /**
401 * Searches for a node in a tree.
402 *
403 * When no node with the same data can be found, the search function might
404 * return a closest result which might be a good starting point for adding the
405 * new node to the tree (see also #cx_tree_add()).
406 *
407 * Depending on the tree structure it is not necessarily guaranteed that the
408 * "closest" match is uniquely defined. This function will search for a node
409 * with the best match according to the @p sfunc (meaning: the return value of
410 * @p sfunc which is closest to zero). If that is also ambiguous, an arbitrary
411 * node matching the criteria is returned.
412 *
413 * @param root the root node
414 * @param depth the maximum depth (zero=indefinite, one=just root)
415 * @param node the node to search for
416 * @param sfunc the search function
417 * @param result where the result shall be stored
418 * @param loc_children offset in the node struct for the children linked list
419 * @param loc_next offset in the node struct for the next pointer
420 * @return zero if the node was found exactly, positive if a node was found that
421 * could contain the node (but doesn't right now), negative if the tree does not
422 * contain any node that might be related to the searched data
423 */
424 cx_attr_nonnull
425 cx_attr_access_w(5)
337 int cx_tree_search( 426 int cx_tree_search(
338 void const *root, 427 const void *root,
339 void const *data, 428 size_t depth,
429 const void *node,
340 cx_tree_search_func sfunc, 430 cx_tree_search_func sfunc,
341 void **result, 431 void **result,
342 ptrdiff_t loc_children, 432 ptrdiff_t loc_children,
343 ptrdiff_t loc_next 433 ptrdiff_t loc_next
344 ); 434 );
345 435
346 /** 436 /**
347 * Creates a depth-first iterator for a tree with the specified root node. 437 * Creates a depth-first iterator for a tree with the specified root node.
348 * 438 *
349 * @note A tree iterator needs to maintain a stack of visited nodes, which is allocated using stdlib malloc(). 439 * @note A tree iterator needs to maintain a stack of visited nodes, which is
350 * When the iterator becomes invalid, this memory is automatically released. However, if you wish to cancel the 440 * allocated using stdlib malloc().
351 * iteration before the iterator becomes invalid by itself, you MUST call cxTreeIteratorDispose() manually to release 441 * When the iterator becomes invalid, this memory is automatically released.
442 * However, if you wish to cancel the iteration before the iterator becomes
443 * invalid by itself, you MUST call cxTreeIteratorDispose() manually to release
352 * the memory. 444 * the memory.
353 * 445 *
354 * @remark The returned iterator does not support cxIteratorFlagRemoval(). 446 * @remark The returned iterator does not support cxIteratorFlagRemoval().
355 * 447 *
356 * @param root the root node 448 * @param root the root node
357 * @param visit_on_exit set to true, when the iterator shall visit a node again after processing all children 449 * @param visit_on_exit set to true, when the iterator shall visit a node again
450 * after processing all children
358 * @param loc_children offset in the node struct for the children linked list 451 * @param loc_children offset in the node struct for the children linked list
359 * @param loc_next offset in the node struct for the next pointer 452 * @param loc_next offset in the node struct for the next pointer
360 * @return the new tree iterator 453 * @return the new tree iterator
361 * @see cxTreeIteratorDispose() 454 * @see cxTreeIteratorDispose()
362 */ 455 */
363 __attribute__((__nonnull__)) 456 cx_attr_nodiscard
364 CxTreeIterator cx_tree_iterator( 457 CxTreeIterator cx_tree_iterator(
365 void *root, 458 void *root,
366 bool visit_on_exit, 459 bool visit_on_exit,
367 ptrdiff_t loc_children, 460 ptrdiff_t loc_children,
368 ptrdiff_t loc_next 461 ptrdiff_t loc_next
369 ); 462 );
370 463
371 /** 464 /**
372 * Creates a breadth-first iterator for a tree with the specified root node. 465 * Creates a breadth-first iterator for a tree with the specified root node.
373 * 466 *
374 * @note A tree visitor needs to maintain a queue of to be visited nodes, which is allocated using stdlib malloc(). 467 * @note A tree visitor needs to maintain a queue of to be visited nodes, which
375 * When the visitor becomes invalid, this memory is automatically released. However, if you wish to cancel the 468 * is allocated using stdlib malloc().
376 * iteration before the visitor becomes invalid by itself, you MUST call cxTreeVisitorDispose() manually to release 469 * When the visitor becomes invalid, this memory is automatically released.
470 * However, if you wish to cancel the iteration before the visitor becomes
471 * invalid by itself, you MUST call cxTreeVisitorDispose() manually to release
377 * the memory. 472 * the memory.
378 * 473 *
379 * @remark The returned iterator does not support cxIteratorFlagRemoval(). 474 * @remark The returned iterator does not support cxIteratorFlagRemoval().
380 * 475 *
381 * @param root the root node 476 * @param root the root node
382 * @param loc_children offset in the node struct for the children linked list 477 * @param loc_children offset in the node struct for the children linked list
383 * @param loc_next offset in the node struct for the next pointer 478 * @param loc_next offset in the node struct for the next pointer
384 * @return the new tree visitor 479 * @return the new tree visitor
385 * @see cxTreeVisitorDispose() 480 * @see cxTreeVisitorDispose()
386 */ 481 */
387 __attribute__((__nonnull__)) 482 cx_attr_nodiscard
388 CxTreeVisitor cx_tree_visitor( 483 CxTreeVisitor cx_tree_visitor(
389 void *root, 484 void *root,
390 ptrdiff_t loc_children, 485 ptrdiff_t loc_children,
391 ptrdiff_t loc_next 486 ptrdiff_t loc_next
392 ); 487 );
393 488
489 /**
490 * Describes a function that creates a tree node from the specified data.
491 * The first argument points to the data the node shall contain and
492 * the second argument may be used for additional data (e.g. an allocator).
493 * Functions of this type shall either return a new pointer to a newly
494 * created node or @c NULL when allocation fails.
495 *
496 * @note the function may leave the node pointers in the struct uninitialized.
497 * The caller is responsible to set them according to the intended use case.
498 */
499 cx_attr_nonnull_arg(1)
500 typedef void *(*cx_tree_node_create_func)(const void *, void *);
501
502 /**
503 * The local search depth for a new subtree when adding multiple elements.
504 * The default value is 3.
505 * This variable is used by #cx_tree_add_array() and #cx_tree_add_iter() to
506 * implement optimized insertion of multiple elements into a tree.
507 */
508 extern unsigned int cx_tree_add_look_around_depth;
509
510 /**
511 * Adds multiple elements efficiently to a tree.
512 *
513 * Once an element cannot be added to the tree, this function returns, leaving
514 * the iterator in a valid state pointing to the element that could not be
515 * added.
516 * Also, the pointer of the created node will be stored to @p failed.
517 * The integer returned by this function denotes the number of elements obtained
518 * from the @p iter that have been successfully processed.
519 * When all elements could be processed, a @c NULL pointer will be written to
520 * @p failed.
521 *
522 * The advantage of this function compared to multiple invocations of
523 * #cx_tree_add() is that the search for the insert locations is not always
524 * started from the root node.
525 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes
526 * of the current insert location before starting from the root node again.
527 * When the variable is set to zero, only the last found location is checked
528 * again.
529 *
530 * Refer to the documentation of #cx_tree_add() for more details.
531 *
532 * @param iter a pointer to an arbitrary iterator
533 * @param num the maximum number of elements to obtain from the iterator
534 * @param sfunc a search function
535 * @param cfunc a node creation function
536 * @param cdata optional additional data
537 * @param root the root node of the tree
538 * @param failed location where the pointer to a failed node shall be stored
539 * @param loc_parent offset in the node struct for the parent pointer
540 * @param loc_children offset in the node struct for the children linked list
541 * @param loc_last_child optional offset in the node struct for the pointer to
542 * the last child in the linked list (negative if there is no such pointer)
543 * @param loc_prev optional offset in the node struct for the prev pointer
544 * @param loc_next offset in the node struct for the next pointer
545 * @return the number of nodes created and added
546 * @see cx_tree_add()
547 */
548 cx_attr_nonnull_arg(1, 3, 4, 6, 7)
549 cx_attr_access_w(6)
550 size_t cx_tree_add_iter(
551 struct cx_iterator_base_s *iter,
552 size_t num,
553 cx_tree_search_func sfunc,
554 cx_tree_node_create_func cfunc,
555 void *cdata,
556 void **failed,
557 void *root,
558 ptrdiff_t loc_parent,
559 ptrdiff_t loc_children,
560 ptrdiff_t loc_last_child,
561 ptrdiff_t loc_prev,
562 ptrdiff_t loc_next
563 );
564
565 /**
566 * Adds multiple elements efficiently to a tree.
567 *
568 * Once an element cannot be added to the tree, this function returns, storing
569 * the pointer of the created node to @p failed.
570 * The integer returned by this function denotes the number of elements from
571 * the @p src array that have been successfully processed.
572 * When all elements could be processed, a @c NULL pointer will be written to
573 * @p failed.
574 *
575 * The advantage of this function compared to multiple invocations of
576 * #cx_tree_add() is that the search for the insert locations is not always
577 * started from the root node.
578 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes
579 * of the current insert location before starting from the root node again.
580 * When the variable is set to zero, only the last found location is checked
581 * again.
582 *
583 * Refer to the documentation of #cx_tree_add() for more details.
584 *
585 * @param src a pointer to the source data array
586 * @param num the number of elements in the @p src array
587 * @param elem_size the size of each element in the @p src array
588 * @param sfunc a search function
589 * @param cfunc a node creation function
590 * @param cdata optional additional data
591 * @param failed location where the pointer to a failed node shall be stored
592 * @param root the root node of the tree
593 * @param loc_parent offset in the node struct for the parent pointer
594 * @param loc_children offset in the node struct for the children linked list
595 * @param loc_last_child optional offset in the node struct for the pointer to
596 * the last child in the linked list (negative if there is no such pointer)
597 * @param loc_prev optional offset in the node struct for the prev pointer
598 * @param loc_next offset in the node struct for the next pointer
599 * @return the number of array elements successfully processed
600 * @see cx_tree_add()
601 */
602 cx_attr_nonnull_arg(1, 4, 5, 7, 8)
603 cx_attr_access_w(7)
604 size_t cx_tree_add_array(
605 const void *src,
606 size_t num,
607 size_t elem_size,
608 cx_tree_search_func sfunc,
609 cx_tree_node_create_func cfunc,
610 void *cdata,
611 void **failed,
612 void *root,
613 ptrdiff_t loc_parent,
614 ptrdiff_t loc_children,
615 ptrdiff_t loc_last_child,
616 ptrdiff_t loc_prev,
617 ptrdiff_t loc_next
618 );
619
620 /**
621 * Adds data to a tree.
622 *
623 * An adequate location where to add the new tree node is searched with the
624 * specified @p sfunc.
625 *
626 * When a location is found, the @p cfunc will be invoked with @p cdata.
627 *
628 * The node returned by @p cfunc will be linked into the tree.
629 * When @p sfunc returned a positive integer, the new node will be linked as a
630 * child. The other children (now siblings of the new node) are then checked
631 * with @p sfunc, whether they could be children of the new node and re-linked
632 * accordingly.
633 *
634 * When @p sfunc returned zero and the found node has a parent, the new
635 * node will be added as sibling - otherwise, the new node will be added
636 * as a child.
637 *
638 * When @p sfunc returned a negative value, the new node will not be added to
639 * the tree and this function returns a non-zero value.
640 * The caller should check if @p cnode contains a node pointer and deal with the
641 * node that could not be added.
642 *
643 * This function also returns a non-zero value when @p cfunc tries to allocate
644 * a new node but fails to do so. In that case, the pointer stored to @p cnode
645 * will be @c NULL.
646 *
647 * Multiple elements can be added more efficiently with
648 * #cx_tree_add_array() or #cx_tree_add_iter().
649 *
650 * @param src a pointer to the data
651 * @param sfunc a search function
652 * @param cfunc a node creation function
653 * @param cdata optional additional data
654 * @param cnode the location where a pointer to the new node is stored
655 * @param root the root node of the tree
656 * @param loc_parent offset in the node struct for the parent pointer
657 * @param loc_children offset in the node struct for the children linked list
658 * @param loc_last_child optional offset in the node struct for the pointer to
659 * the last child in the linked list (negative if there is no such pointer)
660 * @param loc_prev optional offset in the node struct for the prev pointer
661 * @param loc_next offset in the node struct for the next pointer
662 * @return zero when a new node was created and added to the tree,
663 * non-zero otherwise
664 */
665 cx_attr_nonnull_arg(1, 2, 3, 5, 6)
666 cx_attr_access_w(5)
667 int cx_tree_add(
668 const void *src,
669 cx_tree_search_func sfunc,
670 cx_tree_node_create_func cfunc,
671 void *cdata,
672 void **cnode,
673 void *root,
674 ptrdiff_t loc_parent,
675 ptrdiff_t loc_children,
676 ptrdiff_t loc_last_child,
677 ptrdiff_t loc_prev,
678 ptrdiff_t loc_next
679 );
680
681
682 /**
683 * Tree class type.
684 */
685 typedef struct cx_tree_class_s cx_tree_class;
686
687 /**
688 * Base structure that can be used for tree nodes in a #CxTree.
689 */
690 struct cx_tree_node_base_s {
691 /**
692 * Pointer to the parent.
693 */
694 struct cx_tree_node_base_s *parent;
695 /**
696 * Pointer to the first child.
697 */
698 struct cx_tree_node_base_s *children;
699 /**
700 * Pointer to the last child.
701 */
702 struct cx_tree_node_base_s *last_child;
703 /**
704 * Pointer to the previous sibling.
705 */
706 struct cx_tree_node_base_s *prev;
707 /**
708 * Pointer to the next sibling.
709 */
710 struct cx_tree_node_base_s *next;
711 };
712
713 /**
714 * Structure for holding the base data of a tree.
715 */
716 struct cx_tree_s {
717 /**
718 * The tree class definition.
719 */
720 const cx_tree_class *cl;
721
722 /**
723 * Allocator to allocate new nodes.
724 */
725 const CxAllocator *allocator;
726
727 /**
728 * A pointer to the root node.
729 *
730 * Will be @c NULL when @c size is 0.
731 */
732 void *root;
733
734 /**
735 * A function to create new nodes.
736 *
737 * Invocations to this function will receive a pointer to this tree
738 * structure as second argument.
739 *
740 * Nodes MAY use #cx_tree_node_base_s as base layout, but do not need to.
741 */
742 cx_tree_node_create_func node_create;
743
744 /**
745 * An optional simple destructor for the tree nodes.
746 */
747 cx_destructor_func simple_destructor;
748
749 /**
750 * An optional advanced destructor for the tree nodes.
751 */
752 cx_destructor_func2 advanced_destructor;
753
754 /**
755 * The pointer to additional data that is passed to the advanced destructor.
756 */
757 void *destructor_data;
758
759 /**
760 * A function to compare two nodes.
761 */
762 cx_tree_search_func search;
763
764 /**
765 * A function to compare a node with data.
766 */
767 cx_tree_search_data_func search_data;
768
769 /**
770 * The number of currently stored elements.
771 */
772 size_t size;
773
774 /**
775 * Offset in the node struct for the parent pointer.
776 */
777 ptrdiff_t loc_parent;
778
779 /**
780 * Offset in the node struct for the children linked list.
781 */
782 ptrdiff_t loc_children;
783
784 /**
785 * Optional offset in the node struct for the pointer to the last child
786 * in the linked list (negative if there is no such pointer).
787 */
788 ptrdiff_t loc_last_child;
789
790 /**
791 * Offset in the node struct for the previous sibling pointer.
792 */
793 ptrdiff_t loc_prev;
794
795 /**
796 * Offset in the node struct for the next sibling pointer.
797 */
798 ptrdiff_t loc_next;
799 };
800
801 /**
802 * Macro to roll out the #cx_tree_node_base_s structure with a custom
803 * node type.
804 *
805 * Must be used as first member in your custom tree struct.
806 *
807 * @param type the data type for the nodes
808 */
809 #define CX_TREE_NODE_BASE(type) \
810 type *parent; \
811 type *children;\
812 type *last_child;\
813 type *prev;\
814 type *next
815
816 /**
817 * Macro for specifying the layout of a base node tree.
818 *
819 * When your tree uses #CX_TREE_NODE_BASE, you can use this
820 * macro in all tree functions that expect the layout parameters
821 * @c loc_parent, @c loc_children, @c loc_last_child, @c loc_prev,
822 * and @c loc_next.
823 */
824 #define cx_tree_node_base_layout \
825 offsetof(struct cx_tree_node_base_s, parent),\
826 offsetof(struct cx_tree_node_base_s, children),\
827 offsetof(struct cx_tree_node_base_s, last_child),\
828 offsetof(struct cx_tree_node_base_s, prev), \
829 offsetof(struct cx_tree_node_base_s, next)
830
831 /**
832 * The class definition for arbitrary trees.
833 */
834 struct cx_tree_class_s {
835 /**
836 * Member function for inserting a single element.
837 *
838 * Implementations SHALL NOT simply invoke @p insert_many as this comes
839 * with too much overhead.
840 */
841 int (*insert_element)(
842 struct cx_tree_s *tree,
843 const void *data
844 );
845
846 /**
847 * Member function for inserting multiple elements.
848 *
849 * Implementations SHALL avoid to perform a full search in the tree for
850 * every element even though the source data MAY be unsorted.
851 */
852 size_t (*insert_many)(
853 struct cx_tree_s *tree,
854 struct cx_iterator_base_s *iter,
855 size_t n
856 );
857
858 /**
859 * Member function for finding a node.
860 */
861 void *(*find)(
862 struct cx_tree_s *tree,
863 const void *subtree,
864 const void *data,
865 size_t depth
866 );
867 };
868
869 /**
870 * Common type for all tree implementations.
871 */
872 typedef struct cx_tree_s CxTree;
873
874
875 /**
876 * Destroys a node and it's subtree.
877 *
878 * It is guaranteed that the simple destructor is invoked before
879 * the advanced destructor, starting with the leaf nodes of the subtree.
880 *
881 * When this function is invoked on the root node of the tree, it destroys the
882 * tree contents, but - in contrast to #cxTreeFree() - not the tree
883 * structure, leaving an empty tree behind.
884 *
885 * @note The destructor function, if any, will @em not be invoked. That means
886 * you will need to free the removed subtree by yourself, eventually.
887 *
888 * @attention This function will not free the memory of the nodes with the
889 * tree's allocator, because that is usually done by the advanced destructor
890 * and would therefore result in a double-free.
891 *
892 * @param tree the tree
893 * @param node the node to remove
894 * @see cxTreeFree()
895 */
896 cx_attr_nonnull
897 void cxTreeDestroySubtree(CxTree *tree, void *node);
898
899
900 /**
901 * Destroys the tree contents.
902 *
903 * It is guaranteed that the simple destructor is invoked before
904 * the advanced destructor, starting with the leaf nodes of the subtree.
905 *
906 * This is a convenience macro for invoking #cxTreeDestroySubtree() on the
907 * root node of the tree.
908 *
909 * @attention Be careful when calling this function when no destructor function
910 * is registered that actually frees the memory of nodes. In that case you will
911 * need a reference to the (former) root node of the tree somewhere or
912 * otherwise you will be leaking memory.
913 *
914 * @param tree the tree
915 * @see cxTreeDestroySubtree()
916 */
917 #define cxTreeClear(tree) cxTreeDestroySubtree(tree, tree->root)
918
919 /**
920 * Deallocates the tree structure.
921 *
922 * The destructor functions are invoked for each node, starting with the leaf
923 * nodes.
924 * It is guaranteed that for each node the simple destructor is invoked before
925 * the advanced destructor.
926 *
927 * @attention This function will only invoke the destructor functions
928 * on the nodes.
929 * It will NOT additionally free the nodes with the tree's allocator, because
930 * that would cause a double-free in most scenarios where the advanced
931 * destructor is already freeing the memory.
932 *
933 * @param tree the tree to free
934 */
935 void cxTreeFree(CxTree *tree);
936
937 /**
938 * Creates a new tree structure based on the specified layout.
939 *
940 * The specified @p allocator will be used for creating the tree struct
941 * and SHALL be used by @p create_func to allocate memory for the nodes.
942 *
943 * @note This function will also register an advanced destructor which
944 * will free the nodes with the allocator's free() method.
945 *
946 * @param allocator the allocator that shall be used
947 * (if @c NULL, a default stdlib allocator will be used)
948 * @param create_func a function that creates new nodes
949 * @param search_func a function that compares two nodes
950 * @param search_data_func a function that compares a node with data
951 * @param loc_parent offset in the node struct for the parent pointer
952 * @param loc_children offset in the node struct for the children linked list
953 * @param loc_last_child optional offset in the node struct for the pointer to
954 * the last child in the linked list (negative if there is no such pointer)
955 * @param loc_prev optional offset in the node struct for the prev pointer
956 * @param loc_next offset in the node struct for the next pointer
957 * @return the new tree
958 * @see cxTreeCreateSimple()
959 * @see cxTreeCreateWrapped()
960 */
961 cx_attr_nonnull_arg(2, 3, 4)
962 cx_attr_nodiscard
963 cx_attr_malloc
964 cx_attr_dealloc(cxTreeFree, 1)
965 CxTree *cxTreeCreate(
966 const CxAllocator *allocator,
967 cx_tree_node_create_func create_func,
968 cx_tree_search_func search_func,
969 cx_tree_search_data_func search_data_func,
970 ptrdiff_t loc_parent,
971 ptrdiff_t loc_children,
972 ptrdiff_t loc_last_child,
973 ptrdiff_t loc_prev,
974 ptrdiff_t loc_next
975 );
976
977 /**
978 * Creates a new tree structure based on a default layout.
979 *
980 * Nodes created by @p create_func MUST contain #cx_tree_node_base_s as first
981 * member (or at least respect the default offsets specified in the tree
982 * struct) and they MUST be allocated with the specified allocator.
983 *
984 * @note This function will also register an advanced destructor which
985 * will free the nodes with the allocator's free() method.
986 *
987 * @param allocator (@c CxAllocator*) the allocator that shall be used
988 * @param create_func (@c cx_tree_node_create_func) a function that creates new nodes
989 * @param search_func (@c cx_tree_search_func) a function that compares two nodes
990 * @param search_data_func (@c cx_tree_search_data_func) a function that compares a node with data
991 * @return (@c CxTree*) the new tree
992 * @see cxTreeCreate()
993 */
994 #define cxTreeCreateSimple(\
995 allocator, create_func, search_func, search_data_func \
996 ) cxTreeCreate(allocator, create_func, search_func, search_data_func, \
997 cx_tree_node_base_layout)
998
999 /**
1000 * Creates a new tree structure based on an existing tree.
1001 *
1002 * The specified @p allocator will be used for creating the tree struct.
1003 *
1004 * @attention This function will create an incompletely defined tree structure
1005 * where neither the create function, the search function, nor a destructor
1006 * will be set. If you wish to use any of this functionality for the wrapped
1007 * tree, you need to specify those functions afterwards.
1008 *
1009 * @param allocator the allocator that was used for nodes of the wrapped tree
1010 * (if @c NULL, a default stdlib allocator is assumed)
1011 * @param root the root node of the tree that shall be wrapped
1012 * @param loc_parent offset in the node struct for the parent pointer
1013 * @param loc_children offset in the node struct for the children linked list
1014 * @param loc_last_child optional offset in the node struct for the pointer to
1015 * the last child in the linked list (negative if there is no such pointer)
1016 * @param loc_prev optional offset in the node struct for the prev pointer
1017 * @param loc_next offset in the node struct for the next pointer
1018 * @return the new tree
1019 * @see cxTreeCreate()
1020 */
1021 cx_attr_nonnull_arg(2)
1022 cx_attr_nodiscard
1023 cx_attr_malloc
1024 cx_attr_dealloc(cxTreeFree, 1)
1025 CxTree *cxTreeCreateWrapped(
1026 const CxAllocator *allocator,
1027 void *root,
1028 ptrdiff_t loc_parent,
1029 ptrdiff_t loc_children,
1030 ptrdiff_t loc_last_child,
1031 ptrdiff_t loc_prev,
1032 ptrdiff_t loc_next
1033 );
1034
1035 /**
1036 * Inserts data into the tree.
1037 *
1038 * @remark For this function to work, the tree needs specified search and
1039 * create functions, which might not be available for wrapped trees
1040 * (see #cxTreeCreateWrapped()).
1041 *
1042 * @param tree the tree
1043 * @param data the data to insert
1044 * @retval zero success
1045 * @retval non-zero failure
1046 */
1047 cx_attr_nonnull
1048 static inline int cxTreeInsert(
1049 CxTree *tree,
1050 const void *data
1051 ) {
1052 return tree->cl->insert_element(tree, data);
1053 }
1054
1055 /**
1056 * Inserts elements provided by an iterator efficiently into the tree.
1057 *
1058 * @remark For this function to work, the tree needs specified search and
1059 * create functions, which might not be available for wrapped trees
1060 * (see #cxTreeCreateWrapped()).
1061 *
1062 * @param tree the tree
1063 * @param iter the iterator providing the elements
1064 * @param n the maximum number of elements to insert
1065 * @return the number of elements that could be successfully inserted
1066 */
1067 cx_attr_nonnull
1068 static inline size_t cxTreeInsertIter(
1069 CxTree *tree,
1070 struct cx_iterator_base_s *iter,
1071 size_t n
1072 ) {
1073 return tree->cl->insert_many(tree, iter, n);
1074 }
1075
1076 /**
1077 * Inserts an array of data efficiently into the tree.
1078 *
1079 * @remark For this function to work, the tree needs specified search and
1080 * create functions, which might not be available for wrapped trees
1081 * (see #cxTreeCreateWrapped()).
1082 *
1083 * @param tree the tree
1084 * @param data the array of data to insert
1085 * @param elem_size the size of each element in the array
1086 * @param n the number of elements in the array
1087 * @return the number of elements that could be successfully inserted
1088 */
1089 cx_attr_nonnull
1090 static inline size_t cxTreeInsertArray(
1091 CxTree *tree,
1092 const void *data,
1093 size_t elem_size,
1094 size_t n
1095 ) {
1096 if (n == 0) return 0;
1097 if (n == 1) return 0 == cxTreeInsert(tree, data) ? 1 : 0;
1098 CxIterator iter = cxIterator(data, elem_size, n);
1099 return cxTreeInsertIter(tree, cxIteratorRef(iter), n);
1100 }
1101
1102 /**
1103 * Searches the data in the specified tree.
1104 *
1105 * @remark For this function to work, the tree needs a specified @c search_data
1106 * function, which might not be available wrapped trees
1107 * (see #cxTreeCreateWrapped()).
1108 *
1109 * @param tree the tree
1110 * @param data the data to search for
1111 * @return the first matching node, or @c NULL when the data cannot be found
1112 */
1113 cx_attr_nonnull
1114 cx_attr_nodiscard
1115 static inline void *cxTreeFind(
1116 CxTree *tree,
1117 const void *data
1118 ) {
1119 return tree->cl->find(tree, tree->root, data, 0);
1120 }
1121
1122 /**
1123 * Searches the data in the specified subtree.
1124 *
1125 * When @p max_depth is zero, the depth is not limited.
1126 * The @p subtree_root itself is on depth 1 and its children have depth 2.
1127 *
1128 * @note When @p subtree_root is not part of the @p tree, the behavior is
1129 * undefined.
1130 *
1131 * @remark For this function to work, the tree needs a specified @c search_data
1132 * function, which might not be the case for wrapped trees
1133 * (see #cxTreeCreateWrapped()).
1134 *
1135 * @param tree the tree
1136 * @param data the data to search for
1137 * @param subtree_root the node where to start
1138 * @param max_depth the maximum search depth
1139 * @return the first matching node, or @c NULL when the data cannot be found
1140 */
1141 cx_attr_nonnull
1142 cx_attr_nodiscard
1143 static inline void *cxTreeFindInSubtree(
1144 CxTree *tree,
1145 const void *data,
1146 void *subtree_root,
1147 size_t max_depth
1148 ) {
1149 return tree->cl->find(tree, subtree_root, data, max_depth);
1150 }
1151
1152 /**
1153 * Determines the size of the specified subtree.
1154 *
1155 * @param tree the tree
1156 * @param subtree_root the root node of the subtree
1157 * @return the number of nodes in the specified subtree
1158 */
1159 cx_attr_nonnull
1160 cx_attr_nodiscard
1161 size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root);
1162
1163 /**
1164 * Determines the depth of the specified subtree.
1165 *
1166 * @param tree the tree
1167 * @param subtree_root the root node of the subtree
1168 * @return the tree depth including the @p subtree_root
1169 */
1170 cx_attr_nonnull
1171 cx_attr_nodiscard
1172 size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root);
1173
1174 /**
1175 * Determines the depth of the entire tree.
1176 *
1177 * @param tree the tree
1178 * @return the tree depth, counting the root as one
1179 */
1180 cx_attr_nonnull
1181 cx_attr_nodiscard
1182 size_t cxTreeDepth(CxTree *tree);
1183
1184 /**
1185 * Creates a depth-first iterator for the specified tree starting in @p node.
1186 *
1187 * If the node is not part of the tree, the behavior is undefined.
1188 *
1189 * @param tree the tree to iterate
1190 * @param node the node where to start
1191 * @param visit_on_exit true, if the iterator shall visit a node again when
1192 * leaving the subtree
1193 * @return a tree iterator (depth-first)
1194 * @see cxTreeVisit()
1195 */
1196 cx_attr_nonnull
1197 cx_attr_nodiscard
1198 static inline CxTreeIterator cxTreeIterateSubtree(
1199 CxTree *tree,
1200 void *node,
1201 bool visit_on_exit
1202 ) {
1203 return cx_tree_iterator(
1204 node, visit_on_exit,
1205 tree->loc_children, tree->loc_next
1206 );
1207 }
1208
1209 /**
1210 * Creates a breadth-first iterator for the specified tree starting in @p node.
1211 *
1212 * If the node is not part of the tree, the behavior is undefined.
1213 *
1214 * @param tree the tree to iterate
1215 * @param node the node where to start
1216 * @return a tree visitor (a.k.a. breadth-first iterator)
1217 * @see cxTreeIterate()
1218 */
1219 cx_attr_nonnull
1220 cx_attr_nodiscard
1221 static inline CxTreeVisitor cxTreeVisitSubtree(CxTree *tree, void *node) {
1222 return cx_tree_visitor(
1223 node, tree->loc_children, tree->loc_next
1224 );
1225 }
1226
1227 /**
1228 * Creates a depth-first iterator for the specified tree.
1229 *
1230 * @param tree the tree to iterate
1231 * @param visit_on_exit true, if the iterator shall visit a node again when
1232 * leaving the subtree
1233 * @return a tree iterator (depth-first)
1234 * @see cxTreeVisit()
1235 */
1236 cx_attr_nonnull
1237 cx_attr_nodiscard
1238 static inline CxTreeIterator cxTreeIterate(
1239 CxTree *tree,
1240 bool visit_on_exit
1241 ) {
1242 return cxTreeIterateSubtree(tree, tree->root, visit_on_exit);
1243 }
1244
1245 /**
1246 * Creates a breadth-first iterator for the specified tree.
1247 *
1248 * @param tree the tree to iterate
1249 * @return a tree visitor (a.k.a. breadth-first iterator)
1250 * @see cxTreeIterate()
1251 */
1252 cx_attr_nonnull
1253 cx_attr_nodiscard
1254 static inline CxTreeVisitor cxTreeVisit(CxTree *tree) {
1255 return cxTreeVisitSubtree(tree, tree->root);
1256 }
1257
1258 /**
1259 * Sets the (new) parent of the specified child.
1260 *
1261 * If the @p child is not already member of the tree, this function behaves
1262 * as #cxTreeAddChildNode().
1263 *
1264 * @param tree the tree
1265 * @param parent the (new) parent of the child
1266 * @param child the node to add
1267 * @see cxTreeAddChildNode()
1268 */
1269 cx_attr_nonnull
1270 void cxTreeSetParent(
1271 CxTree *tree,
1272 void *parent,
1273 void *child
1274 );
1275
1276 /**
1277 * Adds a new node to the tree.
1278 *
1279 * If the @p child is already member of the tree, the behavior is undefined.
1280 * Use #cxTreeSetParent() if you want to move a subtree to another location.
1281 *
1282 * @attention The node may be externally created, but MUST obey the same rules
1283 * as if it was created by the tree itself with #cxTreeAddChild() (e.g. use
1284 * the same allocator).
1285 *
1286 * @param tree the tree
1287 * @param parent the parent of the node to add
1288 * @param child the node to add
1289 * @see cxTreeSetParent()
1290 */
1291 cx_attr_nonnull
1292 void cxTreeAddChildNode(
1293 CxTree *tree,
1294 void *parent,
1295 void *child
1296 );
1297
1298 /**
1299 * Creates a new node and adds it to the tree.
1300 *
1301 * With this function you can decide where exactly the new node shall be added.
1302 * If you specified an appropriate search function, you may want to consider
1303 * leaving this task to the tree by using #cxTreeInsert().
1304 *
1305 * Be aware that adding nodes at arbitrary locations in the tree might cause
1306 * wrong or undesired results when subsequently invoking #cxTreeInsert() and
1307 * the invariant imposed by the search function does not hold any longer.
1308 *
1309 * @param tree the tree
1310 * @param parent the parent node of the new node
1311 * @param data the data that will be submitted to the create function
1312 * @return zero when the new node was created, non-zero on allocation failure
1313 * @see cxTreeInsert()
1314 */
1315 cx_attr_nonnull
1316 int cxTreeAddChild(
1317 CxTree *tree,
1318 void *parent,
1319 const void *data
1320 );
1321
1322 /**
1323 * A function that is invoked when a node needs to be re-linked to a new parent.
1324 *
1325 * When a node is re-linked, sometimes the contents need to be updated.
1326 * This callback is invoked by #cxTreeRemoveNode() and #cxTreeDestroyNode()
1327 * so that those updates can be applied when re-linking the children of the
1328 * removed node.
1329 *
1330 * @param node the affected node
1331 * @param old_parent the old parent of the node
1332 * @param new_parent the new parent of the node
1333 */
1334 cx_attr_nonnull
1335 typedef void (*cx_tree_relink_func)(
1336 void *node,
1337 const void *old_parent,
1338 const void *new_parent
1339 );
1340
1341 /**
1342 * Removes a node and re-links its children to its former parent.
1343 *
1344 * If the node is not part of the tree, the behavior is undefined.
1345 *
1346 * @note The destructor function, if any, will @em not be invoked. That means
1347 * you will need to free the removed node by yourself, eventually.
1348 *
1349 * @param tree the tree
1350 * @param node the node to remove (must not be the root node)
1351 * @param relink_func optional callback to update the content of each re-linked
1352 * node
1353 * @return zero on success, non-zero if @p node is the root node of the tree
1354 */
1355 cx_attr_nonnull_arg(1, 2)
1356 int cxTreeRemoveNode(
1357 CxTree *tree,
1358 void *node,
1359 cx_tree_relink_func relink_func
1360 );
1361
1362 /**
1363 * Removes a node and it's subtree from the tree.
1364 *
1365 * If the node is not part of the tree, the behavior is undefined.
1366 *
1367 * @note The destructor function, if any, will @em not be invoked. That means
1368 * you will need to free the removed subtree by yourself, eventually.
1369 *
1370 * @param tree the tree
1371 * @param node the node to remove
1372 */
1373 cx_attr_nonnull
1374 void cxTreeRemoveSubtree(CxTree *tree, void *node);
1375
1376 /**
1377 * Destroys a node and re-links its children to its former parent.
1378 *
1379 * If the node is not part of the tree, the behavior is undefined.
1380 *
1381 * It is guaranteed that the simple destructor is invoked before
1382 * the advanced destructor.
1383 *
1384 * @attention This function will not free the memory of the node with the
1385 * tree's allocator, because that is usually done by the advanced destructor
1386 * and would therefore result in a double-free.
1387 *
1388 * @param tree the tree
1389 * @param node the node to destroy (must not be the root node)
1390 * @param relink_func optional callback to update the content of each re-linked
1391 * node
1392 * @return zero on success, non-zero if @p node is the root node of the tree
1393 */
1394 cx_attr_nonnull_arg(1, 2)
1395 int cxTreeDestroyNode(
1396 CxTree *tree,
1397 void *node,
1398 cx_tree_relink_func relink_func
1399 );
1400
394 #ifdef __cplusplus 1401 #ifdef __cplusplus
395 } // extern "C" 1402 } // extern "C"
396 #endif 1403 #endif
397 1404
398 #endif //UCX_TREE_H 1405 #endif //UCX_TREE_H

mercurial