802 |
802 |
803 void cxListFree(CxList *list) { |
803 void cxListFree(CxList *list) { |
804 if (list == NULL) return; |
804 if (list == NULL) return; |
805 list->cl->deallocate(list); |
805 list->cl->deallocate(list); |
806 } |
806 } |
|
807 |
|
808 size_t cxListClone(CxList *dst, const CxList *src, cx_clone_func clone_func, |
|
809 const CxAllocator *clone_allocator, void *data) { |
|
810 |
|
811 // remember the original size |
|
812 size_t orig_size = dst->collection.size; |
|
813 |
|
814 // first, try to allocate the memory in the new list |
|
815 CxIterator empl_iter = cxListEmplaceArray(dst, src->collection.size); |
|
816 |
|
817 // get an iterator over the source elements |
|
818 CxIterator src_iter = cxListIterator(src); |
|
819 |
|
820 // now clone the elements |
|
821 size_t cloned = empl_iter.elem_count; |
|
822 if (cxCollectionStoresPointers(dst)) { |
|
823 for (size_t i = 0 ; i < empl_iter.elem_count; i++) { |
|
824 void *src_elem = cxIteratorCurrent(src_iter); |
|
825 void **dest_memory = cxIteratorCurrent(empl_iter); |
|
826 void *dest_ptr = clone_func(NULL, src_elem, clone_allocator, data); |
|
827 if (dest_ptr == NULL) { |
|
828 cloned = i; |
|
829 break; |
|
830 } |
|
831 *dest_memory = dest_ptr; |
|
832 cxIteratorNext(src_iter); |
|
833 cxIteratorNext(empl_iter); |
|
834 } |
|
835 } else { |
|
836 for (size_t i = 0 ; i < empl_iter.elem_count; i++) { |
|
837 void *src_elem = cxIteratorCurrent(src_iter); |
|
838 void *dest_memory = cxIteratorCurrent(empl_iter); |
|
839 if (clone_func(dest_memory, src_elem, clone_allocator, data) == NULL) { |
|
840 cloned = i; |
|
841 break; |
|
842 } |
|
843 cxIteratorNext(src_iter); |
|
844 cxIteratorNext(empl_iter); |
|
845 } |
|
846 } |
|
847 |
|
848 // if we could not clone everything, free the allocated memory |
|
849 // (disable the destructors!) |
|
850 if (cloned < src->collection.size) { |
|
851 cx_destructor_func destr_bak = dst->collection.simple_destructor; |
|
852 cx_destructor_func2 destr2_bak = dst->collection.advanced_destructor; |
|
853 dst->collection.simple_destructor = NULL; |
|
854 dst->collection.advanced_destructor = NULL; |
|
855 cxListRemoveArray(dst, |
|
856 orig_size + cloned, |
|
857 dst->collection.size - cloned - orig_size); |
|
858 dst->collection.simple_destructor = destr_bak; |
|
859 dst->collection.advanced_destructor = destr2_bak; |
|
860 } |
|
861 |
|
862 // return how many elements we have cloned |
|
863 return cloned; |
|
864 } |