Thanks to Justin Guyett for making the hashmap_insert() function use a

constant time insert.  Explanation: new enteries are added to the _front_
of the chain, rather than search to the end.
This commit is contained in:
Robert James Kaes 2002-05-13 20:02:23 +00:00
parent 73e3b495e0
commit 16e96c79e8
2 changed files with 19 additions and 28 deletions

View File

@ -5,6 +5,8 @@
(hashmap_remove): Fixed a problem where an entry could have it's (hashmap_remove): Fixed a problem where an entry could have it's
"prev" pointer still pointing at freed memory. Thanks to Justin "prev" pointer still pointing at freed memory. Thanks to Justin
Guyett for finding and fixing this problem. Guyett for finding and fixing this problem.
(hashmap_insert): Thanks to Justin Guyett for changing the code to
use a constant time insert. Much cleaner _and_ faster.
2002-05-10 Robert James Kaes <rjkaes@flarenet.com> 2002-05-10 Robert James Kaes <rjkaes@flarenet.com>

View File

@ -1,4 +1,4 @@
/* $Id: hashmap.c,v 1.8 2002-05-13 18:47:46 rjkaes Exp $ /* $Id: hashmap.c,v 1.9 2002-05-13 20:02:23 rjkaes Exp $
* *
* A hashmap implementation. The keys are case-insensitive NULL terminated * A hashmap implementation. The keys are case-insensitive NULL terminated
* strings, and the data is arbitrary lumps of data. Copies of both the * strings, and the data is arbitrary lumps of data. Copies of both the
@ -185,7 +185,7 @@ int
hashmap_insert(hashmap_t map, const char *key, hashmap_insert(hashmap_t map, const char *key,
const void *data, size_t len) const void *data, size_t len)
{ {
struct hashentry_s *ptr, *prevptr; struct hashentry_s *ptr;
int hash; int hash;
char *key_copy; char *key_copy;
void *data_copy; void *data_copy;
@ -223,40 +223,29 @@ hashmap_insert(hashmap_t map, const char *key,
data_copy = NULL; data_copy = NULL;
} }
ptr = map->buckets[hash]; ptr = safemalloc(sizeof(struct hashentry_s));
if (ptr) { if (!ptr) {
/* There is already an entry, so tack onto the end */ safefree(key_copy);
while (ptr) { safefree(data_copy);
prevptr = ptr; return -ENOMEM;
ptr = ptr->next;
}
ptr = safecalloc(1, sizeof(struct hashentry_s));
if (!ptr)
goto MEM_ERROR_EXIT;
ptr->prev = prevptr;
ptr->next = NULL;
prevptr->next = ptr;
} else {
ptr = map->buckets[hash] = safecalloc(1, sizeof(struct hashentry_s));
if (!ptr)
goto MEM_ERROR_EXIT;
ptr->next = ptr->prev = NULL;
} }
ptr->key = key_copy; ptr->key = key_copy;
ptr->data = data_copy; ptr->data = data_copy;
ptr->len = len; ptr->len = len;
/*
* Put the entry at the beginning of the chain. This is a constant
* time insert. Thanks to Justin Guyett for the code.
*/
ptr->prev = NULL;
ptr->next = map->buckets[hash];
map->buckets[hash] = ptr;
if (ptr->next)
ptr->next->prev = ptr;
map->end_iterator++; map->end_iterator++;
return 0; return 0;
MEM_ERROR_EXIT:
safefree(key_copy);
safefree(data_copy);
return -ENOMEM;
} }
/* /*