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