--- a/ucx/hash_map.c Thu Oct 03 18:54:19 2024 +0200 +++ b/ucx/hash_map.c Sun Oct 06 12:00:31 2024 +0200 @@ -53,9 +53,9 @@ // invoke the destructor cx_invoke_destructor(map, elem->data); // free the key data - cxFree(map->allocator, (void *) elem->key.data); + cxFree(map->collection.allocator, (void *) elem->key.data); // free the node - cxFree(map->allocator, elem); + cxFree(map->collection.allocator, elem); // proceed elem = next; } while (elem != NULL); @@ -64,7 +64,7 @@ hash_map->buckets[i] = NULL; } } - map->size = 0; + map->collection.size = 0; } static void cx_hash_map_destructor(struct cx_map_s *map) { @@ -72,10 +72,10 @@ // free the buckets cx_hash_map_clear(map); - cxFree(map->allocator, hash_map->buckets); + cxFree(map->collection.allocator, hash_map->buckets); // free the map structure - cxFree(map->allocator, map); + cxFree(map->collection.allocator, map); } static int cx_hash_map_put( @@ -84,7 +84,7 @@ void *value ) { struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; - CxAllocator const *allocator = map->allocator; + const CxAllocator *allocator = map->collection.allocator; unsigned hash = key.hash; if (hash == 0) { @@ -104,26 +104,26 @@ if (elm != NULL && elm->key.hash == hash && elm->key.len == key.len && memcmp(elm->key.data, key.data, key.len) == 0) { // overwrite existing element - if (map->store_pointer) { + if (map->collection.store_pointer) { memcpy(elm->data, &value, sizeof(void *)); } else { - memcpy(elm->data, value, map->item_size); + memcpy(elm->data, value, map->collection.elem_size); } } else { // allocate new element struct cx_hash_map_element_s *e = cxMalloc( allocator, - sizeof(struct cx_hash_map_element_s) + map->item_size + sizeof(struct cx_hash_map_element_s) + map->collection.elem_size ); if (e == NULL) { return -1; } // write the value - if (map->store_pointer) { + if (map->collection.store_pointer) { memcpy(e->data, &value, sizeof(void *)); } else { - memcpy(e->data, value, map->item_size); + memcpy(e->data, value, map->collection.elem_size); } // copy the key @@ -145,7 +145,7 @@ e->next = elm; // increase the size - map->size++; + map->collection.size++; } return 0; @@ -164,10 +164,10 @@ prev->next = elm->next; } // free element - cxFree(hash_map->base.allocator, (void *) elm->key.data); - cxFree(hash_map->base.allocator, elm); + cxFree(hash_map->base.collection.allocator, (void *) elm->key.data); + cxFree(hash_map->base.collection.allocator, elm); // decrease size - hash_map->base.size--; + hash_map->base.collection.size--; } /** @@ -203,7 +203,7 @@ if (destroy) { cx_invoke_destructor(map, elm->data); } else { - if (map->store_pointer) { + if (map->collection.store_pointer) { data = *(void **) elm->data; } else { data = elm->data; @@ -223,7 +223,7 @@ } static void *cx_hash_map_get( - CxMap const *map, + const CxMap *map, CxHashKey key ) { // we can safely cast, because we know the map stays untouched @@ -238,43 +238,41 @@ return cx_hash_map_get_remove(map, key, true, destroy); } -static void *cx_hash_map_iter_current_entry(void const *it) { - struct cx_iterator_s const *iter = it; +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); } -static void *cx_hash_map_iter_current_key(void const *it) { - struct cx_iterator_s const *iter = it; +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; return &elm->key; } -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; +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.store_pointer) { + if (map->base.collection.store_pointer) { return *(void **) elm->data; } else { return elm->data; } } -static bool cx_hash_map_iter_valid(void const *it) { - struct cx_iterator_s const *iter = it; +static bool cx_hash_map_iter_valid(const void *it) { + const struct cx_iterator_s *iter = it; return iter->elem_handle != 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; // remove current element, if asked if (iter->base.remove) { - // obtain mutable pointer to the map - struct cx_mut_iterator_s *miter = it; - struct cx_hash_map_s *map = miter->src_handle; // clear the flag iter->base.remove = false; @@ -306,7 +304,6 @@ } // search the next bucket, if required - struct cx_hash_map_s const *map = iter->src_handle; while (elm == NULL && ++iter->slot < map->bucket_count) { elm = map->buckets[iter->slot]; } @@ -318,7 +315,7 @@ iter->kv_data.value = NULL; } else { iter->kv_data.key = &elm->key; - if (map->base.store_pointer) { + if (map->base.collection.store_pointer) { iter->kv_data.value = *(void **) elm->data; } else { iter->kv_data.value = elm->data; @@ -326,48 +323,41 @@ } } -static bool cx_hash_map_iter_flag_rm(void *it) { - struct cx_iterator_base_s *iter = it; - if (iter->mutating) { - iter->remove = true; - return true; - } else { - return false; - } -} - static CxIterator cx_hash_map_iterator( - CxMap const *map, + const CxMap *map, enum cx_map_iterator_type type ) { CxIterator iter; - iter.src_handle = map; - iter.base.valid = cx_hash_map_iter_valid; - iter.base.next = cx_hash_map_iter_next; + iter.src_handle.c = map; + iter.elem_count = map->collection.size; switch (type) { case CX_MAP_ITERATOR_PAIRS: + iter.elem_size = sizeof(CxMapEntry); iter.base.current = cx_hash_map_iter_current_entry; break; case CX_MAP_ITERATOR_KEYS: + iter.elem_size = sizeof(CxHashKey); iter.base.current = cx_hash_map_iter_current_key; break; case CX_MAP_ITERATOR_VALUES: + iter.elem_size = map->collection.elem_size; iter.base.current = cx_hash_map_iter_current_value; break; default: assert(false); } - iter.base.flag_removal = cx_hash_map_iter_flag_rm; + iter.base.valid = cx_hash_map_iter_valid; + iter.base.next = cx_hash_map_iter_next; iter.base.remove = false; iter.base.mutating = false; iter.slot = 0; iter.index = 0; - if (map->size > 0) { + if (map->collection.size > 0) { struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; struct cx_hash_map_element_s *elm = hash_map->buckets[0]; while (elm == NULL) { @@ -375,7 +365,7 @@ } iter.elem_handle = elm; iter.kv_data.key = &elm->key; - if (map->store_pointer) { + if (map->collection.store_pointer) { iter.kv_data.value = *(void **) elm->data; } else { iter.kv_data.value = elm->data; @@ -399,7 +389,7 @@ }; CxMap *cxHashMapCreate( - CxAllocator const *allocator, + const CxAllocator *allocator, size_t itemsize, size_t buckets ) { @@ -423,14 +413,14 @@ // initialize base members map->base.cl = &cx_hash_map_class; - map->base.allocator = allocator; + map->base.collection.allocator = allocator; if (itemsize > 0) { - map->base.store_pointer = false; - map->base.item_size = itemsize; + map->base.collection.store_pointer = false; + map->base.collection.elem_size = itemsize; } else { - map->base.store_pointer = true; - map->base.item_size = sizeof(void *); + map->base.collection.store_pointer = true; + map->base.collection.elem_size = sizeof(void *); } return (CxMap *) map; @@ -438,11 +428,11 @@ int cxMapRehash(CxMap *map) { struct cx_hash_map_s *hash_map = (struct cx_hash_map_s *) map; - if (map->size > ((hash_map->bucket_count * 3) >> 2)) { + if (map->collection.size > ((hash_map->bucket_count * 3) >> 2)) { - size_t new_bucket_count = (map->size * 5) >> 1; + size_t new_bucket_count = (map->collection.size * 5) >> 1; struct cx_hash_map_element_s **new_buckets = cxCalloc( - map->allocator, + map->collection.allocator, new_bucket_count, sizeof(struct cx_hash_map_element_s *) ); @@ -482,7 +472,7 @@ // assign result to the map hash_map->bucket_count = new_bucket_count; - cxFree(map->allocator, hash_map->buckets); + cxFree(map->collection.allocator, hash_map->buckets); hash_map->buckets = new_buckets; } return 0;