src/tree.c

changeset 845
2615317311b7
parent 840
4f02995ce44e
child 848
6456036bbb37
     1.1 --- a/src/tree.c	Thu Mar 14 22:07:19 2024 +0100
     1.2 +++ b/src/tree.c	Wed Mar 20 23:31:41 2024 +0100
     1.3 @@ -178,10 +178,8 @@
     1.4  
     1.5  static void cx_tree_iter_next(void *it) {
     1.6      struct cx_tree_iterator_s *iter = it;
     1.7 -    off_t const loc_next = iter->loc_next;
     1.8 -    off_t const loc_children = iter->loc_children;
     1.9 -
    1.10 -    // TODO: support mutating iterator
    1.11 +    ptrdiff_t const loc_next = iter->loc_next;
    1.12 +    ptrdiff_t const loc_children = iter->loc_children;
    1.13  
    1.14      void *children;
    1.15  
    1.16 @@ -280,3 +278,116 @@
    1.17  
    1.18      return iter;
    1.19  }
    1.20 +
    1.21 +static bool cx_tree_visitor_valid(void const *it) {
    1.22 +    struct cx_tree_visitor_s const *iter = it;
    1.23 +    return iter->node != NULL;
    1.24 +}
    1.25 +
    1.26 +static void *cx_tree_visitor_current(void const *it) {
    1.27 +    struct cx_tree_visitor_s const *iter = it;
    1.28 +    return iter->node;
    1.29 +}
    1.30 +
    1.31 +__attribute__((__nonnull__))
    1.32 +static void cx_tree_visitor_enqueue_siblings(
    1.33 +        struct cx_tree_visitor_s *iter, void *node, ptrdiff_t loc_next) {
    1.34 +    node = tree_next(node);
    1.35 +    while (node != NULL) {
    1.36 +        struct cx_tree_visitor_queue_s *q;
    1.37 +        q = malloc(sizeof(struct cx_tree_visitor_queue_s));
    1.38 +        q->depth = iter->queue_last->depth;
    1.39 +        q->node = node;
    1.40 +        iter->queue_last->next = q;
    1.41 +        iter->queue_last = q;
    1.42 +        node = tree_next(node);
    1.43 +    }
    1.44 +    iter->queue_last->next = NULL;
    1.45 +}
    1.46 +
    1.47 +static void cx_tree_visitor_next(void *it) {
    1.48 +    struct cx_tree_visitor_s *iter = it;
    1.49 +    ptrdiff_t const loc_next = iter->loc_next;
    1.50 +    ptrdiff_t const loc_children = iter->loc_children;
    1.51 +
    1.52 +    // check if there is a next node
    1.53 +    if (iter->queue_next == NULL) {
    1.54 +        iter->node = NULL;
    1.55 +        return;
    1.56 +    }
    1.57 +
    1.58 +    // dequeue the next node
    1.59 +    iter->node = iter->queue_next->node;
    1.60 +    iter->depth = iter->queue_next->depth;
    1.61 +    {
    1.62 +        struct cx_tree_visitor_queue_s *q = iter->queue_next;
    1.63 +        iter->queue_next = q->next;
    1.64 +        if (iter->queue_next == NULL) {
    1.65 +            assert(iter->queue_last == q);
    1.66 +            iter->queue_last = NULL;
    1.67 +        }
    1.68 +        free(q);
    1.69 +    }
    1.70 +
    1.71 +    // increment the node counter
    1.72 +    iter->counter++;
    1.73 +
    1.74 +    // add the children of the new node to the queue
    1.75 +    void *children = tree_children(iter->node);
    1.76 +    if (children != NULL) {
    1.77 +        struct cx_tree_visitor_queue_s *q;
    1.78 +        q = malloc(sizeof(struct cx_tree_visitor_queue_s));
    1.79 +        q->depth = iter->depth + 1;
    1.80 +        q->node = children;
    1.81 +        if (iter->queue_last == NULL) {
    1.82 +            assert(iter->queue_next == NULL);
    1.83 +            iter->queue_next = q;
    1.84 +        } else {
    1.85 +            iter->queue_last->next = q;
    1.86 +        }
    1.87 +        iter->queue_last = q;
    1.88 +        cx_tree_visitor_enqueue_siblings(iter, children, loc_next);
    1.89 +    }
    1.90 +}
    1.91 +
    1.92 +CxTreeVisitor cx_tree_visitor(
    1.93 +        void *root,
    1.94 +        ptrdiff_t loc_children,
    1.95 +        ptrdiff_t loc_next
    1.96 +) {
    1.97 +    CxTreeVisitor iter;
    1.98 +    iter.loc_children = loc_children;
    1.99 +    iter.loc_next = loc_next;
   1.100 +
   1.101 +    // allocate stack
   1.102 +    iter.depth = 0;
   1.103 +
   1.104 +    // visit the root node
   1.105 +    iter.node = root;
   1.106 +    iter.counter = 1;
   1.107 +    iter.depth = 1;
   1.108 +
   1.109 +    // put all children of root into the queue
   1.110 +    void *children = tree_children(root);
   1.111 +    if (children == NULL) {
   1.112 +        iter.queue_next = NULL;
   1.113 +        iter.queue_last = NULL;
   1.114 +    } else {
   1.115 +        iter.queue_next = malloc(sizeof(struct cx_tree_visitor_queue_s));
   1.116 +        iter.queue_next->depth = 2;
   1.117 +        iter.queue_next->node = children;
   1.118 +        iter.queue_last = iter.queue_next;
   1.119 +        cx_tree_visitor_enqueue_siblings(&iter, children, loc_next);
   1.120 +    }
   1.121 +
   1.122 +    // assign base iterator functions
   1.123 +    iter.base.mutating = false;
   1.124 +    iter.base.remove = false;
   1.125 +    iter.base.current_impl = NULL;
   1.126 +    iter.base.valid = cx_tree_visitor_valid;
   1.127 +    iter.base.next = cx_tree_visitor_next;
   1.128 +    iter.base.current = cx_tree_visitor_current;
   1.129 +
   1.130 +    return iter;
   1.131 +}
   1.132 +

mercurial