]> git.seodisparate.com - UDPConnection/commitdiff
Change HashMap to use llists, testing required
authorStephen Seo <seo.disparate@gmail.com>
Mon, 18 Feb 2019 03:13:49 +0000 (12:13 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Mon, 18 Feb 2019 03:13:49 +0000 (12:13 +0900)
src/UDPC_HashMap.c
src/UDPC_HashMap.h

index 8fcabb072ed242c38d79dd65b2b07bb4f1bab551..ad95198a1b65c3c67b74e5277da607e350a4f8e9 100644 (file)
@@ -172,7 +172,6 @@ int UDPC_HashMap_has(UDPC_HashMap *hm, uint32_t key)
     return current != NULL ? 1 : 0;
 }
 
-// TODO change to linkedList buckets up to this point
 int UDPC_HashMap_realloc(UDPC_HashMap *hm, uint32_t newCapacity)
 {
     if(hm->size > newCapacity)
@@ -180,100 +179,112 @@ int UDPC_HashMap_realloc(UDPC_HashMap *hm, uint32_t newCapacity)
         return 0;
     }
 
-    UDPC_Deque **newBuckets = malloc(sizeof(UDPC_Deque*) * newCapacity);
-    UDPC_Deque *newOverflow = UDPC_Deque_init(UDPC_HASHMAP_BUCKET_SIZE
-        * (4 + hm->unitSize));
+    // allocate newBuckets
+    int fail = 0;
+    UDPC_HashMap_Node **newBuckets = malloc(sizeof(UDPC_HashMap_Node*) * newCapacity);
+    if(!newBuckets) { return 0; }
     for(int x = 0; x < newCapacity; ++x)
     {
-        newBuckets[x] = UDPC_Deque_init(UDPC_HASHMAP_BUCKET_SIZE
-            * (4 + hm->unitSize));
+        if(fail != 0) { newBuckets[x] = NULL; continue; }
+        newBuckets[x] = calloc(1, sizeof(UDPC_HashMap_Node));
+        if(!newBuckets[x]) { fail = 1; }
+    }
+    if(fail != 0)
+    {
+        for(int x = 0; x < newCapacity; ++x)
+        {
+            if(newBuckets[x]) { free(newBuckets[x]); }
+        }
+        free(newBuckets);
+        return 0;
     }
 
+    // rehash entries from hm->buckets to newBuckets
     uint32_t hash;
-    char *data;
-    int fail = 0;
+    UDPC_HashMap_Node *current;
+    UDPC_HashMap_Node *next;
+    UDPC_HashMap_Node *newCurrent;
     for(int x = 0; x < hm->capacity; ++x)
     {
-        for(int y = 0; y * (4 + hm->unitSize) < hm->buckets[x]->size; ++y)
+        current = hm->buckets[x]->next;
+        while(current)
         {
-            data = UDPC_Deque_index_ptr(hm->buckets[x], 4 + hm->unitSize, y);
-            hash = UDPC_HASHMAP_MOD(*((uint32_t*)data), newCapacity);
-            if(newBuckets[hash]->size < newBuckets[hash]->alloc_size)
+            next = current->next;
+            hash = UDPC_HASHMAP_MOD(current->key, newCapacity);
+            newCurrent = newBuckets[hash];
+            while(newCurrent->next)
             {
-                if(UDPC_Deque_push_back(newBuckets[hash], data, 4 + hm->unitSize) == 0)
-                {
-                    fail = 1;
-                    break;
-                }
+                newCurrent = newCurrent->next;
             }
-            else if(UDPC_Deque_push_back(newOverflow, data, 4 + hm->unitSize) == 0)
+            newCurrent->next = malloc(sizeof(UDPC_HashMap_Node));
+            if(!newCurrent->next)
             {
                 fail = 1;
                 break;
             }
+            newCurrent->next->key = current->key;
+            newCurrent->next->data = current->data;
+            newCurrent->next->next = NULL;
+            newCurrent->next->prev = newCurrent;
+            current = next;
         }
         if(fail != 0)
         {
             break;
         }
     }
-
-    if(fail == 0)
-    {
-        for(int x = 0; x * (4 + hm->unitSize) < hm->overflow->size; ++x)
-        {
-            data = UDPC_Deque_index_ptr(hm->overflow, 4 + hm->unitSize, x);
-            hash = UDPC_HASHMAP_MOD(*((uint32_t*)data), newCapacity);
-            if(newBuckets[hash]->size < newBuckets[hash]->alloc_size)
-            {
-                if(UDPC_Deque_push_back(newBuckets[hash], data, 4 + hm->unitSize) == 0)
-                {
-                    fail = 1;
-                    break;
-                }
-            }
-            else if(UDPC_Deque_push_back(newOverflow, data, 4 + hm->unitSize) == 0)
-            {
-                fail = 1;
-                break;
-            }
-        }
-    }
-
     if(fail != 0)
     {
         for(int x = 0; x < newCapacity; ++x)
         {
-            UDPC_Deque_destroy(newBuckets[x]);
+            current = newBuckets[x];
+            while(current)
+            {
+                next = current->next;
+                free(current);
+                current = next;
+            }
         }
         free(newBuckets);
-        UDPC_Deque_destroy(newOverflow);
         return 0;
     }
