From ec35c1ba09b8eb49505d32d23a2b679be3c45add Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Tue, 19 Jan 2010 15:39:13 -0800 Subject: [PATCH] Added full support for custom hash functions. --- libhashkit/algorithm.h | 61 +++++++++++++++++++++++++++++++------- libhashkit/crc32.c | 2 +- libhashkit/fnv.c | 8 ++--- libhashkit/hashkit.c | 22 +++++++------- libhashkit/hsieh.c | 2 +- libhashkit/include.am | 3 +- libhashkit/jenkins.c | 2 +- libhashkit/md5.c | 2 +- libhashkit/murmur.c | 2 +- libhashkit/one_at_a_time.c | 2 +- libhashkit/types.h | 2 +- tests/hashkit_functions.c | 28 ++++++++++------- 12 files changed, 92 insertions(+), 44 deletions(-) diff --git a/libhashkit/algorithm.h b/libhashkit/algorithm.h index f575222e..465d0b5d 100644 --- a/libhashkit/algorithm.h +++ b/libhashkit/algorithm.h @@ -19,27 +19,68 @@ extern "C" { #endif HASHKIT_API -uint32_t hashkit_one_at_a_time(const char *key, size_t key_length); +uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length); + HASHKIT_API -uint32_t hashkit_fnv1_64(const char *key, size_t key_length); +uint32_t libhashkit_fnv1_64(const char *key, size_t key_length); + HASHKIT_API -uint32_t hashkit_fnv1a_64(const char *key, size_t key_length); +uint32_t libhashkit_fnv1a_64(const char *key, size_t key_length); + HASHKIT_API -uint32_t hashkit_fnv1_32(const char *key, size_t key_length); +uint32_t libhashkit_fnv1_32(const char *key, size_t key_length); + HASHKIT_API -uint32_t hashkit_fnv1a_32(const char *key, size_t key_length); +uint32_t libhashkit_fnv1a_32(const char *key, size_t key_length); + HASHKIT_API -uint32_t hashkit_crc32(const char *key, size_t key_length); +uint32_t libhashkit_crc32(const char *key, size_t key_length); + #ifdef HAVE_HSIEH_HASH HASHKIT_API -uint32_t hashkit_hsieh(const char *key, size_t key_length); +uint32_t libhashkit_hsieh(const char *key, size_t key_length); #endif + HASHKIT_API -uint32_t hashkit_murmur(const char *key, size_t key_length); +uint32_t libhashkit_murmur(const char *key, size_t key_length); + HASHKIT_API -uint32_t hashkit_jenkins(const char *key, size_t key_length); +uint32_t libhashkit_jenkins(const char *key, size_t key_length); + HASHKIT_API -uint32_t hashkit_md5(const char *key, size_t key_length); +uint32_t libhashkit_md5(const char *key, size_t key_length); + +HASHKIT_LOCAL +uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context); + +HASHKIT_LOCAL +uint32_t hashkit_fnv1_64(const char *key, size_t key_length, void *context); + +HASHKIT_LOCAL +uint32_t hashkit_fnv1a_64(const char *key, size_t key_length, void *context); + +HASHKIT_LOCAL +uint32_t hashkit_fnv1_32(const char *key, size_t key_length, void *context); + +HASHKIT_LOCAL +uint32_t hashkit_fnv1a_32(const char *key, size_t key_length, void *context); + +HASHKIT_LOCAL +uint32_t hashkit_crc32(const char *key, size_t key_length, void *context); + +#ifdef HAVE_HSIEH_HASH +HASHKIT_LOCAL +uint32_t hashkit_hsieh(const char *key, size_t key_length, void *context); +#endif + +HASHKIT_LOCAL +uint32_t hashkit_murmur(const char *key, size_t key_length, void *context); + +HASHKIT_LOCAL +uint32_t hashkit_jenkins(const char *key, size_t key_length, void *context); + +HASHKIT_LOCAL +uint32_t hashkit_md5(const char *key, size_t key_length, void *context); #ifdef __cplusplus } diff --git a/libhashkit/crc32.c b/libhashkit/crc32.c index 023abbb6..6db04783 100644 --- a/libhashkit/crc32.c +++ b/libhashkit/crc32.c @@ -73,7 +73,7 @@ static const uint32_t crc32tab[256] = { 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, }; -uint32_t hashkit_crc32(const char *key, size_t key_length) +uint32_t hashkit_crc32(const char *key, size_t key_length, void *context __attribute__((unused))) { uint64_t x; uint32_t crc= UINT32_MAX; diff --git a/libhashkit/fnv.c b/libhashkit/fnv.c index c4ad0668..ee3754d8 100644 --- a/libhashkit/fnv.c +++ b/libhashkit/fnv.c @@ -14,7 +14,7 @@ static uint64_t FNV_64_PRIME= UINT64_C(0x100000001b3); static uint32_t FNV_32_INIT= 2166136261UL; static uint32_t FNV_32_PRIME= 16777619; -uint32_t hashkit_fnv1_64(const char *key, size_t key_length) +uint32_t hashkit_fnv1_64(const char *key, size_t key_length, void *context __attribute__((unused))) { /* Thanks to pierre@demartines.com for the pointer */ uint64_t hash= FNV_64_INIT; @@ -28,7 +28,7 @@ uint32_t hashkit_fnv1_64(const char *key, size_t key_length) return (uint32_t)hash; } -uint32_t hashkit_fnv1a_64(const char *key, size_t key_length) +uint32_t hashkit_fnv1a_64(const char *key, size_t key_length, void *context __attribute__((unused))) { uint32_t hash= (uint32_t) FNV_64_INIT; @@ -42,7 +42,7 @@ uint32_t hashkit_fnv1a_64(const char *key, size_t key_length) return hash; } -uint32_t hashkit_fnv1_32(const char *key, size_t key_length) +uint32_t hashkit_fnv1_32(const char *key, size_t key_length, void *context __attribute__((unused))) { uint32_t hash= FNV_32_INIT; @@ -56,7 +56,7 @@ uint32_t hashkit_fnv1_32(const char *key, size_t key_length) return hash; } -uint32_t hashkit_fnv1a_32(const char *key, size_t key_length) +uint32_t hashkit_fnv1a_32(const char *key, size_t key_length, void *context __attribute__((unused))) { uint32_t hash= FNV_32_INIT; diff --git a/libhashkit/hashkit.c b/libhashkit/hashkit.c index 64158f98..cd33c4e7 100644 --- a/libhashkit/hashkit.c +++ b/libhashkit/hashkit.c @@ -76,7 +76,7 @@ hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *source) uint32_t hashkit_generate_value(const hashkit_st *self, const char *key, size_t key_length) { - return self->base_hash.function(key, key_length); + return self->base_hash.function(key, key_length, self->base_hash.context); } hashkit_return_t hashkit_set_base_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm) @@ -146,29 +146,29 @@ uint32_t libhashkit_generate_value(const char *key, size_t key_length, hashkit_h switch (hash_algorithm) { case HASHKIT_HASH_DEFAULT: - return hashkit_one_at_a_time(key, key_length); + return libhashkit_one_at_a_time(key, key_length); case HASHKIT_HASH_MD5: - return hashkit_md5(key, key_length); + return libhashkit_md5(key, key_length); case HASHKIT_HASH_CRC: - return hashkit_crc32(key, key_length); + return libhashkit_crc32(key, key_length); case HASHKIT_HASH_FNV1_64: - return hashkit_fnv1_64(key, key_length); + return libhashkit_fnv1_64(key, key_length); case HASHKIT_HASH_FNV1A_64: - return hashkit_fnv1a_64(key, key_length); + return libhashkit_fnv1a_64(key, key_length); case HASHKIT_HASH_FNV1_32: - return hashkit_fnv1_32(key, key_length); + return libhashkit_fnv1_32(key, key_length); case HASHKIT_HASH_FNV1A_32: - return hashkit_fnv1a_32(key, key_length); + return libhashkit_fnv1a_32(key, key_length); case HASHKIT_HASH_HSIEH: #ifdef HAVE_HSIEH_HASH - return hashkit_hsieh(key, key_length); + return libhashkit_hsieh(key, key_length); #else return 1; #endif case HASHKIT_HASH_MURMUR: - return hashkit_murmur(key, key_length); + return libhashkit_murmur(key, key_length); case HASHKIT_HASH_JENKINS: - return hashkit_jenkins(key, key_length); + return libhashkit_jenkins(key, key_length); case HASHKIT_HASH_MAX: default: #ifdef HAVE_DEBUG diff --git a/libhashkit/hsieh.c b/libhashkit/hsieh.c index 9060bba0..46cc241e 100644 --- a/libhashkit/hsieh.c +++ b/libhashkit/hsieh.c @@ -17,7 +17,7 @@ +(uint32_t)(((const uint8_t *)(d))[0]) ) #endif -uint32_t hashkit_hsieh(const char *key, size_t key_length) +uint32_t hashkit_hsieh(const char *key, size_t key_length, void *context__attribute__((unused))) { uint32_t hash = 0, tmp; int rem; diff --git a/libhashkit/include.am b/libhashkit/include.am index f8aa79f5..7bcd7801 100644 --- a/libhashkit/include.am +++ b/libhashkit/include.am @@ -23,8 +23,9 @@ noinst_HEADERS+= \ libhashkit/common.h libhashkit_libhashkit_la_SOURCES= \ - libhashkit/crc32.c \ + libhashkit/algorithm.c \ libhashkit/behavior.c \ + libhashkit/crc32.c \ libhashkit/fnv.c \ libhashkit/hashkit.c \ libhashkit/jenkins.c \ diff --git a/libhashkit/jenkins.c b/libhashkit/jenkins.c index 29d9454e..b684d7a0 100644 --- a/libhashkit/jenkins.c +++ b/libhashkit/jenkins.c @@ -56,7 +56,7 @@ use a bitmask. For example, if you need only 10 bits, do In which case, the hash table should have hashsize(10) elements. */ -uint32_t hashkit_jenkins(const char *key, size_t length) +uint32_t hashkit_jenkins(const char *key, size_t length, void *context __attribute__((unused))) { uint32_t a,b,c; /* internal state */ union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ diff --git a/libhashkit/md5.c b/libhashkit/md5.c index d550c773..a968548d 100644 --- a/libhashkit/md5.c +++ b/libhashkit/md5.c @@ -352,7 +352,7 @@ unsigned int len) (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); } -uint32_t hashkit_md5(const char *key, size_t key_length) +uint32_t hashkit_md5(const char *key, size_t key_length, void *context __attribute__((unused))) { unsigned char results[16]; diff --git a/libhashkit/murmur.c b/libhashkit/murmur.c index cd5e6419..a18ac403 100644 --- a/libhashkit/murmur.c +++ b/libhashkit/murmur.c @@ -17,7 +17,7 @@ #include "common.h" -uint32_t hashkit_murmur(const char *key, size_t length) +uint32_t hashkit_murmur(const char *key, size_t length, void *context __attribute__((unused))) { /* 'm' and 'r' are mixing constants generated offline. They're not diff --git a/libhashkit/one_at_a_time.c b/libhashkit/one_at_a_time.c index ab106f1d..579d0445 100644 --- a/libhashkit/one_at_a_time.c +++ b/libhashkit/one_at_a_time.c @@ -13,7 +13,7 @@ http://en.wikipedia.org/wiki/Jenkins_hash_function #include "common.h" -uint32_t hashkit_one_at_a_time(const char *key, size_t key_length) +uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context __attribute__((unused))) { const char *ptr= key; uint32_t value= 0; diff --git a/libhashkit/types.h b/libhashkit/types.h index fadb4d93..b3ea7346 100644 --- a/libhashkit/types.h +++ b/libhashkit/types.h @@ -48,7 +48,7 @@ typedef enum typedef struct hashkit_st hashkit_st; -typedef uint32_t (*hashkit_hash_fn)(const char *key, size_t key_length); +typedef uint32_t (*hashkit_hash_fn)(const char *key, size_t key_length, void *context); #ifdef __cplusplus } diff --git a/tests/hashkit_functions.c b/tests/hashkit_functions.c index 0e4a894d..d97b40c8 100644 --- a/tests/hashkit_functions.c +++ b/tests/hashkit_functions.c @@ -122,7 +122,7 @@ static test_return_t one_at_a_time_run (hashkit_st *hashk __attribute__((unused) { uint32_t hash_val; - hash_val= hashkit_one_at_a_time(*ptr, strlen(*ptr)); + hash_val= libhashkit_one_at_a_time(*ptr, strlen(*ptr)); test_true(one_at_a_time_values[x] == hash_val); } @@ -138,7 +138,7 @@ static test_return_t md5_run (hashkit_st *hashk __attribute__((unused))) { uint32_t hash_val; - hash_val= hashkit_md5(*ptr, strlen(*ptr)); + hash_val= libhashkit_md5(*ptr, strlen(*ptr)); test_true(md5_values[x] == hash_val); } @@ -154,7 +154,7 @@ static test_return_t crc_run (hashkit_st *hashk __attribute__((unused))) { uint32_t hash_val; - hash_val= hashkit_crc32(*ptr, strlen(*ptr)); + hash_val= libhashkit_crc32(*ptr, strlen(*ptr)); assert(crc_values[x] == hash_val); } @@ -170,7 +170,7 @@ static test_return_t fnv1_64_run (hashkit_st *hashk __attribute__((unused))) { uint32_t hash_val; - hash_val= hashkit_fnv1_64(*ptr, strlen(*ptr)); + hash_val= libhashkit_fnv1_64(*ptr, strlen(*ptr)); assert(fnv1_64_values[x] == hash_val); } @@ -186,7 +186,7 @@ static test_return_t fnv1a_64_run (hashkit_st *hashk __attribute__((unused))) { uint32_t hash_val; - hash_val= hashkit_fnv1a_64(*ptr, strlen(*ptr)); + hash_val= libhashkit_fnv1a_64(*ptr, strlen(*ptr)); assert(fnv1a_64_values[x] == hash_val); } @@ -203,7 +203,7 @@ static test_return_t fnv1_32_run (hashkit_st *hashk __attribute__((unused))) { uint32_t hash_val; - hash_val= hashkit_fnv1_32(*ptr, strlen(*ptr)); + hash_val= libhashkit_fnv1_32(*ptr, strlen(*ptr)); assert(fnv1_32_values[x] == hash_val); } @@ -219,7 +219,7 @@ static test_return_t fnv1a_32_run (hashkit_st *hashk __attribute__((unused))) { uint32_t hash_val; - hash_val= hashkit_fnv1a_32(*ptr, strlen(*ptr)); + hash_val= libhashkit_fnv1a_32(*ptr, strlen(*ptr)); assert(fnv1a_32_values[x] == hash_val); } @@ -236,7 +236,7 @@ static test_return_t hsieh_run (hashkit_st *hashk __attribute__((unused))) uint32_t hash_val; #ifdef HAVE_HSIEH_HASH - hash_val= hashkit_hsieh(*ptr, strlen(*ptr)); + hash_val= libhashkit_hsieh(*ptr, strlen(*ptr)); #else hash_val= 1; #endif @@ -258,7 +258,7 @@ static test_return_t murmur_run (hashkit_st *hashk __attribute__((unused))) { uint32_t hash_val; - hash_val= hashkit_murmur(*ptr, strlen(*ptr)); + hash_val= libhashkit_murmur(*ptr, strlen(*ptr)); assert(murmur_values[x] == hash_val); } @@ -276,7 +276,7 @@ static test_return_t jenkins_run (hashkit_st *hashk __attribute__((unused))) { uint32_t hash_val; - hash_val= hashkit_jenkins(*ptr, strlen(*ptr)); + hash_val= libhashkit_jenkins(*ptr, strlen(*ptr)); assert(jenkins_values[x] == hash_val); } @@ -373,6 +373,12 @@ static test_return_t hashkit_set_base_function_test(hashkit_st *hashk) return TEST_SUCCESS; } +static uint32_t hash_test_function(const char *string, size_t string_length, void *context) +{ + (void)context; + return libhashkit_md5(string, string_length); +} + static test_return_t hashkit_set_base_function_custom_test(hashkit_st *hashk) { hashkit_return_t rc; @@ -380,7 +386,7 @@ static test_return_t hashkit_set_base_function_custom_test(hashkit_st *hashk) const char **ptr; - rc= hashkit_set_base_function_custom(hashk, hashkit_md5, NULL); + rc= hashkit_set_base_function_custom(hashk, hash_test_function, NULL); test_true(rc == HASHKIT_SUCCESS); for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) -- 2.30.2