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 |