From bb301d84e9ab7943610e55e0b71e2885225e5d0f Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 16 Feb 2019 19:00:45 +0900 Subject: [PATCH 1/4] WIP change to linked list buckets instead of deque --- src/UDPC_HashMap.c | 184 ++++++++++++++++----------------------------- src/UDPC_HashMap.h | 23 ++++-- 2 files changed, 82 insertions(+), 125 deletions(-) diff --git a/src/UDPC_HashMap.c b/src/UDPC_HashMap.c index 8fdabbb..8fcabb0 100644 --- a/src/UDPC_HashMap.c +++ b/src/UDPC_HashMap.c @@ -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; } + current->next = malloc(sizeof(UDPC_HashMap_Node)); + current->next->key = key; + if(hm->unitSize != 0) + { + current->next->data = malloc(hm->unitSize); + memcpy(current->next->data, data, hm->unitSize); + } + else + { + current->next->data = NULL; + } + current->next->next = NULL; + current->next->prev = current; - if(UDPC_Deque_get_available(hm->buckets[hash]) == 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; - } - } - 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; + 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; } - return 0; + current->prev->next = current->next; + if(current->next) { current->next->prev = current->prev; } + + 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) - { - 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; - } - } - } + if(!current) { return NULL; } - return NULL; + return current->data; } +int UDPC_HashMap_has(UDPC_HashMap *hm, uint32_t key) +{ + if(hm->size == 0) + { + 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 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) diff --git a/src/UDPC_HashMap.h b/src/UDPC_HashMap.h index de163aa..0bda507 100644 --- a/src/UDPC_HashMap.h +++ b/src/UDPC_HashMap.h @@ -1,6 +1,8 @@ #ifndef UDPC_HASHMAP_H #define UDPC_HASHMAP_H +#include + // 5 8 2 7 3 6 1 // 3 2 5 1 8 7 6 #define UDPC_HASH32(x) ( \ @@ -16,18 +18,22 @@ ) #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. From 2f794beedeec91c49c7392abfacd12c9e72d73c6 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 18 Feb 2019 12:13:49 +0900 Subject: [PATCH 2/4] Change HashMap to use llists, testing required --- src/UDPC_HashMap.c | 183 ++++++++++++++++++--------------------------- src/UDPC_HashMap.h | 8 +- 2 files changed, 75 insertions(+), 116 deletions(-) diff --git a/src/UDPC_HashMap.c b/src/UDPC_HashMap.c index 8fcabb0..ad95198 100644 --- a/src/UDPC_HashMap.c +++ b/src/UDPC_HashMap.c @@ -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); - - hm->buckets = newBuckets; - hm->overflow = newOverflow; - - hm->capacity = newCapacity; - return 1; } + free(hm->buckets); + + hm->capacity = newCapacity; + hm->buckets = newBuckets; + + 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) + current = hm->buckets[x]->next; + while(current) { - 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); } + fn(userData, current->key, current->data); + current = current->next; } } - 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) - { - free(temp); - return NULL; - } - } - 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; } diff --git a/src/UDPC_HashMap.h b/src/UDPC_HashMap.h index 0bda507..c36d3af 100644 --- a/src/UDPC_HashMap.h +++ b/src/UDPC_HashMap.h @@ -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 From 40f4df0fbab52e9d083253cdc218fe9ce58c8823 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 18 Feb 2019 12:24:34 +0900 Subject: [PATCH 3/4] Update unit tests for HashMap, fixes --- src/UDPC_HashMap.c | 6 ++++-- src/test/UDPC_UnitTest.c | 23 +++++++++++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/UDPC_HashMap.c b/src/UDPC_HashMap.c index ad95198..ac7217e 100644 --- a/src/UDPC_HashMap.c +++ b/src/UDPC_HashMap.c @@ -117,8 +117,8 @@ int UDPC_HashMap_remove(UDPC_HashMap *hm, uint32_t key) 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)) + UDPC_HashMap_Node *current = hm->buckets[hash]->next; + while(current && current->key != key) { current = current->next; } @@ -131,6 +131,8 @@ int UDPC_HashMap_remove(UDPC_HashMap *hm, uint32_t key) if(current->data) { free(current->data); } free(current); + --hm->size; + return 1; } diff --git a/src/test/UDPC_UnitTest.c b/src/test/UDPC_UnitTest.c index 2f30350..d345a90 100644 --- a/src/test/UDPC_UnitTest.c +++ b/src/test/UDPC_UnitTest.c @@ -232,11 +232,11 @@ void TEST_ATOSTR() UNITTEST_REPORT(ATOSTR); } -void TEST_HASHMAP_itercall_comp(void *userData, char *data) +void TEST_HASHMAP_itercall_comp(void *userData, uint32_t key, char *data) { *((int*)userData) += 1; int temp = *((int*)(data)) / 100; - ASSERT_EQ_MEM(&temp, data - 4, 4); + ASSERT_EQ(temp, key); } void TEST_HASHMAP() @@ -247,20 +247,32 @@ void TEST_HASHMAP() temp = 1333; ASSERT_NEQ(UDPC_HashMap_insert(hm, 0, &temp), NULL); ASSERT_EQ_MEM(UDPC_HashMap_get(hm, 0), &temp, sizeof(int)); + ASSERT_NEQ(UDPC_HashMap_has(hm, 0), 0); + ASSERT_EQ(UDPC_HashMap_has(hm, 1), 0); temp = 9999; ASSERT_NEQ(UDPC_HashMap_insert(hm, 1, &temp), NULL); ASSERT_EQ_MEM(UDPC_HashMap_get(hm, 1), &temp, sizeof(int)); + ASSERT_NEQ(UDPC_HashMap_has(hm, 0), 0); + ASSERT_NEQ(UDPC_HashMap_has(hm, 1), 0); + ASSERT_EQ(UDPC_HashMap_has(hm, 2), 0); temp = 1235987; ASSERT_NEQ(UDPC_HashMap_insert(hm, 2, &temp), NULL); ASSERT_EQ_MEM(UDPC_HashMap_get(hm, 2), &temp, sizeof(int)); + ASSERT_NEQ(UDPC_HashMap_has(hm, 0), 0); + ASSERT_NEQ(UDPC_HashMap_has(hm, 1), 0); + ASSERT_NEQ(UDPC_HashMap_has(hm, 2), 0); + ASSERT_EQ(UDPC_HashMap_has(hm, 3), 0); ASSERT_NEQ(UDPC_HashMap_remove(hm, 1), 0); temp = 1333; ASSERT_EQ_MEM(UDPC_HashMap_get(hm, 0), &temp, sizeof(int)); temp = 1235987; ASSERT_EQ_MEM(UDPC_HashMap_get(hm, 2), &temp, sizeof(int)); + ASSERT_NEQ(UDPC_HashMap_has(hm, 0), 0); + ASSERT_EQ(UDPC_HashMap_has(hm, 1), 0); + ASSERT_NEQ(UDPC_HashMap_has(hm, 2), 0); ASSERT_EQ(UDPC_HashMap_realloc(hm, 0), 0); ASSERT_NEQ(UDPC_HashMap_realloc(hm, 16), 0); @@ -269,6 +281,9 @@ void TEST_HASHMAP() ASSERT_EQ_MEM(UDPC_HashMap_get(hm, 0), &temp, sizeof(int)); temp = 1235987; ASSERT_EQ_MEM(UDPC_HashMap_get(hm, 2), &temp, sizeof(int)); + ASSERT_NEQ(UDPC_HashMap_has(hm, 0), 0); + ASSERT_EQ(UDPC_HashMap_has(hm, 1), 0); + ASSERT_NEQ(UDPC_HashMap_has(hm, 2), 0); UDPC_HashMap_clear(hm); ASSERT_EQ(hm->size, 0); @@ -287,6 +302,7 @@ void TEST_HASHMAP() { temp = x * 100; ASSERT_EQ_MEM(UDPC_HashMap_get(hm, x), &temp, sizeof(int)); + ASSERT_NEQ(UDPC_HashMap_has(hm, x), 0); } ASSERT_GTE(hm->capacity, 8); @@ -296,12 +312,14 @@ void TEST_HASHMAP() { temp = x * 100; ASSERT_EQ_MEM(UDPC_HashMap_get(hm, x), &temp, sizeof(int)); + ASSERT_NEQ(UDPC_HashMap_has(hm, x), 0); } ASSERT_GTE(hm->capacity, 16); for(int x = 0; x < 9; ++x) { ASSERT_NEQ(UDPC_HashMap_remove(hm, x), 0); + ASSERT_EQ(UDPC_HashMap_has(hm, x), 0); } ASSERT_EQ(hm->size, 0); ASSERT_GTE(hm->capacity, 16); @@ -317,6 +335,7 @@ void TEST_HASHMAP() { temp = x * 100; ASSERT_EQ_MEM(UDPC_HashMap_get(hm, x), &temp, sizeof(int)); + ASSERT_NEQ(UDPC_HashMap_has(hm, x), 0); } temp = 0; From 84791a5399c1300207f684c2fafb4313cca895d5 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 18 Feb 2019 12:31:42 +0900 Subject: [PATCH 4/4] Update UDPConnection to use updated HashMap --- src/UDPConnection.c | 28 ++++++++++++++-------------- src/UDPConnection.h | 6 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/UDPConnection.c b/src/UDPConnection.c index 54fb9e5..c8280d9 100644 --- a/src/UDPConnection.c +++ b/src/UDPConnection.c @@ -152,7 +152,7 @@ void UDPC_destroy(UDPC_Context *ctx) free(ctx); } -void UDPC_INTERNAL_destroy_conMap(void *unused, char *data) +void UDPC_INTERNAL_destroy_conMap(void *unused, uint32_t addr, char *data) { UDPC_INTERNAL_ConnectionData *cd = (UDPC_INTERNAL_ConnectionData*)data; for(int x = 0; x * sizeof(UDPC_INTERNAL_PacketInfo) < cd->sentPkts->size; ++x) @@ -352,7 +352,7 @@ void UDPC_update(UDPC_Context *ctx) // TODO rest of received packet actions } -void UDPC_INTERNAL_update_to_rtt_si(void *userData, char *data) +void UDPC_INTERNAL_update_to_rtt_si(void *userData, uint32_t addr, char *data) { UDPC_INTERNAL_update_struct *us = (UDPC_INTERNAL_update_struct*)userData; @@ -361,9 +361,9 @@ void UDPC_INTERNAL_update_to_rtt_si(void *userData, char *data) // check for timed out connection if(UDPC_ts_diff_to_seconds(&us->tsNow, &cd->received) >= UDPC_TIMEOUT_SECONDS) { - UDPC_Deque_push_back(us->removedQueue, &cd->addr, 4); + UDPC_Deque_push_back(us->removedQueue, &addr, 4); UDPC_INTERNAL_log(us->ctx, 2, "Connection timed out with addr %s port %d", - UDPC_INTERNAL_atostr(us->ctx, cd->addr), + UDPC_INTERNAL_atostr(us->ctx, addr), cd->port); return; } @@ -375,7 +375,7 @@ void UDPC_INTERNAL_update_to_rtt_si(void *userData, char *data) { // good mode, bad rtt UDPC_INTERNAL_log(us->ctx, 2, "Connection with %s switching to bad mode", - UDPC_INTERNAL_atostr(us->ctx, cd->addr)); + UDPC_INTERNAL_atostr(us->ctx, addr)); cd->flags = cd->flags & 0xFFFFFFFD; if(cd->toggledTimer <= 10.0f) @@ -409,7 +409,7 @@ void UDPC_INTERNAL_update_to_rtt_si(void *userData, char *data) cd->toggleTimer = 0.0f; cd->toggledTimer = 0.0f; UDPC_INTERNAL_log(us->ctx, 2, "Connection with %s switching to good mode", - UDPC_INTERNAL_atostr(us->ctx, cd->addr)); + UDPC_INTERNAL_atostr(us->ctx, addr)); cd->flags |= 0x2; } } @@ -429,7 +429,7 @@ void UDPC_INTERNAL_update_to_rtt_si(void *userData, char *data) } } -void UDPC_INTERNAL_update_send(void *userData, char *data) +void UDPC_INTERNAL_update_send(void *userData, uint32_t addr, char *data) { UDPC_INTERNAL_update_struct *us = (UDPC_INTERNAL_update_struct*)userData; @@ -454,7 +454,7 @@ void UDPC_INTERNAL_update_send(void *userData, char *data) struct sockaddr_in destinationInfo; destinationInfo.sin_family = AF_INET; - destinationInfo.sin_addr.s_addr = cd->addr; + destinationInfo.sin_addr.s_addr = addr; destinationInfo.sin_port = htons(cd->port); long int sentBytes = sendto( us->ctx->socketHandle, @@ -466,13 +466,13 @@ void UDPC_INTERNAL_update_send(void *userData, char *data) if(sentBytes != 20) { UDPC_INTERNAL_log(us->ctx, 0, "Failed to send packet to %s port %d", - UDPC_INTERNAL_atostr(us->ctx, cd->addr), cd->port); + UDPC_INTERNAL_atostr(us->ctx, addr), cd->port); free(data); return; } UDPC_INTERNAL_PacketInfo sentInfo = { - cd->addr, + addr, cd->lseq - 1, 0, NULL, @@ -510,7 +510,7 @@ void UDPC_INTERNAL_update_send(void *userData, char *data) struct sockaddr_in destinationInfo; destinationInfo.sin_family = AF_INET; - destinationInfo.sin_addr.s_addr = cd->addr; + destinationInfo.sin_addr.s_addr = addr; destinationInfo.sin_port = htons(cd->port); long int sentBytes = sendto( us->ctx->socketHandle, @@ -522,7 +522,7 @@ void UDPC_INTERNAL_update_send(void *userData, char *data) if(sentBytes != 20 + pinfo->size) { UDPC_INTERNAL_log(us->ctx, 0, "Failed to send packet to %s port %d", - UDPC_INTERNAL_atostr(us->ctx, cd->addr), cd->port); + UDPC_INTERNAL_atostr(us->ctx, addr), cd->port); free(data); free(pinfo->data); UDPC_Deque_pop_front(cd->sendPktQueue, sizeof(UDPC_INTERNAL_PacketInfo)); @@ -532,7 +532,7 @@ void UDPC_INTERNAL_update_send(void *userData, char *data) if((pinfo->flags & 0x2) != 0) { UDPC_INTERNAL_PacketInfo sentInfo = { - cd->addr, + addr, cd->lseq - 1, 0x2, data, @@ -545,7 +545,7 @@ void UDPC_INTERNAL_update_send(void *userData, char *data) else { UDPC_INTERNAL_PacketInfo sentInfo = { - cd->addr, + addr, cd->lseq - 1, 0, NULL, diff --git a/src/UDPConnection.h b/src/UDPConnection.h index 0780b3c..a449427 100644 --- a/src/UDPConnection.h +++ b/src/UDPConnection.h @@ -109,7 +109,7 @@ UDPC_Context* UDPC_init_threaded_update(uint16_t listenPort, int isClient); void UDPC_destroy(UDPC_Context *ctx); -void UDPC_INTERNAL_destroy_conMap(void *unused, char *data); +void UDPC_INTERNAL_destroy_conMap(void *unused, uint32_t addr, char *data); uint32_t UDPC_get_error(UDPC_Context *ctx); @@ -129,9 +129,9 @@ void UDPC_set_logging_type(UDPC_Context *ctx, uint32_t logType); /// If threaded, this function is called automatically void UDPC_update(UDPC_Context *ctx); -void UDPC_INTERNAL_update_to_rtt_si(void *userData, char *data); +void UDPC_INTERNAL_update_to_rtt_si(void *userData, uint32_t addr, char *data); -void UDPC_INTERNAL_update_send(void *userData, char *data); +void UDPC_INTERNAL_update_send(void *userData, uint32_t addr, char *data); float UDPC_ts_diff_to_seconds(struct timespec *ts0, struct timespec *ts1);