278 iter.base.next = cx_tree_iter_next; |
276 iter.base.next = cx_tree_iter_next; |
279 iter.base.current = cx_tree_iter_current; |
277 iter.base.current = cx_tree_iter_current; |
280 |
278 |
281 return iter; |
279 return iter; |
282 } |
280 } |
|
281 |
|
282 static bool cx_tree_visitor_valid(void const *it) { |
|
283 struct cx_tree_visitor_s const *iter = it; |
|
284 return iter->node != NULL; |
|
285 } |
|
286 |
|
287 static void *cx_tree_visitor_current(void const *it) { |
|
288 struct cx_tree_visitor_s const *iter = it; |
|
289 return iter->node; |
|
290 } |
|
291 |
|
292 __attribute__((__nonnull__)) |
|
293 static void cx_tree_visitor_enqueue_siblings( |
|
294 struct cx_tree_visitor_s *iter, void *node, ptrdiff_t loc_next) { |
|
295 node = tree_next(node); |
|
296 while (node != NULL) { |
|
297 struct cx_tree_visitor_queue_s *q; |
|
298 q = malloc(sizeof(struct cx_tree_visitor_queue_s)); |
|
299 q->depth = iter->queue_last->depth; |
|
300 q->node = node; |
|
301 iter->queue_last->next = q; |
|
302 iter->queue_last = q; |
|
303 node = tree_next(node); |
|
304 } |
|
305 iter->queue_last->next = NULL; |
|
306 } |
|
307 |
|
308 static void cx_tree_visitor_next(void *it) { |
|
309 struct cx_tree_visitor_s *iter = it; |
|
310 ptrdiff_t const loc_next = iter->loc_next; |
|
311 ptrdiff_t const loc_children = iter->loc_children; |
|
312 |
|
313 // check if there is a next node |
|
314 if (iter->queue_next == NULL) { |
|
315 iter->node = NULL; |
|
316 return; |
|
317 } |
|
318 |
|
319 // dequeue the next node |
|
320 iter->node = iter->queue_next->node; |
|
321 iter->depth = iter->queue_next->depth; |
|
322 { |
|
323 struct cx_tree_visitor_queue_s *q = iter->queue_next; |
|
324 iter->queue_next = q->next; |
|
325 if (iter->queue_next == NULL) { |
|
326 assert(iter->queue_last == q); |
|
327 iter->queue_last = NULL; |
|
328 } |
|
329 free(q); |
|
330 } |
|
331 |
|
332 // increment the node counter |
|
333 iter->counter++; |
|
334 |
|
335 // add the children of the new node to the queue |
|
336 void *children = tree_children(iter->node); |
|
337 if (children != NULL) { |
|
338 struct cx_tree_visitor_queue_s *q; |
|
339 q = malloc(sizeof(struct cx_tree_visitor_queue_s)); |
|
340 q->depth = iter->depth + 1; |
|
341 q->node = children; |
|
342 if (iter->queue_last == NULL) { |
|
343 assert(iter->queue_next == NULL); |
|
344 iter->queue_next = q; |
|
345 } else { |
|
346 iter->queue_last->next = q; |
|
347 } |
|
348 iter->queue_last = q; |
|
349 cx_tree_visitor_enqueue_siblings(iter, children, loc_next); |
|
350 } |
|
351 } |
|
352 |
|
353 CxTreeVisitor cx_tree_visitor( |
|
354 void *root, |
|
355 ptrdiff_t loc_children, |
|
356 ptrdiff_t loc_next |
|
357 ) { |
|
358 CxTreeVisitor iter; |
|
359 iter.loc_children = loc_children; |
|
360 iter.loc_next = loc_next; |
|
361 |
|
362 // allocate stack |
|
363 iter.depth = 0; |
|
364 |
|
365 // visit the root node |
|
366 iter.node = root; |
|
367 iter.counter = 1; |
|
368 iter.depth = 1; |
|
369 |
|
370 // put all children of root into the queue |
|
371 void *children = tree_children(root); |
|
372 if (children == NULL) { |
|
373 iter.queue_next = NULL; |
|
374 iter.queue_last = NULL; |
|
375 } else { |
|
376 iter.queue_next = malloc(sizeof(struct cx_tree_visitor_queue_s)); |
|
377 iter.queue_next->depth = 2; |
|
378 iter.queue_next->node = children; |
|
379 iter.queue_last = iter.queue_next; |
|
380 cx_tree_visitor_enqueue_siblings(&iter, children, loc_next); |
|
381 } |
|
382 |
|
383 // assign base iterator functions |
|
384 iter.base.mutating = false; |
|
385 iter.base.remove = false; |
|
386 iter.base.current_impl = NULL; |
|
387 iter.base.valid = cx_tree_visitor_valid; |
|
388 iter.base.next = cx_tree_visitor_next; |
|
389 iter.base.current = cx_tree_visitor_current; |
|
390 |
|
391 return iter; |
|
392 } |
|
393 |