src/cx/tree.h

branch
feature/tree_add
changeset 871
e29c1f96646d
parent 867
471c714d5b6f
equal deleted inserted replaced
870:af0092d8789a 871:e29c1f96646d
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 );
411 ); 470 );
412 471
413 /** 472 /**
414 * Describes a function that creates a tree node from the specified data. 473 * Describes a function that creates a tree node from the specified data.
415 * The first argument points to the data the node shall contain and 474 * The first argument points to the data the node shall contain and
416 * the second, optional, argument points to an existing node that already 475 * the second argument may be used for additional data (e.g. an allocator).
417 * contains the data.
418 * The third argument may be used for additional data (e.g. an allocator).
419 * Functions of this type shall either return a new pointer to a newly 476 * Functions of this type shall either return a new pointer to a newly
420 * created node, a pointer to the existing node, or \c NULL when allocation 477 * created node or \c NULL when allocation fails.
421 * fails.
422 * Returning a pointer to the existing node means, that the function decides
423 * not to create a new node for the data and that the caller shall continue to
424 * use the existing node.
425 * 478 *
426 * \note the function may leave the node pointers in the struct uninitialized. 479 * \note the function may leave the node pointers in the struct uninitialized.
427 * The caller is responsible to set them according to where the node will be 480 * The caller is responsible to set them according to the intended use case.
428 * added to the tree. 481 */
429 */ 482 typedef void *(*cx_tree_node_create_func)(void const *, void *);
430 typedef void *(*cx_tree_node_create_func)(void const *, void const *, void *);
431 483
432 /** 484 /**
433 * The local search depth for a new subtree when adding multiple elements. 485 * The local search depth for a new subtree when adding multiple elements.
434 * The default value is 3. 486 * The default value is 3.
435 * This variable is used by #cx_tree_add_array() and #cx_tree_add_iter() to 487 * This variable is used by #cx_tree_add_array() and #cx_tree_add_iter() to
438 extern unsigned int cx_tree_add_look_around_depth; 490 extern unsigned int cx_tree_add_look_around_depth;
439 491
440 /** 492 /**
441 * Adds multiple elements efficiently to a tree. 493 * Adds multiple elements efficiently to a tree.
442 * 494 *
443 * This function returns the number of elements successfully obtained from the
444 * iterator, which is not necessarily the number of new nodes created (depending
445 * on the implementation of \p cfunc).
446 *
447 * Once an element cannot be added to the tree, this function returns, leaving 495 * Once an element cannot be added to the tree, this function returns, leaving
448 * the iterator in a valid state pointing to the element that could not be 496 * the iterator in a valid state pointing to the element that could not be
449 * added. 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.
450 * 503 *
451 * The advantage of this function compared to multiple invocations of 504 * The advantage of this function compared to multiple invocations of
452 * #cx_tree_add() is that the search for the insert locations is not always 505 * #cx_tree_add() is that the search for the insert locations is not always
453 * started from the root node. 506 * started from the root node.
454 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes 507 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes
460 * 513 *
461 * @param iter a pointer to an arbitrary iterator 514 * @param iter a pointer to an arbitrary iterator
462 * @param sfunc a search function 515 * @param sfunc a search function
463 * @param cfunc a node creation function 516 * @param cfunc a node creation function
464 * @param cdata optional additional data 517 * @param cdata optional additional data
465 * @param root the location where a pointer to the root node is stored 518 * @param root the root node of the tree
519 * @param failed location where the pointer to a failed node shall be stored
466 * @param loc_parent offset in the node struct for the parent pointer 520 * @param loc_parent offset in the node struct for the parent pointer
467 * @param loc_children offset in the node struct for the children linked list 521 * @param loc_children offset in the node struct for the children linked list
468 * @param loc_last_child optional offset in the node struct for the pointer to 522 * @param loc_last_child optional offset in the node struct for the pointer to
469 * the last child in the linked list (negative if there is no such pointer) 523 * the last child in the linked list (negative if there is no such pointer)
470 * @param loc_prev offset in the node struct for the prev pointer 524 * @param loc_prev offset in the node struct for the prev pointer
471 * @param loc_next offset in the node struct for the next pointer 525 * @param loc_next offset in the node struct for the next pointer
472 * @return the number of elements obtained from the iterator 526 * @return the number of nodes created and added
473 * @see cx_tree_add() 527 * @see cx_tree_add()
474 */ 528 */
475 __attribute__((__nonnull__(1, 2, 3, 5))) 529 __attribute__((__nonnull__(1, 2, 3, 5, 6)))
476 size_t cx_tree_add_iter( 530 size_t cx_tree_add_iter(
477 struct cx_iterator_base_s *iter, 531 struct cx_iterator_base_s *iter,
478 cx_tree_search_func sfunc, 532 cx_tree_search_func sfunc,
479 cx_tree_node_create_func cfunc, 533 cx_tree_node_create_func cfunc,
480 void *cdata, 534 void *cdata,
481 void **root, 535 void **failed,
536 void *root,
482 ptrdiff_t loc_parent, 537 ptrdiff_t loc_parent,
483 ptrdiff_t loc_children, 538 ptrdiff_t loc_children,
484 ptrdiff_t loc_last_child, 539 ptrdiff_t loc_last_child,
485 ptrdiff_t loc_prev, 540 ptrdiff_t loc_prev,
486 ptrdiff_t loc_next 541 ptrdiff_t loc_next
487 ); 542 );
488 543
489 /** 544 /**
490 * Adds multiple elements efficiently to a tree. 545 * Adds multiple elements efficiently to a tree.
491 * 546 *
492 * This function returns the number of elements successfully processed which 547 * Once an element cannot be added to the tree, this function returns, storing
493 * is not necessarily the number of new nodes created (depending on the 548 * the pointer of the created node to \p failed.
494 * implementation of \p cfunc). 549 * The integer returned by this function denotes the number of elements from
495 * 550 * the \p src array that have been successfully processed.
496 * Once an element cannot be added to the tree, this function returns. 551 * When all elements could be processed, a \c NULL pointer will be written to
497 * That means, the integer \c n returned by this function means, that the first 552 * \p failed.
498 * \c n elements of \p src will be definitely in the tree.
499 * 553 *
500 * The advantage of this function compared to multiple invocations of 554 * The advantage of this function compared to multiple invocations of
501 * #cx_tree_add() is that the search for the insert locations is not always 555 * #cx_tree_add() is that the search for the insert locations is not always
502 * started from the root node. 556 * started from the root node.
503 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes 557 * Instead, the function checks #cx_tree_add_look_around_depth many parent nodes
511 * @param num the number of elements in the \p src array 565 * @param num the number of elements in the \p src array
512 * @param elem_size the size of each element in the \p src array 566 * @param elem_size the size of each element in the \p src array
513 * @param sfunc a search function 567 * @param sfunc a search function
514 * @param cfunc a node creation function 568 * @param cfunc a node creation function
515 * @param cdata optional additional data 569 * @param cdata optional additional data
516 * @param root the location where a pointer to the root node is stored 570 * @param failed location where the pointer to a failed node shall be stored
571 * @param root the root node of the tree
517 * @param loc_parent offset in the node struct for the parent pointer 572 * @param loc_parent offset in the node struct for the parent pointer
518 * @param loc_children offset in the node struct for the children linked list 573 * @param loc_children offset in the node struct for the children linked list
519 * @param loc_last_child optional offset in the node struct for the pointer to 574 * @param loc_last_child optional offset in the node struct for the pointer to
520 * the last child in the linked list (negative if there is no such pointer) 575 * the last child in the linked list (negative if there is no such pointer)
521 * @param loc_prev offset in the node struct for the prev pointer 576 * @param loc_prev offset in the node struct for the prev pointer
522 * @param loc_next offset in the node struct for the next pointer 577 * @param loc_next offset in the node struct for the next pointer
523 * @return the number of array elements successfully processed 578 * @return the number of array elements successfully processed
524 * @see cx_tree_add() 579 * @see cx_tree_add()
525 */ 580 */
526 __attribute__((__nonnull__(1, 4, 5, 7))) 581 __attribute__((__nonnull__(1, 4, 5, 7, 8)))
527 size_t cx_tree_add_array( 582 size_t cx_tree_add_array(
528 void const *src, 583 void const *src,
529 size_t num, 584 size_t num,
530 size_t elem_size, 585 size_t elem_size,
531 cx_tree_search_func sfunc, 586 cx_tree_search_func sfunc,
532 cx_tree_node_create_func cfunc, 587 cx_tree_node_create_func cfunc,
533 void *cdata, 588 void *cdata,
534 void **root, 589 void **failed,
590 void *root,
535 ptrdiff_t loc_parent, 591 ptrdiff_t loc_parent,
536 ptrdiff_t loc_children, 592 ptrdiff_t loc_children,
537 ptrdiff_t loc_last_child, 593 ptrdiff_t loc_last_child,
538 ptrdiff_t loc_prev, 594 ptrdiff_t loc_prev,
539 ptrdiff_t loc_next 595 ptrdiff_t loc_next
543 * Adds data to a tree. 599 * Adds data to a tree.
544 * 600 *
545 * An adequate location where to add the new tree node is searched with the 601 * An adequate location where to add the new tree node is searched with the
546 * specified \p sfunc. 602 * specified \p sfunc.
547 * 603 *
548 * When a location is found, the \p cfunc will be invoked with \p cdata and, 604 * When a location is found, the \p cfunc will be invoked with \p cdata.
549 * in case \p sfunc returned a direct match, the already found node. 605 *
550 * 606 * The node returned by \p cfunc will be linked into the tree.
551 * If \p cfunc returns a new node pointer, it will be linked into the tree.
552 * When \p sfunc returned a positive integer, the new node will be linked as a 607 * When \p sfunc returned a positive integer, the new node will be linked as a
553 * child. When \p sfunc returned zero and the found node has a parent, the new 608 * child. The other children (now siblings of the new node) are then checked
554 * node will be added as sibling - otherwise, the new node will be the new root. 609 * with \p sfunc, whether they could be children of the new node and re-linked
555 * When \p sfunc returned a negative value, the new node will always be the 610 * accordingly.
556 * new root. 611 *
557 * 612 * When \p sfunc returned zero and the found node has a parent, the new
558 * If \p cfunc returns an existing node found by \p sfunc, this function just 613 * node will be added as sibling - otherwise, the new node will be added
559 * returns the found node without modifying the tree. 614 * as a child.
560 * 615 *
561 * This function may return \c NULL when \p cfunc tries to allocate a new node 616 * When \p sfunc returned a negative value, the new node will not be added to
562 * but fails to do so. 617 * the tree and this function returns a non-zero value.
563 * 618 * The caller should check if \p cnode contains a node pointer and deal with the
564 * The \p root argument shall point to a location where the pointer to the root 619 * node that could not be added.
565 * node is stored. The pointer to the root node may be \c NULL in which case 620 *
566 * this function will instantly create a new node and write the location to 621 * This function also returns a non-zero value when \p cfunc tries to allocate
567 * \p root. 622 * a new node but fails to do so. In that case, the pointer stored to \p cnode
623 * will be \c NULL.
568 * 624 *
569 * Multiple elements can be added more efficiently with 625 * Multiple elements can be added more efficiently with
570 * #cx_tree_add_array() or #cx_tree_add_iter(). 626 * #cx_tree_add_array() or #cx_tree_add_iter().
571 * 627 *
572 * @param src a pointer to the data 628 * @param src a pointer to the data
573 * @param sfunc a search function 629 * @param sfunc a search function
574 * @param cfunc a node creation function 630 * @param cfunc a node creation function
575 * @param cdata optional additional data 631 * @param cdata optional additional data
576 * @param root the location where a pointer to the root node is stored 632 * @param cnode the location where a pointer to the new node is stored
633 * @param root the root node of the tree
577 * @param loc_parent offset in the node struct for the parent pointer 634 * @param loc_parent offset in the node struct for the parent pointer
578 * @param loc_children offset in the node struct for the children linked list 635 * @param loc_children offset in the node struct for the children linked list
579 * @param loc_last_child optional offset in the node struct for the pointer to 636 * @param loc_last_child optional offset in the node struct for the pointer to
580 * the last child in the linked list (negative if there is no such pointer) 637 * the last child in the linked list (negative if there is no such pointer)
581 * @param loc_prev offset in the node struct for the prev pointer 638 * @param loc_prev offset in the node struct for the prev pointer
582 * @param loc_next offset in the node struct for the next pointer 639 * @param loc_next offset in the node struct for the next pointer
583 * @return a pointer to the new node, to an existing node, or \c NULL 640 * @return zero when a new node was created and added to the tree,
584 */ 641 * non-zero otherwise
585 __attribute__((__nonnull__(1, 2, 3, 5))) 642 */
586 void *cx_tree_add( 643 __attribute__((__nonnull__(1, 2, 3, 5, 6)))
644 int cx_tree_add(
587 void const *src, 645 void const *src,
588 cx_tree_search_func sfunc, 646 cx_tree_search_func sfunc,
589 cx_tree_node_create_func cfunc, 647 cx_tree_node_create_func cfunc,
590 void *cdata, 648 void *cdata,
591 void **root, 649 void **cnode,
650 void *root,
592 ptrdiff_t loc_parent, 651 ptrdiff_t loc_parent,
593 ptrdiff_t loc_children, 652 ptrdiff_t loc_children,
594 ptrdiff_t loc_last_child, 653 ptrdiff_t loc_last_child,
595 ptrdiff_t loc_prev, 654 ptrdiff_t loc_prev,
596 ptrdiff_t loc_next 655 ptrdiff_t loc_next

mercurial