107 *result = (void*)root; |
107 *result = (void*)root; |
108 return ret; |
108 return ret; |
109 } |
109 } |
110 |
110 |
111 // create a working stack |
111 // create a working stack |
112 size_t work_cap = 32; |
112 cx_array_declare(void const*, work); |
113 size_t work_size = 0; |
113 cx_array_initialize(work, 32); |
114 void const **work = malloc(sizeof(void*) * work_cap); |
|
115 #define work_add(node) cx_array_add(&work, &work_size, &work_cap, \ |
|
116 sizeof(void*), &(node), cx_array_default_reallocator) |
|
117 |
114 |
118 // add the children of root to the working stack |
115 // add the children of root to the working stack |
119 { |
116 { |
120 void *c = tree_children(root); |
117 void *c = tree_children(root); |
121 while (c != NULL) { |
118 while (c != NULL) { |
122 work_add(c); |
119 cx_array_simple_add(work, c); |
123 c = tree_next(c); |
120 c = tree_next(c); |
124 } |
121 } |
125 } |
122 } |
126 |
123 |
127 // remember a candidate for adding the data |
124 // remember a candidate for adding the data |
178 static void *cx_tree_iter_current(void const *it) { |
174 static void *cx_tree_iter_current(void const *it) { |
179 struct cx_tree_iterator_s const *iter = it; |
175 struct cx_tree_iterator_s const *iter = it; |
180 return iter->node; |
176 return iter->node; |
181 } |
177 } |
182 |
178 |
183 static void cx_tree_iter_stack_add( |
|
184 struct cx_tree_iterator_s *iter, |
|
185 void *node |
|
186 ) { |
|
187 cx_array_add(&iter->stack, &iter->depth, &iter->stack_capacity, |
|
188 sizeof(void*), &node, cx_array_default_reallocator); |
|
189 } |
|
190 |
|
191 static void cx_tree_iter_next(void *it) { |
179 static void cx_tree_iter_next(void *it) { |
192 struct cx_tree_iterator_s *iter = it; |
180 struct cx_tree_iterator_s *iter = it; |
193 // TODO: support mutating iterator |
181 // TODO: support mutating iterator |
194 |
182 |
195 // TODO: implement |
183 // TODO: implement |
196 } |
184 } |
197 |
185 |
198 |
|
199 CxTreeIterator cx_tree_iterator( |
186 CxTreeIterator cx_tree_iterator( |
200 void *root, |
187 void *root, |
201 int passes, |
188 bool visit_on_exit, |
202 ptrdiff_t loc_children, |
189 ptrdiff_t loc_children, |
203 ptrdiff_t loc_next |
190 ptrdiff_t loc_next |
204 ) { |
191 ) { |
205 CxTreeIterator iter; |
192 CxTreeIterator iter; |
206 iter.loc_children = loc_children; |
193 iter.loc_children = loc_children; |
207 iter.loc_next = loc_next; |
194 iter.loc_next = loc_next; |
208 iter.requested_passes = passes; |
195 iter.visit_on_exit = visit_on_exit; |
209 |
|
210 // invalidate iterator immediately when passes is invalid |
|
211 if ((passes & (CX_TREE_ITERATOR_ENTER | |
|
212 CX_TREE_ITERATOR_NEXT_CHILD | |
|
213 CX_TREE_ITERATOR_EXIT)) == 0) { |
|
214 iter.stack = NULL; |
|
215 iter.node = NULL; |
|
216 return iter; |
|
217 } |
|
218 |
196 |
219 // allocate stack |
197 // allocate stack |
220 iter.stack_capacity = 16; |
198 iter.stack_capacity = 16; |
221 iter.stack = malloc(sizeof(void *) * 16); |
199 iter.stack = malloc(sizeof(void *) * 16); |
222 iter.depth = 0; |
200 iter.depth = 0; |
223 |
201 |
224 // determine start |
202 // visit the root node |
225 if ((passes & CX_TREE_ITERATOR_ENTER) == 0) { |
203 iter.node = root; |
226 // we have to skip the first "entering" passes |
204 iter.counter = 1; |
227 void *s = NULL; |
205 iter.depth = 1; |
228 void *n = root; |
206 iter.stack[0] = root; |
229 iter.counter = 0; |
207 iter.exiting = false; |
230 do { |
|
231 iter.counter++; |
|
232 iter.source = s; |
|
233 iter.node = n; |
|
234 cx_tree_iter_stack_add(&iter, n); |
|
235 s = n; |
|
236 n = tree_children(n); |
|
237 } while (n != NULL); |
|
238 // found a leaf node s (might be root itself if it has no children) |
|
239 |
|
240 // check if there is a sibling |
|
241 n = tree_next(s); |
|
242 |
|
243 if (n == NULL) { |
|
244 // no sibling found, exit back to parent node |
|
245 // TODO: implement |
|
246 } else { |
|
247 // there is a sibling |
|
248 if ((passes & CX_TREE_ITERATOR_EXIT) == 0) { |
|
249 // no exit requested, conclude that only next_child is requested |
|
250 iter.source = s; |
|
251 iter.node = n; |
|
252 iter.counter++; |
|
253 iter.current_pass = CX_TREE_ITERATOR_NEXT_CHILD; |
|
254 } else { |
|
255 // exit requested, so we have found our first pass |
|
256 // iter.node and iter.source are still correct |
|
257 iter.current_pass = CX_TREE_ITERATOR_EXIT; |
|
258 } |
|
259 } |
|
260 } else { |
|
261 // enter passes are requested, we can start by entering the root node |
|
262 iter.source = NULL; |
|
263 iter.node = root; |
|
264 iter.current_pass = CX_TREE_ITERATOR_ENTER; |
|
265 iter.counter = 1; |
|
266 iter.depth = 1; |
|
267 iter.stack[0] = root; |
|
268 } |
|
269 |
208 |
270 // assign base iterator functions |
209 // assign base iterator functions |
271 iter.base.mutating = false; |
210 iter.base.mutating = false; |
272 iter.base.remove = false; |
211 iter.base.remove = false; |
273 iter.base.current_impl = NULL; |
212 iter.base.current_impl = NULL; |