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:
parent
73e3b495e0
commit
16e96c79e8
@ -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>
|
||||||
|
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user