--- a/ucx/hash_map.c Sat Feb 22 18:10:36 2025 +0100 +++ b/ucx/hash_map.c Sun Feb 23 14:28:47 2025 +0100 @@ -103,7 +103,8 @@ if (elm != NULL && elm->key.hash == hash && elm->key.len == key.len && memcmp(elm->key.data, key.data, key.len) == 0) { - // overwrite existing element + // overwrite existing element, but call destructors first + cx_invoke_destructor(map, elm->data); if (map->collection.store_pointer) { memcpy(elm->data, &value, sizeof(void *)); } else { @@ -252,22 +253,22 @@ } static void *cx_hash_map_iter_current_entry(const void *it) { - const struct cx_iterator_s *iter = it; - // struct has to have a compatible signature - return (struct cx_map_entry_s *) &(iter->kv_data); + const CxMapIterator *iter = it; + // we have to cast away const, because of the signature + return (void*) &iter->entry; } static void *cx_hash_map_iter_current_key(const void *it) { - const struct cx_iterator_s *iter = it; - struct cx_hash_map_element_s *elm = iter->elem_handle; + const CxMapIterator *iter = it; + struct cx_hash_map_element_s *elm = iter->elem; return &elm->key; } static void *cx_hash_map_iter_current_value(const void *it) { - const struct cx_iterator_s *iter = it; - const struct cx_hash_map_s *map = iter->src_handle.c; - struct cx_hash_map_element_s *elm = iter->elem_handle; - if (map->base.collection.store_pointer) { + const CxMapIterator *iter = it; + const CxMap *map = iter->map.c; + struct cx_hash_map_element_s *elm = iter->elem; + if (map->collection.store_pointer) { return *(void **) elm->data; } else { return elm->data; @@ -275,14 +276,15 @@ } static bool cx_hash_map_iter_valid(const void *it) { - const struct cx_iterator_s *iter = it; - return iter->elem_handle != NULL; + const CxMapIterator *iter = it; + return iter->elem != NULL; } static void cx_hash_map_iter_next(void *it) { - struct cx_iterator_s *iter = it; - struct cx_hash_map_element_s *elm = iter->elem_handle; - struct cx_hash_map_s *map = iter->src_handle.m; + CxMapIterator *iter = it; + CxMap *map = iter->map.m; + struct cx_hash_map_s *hmap = (struct cx_hash_map_s *) map; + struct cx_hash_map_element_s *elm = iter->elem; // remove current element, if asked if (iter->base.remove) { @@ -295,18 +297,18 @@ // search the previous element struct cx_hash_map_element_s *prev = NULL; - if (map->buckets[iter->slot] != elm) { - prev = map->buckets[iter->slot]; + if (hmap->buckets[iter->slot] != elm) { + prev = hmap->buckets[iter->slot]; while (prev->next != elm) { prev = prev->next; } } // destroy - cx_invoke_destructor((struct cx_map_s *) map, elm->data); + cx_invoke_destructor(map, elm->data); // unlink - cx_hash_map_unlink(map, iter->slot, prev, elm); + cx_hash_map_unlink(hmap, iter->slot, prev, elm); // advance elm = next; @@ -317,32 +319,31 @@ } // search the next bucket, if required - while (elm == NULL && ++iter->slot < map->bucket_count) { - elm = map->buckets[iter->slot]; + while (elm == NULL && ++iter->slot < hmap->bucket_count) { + elm = hmap->buckets[iter->slot]; } + iter->elem = elm; - // fill the struct with the next element - iter->elem_handle = elm; - if (elm == NULL) { - iter->kv_data.key = NULL; - iter->kv_data.value = NULL; - } else { - iter->kv_data.key = &elm->key; - if (map->base.collection.store_pointer) { - iter->kv_data.value = *(void **) elm->data; + // copy data to a location where the iterator can point to + // we need to do it here, because the iterator function call + // must not modify the iterator (the parameter is const) + if (elm != NULL) { + iter->entry.key = &elm->key; + if (iter->map.c->collection.store_pointer) { + iter->entry.value = *(void **) elm->data; } else { - iter->kv_data.value = elm->data; + iter->entry.value = elm->data; } } } -static CxIterator cx_hash_map_iterator( +static CxMapIterator cx_hash_map_iterator( const CxMap *map, enum cx_map_iterator_type type ) { - CxIterator iter; + CxMapIterator iter; - iter.src_handle.c = map; + iter.map.c = map; iter.elem_count = map->collection.size; switch (type) { @@ -376,17 +377,15 @@ while (elm == NULL) { elm = hash_map->buckets[++iter.slot]; } - iter.elem_handle = elm; - iter.kv_data.key = &elm->key; + iter.elem = elm; + iter.entry.key = &elm->key; if (map->collection.store_pointer) { - iter.kv_data.value = *(void **) elm->data; + iter.entry.value = *(void **) elm->data; } else { - iter.kv_data.value = elm->data; + iter.entry.value = elm->data; } } else { - iter.elem_handle = NULL; - iter.kv_data.key = NULL; - iter.kv_data.value = NULL; + iter.elem = NULL; } return iter; @@ -433,11 +432,10 @@ map->base.collection.allocator = allocator; if (itemsize > 0) { - map->base.collection.store_pointer = false; map->base.collection.elem_size = itemsize; } else { + map->base.collection.elem_size = sizeof(void *); map->base.collection.store_pointer = true; - map->base.collection.elem_size = sizeof(void *); } return (CxMap *) map;