]> git.seodisparate.com - UDPConnection/commitdiff
WIP change to linked list buckets instead of deque
authorStephen Seo <seo.disparate@gmail.com>
Sat, 16 Feb 2019 10:00:45 +0000 (19:00 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sat, 16 Feb 2019 10:00:45 +0000 (19:00 +0900)
src/UDPC_HashMap.c
src/UDPC_HashMap.h

index 8fdabbbe73d74c618313e0c26a7a8bb9ee932b57..8fcabb072ed242c38d79dd65b2b07bb4f1bab551 100644 (file)
@@ -16,7 +16,7 @@ UDPC_HashMap* UDPC_HashMap_init(uint32_t capacity, uint32_t unitSize)
     m->capacity = (capacity > UDPC_HASHMAP_INIT_CAPACITY ? capacity : UDPC_HASHMAP_INIT_CAPACITY);
     m->unitSize = unitSize;
 
-    m->buckets = malloc(sizeof(UDPC_Deque*) * m->capacity);
+    m->buckets = malloc(sizeof(UDPC_HashMap_Node*) * m->capacity);
     if(!m->buckets)
     {
         free(m);
@@ -30,7 +30,7 @@ UDPC_HashMap* UDPC_HashMap_init(uint32_t capacity, uint32_t unitSize)
             m->buckets[x] = NULL;
             continue;
         }
-        m->buckets[x] = UDPC_Deque_init(UDPC_HASHMAP_BUCKET_SIZE * (4 + unitSize));
+        m->buckets[x] = calloc(1, sizeof(UDPC_HashMap_Node));
         if(!m->buckets[x])
         {
             fail = 1;
@@ -43,22 +43,7 @@ UDPC_HashMap* UDPC_HashMap_init(uint32_t capacity, uint32_t unitSize)
         {
             if(m->buckets[x])
             {
-                UDPC_Deque_destroy(m->buckets[x]);
-            }
-        }
-        free(m->buckets);
-        free(m);
-        return NULL;
-    }
-
-    m->overflow = UDPC_Deque_init(UDPC_HASHMAP_BUCKET_SIZE * (4 + unitSize));
-    if(!m->overflow)
-    {
-        for(int x = 0; x < m->capacity; ++x)
-        {
-            if(m->buckets[x])
-            {
-                UDPC_Deque_destroy(m->buckets[x]);
+                free(m->buckets[x]);
             }
         }
         free(m->buckets);
@@ -71,12 +56,20 @@ UDPC_HashMap* UDPC_HashMap_init(uint32_t capacity, uint32_t unitSize)
 
 void UDPC_HashMap_destroy(UDPC_HashMap *hashMap)
 {
+    UDPC_HashMap_Node *current;
+    UDPC_HashMap_Node *next;
     for(int x = 0; x < hashMap->capacity; ++x)
     {
-        UDPC_Deque_destroy(hashMap->buckets[x]);
+        current = hashMap->buckets[x];
+        while(current)
+        {
+            next = current->next;
+            if(current->data) { free(current->data); }
+            free(current);
+            current = next;
+        }
     }
     free(hashMap->buckets);
-    UDPC_Deque_destroy(hashMap->overflow);
     free(hashMap);
 }
 
@@ -92,43 +85,27 @@ void* UDPC_HashMap_insert(UDPC_HashMap *hm, uint32_t key, void *data)
 
     uint32_t hash = UDPC_HASHMAP_MOD(key, hm->capacity);
 
-    char *temp = malloc(4 + hm->unitSize);
-    memcpy(temp, &key, 4);
-    if(hm->unitSize > 0)
+    UDPC_HashMap_Node *current = hm->buckets[hash];
+    while(current->next)
     {
-        memcpy(temp + 4, data, hm->unitSize);
+        current = current->next;
     }
-
-    if(UDPC_Deque_get_available(hm->buckets[hash]) == 0)
+    current->next = malloc(sizeof(UDPC_HashMap_Node));
+    current->next->key = key;
+    if(hm->unitSize != 0)
     {
-        if(UDPC_Deque_get_available(hm->overflow) == 0)
-        {
-            free(temp);
-            if(UDPC_HashMap_realloc(hm, hm->capacity * 2) != 0)
-            {
-                return UDPC_HashMap_INTERNAL_reinsert(hm, key, data);
-            }
-            else
-            {
-                return NULL;
-            }
-        }
-        else if(UDPC_Deque_push_back(hm->overflow, temp, 4 + hm->unitSize) == 0)
-        {
-            free(temp);
-            return NULL;
-        }
+        current->next->data = malloc(hm->unitSize);
+        memcpy(current->next->data, data, hm->unitSize);
     }
-    else if(UDPC_Deque_push_back(hm->buckets[hash], temp, 4 + hm->unitSize) == 0)
+    else
     {
-        free(temp);
-        return NULL;
+        current->next->data = NULL;
     }
+    current->next->next = NULL;
+    current->next->prev = current;
 
-    free(temp);
     ++hm->size;
-    temp = UDPC_Deque_get_back_ptr(hm->buckets[hash], 4 + hm->unitSize);
-    return temp + 4;
+    return current->next->data;
 }
 
 int UDPC_HashMap_remove(UDPC_HashMap *hm, uint32_t key)
@@ -140,47 +117,21 @@ int UDPC_HashMap_remove(UDPC_HashMap *hm, uint32_t key)
 
     uint32_t hash = UDPC_HASHMAP_MOD(key, hm->capacity);
 
-    for(int x = 0; x * (4 + hm->unitSize) < hm->buckets[hash]->size; ++x)
+    UDPC_HashMap_Node *current = hm->buckets[hash];
+    while(current && (current == hm->buckets[hash] || current->key != key))
     {
-        if(memcmp(
-            UDPC_Deque_index_ptr(hm->buckets[hash], 4 + hm->unitSize, x),
-            &key,
-            4) == 0)
-        {
-            int result = UDPC_Deque_remove(hm->buckets[hash], 4 + hm->unitSize, x);
-            if(result != 0)
-            {
-                --hm->size;
-                return 1;
-            }
-            else
-            {
-                return 0;
-            }
-        }
+        current = current->next;
     }
 
-    for(int x = 0; x * (4 + hm->unitSize) < hm->overflow->size; ++x)
-    {
-        if(memcmp(
-            UDPC_Deque_index_ptr(hm->overflow, 4 + hm->unitSize, x),
-            &key,
-            4) == 0)
-        {
-            int result = UDPC_Deque_remove(hm->overflow, 4 + hm->unitSize, x);
-            if(result != 0)
-            {
-                --hm->size;
-                return 1;
-            }
-            else
-            {
-                return 0;
-            }
-        }
-    }
+    if(!current) { return 0; }
+
+    current->prev->next = current->next;
+    if(current->next) { current->next->prev = current->prev; }
 
-    return 0;
+    if(current->data) { free(current->data); }
+    free(current);
+
+    return 1;
 }
 
 void* UDPC_HashMap_get(UDPC_HashMap *hm, uint32_t key)
