src/cx/tree.h

changeset 872
d607a184925a
parent 871
e29c1f96646d
child 890
54565fd74e74
equal deleted inserted replaced
862:387414a7afd8 872:d607a184925a
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

mercurial