ucx/cx/tree.h

changeset 101
7b3a3130be44
parent 49
2f71f4ee247a
equal deleted inserted replaced
100:d2bd73d28ff1 101:7b3a3130be44
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
136 /** 136 /**
137 * The depth of the node. 137 * The depth of the node.
138 */ 138 */
139 size_t depth; 139 size_t depth;
140 /** 140 /**
141 * The next element in the queue or \c NULL. 141 * The next element in the queue or @c NULL.
142 */ 142 */
143 struct cx_tree_visitor_queue_s *next; 143 struct cx_tree_visitor_queue_s *next;
144 }; 144 };
145 145
146 /** 146 /**
207 207
208 /** 208 /**
209 * Releases internal memory of the given tree iterator. 209 * Releases internal memory of the given tree iterator.
210 * @param iter the iterator 210 * @param iter the iterator
211 */ 211 */
212 __attribute__((__nonnull__)) 212 cx_attr_nonnull
213 static inline void cxTreeIteratorDispose(CxTreeIterator *iter) { 213 static inline void cxTreeIteratorDispose(CxTreeIterator *iter) {
214 free(iter->stack); 214 free(iter->stack);
215 iter->stack = NULL; 215 iter->stack = NULL;
216 } 216 }
217 217
218 /** 218 /**
219 * Releases internal memory of the given tree visitor. 219 * Releases internal memory of the given tree visitor.
220 * @param visitor the visitor 220 * @param visitor the visitor
221 */ 221 */
222 __attribute__((__nonnull__)) 222 cx_attr_nonnull
223 static inline void cxTreeVisitorDispose(CxTreeVisitor *visitor) { 223 static inline void cxTreeVisitorDispose(CxTreeVisitor *visitor) {
224 struct cx_tree_visitor_queue_s *q = visitor->queue_next; 224 struct cx_tree_visitor_queue_s *q = visitor->queue_next;
225 while (q != NULL) { 225 while (q != NULL) {
226 struct cx_tree_visitor_queue_s *next = q->next; 226 struct cx_tree_visitor_queue_s *next = q->next;
227 free(q); 227 free(q);
231 231
232 /** 232 /**
233 * 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
234 * also continues the current loop. 234 * also continues the current loop.
235 * 235 *
236 * @param iterator the iterator 236 * @param iterator (@c CxTreeIterator) the iterator
237 */ 237 */
238 #define cxTreeIteratorContinue(iterator) (iterator).skip = true; continue 238 #define cxTreeIteratorContinue(iterator) (iterator).skip = true; continue
239 239
240 /** 240 /**
241 * 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
242 * also continues the current loop. 242 * also continues the current loop.
243 * 243 *
244 * @param visitor the visitor 244 * @param visitor (@c CxTreeVisitor) the visitor
245 */ 245 */
246 #define cxTreeVisitorContinue(visitor) cxTreeIteratorContinue(visitor) 246 #define cxTreeVisitorContinue(visitor) cxTreeIteratorContinue(visitor)
247 247
248 /** 248 /**
249 * Links a node to a (new) parent. 249 * Links a node to a (new) parent.
250 * 250 *
251 * If the node has already a parent, it is unlinked, first. 251 * If the node has already a parent, it is unlinked, first.
252 * If the parent has children already, the node is \em appended to the list 252 * If the parent has children already, the node is @em appended to the list
253 * of all currently existing children. 253 * of all currently existing children.
254 * 254 *
255 * @param parent the parent node 255 * @param parent the parent node
256 * @param node the node that shall be linked 256 * @param node the node that shall be linked
257 * @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
258 * @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
259 * @param loc_last_child optional offset in the node struct for the pointer to 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) 260 * the last child in the linked list (negative if there is no such pointer)
261 * @param loc_prev offset in the node struct for the prev pointer 261 * @param loc_prev optional offset in the node struct for the prev pointer
262 * @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
263 * @see cx_tree_unlink() 263 * @see cx_tree_unlink()
264 */ 264 */
265 __attribute__((__nonnull__)) 265 cx_attr_nonnull
266 void cx_tree_link( 266 void cx_tree_link(
267 void *restrict parent, 267 void *parent,
268 void *restrict node, 268 void *node,
269 ptrdiff_t loc_parent, 269 ptrdiff_t loc_parent,
270 ptrdiff_t loc_children, 270 ptrdiff_t loc_children,
271 ptrdiff_t loc_last_child, 271 ptrdiff_t loc_last_child,
272 ptrdiff_t loc_prev, 272 ptrdiff_t loc_prev,
273 ptrdiff_t loc_next 273 ptrdiff_t loc_next
281 * @param node the node that shall be unlinked from its parent 281 * @param node the node that shall be unlinked from its parent
282 * @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
283 * @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
284 * @param loc_last_child optional offset in the node struct for the pointer to 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) 285 * the last child in the linked list (negative if there is no such pointer)
286 * @param loc_prev offset in the node struct for the prev pointer 286 * @param loc_prev optional offset in the node struct for the prev pointer
287 * @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
288 * @see cx_tree_link() 288 * @see cx_tree_link()
289 */ 289 */
290 __attribute__((__nonnull__)) 290 cx_attr_nonnull
291 void cx_tree_unlink( 291 void cx_tree_unlink(
292 void *node, 292 void *node,
293 ptrdiff_t loc_parent, 293 ptrdiff_t loc_parent,
294 ptrdiff_t loc_children, 294 ptrdiff_t loc_children,
295 ptrdiff_t loc_last_child, 295 ptrdiff_t loc_last_child,
296 ptrdiff_t loc_prev, 296 ptrdiff_t loc_prev,
297 ptrdiff_t loc_next 297 ptrdiff_t loc_next
298 ); 298 );
299 299
300 /** 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 /**
301 * Function pointer for a search function. 306 * Function pointer for a search function.
302 * 307 *
303 * 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
304 * 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
305 * the data. 310 * the data.
306 * 311 *
307 * 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
308 * 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.
309 * 316 *
310 * 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
311 * describing a parent directory of a filename that is searched, shall 318 * describing a parent directory of a filename that is searched, shall
312 * 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
313 * 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
319 * 326 *
320 * @return 0 if the node contains the data, 327 * @return 0 if the node contains the data,
321 * positive if one of the children might contain the data, 328 * positive if one of the children might contain the data,
322 * negative if neither the node, nor the children contains the data 329 * negative if neither the node, nor the children contains the data
323 */ 330 */
331 cx_attr_nonnull
324 typedef int (*cx_tree_search_data_func)(const void *node, const void *data); 332 typedef int (*cx_tree_search_data_func)(const void *node, const void *data);
325 333
326 334
327 /** 335 /**
328 * Function pointer for a search function. 336 * Function pointer for a search function.
329 * 337 *
330 * A function of this kind shall check if the specified \p node 338 * A function of this kind shall check if the specified @p node
331 * contains the same \p data as \p new_node or if one of the children might 339 * contains the same @p data as @p new_node or if one of the children might
332 * contain the data. 340 * contain the data.
333 * 341 *
334 * The function should use the returned integer to indicate how close the 342 * The function should use the returned integer to indicate how close the
335 * match is, where a negative number means that it does not match at all. 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.
336 * 346 *
337 * For example if a tree stores file path information, a node that is 347 * For example if a tree stores file path information, a node that is
338 * describing a parent directory of a filename that is searched, shall 348 * describing a parent directory of a filename that is searched, shall
339 * return a positive number to indicate that a child node might contain the 349 * return a positive number to indicate that a child node might contain the
340 * searched item. On the other hand, if the node denotes a path that is not a 350 * searched item. On the other hand, if the node denotes a path that is not a
342 * that the search does not need to be continued in that branch. 352 * that the search does not need to be continued in that branch.
343 * 353 *
344 * @param node the node that is currently investigated 354 * @param node the node that is currently investigated
345 * @param new_node a new node with the information which is searched 355 * @param new_node a new node with the information which is searched
346 * 356 *
347 * @return 0 if \p node contains the same data as \p new_node, 357 * @return 0 if @p node contains the same data as @p new_node,
348 * positive if one of the children might contain the data, 358 * positive if one of the children might contain the data,
349 * negative if neither the node, nor the children contains the data 359 * negative if neither the node, nor the children contains the data
350 */ 360 */
361 cx_attr_nonnull
351 typedef int (*cx_tree_search_func)(const void *node, const void *new_node); 362 typedef int (*cx_tree_search_func)(const void *node, const void *new_node);
352 363
353 /** 364 /**
354 * Searches for data in a tree. 365 * Searches for data in a tree.
355 * 366 *
357 * 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
358 * to the tree (see also #cx_tree_add()). 369 * to the tree (see also #cx_tree_add()).
359 * 370 *
360 * 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
361 * "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
362 * 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
363 * \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
364 * node matching the criteria is returned. 375 * node matching the criteria is returned.
365 * 376 *
366 * @param root the root node 377 * @param root the root node
378 * @param depth the maximum depth (zero=indefinite, one=just root)
367 * @param data the data to search for 379 * @param data the data to search for
368 * @param sfunc the search function 380 * @param sfunc the search function
369 * @param result where the result shall be stored 381 * @param result where the result shall be stored
370 * @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
371 * @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
372 * @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
373 * 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
374 * contain any node that might be related to the searched data 386 * contain any node that might be related to the searched data
375 */ 387 */
376 __attribute__((__nonnull__)) 388 cx_attr_nonnull
389 cx_attr_access_w(5)
377 int cx_tree_search_data( 390 int cx_tree_search_data(
378 const void *root, 391 const void *root,
392 size_t depth,
379 const void *data, 393 const void *data,
380 cx_tree_search_data_func sfunc, 394 cx_tree_search_data_func sfunc,
381 void **result, 395 void **result,
382 ptrdiff_t loc_children, 396 ptrdiff_t loc_children,
383 ptrdiff_t loc_next 397 ptrdiff_t loc_next
390 * return a closest result which might be a good starting point for adding the 404 * return a closest result which might be a good starting point for adding the
391 * new node to the tree (see also #cx_tree_add()). 405 * new node to the tree (see also #cx_tree_add()).
392 * 406 *
393 * Depending on the tree structure it is not necessarily guaranteed that the 407 * Depending on the tree structure it is not necessarily guaranteed that the
394 * "closest" match is uniquely defined. This function will search for a node 408 * "closest" match is uniquely defined. This function will search for a node
395 * with the best match according to the \p sfunc (meaning: the return value of 409 * with the best match according to the @p sfunc (meaning: the return value of
396 * \p sfunc which is closest to zero). If that is also ambiguous, an arbitrary 410 * @p sfunc which is closest to zero). If that is also ambiguous, an arbitrary
397 * node matching the criteria is returned. 411 * node matching the criteria is returned.
398 * 412 *
399 * @param root the root node 413 * @param root the root node
414 * @param depth the maximum depth (zero=indefinite, one=just root)
400 * @param node the node to search for 415 * @param node the node to search for
401 * @param sfunc the search function 416 * @param sfunc the search function
402 * @param result where the result shall be stored 417 * @param result where the result shall be stored
403 * @param loc_children offset in the node struct for the children linked list 418 * @param loc_children offset in the node struct for the children linked list
404 * @param loc_next offset in the node struct for the next pointer 419 * @param loc_next offset in the node struct for the next pointer
405 * @return zero if the node was found exactly, positive if a node was found that 420 * @return zero if the node was found exactly, positive if a node was found that
406 * could contain the node (but doesn't right now), negative if the tree does not 421 * could contain the node (but doesn't right now), negative if the tree does not
407 * contain any node that might be related to the searched data 422 * contain any node that might be related to the searched data
408 */ 423 */
409 __attribute__((__nonnull__)) 424 cx_attr_nonnull
425 cx_attr_access_w(5)
410 int cx_tree_search( 426 int cx_tree_search(
411 const void *root, 427 const void *root,
428 size_t depth,
412 const void *node, 429 const void *node,
413 cx_tree_search_func sfunc, 430 cx_tree_search_func sfunc,
414 void **result, 431 void **result,
415 ptrdiff_t loc_children, 432 ptrdiff_t loc_children,
416 ptrdiff_t loc_next 433 ptrdiff_t loc_next
434 * @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
435 * @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
436 * @return the new tree iterator 453 * @return the new tree iterator
437 * @see cxTreeIteratorDispose() 454 * @see cxTreeIteratorDispose()
438 */ 455 */
456 cx_attr_nodiscard
439 CxTreeIterator cx_tree_iterator( 457 CxTreeIterator cx_tree_iterator(
440 void *root, 458 void *root,
441 bool visit_on_exit, 459 bool visit_on_exit,
442 ptrdiff_t loc_children, 460 ptrdiff_t loc_children,
443 ptrdiff_t loc_next 461 ptrdiff_t loc_next
459 * @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
460 * @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
461 * @return the new tree visitor 479 * @return the new tree visitor
462 * @see cxTreeVisitorDispose() 480 * @see cxTreeVisitorDispose()
463 */ 481 */
482 cx_attr_nodiscard
464 CxTreeVisitor cx_tree_visitor( 483 CxTreeVisitor cx_tree_visitor(
465 void *root, 484 void *root,
466 ptrdiff_t loc_children, 485 ptrdiff_t loc_children,
467 ptrdiff_t loc_next 486 ptrdiff_t loc_next
468 ); 487 );
470 /** 489 /**
471 * Describes a function that creates a tree node from the specified data. 490 * Describes a function that creates a tree node from the specified data.
472 * The first argument points to the data the node shall contain and 491 * The first argument points to the data the node shall contain and
473 * the second argument may be used for additional data (e.g. an allocator). 492 * the second argument may be used for additional data (e.g. an allocator).
474 * Functions of this type shall either return a new pointer to a newly 493 * Functions of this type shall either return a new pointer to a newly
475 * created node or \c NULL when allocation fails. 494 * created node or @c NULL when allocation fails.
476 * 495 *
477 * \note the function may leave the node pointers in the struct uninitialized. 496 * @note the function may leave the node pointers in the struct uninitialized.
478 * The caller is responsible to set them according to the intended use case. 497 * The caller is responsible to set them according to the intended use case.
479 */ 498 */
499 cx_attr_nonnull_arg(1)
480 typedef void *(*cx_tree_node_create_func)(const void *, void *); 500 typedef void *(*cx_tree_node_create_func)(const void *, void *);
481 501
482 /** 502 /**
483 * The local search depth for a new subtree when adding multiple elements. 503 * The local search depth for a new subtree when adding multiple elements.
484 * The default value is 3. 504 * The default value is 3.
491 * Adds multiple elements efficiently to a tree. 511 * Adds multiple elements efficiently to a tree.
492 * 512 *
493 * Once an element cannot be added to the tree, this function returns, leaving 513 * Once an element cannot be added to the tree, this function returns, leaving
494 * the iterator in a valid state pointing to the element that could not be 514 * the iterator in a valid state pointing to the element that could not be
495 * added. 515 * added.
496 * Also, the pointer of the created node will be stored to \p failed. 516 * Also, the pointer of the created node will be stored to @p failed.
497 * The integer returned by this function denotes the number of elements obtained 517 * The integer returned by this function denotes the number of elements obtained
498 * from the \p iter that have been successfully processed. 518 * from the @p iter that have been successfully processed.
499 * When all elements could be processed, a \c NULL pointer will be written to 519 * When all elements could be processed, a @c NULL pointer will be written to
500 * \p failed. 520 * @p failed.
501 * 521 *
502 * The advantage of this function compared to multiple invocations of 522 * The advantage of this function compared to multiple invocations of
503 * #cx_tree_add() is that the search for the insert locations is not always 523 * #cx_tree_add() is that the search for the insert locations is not always
504 * started from the root node. 524 * started from the root node.
505 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes 525 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes
518 * @param failed location where the pointer to a failed node shall be stored 538 * @param failed location where the pointer to a failed node shall be stored
519 * @param loc_parent offset in the node struct for the parent pointer 539 * @param loc_parent offset in the node struct for the parent pointer
520 * @param loc_children offset in the node struct for the children linked list 540 * @param loc_children offset in the node struct for the children linked list
521 * @param loc_last_child optional offset in the node struct for the pointer to 541 * @param loc_last_child optional offset in the node struct for the pointer to
522 * the last child in the linked list (negative if there is no such pointer) 542 * the last child in the linked list (negative if there is no such pointer)
523 * @param loc_prev offset in the node struct for the prev pointer 543 * @param loc_prev optional offset in the node struct for the prev pointer
524 * @param loc_next offset in the node struct for the next pointer 544 * @param loc_next offset in the node struct for the next pointer
525 * @return the number of nodes created and added 545 * @return the number of nodes created and added
526 * @see cx_tree_add() 546 * @see cx_tree_add()
527 */ 547 */
528 __attribute__((__nonnull__(1, 3, 4, 6, 7))) 548 cx_attr_nonnull_arg(1, 3, 4, 6, 7)
549 cx_attr_access_w(6)
529 size_t cx_tree_add_iter( 550 size_t cx_tree_add_iter(
530 struct cx_iterator_base_s *iter, 551 struct cx_iterator_base_s *iter,
531 size_t num, 552 size_t num,
532 cx_tree_search_func sfunc, 553 cx_tree_search_func sfunc,
533 cx_tree_node_create_func cfunc, 554 cx_tree_node_create_func cfunc,
543 564
544 /** 565 /**
545 * Adds multiple elements efficiently to a tree. 566 * Adds multiple elements efficiently to a tree.
546 * 567 *
547 * Once an element cannot be added to the tree, this function returns, storing 568 * Once an element cannot be added to the tree, this function returns, storing
548 * the pointer of the created node to \p failed. 569 * the pointer of the created node to @p failed.
549 * The integer returned by this function denotes the number of elements from 570 * The integer returned by this function denotes the number of elements from
550 * the \p src array that have been successfully processed. 571 * the @p src array that have been successfully processed.
551 * When all elements could be processed, a \c NULL pointer will be written to 572 * When all elements could be processed, a @c NULL pointer will be written to
552 * \p failed. 573 * @p failed.
553 * 574 *
554 * The advantage of this function compared to multiple invocations of 575 * The advantage of this function compared to multiple invocations of
555 * #cx_tree_add() is that the search for the insert locations is not always 576 * #cx_tree_add() is that the search for the insert locations is not always
556 * started from the root node. 577 * started from the root node.
557 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes 578 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes
560 * again. 581 * again.
561 * 582 *
562 * Refer to the documentation of #cx_tree_add() for more details. 583 * Refer to the documentation of #cx_tree_add() for more details.
563 * 584 *
564 * @param src a pointer to the source data array 585 * @param src a pointer to the source data array
565 * @param num the number of elements in the \p src array 586 * @param num the number of elements in the @p src array
566 * @param elem_size the size of each element in the \p src array 587 * @param elem_size the size of each element in the @p src array
567 * @param sfunc a search function 588 * @param sfunc a search function
568 * @param cfunc a node creation function 589 * @param cfunc a node creation function
569 * @param cdata optional additional data 590 * @param cdata optional additional data
570 * @param failed location where the pointer to a failed node shall be stored 591 * @param failed location where the pointer to a failed node shall be stored
571 * @param root the root node of the tree 592 * @param root the root node of the tree
572 * @param loc_parent offset in the node struct for the parent pointer 593 * @param loc_parent offset in the node struct for the parent pointer
573 * @param loc_children offset in the node struct for the children linked list 594 * @param loc_children offset in the node struct for the children linked list
574 * @param loc_last_child optional offset in the node struct for the pointer to 595 * @param loc_last_child optional offset in the node struct for the pointer to
575 * the last child in the linked list (negative if there is no such pointer) 596 * the last child in the linked list (negative if there is no such pointer)
576 * @param loc_prev offset in the node struct for the prev pointer 597 * @param loc_prev optional offset in the node struct for the prev pointer
577 * @param loc_next offset in the node struct for the next pointer 598 * @param loc_next offset in the node struct for the next pointer
578 * @return the number of array elements successfully processed 599 * @return the number of array elements successfully processed
579 * @see cx_tree_add() 600 * @see cx_tree_add()
580 */ 601 */
581 __attribute__((__nonnull__(1, 4, 5, 7, 8))) 602 cx_attr_nonnull_arg(1, 4, 5, 7, 8)
603 cx_attr_access_w(7)
582 size_t cx_tree_add_array( 604 size_t cx_tree_add_array(
583 const void *src, 605 const void *src,
584 size_t num, 606 size_t num,
585 size_t elem_size, 607 size_t elem_size,
586 cx_tree_search_func sfunc, 608 cx_tree_search_func sfunc,
597 619
598 /** 620 /**
599 * Adds data to a tree. 621 * Adds data to a tree.
600 * 622 *
601 * An adequate location where to add the new tree node is searched with the 623 * An adequate location where to add the new tree node is searched with the
602 * specified \p sfunc. 624 * specified @p sfunc.
603 * 625 *
604 * When a location is found, the \p cfunc will be invoked with \p cdata. 626 * When a location is found, the @p cfunc will be invoked with @p cdata.
605 * 627 *
606 * The node returned by \p cfunc will be linked into the tree. 628 * The node returned by @p cfunc will be linked into the tree.
607 * When \p sfunc returned a positive integer, the new node will be linked as a 629 * When @p sfunc returned a positive integer, the new node will be linked as a
608 * child. The other children (now siblings of the new node) are then checked 630 * child. The other children (now siblings of the new node) are then checked
609 * with \p sfunc, whether they could be children of the new node and re-linked 631 * with @p sfunc, whether they could be children of the new node and re-linked
610 * accordingly. 632 * accordingly.
611 * 633 *
612 * When \p sfunc returned zero and the found node has a parent, the new 634 * When @p sfunc returned zero and the found node has a parent, the new
613 * node will be added as sibling - otherwise, the new node will be added 635 * node will be added as sibling - otherwise, the new node will be added
614 * as a child. 636 * as a child.
615 * 637 *
616 * When \p sfunc returned a negative value, the new node will not be added to 638 * When @p sfunc returned a negative value, the new node will not be added to
617 * the tree and this function returns a non-zero value. 639 * the tree and this function returns a non-zero value.
618 * The caller should check if \p cnode contains a node pointer and deal with the 640 * The caller should check if @p cnode contains a node pointer and deal with the
619 * node that could not be added. 641 * node that could not be added.
620 * 642 *
621 * This function also returns a non-zero value when \p cfunc tries to allocate 643 * This function also returns a non-zero value when @p cfunc tries to allocate
622 * a new node but fails to do so. In that case, the pointer stored to \p cnode 644 * a new node but fails to do so. In that case, the pointer stored to @p cnode
623 * will be \c NULL. 645 * will be @c NULL.
624 * 646 *
625 * Multiple elements can be added more efficiently with 647 * Multiple elements can be added more efficiently with
626 * #cx_tree_add_array() or #cx_tree_add_iter(). 648 * #cx_tree_add_array() or #cx_tree_add_iter().
627 * 649 *
628 * @param src a pointer to the data 650 * @param src a pointer to the data
633 * @param root the root node of the tree 655 * @param root the root node of the tree
634 * @param loc_parent offset in the node struct for the parent pointer 656 * @param loc_parent offset in the node struct for the parent pointer
635 * @param loc_children offset in the node struct for the children linked list 657 * @param loc_children offset in the node struct for the children linked list
636 * @param loc_last_child optional offset in the node struct for the pointer to 658 * @param loc_last_child optional offset in the node struct for the pointer to
637 * the last child in the linked list (negative if there is no such pointer) 659 * the last child in the linked list (negative if there is no such pointer)
638 * @param loc_prev offset in the node struct for the prev pointer 660 * @param loc_prev optional offset in the node struct for the prev pointer
639 * @param loc_next offset in the node struct for the next pointer 661 * @param loc_next offset in the node struct for the next pointer
640 * @return zero when a new node was created and added to the tree, 662 * @return zero when a new node was created and added to the tree,
641 * non-zero otherwise 663 * non-zero otherwise
642 */ 664 */
643 __attribute__((__nonnull__(1, 2, 3, 5, 6))) 665 cx_attr_nonnull_arg(1, 2, 3, 5, 6)
666 cx_attr_access_w(5)
644 int cx_tree_add( 667 int cx_tree_add(
645 const void *src, 668 const void *src,
646 cx_tree_search_func sfunc, 669 cx_tree_search_func sfunc,
647 cx_tree_node_create_func cfunc, 670 cx_tree_node_create_func cfunc,
648 void *cdata, 671 void *cdata,
702 const CxAllocator *allocator; 725 const CxAllocator *allocator;
703 726
704 /** 727 /**
705 * A pointer to the root node. 728 * A pointer to the root node.
706 * 729 *
707 * Will be \c NULL when \c size is 0. 730 * Will be @c NULL when @c size is 0.
708 */ 731 */
709 void *root; 732 void *root;
710 733
711 /** 734 /**
712 * A function to create new nodes. 735 * A function to create new nodes.
776 }; 799 };
777 800
778 /** 801 /**
779 * Macro to roll out the #cx_tree_node_base_s structure with a custom 802 * Macro to roll out the #cx_tree_node_base_s structure with a custom
780 * node type. 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
781 */ 808 */
782 #define CX_TREE_NODE_BASE(type) \ 809 #define CX_TREE_NODE_BASE(type) \
783 type *parent; \ 810 type *parent; \
784 type *children;\ 811 type *children;\
785 type *last_child;\ 812 type *last_child;\
786 type *prev;\ 813 type *prev;\
787 type *next 814 type *next
788 815
789 /** 816 /**
790 * Macro for specifying the layout of a base node tree. 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.
791 */ 823 */
792 #define cx_tree_node_base_layout \ 824 #define cx_tree_node_base_layout \
793 offsetof(struct cx_tree_node_base_s, parent),\ 825 offsetof(struct cx_tree_node_base_s, parent),\
794 offsetof(struct cx_tree_node_base_s, children),\ 826 offsetof(struct cx_tree_node_base_s, children),\
795 offsetof(struct cx_tree_node_base_s, last_child),\ 827 offsetof(struct cx_tree_node_base_s, last_child),\
796 offsetof(struct cx_tree_node_base_s, prev), \ 828 offsetof(struct cx_tree_node_base_s, prev), \
797 offsetof(struct cx_tree_node_base_s, next) 829 offsetof(struct cx_tree_node_base_s, next)
798 830
799 /** 831 /**
800 * Macro for obtaining the node pointer layout for a specific tree.
801 */
802 #define cx_tree_node_layout(tree) \
803 (tree)->loc_parent,\
804 (tree)->loc_children,\
805 (tree)->loc_last_child,\
806 (tree)->loc_prev, \
807 (tree)->loc_next
808
809 /**
810 * The class definition for arbitrary trees. 832 * The class definition for arbitrary trees.
811 */ 833 */
812 struct cx_tree_class_s { 834 struct cx_tree_class_s {
813 /**
814 * Destructor function.
815 *
816 * Implementations SHALL invoke the node destructor functions if provided
817 * and SHALL deallocate the tree memory.
818 */
819 void (*destructor)(struct cx_tree_s *);
820
821 /** 835 /**
822 * Member function for inserting a single element. 836 * Member function for inserting a single element.
823 * 837 *
824 * Implementations SHALL NOT simply invoke \p insert_many as this comes 838 * Implementations SHALL NOT simply invoke @p insert_many as this comes
825 * with too much overhead. 839 * with too much overhead.
826 */ 840 */
827 int (*insert_element)( 841 int (*insert_element)(
828 struct cx_tree_s *tree, 842 struct cx_tree_s *tree,
829 const void *data 843 const void *data
845 * Member function for finding a node. 859 * Member function for finding a node.
846 */ 860 */
847 void *(*find)( 861 void *(*find)(
848 struct cx_tree_s *tree, 862 struct cx_tree_s *tree,
849 const void *subtree, 863 const void *subtree,
850 const void *data 864 const void *data,
865 size_t depth
851 ); 866 );
852
853 /**
854 * Member function for creating an iterator for the tree.
855 */
856 CxTreeIterator (*iterator)(
857 struct cx_tree_s *tree,
858 bool visit_on_exit
859 );
860
861 /**
862 * Member function for creating a visitor for the tree.
863 */
864 CxTreeVisitor (*visitor)(struct cx_tree_s *tree);
865 }; 867 };
866 868
867 /** 869 /**
868 * Common type for all tree implementations. 870 * Common type for all tree implementations.
869 */ 871 */
870 typedef struct cx_tree_s CxTree; 872 typedef struct cx_tree_s CxTree;
871 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
872 /** 937 /**
873 * Creates a new tree structure based on the specified layout. 938 * Creates a new tree structure based on the specified layout.
874 * 939 *
875 * The specified \p allocator will be used for creating the tree struct 940 * The specified @p allocator will be used for creating the tree struct
876 * and SHALL be used by \p create_func to allocate memory for the nodes. 941 * and SHALL be used by @p create_func to allocate memory for the nodes.
877 * 942 *
878 * \note This function will also register an advanced destructor which 943 * @note This function will also register an advanced destructor which
879 * will free the nodes with the allocator's free() method. 944 * will free the nodes with the allocator's free() method.
880 * 945 *
881 * @param allocator the allocator that shall be used 946 * @param allocator the allocator that shall be used
947 * (if @c NULL, a default stdlib allocator will be used)
882 * @param create_func a function that creates new nodes 948 * @param create_func a function that creates new nodes
883 * @param search_func a function that compares two nodes 949 * @param search_func a function that compares two nodes
884 * @param search_data_func a function that compares a node with data 950 * @param search_data_func a function that compares a node with data
885 * @param loc_parent offset in the node struct for the parent pointer 951 * @param loc_parent offset in the node struct for the parent pointer
886 * @param loc_children offset in the node struct for the children linked list 952 * @param loc_children offset in the node struct for the children linked list
887 * @param loc_last_child optional offset in the node struct for the pointer to 953 * @param loc_last_child optional offset in the node struct for the pointer to
888 * the last child in the linked list (negative if there is no such pointer) 954 * the last child in the linked list (negative if there is no such pointer)
889 * @param loc_prev offset in the node struct for the prev pointer 955 * @param loc_prev optional offset in the node struct for the prev pointer
890 * @param loc_next offset in the node struct for the next pointer 956 * @param loc_next offset in the node struct for the next pointer
891 * @return the new tree 957 * @return the new tree
892 * @see cxTreeCreateSimple() 958 * @see cxTreeCreateSimple()
893 * @see cxTreeCreateWrapped() 959 * @see cxTreeCreateWrapped()
894 */ 960 */
895 __attribute__((__nonnull__, __warn_unused_result__)) 961 cx_attr_nonnull_arg(2, 3, 4)
962 cx_attr_nodiscard
963 cx_attr_malloc
964 cx_attr_dealloc(cxTreeFree, 1)
896 CxTree *cxTreeCreate( 965 CxTree *cxTreeCreate(
897 const CxAllocator *allocator, 966 const CxAllocator *allocator,
898 cx_tree_node_create_func create_func, 967 cx_tree_node_create_func create_func,
899 cx_tree_search_func search_func, 968 cx_tree_search_func search_func,
900 cx_tree_search_data_func search_data_func, 969 cx_tree_search_data_func search_data_func,
906 ); 975 );
907 976
908 /** 977 /**
909 * Creates a new tree structure based on a default layout. 978 * Creates a new tree structure based on a default layout.
910 * 979 *
911 * Nodes created by \p create_func MUST contain #cx_tree_node_base_s as first 980 * Nodes created by @p create_func MUST contain #cx_tree_node_base_s as first
912 * member (or at least respect the default offsets specified in the tree 981 * member (or at least respect the default offsets specified in the tree
913 * struct) and they MUST be allocated with the specified allocator. 982 * struct) and they MUST be allocated with the specified allocator.
914 * 983 *
915 * \note This function will also register an advanced destructor which 984 * @note This function will also register an advanced destructor which
916 * will free the nodes with the allocator's free() method. 985 * will free the nodes with the allocator's free() method.
917 * 986 *
918 * @param allocator the allocator that shall be used 987 * @param allocator (@c CxAllocator*) the allocator that shall be used
919 * @param create_func a function that creates new nodes 988 * @param create_func (@c cx_tree_node_create_func) a function that creates new nodes
920 * @param search_func a function that compares two nodes 989 * @param search_func (@c cx_tree_search_func) a function that compares two nodes
921 * @param search_data_func a function that compares a node with data 990 * @param search_data_func (@c cx_tree_search_data_func) a function that compares a node with data
922 * @return the new tree 991 * @return (@c CxTree*) the new tree
923 * @see cxTreeCreate() 992 * @see cxTreeCreate()
924 */ 993 */
925 __attribute__((__nonnull__, __warn_unused_result__)) 994 #define cxTreeCreateSimple(\
926 static inline CxTree *cxTreeCreateSimple( 995 allocator, create_func, search_func, search_data_func \
927 const CxAllocator *allocator, 996 ) cxTreeCreate(allocator, create_func, search_func, search_data_func, \
928 cx_tree_node_create_func create_func, 997 cx_tree_node_base_layout)
929 cx_tree_search_func search_func,
930 cx_tree_search_data_func search_data_func
931 ) {
932 return cxTreeCreate(
933 allocator,
934 create_func,
935 search_func,
936 search_data_func,
937 cx_tree_node_base_layout
938 );
939 }
940 998
941 /** 999 /**
942 * Creates a new tree structure based on an existing tree. 1000 * Creates a new tree structure based on an existing tree.
943 * 1001 *
944 * The specified \p allocator will be used for creating the tree struct. 1002 * The specified @p allocator will be used for creating the tree struct.
945 * 1003 *
946 * \attention This function will create an incompletely defined tree structure 1004 * @attention This function will create an incompletely defined tree structure
947 * where neither the create function, the search function, nor a destructor 1005 * where neither the create function, the search function, nor a destructor
948 * will be set. If you wish to use any of this functionality for the wrapped 1006 * will be set. If you wish to use any of this functionality for the wrapped
949 * tree, you need to specify those functions afterwards. 1007 * tree, you need to specify those functions afterwards.
950 * 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)
951 * @param root the root node of the tree that shall be wrapped 1011 * @param root the root node of the tree that shall be wrapped
952 * @param loc_parent offset in the node struct for the parent pointer 1012 * @param loc_parent offset in the node struct for the parent pointer
953 * @param loc_children offset in the node struct for the children linked list 1013 * @param loc_children offset in the node struct for the children linked list
954 * @param loc_last_child optional offset in the node struct for the pointer to 1014 * @param loc_last_child optional offset in the node struct for the pointer to
955 * the last child in the linked list (negative if there is no such pointer) 1015 * the last child in the linked list (negative if there is no such pointer)
956 * @param loc_prev offset in the node struct for the prev pointer 1016 * @param loc_prev optional offset in the node struct for the prev pointer
957 * @param loc_next offset in the node struct for the next pointer 1017 * @param loc_next offset in the node struct for the next pointer
958 * @return the new tree 1018 * @return the new tree
959 * @see cxTreeCreate() 1019 * @see cxTreeCreate()
960 */ 1020 */
961 __attribute__((__nonnull__, __warn_unused_result__)) 1021 cx_attr_nonnull_arg(2)
1022 cx_attr_nodiscard
1023 cx_attr_malloc
1024 cx_attr_dealloc(cxTreeFree, 1)
962 CxTree *cxTreeCreateWrapped( 1025 CxTree *cxTreeCreateWrapped(
963 const CxAllocator *allocator, 1026 const CxAllocator *allocator,
964 void *root, 1027 void *root,
965 ptrdiff_t loc_parent, 1028 ptrdiff_t loc_parent,
966 ptrdiff_t loc_children, 1029 ptrdiff_t loc_children,
968 ptrdiff_t loc_prev, 1031 ptrdiff_t loc_prev,
969 ptrdiff_t loc_next 1032 ptrdiff_t loc_next
970 ); 1033 );
971 1034
972 /** 1035 /**
973 * Destroys the tree structure.
974 *
975 * \attention This function will only invoke the destructor functions
976 * on the nodes, if specified.
977 * It will NOT additionally free the nodes with the tree's allocator, because
978 * that would cause a double-free in most scenarios.
979 *
980 * @param tree the tree to destroy
981 */
982 __attribute__((__nonnull__))
983 static inline void cxTreeDestroy(CxTree *tree) {
984 tree->cl->destructor(tree);
985 }
986
987 /**
988 * Inserts data into the tree. 1036 * Inserts data into the tree.
989 * 1037 *
990 * \remark For this function to work, the tree needs specified search and 1038 * @remark For this function to work, the tree needs specified search and
991 * create functions, which might not be available for wrapped trees 1039 * create functions, which might not be available for wrapped trees
992 * (see #cxTreeCreateWrapped()). 1040 * (see #cxTreeCreateWrapped()).
993 * 1041 *
994 * @param tree the tree 1042 * @param tree the tree
995 * @param data the data to insert 1043 * @param data the data to insert
996 * @return zero on success, non-zero on failure 1044 * @retval zero success
997 */ 1045 * @retval non-zero failure
998 __attribute__((__nonnull__)) 1046 */
1047 cx_attr_nonnull
999 static inline int cxTreeInsert( 1048 static inline int cxTreeInsert(
1000 CxTree *tree, 1049 CxTree *tree,
1001 const void *data 1050 const void *data
1002 ) { 1051 ) {
1003 return tree->cl->insert_element(tree, data); 1052 return tree->cl->insert_element(tree, data);
1004 } 1053 }
1005 1054
1006 /** 1055 /**
1007 * Inserts elements provided by an iterator efficiently into the tree. 1056 * Inserts elements provided by an iterator efficiently into the tree.
1008 * 1057 *
1009 * \remark For this function to work, the tree needs specified search and 1058 * @remark For this function to work, the tree needs specified search and
1010 * create functions, which might not be available for wrapped trees 1059 * create functions, which might not be available for wrapped trees
1011 * (see #cxTreeCreateWrapped()). 1060 * (see #cxTreeCreateWrapped()).
1012 * 1061 *
1013 * @param tree the tree 1062 * @param tree the tree
1014 * @param iter the iterator providing the elements 1063 * @param iter the iterator providing the elements
1015 * @param n the maximum number of elements to insert 1064 * @param n the maximum number of elements to insert
1016 * @return the number of elements that could be successfully inserted 1065 * @return the number of elements that could be successfully inserted
1017 */ 1066 */
1018 __attribute__((__nonnull__)) 1067 cx_attr_nonnull
1019 static inline size_t cxTreeInsertIter( 1068 static inline size_t cxTreeInsertIter(
1020 CxTree *tree, 1069 CxTree *tree,
1021 struct cx_iterator_base_s *iter, 1070 struct cx_iterator_base_s *iter,
1022 size_t n 1071 size_t n
1023 ) { 1072 ) {
1025 } 1074 }
1026 1075
1027 /** 1076 /**
1028 * Inserts an array of data efficiently into the tree. 1077 * Inserts an array of data efficiently into the tree.
1029 * 1078 *
1030 * \remark For this function to work, the tree needs specified search and 1079 * @remark For this function to work, the tree needs specified search and
1031 * create functions, which might not be available for wrapped trees 1080 * create functions, which might not be available for wrapped trees
1032 * (see #cxTreeCreateWrapped()). 1081 * (see #cxTreeCreateWrapped()).
1033 * 1082 *
1034 * @param tree the tree 1083 * @param tree the tree
1035 * @param data the array of data to insert 1084 * @param data the array of data to insert
1036 * @param elem_size the size of each element in the array 1085 * @param elem_size the size of each element in the array
1037 * @param n the number of elements in the array 1086 * @param n the number of elements in the array
1038 * @return the number of elements that could be successfully inserted 1087 * @return the number of elements that could be successfully inserted
1039 */ 1088 */
1040 __attribute__((__nonnull__)) 1089 cx_attr_nonnull
1041 static inline size_t cxTreeInsertArray( 1090 static inline size_t cxTreeInsertArray(
1042 CxTree *tree, 1091 CxTree *tree,
1043 const void *data, 1092 const void *data,
1044 size_t elem_size, 1093 size_t elem_size,
1045 size_t n 1094 size_t n
1051 } 1100 }
1052 1101
1053 /** 1102 /**
1054 * Searches the data in the specified tree. 1103 * Searches the data in the specified tree.
1055 * 1104 *
1056 * \remark For this function to work, the tree needs a specified \c search_data 1105 * @remark For this function to work, the tree needs a specified @c search_data
1057 * function, which might not be available wrapped trees 1106 * function, which might not be available wrapped trees
1058 * (see #cxTreeCreateWrapped()). 1107 * (see #cxTreeCreateWrapped()).
1059 * 1108 *
1060 * @param tree the tree 1109 * @param tree the tree
1061 * @param data the data to search for 1110 * @param data the data to search for
1062 * @return the first matching node, or \c NULL when the data cannot be found 1111 * @return the first matching node, or @c NULL when the data cannot be found
1063 */ 1112 */
1064 __attribute__((__nonnull__)) 1113 cx_attr_nonnull
1114 cx_attr_nodiscard
1065 static inline void *cxTreeFind( 1115 static inline void *cxTreeFind(
1066 CxTree *tree, 1116 CxTree *tree,
1067 const void *data 1117 const void *data
1068 ) { 1118 ) {
1069 return tree->cl->find(tree, tree->root, data); 1119 return tree->cl->find(tree, tree->root, data, 0);
1070 } 1120 }
1071 1121
1072 /** 1122 /**
1073 * Searches the data in the specified subtree. 1123 * Searches the data in the specified subtree.
1074 * 1124 *
1075 * \note When \p subtree_root is not part of the \p tree, the behavior is 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
1076 * undefined. 1129 * undefined.
1077 * 1130 *
1078 * \remark For this function to work, the tree needs a specified \c search_data 1131 * @remark For this function to work, the tree needs a specified @c search_data
1079 * function, which might not be the case for wrapped trees 1132 * function, which might not be the case for wrapped trees
1080 * (see #cxTreeCreateWrapped()). 1133 * (see #cxTreeCreateWrapped()).
1081 * 1134 *
1082 * @param tree the tree 1135 * @param tree the tree
1083 * @param data the data to search for 1136 * @param data the data to search for
1084 * @param subtree_root the node where to start 1137 * @param subtree_root the node where to start
1085 * @return the first matching node, or \c NULL when the data cannot be found 1138 * @param max_depth the maximum search depth
1086 */ 1139 * @return the first matching node, or @c NULL when the data cannot be found
1087 __attribute__((__nonnull__)) 1140 */
1141 cx_attr_nonnull
1142 cx_attr_nodiscard
1088 static inline void *cxTreeFindInSubtree( 1143 static inline void *cxTreeFindInSubtree(
1089 CxTree *tree, 1144 CxTree *tree,
1090 const void *data, 1145 const void *data,
1091 void *subtree_root 1146 void *subtree_root,
1147 size_t max_depth
1092 ) { 1148 ) {
1093 return tree->cl->find(tree, subtree_root, data); 1149 return tree->cl->find(tree, subtree_root, data, max_depth);
1094 } 1150 }
1095 1151
1096 /** 1152 /**
1097 * Determines the size of the specified subtree. 1153 * Determines the size of the specified subtree.
1098 * 1154 *
1099 * @param tree the tree 1155 * @param tree the tree
1100 * @param subtree_root the root node of the subtree 1156 * @param subtree_root the root node of the subtree
1101 * @return the number of nodes in the specified subtree 1157 * @return the number of nodes in the specified subtree
1102 */ 1158 */
1103 __attribute__((__nonnull__)) 1159 cx_attr_nonnull
1160 cx_attr_nodiscard
1104 size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root); 1161 size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root);
1105 1162
1106 /** 1163 /**
1107 * Determines the depth of the specified subtree. 1164 * Determines the depth of the specified subtree.
1108 * 1165 *
1109 * @param tree the tree 1166 * @param tree the tree
1110 * @param subtree_root the root node of the subtree 1167 * @param subtree_root the root node of the subtree
1111 * @return the tree depth including the \p subtree_root 1168 * @return the tree depth including the @p subtree_root
1112 */ 1169 */
1113 __attribute__((__nonnull__)) 1170 cx_attr_nonnull
1171 cx_attr_nodiscard
1114 size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root); 1172 size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root);
1115 1173
1116 /** 1174 /**
1117 * Determines the depth of the entire tree. 1175 * Determines the depth of the entire tree.
1118 * 1176 *
1119 * @param tree the tree 1177 * @param tree the tree
1120 * @return the tree depth, counting the root as one 1178 * @return the tree depth, counting the root as one
1121 */ 1179 */
1122 __attribute__((__nonnull__)) 1180 cx_attr_nonnull
1181 cx_attr_nodiscard
1123 size_t cxTreeDepth(CxTree *tree); 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 }
1124 1226
1125 /** 1227 /**
1126 * Creates a depth-first iterator for the specified tree. 1228 * Creates a depth-first iterator for the specified tree.
1127 * 1229 *
1128 * @param tree the tree to iterate 1230 * @param tree the tree to iterate
1129 * @param visit_on_exit true, if the iterator shall visit a node again when 1231 * @param visit_on_exit true, if the iterator shall visit a node again when
1130 * leaving the sub-tree 1232 * leaving the subtree
1131 * @return a tree iterator (depth-first) 1233 * @return a tree iterator (depth-first)
1132 * @see cxTreeVisitor() 1234 * @see cxTreeVisit()
1133 */ 1235 */
1134 __attribute__((__nonnull__, __warn_unused_result__)) 1236 cx_attr_nonnull
1135 static inline CxTreeIterator cxTreeIterator( 1237 cx_attr_nodiscard
1238 static inline CxTreeIterator cxTreeIterate(
1136 CxTree *tree, 1239 CxTree *tree,
1137 bool visit_on_exit 1240 bool visit_on_exit
1138 ) { 1241 ) {
1139 return tree->cl->iterator(tree, visit_on_exit); 1242 return cxTreeIterateSubtree(tree, tree->root, visit_on_exit);
1140 } 1243 }
1141 1244
1142 /** 1245 /**
1143 * Creates a breadth-first iterator for the specified tree. 1246 * Creates a breadth-first iterator for the specified tree.
1144 * 1247 *
1145 * @param tree the tree to iterate 1248 * @param tree the tree to iterate
1146 * @return a tree visitor (a.k.a. breadth-first iterator) 1249 * @return a tree visitor (a.k.a. breadth-first iterator)
1147 * @see cxTreeIterator() 1250 * @see cxTreeIterate()
1148 */ 1251 */
1149 __attribute__((__nonnull__, __warn_unused_result__)) 1252 cx_attr_nonnull
1150 static inline CxTreeVisitor cxTreeVisitor(CxTree *tree) { 1253 cx_attr_nodiscard
1151 return tree->cl->visitor(tree); 1254 static inline CxTreeVisitor cxTreeVisit(CxTree *tree) {
1255 return cxTreeVisitSubtree(tree, tree->root);
1152 } 1256 }
1153 1257
1154 /** 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 /**
1155 * Adds a new node to the tree. 1277 * Adds a new node to the tree.
1156 * 1278 *
1157 * \attention The node may be externally created, but MUST obey the same rules 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
1158 * as if it was created by the tree itself with #cxTreeAddChild() (e.g. use 1283 * as if it was created by the tree itself with #cxTreeAddChild() (e.g. use
1159 * the same allocator). 1284 * the same allocator).
1160 * 1285 *
1161 * @param tree the tree 1286 * @param tree the tree
1162 * @param parent the parent of the node to add 1287 * @param parent the parent of the node to add
1163 * @param child the node to add 1288 * @param child the node to add
1164 */ 1289 * @see cxTreeSetParent()
1165 __attribute__((__nonnull__)) 1290 */
1166 static inline void cxTreeAddChildNode( 1291 cx_attr_nonnull
1292 void cxTreeAddChildNode(
1167 CxTree *tree, 1293 CxTree *tree,
1168 void *parent, 1294 void *parent,
1169 void *child) { 1295 void *child
1170 cx_tree_link(parent, child, cx_tree_node_layout(tree)); 1296 );
1171 tree->size++;
1172 }
1173 1297
1174 /** 1298 /**
1175 * Creates a new node and adds it to the tree. 1299 * Creates a new node and adds it to the tree.
1176 * 1300 *
1177 * With this function you can decide where exactly the new node shall be added. 1301 * With this function you can decide where exactly the new node shall be added.
1186 * @param parent the parent node of the new node 1310 * @param parent the parent node of the new node
1187 * @param data the data that will be submitted to the create function 1311 * @param data the data that will be submitted to the create function
1188 * @return zero when the new node was created, non-zero on allocation failure 1312 * @return zero when the new node was created, non-zero on allocation failure
1189 * @see cxTreeInsert() 1313 * @see cxTreeInsert()
1190 */ 1314 */
1191 __attribute__((__nonnull__)) 1315 cx_attr_nonnull
1192 int cxTreeAddChild( 1316 int cxTreeAddChild(
1193 CxTree *tree, 1317 CxTree *tree,
1194 void *parent, 1318 void *parent,
1195 const void *data 1319 const void *data
1196 ); 1320 );
1197 1321
1198 /** 1322 /**
1199 * A function that is invoked when a node needs to be re-linked to a new parent. 1323 * A function that is invoked when a node needs to be re-linked to a new parent.
1200 * 1324 *
1201 * When a node is re-linked, sometimes the contents need to be updated. 1325 * When a node is re-linked, sometimes the contents need to be updated.
1202 * This callback is invoked by #cxTreeRemove() so that those updates can be 1326 * This callback is invoked by #cxTreeRemoveNode() and #cxTreeDestroyNode()
1203 * applied when re-linking the children of the removed node. 1327 * so that those updates can be applied when re-linking the children of the
1328 * removed node.
1204 * 1329 *
1205 * @param node the affected node 1330 * @param node the affected node
1206 * @param old_parent the old parent of the node 1331 * @param old_parent the old parent of the node
1207 * @param new_parent the new parent of the node 1332 * @param new_parent the new parent of the node
1208 */ 1333 */
1334 cx_attr_nonnull
1209 typedef void (*cx_tree_relink_func)( 1335 typedef void (*cx_tree_relink_func)(
1210 void *node, 1336 void *node,
1211 const void *old_parent, 1337 const void *old_parent,
1212 const void *new_parent 1338 const void *new_parent
1213 ); 1339 );
1215 /** 1341 /**
1216 * Removes a node and re-links its children to its former parent. 1342 * Removes a node and re-links its children to its former parent.
1217 * 1343 *
1218 * If the node is not part of the tree, the behavior is undefined. 1344 * If the node is not part of the tree, the behavior is undefined.
1219 * 1345 *
1220 * \note The destructor function, if any, will \em not be invoked. That means 1346 * @note The destructor function, if any, will @em not be invoked. That means
1221 * you will need to free the removed node by yourself, eventually. 1347 * you will need to free the removed node by yourself, eventually.
1222 * 1348 *
1223 * @param tree the tree 1349 * @param tree the tree
1224 * @param node the node to remove (must not be the root node) 1350 * @param node the node to remove (must not be the root node)
1225 * @param relink_func optional callback to update the content of each re-linked 1351 * @param relink_func optional callback to update the content of each re-linked
1226 * node 1352 * node
1227 * @return zero on success, non-zero if \p node is the root node of the tree 1353 * @return zero on success, non-zero if @p node is the root node of the tree
1228 */ 1354 */
1229 __attribute__((__nonnull__(1,2))) 1355 cx_attr_nonnull_arg(1, 2)
1230 int cxTreeRemove( 1356 int cxTreeRemoveNode(
1231 CxTree *tree, 1357 CxTree *tree,
1232 void *node, 1358 void *node,
1233 cx_tree_relink_func relink_func 1359 cx_tree_relink_func relink_func
1234 ); 1360 );
1235 1361
1236 /** 1362 /**
1237 * Removes a node and it's subtree from the tree. 1363 * Removes a node and it's subtree from the tree.
1238 * 1364 *
1239 * If the node is not part of the tree, the behavior is undefined. 1365 * If the node is not part of the tree, the behavior is undefined.
1240 * 1366 *
1241 * \note The destructor function, if any, will \em not be invoked. That means 1367 * @note The destructor function, if any, will @em not be invoked. That means
1242 * you will need to free the removed subtree by yourself, eventually. 1368 * you will need to free the removed subtree by yourself, eventually.
1243 * 1369 *
1244 * @param tree the tree 1370 * @param tree the tree
1245 * @param node the node to remove 1371 * @param node the node to remove
1246 */ 1372 */
1247 __attribute__((__nonnull__)) 1373 cx_attr_nonnull
1248 void cxTreeRemoveSubtree(CxTree *tree, void *node); 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 );
1249 1400
1250 #ifdef __cplusplus 1401 #ifdef __cplusplus
1251 } // extern "C" 1402 } // extern "C"
1252 #endif 1403 #endif
1253 1404

mercurial