| 756 if (!iter->valid(iter)) return 0; |
763 if (!iter->valid(iter)) return 0; |
| 757 if (tree->root == NULL) { |
764 if (tree->root == NULL) { |
| 758 // use the first element from the iter to create the root node |
765 // use the first element from the iter to create the root node |
| 759 void **eptr = iter->current(iter); |
766 void **eptr = iter->current(iter); |
| 760 void *node = tree->node_create(*eptr, tree); |
767 void *node = tree->node_create(*eptr, tree); |
| 761 if (node == NULL) return 0; |
768 if (node == NULL) return 0; // LCOV_EXCL_LINE |
| 762 cx_tree_zero_pointers(node, cx_tree_node_layout(tree)); |
769 cx_tree_zero_pointers(node, cx_tree_node_layout(tree)); |
| 763 tree->root = node; |
770 tree->root = node; |
| 764 ins = 1; |
771 ins = 1; |
| 765 iter->next(iter); |
772 iter->next(iter); |
| 766 } |
773 } |
| 767 void *failed; |
774 void *failed; |
| 768 ins += cx_tree_add_iter(iter, n, tree->search, tree->node_create, |
775 ins += cx_tree_add_iter(iter, n, tree->search, tree->node_create, |
| 769 tree, &failed, tree->root, cx_tree_node_layout(tree)); |
776 tree, &failed, tree->root, cx_tree_node_layout(tree)); |
| 770 tree->size += ins; |
777 tree->collection.size += ins; |
| 771 if (ins < n) { |
778 if (ins < n) { |
| 772 cxFree(tree->allocator, failed); |
779 cxFree(tree->collection.allocator, failed); |
| 773 } |
780 } |
| 774 return ins; |
781 return ins; |
| 775 } |
782 } |
| 776 |
783 |
| 777 static void *cx_tree_default_find( |
784 static void *cx_tree_default_find( |
| 778 CxTree *tree, |
785 CxTree *tree, |
| 779 const void *subtree, |
786 const void *subtree, |
| 780 const void *data, |
787 const void *data, |
| 781 size_t depth |
788 size_t depth |
| 782 ) { |
789 ) { |
| 783 if (tree->root == NULL) return NULL; |
790 if (tree->root == NULL) return NULL; // LCOV_EXCL_LINE |
| 784 |
791 |
| 785 void *found; |
792 void *found; |
| 786 if (0 == cx_tree_search_data( |
793 if (0 == cx_tree_search_data( |
| 787 subtree, |
794 subtree, |
| 788 depth, |
795 depth, |
| 816 } |
823 } |
| 817 assert(create_func != NULL); |
824 assert(create_func != NULL); |
| 818 assert(search_func != NULL); |
825 assert(search_func != NULL); |
| 819 assert(search_data_func != NULL); |
826 assert(search_data_func != NULL); |
| 820 |
827 |
| 821 CxTree *tree = cxMalloc(allocator, sizeof(CxTree)); |
828 CxTree *tree = cxZalloc(allocator, sizeof(CxTree)); |
| 822 if (tree == NULL) return NULL; |
829 if (tree == NULL) return NULL; // LCOV_EXCL_LINE |
| 823 |
830 |
| 824 tree->cl = &cx_tree_default_class; |
831 tree->cl = &cx_tree_default_class; |
| 825 tree->allocator = allocator; |
832 tree->collection.allocator = allocator; |
| 826 tree->node_create = create_func; |
833 tree->node_create = create_func; |
| 827 tree->search = search_func; |
834 tree->search = search_func; |
| 828 tree->search_data = search_data_func; |
835 tree->search_data = search_data_func; |
| 829 tree->simple_destructor = NULL; |
836 tree->collection.advanced_destructor = (cx_destructor_func2) cxFree; |
| 830 tree->advanced_destructor = (cx_destructor_func2) cxFree; |
837 tree->collection.destructor_data = (void *) allocator; |
| 831 tree->destructor_data = (void *) allocator; |
|
| 832 tree->loc_parent = loc_parent; |
838 tree->loc_parent = loc_parent; |
| 833 tree->loc_children = loc_children; |
839 tree->loc_children = loc_children; |
| 834 tree->loc_last_child = loc_last_child; |
840 tree->loc_last_child = loc_last_child; |
| 835 tree->loc_prev = loc_prev; |
841 tree->loc_prev = loc_prev; |
| 836 tree->loc_next = loc_next; |
842 tree->loc_next = loc_next; |
| 837 tree->root = NULL; |
|
| 838 tree->size = 0; |
|
| 839 |
843 |
| 840 return tree; |
844 return tree; |
| 841 } |
845 } |
| 842 |
846 |
| 843 void cxTreeFree(CxTree *tree) { |
847 void cxTreeFree(CxTree *tree) { |
| 844 if (tree == NULL) return; |
848 if (tree == NULL) return; |
| 845 if (tree->root != NULL) { |
849 if (tree->root != NULL) { |
| 846 cxTreeClear(tree); |
850 cxTreeClear(tree); |
| 847 } |
851 } |
| 848 cxFree(tree->allocator, tree); |
852 cxFree(tree->collection.allocator, tree); |
| 849 } |
853 } |
| 850 |
854 |
| 851 CxTree *cxTreeCreateWrapped(const CxAllocator *allocator, void *root, |
855 CxTree *cxTreeCreateWrapped(const CxAllocator *allocator, void *root, |
| 852 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, |
856 ptrdiff_t loc_parent, ptrdiff_t loc_children, ptrdiff_t loc_last_child, |
| 853 ptrdiff_t loc_prev, ptrdiff_t loc_next) { |
857 ptrdiff_t loc_prev, ptrdiff_t loc_next) { |
| 854 if (allocator == NULL) { |
858 if (allocator == NULL) { |
| 855 allocator = cxDefaultAllocator; |
859 allocator = cxDefaultAllocator; |
| 856 } |
860 } |
| 857 assert(root != NULL); |
861 assert(root != NULL); |
| 858 |
862 |
| 859 CxTree *tree = cxMalloc(allocator, sizeof(CxTree)); |
863 CxTree *tree = cxZalloc(allocator, sizeof(CxTree)); |
| 860 if (tree == NULL) return NULL; |
864 if (tree == NULL) return NULL; // LCOV_EXCL_LINE |
| 861 |
865 |
| 862 tree->cl = &cx_tree_default_class; |
866 tree->cl = &cx_tree_default_class; |
| 863 // set the allocator anyway, just in case... |
867 // set the allocator anyway, just in case... |
| 864 tree->allocator = allocator; |
868 tree->collection.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; |
869 tree->loc_parent = loc_parent; |
| 872 tree->loc_children = loc_children; |
870 tree->loc_children = loc_children; |
| 873 tree->loc_last_child = loc_last_child; |
871 tree->loc_last_child = loc_last_child; |
| 874 tree->loc_prev = loc_prev; |
872 tree->loc_prev = loc_prev; |
| 875 tree->loc_next = loc_next; |
873 tree->loc_next = loc_next; |
| 876 tree->root = root; |
874 tree->root = root; |
| 877 tree->size = cxTreeSubtreeSize(tree, root); |
875 tree->collection.size = cxTreeSubtreeSize(tree, root); |
| 878 return tree; |
876 return tree; |
| 879 } |
877 } |
| 880 |
878 |
| 881 void cxTreeSetParent(CxTree *tree, void *parent, void *child) { |
879 void cxTreeSetParent(CxTree *tree, void *parent, void *child) { |
| 882 size_t loc_parent = tree->loc_parent; |
880 size_t loc_parent = tree->loc_parent; |
| 883 if (tree_parent(child) == NULL) { |
881 if (tree_parent(child) == NULL) { |
| 884 tree->size++; |
882 tree->collection.size++; |
| 885 } |
883 } |
| 886 cx_tree_link(parent, child, cx_tree_node_layout(tree)); |
884 cx_tree_link(parent, child, cx_tree_node_layout(tree)); |
| 887 } |
885 } |
| 888 |
886 |
| 889 void cxTreeAddChildNode(CxTree *tree, void *parent, void *child) { |
887 void cxTreeAddChildNode(CxTree *tree, void *parent, void *child) { |
| 890 cx_tree_link(parent, child, cx_tree_node_layout(tree)); |
888 cx_tree_link(parent, child, cx_tree_node_layout(tree)); |
| 891 tree->size++; |
889 tree->collection.size++; |
| 892 } |
890 } |
| 893 |
891 |
| 894 int cxTreeAddChild(CxTree *tree, void *parent, const void *data) { |
892 int cxTreeAddChild(CxTree *tree, void *parent, const void *data) { |
| 895 void *node = tree->node_create(data, tree); |
893 void *node = tree->node_create(data, tree); |
| 896 if (node == NULL) return 1; |
894 if (node == NULL) return 1; // LCOV_EXCL_LINE |
| 897 cx_tree_zero_pointers(node, cx_tree_node_layout(tree)); |
895 cx_tree_zero_pointers(node, cx_tree_node_layout(tree)); |
| 898 cx_tree_link(parent, node, cx_tree_node_layout(tree)); |
896 cx_tree_link(parent, node, cx_tree_node_layout(tree)); |
| 899 tree->size++; |
897 tree->collection.size++; |
| 900 return 0; |
898 return 0; |
| 901 } |
899 } |
| 902 |
900 |
| 903 int cxTreeInsert(CxTree *tree, const void *data) { |
901 int cxTreeInsert(CxTree *tree, const void *data) { |
| 904 return tree->cl->insert_element(tree, data); |
902 return tree->cl->insert_element(tree, data); |
| 1000 tree_children(node) = NULL; |
998 tree_children(node) = NULL; |
| 1001 ptrdiff_t loc_last_child = tree->loc_last_child; |
999 ptrdiff_t loc_last_child = tree->loc_last_child; |
| 1002 if (loc_last_child >= 0) tree_last_child(node) = NULL; |
1000 if (loc_last_child >= 0) tree_last_child(node) = NULL; |
| 1003 |
1001 |
| 1004 // the tree now has one member less |
1002 // the tree now has one member less |
| 1005 tree->size--; |
1003 tree->collection.size--; |
| 1006 |
1004 |
| 1007 return 0; |
1005 return 0; |
| 1008 } |
1006 } |
| 1009 |
1007 |
| 1010 void cxTreeRemoveSubtree(CxTree *tree, void *node) { |
1008 void cxTreeRemoveSubtree(CxTree *tree, void *node) { |
| 1011 if (node == tree->root) { |
1009 if (node == tree->root) { |
| 1012 tree->root = NULL; |
1010 tree->root = NULL; |
| 1013 tree->size = 0; |
1011 tree->collection.size = 0; |
| 1014 return; |
1012 return; |
| 1015 } |
1013 } |
| 1016 size_t subtree_size = cxTreeSubtreeSize(tree, node); |
1014 size_t subtree_size = cxTreeSubtreeSize(tree, node); |
| 1017 cx_tree_unlink(node, cx_tree_node_layout(tree)); |
1015 cx_tree_unlink(node, cx_tree_node_layout(tree)); |
| 1018 tree->size -= subtree_size; |
1016 tree->collection.size -= subtree_size; |
| 1019 } |
1017 } |
| 1020 |
1018 |
| 1021 int cxTreeDestroyNode( |
1019 int cxTreeDestroyNode( |
| 1022 CxTree *tree, |
1020 CxTree *tree, |
| 1023 void *node, |
1021 void *node, |
| 1024 cx_tree_relink_func relink_func |
1022 cx_tree_relink_func relink_func |
| 1025 ) { |
1023 ) { |
| 1026 int result = cxTreeRemoveNode(tree, node, relink_func); |
1024 int result = cxTreeRemoveNode(tree, node, relink_func); |
| 1027 if (result == 0) { |
1025 if (result == 0) { |
| 1028 if (tree->simple_destructor) { |
1026 cx_invoke_destructor(tree, node); |
| 1029 tree->simple_destructor(node); |
|
| 1030 } |
|
| 1031 if (tree->advanced_destructor) { |
|
| 1032 tree->advanced_destructor(tree->destructor_data, node); |
|
| 1033 } |
|
| 1034 return 0; |
1027 return 0; |
| 1035 } else { |
1028 } else { |
| 1036 return result; |
1029 return result; |
| 1037 } |
1030 } |
| 1038 } |
1031 } |