diff -r 3eeadf666d6b -r 56c62780582e src/hash_map.c --- a/src/hash_map.c Mon Feb 20 19:55:42 2023 +0100 +++ b/src/hash_map.c Thu Feb 23 18:58:15 2023 +0100 @@ -30,6 +30,17 @@ #include "cx/hash_map.h" #include "cx/utils.h" +struct cx_hash_map_element_s { + /** A pointer to the next element in the current bucket. */ + struct cx_hash_map_element_s *next; + + /** The corresponding key. */ + CxHashKey key; + + /** The value data. */ + char data[]; +}; + static void cx_hash_map_clear(struct cx_map_s *map) { struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; cx_for_n(i, hash_map->bucket_count) { @@ -89,17 +100,27 @@ if (elm != NULL && elm->key.hash == hash && elm->key.len == key.len && memcmp(elm->key.data.obj, key.data.obj, key.len) == 0) { // overwrite existing element - elm->data = value; + if (map->store_pointers) { + memcpy(elm->data, &value, sizeof(void *)); + } else { + memcpy(elm->data, value, map->itemsize); + } } else { // allocate new element - struct cx_hash_map_element_s *e = cxMalloc(allocator, sizeof(struct cx_hash_map_element_s)); + struct cx_hash_map_element_s *e = cxMalloc( + allocator, + sizeof(struct cx_hash_map_element_s) + map->itemsize + ); if (e == NULL) { return -1; } // write the value - // TODO: depending on future map features, we may want to copy here - e->data = value; + if (map->store_pointers) { + memcpy(e->data, &value, sizeof(void *)); + } else { + memcpy(e->data, value, map->itemsize); + } // copy the key void *kd = cxMalloc(allocator, key.len); @@ -151,7 +172,7 @@ * @param map the map * @param key the key to look up * @param remove flag indicating whether the looked up entry shall be removed - * @return the value corresponding to the key or \c NULL + * @return a pointer to the value corresponding to the key or \c NULL */ static void *cx_hash_map_get_remove( CxMap *map, @@ -172,7 +193,12 @@ while (elm && elm->key.hash <= hash) { if (elm->key.hash == hash && elm->key.len == key.len) { if (memcmp(elm->key.data.obj, key.data.obj, key.len) == 0) { - void *data = elm->data; + void *data = NULL; + if (map->store_pointers) { + data = *(void **) elm->data; + } else if (!remove) { + data = elm->data; + } if (remove) { cx_hash_map_unlink(hash_map, slot, prev, elm); } @@ -215,9 +241,13 @@ static void *cx_hash_map_iter_current_value(void const *it) { struct cx_iterator_s const *iter = it; + struct cx_hash_map_s const *map = iter->src_handle; struct cx_hash_map_element_s *elm = iter->elem_handle; - // TODO: return a pointer to data if this map is storing copies - return elm->data; + if (map->base.store_pointers) { + return *(void **) elm->data; + } else { + return elm->data; + } } static bool cx_hash_map_iter_valid(void const *it) { @@ -274,8 +304,11 @@ iter->kv_data.value = NULL; } else { iter->kv_data.key = &elm->key; - // TODO: pointer to data if this map is storing copies - iter->kv_data.value = elm->data; + if (map->base.store_pointers) { + iter->kv_data.value = *(void **) elm->data; + } else { + iter->kv_data.value = elm->data; + } } } @@ -311,8 +344,11 @@ } iter.elem_handle = elm; iter.kv_data.key = &elm->key; - // TODO: pointer to data if this map is storing copies - iter.kv_data.value = elm->data; + if (map->store_pointers) { + iter.kv_data.value = *(void **) elm->data; + } else { + iter.kv_data.value = elm->data; + } } else { iter.elem_handle = NULL; iter.kv_data.key = NULL; @@ -372,6 +408,7 @@ CxMap *cxHashMapCreate( CxAllocator *allocator, + size_t itemsize, size_t buckets ) { if (buckets == 0) { @@ -391,9 +428,11 @@ } // initialize base members + map->base.store_pointers = false; map->base.cl = &cx_hash_map_class; map->base.allocator = allocator; map->base.size = 0; + map->base.itemsize = itemsize; return (CxMap *) map; }