1.1 --- a/src/tree.c Sun Feb 18 13:16:38 2024 +0100 1.2 +++ b/src/tree.c Sun Feb 18 13:38:42 2024 +0100 1.3 @@ -109,17 +109,14 @@ 1.4 } 1.5 1.6 // create a working stack 1.7 - size_t work_cap = 32; 1.8 - size_t work_size = 0; 1.9 - void const **work = malloc(sizeof(void*) * work_cap); 1.10 - #define work_add(node) cx_array_add(&work, &work_size, &work_cap, \ 1.11 - sizeof(void*), &(node), cx_array_default_reallocator) 1.12 + cx_array_declare(void const*, work); 1.13 + cx_array_initialize(work, 32); 1.14 1.15 // add the children of root to the working stack 1.16 { 1.17 void *c = tree_children(root); 1.18 while (c != NULL) { 1.19 - work_add(c); 1.20 + cx_array_simple_add(work, c); 1.21 c = tree_next(c); 1.22 } 1.23 } 1.24 @@ -146,7 +143,7 @@ 1.25 // if children might contain the data, add them to the stack 1.26 void *c = tree_children(node); 1.27 while (c != NULL) { 1.28 - work_add(c); 1.29 + cx_array_simple_add(work, c); 1.30 c = tree_next(c); 1.31 } 1.32 1.33 @@ -165,7 +162,6 @@ 1.34 } 1.35 1.36 // free the working queue and return 1.37 - #undef workq_add 1.38 free(work); 1.39 return ret; 1.40 } 1.41 @@ -180,14 +176,6 @@ 1.42 return iter->node; 1.43 } 1.44 1.45 -static void cx_tree_iter_stack_add( 1.46 - struct cx_tree_iterator_s *iter, 1.47 - void *node 1.48 -) { 1.49 - cx_array_add(&iter->stack, &iter->depth, &iter->stack_capacity, 1.50 - sizeof(void*), &node, cx_array_default_reallocator); 1.51 -} 1.52 - 1.53 static void cx_tree_iter_next(void *it) { 1.54 struct cx_tree_iterator_s *iter = it; 1.55 // TODO: support mutating iterator 1.56 @@ -195,77 +183,28 @@ 1.57 // TODO: implement 1.58 } 1.59 1.60 - 1.61 CxTreeIterator cx_tree_iterator( 1.62 void *root, 1.63 - int passes, 1.64 + bool visit_on_exit, 1.65 ptrdiff_t loc_children, 1.66 ptrdiff_t loc_next 1.67 ) { 1.68 CxTreeIterator iter; 1.69 iter.loc_children = loc_children; 1.70 iter.loc_next = loc_next; 1.71 - iter.requested_passes = passes; 1.72 - 1.73 - // invalidate iterator immediately when passes is invalid 1.74 - if ((passes & (CX_TREE_ITERATOR_ENTER | 1.75 - CX_TREE_ITERATOR_NEXT_CHILD | 1.76 - CX_TREE_ITERATOR_EXIT)) == 0) { 1.77 - iter.stack = NULL; 1.78 - iter.node = NULL; 1.79 - return iter; 1.80 - } 1.81 + iter.visit_on_exit = visit_on_exit; 1.82 1.83 // allocate stack 1.84 iter.stack_capacity = 16; 1.85 iter.stack = malloc(sizeof(void *) * 16); 1.86 iter.depth = 0; 1.87 1.88 - // determine start 1.89 - if ((passes & CX_TREE_ITERATOR_ENTER) == 0) { 1.90 - // we have to skip the first "entering" passes 1.91 - void *s = NULL; 1.92 - void *n = root; 1.93 - iter.counter = 0; 1.94 - do { 1.95 - iter.counter++; 1.96 - iter.source = s; 1.97 - iter.node = n; 1.98 - cx_tree_iter_stack_add(&iter, n); 1.99 - s = n; 1.100 - n = tree_children(n); 1.101 - } while (n != NULL); 1.102 - // found a leaf node s (might be root itself if it has no children) 1.103 - 1.104 - // check if there is a sibling 1.105 - n = tree_next(s); 1.106 - 1.107 - if (n == NULL) { 1.108 - // no sibling found, exit back to parent node 1.109 - // TODO: implement 1.110 - } else { 1.111 - // there is a sibling 1.112 - if ((passes & CX_TREE_ITERATOR_EXIT) == 0) { 1.113 - // no exit requested, conclude that only next_child is requested 1.114 - iter.source = s; 1.115 - iter.node = n; 1.116 - iter.counter++; 1.117 - iter.current_pass = CX_TREE_ITERATOR_NEXT_CHILD; 1.118 - } else { 1.119 - // exit requested, so we have found our first pass 1.120 - // iter.node and iter.source are still correct 1.121 - iter.current_pass = CX_TREE_ITERATOR_EXIT; 1.122 - } 1.123 - } 1.124 - } else { 1.125 - // enter passes are requested, we can start by entering the root node 1.126 - iter.source = NULL; 1.127 - iter.node = root; 1.128 - iter.current_pass = CX_TREE_ITERATOR_ENTER; 1.129 - iter.counter = 1; 1.130 - iter.depth = 1; 1.131 - iter.stack[0] = root; 1.132 - } 1.133 + // visit the root node 1.134 + iter.node = root; 1.135 + iter.counter = 1; 1.136 + iter.depth = 1; 1.137 + iter.stack[0] = root; 1.138 + iter.exiting = false; 1.139 1.140 // assign base iterator functions 1.141 iter.base.mutating = false;