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