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