| 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 |