src/cx/tree.h

Fri, 16 Feb 2024 20:23:48 +0100

author
Mike Becker <universe@uap-core.de>
date
Fri, 16 Feb 2024 20:23:48 +0100
changeset 827
13b40a598d16
parent 826
21840975d541
child 828
88fa3381206d
permissions
-rw-r--r--

first draft of a tree iterator

see issue #371

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2024 Mike Becker, Olaf Wintermann All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  */
    28 /**
    29  * \file tree.h
    30  * \brief Interface for tree implementations.
    31  * \author Mike Becker
    32  * \author Olaf Wintermann
    33  * \copyright 2-Clause BSD License
    34  */
    36 #ifndef UCX_TREE_H
    37 #define UCX_TREE_H
    39 #include "common.h"
    41 #include "iterator.h"
    43 #ifdef __cplusplus
    44 extern "C" {
    45 #endif
    47 /**
    48  * When entering a node.
    49  */
    50 #define CX_TREE_ITERATOR_ENTER      0x1
    51 /**
    52  * When advancing to the next child.
    53  */
    54 #define CX_TREE_ITERATOR_NEXT_CHILD 0x2
    55 /**
    56  * When exiting the node.
    57  */
    58 #define CX_TREE_ITERATOR_EXIT       0x4
    60 /**
    61  * Tree iterator.
    62  *
    63  * This iterator is not position-aware in a strict sense, as it does not assume a particular order of elements in the
    64  * tree. However, the iterator keeps track of the number of nodes it has passed in a counter variable.
    65  * Each node, regardless of the number of passes, is counted only once.
    66  *
    67  * @note Objects that are pointed to by an iterator are mutable through that iterator. However, if the
    68  * iterator is based on a collection and the underlying collection is mutated by other means than this iterator
    69  * (e.g. elements added or removed), the iterator becomes invalid (regardless of what cxIteratorValid() returns)
    70  * and MUST be re-obtained from the collection.
    71  *
    72  * @see CxIterator
    73  */
    74 typedef struct cx_tree_iterator_s {
    75     /**
    76      * The base properties of this iterator.
    77      */
    78     struct cx_iterator_base_s base;
    79     /**
    80      * The passes that are requested by this iterator.
    81      * A combination of the flags #CX_TREE_ITERATOR_ENTER, #CX_TREE_ITERATOR_NEXT_CHILD, #CX_TREE_ITERATOR_EXIT.
    82      *
    83      * Changing the value after beginning the iteration is unspecified.
    84      */
    85     uint8_t requested_passes;
    86     /**
    87      * The current pass.
    88      *
    89      * @see CX_TREE_ITERATOR_ENTER
    90      * @see CX_TREE_ITERATOR_NEXT_CHILD
    91      * @see CX_TREE_ITERATOR_EXIT
    92      */
    93     uint8_t current_pass;
    94     /**
    95      * Offset in the node struct for the children linked list.
    96      */
    97     off_t loc_children;
    98     /**
    99      * Offset in the node struct for the next pointer.
   100      */
   101     off_t loc_next;
   102     /**
   103      * The total number of distinct nodes that have been passed so far.
   104      */
   105     size_t counter;
   106     /**
   107      * The currently observed node.
   108      *
   109      * This is the same what cxIteratorCurrent() would return.
   110      */
   111     void *node;
   112     /**
   113      * The node where we came from.
   114      *
   115      * - When entering the root node, this is \c NULL.
   116      * - When entering another node, this is the node's parent.
   117      * - When advancing to the next child, this is the previous child.
   118      */
   119     void *source;
   120     /**
   121      * Internal stack.
   122      * Will be automatically freed once the iterator becomes invalid.
   123      *
   124      * If you want to discard the iterator before, you need to manually
   125      * call cxTreeIteratorDispose().
   126      */
   127     void **stack;
   128 } CxTreeIterator;
   130 /**
   131  * Releases internal memory of the given tree iterator.
   132  * @param iter the iterator
   133  */
   134 static inline void cxTreeIteratorDispose(CxTreeIterator *iter) {
   135     free(iter->stack);
   136 }
   138 /**
   139  * Links a node to a (new) parent.
   140  *
   141  * If the node has already a parent, it is unlinked, first.
   142  * If the parent has children already, the node is prepended to the list
   143  * of all currently existing children.
   144  *
   145  * @param parent the parent node
   146  * @param node the node that shall be linked
   147  * @param loc_parent offset in the node struct for the parent pointer
   148  * @param loc_children offset in the node struct for the children linked list
   149  * @param loc_prev offset in the node struct for the prev pointer
   150  * @param loc_next offset in the node struct for the next pointer
   151  * @see cx_tree_unlink()
   152  */
   153 __attribute__((__nonnull__))
   154 void cx_tree_link(
   155         void * restrict parent,
   156         void * restrict node,
   157         ptrdiff_t loc_parent,
   158         ptrdiff_t loc_children,
   159         ptrdiff_t loc_prev,
   160         ptrdiff_t loc_next
   161 );
   163 /**
   164  * Unlinks a node from its parent.
   165  *
   166  * If the node has no parent, this function does nothing.
   167  *
   168  * @param node the node that shall be unlinked from its parent
   169  * @param loc_parent offset in the node struct for the parent pointer
   170  * @param loc_children offset in the node struct for the children linked list
   171  * @param loc_prev offset in the node struct for the prev pointer
   172  * @param loc_next offset in the node struct for the next pointer
   173  * @see cx_tree_link()
   174  */
   175 __attribute__((__nonnull__))
   176 void cx_tree_unlink(
   177         void *node,
   178         ptrdiff_t loc_parent,
   179         ptrdiff_t loc_children,
   180         ptrdiff_t loc_prev,
   181         ptrdiff_t loc_next
   182 );
   184 /**
   185  * Function pointer for a search function.
   186  *
   187  * A function of this kind shall check if the specified \p node
   188  * contains the given \p data or if one of the children might contain
   189  * the data.
   190  *
   191  * The function should use the returned integer to indicate how close the
   192  * match is, where a negative number means that it does not match at all.
   193  *
   194  * For example if a tree stores file path information, a node that is
   195  * describing a parent directory of a filename that is searched, shall
   196  * return a positive number to indicate that a child node might contain the
   197  * searched item. On the other hand, if the node denotes a path that is not a
   198  * prefix of the searched filename, the function would return -1 to indicate
   199  * that * the search does not need to be continued in that branch.
   200  *
   201  * @param node the node that is currently investigated
   202  * @param data the data that is searched for
   203  *
   204  * @return 0 if the node contains the data,
   205  * positive if one of the children might contain the data,
   206  * negative if neither the node, nor the children contains the data
   207  */
   208 typedef int (*cx_tree_search_func)(void const *node, void const* data);
   211 /**
   212  * Searches for data in a tree.
   213  *
   214  * When the data cannot be found exactly, the search function might return a
   215  * closest result which might be a good starting point for adding a new node
   216  * to the tree.
   217  *
   218  * Depending on the tree structure it is not necessarily guaranteed that the
   219  * "closest" match is uniquely defined. This function will search for a node
   220  * with the best match according to the \p sfunc (meaning: the return value of
   221  * \p sfunc which is closest to zero). If that is also ambiguous, an arbitrary
   222  * node matching the criteria is returned.
   223  *
   224  * @param root the root node
   225  * @param data the data to search for
   226  * @param sfunc the search function
   227  * @param result where the result shall be stored
   228  * @param loc_children offset in the node struct for the children linked list
   229  * @param loc_next offset in the node struct for the next pointer
   230  * @return zero if the node was found exactly, positive if a node was found that
   231  * could contain the node (but doesn't right now), negative if the tree does not
   232  * contain any node that might be related to the searched data
   233  */
   234 __attribute__((__nonnull__))
   235 int cx_tree_search(
   236         void const *root,
   237         void const *data,
   238         cx_tree_search_func sfunc,
   239         void **result,
   240         ptrdiff_t loc_children,
   241         ptrdiff_t loc_next
   242 );
   244 #ifdef __cplusplus
   245 } // extern "C"
   246 #endif
   248 #endif //UCX_TREE_H

mercurial