src/list.c

changeset 1477
9170a7dff573
parent 1469
9b2b40a3c9f0
equal deleted inserted replaced
1476:79d4c281a63b 1477:9170a7dff573
991 } 991 }
992 } 992 }
993 993
994 return 0; 994 return 0;
995 } 995 }
996
997 int cxListUnion(CxList *dst,
998 const CxList *src, const CxList *other,
999 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) {
1000 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator;
1001
1002 // optimize for sorted collections
1003 if (cxCollectionSorted(src) && cxCollectionSorted(other)) {
1004 bool dst_was_empty = cxCollectionSize(dst) == 0;
1005
1006 CxIterator src_iter = cxListIterator(src);
1007 CxIterator other_iter = cxListIterator(other);
1008 while (cxIteratorValid(src_iter) || cxIteratorValid(other_iter)) {
1009 void *src_elem, *other_elem;
1010 int d;
1011 if (!cxIteratorValid(src_iter)) {
1012 other_elem = cxIteratorCurrent(other_iter);
1013 d = 1;
1014 } else if (!cxIteratorValid(other_iter)) {
1015 src_elem = cxIteratorCurrent(src_iter);
1016 d = -1;
1017 } else {
1018 src_elem = cxIteratorCurrent(src_iter);
1019 other_elem = cxIteratorCurrent(other_iter);
1020 d = src->collection.cmpfunc(src_elem, other_elem);
1021 }
1022 if (d <= 0) {
1023 // source element is smaller or equal, clone it
1024 void **dst_mem = cxListEmplace(dst);
1025 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem;
1026 void* dst_ptr = clone_func(target, src_elem, clone_allocator, data);
1027 if (dst_ptr == NULL) {
1028 cx_list_pop_uninitialized_elements(dst, 1);
1029 return 1;
1030 }
1031 if (cxCollectionStoresPointers(dst)) {
1032 *dst_mem = dst_ptr;
1033 }
1034 cxIteratorNext(src_iter);
1035 // if the other element was equal, skip it
1036 if (d == 0) {
1037 cxIteratorNext(other_iter);
1038 }
1039 } else {
1040 // the other element is smaller, clone it
1041 void **dst_mem = cxListEmplace(dst);
1042 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem;
1043 void* dst_ptr = clone_func(target, other_elem, clone_allocator, data);
1044 if (dst_ptr == NULL) {
1045 cx_list_pop_uninitialized_elements(dst, 1);
1046 return 1;
1047 }
1048 if (cxCollectionStoresPointers(dst)) {
1049 *dst_mem = dst_ptr;
1050 }
1051 cxIteratorNext(other_iter);
1052 }
1053 }
1054
1055 // if dst was empty, it is now guaranteed to be sorted
1056 dst->collection.sorted = dst_was_empty;
1057 } else {
1058 if (cxListClone(dst, src, clone_func, clone_allocator, data)) {
1059 return 1;
1060 }
1061 CxIterator other_iter = cxListIterator(other);
1062 cx_foreach(void *, elem, other_iter) {
1063 if (cxListContains(src, elem)) {
1064 continue;
1065 }
1066 void **dst_mem = cxListEmplace(dst);
1067 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem;
1068 void* dst_ptr = clone_func(target, elem, clone_allocator, data);
1069 if (dst_ptr == NULL) {
1070 cx_list_pop_uninitialized_elements(dst, 1);
1071 return 1;
1072 }
1073 if (cxCollectionStoresPointers(dst)) {
1074 *dst_mem = dst_ptr;
1075 }
1076 }
1077 }
1078
1079 return 0;
1080 }

mercurial