251 ) { |
251 ) { |
252 return cx_hash_map_get_remove(map, key, targetbuf, true); |
252 return cx_hash_map_get_remove(map, key, targetbuf, true); |
253 } |
253 } |
254 |
254 |
255 static void *cx_hash_map_iter_current_entry(const void *it) { |
255 static void *cx_hash_map_iter_current_entry(const void *it) { |
256 const struct cx_iterator_s *iter = it; |
256 const CxMapIterator *iter = it; |
257 // struct has to have a compatible signature |
257 // we have to cast away const, because of the signature |
258 return (struct cx_map_entry_s *) &(iter->kv_data); |
258 return (void*) &iter->entry; |
259 } |
259 } |
260 |
260 |
261 static void *cx_hash_map_iter_current_key(const void *it) { |
261 static void *cx_hash_map_iter_current_key(const void *it) { |
262 const struct cx_iterator_s *iter = it; |
262 const CxMapIterator *iter = it; |
263 struct cx_hash_map_element_s *elm = iter->elem_handle; |
263 struct cx_hash_map_element_s *elm = iter->elem; |
264 return &elm->key; |
264 return &elm->key; |
265 } |
265 } |
266 |
266 |
267 static void *cx_hash_map_iter_current_value(const void *it) { |
267 static void *cx_hash_map_iter_current_value(const void *it) { |
268 const struct cx_iterator_s *iter = it; |
268 const CxMapIterator *iter = it; |
269 const struct cx_hash_map_s *map = iter->src_handle.c; |
269 const CxMap *map = iter->map.c; |
270 struct cx_hash_map_element_s *elm = iter->elem_handle; |
270 struct cx_hash_map_element_s *elm = iter->elem; |
271 if (map->base.collection.store_pointer) { |
271 if (map->collection.store_pointer) { |
272 return *(void **) elm->data; |
272 return *(void **) elm->data; |
273 } else { |
273 } else { |
274 return elm->data; |
274 return elm->data; |
275 } |
275 } |
276 } |
276 } |
277 |
277 |
278 static bool cx_hash_map_iter_valid(const void *it) { |
278 static bool cx_hash_map_iter_valid(const void *it) { |
279 const struct cx_iterator_s *iter = it; |
279 const CxMapIterator *iter = it; |
280 return iter->elem_handle != NULL; |
280 return iter->elem != NULL; |
281 } |
281 } |
282 |
282 |
283 static void cx_hash_map_iter_next(void *it) { |
283 static void cx_hash_map_iter_next(void *it) { |
284 struct cx_iterator_s *iter = it; |
284 CxMapIterator *iter = it; |
285 struct cx_hash_map_element_s *elm = iter->elem_handle; |
285 CxMap *map = iter->map.m; |
286 struct cx_hash_map_s *map = iter->src_handle.m; |
286 struct cx_hash_map_s *hmap = (struct cx_hash_map_s *) map; |
|
287 struct cx_hash_map_element_s *elm = iter->elem; |
287 |
288 |
288 // remove current element, if asked |
289 // remove current element, if asked |
289 if (iter->base.remove) { |
290 if (iter->base.remove) { |
290 |
291 |
291 // clear the flag |
292 // clear the flag |
294 // determine the next element |
295 // determine the next element |
295 struct cx_hash_map_element_s *next = elm->next; |
296 struct cx_hash_map_element_s *next = elm->next; |
296 |
297 |
297 // search the previous element |
298 // search the previous element |
298 struct cx_hash_map_element_s *prev = NULL; |
299 struct cx_hash_map_element_s *prev = NULL; |
299 if (map->buckets[iter->slot] != elm) { |
300 if (hmap->buckets[iter->slot] != elm) { |
300 prev = map->buckets[iter->slot]; |
301 prev = hmap->buckets[iter->slot]; |
301 while (prev->next != elm) { |
302 while (prev->next != elm) { |
302 prev = prev->next; |
303 prev = prev->next; |
303 } |
304 } |
304 } |
305 } |
305 |
306 |
306 // destroy |
307 // destroy |
307 cx_invoke_destructor((struct cx_map_s *) map, elm->data); |
308 cx_invoke_destructor(map, elm->data); |
308 |
309 |
309 // unlink |
310 // unlink |
310 cx_hash_map_unlink(map, iter->slot, prev, elm); |
311 cx_hash_map_unlink(hmap, iter->slot, prev, elm); |
311 |
312 |
312 // advance |
313 // advance |
313 elm = next; |
314 elm = next; |
314 } else { |
315 } else { |
315 // just advance |
316 // just advance |
316 elm = elm->next; |
317 elm = elm->next; |
317 iter->index++; |
318 iter->index++; |
318 } |
319 } |
319 |
320 |
320 // search the next bucket, if required |
321 // search the next bucket, if required |
321 while (elm == NULL && ++iter->slot < map->bucket_count) { |
322 while (elm == NULL && ++iter->slot < hmap->bucket_count) { |
322 elm = map->buckets[iter->slot]; |
323 elm = hmap->buckets[iter->slot]; |
323 } |
324 } |
324 |
325 iter->elem = elm; |
325 // fill the struct with the next element |
326 |
326 iter->elem_handle = elm; |
327 // copy data to a location where the iterator can point to |
327 if (elm == NULL) { |
328 // we need to do it here, because the iterator function call |
328 iter->kv_data.key = NULL; |
329 // must not modify the iterator (the parameter is const) |
329 iter->kv_data.value = NULL; |
330 if (elm != NULL) { |
330 } else { |
331 iter->entry.key = &elm->key; |
331 iter->kv_data.key = &elm->key; |
332 if (iter->map.c->collection.store_pointer) { |
332 if (map->base.collection.store_pointer) { |
333 iter->entry.value = *(void **) elm->data; |
333 iter->kv_data.value = *(void **) elm->data; |
|
334 } else { |
334 } else { |
335 iter->kv_data.value = elm->data; |
335 iter->entry.value = elm->data; |
336 } |
336 } |
337 } |
337 } |
338 } |
338 } |
339 |
339 |
340 static CxIterator cx_hash_map_iterator( |
340 static CxMapIterator cx_hash_map_iterator( |
341 const CxMap *map, |
341 const CxMap *map, |
342 enum cx_map_iterator_type type |
342 enum cx_map_iterator_type type |
343 ) { |
343 ) { |
344 CxIterator iter; |
344 CxMapIterator iter; |
345 |
345 |
346 iter.src_handle.c = map; |
346 iter.map.c = map; |
347 iter.elem_count = map->collection.size; |
347 iter.elem_count = map->collection.size; |
348 |
348 |
349 switch (type) { |
349 switch (type) { |
350 case CX_MAP_ITERATOR_PAIRS: |
350 case CX_MAP_ITERATOR_PAIRS: |
351 iter.elem_size = sizeof(CxMapEntry); |
351 iter.elem_size = sizeof(CxMapEntry); |
375 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
375 struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; |
376 struct cx_hash_map_element_s *elm = hash_map->buckets[0]; |
376 struct cx_hash_map_element_s *elm = hash_map->buckets[0]; |
377 while (elm == NULL) { |
377 while (elm == NULL) { |
378 elm = hash_map->buckets[++iter.slot]; |
378 elm = hash_map->buckets[++iter.slot]; |
379 } |
379 } |
380 iter.elem_handle = elm; |
380 iter.elem = elm; |
381 iter.kv_data.key = &elm->key; |
381 iter.entry.key = &elm->key; |
382 if (map->collection.store_pointer) { |
382 if (map->collection.store_pointer) { |
383 iter.kv_data.value = *(void **) elm->data; |
383 iter.entry.value = *(void **) elm->data; |
384 } else { |
384 } else { |
385 iter.kv_data.value = elm->data; |
385 iter.entry.value = elm->data; |
386 } |
386 } |
387 } else { |
387 } else { |
388 iter.elem_handle = NULL; |
388 iter.elem = NULL; |
389 iter.kv_data.key = NULL; |
|
390 iter.kv_data.value = NULL; |
|
391 } |
389 } |
392 |
390 |
393 return iter; |
391 return iter; |
394 } |
392 } |
395 |
393 |