| 142 |
142 |
| 143 int cxMapClone(CxMap *dst, const CxMap *src, cx_clone_func clone_func, |
143 int cxMapClone(CxMap *dst, const CxMap *src, cx_clone_func clone_func, |
| 144 const CxAllocator *clone_allocator, void *data) { |
144 const CxAllocator *clone_allocator, void *data) { |
| 145 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; |
145 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; |
| 146 CxMapIterator src_iter = cxMapIterator(src); |
146 CxMapIterator src_iter = cxMapIterator(src); |
| 147 if (cxCollectionStoresPointers(dst)) { |
147 for (size_t i = 0; i < cxMapSize(src); i++) { |
| 148 for (size_t i = 0; i < cxMapSize(src); i++) { |
148 const CxMapEntry *entry = cxIteratorCurrent(src_iter); |
| 149 const CxMapEntry *entry = cxIteratorCurrent(src_iter); |
149 void **dst_mem = cxMapEmplace(dst, *(entry->key)); |
| 150 void **dst_mem = cxMapEmplace(dst, *(entry->key)); |
150 if (dst_mem == NULL) { |
| 151 if (dst_mem == NULL) { |
151 return 1; |
| 152 return 1; |
152 } |
| 153 } |
153 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; |
| 154 void *dst_ptr = clone_func(NULL, entry->value, clone_allocator, data); |
154 void *dst_ptr = clone_func(target, entry->value, clone_allocator, data); |
| 155 if (dst_ptr == NULL) { |
155 if (dst_ptr == NULL) { |
| 156 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
156 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
| 157 return 1; |
157 return 1; |
| 158 } |
158 } |
| |
159 if (cxCollectionStoresPointers(dst)) { |
| 159 *dst_mem = dst_ptr; |
160 *dst_mem = dst_ptr; |
| 160 cxIteratorNext(src_iter); |
161 } |
| 161 } |
162 cxIteratorNext(src_iter); |
| 162 } else { |
|
| 163 for (size_t i = 0; i < cxMapSize(src); i++) { |
|
| 164 const CxMapEntry *entry = cxIteratorCurrent(src_iter); |
|
| 165 void *dst_mem = cxMapEmplace(dst, *(entry->key)); |
|
| 166 if (dst_mem == NULL) { |
|
| 167 return 1; |
|
| 168 } |
|
| 169 if (clone_func(dst_mem, entry->value, clone_allocator, data) == NULL) { |
|
| 170 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
|
| 171 return 1; |
|
| 172 } |
|
| 173 cxIteratorNext(src_iter); |
|
| 174 } |
|
| 175 } |
163 } |
| 176 return 0; |
164 return 0; |
| 177 } |
165 } |
| 178 |
166 |
| 179 int cxMapDifference(CxMap *dst, const CxMap *minuend, const CxMap *subtrahend, |
167 int cxMapDifference(CxMap *dst, const CxMap *minuend, const CxMap *subtrahend, |
| 180 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { |
168 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { |
| 181 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; |
169 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; |
| 182 |
170 |
| 183 const bool map_was_not_empty = cxMapSize(dst) > 0; |
171 const bool map_was_not_empty = cxMapSize(dst) > 0; |
| 184 CxMapIterator src_iter = cxMapIterator(minuend); |
172 CxMapIterator src_iter = cxMapIterator(minuend); |
| 185 if (cxCollectionStoresPointers(dst)) { |
173 cx_foreach(const CxMapEntry *, entry, src_iter) { |
| 186 cx_foreach(const CxMapEntry *, entry, src_iter) { |
174 if (cxMapContains(subtrahend, *entry->key)) { |
| 187 if (cxMapContains(subtrahend, *entry->key)) { |
175 if (map_was_not_empty) { |
| 188 if (map_was_not_empty) { |
176 cxMapRemove(dst, *entry->key); |
| 189 cxMapRemove(dst, *entry->key); |
177 } |
| 190 } |
178 } else { |
| 191 } else { |
179 void** dst_mem = cxMapEmplace(dst, *entry->key); |
| 192 void** dst_mem = cxMapEmplace(dst, *entry->key); |
180 if (dst_mem == NULL) { |
| 193 if (dst_mem == NULL) { |
181 return 1; |
| 194 return 1; |
182 } |
| 195 } |
183 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; |
| 196 |
184 void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); |
| 197 void* dst_ptr = clone_func(NULL, entry->value, clone_allocator, data); |
185 if (dst_ptr == NULL) { |
| 198 if (dst_ptr == NULL) { |
186 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
| 199 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
187 return 1; |
| 200 return 1; |
188 } |
| 201 } |
189 if (cxCollectionStoresPointers(dst)) { |
| 202 *dst_mem = dst_ptr; |
190 *dst_mem = dst_ptr; |
| 203 } |
|
| 204 } |
|
| 205 } else { |
|
| 206 cx_foreach(const CxMapEntry *, entry, src_iter) { |
|
| 207 if (cxMapContains(subtrahend, *entry->key)) { |
|
| 208 if (map_was_not_empty) { |
|
| 209 cxMapRemove(dst, *entry->key); |
|
| 210 } |
|
| 211 } else { |
|
| 212 void* dst_mem = cxMapEmplace(dst, *entry->key); |
|
| 213 if (dst_mem == NULL) { |
|
| 214 return 1; |
|
| 215 } |
|
| 216 if (NULL == clone_func(dst_mem, entry->value, clone_allocator, data)) { |
|
| 217 cx_map_remove_uninitialized_entry(dst, *entry->key); |
|
| 218 return 1; |
|
| 219 } |
|
| 220 } |
191 } |
| 221 } |
192 } |
| 222 } |
193 } |
| 223 return 0; |
194 return 0; |
| 224 } |
195 } |
| 225 |
196 |
| 226 int cxMapListDifference(CxMap *dst, const CxMap *src, const CxList *keys, |
197 int cxMapListDifference(CxMap *dst, const CxMap *src, const CxList *keys, |
| 227 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { |
198 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { |
| 228 const bool map_was_not_empty = cxMapSize(dst) > 0; |
199 const bool map_was_not_empty = cxMapSize(dst) > 0; |
| 229 CxMapIterator src_iter = cxMapIterator(src); |
200 CxMapIterator src_iter = cxMapIterator(src); |
| 230 if (cxCollectionStoresPointers(dst)) { |
201 cx_foreach(const CxMapEntry *, entry, src_iter) { |
| 231 cx_foreach(const CxMapEntry *, entry, src_iter) { |
202 if (cxListContains(keys, entry->key)) { |
| 232 if (cxListContains(keys, entry->key)) { |
203 if (map_was_not_empty) { |
| 233 if (map_was_not_empty) { |
204 cxMapRemove(dst, *entry->key); |
| 234 cxMapRemove(dst, *entry->key); |
205 } |
| 235 } |
206 } else { |
| 236 } else { |
207 void** dst_mem = cxMapEmplace(dst, *entry->key); |
| 237 void** dst_mem = cxMapEmplace(dst, *entry->key); |
208 if (dst_mem == NULL) { |
| 238 if (dst_mem == NULL) { |
209 return 1; |
| 239 return 1; |
210 } |
| 240 } |
211 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; |
| 241 |
212 void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); |
| 242 void* dst_ptr = clone_func(NULL, entry->value, clone_allocator, data); |
213 if (dst_ptr == NULL) { |
| 243 if (dst_ptr == NULL) { |
214 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
| 244 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
215 return 1; |
| 245 return 1; |
216 } |
| 246 } |
217 if (cxCollectionStoresPointers(dst)) { |
| 247 *dst_mem = dst_ptr; |
218 *dst_mem = dst_ptr; |
| 248 } |
|
| 249 } |
|
| 250 } else { |
|
| 251 cx_foreach(const CxMapEntry *, entry, src_iter) { |
|
| 252 if (cxListContains(keys, entry->key)) { |
|
| 253 if (map_was_not_empty) { |
|
| 254 cxMapRemove(dst, *entry->key); |
|
| 255 } |
|
| 256 } else { |
|
| 257 void* dst_mem = cxMapEmplace(dst, *entry->key); |
|
| 258 if (dst_mem == NULL) { |
|
| 259 return 1; |
|
| 260 } |
|
| 261 if (NULL == clone_func(dst_mem, entry->value, clone_allocator, data)) { |
|
| 262 cx_map_remove_uninitialized_entry(dst, *entry->key); |
|
| 263 return 1; |
|
| 264 } |
|
| 265 } |
219 } |
| 266 } |
220 } |
| 267 } |
221 } |
| 268 return 0; |
222 return 0; |
| 269 } |
223 } |