ucx/hash_map.c

branch
newapi
changeset 324
ce13a778654a
parent 174
0358f1d9c506
--- 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;

mercurial