| 224 cx_foreach(void *, elem, iter) { |
224 cx_foreach(void *, elem, iter) { |
| 225 // investigate the current node |
225 // investigate the current node |
| 226 int ret_elem = sfunc(elem, node); |
226 int ret_elem = sfunc(elem, node); |
| 227 if (ret_elem == 0) { |
227 if (ret_elem == 0) { |
| 228 // if found, exit the search |
228 // if found, exit the search |
| 229 *result = (void *) elem; |
229 *result = elem; |
| 230 ret = 0; |
230 ret = 0; |
| 231 break; |
231 break; |
| 232 } else if (ret_elem > 0 && ret_elem < ret) { |
232 } else if (ret_elem > 0 && ret_elem < ret) { |
| 233 // new distance is better |
233 // new distance is better |
| 234 *result = elem; |
234 *result = elem; |
| 235 ret = ret_elem; |
235 ret = ret_elem; |
| 236 } else { |
236 } else if (ret_elem < 0 || ret_elem > ret) { |
| 237 // not contained or distance is worse, skip entire subtree |
237 // not contained or distance is worse, skip entire subtree |
| 238 cxTreeIteratorContinue(iter); |
238 cxTreeIteratorContinue(iter); |
| 239 } |
239 } |
| 240 |
240 |
| 241 // when we reached the max depth, skip the subtree |
241 // when we reached the max depth, skip the subtree |
| 303 } |
303 } |
| 304 } |
304 } |
| 305 |
305 |
| 306 if (children == NULL) { |
306 if (children == NULL) { |
| 307 // search for the next node |
307 // search for the next node |
| 308 void *next; |
308 void *next = NULL; |
| 309 cx_tree_iter_search_next: |
309 cx_tree_iter_search_next: |
| 310 // check if there is a sibling |
310 // check if there is a sibling, but only if we are not a (subtree-)root |
| 311 if (iter->exiting) { |
311 if (iter->exiting) { |
| 312 next = iter->node_next; |
312 next = iter->node_next; |
| 313 } else { |
313 } else if (iter->depth > 1) { |
| 314 next = tree_next(iter->node); |
314 next = tree_next(iter->node); |
| 315 iter->node_next = next; |
315 iter->node_next = next; |
| 316 } |
316 } |
| 317 if (next == NULL) { |
317 if (next == NULL) { |
| 318 // no sibling, we are done with this node and exit |
318 // no sibling, we are done with this node and exit |
| 324 if (iter->depth == 1) { |
324 if (iter->depth == 1) { |
| 325 // there is no parent - we have iterated the entire tree |
325 // there is no parent - we have iterated the entire tree |
| 326 // invalidate the iterator and free the node stack |
326 // invalidate the iterator and free the node stack |
| 327 iter->node = iter->node_next = NULL; |
327 iter->node = iter->node_next = NULL; |
| 328 iter->stack_capacity = iter->depth = 0; |
328 iter->stack_capacity = iter->depth = 0; |
| 329 free(iter->stack); |
329 cxFreeDefault(iter->stack); |
| 330 iter->stack = NULL; |
330 iter->stack = NULL; |
| 331 } else { |
331 } else { |
| 332 // the parent node can be obtained from the top of stack |
332 // the parent node can be obtained from the top of stack |
| 333 // this way we can avoid the loc_parent in the iterator |
333 // this way we can avoid the loc_parent in the iterator |
| 334 iter->depth--; |
334 iter->depth--; |
| 373 iter.node_next = NULL; |
373 iter.node_next = NULL; |
| 374 iter.exiting = false; |
374 iter.exiting = false; |
| 375 iter.skip = false; |
375 iter.skip = false; |
| 376 |
376 |
| 377 // assign base iterator functions |
377 // assign base iterator functions |
| 378 iter.base.mutating = false; |
378 iter.base.allow_remove = false; |
| 379 iter.base.remove = false; |
379 iter.base.remove = false; |
| 380 iter.base.current_impl = NULL; |
380 iter.base.current_impl = NULL; |
| 381 iter.base.valid = cx_tree_iter_valid; |
381 iter.base.valid = cx_tree_iter_valid; |
| 382 iter.base.next = cx_tree_iter_next; |
382 iter.base.next = cx_tree_iter_next; |
| 383 iter.base.current = cx_tree_iter_current; |
383 iter.base.current = cx_tree_iter_current; |
| 384 |
384 |
| 385 // visit the root node |
385 // visit the root node |
| 386 iter.node = root; |
386 iter.node = root; |
| 387 if (root != NULL) { |
387 if (root != NULL) { |
| 388 iter.stack_capacity = 16; |
388 iter.stack_capacity = 16; |
| 389 iter.stack = malloc(sizeof(void *) * 16); |
389 iter.stack = cxMallocDefault(sizeof(void *) * 16); |
| 390 iter.stack[0] = root; |
390 iter.stack[0] = root; |
| 391 iter.counter = 1; |
391 iter.counter = 1; |
| 392 iter.depth = 1; |
392 iter.depth = 1; |
| 393 } else { |
393 } else { |
| 394 iter.stack_capacity = 0; |
394 iter.stack_capacity = 0; |
| 414 static void cx_tree_visitor_enqueue_siblings( |
414 static void cx_tree_visitor_enqueue_siblings( |
| 415 struct cx_tree_visitor_s *iter, void *node, ptrdiff_t loc_next) { |
415 struct cx_tree_visitor_s *iter, void *node, ptrdiff_t loc_next) { |
| 416 node = tree_next(node); |
416 node = tree_next(node); |
| 417 while (node != NULL) { |
417 while (node != NULL) { |
| 418 struct cx_tree_visitor_queue_s *q; |
418 struct cx_tree_visitor_queue_s *q; |
| 419 q = malloc(sizeof(struct cx_tree_visitor_queue_s)); |
419 q = cxMallocDefault(sizeof(struct cx_tree_visitor_queue_s)); |
| 420 q->depth = iter->queue_last->depth; |
420 q->depth = iter->queue_last->depth; |
| 421 q->node = node; |
421 q->node = node; |
| 422 iter->queue_last->next = q; |
422 iter->queue_last->next = q; |
| 423 iter->queue_last = q; |
423 iter->queue_last = q; |
| 424 node = tree_next(node); |
424 node = tree_next(node); |
| 443 } else { |
443 } else { |
| 444 children = tree_children(iter->node); |
444 children = tree_children(iter->node); |
| 445 } |
445 } |
| 446 if (children != NULL) { |
446 if (children != NULL) { |
| 447 struct cx_tree_visitor_queue_s *q; |
447 struct cx_tree_visitor_queue_s *q; |
| 448 q = malloc(sizeof(struct cx_tree_visitor_queue_s)); |
448 q = cxMallocDefault(sizeof(struct cx_tree_visitor_queue_s)); |
| 449 q->depth = iter->depth + 1; |
449 q->depth = iter->depth + 1; |
| 450 q->node = children; |
450 q->node = children; |
| 451 if (iter->queue_last == NULL) { |
451 if (iter->queue_last == NULL) { |
| 452 assert(iter->queue_next == NULL); |
452 assert(iter->queue_next == NULL); |
| 453 iter->queue_next = q; |
453 iter->queue_next = q; |
| 494 iter.skip = false; |
494 iter.skip = false; |
| 495 iter.queue_next = NULL; |
495 iter.queue_next = NULL; |
| 496 iter.queue_last = NULL; |
496 iter.queue_last = NULL; |
| 497 |
497 |
| 498 // assign base iterator functions |
498 // assign base iterator functions |
| 499 iter.base.mutating = false; |
499 iter.base.allow_remove = false; |
| 500 iter.base.remove = false; |
500 iter.base.remove = false; |
| 501 iter.base.current_impl = NULL; |
501 iter.base.current_impl = NULL; |
| 502 iter.base.valid = cx_tree_visitor_valid; |
502 iter.base.valid = cx_tree_visitor_valid; |
| 503 iter.base.next = cx_tree_visitor_next; |
503 iter.base.next = cx_tree_visitor_next; |
| 504 iter.base.current = cx_tree_visitor_current; |
504 iter.base.current = cx_tree_visitor_current; |
| 715 return 0; |
715 return 0; |
| 716 } |
716 } |
| 717 } |
717 } |
| 718 |
718 |
| 719 // otherwise, create iterator and hand over to other function |
719 // otherwise, create iterator and hand over to other function |
| 720 CxIterator iter = cxIterator(src, elem_size, num); |
720 CxIterator iter = cxIterator(src, elem_size, num, false); |
| 721 return cx_tree_add_iter(cxIteratorRef(iter), num, sfunc, |
721 return cx_tree_add_iter(cxIteratorRef(iter), num, sfunc, |
| 722 cfunc, cdata, failed, root, |
722 cfunc, cdata, failed, root, |
| 723 loc_parent, loc_children, loc_last_child, |
723 loc_parent, loc_children, loc_last_child, |
| 724 loc_prev, loc_next); |
724 loc_prev, loc_next); |
| 725 } |
725 } |
| 802 cx_tree_default_insert_element, |
802 cx_tree_default_insert_element, |
| 803 cx_tree_default_insert_many, |
803 cx_tree_default_insert_many, |
| 804 cx_tree_default_find |
804 cx_tree_default_find |
| 805 }; |
805 }; |
| 806 |
806 |
| 807 CxTree *cxTreeCreate( |
807 CxTree *cxTreeCreate(const CxAllocator *allocator, |
| 808 const CxAllocator *allocator, |
|
| 809 cx_tree_node_create_func create_func, |
808 cx_tree_node_create_func create_func, |
| 810 cx_tree_search_func search_func, |
809 cx_tree_search_func search_func, |
| 811 cx_tree_search_data_func search_data_func, |
810 cx_tree_search_data_func search_data_func, |
| 812 ptrdiff_t loc_parent, |
811 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, |
| 813 ptrdiff_t loc_children, |
812 ptrdiff_t loc_prev, ptrdiff_t loc_next |
| 814 ptrdiff_t loc_last_child, |
|
| 815 ptrdiff_t loc_prev, |
|
| 816 ptrdiff_t loc_next |
|
| 817 ) { |
813 ) { |
| 818 if (allocator == NULL) { |
814 if (allocator == NULL) { |
| 819 allocator = cxDefaultAllocator; |
815 allocator = cxDefaultAllocator; |
| 820 } |
816 } |
| 821 assert(create_func != NULL); |
817 assert(create_func != NULL); |
| 850 cxTreeClear(tree); |
846 cxTreeClear(tree); |
| 851 } |
847 } |
| 852 cxFree(tree->allocator, tree); |
848 cxFree(tree->allocator, tree); |
| 853 } |
849 } |
| 854 |
850 |
| 855 CxTree *cxTreeCreateWrapped( |
851 CxTree *cxTreeCreateWrapped(const CxAllocator *allocator, void *root, |
| 856 const CxAllocator *allocator, |
852 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, |
| 857 void *root, |
853 ptrdiff_t loc_prev, ptrdiff_t loc_next) { |
| 858 ptrdiff_t loc_parent, |
|
| 859 ptrdiff_t loc_children, |
|
| 860 ptrdiff_t loc_last_child, |
|
| 861 ptrdiff_t loc_prev, |
|
| 862 ptrdiff_t loc_next |
|
| 863 ) { |
|
| 864 if (allocator == NULL) { |
854 if (allocator == NULL) { |
| 865 allocator = cxDefaultAllocator; |
855 allocator = cxDefaultAllocator; |
| 866 } |
856 } |
| 867 assert(root != NULL); |
857 assert(root != NULL); |
| 868 |
858 |
| 886 tree->root = root; |
876 tree->root = root; |
| 887 tree->size = cxTreeSubtreeSize(tree, root); |
877 tree->size = cxTreeSubtreeSize(tree, root); |
| 888 return tree; |
878 return tree; |
| 889 } |
879 } |
| 890 |
880 |
| 891 void cxTreeSetParent( |
881 void cxTreeSetParent(CxTree *tree, void *parent, void *child) { |
| 892 CxTree *tree, |
|
| 893 void *parent, |
|
| 894 void *child |
|
| 895 ) { |
|
| 896 size_t loc_parent = tree->loc_parent; |
882 size_t loc_parent = tree->loc_parent; |
| 897 if (tree_parent(child) == NULL) { |
883 if (tree_parent(child) == NULL) { |
| 898 tree->size++; |
884 tree->size++; |
| 899 } |
885 } |
| 900 cx_tree_link(parent, child, cx_tree_node_layout(tree)); |
886 cx_tree_link(parent, child, cx_tree_node_layout(tree)); |
| 901 } |
887 } |
| 902 |
888 |
| 903 void cxTreeAddChildNode( |
889 void cxTreeAddChildNode(CxTree *tree, void *parent, void *child) { |
| 904 CxTree *tree, |
|
| 905 void *parent, |
|
| 906 void *child |
|
| 907 ) { |
|
| 908 cx_tree_link(parent, child, cx_tree_node_layout(tree)); |
890 cx_tree_link(parent, child, cx_tree_node_layout(tree)); |
| 909 tree->size++; |
891 tree->size++; |
| 910 } |
892 } |
| 911 |
893 |
| 912 int cxTreeAddChild( |
894 int cxTreeAddChild(CxTree *tree, void *parent, const void *data) { |
| 913 CxTree *tree, |
|
| 914 void *parent, |
|
| 915 const void *data) { |
|
| 916 void *node = tree->node_create(data, tree); |
895 void *node = tree->node_create(data, tree); |
| 917 if (node == NULL) return 1; |
896 if (node == NULL) return 1; |
| 918 cx_tree_zero_pointers(node, cx_tree_node_layout(tree)); |
897 cx_tree_zero_pointers(node, cx_tree_node_layout(tree)); |
| 919 cx_tree_link(parent, node, cx_tree_node_layout(tree)); |
898 cx_tree_link(parent, node, cx_tree_node_layout(tree)); |
| 920 tree->size++; |
899 tree->size++; |
| 921 return 0; |
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); |
| 922 } |
924 } |
| 923 |
925 |
| 924 size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root) { |
926 size_t cxTreeSubtreeSize(CxTree *tree, void *subtree_root) { |
| 925 CxTreeVisitor visitor = cx_tree_visitor( |
927 CxTreeVisitor visitor = cx_tree_visitor( |
| 926 subtree_root, |
928 subtree_root, |
| 941 ); |
943 ); |
| 942 while (cxIteratorValid(visitor)) { |
944 while (cxIteratorValid(visitor)) { |
| 943 cxIteratorNext(visitor); |
945 cxIteratorNext(visitor); |
| 944 } |
946 } |
| 945 return visitor.depth; |
947 return visitor.depth; |
| |
948 } |
| |
949 |
| |
950 size_t cxTreeSize(CxTree *tree) { |
| |
951 return tree->size; |
| 946 } |
952 } |
| 947 |
953 |
| 948 size_t cxTreeDepth(CxTree *tree) { |
954 size_t cxTreeDepth(CxTree *tree) { |
| 949 CxTreeVisitor visitor = cx_tree_visitor( |
955 CxTreeVisitor visitor = cx_tree_visitor( |
| 950 tree->root, tree->loc_children, tree->loc_next |
956 tree->root, tree->loc_children, tree->loc_next |
| 1050 tree->size -= iter.counter; |
1056 tree->size -= iter.counter; |
| 1051 if (node == tree->root) { |
1057 if (node == tree->root) { |
| 1052 tree->root = NULL; |
1058 tree->root = NULL; |
| 1053 } |
1059 } |
| 1054 } |
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 } |
| |
1075 |
| |
1076 CxTreeIterator cxTreeIterateSubtree(CxTree *tree, void *node, bool visit_on_exit) { |
| |
1077 return cx_tree_iterator( |
| |
1078 node, visit_on_exit, |
| |
1079 tree->loc_children, tree->loc_next |
| |
1080 ); |
| |
1081 } |
| |
1082 |
| |
1083 CxTreeVisitor cxTreeVisitSubtree(CxTree *tree, void *node) { |
| |
1084 return cx_tree_visitor( |
| |
1085 node, tree->loc_children, tree->loc_next |
| |
1086 ); |
| |
1087 } |
| |
1088 |
| |
1089 CxTreeIterator cxTreeIterate(CxTree *tree, bool visit_on_exit) { |
| |
1090 return cxTreeIterateSubtree(tree, tree->root, visit_on_exit); |
| |
1091 } |
| |
1092 |
| |
1093 CxTreeVisitor cxTreeVisit(CxTree *tree) { |
| |
1094 return cxTreeVisitSubtree(tree, tree->root); |
| |
1095 } |