ucx/cx/tree.h

changeset 11
0aa8cbd7912e
parent 0
1a157da63d7c
child 16
04c9f8d8f03b
equal deleted inserted replaced
10:80f9d007cb52 11:0aa8cbd7912e
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 /**
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);
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 );
299
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
285 304
286 /** 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 #define CX_TREE_NODE_BASE(type) \
806 type *parent; \
807 type *children;\
808 type *last_child;\
809 type *prev;\
810 type *next
811
812 /**
813 * Macro for specifying the layout of a base node tree.
814 */
815 #define cx_tree_node_base_layout \
816 offsetof(struct cx_tree_node_base_s, parent),\
817 offsetof(struct cx_tree_node_base_s, children),\
818 offsetof(struct cx_tree_node_base_s, last_child),\
819 offsetof(struct cx_tree_node_base_s, prev), \
820 offsetof(struct cx_tree_node_base_s, next)
821
822 /**
823 * Macro for obtaining the node pointer layout for a specific tree.
824 */
825 #define cx_tree_node_layout(tree) \
826 (tree)->loc_parent,\
827 (tree)->loc_children,\
828 (tree)->loc_last_child,\
829 (tree)->loc_prev, \
830 (tree)->loc_next
831
832 /**
833 * The class definition for arbitrary trees.
834 */
835 struct cx_tree_class_s {
836 /**
837 * Member function for inserting a single element.
838 *
839 * Implementations SHALL NOT simply invoke \p insert_many as this comes
840 * with too much overhead.
841 */
842 cx_attr_nonnull
843 int (*insert_element)(
844 struct cx_tree_s *tree,
845 const void *data
846 );
847
848 /**
849 * Member function for inserting multiple elements.
850 *
851 * Implementations SHALL avoid to perform a full search in the tree for
852 * every element even though the source data MAY be unsorted.
853 */
854 cx_attr_nonnull
855 size_t (*insert_many)(
856 struct cx_tree_s *tree,
857 struct cx_iterator_base_s *iter,
858 size_t n
859 );
860
861 /**
862 * Member function for finding a node.
863 */
864 cx_attr_nonnull
865 void *(*find)(
866 struct cx_tree_s *tree,
867 const void *subtree,
868 const void *data,
869 size_t depth
870 );
871 };
872
873 /**
874 * Common type for all tree implementations.
875 */
876 typedef struct cx_tree_s CxTree;
877
878
879 /**
880 * Destroys a node and it's subtree.
881 *
882 * It is guaranteed that the simple destructor is invoked before
883 * the advanced destructor, starting with the leaf nodes of the subtree.
884 *
885 * When this function is invoked on the root node of the tree, it destroys the
886 * tree contents, but - in contrast to #cxTreeFree() - not the tree
887 * structure, leaving an empty tree behind.
888 *
889 * \note The destructor function, if any, will \em not be invoked. That means
890 * you will need to free the removed subtree by yourself, eventually.
891 *
892 * \attention This function will not free the memory of the nodes with the
893 * tree's allocator, because that is usually done by the advanced destructor
894 * and would therefore result in a double-free.
895 *
896 * @param tree the tree
897 * @param node the node to remove
898 * @see cxTreeFree()
899 */
900 cx_attr_nonnull
901 void cxTreeDestroySubtree(CxTree *tree, void *node);
902
903
904 /**
905 * Destroys the tree contents.
906 *
907 * It is guaranteed that the simple destructor is invoked before
908 * the advanced destructor, starting with the leaf nodes of the subtree.
909 *
910 * This is a convenience macro for invoking #cxTreeDestroySubtree() on the
911 * root node of the tree.
912 *
913 * \attention Be careful when calling this function when no destructor function
914 * is registered that actually frees the memory of nodes. In that case you will
915 * need a reference to the (former) root node of the tree somewhere or
916 * otherwise you will be leaking memory.
917 *
918 * @param tree the tree
919 * @see cxTreeDestroySubtree()
920 */
921 #define cxTreeClear(tree) cxTreeDestroySubtree(tree, tree->root)
922
923 /**
924 * Deallocates the tree structure.
925 *
926 * The destructor functions are invoked for each node, starting with the leaf
927 * nodes.
928 * It is guaranteed that for each node the simple destructor is invoked before
929 * the advanced destructor.
930 *
931 * \attention This function will only invoke the destructor functions
932 * on the nodes.
933 * It will NOT additionally free the nodes with the tree's allocator, because
934 * that would cause a double-free in most scenarios where the advanced
935 * destructor is already freeing the memory.
936 *
937 * @param tree the tree to free
938 */
939 static inline void cxTreeFree(CxTree *tree) {
940 if (tree == NULL) return;
941 if (tree->root != NULL) {
942 cxTreeClear(tree);
943 }
944 cxFree(tree->allocator, tree);
945 }
946
947 /**
948 * Creates a new tree structure based on the specified layout.
949 *
950 * The specified \p allocator will be used for creating the tree struct
951 * and SHALL be used by \p create_func to allocate memory for the nodes.
952 *
953 * \note This function will also register an advanced destructor which
954 * will free the nodes with the allocator's free() method.
955 *
956 * @param allocator the allocator that shall be used
957 * (if \c NULL, a default stdlib allocator will be used)
958 * @param create_func a function that creates new nodes
959 * @param search_func a function that compares two nodes
960 * @param search_data_func a function that compares a node with data
961 * @param loc_parent offset in the node struct for the parent pointer
962 * @param loc_children offset in the node struct for the children linked list
963 * @param loc_last_child optional offset in the node struct for the pointer to
964 * the last child in the linked list (negative if there is no such pointer)
965 * @param loc_prev optional offset in the node struct for the prev pointer
966 * @param loc_next offset in the node struct for the next pointer
967 * @return the new tree
968 * @see cxTreeCreateSimple()
969 * @see cxTreeCreateWrapped()
970 */
971 cx_attr_nonnull_arg(2, 3, 4)
972 cx_attr_nodiscard
973 cx_attr_malloc
974 cx_attr_dealloc(cxTreeFree, 1)
975 CxTree *cxTreeCreate(
976 const CxAllocator *allocator,
977 cx_tree_node_create_func create_func,
978 cx_tree_search_func search_func,
979 cx_tree_search_data_func search_data_func,
980 ptrdiff_t loc_parent,
981 ptrdiff_t loc_children,
982 ptrdiff_t loc_last_child,
983 ptrdiff_t loc_prev,
984 ptrdiff_t loc_next
985 );
986
987 /**
988 * Creates a new tree structure based on a default layout.
989 *
990 * Nodes created by \p create_func MUST contain #cx_tree_node_base_s as first
991 * member (or at least respect the default offsets specified in the tree
992 * struct) and they MUST be allocated with the specified allocator.
993 *
994 * \note This function will also register an advanced destructor which
995 * will free the nodes with the allocator's free() method.
996 *
997 * @param allocator the allocator that shall be used
998 * @param create_func a function that creates new nodes
999 * @param search_func a function that compares two nodes
1000 * @param search_data_func a function that compares a node with data
1001 * @return the new tree
1002 * @see cxTreeCreate()
1003 */
1004 #define cxTreeCreateSimple(\
1005 allocator, create_func, search_func, search_data_func \
1006 ) cxTreeCreate(allocator, create_func, search_func, search_data_func, \
1007 cx_tree_node_base_layout)
1008
1009 /**
1010 * Creates a new tree structure based on an existing tree.
1011 *
1012 * The specified \p allocator will be used for creating the tree struct.
1013 *
1014 * \attention This function will create an incompletely defined tree structure
1015 * where neither the create function, the search function, nor a destructor
1016 * will be set. If you wish to use any of this functionality for the wrapped
1017 * tree, you need to specify those functions afterwards.
1018 *
1019 * @param allocator the allocator that was used for nodes of the wrapped tree
1020 * (if \c NULL, a default stdlib allocator is assumed)
1021 * @param root the root node of the tree that shall be wrapped
1022 * @param loc_parent offset in the node struct for the parent pointer
1023 * @param loc_children offset in the node struct for the children linked list
1024 * @param loc_last_child optional offset in the node struct for the pointer to
1025 * the last child in the linked list (negative if there is no such pointer)
1026 * @param loc_prev optional offset in the node struct for the prev pointer
1027 * @param loc_next offset in the node struct for the next pointer
1028 * @return the new tree
1029 * @see cxTreeCreate()
1030 */
1031 cx_attr_nonnull_arg(2)
1032 cx_attr_nodiscard
1033 cx_attr_malloc
1034 cx_attr_dealloc(cxTreeFree, 1)
1035 CxTree *cxTreeCreateWrapped(
1036 const CxAllocator *allocator,
1037 void *root,
1038 ptrdiff_t loc_parent,
1039 ptrdiff_t loc_children,
1040 ptrdiff_t loc_last_child,
1041 ptrdiff_t loc_prev,
1042 ptrdiff_t loc_next
1043 );
1044
1045 /**
1046 * Inserts data into the tree.
1047 *
1048 * \remark For this function to work, the tree needs specified search and
1049 * create functions, which might not be available for wrapped trees
1050 * (see #cxTreeCreateWrapped()).
1051 *
1052 * @param tree the tree
1053 * @param data the data to insert
1054 * @return zero on success, non-zero on failure
1055 */
1056 cx_attr_nonnull
1057 static inline int cxTreeInsert(
1058 CxTree *tree,
1059 const void *data
1060 ) {
1061 return tree->cl->insert_element(tree, data);
1062 }
1063
1064 /**
1065 * Inserts elements provided by an iterator efficiently into the tree.
1066 *
1067 * \remark For this function to work, the tree needs specified search and
1068 * create functions, which might not be available for wrapped trees
1069 * (see #cxTreeCreateWrapped()).
1070 *
1071 * @param tree the tree
1072 * @param iter the iterator providing the elements
1073 * @param n the maximum number of elements to insert
1074 * @return the number of elements that could be successfully inserted
1075 */
1076 cx_attr_nonnull
1077 static inline size_t cxTreeInsertIter(
1078 CxTree *tree,
1079 struct cx_iterator_base_s *iter,
1080 size_t n
1081 ) {
1082 return tree->cl->insert_many(tree, iter, n);
1083 }
1084
1085 /**
1086 * Inserts an array of data efficiently into the tree.
1087 *
1088 * \remark For this function to work, the tree needs specified search and
1089 * create functions, which might not be available for wrapped trees
1090 * (see #cxTreeCreateWrapped()).
1091 *
1092 * @param tree the tree
1093 * @param data the array of data to insert
1094 * @param elem_size the size of each element in the array
1095 * @param n the number of elements in the array
1096 * @return the number of elements that could be successfully inserted
1097 */
1098 cx_attr_nonnull
1099 static inline size_t cxTreeInsertArray(
1100 CxTree *tree,
1101 const void *data,
1102 size_t elem_size,
1103 size_t n
1104 ) {
1105 if (n == 0) return 0;
1106 if (n == 1) return 0 == cxTreeInsert(tree, data) ? 1 : 0;
1107 CxIterator iter = cxIterator(data, elem_size, n);
1108 return cxTreeInsertIter(tree, cxIteratorRef(iter), n);
1109 }
1110
1111 /**
1112 * Searches the data in the specified tree.
1113 *
1114 * \remark For this function to work, the tree needs a specified \c search_data
1115 * function, which might not be available wrapped trees
1116 * (see #cxTreeCreateWrapped()).
1117 *
1118 * @param tree the tree
1119 * @param data the data to search for
1120 * @return the first matching node, or \c NULL when the data cannot be found
1121 */
1122 cx_attr_nonnull
1123 cx_attr_nodiscard
1124 static inline void *cxTreeFind(
1125 CxTree *tree,
1126 const void *data
1127 ) {
1128 return tree->cl->find(tree, tree->root, data, 0);
1129 }
1130
1131 /**
1132 * Searches the data in the specified subtree.
1133 *
1134 * When \p max_depth is zero, the depth is not limited.
1135 * The \p subtree_root itself is on depth 1 and its children have depth 2.
1136 *
1137 * \note When \p subtree_root is not part of the \p tree, the behavior is
1138 * undefined.
1139 *
1140 * \remark For this function to work, the tree needs a specified \c search_data
1141 * function, which might not be the case for wrapped trees
1142 * (see #cxTreeCreateWrapped()).
1143 *
1144 * @param tree the tree
1145 * @param data the data to search for
1146 * @param subtree_root the node where to start
1147 * @param max_depth the maximum search depth
1148 * @return the first matching node, or \c NULL when the data cannot be found
1149 */
1150 cx_attr_nonnull
1151 cx_attr_nodiscard
1152 static inline void *cxTreeFindInSubtree(
1153 CxTree *tree,
1154 const void *data,
1155 void *subtree_root,
1156 size_t max_depth
1157 ) {
1158 return tree->cl->find(tree, subtree_root, data, max_depth);
1159 }
1160
1161 /**
1162 * Determines the size of the specified subtree.
1163 *
1164 * @param tree the tree
1165 * @param subtree_root the root node of the subtree
1166 * @return the number of nodes in the specified subtree
1167 */
1168 cx_attr_nonnull
1169 cx_attr_nodiscard
1170 size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root);
1171
1172 /**
1173 * Determines the depth of the specified subtree.
1174 *
1175 * @param tree the tree
1176 * @param subtree_root the root node of the subtree
1177 * @return the tree depth including the \p subtree_root
1178 */
1179 cx_attr_nonnull
1180 cx_attr_nodiscard
1181 size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root);
1182
1183 /**
1184 * Determines the depth of the entire tree.
1185 *
1186 * @param tree the tree
1187 * @return the tree depth, counting the root as one
1188 */
1189 cx_attr_nonnull
1190 cx_attr_nodiscard
1191 size_t cxTreeDepth(CxTree *tree);
1192
1193 /**
1194 * Creates a depth-first iterator for the specified tree starting in \p node.
1195 *
1196 * If the node is not part of the tree, the behavior is undefined.
1197 *
1198 * @param tree the tree to iterate
1199 * @param node the node where to start
1200 * @param visit_on_exit true, if the iterator shall visit a node again when
1201 * leaving the subtree
1202 * @return a tree iterator (depth-first)
1203 * @see cxTreeVisit()
1204 */
1205 cx_attr_nonnull
1206 cx_attr_nodiscard
1207 static inline CxTreeIterator cxTreeIterateSubtree(
1208 CxTree *tree,
1209 void *node,
1210 bool visit_on_exit
1211 ) {
1212 return cx_tree_iterator(
1213 node, visit_on_exit,
1214 tree->loc_children, tree->loc_next
1215 );
1216 }
1217
1218 /**
1219 * Creates a breadth-first iterator for the specified tree starting in \p node.
1220 *
1221 * If the node is not part of the tree, the behavior is undefined.
1222 *
1223 * @param tree the tree to iterate
1224 * @param node the node where to start
1225 * @return a tree visitor (a.k.a. breadth-first iterator)
1226 * @see cxTreeIterate()
1227 */
1228 cx_attr_nonnull
1229 cx_attr_nodiscard
1230 static inline CxTreeVisitor cxTreeVisitSubtree(CxTree *tree, void *node) {
1231 return cx_tree_visitor(
1232 node, tree->loc_children, tree->loc_next
1233 );
1234 }
1235
1236 /**
1237 * Creates a depth-first iterator for the specified tree.
1238 *
1239 * @param tree the tree to iterate
1240 * @param visit_on_exit true, if the iterator shall visit a node again when
1241 * leaving the subtree
1242 * @return a tree iterator (depth-first)
1243 * @see cxTreeVisit()
1244 */
1245 cx_attr_nonnull
1246 cx_attr_nodiscard
1247 static inline CxTreeIterator cxTreeIterate(
1248 CxTree *tree,
1249 bool visit_on_exit
1250 ) {
1251 return cxTreeIterateSubtree(tree, tree->root, visit_on_exit);
1252 }
1253
1254 /**
1255 * Creates a breadth-first iterator for the specified tree.
1256 *
1257 * @param tree the tree to iterate
1258 * @return a tree visitor (a.k.a. breadth-first iterator)
1259 * @see cxTreeIterate()
1260 */
1261 cx_attr_nonnull
1262 cx_attr_nodiscard
1263 static inline CxTreeVisitor cxTreeVisit(CxTree *tree) {
1264 return cxTreeVisitSubtree(tree, tree->root);
1265 }
1266
1267 /**
1268 * Sets the (new) parent of the specified child.
1269 *
1270 * If the \p child is not already member of the tree, this function behaves
1271 * as #cxTreeAddChildNode().
1272 *
1273 * @param tree the tree
1274 * @param parent the (new) parent of the child
1275 * @param child the node to add
1276 * @see cxTreeAddChildNode()
1277 */
1278 cx_attr_nonnull
1279 void cxTreeSetParent(
1280 CxTree *tree,
1281 void *parent,
1282 void *child
1283 );
1284
1285 /**
1286 * Adds a new node to the tree.
1287 *
1288 * If the \p child is already member of the tree, the behavior is undefined.
1289 * Use #cxTreeSetParent() if you want to move a subtree to another location.
1290 *
1291 * \attention The node may be externally created, but MUST obey the same rules
1292 * as if it was created by the tree itself with #cxTreeAddChild() (e.g. use
1293 * the same allocator).
1294 *
1295 * @param tree the tree
1296 * @param parent the parent of the node to add
1297 * @param child the node to add
1298 * @see cxTreeSetParent()
1299 */
1300 cx_attr_nonnull
1301 void cxTreeAddChildNode(
1302 CxTree *tree,
1303 void *parent,
1304 void *child
1305 );
1306
1307 /**
1308 * Creates a new node and adds it to the tree.
1309 *
1310 * With this function you can decide where exactly the new node shall be added.
1311 * If you specified an appropriate search function, you may want to consider
1312 * leaving this task to the tree by using #cxTreeInsert().
1313 *
1314 * Be aware that adding nodes at arbitrary locations in the tree might cause
1315 * wrong or undesired results when subsequently invoking #cxTreeInsert() and
1316 * the invariant imposed by the search function does not hold any longer.
1317 *
1318 * @param tree the tree
1319 * @param parent the parent node of the new node
1320 * @param data the data that will be submitted to the create function
1321 * @return zero when the new node was created, non-zero on allocation failure
1322 * @see cxTreeInsert()
1323 */
1324 cx_attr_nonnull
1325 int cxTreeAddChild(
1326 CxTree *tree,
1327 void *parent,
1328 const void *data
1329 );
1330
1331 /**
1332 * A function that is invoked when a node needs to be re-linked to a new parent.
1333 *
1334 * When a node is re-linked, sometimes the contents need to be updated.
1335 * This callback is invoked by #cxTreeRemoveNode() and #cxTreeDestroyNode()
1336 * so that those updates can be applied when re-linking the children of the
1337 * removed node.
1338 *
1339 * @param node the affected node
1340 * @param old_parent the old parent of the node
1341 * @param new_parent the new parent of the node
1342 */
1343 cx_attr_nonnull
1344 typedef void (*cx_tree_relink_func)(
1345 void *node,
1346 const void *old_parent,
1347 const void *new_parent
1348 );
1349
1350 /**
1351 * Removes a node and re-links its children to its former parent.
1352 *
1353 * If the node is not part of the tree, the behavior is undefined.
1354 *
1355 * \note The destructor function, if any, will \em not be invoked. That means
1356 * you will need to free the removed node by yourself, eventually.
1357 *
1358 * @param tree the tree
1359 * @param node the node to remove (must not be the root node)
1360 * @param relink_func optional callback to update the content of each re-linked
1361 * node
1362 * @return zero on success, non-zero if \p node is the root node of the tree
1363 */
1364 cx_attr_nonnull_arg(1, 2)
1365 int cxTreeRemoveNode(
1366 CxTree *tree,
1367 void *node,
1368 cx_tree_relink_func relink_func
1369 );
1370
1371 /**
1372 * Removes a node and it's subtree from the tree.
1373 *
1374 * If the node is not part of the tree, the behavior is undefined.
1375 *
1376 * \note The destructor function, if any, will \em not be invoked. That means
1377 * you will need to free the removed subtree by yourself, eventually.
1378 *
1379 * @param tree the tree
1380 * @param node the node to remove
1381 */
1382 cx_attr_nonnull
1383 void cxTreeRemoveSubtree(CxTree *tree, void *node);
1384
1385 /**
1386 * Destroys a node and re-links its children to its former parent.
1387 *
1388 * If the node is not part of the tree, the behavior is undefined.
1389 *
1390 * It is guaranteed that the simple destructor is invoked before
1391 * the advanced destructor.
1392 *
1393 * \attention This function will not free the memory of the node with the
1394 * tree's allocator, because that is usually done by the advanced destructor
1395 * and would therefore result in a double-free.
1396 *
1397 * @param tree the tree
1398 * @param node the node to destroy (must not be the root node)
1399 * @param relink_func optional callback to update the content of each re-linked
1400 * node
1401 * @return zero on success, non-zero if \p node is the root node of the tree
1402 */
1403 cx_attr_nonnull_arg(1, 2)
1404 int cxTreeDestroyNode(
1405 CxTree *tree,
1406 void *node,
1407 cx_tree_relink_func relink_func
1408 );
1409
394 #ifdef __cplusplus 1410 #ifdef __cplusplus
395 } // extern "C" 1411 } // extern "C"
396 #endif 1412 #endif
397 1413
398 #endif //UCX_TREE_H 1414 #endif //UCX_TREE_H

mercurial