ucx/map.c

changeset 888
af685cc9d623
parent 854
1c8401ece69e
equal deleted inserted replaced
877:b60487c3ec36 888:af685cc9d623
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 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 }

mercurial