From: Urban Wallasch Date: Sun, 3 Nov 2019 21:36:29 +0000 (+0100) Subject: * dict: added dict_resize(); fixed hash type X-Git-Url: https://git.packet-gain.de/?a=commitdiff_plain;h=cbd85e86d14bc9c71ccd43b8caba0dcdd41ca3b8;p=oddbits.git * dict: added dict_resize(); fixed hash type --- diff --git a/dict/dict.c b/dict/dict.c index 94056ce..a1c4c1e 100644 --- a/dict/dict.c +++ b/dict/dict.c @@ -53,7 +53,7 @@ static inline void *mem_dup(const void *src, size_t n) { /* Jenkins's one_at_a_time hash; used to compute hash table index: */ -static inline int dict_hash(const char *key) { +static inline uint32_t dict_hash(const char *key) { size_t len = strlen(key); uint32_t hash = 0; @@ -83,7 +83,7 @@ static inline int dict_makeentry(dict_t *d, const char *key, const void *data, s dict_entry_t *e; char *k; void *v; - unsigned h; + uint32_t h; e = malloc(sizeof *e); if (!e) @@ -137,6 +137,37 @@ dict_t *dict_new(size_t ht_size) { return d; } +/* Resize dictionary hash table: */ +int dict_resize(dict_t *d, size_t newsize) { + dict_entry_t **newht; + + if (!d || !newsize) { + errno = EINVAL; + return -1; + } + if (newsize == d->htsz) + return 0; + newht = malloc(newsize * sizeof *newht); + if (!newht) + return -1; + for (size_t i = 0; i < newsize; ++i ) + newht[i] = NULL; + for (size_t i = 0; i < d->htsz; ++i ) { + uint32_t h; + dict_entry_t *next, *e; + for (e = d->ht[i]; e; e = next) { + h = dict_hash(e->key) % newsize; + next = e->next; + e->next = newht[h]; + newht[h] = e; + } + } + free(d->ht); + d->ht = newht; + d->htsz = newsize; + return 0; +} + /* Delete existing dictionary: */ int dict_delete(dict_t *d) { if (!d) diff --git a/dict/dict.h b/dict/dict.h index 9f507e2..cdadc74 100644 --- a/dict/dict.h +++ b/dict/dict.h @@ -39,6 +39,13 @@ typedef */ dict_t *dict_new(size_t ht_size); +/* + * Resize dictionary hash table. + * + * Returns 0 on success, or -1 on error. + */ +int dict_resize(dict_t *d, size_t newsize); + /* * Delete a dictionary previously created with dict_new() and release * all resources associated with it. diff --git a/dict/dict_test.c b/dict/dict_test.c index 25567b7..a742787 100644 --- a/dict/dict_test.c +++ b/dict/dict_test.c @@ -52,7 +52,7 @@ int main(void) { assert( dict_remove(d, "foo") == 0 ); assert( dict_delete(d) == 0 ); - d = dict_new(2048); + d = dict_new(20480); assert(d != NULL); for (unsigned i = 0; i < 300000; ++i) { char k[100], s[100]; @@ -63,15 +63,21 @@ int main(void) { cnt = 0; assert( dict_foreach( d, dump_cb, &cnt) == 0); dict_stat(d); + + assert( dict_resize(d, 300000) == 0 ); + dict_stat(d); + + assert( dict_resize(d, 4096) == 0 ); + dict_stat(d); + for (unsigned i = 0; i < 300000; ++i) { char k[100]; sprintf(k, "%u %x", i, i); - dict_remove(d, k); + assert( dict_remove(d, k) == 0 ); } assert(dict_count(d) == 0); - cnt = 0; - assert( dict_foreach( d, dump_cb, &cnt) == 0); dict_stat(d); + assert( dict_delete(d) == 0 ); return 0;