319 * |
319 * |
320 * @return 0 if the node contains the data, |
320 * @return 0 if the node contains the data, |
321 * positive if one of the children might contain the data, |
321 * positive if one of the children might contain the data, |
322 * negative if neither the node, nor the children contains the data |
322 * negative if neither the node, nor the children contains the data |
323 */ |
323 */ |
324 typedef int (*cx_tree_search_func)(void const *node, void const *data); |
324 typedef int (*cx_tree_search_data_func)(void const *node, void const *data); |
325 |
325 |
|
326 |
|
327 /** |
|
328 * Function pointer for a search function. |
|
329 * |
|
330 * 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 |
|
332 * contain the data. |
|
333 * |
|
334 * 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. |
|
336 * |
|
337 * 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 |
|
339 * 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 |
|
341 * prefix of the searched filename, the function would return -1 to indicate |
|
342 * that the search does not need to be continued in that branch. |
|
343 * |
|
344 * @param node the node that is currently investigated |
|
345 * @param new_node a new node with the information which is searched |
|
346 * |
|
347 * @return 0 if \p node contains the same data as \p new_node, |
|
348 * positive if one of the children might contain the data, |
|
349 * negative if neither the node, nor the children contains the data |
|
350 */ |
|
351 typedef int (*cx_tree_search_func)(void const *node, void const *new_node); |
326 |
352 |
327 /** |
353 /** |
328 * Searches for data in a tree. |
354 * Searches for data in a tree. |
329 * |
355 * |
330 * When the data cannot be found exactly, the search function might return a |
356 * When the data cannot be found exactly, the search function might return a |
331 * closest result which might be a good starting point for adding a new node |
357 * closest result which might be a good starting point for adding a new node |
332 * to the tree. |
358 * to the tree (see also #cx_tree_add()). |
333 * |
359 * |
334 * Depending on the tree structure it is not necessarily guaranteed that the |
360 * Depending on the tree structure it is not necessarily guaranteed that the |
335 * "closest" match is uniquely defined. This function will search for a node |
361 * "closest" match is uniquely defined. This function will search for a node |
336 * with the best match according to the \p sfunc (meaning: the return value of |
362 * with the best match according to the \p sfunc (meaning: the return value of |
337 * \p sfunc which is closest to zero). If that is also ambiguous, an arbitrary |
363 * \p sfunc which is closest to zero). If that is also ambiguous, an arbitrary |
346 * @return zero if the node was found exactly, positive if a node was found that |
372 * @return zero if the node was found exactly, positive if a node was found that |
347 * could contain the node (but doesn't right now), negative if the tree does not |
373 * could contain the node (but doesn't right now), negative if the tree does not |
348 * contain any node that might be related to the searched data |
374 * contain any node that might be related to the searched data |
349 */ |
375 */ |
350 __attribute__((__nonnull__)) |
376 __attribute__((__nonnull__)) |
|
377 int cx_tree_search_data( |
|
378 void const *root, |
|
379 void const *data, |
|
380 cx_tree_search_data_func sfunc, |
|
381 void **result, |
|
382 ptrdiff_t loc_children, |
|
383 ptrdiff_t loc_next |
|
384 ); |
|
385 |
|
386 /** |
|
387 * Searches for a node in a tree. |
|
388 * |
|
389 * When no node with the same data can be found, the search function might |
|
390 * 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()). |
|
392 * |
|
393 * 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 |
|
395 * 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 |
|
397 * node matching the criteria is returned. |
|
398 * |
|
399 * @param root the root node |
|
400 * @param node the node to search for |
|
401 * @param sfunc the search function |
|
402 * @param result where the result shall be stored |
|
403 * @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 |
|
405 * @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 |
|
407 * contain any node that might be related to the searched data |
|
408 */ |
|
409 __attribute__((__nonnull__)) |
351 int cx_tree_search( |
410 int cx_tree_search( |
352 void const *root, |
411 void const *root, |
353 void const *data, |
412 void const *node, |
354 cx_tree_search_func sfunc, |
413 cx_tree_search_func sfunc, |
355 void **result, |
414 void **result, |
356 ptrdiff_t loc_children, |
415 ptrdiff_t loc_children, |
357 ptrdiff_t loc_next |
416 ptrdiff_t loc_next |
358 ); |
417 ); |
408 void *root, |
467 void *root, |
409 ptrdiff_t loc_children, |
468 ptrdiff_t loc_children, |
410 ptrdiff_t loc_next |
469 ptrdiff_t loc_next |
411 ); |
470 ); |
412 |
471 |
|
472 /** |
|
473 * Describes a function that creates a tree node from the specified data. |
|
474 * The first argument points to the data the node shall contain and |
|
475 * the second argument may be used for additional data (e.g. an allocator). |
|
476 * Functions of this type shall either return a new pointer to a newly |
|
477 * created node or \c NULL when allocation fails. |
|
478 * |
|
479 * \note the function may leave the node pointers in the struct uninitialized. |
|
480 * The caller is responsible to set them according to the intended use case. |
|
481 */ |
|
482 typedef void *(*cx_tree_node_create_func)(void const *, void *); |
|
483 |
|
484 /** |
|
485 * The local search depth for a new subtree when adding multiple elements. |
|
486 * The default value is 3. |
|
487 * This variable is used by #cx_tree_add_array() and #cx_tree_add_iter() to |
|
488 * implement optimized insertion of multiple elements into a tree. |
|
489 */ |
|
490 extern unsigned int cx_tree_add_look_around_depth; |
|
491 |
|
492 /** |
|
493 * Adds multiple elements efficiently to a tree. |
|
494 * |
|
495 * Once an element cannot be added to the tree, this function returns, leaving |
|
496 * the iterator in a valid state pointing to the element that could not be |
|
497 * added. |
|
498 * Also, the pointer of the created node will be stored to \p failed. |
|
499 * The integer returned by this function denotes the number of elements obtained |
|
500 * from the \p iter that have been successfully processed. |
|
501 * When all elements could be processed, a \c NULL pointer will be written to |
|
502 * \p failed. |
|
503 * |
|
504 * The advantage of this function compared to multiple invocations of |
|
505 * #cx_tree_add() is that the search for the insert locations is not always |
|
506 * started from the root node. |
|
507 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes |
|
508 * of the current insert location before starting from the root node again. |
|
509 * When the variable is set to zero, only the last found location is checked |
|
510 * again. |
|
511 * |
|
512 * Refer to the documentation of #cx_tree_add() for more details. |
|
513 * |
|
514 * @param iter a pointer to an arbitrary iterator |
|
515 * @param sfunc a search function |
|
516 * @param cfunc a node creation function |
|
517 * @param cdata optional additional data |
|
518 * @param root the root node of the tree |
|
519 * @param failed location where the pointer to a failed node shall be stored |
|
520 * @param loc_parent offset in the node struct for the parent pointer |
|
521 * @param loc_children offset in the node struct for the children linked list |
|
522 * @param loc_last_child optional offset in the node struct for the pointer to |
|
523 * the last child in the linked list (negative if there is no such pointer) |
|
524 * @param loc_prev offset in the node struct for the prev pointer |
|
525 * @param loc_next offset in the node struct for the next pointer |
|
526 * @return the number of nodes created and added |
|
527 * @see cx_tree_add() |
|
528 */ |
|
529 __attribute__((__nonnull__(1, 2, 3, 5, 6))) |
|
530 size_t cx_tree_add_iter( |
|
531 struct cx_iterator_base_s *iter, |
|
532 cx_tree_search_func sfunc, |
|
533 cx_tree_node_create_func cfunc, |
|
534 void *cdata, |
|
535 void **failed, |
|
536 void *root, |
|
537 ptrdiff_t loc_parent, |
|
538 ptrdiff_t loc_children, |
|
539 ptrdiff_t loc_last_child, |
|
540 ptrdiff_t loc_prev, |
|
541 ptrdiff_t loc_next |
|
542 ); |
|
543 |
|
544 /** |
|
545 * Adds multiple elements efficiently to a tree. |
|
546 * |
|
547 * Once an element cannot be added to the tree, this function returns, storing |
|
548 * the pointer of the created node to \p failed. |
|
549 * The integer returned by this function denotes the number of elements from |
|
550 * the \p src array that have been successfully processed. |
|
551 * When all elements could be processed, a \c NULL pointer will be written to |
|
552 * \p failed. |
|
553 * |
|
554 * 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 |
|
556 * started from the root node. |
|
557 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes |
|
558 * of the current insert location before starting from the root node again. |
|
559 * When the variable is set to zero, only the last found location is checked |
|
560 * again. |
|
561 * |
|
562 * Refer to the documentation of #cx_tree_add() for more details. |
|
563 * |
|
564 * @param src a pointer to the source data array |
|
565 * @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 |
|
567 * @param sfunc a search function |
|
568 * @param cfunc a node creation function |
|
569 * @param cdata optional additional data |
|
570 * @param failed location where the pointer to a failed node shall be stored |
|
571 * @param root the root node of the tree |
|
572 * @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 |
|
574 * @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) |
|
576 * @param loc_prev offset in the node struct for the prev pointer |
|
577 * @param loc_next offset in the node struct for the next pointer |
|
578 * @return the number of array elements successfully processed |
|
579 * @see cx_tree_add() |
|
580 */ |
|
581 __attribute__((__nonnull__(1, 4, 5, 7, 8))) |
|
582 size_t cx_tree_add_array( |
|
583 void const *src, |
|
584 size_t num, |
|
585 size_t elem_size, |
|
586 cx_tree_search_func sfunc, |
|
587 cx_tree_node_create_func cfunc, |
|
588 void *cdata, |
|
589 void **failed, |
|
590 void *root, |
|
591 ptrdiff_t loc_parent, |
|
592 ptrdiff_t loc_children, |
|
593 ptrdiff_t loc_last_child, |
|
594 ptrdiff_t loc_prev, |
|
595 ptrdiff_t loc_next |
|
596 ); |
|
597 |
|
598 /** |
|
599 * Adds data to a tree. |
|
600 * |
|
601 * An adequate location where to add the new tree node is searched with the |
|
602 * specified \p sfunc. |
|
603 * |
|
604 * When a location is found, the \p cfunc will be invoked with \p cdata. |
|
605 * |
|
606 * 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 |
|
608 * 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 |
|
610 * accordingly. |
|
611 * |
|
612 * 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 |
|
614 * as a child. |
|
615 * |
|
616 * 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. |
|
618 * The caller should check if \p cnode contains a node pointer and deal with the |
|
619 * node that could not be added. |
|
620 * |
|
621 * 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 |
|
623 * will be \c NULL. |
|
624 * |
|
625 * Multiple elements can be added more efficiently with |
|
626 * #cx_tree_add_array() or #cx_tree_add_iter(). |
|
627 * |
|
628 * @param src a pointer to the data |
|
629 * @param sfunc a search function |
|
630 * @param cfunc a node creation function |
|
631 * @param cdata optional additional data |
|
632 * @param cnode the location where a pointer to the new node is stored |
|
633 * @param root the root node of the tree |
|
634 * @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 |
|
636 * @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) |
|
638 * @param loc_prev offset in the node struct for the prev pointer |
|
639 * @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, |
|
641 * non-zero otherwise |
|
642 */ |
|
643 __attribute__((__nonnull__(1, 2, 3, 5, 6))) |
|
644 int cx_tree_add( |
|
645 void const *src, |
|
646 cx_tree_search_func sfunc, |
|
647 cx_tree_node_create_func cfunc, |
|
648 void *cdata, |
|
649 void **cnode, |
|
650 void *root, |
|
651 ptrdiff_t loc_parent, |
|
652 ptrdiff_t loc_children, |
|
653 ptrdiff_t loc_last_child, |
|
654 ptrdiff_t loc_prev, |
|
655 ptrdiff_t loc_next |
|
656 ); |
|
657 |
413 #ifdef __cplusplus |
658 #ifdef __cplusplus |
414 } // extern "C" |
659 } // extern "C" |
415 #endif |
660 #endif |
416 |
661 |
417 #endif //UCX_TREE_H |
662 #endif //UCX_TREE_H |