1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "cx/tree.h"
30
31 #include "cx/array_list.h"
32
33 #include <assert.h>
34
35 #define CX_TREE_PTR(cur, off) (*(
void**)(((
char*)(cur))+(off)))
36 #define tree_parent(node)
CX_TREE_PTR(node, loc_parent)
37 #define tree_children(node)
CX_TREE_PTR(node, loc_children)
38 #define tree_last_child(node)
CX_TREE_PTR(node, loc_last_child)
39 #define tree_prev(node)
CX_TREE_PTR(node, loc_prev)
40 #define tree_next(node)
CX_TREE_PTR(node, loc_next)
41
42 #define cx_tree_ptr_locations \
43 loc_parent, loc_children, loc_last_child, loc_prev, loc_next
44
45 static void cx_tree_zero_pointers(
46 void *node,
47 ptrdiff_t loc_parent,
48 ptrdiff_t loc_children,
49 ptrdiff_t loc_last_child,
50 ptrdiff_t loc_prev,
51 ptrdiff_t loc_next
52 ) {
53 tree_parent(node) =
NULL;
54 tree_prev(node) =
NULL;
55 tree_next(node) =
NULL;
56 tree_children(node) =
NULL;
57 if (loc_last_child >=
0) {
58 tree_last_child(node) =
NULL;
59 }
60 }
61
62 void cx_tree_link(
63 void *restrict parent,
64 void *restrict node,
65 ptrdiff_t loc_parent,
66 ptrdiff_t loc_children,
67 ptrdiff_t loc_last_child,
68 ptrdiff_t loc_prev,
69 ptrdiff_t loc_next
70 ) {
71 void *current_parent = tree_parent(node);
72 if (current_parent == parent)
return;
73 if (current_parent !=
NULL) {
74 cx_tree_unlink(node, cx_tree_ptr_locations);
75 }
76
77 if (tree_children(parent) ==
NULL) {
78 tree_children(parent) = node;
79 if (loc_last_child >=
0) {
80 tree_last_child(parent) = node;
81 }
82 }
else {
83 if (loc_last_child >=
0) {
84 void *child = tree_last_child(parent);
85 tree_prev(node) = child;
86 tree_next(child) = node;
87 tree_last_child(parent) = node;
88 }
else {
89 void *child = tree_children(parent);
90 void *next;
91 while ((next = tree_next(child)) !=
NULL) {
92 child = next;
93 }
94 tree_prev(node) = child;
95 tree_next(child) = node;
96 }
97 }
98 tree_parent(node) = parent;
99 }
100
101 void cx_tree_unlink(
102 void *node,
103 ptrdiff_t loc_parent,
104 ptrdiff_t loc_children,
105 ptrdiff_t loc_last_child,
106 ptrdiff_t loc_prev,
107 ptrdiff_t loc_next
108 ) {
109 if (tree_parent(node) ==
NULL)
return;
110
111 void *left = tree_prev(node);
112 void *right = tree_next(node);
113 void *parent = tree_parent(node);
114 assert(left ==
NULL || tree_children(parent) != node);
115 assert(right ==
NULL || loc_last_child <
0 ||
116 tree_last_child(parent) != node);
117
118 if (left ==
NULL) {
119 tree_children(parent) = right;
120 }
else {
121 tree_next(left) = right;
122 }
123 if (right ==
NULL) {
124 if (loc_last_child >=
0) {
125 tree_last_child(parent) = left;
126 }
127 }
else {
128 tree_prev(right) = left;
129 }
130
131 tree_parent(node) =
NULL;
132 tree_prev(node) =
NULL;
133 tree_next(node) =
NULL;
134 }
135
136 int cx_tree_search(
137 const void *root,
138 const void *node,
139 cx_tree_search_func sfunc,
140 void **result,
141 ptrdiff_t loc_children,
142 ptrdiff_t loc_next
143 ) {
144 int ret;
145 *result =
NULL;
146
147
148 ret = sfunc(root, node);
149 if (ret <
0) {
150 return ret;
151 }
else if (ret ==
0 || tree_children(root) ==
NULL) {
152 *result = (
void*)root;
153 return ret;
154 }
155
156
157 CX_ARRAY_DECLARE(
const void *, work);
158 cx_array_initialize(work,
32);
159
160
161 {
162 void *c = tree_children(root);
163 while (c !=
NULL) {
164 cx_array_simple_add(work, c);
165 c = tree_next(c);
166 }
167 }
168
169
170
171 void *candidate = (
void *) root;
172 int ret_candidate = ret;
173
174
175 while (work_size >
0) {
176
177 const void *elem = work[--work_size];
178
179
180 ret = sfunc(elem, node);
181
182 if (ret ==
0) {
183
184 *result = (
void *) elem;
185 work_size =
0;
186 break;
187 }
else if (ret >
0) {
188
189 void *c = tree_children(elem);
190 while (c !=
NULL) {
191 cx_array_simple_add(work, c);
192 c = tree_next(c);
193 }
194
195
196 if (ret < ret_candidate) {
197 candidate = (
void *) elem;
198 ret_candidate = ret;
199 }
200 }
201 }
202
203
204 if (ret !=
0 && candidate !=
NULL) {
205 ret = ret_candidate;
206 *result = candidate;
207 }
208
209
210 free(work);
211 return ret;
212 }
213
214 int cx_tree_search_data(
215 const void *root,
216 const void *data,
217 cx_tree_search_data_func sfunc,
218 void **result,
219 ptrdiff_t loc_children,
220 ptrdiff_t loc_next
221 ) {
222
223 return cx_tree_search(
224 root, data,
225 (cx_tree_search_func) sfunc,
226 result,
227 loc_children, loc_next);
228 }
229
230 static bool cx_tree_iter_valid(
const void *it) {
231 const struct cx_tree_iterator_s *iter = it;
232 return iter->node !=
NULL;
233 }
234
235 static void *cx_tree_iter_current(
const void *it) {
236 const struct cx_tree_iterator_s *iter = it;
237 return iter->node;
238 }
239
240 static void cx_tree_iter_next(
void *it) {
241 struct cx_tree_iterator_s *iter = it;
242 ptrdiff_t const loc_next = iter->loc_next;
243 ptrdiff_t const loc_children = iter->loc_children;
244
245 if (!iter->base.valid(iter))
return;
246
247 void *children;
248
249
250 if (iter->exiting) {
251 children =
NULL;
252
253 iter->skip = false;
254 }
else {
255 if (iter->skip) {
256
257 iter->skip = false;
258 children =
NULL;
259 }
else {
260
261 children = tree_children(iter->node);
262 }
263 }
264
265 if (children ==
NULL) {
266
267 void *next;
268 cx_tree_iter_search_next:
269
270 if (iter->exiting) {
271 next = iter->node_next;
272 }
else {
273 next = tree_next(iter->node);
274 iter->node_next = next;
275 }
276 if (next ==
NULL) {
277
278 if (iter->visit_on_exit && !iter->exiting) {
279
280 iter->exiting = true;
281 }
else {
282 iter->exiting = false;
283 if (iter->depth ==
1) {
284
285
286 iter->node = iter->node_next =
NULL;
287 iter->stack_capacity = iter->depth =
0;
288 free(iter->stack);
289 iter->stack =
NULL;
290 }
else {
291
292
293 iter->depth--;
294 iter->node = iter->stack[iter->depth -
1];
295
296 goto cx_tree_iter_search_next;
297 }
298 }
299 }
else {
300 if (iter->visit_on_exit && !iter->exiting) {
301
302 iter->exiting = true;
303 }
else {
304 iter->exiting = false;
305
306 iter->counter++;
307 iter->node = next;
308
309 iter->stack[iter->depth -
1] = next;
310 }
311 }
312 }
else {
313
314 cx_array_simple_add(iter->stack, children);
315 iter->node = children;
316 iter->counter++;
317 }
318 }
319
320 CxTreeIterator cx_tree_iterator(
321 void *root,
322 bool visit_on_exit,
323 ptrdiff_t loc_children,
324 ptrdiff_t loc_next
325 ) {
326 CxTreeIterator iter;
327 iter.loc_children = loc_children;
328 iter.loc_next = loc_next;
329 iter.visit_on_exit = visit_on_exit;
330
331
332 iter.node_next =
NULL;
333 iter.exiting = false;
334 iter.skip = false;
335
336
337 iter.base.mutating = false;
338 iter.base.remove = false;
339 iter.base.current_impl =
NULL;
340 iter.base.valid = cx_tree_iter_valid;
341 iter.base.next = cx_tree_iter_next;
342 iter.base.current = cx_tree_iter_current;
343
344
345 iter.node = root;
346 if (root !=
NULL) {
347 iter.stack_capacity =
16;
348 iter.stack = malloc(
sizeof(
void *) *
16);
349 iter.stack[
0] = root;
350 iter.counter =
1;
351 iter.depth =
1;
352 }
else {
353 iter.stack_capacity =
0;
354 iter.stack =
NULL;
355 iter.counter =
0;
356 iter.depth =
0;
357 }
358
359 return iter;
360 }
361
362 static bool cx_tree_visitor_valid(
const void *it) {
363 const struct cx_tree_visitor_s *iter = it;
364 return iter->node !=
NULL;
365 }
366
367 static void *cx_tree_visitor_current(
const void *it) {
368 const struct cx_tree_visitor_s *iter = it;
369 return iter->node;
370 }
371
372 __attribute__((__nonnull__))
373 static void cx_tree_visitor_enqueue_siblings(
374 struct cx_tree_visitor_s *iter,
void *node,
ptrdiff_t loc_next) {
375 node = tree_next(node);
376 while (node !=
NULL) {
377 struct cx_tree_visitor_queue_s *q;
378 q = malloc(
sizeof(
struct cx_tree_visitor_queue_s));
379 q->depth = iter->queue_last->depth;
380 q->node = node;
381 iter->queue_last->next = q;
382 iter->queue_last = q;
383 node = tree_next(node);
384 }
385 iter->queue_last->next =
NULL;
386 }
387
388 static void cx_tree_visitor_next(
void *it) {
389 struct cx_tree_visitor_s *iter = it;
390
391 if (!iter->base.valid(iter))
return;
392
393 ptrdiff_t const loc_next = iter->loc_next;
394 ptrdiff_t const loc_children = iter->loc_children;
395
396
397
398 void *children;
399 if (iter->skip) {
400 iter->skip = false;
401 children =
NULL;
402 }
else {
403 children = tree_children(iter->node);
404 }
405 if (children !=
NULL) {
406 struct cx_tree_visitor_queue_s *q;
407 q = malloc(
sizeof(
struct cx_tree_visitor_queue_s));
408 q->depth = iter->depth +
1;
409 q->node = children;
410 if (iter->queue_last ==
NULL) {
411 assert(iter->queue_next ==
NULL);
412 iter->queue_next = q;
413 }
else {
414 iter->queue_last->next = q;
415 }
416 iter->queue_last = q;
417 cx_tree_visitor_enqueue_siblings(iter, children, loc_next);
418 }
419
420
421 if (iter->queue_next ==
NULL) {
422 iter->node =
NULL;
423 return;
424 }
425
426
427 iter->node = iter->queue_next->node;
428 iter->depth = iter->queue_next->depth;
429 {
430 struct cx_tree_visitor_queue_s *q = iter->queue_next;
431 iter->queue_next = q->next;
432 if (iter->queue_next ==
NULL) {
433 assert(iter->queue_last == q);
434 iter->queue_last =
NULL;
435 }
436 free(q);
437 }
438
439
440 iter->counter++;
441 }
442
443 CxTreeVisitor cx_tree_visitor(
444 void *root,
445 ptrdiff_t loc_children,
446 ptrdiff_t loc_next
447 ) {
448 CxTreeVisitor iter;
449 iter.loc_children = loc_children;
450 iter.loc_next = loc_next;
451
452
453 iter.skip = false;
454 iter.queue_next =
NULL;
455 iter.queue_last =
NULL;
456
457
458 iter.base.mutating = false;
459 iter.base.remove = false;
460 iter.base.current_impl =
NULL;
461 iter.base.valid = cx_tree_visitor_valid;
462 iter.base.next = cx_tree_visitor_next;
463 iter.base.current = cx_tree_visitor_current;
464
465
466 iter.node = root;
467 if (root !=
NULL) {
468 iter.counter =
1;
469 iter.depth =
1;
470 }
else {
471 iter.counter =
0;
472 iter.depth =
0;
473 }
474
475 return iter;
476 }
477
478 static void cx_tree_add_link_duplicate(
479 void *original,
void *duplicate,
480 ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
481 ptrdiff_t loc_prev,
ptrdiff_t loc_next
482 ) {
483 void *shared_parent = tree_parent(original);
484 if (shared_parent ==
NULL) {
485 cx_tree_link(original, duplicate, cx_tree_ptr_locations);
486 }
else {
487 cx_tree_link(shared_parent, duplicate, cx_tree_ptr_locations);
488 }
489 }
490
491 static void cx_tree_add_link_new(
492 void *parent,
void *node, cx_tree_search_func sfunc,
493 ptrdiff_t loc_parent,
ptrdiff_t loc_children,
ptrdiff_t loc_last_child,
494 ptrdiff_t loc_prev,
ptrdiff_t loc_next
495 ) {
496
497
498 void *child = tree_children(parent);
499 while (child !=
NULL) {
500 void *next = tree_next(child);
501
502 if (sfunc(node, child) >
0) {
503
504 cx_tree_link(node, child, cx_tree_ptr_locations);
505 }
506
507 child = next;
508 }
509
510
511 cx_tree_link(parent, node, cx_tree_ptr_locations);
512 }
513
514 int cx_tree_add(
515 const void *src,
516 cx_tree_search_func sfunc,
517 cx_tree_node_create_func cfunc,
518 void *cdata,
519 void **cnode,
520 void *root,
521 ptrdiff_t loc_parent,
522 ptrdiff_t loc_children,
523 ptrdiff_t loc_last_child,
524 ptrdiff_t loc_prev,
525 ptrdiff_t loc_next
526 ) {
527 *cnode = cfunc(src, cdata);
528 if (*cnode ==
NULL)
return 1;
529 cx_tree_zero_pointers(*cnode, cx_tree_ptr_locations);
530
531 void *match =
NULL;
532 int result = cx_tree_search(
533 root,
534 *cnode,
535 sfunc,
536 &match,
537 loc_children,
538 loc_next
539 );
540
541 if (result <
0) {
542
543 return 1;
544 }
else if (result ==
0) {
545
546 cx_tree_add_link_duplicate(match, *cnode, cx_tree_ptr_locations);
547 }
else {
548
549 cx_tree_add_link_new(match, *cnode, sfunc, cx_tree_ptr_locations);
550 }
551
552 return 0;
553 }
554
555 unsigned int cx_tree_add_look_around_depth =
3;
556
557 size_t cx_tree_add_iter(
558 struct cx_iterator_base_s *iter,
559 size_t num,
560 cx_tree_search_func sfunc,
561 cx_tree_node_create_func cfunc,
562 void *cdata,
563 void **failed,
564 void *root,
565 ptrdiff_t loc_parent,
566 ptrdiff_t loc_children,
567 ptrdiff_t loc_last_child,
568 ptrdiff_t loc_prev,
569 ptrdiff_t loc_next
570 ) {
571
572 *failed =
NULL;
573
574
575 if (!iter->valid(iter))
return 0;
576
577 size_t processed =
0;
578 void *current_node = root;
579 const void *elem;
580
581 for (
void **eptr; processed < num &&
582 iter->valid(iter) && (eptr = iter->current(iter)) !=
NULL;
583 iter->next(iter)) {
584 elem = *eptr;
585
586
587 void *new_node = cfunc(elem, cdata);
588 if (new_node ==
NULL)
return processed;
589 cx_tree_zero_pointers(new_node, cx_tree_ptr_locations);
590
591
592 void *match;
593 int result;
594 unsigned int look_around_retries = cx_tree_add_look_around_depth;
595 cx_tree_add_look_around_retry:
596 result = cx_tree_search(
597 current_node,
598 new_node,
599 sfunc,
600 &match,
601 loc_children,
602 loc_next
603 );
604
605 if (result <
0) {
606
607 void *parent = tree_parent(current_node);
608 if (parent !=
NULL) {
609 if (look_around_retries >
0) {
610 look_around_retries--;
611 current_node = parent;
612 }
else {
613
614 current_node = root;
615 }
616 goto cx_tree_add_look_around_retry;
617 }
else {
618
619 *failed = new_node;
620 return processed;
621 }
622 }
else if (result ==
0) {
623
624 cx_tree_add_link_duplicate(match, new_node, cx_tree_ptr_locations);
625
626 current_node = match;
627 }
else {
628
629 cx_tree_add_link_new(match, new_node, sfunc,
630 cx_tree_ptr_locations);
631 current_node = match;
632 }
633
634 processed++;
635 }
636 return processed;
637 }
638
639 size_t cx_tree_add_array(
640 const void *src,
641 size_t num,
642 size_t elem_size,
643 cx_tree_search_func sfunc,
644 cx_tree_node_create_func cfunc,
645 void *cdata,
646 void **failed,
647 void *root,
648 ptrdiff_t loc_parent,
649 ptrdiff_t loc_children,
650 ptrdiff_t loc_last_child,
651 ptrdiff_t loc_prev,
652 ptrdiff_t loc_next
653 ) {
654
655 *failed =
NULL;
656
657
658 if (num ==
0) {
659 return 0;
660 }
661
662
663 if (num ==
1) {
664 void *node;
665 if (
0 == cx_tree_add(
666 src, sfunc, cfunc, cdata, &node, root,
667 loc_parent, loc_children, loc_last_child,
668 loc_prev, loc_next)) {
669 return 1;
670 }
else {
671 *failed = node;
672 return 0;
673 }
674 }
675
676
677 CxIterator iter = cxIterator(src, elem_size, num);
678 return cx_tree_add_iter(cxIteratorRef(iter), num, sfunc,
679 cfunc, cdata, failed, root,
680 loc_parent, loc_children, loc_last_child,
681 loc_prev, loc_next);
682 }
683
684 static void cx_tree_default_destructor(CxTree *tree) {
685 if (tree->simple_destructor !=
NULL || tree->advanced_destructor !=
NULL) {
686 CxTreeIterator iter = tree->cl->iterator(tree, true);
687 cx_foreach(
void *, node, iter) {
688 if (iter.exiting) {
689 if (tree->simple_destructor) {
690 tree->simple_destructor(node);
691 }
692 if (tree->advanced_destructor) {
693 tree->advanced_destructor(tree->destructor_data, node);
694 }
695 }
696 }
697 }
698 cxFree(tree->allocator, tree);
699 }
700
701 static CxTreeIterator cx_tree_default_iterator(
702 CxTree *tree,
703 bool visit_on_exit
704 ) {
705 return cx_tree_iterator(
706 tree->root, visit_on_exit,
707 tree->loc_children, tree->loc_next
708 );
709 }
710
711 static CxTreeVisitor cx_tree_default_visitor(CxTree *tree) {
712 return cx_tree_visitor(tree->root, tree->loc_children, tree->loc_next);
713 }
714
715 static int cx_tree_default_insert_element(
716 CxTree *tree,
717 const void *data
718 ) {
719 void *node;
720 if (tree->root ==
NULL) {
721 node = tree->node_create(data, tree);
722 if (node ==
NULL)
return 1;
723 cx_tree_zero_pointers(node, cx_tree_node_layout(tree));
724 tree->root = node;
725 tree->size =
1;
726 return 0;
727 }
728 int result = cx_tree_add(data, tree->search, tree->node_create,
729 tree, &node, tree->root, cx_tree_node_layout(tree));
730 if (
0 == result) {
731 tree->size++;
732 }
else {
733 cxFree(tree->allocator, node);
734 }
735 return result;
736 }
737
738 static size_t cx_tree_default_insert_many(
739 CxTree *tree,
740 struct cx_iterator_base_s *iter,
741 size_t n
742 ) {
743 size_t ins =
0;
744 if (!iter->valid(iter))
return 0;
745 if (tree->root ==
NULL) {
746
747 void **eptr = iter->current(iter);
748 void *node = tree->node_create(*eptr, tree);
749 if (node ==
NULL)
return 0;
750 cx_tree_zero_pointers(node, cx_tree_node_layout(tree));
751 tree->root = node;
752 ins =
1;
753 iter->next(iter);
754 }
755 void *failed;
756 ins += cx_tree_add_iter(iter, n, tree->search, tree->node_create,
757 tree, &failed, tree->root, cx_tree_node_layout(tree));
758 tree->size += ins;
759 if (ins < n) {
760 cxFree(tree->allocator, failed);
761 }
762 return ins;
763 }
764
765 static void *cx_tree_default_find(
766 CxTree *tree,
767 const void *subtree,
768 const void *data
769 ) {
770 if (tree->root ==
NULL)
return NULL;
771
772 void *found;
773 if (
0 == cx_tree_search_data(
774 subtree,
775 data,
776 tree->search_data,
777 &found,
778 tree->loc_children,
779 tree->loc_next
780 )) {
781 return found;
782 }
else {
783 return NULL;
784 }
785 }
786
787 static cx_tree_class cx_tree_default_class = {
788 cx_tree_default_destructor,
789 cx_tree_default_insert_element,
790 cx_tree_default_insert_many,
791 cx_tree_default_find,
792 cx_tree_default_iterator,
793 cx_tree_default_visitor
794 };
795
796 CxTree *cxTreeCreate(
797 const CxAllocator *allocator,
798 cx_tree_node_create_func create_func,
799 cx_tree_search_func search_func,
800 cx_tree_search_data_func search_data_func,
801 ptrdiff_t loc_parent,
802 ptrdiff_t loc_children,
803 ptrdiff_t loc_last_child,
804 ptrdiff_t loc_prev,
805 ptrdiff_t loc_next
806 ) {
807 CxTree *tree = cxMalloc(allocator,
sizeof(CxTree));
808 if (tree ==
NULL)
return NULL;
809
810 tree->cl = &cx_tree_default_class;
811 tree->allocator = allocator;
812 tree->node_create = create_func;
813 tree->search = search_func;
814 tree->search_data = search_data_func;
815 tree->advanced_destructor = (cx_destructor_func2) cxFree;
816 tree->destructor_data = (
void *) allocator;
817 tree->loc_parent = loc_parent;
818 tree->loc_children = loc_children;
819 tree->loc_last_child = loc_last_child;
820 tree->loc_prev = loc_prev;
821 tree->loc_next = loc_next;
822 tree->root =
NULL;
823 tree->size =
0;
824
825 return tree;
826 }
827
828 CxTree *cxTreeCreateWrapped(
829 const CxAllocator *allocator,
830 void *root,
831 ptrdiff_t loc_parent,
832 ptrdiff_t loc_children,
833 ptrdiff_t loc_last_child,
834 ptrdiff_t loc_prev,
835 ptrdiff_t loc_next
836 ) {
837 CxTree *tree = cxMalloc(allocator,
sizeof(CxTree));
838 if (tree ==
NULL)
return NULL;
839
840 tree->cl = &cx_tree_default_class;
841
842 tree->allocator = allocator;
843 tree->node_create =
NULL;
844 tree->search =
NULL;
845 tree->search_data =
NULL;
846 tree->simple_destructor =
NULL;
847 tree->advanced_destructor =
NULL;
848 tree->destructor_data =
NULL;
849 tree->loc_parent = loc_parent;
850 tree->loc_children = loc_children;
851 tree->loc_last_child = loc_last_child;
852 tree->loc_prev = loc_prev;
853 tree->loc_next = loc_next;
854 tree->root = root;
855 tree->size = cxTreeSubtreeSize(tree, root);
856 return tree;
857 }
858
859 int cxTreeAddChild(
860 CxTree *tree,
861 void *parent,
862 const void *data) {
863 void *node = tree->node_create(data, tree);
864 if (node ==
NULL)
return 1;
865 cx_tree_zero_pointers(node, cx_tree_node_layout(tree));
866 cx_tree_link(parent, node, cx_tree_node_layout(tree));
867 tree->size++;
868 return 0;
869 }
870
871 size_t cxTreeSubtreeSize(CxTree *tree,
void *subtree_root) {
872 CxTreeVisitor visitor = cx_tree_visitor(
873 subtree_root,
874 tree->loc_children,
875 tree->loc_next
876 );
877 while (cxIteratorValid(visitor)) {
878 cxIteratorNext(visitor);
879 }
880 return visitor.counter;
881 }
882
883 size_t cxTreeSubtreeDepth(CxTree *tree,
void *subtree_root) {
884 CxTreeVisitor visitor = cx_tree_visitor(
885 subtree_root,
886 tree->loc_children,
887 tree->loc_next
888 );
889 while (cxIteratorValid(visitor)) {
890 cxIteratorNext(visitor);
891 }
892 return visitor.depth;
893 }
894
895 size_t cxTreeDepth(CxTree *tree) {
896 CxTreeVisitor visitor = tree->cl->visitor(tree);
897 while (cxIteratorValid(visitor)) {
898 cxIteratorNext(visitor);
899 }
900 return visitor.depth;
901 }
902
903 int cxTreeRemove(
904 CxTree *tree,
905 void *node,
906 cx_tree_relink_func relink_func
907 ) {
908 if (node == tree->root)
return 1;
909
910
911 ptrdiff_t loc_parent = tree->loc_parent;
912 void *new_parent = tree_parent(node);
913
914
915 cx_tree_unlink(node, cx_tree_node_layout(tree));
916
917
918 ptrdiff_t loc_children = tree->loc_children;
919 ptrdiff_t loc_next = tree->loc_next;
920 void *child = tree_children(node);
921 while (child !=
NULL) {
922
923
924 tree_parent(child) =
NULL;
925
926
927 if (relink_func !=
NULL) {
928 relink_func(child, node, new_parent);
929 }
930
931
932 cx_tree_link(new_parent, child, cx_tree_node_layout(tree));
933
934
935 child = tree_next(child);
936 }
937
938
939 tree_children(node) =
NULL;
940 ptrdiff_t loc_last_child = tree->loc_last_child;
941 if (loc_last_child >=
0) tree_last_child(node) =
NULL;
942
943
944 tree->size--;
945
946 return 0;
947 }
948
949 void cxTreeRemoveSubtree(CxTree *tree,
void *node) {
950 if (node == tree->root) {
951 tree->root =
NULL;
952 tree->size =
0;
953 return;
954 }
955 size_t subtree_size = cxTreeSubtreeSize(tree, node);
956 cx_tree_unlink(node, cx_tree_node_layout(tree));
957 tree->size -= subtree_size;
958 }
959