* dict: added dict_resize(); fixed hash type
authorUrban Wallasch <urban.wallasch@freenet.de>
Sun, 3 Nov 2019 21:36:29 +0000 (22:36 +0100)
committerUrban Wallasch <urban.wallasch@freenet.de>
Sun, 3 Nov 2019 21:36:29 +0000 (22:36 +0100)
dict/dict.c
dict/dict.h
dict/dict_test.c

index 94056cedbb20425d0ff796acef46acae66ae7a4f..a1c4c1eaa676df9eca32eee7029acf8c9699084a 100644 (file)
@@ -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)
index 9f507e277c5be7573dc023684b608dd22fe80807..cdadc746d049f30ae6f10cb1605b579fd40e9678 100644 (file)
@@ -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.
index 25567b771abd9c267f5c763e413d9f965bad18f5..a74278790f8d729bcb5df34e3fcfac4aa03ad195 100644 (file)
@@ -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;