src/tree.c

changeset 838
1ce90ab4fab9
parent 836
2672a2f79484
child 840
4f02995ce44e
     1.1 --- a/src/tree.c	Mon Feb 19 22:12:13 2024 +0100
     1.2 +++ b/src/tree.c	Wed Feb 21 18:32:38 2024 +0100
     1.3 @@ -182,40 +182,58 @@
     1.4      off_t const loc_children = iter->loc_children;
     1.5  
     1.6      // TODO: support mutating iterator
     1.7 -    // TODO: support visit_on_exit
     1.8  
     1.9 -    void *children = tree_children(iter->node);
    1.10 +    void *children;
    1.11 +
    1.12 +    // check if we are currently exiting or entering nodes
    1.13 +    if (iter->exiting) {
    1.14 +        children = NULL;
    1.15 +    } else {
    1.16 +        children = tree_children(iter->node);
    1.17 +    }
    1.18 +
    1.19      if (children == NULL) {
    1.20          // search for the next node
    1.21 -        void *current = iter->node;
    1.22 -        do {
    1.23 -            // check if there is a sibling
    1.24 -            void *next = tree_next(current);
    1.25 -            if (next == NULL) {
    1.26 -                // no sibling, check again for parent node
    1.27 -                --iter->depth;
    1.28 -                if (iter->depth == 0) {
    1.29 +        void *next;
    1.30 +        cx_tree_iter_search_next:
    1.31 +        // check if there is a sibling
    1.32 +        next = tree_next(iter->node);
    1.33 +        if (next == NULL) {
    1.34 +            // no sibling, we are done with this node and exit
    1.35 +            if (iter->visit_on_exit && !iter->exiting) {
    1.36 +                // iter is supposed to visit the node again
    1.37 +                iter->exiting = true;
    1.38 +            } else {
    1.39 +                iter->exiting = false;
    1.40 +                if (iter->depth == 1) {
    1.41                      // there is no parent - we have iterated the entire tree
    1.42                      // invalidate the iterator and free the node stack
    1.43                      iter->node = NULL;
    1.44 -                    current = NULL;
    1.45 -                    iter->stack_capacity = 0;
    1.46 +                    iter->stack_capacity = iter->depth = 0;
    1.47                      free(iter->stack);
    1.48                      iter->stack = NULL;
    1.49                  } else {
    1.50                      // the parent node can be obtained from the top of stack
    1.51                      // this way we can avoid the loc_parent in the iterator
    1.52 -                    current = iter->stack[iter->depth - 1];
    1.53 +                    iter->depth--;
    1.54 +                    iter->node = iter->stack[iter->depth - 1];
    1.55 +                    // retry with the parent node to find a sibling
    1.56 +                    goto cx_tree_iter_search_next;
    1.57                  }
    1.58 +            }
    1.59 +        } else {
    1.60 +            if (iter->visit_on_exit && !iter->exiting) {
    1.61 +                // iter is supposed to visit the node again
    1.62 +                iter->exiting = true;
    1.63              } else {
    1.64 -                // move to the sibling and break the loop
    1.65 -                current = NULL;
    1.66 +                iter->exiting = false;
    1.67 +                // move to the sibling
    1.68                  iter->counter++;
    1.69                  iter->node = next;
    1.70                  // new top of stack is the sibling
    1.71                  iter->stack[iter->depth - 1] = next;
    1.72              }
    1.73 -        } while (current != NULL);
    1.74 +        }
    1.75      } else {
    1.76          // node has children, push the first child onto the stack and enter it
    1.77          cx_array_simple_add(iter->stack, children);

mercurial