-    else
+
+    // cleanup hm->buckets to be replaced by newBuckets
+    for(int x = 0; x < hm->capacity; ++x)
     {
-        for(int x = 0; x < hm->capacity; ++x)
+        current = hm->buckets[x];
+        while(current)
         {
-            UDPC_Deque_destroy(hm->buckets[x]);
+            next = current->next;
+            // do not free current->data as it is now being pointed to by entries in newBuckets
+            free(current);
+            current = next;
         }
-        free(hm->buckets);
-        UDPC_Deque_destroy(hm->overflow);
+    }
+    free(hm->buckets);
 
-        hm->buckets = newBuckets;
-        hm->overflow = newOverflow;
+    hm->capacity = newCapacity;
+    hm->buckets = newBuckets;
 
-        hm->capacity = newCapacity;
-        return 1;
-    }
+    return 1;
 }
 
 void UDPC_HashMap_clear(UDPC_HashMap *hm)
 {
+    UDPC_HashMap_Node *current;
+    UDPC_HashMap_Node *next;
     for(int x = 0; x < hm->capacity; ++x)
     {
-        UDPC_Deque_clear(hm->buckets[x]);
+        current = hm->buckets[x]->next;
+        while(current)
+        {
+            next = current->next;
+            if(current->data) { free(current->data); }
+            free(current);
+            current = next;
+        }
+        hm->buckets[x]->next = NULL;
     }
-    UDPC_Deque_clear(hm->overflow);
     hm->size = 0;
 }
 
@@ -287,64 +298,16 @@ uint32_t UDPC_HashMap_get_capacity(UDPC_HashMap *hm)
     return hm->capacity;
 }
 
-void UDPC_HashMap_itercall(UDPC_HashMap *hm, void (*fn)(void*, char*), void *userData)
+void UDPC_HashMap_itercall(UDPC_HashMap *hm, void (*fn)(void*, uint32_t, char*), void *userData)
 {
+    UDPC_HashMap_Node *current;
     for(int x = 0; x < hm->capacity; ++x)
     {
-        for(int y = 0; y * (4 + hm->unitSize) < hm->buckets[x]->size; ++y)
-        {
-            char *data = UDPC_Deque_index_ptr(
-                hm->buckets[x], 4 + hm->unitSize, y);
-            if(hm->unitSize > 0) { fn(userData, data + 4); }
-            else { fn(userData, data); }
-        }
-    }
-    for(int x = 0; x * (4 + hm->unitSize) < hm->overflow->size; ++x)
-    {
-        char *data = UDPC_Deque_index_ptr(
-            hm->overflow, 4 + hm->unitSize, x);
-        if(hm->unitSize > 0) { fn(userData, data + 4); }
-        else { fn(userData, data); }
-    }
-}
-
-void* UDPC_HashMap_INTERNAL_reinsert(UDPC_HashMap *hm, uint32_t key, void *data)
-{
-    if(hm->capacity <= hm->size)
-    {
-        return NULL;
-    }
-
-    uint32_t hash = UDPC_HASHMAP_MOD(key, hm->capacity);
-
-    char *temp = malloc(4 + hm->unitSize);
-    memcpy(temp, &key, 4);
-    if(hm->unitSize > 0)
-    {
-        memcpy(temp + 4, data, hm->unitSize);
-    }
-
-    if(UDPC_Deque_get_available(hm->buckets[hash]) == 0)
-    {
-        if(UDPC_Deque_get_available(hm->overflow) == 0)
-        {
-            free(temp);
-            return NULL;
-        }
-        else if(UDPC_Deque_push_back(hm->overflow, temp, 4 + hm->unitSize) == 0)
+        current = hm->buckets[x]->next;
+        while(current)
         {
-            free(temp);
-            return NULL;
+            fn(userData, current->key, current->data);
+            current = current->next;
         }
     }
-    else if(UDPC_Deque_push_back(hm->buckets[hash], temp, 4 + hm->unitSize) == 0)
-    {
-        free(temp);
-        return NULL;
-    }
-
-    free(temp);
-    ++hm->size;
-    temp = UDPC_Deque_get_back_ptr(hm->buckets[hash], 4 + hm->unitSize);
-    return temp + 4;
 }
index 0bda507cf7d1a009d31cd7f975faf6a6bca11ada..c36d3af36b7bd1bf43fb05f83514990ce8ca30f8 100644 (file)
@@ -104,12 +104,8 @@ uint32_t UDPC_HashMap_get_capacity(UDPC_HashMap *hm);
 
 /*!
  * \brief Calls a fn with a ptr to each entry in the hash map
+ * The fn is called with userData, entry key, and entry data.
  */
-void UDPC_HashMap_itercall(UDPC_HashMap *hm, void (*fn)(void*, char*), void *userData);
-
-/*!
- * \brief A variant of insert that does not try to realloc() on no more space
- */
-void* UDPC_HashMap_INTERNAL_reinsert(UDPC_HashMap *hm, uint32_t key, void *data);
+void UDPC_HashMap_itercall(UDPC_HashMap *hm, void (*fn)(void*, uint32_t, char*), void *userData);
 
 #endif