@@ -192,41 +143,36 @@ void* UDPC_HashMap_get(UDPC_HashMap *hm, uint32_t key)
 
     uint32_t hash = UDPC_HASHMAP_MOD(key, hm->capacity);
 
-    for(int x = 0; x * (4 + hm->unitSize) < hm->buckets[hash]->size; ++x)
+    UDPC_HashMap_Node *current = hm->buckets[hash];
+    while(current && (current == hm->buckets[hash] || current->key != key))
     {
-        char *ptr = UDPC_Deque_index_ptr(hm->buckets[hash], 4 + hm->unitSize, x);
-        if(memcmp(ptr, &key, 4) == 0)
-        {
-            if(hm->unitSize > 0)
-            {
-                return ptr + 4;
-            }
-            else
-            {
-                return ptr;
-            }
-        }
+        current = current->next;
     }
 
-    for(int x = 0; x * (4 + hm->unitSize) < hm->overflow->size; ++x)
+    if(!current) { return NULL; }
+
+    return current->data;
+}
+
+int UDPC_HashMap_has(UDPC_HashMap *hm, uint32_t key)
+{
+    if(hm->size == 0)
     {
-        char *ptr = UDPC_Deque_index_ptr(hm->overflow, 4 + hm->unitSize, x);
-        if(memcmp(ptr, &key, 4) == 0)
-        {
-            if(hm->unitSize > 0)
-            {
-                return ptr + 4;
-            }
-            else
-            {
-                return ptr;
-            }
-        }
+        return 0;
+    }
+
+    uint32_t hash = UDPC_HASHMAP_MOD(key, hm->capacity);
+
+    UDPC_HashMap_Node *current = hm->buckets[hash];
+    while(current && (current == hm->buckets[hash] || current->key != key))
+    {
+        current = current->next;
     }
 
-    return NULL;
+    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)
index de163aaf2739da8c5b768a5213583f139f100831..0bda507cf7d1a009d31cd7f975faf6a6bca11ada 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef UDPC_HASHMAP_H
 #define UDPC_HASHMAP_H
 
+#include <stdint.h>
+
 // 5 8 2 7 3 6 1
 // 3 2 5 1 8 7 6
 #define UDPC_HASH32(x) ( \
 )
 
 #define UDPC_HASHMAP_INIT_CAPACITY 13
-#define UDPC_HASHMAP_BUCKET_SIZE 4
 
 #define UDPC_HASHMAP_MOD(k, m) ((UDPC_HASH32(k) % (m * 2 + 1)) % m)
 
-#include "UDPC_Deque.h"
+struct UDPC_HashMap_Node {
+    uint32_t key;
+    char *data;
+    struct UDPC_HashMap_Node *next;
+    struct UDPC_HashMap_Node *prev;
+};
+typedef struct UDPC_HashMap_Node UDPC_HashMap_Node;
 
 typedef struct {
     uint32_t size;
     uint32_t capacity;
     uint32_t unitSize;
-    UDPC_Deque **buckets;
-    UDPC_Deque *overflow;
+    UDPC_HashMap_Node **buckets;
 } UDPC_HashMap;
 
 /*!
@@ -54,7 +60,7 @@ void UDPC_HashMap_destroy(UDPC_HashMap *hashMap);
  * It is possible to insert items with duplicate keys. In that case, the first
  * duplicate inserted will be the first returned with get() and first removed
  * with remove().
- * \return Internally managed pointer to inserted data, NULL on fail
+ * \return Pointer to inserted data, NULL on fail or unitSize = 0
  */
 void* UDPC_HashMap_insert(UDPC_HashMap *hm, uint32_t key, void *data);
 
@@ -69,10 +75,15 @@ int UDPC_HashMap_remove(UDPC_HashMap *hm, uint32_t key);
  * Note if unitSize == 0, then the returned pointer will point to a copy of
  * its integer key, which should not be changed manually (otherwise, the hash
  * map would not be able to find it).
- * \return non-NULL if data was found
+ * \return non-NULL if data was found and unitSize != 0
  */
 void* UDPC_HashMap_get(UDPC_HashMap *hm, uint32_t key);
 
+/*!
+ * \return non-zero if item with specified key is in the hash map
+ */
+int UDPC_HashMap_has(UDPC_HashMap *hm, uint32_t key);
+
 /*!
  * \brief Resizes the maximum capacity of a hash map
  * Note on fail, the hash map is unchanged.