1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

Extend hash functions to handle non-null-terminated data.

This commit is contained in:
Alasdair Kergon 2004-06-18 15:08:22 +00:00
parent b86ef8e2cb
commit 374df1cf8e
3 changed files with 49 additions and 22 deletions

View File

@ -1,5 +1,6 @@
Version 2.00.17 - Version 2.00.17 -
============================= =============================
Extend hash functions to handle non-null-terminated data.
Add local activation support. Add local activation support.
Tidy relative paths in makefile includes. Tidy relative paths in makefile includes.
fsadm support for fsck and resizing - needs testing. fsadm support for fsck and resizing - needs testing.

View File

@ -19,7 +19,8 @@
struct hash_node { struct hash_node {
struct hash_node *next; struct hash_node *next;
void *data; void *data;
char key[1]; int keylen;
char key[0];
}; };
struct hash_table { struct hash_table {
@ -56,22 +57,23 @@ static unsigned char _nums[] = {
209 209
}; };
static struct hash_node *_create_node(const char *str) static struct hash_node *_create_node(const char *str, int len)
{ {
/* remember sizeof(n) includes an extra char from key[1], struct hash_node *n = dbg_malloc(sizeof(*n) + len);
so not adding 1 to the strlen as you would expect */
struct hash_node *n = dbg_malloc(sizeof(*n) + strlen(str));
if (n) if (n) {
strcpy(n->key, str); memcpy(n->key, str, len);
n->keylen = len;
}
return n; return n;
} }
static unsigned _hash(const char *str) static unsigned _hash(const char *str, uint32_t len)
{ {
unsigned long h = 0, g; unsigned long h = 0, g, i;
while (*str) {
for (i = 0; i < len; i++) {
h <<= 4; h <<= 4;
h += _nums[(int) *str++]; h += _nums[(int) *str++];
g = h & ((unsigned long) 0xf << 16u); g = h & ((unsigned long) 0xf << 16u);
@ -80,6 +82,7 @@ static unsigned _hash(const char *str)
h ^= g >> 5u; h ^= g >> 5u;
} }
} }
return h; return h;
} }
@ -134,32 +137,35 @@ void hash_destroy(struct hash_table *t)
dbg_free(t); dbg_free(t);
} }
static struct hash_node **_find(struct hash_table *t, const char *key) static inline struct hash_node **_find(struct hash_table *t, const char *key,
uint32_t len)
{ {
unsigned h = _hash(key) & (t->num_slots - 1); unsigned h = _hash(key, len) & (t->num_slots - 1);
struct hash_node **c; struct hash_node **c;
for (c = &t->slots[h]; *c; c = &((*c)->next)) for (c = &t->slots[h]; *c; c = &((*c)->next))
if (!strcmp(key, (*c)->key)) if (!memcmp(key, (*c)->key, len))
break; break;
return c; return c;
} }
void *hash_lookup(struct hash_table *t, const char *key) void *hash_lookup_binary(struct hash_table *t, const char *key,
uint32_t len)
{ {
struct hash_node **c = _find(t, key); struct hash_node **c = _find(t, key, len);
return *c ? (*c)->data : 0; return *c ? (*c)->data : 0;
} }
int hash_insert(struct hash_table *t, const char *key, void *data) int hash_insert_binary(struct hash_table *t, const char *key,
uint32_t len, void *data)
{ {
struct hash_node **c = _find(t, key); struct hash_node **c = _find(t, key, len);
if (*c) if (*c)
(*c)->data = data; (*c)->data = data;
else { else {
struct hash_node *n = _create_node(key); struct hash_node *n = _create_node(key, len);
if (!n) if (!n)
return 0; return 0;
@ -173,9 +179,10 @@ int hash_insert(struct hash_table *t, const char *key, void *data)
return 1; return 1;
} }
void hash_remove(struct hash_table *t, const char *key) void hash_remove_binary(struct hash_table *t, const char *key,
uint32_t len)
{ {
struct hash_node **c = _find(t, key); struct hash_node **c = _find(t, key, len);
if (*c) { if (*c) {
struct hash_node *old = *c; struct hash_node *old = *c;
@ -185,6 +192,21 @@ void hash_remove(struct hash_table *t, const char *key)
} }
} }
void *hash_lookup(struct hash_table *t, const char *key)
{
return hash_lookup_binary(t, key, strlen(key) + 1);
}
int hash_insert(struct hash_table *t, const char *key, void *data)
{
return hash_insert_binary(t, key, strlen(key) + 1, data);
}
void hash_remove(struct hash_table *t, const char *key)
{
hash_remove_binary(t, key, strlen(key) + 1);
}
unsigned hash_get_num_entries(struct hash_table *t) unsigned hash_get_num_entries(struct hash_table *t)
{ {
return t->num_nodes; return t->num_nodes;
@ -235,6 +257,6 @@ struct hash_node *hash_get_first(struct hash_table *t)
struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n) struct hash_node *hash_get_next(struct hash_table *t, struct hash_node *n)
{ {
unsigned h = _hash(n->key) & (t->num_slots - 1); unsigned h = _hash(n->key, n->keylen) & (t->num_slots - 1);
return n->next ? n->next : _next_slot(t, h + 1); return n->next ? n->next : _next_slot(t, h + 1);
} }

View File

@ -26,10 +26,14 @@ void hash_destroy(struct hash_table *t);
void hash_wipe(struct hash_table *t); void hash_wipe(struct hash_table *t);
void *hash_lookup(struct hash_table *t, const char *key); void *hash_lookup(struct hash_table *t, const char *key);
void *hash_lookup_fixed(struct hash_table *t, const char *key, uint32_t len);
int hash_insert(struct hash_table *t, const char *key, void *data); int hash_insert(struct hash_table *t, const char *key, void *data);
void hash_remove(struct hash_table *t, const char *key); void hash_remove(struct hash_table *t, const char *key);
void *hash_lookup_binary(struct hash_table *t, const char *key, uint32_t len);
int hash_insert_binary(struct hash_table *t, const char *key, uint32_t len,
void *data);
void hash_remove_binary(struct hash_table *t, const char *key, uint32_t len);
unsigned hash_get_num_entries(struct hash_table *t); unsigned hash_get_num_entries(struct hash_table *t);
void hash_iter(struct hash_table *t, iterate_fn f); void hash_iter(struct hash_table *t, iterate_fn f);