src/ucx/map.c

changeset 621
956c03c25edd
parent 579
e10457d74fe1
equal deleted inserted replaced
620:a202cb1ee175 621:956c03c25edd
27 */ 27 */
28 28
29 #include "cx/map.h" 29 #include "cx/map.h"
30 #include <string.h> 30 #include <string.h>
31 31
32 #include "cx/list.h"
33
32 // <editor-fold desc="empty map implementation"> 34 // <editor-fold desc="empty map implementation">
33 35
34 static void cx_empty_map_noop(cx_attr_unused CxMap *map) { 36 static void cx_empty_map_noop(cx_attr_unused CxMap *map) {
35 // this is a noop, but MUST be implemented 37 // this is a noop, but MUST be implemented
36 } 38 }
49 static CxMapIterator cx_empty_map_iterator( 51 static CxMapIterator cx_empty_map_iterator(
50 const struct cx_map_s *map, 52 const struct cx_map_s *map,
51 cx_attr_unused enum cx_map_iterator_type type 53 cx_attr_unused enum cx_map_iterator_type type
52 ) { 54 ) {
53 CxMapIterator iter = {0}; 55 CxMapIterator iter = {0};
54 iter.map.c = map; 56 iter.map = (CxMap*) map;
55 iter.base.valid = cx_empty_map_iter_valid; 57 iter.base.valid = cx_empty_map_iter_valid;
56 return iter; 58 return iter;
57 } 59 }
58 60
59 static struct cx_map_class_s cx_empty_map_class = { 61 static struct cx_map_class_s cx_empty_map_class = {
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 }

mercurial