]> git.seodisparate.com - SimpleArchiver/commitdiff
Impl. way to set custom hasher for hash_map
authorStephen Seo <seo.disparate@gmail.com>
Sat, 21 Sep 2024 09:43:23 +0000 (18:43 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sat, 21 Sep 2024 09:43:23 +0000 (18:43 +0900)
src/data_structures/hash_map.c
src/data_structures/hash_map.h

index cdbb70009340221d3cb66cdab7c630703ba0e26e..c292e82573f59af77256ffb5c3ef8beb1f336508 100644 (file)
@@ -74,8 +74,7 @@ int simple_archiver_hash_map_internal_pick_in_list(void *data, void *ud) {
              : 0;
 }
 
-uint64_t simple_archiver_hash_map_internal_key_to_hash(const void *key,
-                                                       size_t key_size) {
+uint64_t simple_archiver_hash_default_fn(const void *key, size_t key_size) {
   uint64_t seed = 0;
   uint64_t temp = 0;
   size_t count = 0;
@@ -106,6 +105,7 @@ int simple_archiver_hash_map_internal_rehash(SDArchiverHashMap *hash_map) {
     return 1;
   }
   SDArchiverHashMap new_hash_map;
+  new_hash_map.hash_fn = hash_map->hash_fn;
   new_hash_map.buckets_size = hash_map->buckets_size * 2;
   // Pointers have the same size (at least on the same machine), so
   // sizeof(void*) should be ok.
@@ -146,7 +146,14 @@ int simple_archiver_hash_map_internal_rehash(SDArchiverHashMap *hash_map) {
 }
 
 SDArchiverHashMap *simple_archiver_hash_map_init(void) {
+  return simple_archiver_hash_map_init_custom_hasher(
+      simple_archiver_hash_default_fn);
+}
+
+SDArchiverHashMap *simple_archiver_hash_map_init_custom_hasher(
+    uint64_t (*hash_fn)(const void *, size_t)) {
   SDArchiverHashMap *hash_map = malloc(sizeof(SDArchiverHashMap));
+  hash_map->hash_fn = hash_fn;
   hash_map->buckets_size = SC_SA_DS_HASH_MAP_START_BUCKET_SIZE;
   // Pointers have the same size (at least on the same machine), so
   // sizeof(void*) should be ok.
@@ -193,8 +200,7 @@ int simple_archiver_hash_map_insert(SDArchiverHashMap *hash_map, void *value,
   data->value_cleanup_fn = value_cleanup_fn;
   data->key_cleanup_fn = key_cleanup_fn;
 
-  uint64_t hash = simple_archiver_hash_map_internal_key_to_hash(key, key_size) %
-                  hash_map->buckets_size;
+  uint64_t hash = hash_map->hash_fn(key, key_size) % hash_map->buckets_size;
   int result = simple_archiver_list_add_front(
       hash_map->buckets[hash], data,
       simple_archiver_hash_map_internal_cleanup_data);
@@ -225,8 +231,7 @@ int simple_archiver_hash_map_insert(SDArchiverHashMap *hash_map, void *value,
 
 void *simple_archiver_hash_map_get(const SDArchiverHashMap *hash_map,
                                    const void *key, size_t key_size) {
-  uint64_t hash = simple_archiver_hash_map_internal_key_to_hash(key, key_size) %
-                  hash_map->buckets_size;
+  uint64_t hash = hash_map->hash_fn(key, key_size) % hash_map->buckets_size;
 
   SDArchiverLLNode *node = hash_map->buckets[hash]->head;
   while (node) {
@@ -244,8 +249,7 @@ void *simple_archiver_hash_map_get(const SDArchiverHashMap *hash_map,
 
 int simple_archiver_hash_map_remove(SDArchiverHashMap *hash_map, void *key,
                                     size_t key_size) {
-  uint64_t hash = simple_archiver_hash_map_internal_key_to_hash(key, key_size) %
-                  hash_map->buckets_size;
+  uint64_t hash = hash_map->hash_fn(key, key_size) % hash_map->buckets_size;
 
   SDArchiverHashMapKeyData key_data;
   key_data.key = key;
index 22d91fe321c815058c65a08191b115133efdecf6..4fe302f60f09b569ad4145eda8c8c0d3e61ae299 100644 (file)
@@ -32,10 +32,21 @@ typedef struct SDArchiverHashMap {
   SDArchiverLinkedList **buckets;
   size_t buckets_size;
   size_t count;
+  uint64_t (*hash_fn)(const void *, size_t);
 } SDArchiverHashMap;
 
+uint64_t simple_archiver_hash_default_fn(const void *key, size_t key_size);
+
 SDArchiverHashMap *simple_archiver_hash_map_init(void);
 
+/// Creates a hash map that will use the custom hash function instead of the
+/// default. Note that the hash function must return a 64-bit unsigned integer
+/// as specified by the function's api. The first parameter of hash_fn is a
+/// pointer to the key to be hashed, and the second parameter is the size of
+/// the key in bytes.
+SDArchiverHashMap *simple_archiver_hash_map_init_custom_hasher(
+    uint64_t (*hash_fn)(const void *, size_t));
+
 /// It is recommended to use the double-pointer version of hash-map free as
 /// that will ensure the variable holding the pointer will end up pointing to
 /// NULL after free.