199 CxHashKey key |
199 CxHashKey key |
200 ) { |
200 ) { |
201 return cx_hash_map_get_remove(map, key, true); |
201 return cx_hash_map_get_remove(map, key, true); |
202 } |
202 } |
203 |
203 |
204 static void *cx_hash_map_iter_current_entry(CxIterator const *iter) { |
204 static void *cx_hash_map_iter_current_entry(void const *it) { |
|
205 struct cx_iterator_s const *iter = it; |
205 // struct has to have a compatible signature |
206 // struct has to have a compatible signature |
206 return (struct cx_map_entry_s *) &(iter->kv_data); |
207 return (struct cx_map_entry_s *) &(iter->kv_data); |
207 } |
208 } |
208 |
209 |
209 static void *cx_hash_map_iter_current_key(CxIterator const *iter) { |
210 static void *cx_hash_map_iter_current_key(void const *it) { |
|
211 struct cx_iterator_s const *iter = it; |
210 struct cx_hash_map_element_s *elm = iter->elem_handle; |
212 struct cx_hash_map_element_s *elm = iter->elem_handle; |
211 return &elm->key; |
213 return &elm->key; |
212 } |
214 } |
213 |
215 |
214 static void *cx_hash_map_iter_current_value(CxIterator const *iter) { |
216 static void *cx_hash_map_iter_current_value(void const *it) { |
|
217 struct cx_iterator_s const *iter = it; |
215 struct cx_hash_map_element_s *elm = iter->elem_handle; |
218 struct cx_hash_map_element_s *elm = iter->elem_handle; |
216 // TODO: return a pointer to data if this map is storing copies |
219 // TODO: return a pointer to data if this map is storing copies |
217 return elm->data; |
220 return elm->data; |
218 } |
221 } |
219 |
222 |
220 static bool cx_hash_map_iter_valid(CxIterator const *iter) { |
223 static bool cx_hash_map_iter_valid(void const *it) { |
|
224 struct cx_iterator_s const *iter = it; |
221 return iter->elem_handle != NULL; |
225 return iter->elem_handle != NULL; |
222 } |
226 } |
223 |
227 |
224 static void cx_hash_map_iter_next(CxIterator *iter) { |
228 static void cx_hash_map_iter_next(void *it) { |
225 struct cx_hash_map_s *map = iter->src_handle; |
229 struct cx_iterator_s *iter = it; |
226 struct cx_hash_map_element_s *elm = iter->elem_handle; |
230 struct cx_hash_map_element_s *elm = iter->elem_handle; |
227 |
231 |
228 // remove current element, if asked |
232 // remove current element, if asked |
229 if (iter->remove) { |
233 if (iter->base.remove) { |
|
234 // obtain mutable pointer to the map |
|
235 struct cx_mut_iterator_s *miter = it; |
|
236 struct cx_hash_map_s *map = miter->src_handle; |
|
237 |
230 // clear the flag |
238 // clear the flag |
231 iter->remove = false; |
239 iter->base.remove = false; |
232 |
240 |
233 // determine the next element |
241 // determine the next element |
234 struct cx_hash_map_element_s *next = elm->next; |
242 struct cx_hash_map_element_s *next = elm->next; |
235 |
243 |
236 // search the previous element |
244 // search the previous element |
268 // TODO: pointer to data if this map is storing copies |
277 // TODO: pointer to data if this map is storing copies |
269 iter->kv_data.value = elm->data; |
278 iter->kv_data.value = elm->data; |
270 } |
279 } |
271 } |
280 } |
272 |
281 |
273 static CxIterator cx_hash_map_iterator(CxMap *map) { |
282 static bool cx_hash_map_iter_flag_rm(void *it) { |
|
283 struct cx_iterator_base_s *iter = it; |
|
284 if (iter->mutating) { |
|
285 iter->remove = true; |
|
286 return true; |
|
287 } else { |
|
288 return false; |
|
289 } |
|
290 } |
|
291 |
|
292 static CxIterator cx_hash_map_iterator(CxMap const *map) { |
274 CxIterator iter; |
293 CxIterator iter; |
275 |
294 |
276 iter.src_handle = map; |
295 iter.src_handle = map; |
277 iter.valid = cx_hash_map_iter_valid; |
296 iter.base.valid = cx_hash_map_iter_valid; |
278 iter.next = cx_hash_map_iter_next; |
297 iter.base.next = cx_hash_map_iter_next; |
279 iter.current = cx_hash_map_iter_current_entry; |
298 iter.base.current = cx_hash_map_iter_current_entry; |
|
299 iter.base.flag_removal = cx_hash_map_iter_flag_rm; |
|
300 iter.base.remove = false; |
|
301 iter.base.mutating = false; |
280 |
302 |
281 iter.slot = 0; |
303 iter.slot = 0; |
282 iter.index = 0; |
304 iter.index = 0; |
283 iter.remove = false; |
|
284 |
305 |
285 if (map->size > 0) { |
306 if (map->size > 0) { |
286 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
307 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
287 struct cx_hash_map_element_s *elm = hash_map->buckets[0]; |
308 struct cx_hash_map_element_s *elm = hash_map->buckets[0]; |
288 for (; elm == NULL; iter.slot++) { |
309 for (; elm == NULL; iter.slot++) { |
299 } |
320 } |
300 |
321 |
301 return iter; |
322 return iter; |
302 } |
323 } |
303 |
324 |
304 static CxIterator cx_hash_map_iterator_keys(CxMap *map) { |
325 static CxIterator cx_hash_map_iterator_keys(CxMap const *map) { |
305 CxIterator iter = cx_hash_map_iterator(map); |
326 CxIterator iter = cx_hash_map_iterator(map); |
306 iter.current = cx_hash_map_iter_current_key; |
327 iter.base.current = cx_hash_map_iter_current_key; |
307 return iter; |
328 return iter; |
308 } |
329 } |
309 |
330 |
310 static CxIterator cx_hash_map_iterator_values(CxMap *map) { |
331 static CxIterator cx_hash_map_iterator_values(CxMap const *map) { |
311 CxIterator iter = cx_hash_map_iterator(map); |
332 CxIterator iter = cx_hash_map_iterator(map); |
312 iter.current = cx_hash_map_iter_current_value; |
333 iter.base.current = cx_hash_map_iter_current_value; |
|
334 return iter; |
|
335 } |
|
336 |
|
337 static CxMutIterator cx_hash_map_mut_iterator(CxMap *map) { |
|
338 CxIterator it = cx_hash_map_iterator(map); |
|
339 it.base.mutating = true; |
|
340 |
|
341 // we know the iterators share the same memory layout |
|
342 CxMutIterator iter; |
|
343 memcpy(&iter, &it, sizeof(CxMutIterator)); |
|
344 return iter; |
|
345 } |
|
346 |
|
347 static CxMutIterator cx_hash_map_mut_iterator_keys(CxMap *map) { |
|
348 CxMutIterator iter = cx_hash_map_mut_iterator(map); |
|
349 iter.base.current = cx_hash_map_iter_current_key; |
|
350 return iter; |
|
351 } |
|
352 |
|
353 static CxMutIterator cx_hash_map_mut_iterator_values(CxMap *map) { |
|
354 CxMutIterator iter = cx_hash_map_mut_iterator(map); |
|
355 iter.base.current = cx_hash_map_iter_current_value; |
313 return iter; |
356 return iter; |
314 } |
357 } |
315 |
358 |
316 static cx_map_class cx_hash_map_class = { |
359 static cx_map_class cx_hash_map_class = { |
317 cx_hash_map_destructor, |
360 cx_hash_map_destructor, |
320 cx_hash_map_get, |
363 cx_hash_map_get, |
321 cx_hash_map_remove, |
364 cx_hash_map_remove, |
322 cx_hash_map_iterator, |
365 cx_hash_map_iterator, |
323 cx_hash_map_iterator_keys, |
366 cx_hash_map_iterator_keys, |
324 cx_hash_map_iterator_values, |
367 cx_hash_map_iterator_values, |
|
368 cx_hash_map_mut_iterator, |
|
369 cx_hash_map_mut_iterator_keys, |
|
370 cx_hash_map_mut_iterator_values, |
325 }; |
371 }; |
326 |
372 |
327 CxMap *cxHashMapCreate( |
373 CxMap *cxHashMapCreate( |
328 CxAllocator *allocator, |
374 CxAllocator *allocator, |
329 size_t buckets |
375 size_t buckets |