summaryrefslogtreecommitdiff
path: root/src/common/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/hash.c')
-rw-r--r--src/common/hash.c53
1 files changed, 33 insertions, 20 deletions
diff --git a/src/common/hash.c b/src/common/hash.c
index eb48c88..789e85c 100644
--- a/src/common/hash.c
+++ b/src/common/hash.c
@@ -55,7 +55,7 @@
#include <stdlib.h>
#include "hash.h"
-#define KEY_DATA(he) (void*)(((unsigned char*)(he)) + sizeof(*(he)))
+#define KEY_DATA(he) ((he)->key)
/*
* The internal form of a hash table.
@@ -72,6 +72,8 @@ struct hsh_entry_t
{
hsh_entry_t* next;
unsigned int hash;
+ const void* key;
+ size_t klen;
const void* val;
};
@@ -103,25 +105,24 @@ struct hsh_t
hsh_index_t iterator; /* For hsh_first(...) */
unsigned int count;
unsigned int max;
- unsigned int klen;
};
#define INITIAL_MAX 15 /* tunable == 2^n - 1 */
#define int_malloc malloc
+#define int_calloc calloc
#define int_free free
-
/*
* Hash creation functions.
*/
static hsh_entry_t** alloc_array(hsh_t* ht, unsigned int max)
{
- return int_calloc(sizeof(*(ht->array)) * (max + 1));
+ return (hsh_entry_t**)int_calloc(sizeof(*(ht->array)), (max + 1));
}
-hsh_t* hsh_create(size_t klen)
+hsh_t* hsh_create()
{
hsh_t* ht = int_malloc(sizeof(hsh_t));
if(ht)
@@ -129,7 +130,6 @@ hsh_t* hsh_create(size_t klen)
ht->count = 0;
ht->max = INITIAL_MAX;
ht->array = alloc_array(ht, ht->max);
- ht->klen = klen;
if(!ht->array)
{
int_free(ht);
@@ -181,10 +181,12 @@ hsh_index_t* hsh_first(hsh_t* ht)
return hsh_next(hi);
}
-void* hsh_this(hsh_index_t* hi, const void** key)
+void* hsh_this(hsh_index_t* hi, const void** key, size_t* klen)
{
if(key)
*key = KEY_DATA(hi->ths);
+ if(klen)
+ *klen = hi->ths->klen;
return (void*)hi->ths->val;
}
@@ -229,7 +231,7 @@ static int expand_array(hsh_t* ht)
* that hash entries can be removed.
*/
-static hsh_entry_t** find_entry(hsh_t* ht, const void* key, const void* val)
+static hsh_entry_t** find_entry(hsh_t* ht, const void* key, size_t klen, const void* val)
{
hsh_entry_t** hep;
hsh_entry_t* he;
@@ -237,8 +239,6 @@ static hsh_entry_t** find_entry(hsh_t* ht, const void* key, const void* val)
unsigned int hash;
size_t i;
- size_t klen = ht->klen;
-
/*
* This is the popular `times 33' hash algorithm which is used by
* perl and also appears in Berkeley DB. This is one of the best
@@ -278,6 +278,14 @@ static hsh_entry_t** find_entry(hsh_t* ht, const void* key, const void* val)
*/
hash = 0;
+ if(klen == HSH_KEY_STRING)
+ {
+ for(p = key; *p; p++)
+ hash = hash * 33 + *p;
+
+ klen = p - (const unsigned char *)key;
+ }
+ else
{
for(p = key, i = klen; i; i--, p++)
hash = hash * 33 + *p;
@@ -288,6 +296,7 @@ static hsh_entry_t** find_entry(hsh_t* ht, const void* key, const void* val)
he; hep = &he->next, he = *hep)
{
if(he->hash == hash &&
+ he->klen == klen &&
memcmp(KEY_DATA(he), key, klen) == 0)
break;
}
@@ -296,15 +305,17 @@ static hsh_entry_t** find_entry(hsh_t* ht, const void* key, const void* val)
return hep;
/* add a new entry for non-NULL val */
- he = int_malloc(sizeof(*he) + klen);
+ he = int_malloc(sizeof(*he));
+
if(he)
{
- /* Key data points past end of entry */
- memcpy(KEY_DATA(he), key, klen);
+ /* Key points to external data */
+ he->key = key;
+ he->klen = klen;
he->next = NULL;
he->hash = hash;
- he->val = val;
+ he->val = val;
*hep = he;
ht->count++;
@@ -313,18 +324,19 @@ static hsh_entry_t** find_entry(hsh_t* ht, const void* key, const void* val)
return hep;
}
-void* hsh_get(hsh_t* ht, const void *key)
+void* hsh_get(hsh_t* ht, const void *key, size_t klen)
{
- hsh_entry_t** he = find_entry(ht, key, NULL);
+ hsh_entry_t** he = find_entry(ht, key, klen, NULL);
+
if(he && *he)
return (void*)((*he)->val);
else
return NULL;
}
-int hsh_set(hsh_t* ht, const void* key, void* val)
+int hsh_set(hsh_t* ht, const void* key, size_t klen, void* val)
{
- hsh_entry_t** hep = find_entry(ht, key, val);
+ hsh_entry_t** hep = find_entry(ht, key, klen, val);
if(hep && *hep)
{
@@ -344,9 +356,9 @@ int hsh_set(hsh_t* ht, const void* key, void* val)
return 0;
}
-void* hsh_rem(hsh_t* ht, const void* key)
+void* hsh_rem(hsh_t* ht, const void* key, size_t klen)
{
- hsh_entry_t** hep = find_entry(ht, key, NULL);
+ hsh_entry_t** hep = find_entry(ht, key, klen, NULL);
void* val = NULL;
if(hep && *hep)
@@ -365,3 +377,4 @@ unsigned int hsh_count(hsh_t* ht)
{
return ht->count;
}
+