From 414b8d47befb2200f2501e964bbf90b4756aa2f7 Mon Sep 17 00:00:00 2001 From: Jordan Bancino Date: Tue, 11 Oct 2022 09:27:34 -0400 Subject: [PATCH] Add HashMapFunctionSet() to allow custom hash functions. --- TODO.txt | 3 ++- man/man3/HashMap.3 | 12 +++++++++++- src/HashMap.c | 20 ++++++++++++++++---- src/include/HashMap.h | 3 +++ 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/TODO.txt b/TODO.txt index 52a1766..04bc7c4 100644 --- a/TODO.txt +++ b/TODO.txt @@ -23,7 +23,7 @@ Phase 2: Building a foundation [x] Implement an array [x] Implement a logging facility [x] Implement a hash map - [ ] Allow custom hash functions for each hash map + [x] Allow custom hash functions for each hash map [x] Combine library code files [x] Implement configuration file parsing using hash map [x] Base64 encoding/decoding with padded/unpadded support @@ -55,6 +55,7 @@ Phase 2: Building a foundation [x] Properly implement the command line options as stated in telodendria(8) [ ] Remove "chroot" option, just chroot into the data dir, and make the log file live there as well. +[ ] Allow logging to the syslog Phase 3: Welcome to Matrix diff --git a/man/man3/HashMap.3 b/man/man3/HashMap.3 index 03a83f1..9aefe39 100644 --- a/man/man3/HashMap.3 +++ b/man/man3/HashMap.3 @@ -1,4 +1,4 @@ -.Dd $Mdocdate: October 10 2022 $ +.Dd $Mdocdate: October 11 2022 $ .Dt HASHMAP 3 .Os Telodendria Project .Sh NAME @@ -12,6 +12,8 @@ .Fn HashMapFree "HashMap *" .Ft void .Fn HashMapLoadSet "HashMap *" "float" +.Ft void +.Fn HashMapFunctionSet "HashMap *" "unsigned long (*) (const char *)" .Ft void * .Fn HashMapSet "HashMap *" "char *" "void *" .Ft void * @@ -63,6 +65,14 @@ object is 0.75, which should be good enough for most purposes, but if you need finer tuning, feel free to play with the max load with this function. The changes take effect on the next insert. .Pp +.Fn HashMapFunctionSet +allows the given hash map to use a custom hashing function. New hash +maps have a sane hashing function that should work okay for most use +cases, but if you have a better hash function, it can be specified with +this function. Do not change the hash function after keys have been +added; doing so results in undefined behavior. Only set the hash +function immediately after constructing a new hash map. +.Pp .Fn HashMapSet sets the given string key to the given value. Note neither the key nor the value is copied into the hash map's own memory space; only pointers are diff --git a/src/HashMap.c b/src/HashMap.c index 1af9c00..4a062c3 100644 --- a/src/HashMap.c +++ b/src/HashMap.c @@ -39,6 +39,8 @@ struct HashMap size_t capacity; HashMapBucket **entries; + unsigned long (*hashFunc) (const char *); + float maxLoad; size_t iterator; }; @@ -60,7 +62,6 @@ HashMapHashKey(const char *key) return hash; } - static int HashMapGrow(HashMap * map) { @@ -136,6 +137,7 @@ HashMapCreate(void) map->count = 0; map->capacity = 16; map->iterator = 0; + map->hashFunc = HashMapHashKey; map->entries = calloc(map->capacity, sizeof(HashMapBucket *)); if (!map->entries) @@ -158,7 +160,7 @@ HashMapDelete(HashMap * map, const char *key) return NULL; } - hash = HashMapHashKey(key); + hash = map->hashFunc(key); index = hash % map->capacity; for (;;) @@ -212,7 +214,7 @@ HashMapGet(HashMap * map, const char *key) return NULL; } - hash = HashMapHashKey(key); + hash = map->hashFunc(key); index = hash % map->capacity; for (;;) @@ -280,6 +282,16 @@ HashMapMaxLoadSet(HashMap * map, float load) map->maxLoad = load; } +void +HashMapFunctionSet(HashMap * map, unsigned long (*hashFunc) (const char *)) +{ + if (!map || !hashFunc) + { + return; + } + + map->hashFunc = hashFunc; +} void * HashMapSet(HashMap * map, char *key, void *value) @@ -297,7 +309,7 @@ HashMapSet(HashMap * map, char *key, void *value) HashMapGrow(map); } - hash = HashMapHashKey(key); + hash = map->hashFunc(key); index = hash % map->capacity; for (;;) diff --git a/src/include/HashMap.h b/src/include/HashMap.h index 4fcf92f..89a0461 100644 --- a/src/include/HashMap.h +++ b/src/include/HashMap.h @@ -33,6 +33,9 @@ extern HashMap * extern void HashMapMaxLoadSet(HashMap *, float); +extern void +HashMapFunctionSet(HashMap *, unsigned long (*) (const char *)); + extern void * HashMapSet(HashMap *, char *, void *);