commit complicated stuff before simplifying it

Sun, 18 Feb 2024 12:24:04 +0100

author
Mike Becker <universe@uap-core.de>
date
Sun, 18 Feb 2024 12:24:04 +0100
changeset 830
c4dae6fe6d5b
parent 829
7d4e31d295af
child 831
7970eac1c598

commit complicated stuff before simplifying it

relates to #371

src/cx/tree.h file | annotate | diff | comparison | revisions
src/tree.c file | annotate | diff | comparison | revisions
     1.1 --- a/src/cx/tree.h	Sat Feb 17 20:51:27 2024 +0100
     1.2 +++ b/src/cx/tree.h	Sun Feb 18 12:24:04 2024 +0100
     1.3 @@ -46,14 +46,23 @@
     1.4  
     1.5  /**
     1.6   * When entering a node.
     1.7 + *
     1.8 + * When this is the first sibling, source is the parent, otherwise it is the previous child.
     1.9   */
    1.10  #define CX_TREE_ITERATOR_ENTER      0x1
    1.11  /**
    1.12   * When advancing to the next child.
    1.13 + *
    1.14 + * The visited node is the next child and the source is the previous child.
    1.15 + * This pass is triggered after exiting the previous child and before entering the next child.
    1.16   */
    1.17  #define CX_TREE_ITERATOR_NEXT_CHILD 0x2
    1.18  /**
    1.19   * When exiting the node.
    1.20 + *
    1.21 + * The visited node is the node being exited and source is the previously entered node
    1.22 + * (usually the last child of the exited node, unless it has no children, in which case it is the node itself).
    1.23 + * When advancing to the next child in a list of siblings, the previous child is exited, first.
    1.24   */
    1.25  #define CX_TREE_ITERATOR_EXIT       0x4
    1.26  
    1.27 @@ -278,8 +287,8 @@
    1.28   * @see cxTreeIteratorDispose()
    1.29   */
    1.30  __attribute__((__nonnull__))
    1.31 -CxTreeIterator cx_tree_iterate(
    1.32 -        void const *root,
    1.33 +CxTreeIterator cx_tree_iterator(
    1.34 +        void *root,
    1.35          int passes,
    1.36          ptrdiff_t loc_children,
    1.37          ptrdiff_t loc_next
     2.1 --- a/src/tree.c	Sat Feb 17 20:51:27 2024 +0100
     2.2 +++ b/src/tree.c	Sun Feb 18 12:24:04 2024 +0100
     2.3 @@ -169,3 +169,111 @@
     2.4      free(work);
     2.5      return ret;
     2.6  }
     2.7 +
     2.8 +static bool cx_tree_iter_valid(void const *it) {
     2.9 +    struct cx_tree_iterator_s const *iter = it;
    2.10 +    return iter->node != NULL;
    2.11 +}
    2.12 +
    2.13 +static void *cx_tree_iter_current(void const *it) {
    2.14 +    struct cx_tree_iterator_s const *iter = it;
    2.15 +    return iter->node;
    2.16 +}
    2.17 +
    2.18 +static void cx_tree_iter_stack_add(
    2.19 +        struct cx_tree_iterator_s *iter,
    2.20 +        void *node
    2.21 +) {
    2.22 +    cx_array_add(&iter->stack, &iter->depth, &iter->stack_capacity,
    2.23 +        sizeof(void*), &node, cx_array_default_reallocator);
    2.24 +}
    2.25 +
    2.26 +static void cx_tree_iter_next(void *it) {
    2.27 +    struct cx_tree_iterator_s *iter = it;
    2.28 +    // TODO: support mutating iterator
    2.29 +
    2.30 +    // TODO: implement
    2.31 +}
    2.32 +
    2.33 +
    2.34 +CxTreeIterator cx_tree_iterator(
    2.35 +        void *root,
    2.36 +        int passes,
    2.37 +        ptrdiff_t loc_children,
    2.38 +        ptrdiff_t loc_next
    2.39 +) {
    2.40 +    CxTreeIterator iter;
    2.41 +    iter.loc_children = loc_children;
    2.42 +    iter.loc_next = loc_next;
    2.43 +    iter.requested_passes = passes;
    2.44 +
    2.45 +    // invalidate iterator immediately when passes is invalid
    2.46 +    if ((passes & (CX_TREE_ITERATOR_ENTER |
    2.47 +                   CX_TREE_ITERATOR_NEXT_CHILD |
    2.48 +                   CX_TREE_ITERATOR_EXIT)) == 0) {
    2.49 +        iter.stack = NULL;
    2.50 +        iter.node = NULL;
    2.51 +        return iter;
    2.52 +    }
    2.53 +
    2.54 +    // allocate stack
    2.55 +    iter.stack_capacity = 16;
    2.56 +    iter.stack = malloc(sizeof(void *) * 16);
    2.57 +    iter.depth = 0;
    2.58 +
    2.59 +    // determine start
    2.60 +    if ((passes & CX_TREE_ITERATOR_ENTER) == 0) {
    2.61 +        // we have to skip the first "entering" passes
    2.62 +        void *s = NULL;
    2.63 +        void *n = root;
    2.64 +        iter.counter = 0;
    2.65 +        do {
    2.66 +            iter.counter++;
    2.67 +            iter.source = s;
    2.68 +            iter.node = n;
    2.69 +            cx_tree_iter_stack_add(&iter, n);
    2.70 +            s = n;
    2.71 +            n = tree_children(n);
    2.72 +        } while (n != NULL);
    2.73 +        // found a leaf node s (might be root itself if it has no children)
    2.74 +
    2.75 +        // check if there is a sibling
    2.76 +        n = tree_next(s);
    2.77 +
    2.78 +        if (n == NULL) {
    2.79 +            // no sibling found, exit back to parent node
    2.80 +            // TODO: implement
    2.81 +        } else {
    2.82 +            // there is a sibling
    2.83 +            if ((passes & CX_TREE_ITERATOR_EXIT) == 0) {
    2.84 +                // no exit requested, conclude that only next_child is requested
    2.85 +                iter.source = s;
    2.86 +                iter.node = n;
    2.87 +                iter.counter++;
    2.88 +                iter.current_pass = CX_TREE_ITERATOR_NEXT_CHILD;
    2.89 +            } else {
    2.90 +                // exit requested, so we have found our first pass
    2.91 +                // iter.node and iter.source are still correct
    2.92 +                iter.current_pass = CX_TREE_ITERATOR_EXIT;
    2.93 +            }
    2.94 +        }
    2.95 +    } else {
    2.96 +        // enter passes are requested, we can start by entering the root node
    2.97 +        iter.source = NULL;
    2.98 +        iter.node = root;
    2.99 +        iter.current_pass = CX_TREE_ITERATOR_ENTER;
   2.100 +        iter.counter = 1;
   2.101 +        iter.depth = 1;
   2.102 +        iter.stack[0] = root;
   2.103 +    }
   2.104 +
   2.105 +    // assign base iterator functions
   2.106 +    iter.base.mutating = false;
   2.107 +    iter.base.remove = false;
   2.108 +    iter.base.current_impl = NULL;
   2.109 +    iter.base.valid = cx_tree_iter_valid;
   2.110 +    iter.base.next = cx_tree_iter_next;
   2.111 +    iter.base.current = cx_tree_iter_current;
   2.112 +
   2.113 +    return iter;
   2.114 +}

mercurial