176 return iter->node; |
176 return iter->node; |
177 } |
177 } |
178 |
178 |
179 static void cx_tree_iter_next(void *it) { |
179 static void cx_tree_iter_next(void *it) { |
180 struct cx_tree_iterator_s *iter = it; |
180 struct cx_tree_iterator_s *iter = it; |
|
181 off_t const loc_next = iter->loc_next; |
|
182 off_t const loc_children = iter->loc_children; |
|
183 |
181 // TODO: support mutating iterator |
184 // TODO: support mutating iterator |
182 |
185 // TODO: support visit_on_exit |
183 // TODO: implement |
186 |
|
187 void *children = tree_children(iter->node); |
|
188 if (children == NULL) { |
|
189 // search for the next node |
|
190 void *current = iter->node; |
|
191 do { |
|
192 // check if there is a sibling |
|
193 void *next = tree_next(current); |
|
194 if (next == NULL) { |
|
195 // no sibling, check again for parent node |
|
196 --iter->depth; |
|
197 if (iter->depth == 0) { |
|
198 // there is no parent - we have iterated the entire tree |
|
199 // invalidate the iterator and free the node stack |
|
200 iter->node = NULL; |
|
201 current = NULL; |
|
202 iter->stack_capacity = 0; |
|
203 free(iter->stack); |
|
204 iter->stack = NULL; |
|
205 } else { |
|
206 // the parent node can be obtained from the top of stack |
|
207 // this way we can avoid the loc_parent in the iterator |
|
208 current = iter->stack[iter->depth - 1]; |
|
209 } |
|
210 } else { |
|
211 // move to the sibling and break the loop |
|
212 current = NULL; |
|
213 iter->counter++; |
|
214 iter->node = next; |
|
215 // new top of stack is the sibling |
|
216 iter->stack[iter->depth - 1] = next; |
|
217 } |
|
218 } while (current != NULL); |
|
219 } else { |
|
220 // node has children, push the first child onto the stack and enter it |
|
221 cx_array_simple_add(iter->stack, children); |
|
222 iter->node = children; |
|
223 iter->counter++; |
|
224 } |
184 } |
225 } |
185 |
226 |
186 CxTreeIterator cx_tree_iterator( |
227 CxTreeIterator cx_tree_iterator( |
187 void *root, |
228 void *root, |
188 bool visit_on_exit, |
229 bool visit_on_exit, |