Impl. way to set custom hasher for hash_map
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 8s

This commit is contained in:
Stephen Seo 2024-09-21 18:43:23 +09:00
parent 4a69d281de
commit 70415c6caf
2 changed files with 23 additions and 8 deletions

View file

@ -74,8 +74,7 @@ int simple_archiver_hash_map_internal_pick_in_list(void *data, void *ud) {
: 0; : 0;
} }
uint64_t simple_archiver_hash_map_internal_key_to_hash(const void *key, uint64_t simple_archiver_hash_default_fn(const void *key, size_t key_size) {
size_t key_size) {
uint64_t seed = 0; uint64_t seed = 0;
uint64_t temp = 0; uint64_t temp = 0;
size_t count = 0; size_t count = 0;
@ -106,6 +105,7 @@ int simple_archiver_hash_map_internal_rehash(SDArchiverHashMap *hash_map) {
return 1; return 1;
} }
SDArchiverHashMap new_hash_map; SDArchiverHashMap new_hash_map;
new_hash_map.hash_fn = hash_map->hash_fn;
new_hash_map.buckets_size = hash_map->buckets_size * 2; new_hash_map.buckets_size = hash_map->buckets_size * 2;
// Pointers have the same size (at least on the same machine), so // Pointers have the same size (at least on the same machine), so
// sizeof(void*) should be ok. // 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) { 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)); SDArchiverHashMap *hash_map = malloc(sizeof(SDArchiverHashMap));
hash_map->hash_fn = hash_fn;
hash_map->buckets_size = SC_SA_DS_HASH_MAP_START_BUCKET_SIZE; hash_map->buckets_size = SC_SA_DS_HASH_MAP_START_BUCKET_SIZE;
// Pointers have the same size (at least on the same machine), so // Pointers have the same size (at least on the same machine), so
// sizeof(void*) should be ok. // 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->value_cleanup_fn = value_cleanup_fn;
data->key_cleanup_fn = key_cleanup_fn; data->key_cleanup_fn = key_cleanup_fn;
uint64_t hash = simple_archiver_hash_map_internal_key_to_hash(key, key_size) % uint64_t hash = hash_map->hash_fn(key, key_size) % hash_map->buckets_size;
hash_map->buckets_size;
int result = simple_archiver_list_add_front( int result = simple_archiver_list_add_front(
hash_map->buckets[hash], data, hash_map->buckets[hash], data,
simple_archiver_hash_map_internal_cleanup_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, void *simple_archiver_hash_map_get(const SDArchiverHashMap *hash_map,
const void *key, size_t key_size) { const void *key, size_t key_size) {
uint64_t hash = simple_archiver_hash_map_internal_key_to_hash(key, key_size) % uint64_t hash = hash_map->hash_fn(key, key_size) % hash_map->buckets_size;
hash_map->buckets_size;
SDArchiverLLNode *node = hash_map->buckets[hash]->head; SDArchiverLLNode *node = hash_map->buckets[hash]->head;
while (node) { 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, int simple_archiver_hash_map_remove(SDArchiverHashMap *hash_map, void *key,
size_t key_size) { size_t key_size) {
uint64_t hash = simple_archiver_hash_map_internal_key_to_hash(key, key_size) % uint64_t hash = hash_map->hash_fn(key, key_size) % hash_map->buckets_size;
hash_map->buckets_size;
SDArchiverHashMapKeyData key_data; SDArchiverHashMapKeyData key_data;
key_data.key = key; key_data.key = key;

View file

@ -32,10 +32,21 @@ typedef struct SDArchiverHashMap {
SDArchiverLinkedList **buckets; SDArchiverLinkedList **buckets;
size_t buckets_size; size_t buckets_size;
size_t count; size_t count;
uint64_t (*hash_fn)(const void *, size_t);
} SDArchiverHashMap; } SDArchiverHashMap;
uint64_t simple_archiver_hash_default_fn(const void *key, size_t key_size);
SDArchiverHashMap *simple_archiver_hash_map_init(void); 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 /// 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 /// that will ensure the variable holding the pointer will end up pointing to
/// NULL after free. /// NULL after free.