| 82 |
84 |
| 83 CxMap *const cxEmptyMap = &cx_empty_map; |
85 CxMap *const cxEmptyMap = &cx_empty_map; |
| 84 |
86 |
| 85 // </editor-fold> |
87 // </editor-fold> |
| 86 |
88 |
| 87 CxMapIterator cxMapMutIteratorValues(CxMap *map) { |
89 void cxMapClear(CxMap *map) { |
| 88 CxMapIterator it = map->cl->iterator(map, CX_MAP_ITERATOR_VALUES); |
90 map->cl->clear(map); |
| 89 it.base.mutating = true; |
91 } |
| 90 return it; |
92 |
| 91 } |
93 size_t cxMapSize(const CxMap *map) { |
| 92 |
94 return map->collection.size; |
| 93 CxMapIterator cxMapMutIteratorKeys(CxMap *map) { |
95 } |
| 94 CxMapIterator it = map->cl->iterator(map, CX_MAP_ITERATOR_KEYS); |
96 |
| 95 it.base.mutating = true; |
97 CxMapIterator cxMapIteratorValues(const CxMap *map) { |
| 96 return it; |
98 if (map == NULL) map = cxEmptyMap; |
| 97 } |
99 return map->cl->iterator(map, CX_MAP_ITERATOR_VALUES); |
| 98 |
100 } |
| 99 CxMapIterator cxMapMutIterator(CxMap *map) { |
101 |
| 100 CxMapIterator it = map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS); |
102 CxMapIterator cxMapIteratorKeys(const CxMap *map) { |
| 101 it.base.mutating = true; |
103 if (map == NULL) map = cxEmptyMap; |
| 102 return it; |
104 return map->cl->iterator(map, CX_MAP_ITERATOR_KEYS); |
| |
105 } |
| |
106 |
| |
107 CxMapIterator cxMapIterator(const CxMap *map) { |
| |
108 if (map == NULL) map = cxEmptyMap; |
| |
109 return map->cl->iterator(map, CX_MAP_ITERATOR_PAIRS); |
| |
110 } |
| |
111 |
| |
112 int cx_map_put(CxMap *map, CxHashKey key, void *value) { |
| |
113 return map->cl->put(map, key, value) == NULL; |
| |
114 } |
| |
115 |
| |
116 void *cx_map_emplace(CxMap *map, CxHashKey key) { |
| |
117 return map->cl->put(map, key, NULL); |
| |
118 } |
| |
119 |
| |
120 void *cx_map_get(const CxMap *map, CxHashKey key) { |
| |
121 return map->cl->get(map, key); |
| |
122 } |
| |
123 |
| |
124 int cx_map_remove(CxMap *map, CxHashKey key, void *targetbuf) { |
| |
125 return map->cl->remove(map, key, targetbuf); |
| 103 } |
126 } |
| 104 |
127 |
| 105 void cxMapFree(CxMap *map) { |
128 void cxMapFree(CxMap *map) { |
| 106 if (map == NULL) return; |
129 if (map == NULL) return; |
| 107 map->cl->deallocate(map); |
130 map->cl->deallocate(map); |
| 108 } |
131 } |
| |
132 |
| |
133 static void cx_map_remove_uninitialized_entry(CxMap *map, CxHashKey key) { |
| |
134 cx_destructor_func destr_bak = map->collection.simple_destructor; |
| |
135 cx_destructor_func2 destr2_bak = map->collection.advanced_destructor; |
| |
136 map->collection.simple_destructor = NULL; |
| |
137 map->collection.advanced_destructor = NULL; |
| |
138 cxMapRemove(map, key); |
| |
139 map->collection.simple_destructor = destr_bak; |
| |
140 map->collection.advanced_destructor = destr2_bak; |
| |
141 } |
| |
142 |
| |
143 static void* cx_map_simple_clone_func(void *dst, const void *src, const CxAllocator *al, void *data) { |
| |
144 size_t elem_size = *(size_t*)data; |
| |
145 if (dst == NULL) dst = cxMalloc(al, elem_size); |
| |
146 if (dst != NULL) memcpy(dst, src, elem_size); |
| |
147 return dst; |
| |
148 } |
| |
149 |
| |
150 #define use_simple_clone_func(map) cx_map_simple_clone_func, NULL, (void*)&((map)->collection.elem_size) |
| |
151 |
| |
152 int cxMapClone(CxMap *dst, const CxMap *src, cx_clone_func clone_func, |
| |
153 const CxAllocator *clone_allocator, void *data) { |
| |
154 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; |
| |
155 CxMapIterator src_iter = cxMapIterator(src); |
| |
156 for (size_t i = 0; i < cxMapSize(src); i++) { |
| |
157 const CxMapEntry *entry = cxIteratorCurrent(src_iter); |
| |
158 void **dst_mem = cxMapEmplace(dst, *(entry->key)); |
| |
159 if (dst_mem == NULL) { |
| |
160 return 1; // LCOV_EXCL_LINE |
| |
161 } |
| |
162 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; |
| |
163 void *dst_ptr = clone_func(target, entry->value, clone_allocator, data); |
| |
164 if (dst_ptr == NULL) { |
| |
165 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
| |
166 return 1; |
| |
167 } |
| |
168 if (cxCollectionStoresPointers(dst)) { |
| |
169 *dst_mem = dst_ptr; |
| |
170 } |
| |
171 cxIteratorNext(src_iter); |
| |
172 } |
| |
173 return 0; |
| |
174 } |
| |
175 |
| |
176 int cxMapDifference(CxMap *dst, const CxMap *minuend, const CxMap *subtrahend, |
| |
177 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { |
| |
178 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; |
| |
179 |
| |
180 CxMapIterator src_iter = cxMapIterator(minuend); |
| |
181 cx_foreach(const CxMapEntry *, entry, src_iter) { |
| |
182 if (cxMapContains(subtrahend, *entry->key)) { |
| |
183 continue; |
| |
184 } |
| |
185 void** dst_mem = cxMapEmplace(dst, *entry->key); |
| |
186 if (dst_mem == NULL) { |
| |
187 return 1; // LCOV_EXCL_LINE |
| |
188 } |
| |
189 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; |
| |
190 void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); |
| |
191 if (dst_ptr == NULL) { |
| |
192 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
| |
193 return 1; |
| |
194 } |
| |
195 if (cxCollectionStoresPointers(dst)) { |
| |
196 *dst_mem = dst_ptr; |
| |
197 } |
| |
198 } |
| |
199 return 0; |
| |
200 } |
| |
201 |
| |
202 int cxMapListDifference(CxMap *dst, const CxMap *src, const CxList *keys, |
| |
203 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { |
| |
204 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; |
| |
205 |
| |
206 CxMapIterator src_iter = cxMapIterator(src); |
| |
207 cx_foreach(const CxMapEntry *, entry, src_iter) { |
| |
208 if (cxListContains(keys, entry->key)) { |
| |
209 continue; |
| |
210 } |
| |
211 void** dst_mem = cxMapEmplace(dst, *entry->key); |
| |
212 if (dst_mem == NULL) { |
| |
213 return 1; // LCOV_EXCL_LINE |
| |
214 } |
| |
215 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; |
| |
216 void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); |
| |
217 if (dst_ptr == NULL) { |
| |
218 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
| |
219 return 1; |
| |
220 } |
| |
221 if (cxCollectionStoresPointers(dst)) { |
| |
222 *dst_mem = dst_ptr; |
| |
223 } |
| |
224 } |
| |
225 return 0; |
| |
226 } |
| |
227 |
| |
228 int cxMapIntersection(CxMap *dst, const CxMap *src, const CxMap *other, |
| |
229 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { |
| |
230 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; |
| |
231 |
| |
232 CxMapIterator src_iter = cxMapIterator(src); |
| |
233 cx_foreach(const CxMapEntry *, entry, src_iter) { |
| |
234 if (!cxMapContains(other, *entry->key)) { |
| |
235 continue; |
| |
236 } |
| |
237 void** dst_mem = cxMapEmplace(dst, *entry->key); |
| |
238 if (dst_mem == NULL) { |
| |
239 return 1; // LCOV_EXCL_LINE |
| |
240 } |
| |
241 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; |
| |
242 void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); |
| |
243 if (dst_ptr == NULL) { |
| |
244 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
| |
245 return 1; |
| |
246 } |
| |
247 if (cxCollectionStoresPointers(dst)) { |
| |
248 *dst_mem = dst_ptr; |
| |
249 } |
| |
250 } |
| |
251 return 0; |
| |
252 } |
| |
253 |
| |
254 int cxMapListIntersection(CxMap *dst, const CxMap *src, const CxList *keys, |
| |
255 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { |
| |
256 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; |
| |
257 |
| |
258 CxMapIterator src_iter = cxMapIterator(src); |
| |
259 cx_foreach(const CxMapEntry *, entry, src_iter) { |
| |
260 if (!cxListContains(keys, entry->key)) { |
| |
261 continue; |
| |
262 } |
| |
263 void** dst_mem = cxMapEmplace(dst, *entry->key); |
| |
264 if (dst_mem == NULL) { |
| |
265 return 1; // LCOV_EXCL_LINE |
| |
266 } |
| |
267 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; |
| |
268 void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); |
| |
269 if (dst_ptr == NULL) { |
| |
270 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
| |
271 return 1; |
| |
272 } |
| |
273 if (cxCollectionStoresPointers(dst)) { |
| |
274 *dst_mem = dst_ptr; |
| |
275 } |
| |
276 } |
| |
277 return 0; |
| |
278 } |
| |
279 |
| |
280 int cxMapUnion(CxMap *dst, const CxMap *src, |
| |
281 cx_clone_func clone_func, const CxAllocator *clone_allocator, void *data) { |
| |
282 if (clone_allocator == NULL) clone_allocator = cxDefaultAllocator; |
| |
283 |
| |
284 CxMapIterator src_iter = cxMapIterator(src); |
| |
285 cx_foreach(const CxMapEntry *, entry, src_iter) { |
| |
286 if (cxMapContains(dst, *entry->key)) { |
| |
287 continue; |
| |
288 } |
| |
289 void** dst_mem = cxMapEmplace(dst, *entry->key); |
| |
290 if (dst_mem == NULL) { |
| |
291 return 1; // LCOV_EXCL_LINE |
| |
292 } |
| |
293 void *target = cxCollectionStoresPointers(dst) ? NULL : dst_mem; |
| |
294 void* dst_ptr = clone_func(target, entry->value, clone_allocator, data); |
| |
295 if (dst_ptr == NULL) { |
| |
296 cx_map_remove_uninitialized_entry(dst, *(entry->key)); |
| |
297 return 1; |
| |
298 } |
| |
299 if (cxCollectionStoresPointers(dst)) { |
| |
300 *dst_mem = dst_ptr; |
| |
301 } |
| |
302 } |
| |
303 return 0; |
| |
304 } |
| |
305 |
| |
306 int cxMapCloneSimple(CxMap *dst, const CxMap *src) { |
| |
307 return cxMapClone(dst, src, use_simple_clone_func(src)); |
| |
308 } |
| |
309 |
| |
310 int cxMapDifferenceSimple(CxMap *dst, const CxMap *minuend, const CxMap *subtrahend) { |
| |
311 return cxMapDifference(dst, minuend, subtrahend, use_simple_clone_func(minuend)); |
| |
312 } |
| |
313 |
| |
314 int cxMapListDifferenceSimple(CxMap *dst, const CxMap *src, const CxList *keys) { |
| |
315 return cxMapListDifference(dst, src, keys, use_simple_clone_func(src)); |
| |
316 } |
| |
317 |
| |
318 int cxMapIntersectionSimple(CxMap *dst, const CxMap *src, const CxMap *other) { |
| |
319 return cxMapIntersection(dst, src, other, use_simple_clone_func(src)); |
| |
320 } |
| |
321 |
| |
322 int cxMapListIntersectionSimple(CxMap *dst, const CxMap *src, const CxList *keys) { |
| |
323 return cxMapListIntersection(dst, src, keys, use_simple_clone_func(src)); |
| |
324 } |
| |
325 |
| |
326 int cxMapUnionSimple(CxMap *dst, const CxMap *src) { |
| |
327 return cxMapUnion(dst, src, use_simple_clone_func(src)); |
| |
328 } |