소스 검색

HashMap and tests

Kajetan Johannes Hammerle 10 달 전
부모
커밋
9ba928c6c8
3개의 변경된 파일101개의 추가작업 그리고 107개의 파일을 삭제
  1. 19 0
      include/core/HashMap.h
  2. 17 0
      src/HashMap.c
  3. 65 107
      test/modules/HashMapTests.c

+ 19 - 0
include/core/HashMap.h

@@ -42,4 +42,23 @@ size_t coreHashString(const void* key, size_t n);
 size_t coreHash(const void* key, size_t n);
 bool coreEqual(const void* keyA, const void* keyB, size_t n);
 
+typedef struct {
+    const void* key;
+    void* value;
+} CoreHashMapNode;
+
+typedef struct {
+    const CoreHashMap* map;
+    size_t index;
+    CoreHashMapNode node;
+} CoreHashMapIterator;
+
+#define CORE_HASH_MAP_ITERATOR(map)                                            \
+    ((CoreHashMapIterator){map, (size_t)-1, {0}})
+CoreHashMapNode* coreHashMapNext(CoreHashMapIterator* mi);
+#define coreHashMapKeyPointer(node, type) ((const type*)node->key)
+#define coreHashMapKey(node, type) (*coreHashMapKeyPointer(node, type))
+#define coreHashMapValuePointer(node, type) ((const type*)node->value)
+#define coreHashMapValue(node, type) (*coreHashMapValuePointer(node, type))
+
 #endif

+ 17 - 0
src/HashMap.c

@@ -90,6 +90,7 @@ void coreRehashHashMap(CoreHashMap* m, size_t minCapacity) {
     size_t keyBytes = l * m->keySize;
     map.keys = coreAllocate(l * m->keySize);
     memset(map.keys, 0, keyBytes);
+    memset(getKey(&map, l - 1), 1, m->keySize);
     map.values = coreAllocate(l * m->valueSize);
     map.capacity = l;
 
@@ -217,3 +218,19 @@ size_t coreHash(const void* key, size_t n) {
 bool coreEqual(const void* keyA, const void* keyB, size_t n) {
     return memcmp(keyA, keyB, n) == 0;
 }
+
+CoreHashMapNode* coreHashMapNext(CoreHashMapIterator* mi) {
+    const CoreHashMap* m = mi->map;
+    mi->index++;
+    size_t end = m->capacity - 1;
+    while(mi->index < m->capacity) {
+        void* key = getKey(m, mi->index);
+        if(isInvalidKey(m, key) == (mi->index == end)) {
+            mi->node.key = key;
+            mi->node.value = getValue(m, mi->index);
+            return &mi->node;
+        }
+        mi->index++;
+    }
+    return nullptr;
+}

+ 65 - 107
test/modules/HashMapTests.c

@@ -57,6 +57,12 @@ static void testSearch() {
     coreDestroyHashMap(&map);
 }
 
+static void testSearchEmpty() {
+    CoreHashMap map = INT_MAP;
+    CORE_TEST_NULL(coreHashMapSearch(&map, int, 6, int));
+    coreDestroyHashMap(&map);
+}
+
 static void testAddReplace() {
     CoreHashMap map = getTestIntMap();
     coreHashMapPut(&map, int, 5, int, 4);
@@ -79,6 +85,12 @@ static void testClear() {
     coreDestroyHashMap(&map);
 }
 
+static void testClearEmpty() {
+    CoreHashMap map = INT_MAP;
+    coreClearHashMap(&map);
+    coreDestroyHashMap(&map);
+}
+
 static void testOverflow(bool light) {
     int limit = light ? 10000 : 100000;
     CoreHashMap map = getTestIntMap();
@@ -116,117 +128,55 @@ static void testToString() {
 }
 
 static void testEntryForEach() {
-    //     T map;
-    //     map.add(5, 4).add(10, 3).add(15, 2);
-    //
-    //     int counter = 0;
-    //     for(auto entry : map) {
-    //         counter += entry.getKey() + entry.value;
-    //     }
-    //     CORE_TEST_EQUAL(39, counter);
-    //
-    //     const T& cmap = map;
-    //     counter = 0;
-    //     for(auto entry : cmap) {
-    //         counter += entry.getKey() + entry.value;
-    //     }
-    //     CORE_TEST_EQUAL(39, counter);
-}
-
-static void testKeyForEach() {
-    //     T map;
-    //     map.add(5, 4).add(10, 3).add(15, 2);
-    //
-    //     int counter = 0;
-    //     for(const int& key : map.getKeys()) {
-    //         counter += key;
-    //     }
-    //     CORE_TEST_EQUAL(30, counter);
-    //
-    //     const T& cmap = map;
-    //     counter = 0;
-    //     for(const int& key : cmap.getKeys()) {
-    //         counter += key;
-    //     }
-    //     CORE_TEST_EQUAL(30, counter);
-}
+    CoreHashMap map = INT_MAP;
+    coreHashMapPut(&map, int, 0, int, -1);
+    coreHashMapPut(&map, int, 5, int, 4);
+    coreHashMapPut(&map, int, 10, int, 3);
+    coreHashMapPut(&map, int, 15, int, 2);
 
-static void testValueForEach() {
-    //     T map;
-    //     map.add(5, 4).add(10, 3).add(15, 2);
-    //
-    //     int counter = 0;
-    //     for(int& value : map.getValues()) {
-    //         counter += value;
-    //     }
-    //     CORE_TEST_EQUAL(9, counter);
-    //
-    //     const T& cmap = map;
-    //     counter = 0;
-    //     for(const int& value : cmap.getValues()) {
-    //         counter += value;
-    //     }
-    //     CORE_TEST_EQUAL(9, counter);
-}
+    int counter = 0;
+    CoreHashMapIterator i = CORE_HASH_MAP_ITERATOR(&map);
+    while(true) {
+        CoreHashMapNode* n = coreHashMapNext(&i);
+        if(n == nullptr) {
+            break;
+        }
+        counter += coreHashMapKey(n, int) + coreHashMapValue(n, int);
+    }
+    CORE_TEST_INT(38, counter);
 
-static void testInvalid() {
-    //     T map;
-    //     int* v;
-    //     CORE_TEST_TRUE(map.tryEmplace(v, INVALID, 2));
-    //     if(CORE_TEST_NOT_NULL(v)) {
-    //         CORE_TEST_EQUAL(2, *v);
-    //     }
-    //     CORE_TEST_FALSE(map.tryEmplace(v, INVALID, 6));
-    //     if(CORE_TEST_NOT_NULL(v)) {
-    //         CORE_TEST_EQUAL(2, *v);
-    //     }
-    //     CORE_TEST_EQUAL(3, map.put(INVALID, 3));
-    //     v = coreHashMapSearch(&map,int,INVALID);
-    //     if(CORE_TEST_NOT_NULL(v)) {
-    //         CORE_TEST_EQUAL(3, *v);
-    //     }
-    //     coreClearHashMap(&map);
-    //     CORE_TEST_NULL(coreHashMapSearch(&map,int,INVALID));
+    coreDestroyHashMap(&map);
 }
 
 static void testInvalidPut() {
-    //     T map;
-    //     CORE_TEST_EQUAL(3, map.put(INVALID, 3));
-    //     int* v = coreHashMapSearch(&map,int,INVALID);
-    //     if(CORE_TEST_NOT_NULL(v)) {
-    //         CORE_TEST_EQUAL(3, *v);
-    //     }
-    //
-    //     also check to string
-}
+    CoreHashMap map = INT_MAP;
 
-static void testAddCollisions() {
-    //     T map;
-    //     for(int i = 0; i < 8; i++) {
-    //         map.add(i * 16, i);
-    //     }
+    char buffer[128];
+    coreToStringHashMap(&map, buffer, sizeof(buffer), coreToStringInt,
+                        coreToStringInt);
+    CORE_TEST_STRING("[]", buffer);
+
+    coreHashMapPut(&map, int, 0, int, 3);
+    int* v = coreHashMapSearch(&map, int, 0, int);
+    if(CORE_TEST_NOT_NULL(v)) {
+        CORE_TEST_INT(3, *v);
+    }
+    coreToStringHashMap(&map, buffer, sizeof(buffer), coreToStringInt,
+                        coreToStringInt);
+    CORE_TEST_STRING("[0 = 3]", buffer);
+
+    coreClearHashMap(&map);
+    CORE_TEST_NULL(coreHashMapSearch(&map, int, 0, int));
+
+    coreDestroyHashMap(&map);
 }
 
-static void testEmplace() {
-    //     Core::HashMap<int, HashMapTest> map;
-    //
-    //     HashMapTest* ar = nullptr;
-    //     CORE_TEST_TRUE(map.tryEmplace(ar, 0, 3, 4));
-    //     CORE_TEST_TRUE(map.tryEmplace(ar, 3, 4, 5));
-    //     CORE_TEST_TRUE(map.tryEmplace(ar, 20, 5, 6));
-    //     CORE_TEST_FALSE(map.tryEmplace(ar, 3, 6, 7));
-    //     CORE_TEST_FALSE(map.tryEmplace(ar, 20, 7, 8));
-    //
-    //     HashMapTest* a = coreHashMapSearch(&map,int,0);
-    //     HashMapTest* b = coreHashMapSearch(&map,int,3);
-    //     HashMapTest* c = coreHashMapSearch(&map,int,20);
-    //
-    //     if(CORE_TEST_NOT_NULL(a) && CORE_TEST_NOT_NULL(b) &&
-    //        CORE_TEST_NOT_NULL(c)) {
-    //         CORE_TEST_EQUAL(HashMapTest(3, 4), *a);
-    //         CORE_TEST_EQUAL(HashMapTest(4, 5), *b);
-    //         CORE_TEST_EQUAL(HashMapTest(5, 6), *c);
-    //     }
+static void testAddCollisions() {
+    CoreHashMap map = getTestIntMap();
+    for(int i = 0; i < 16; i++) {
+        coreHashMapPut(&map, int, i * 64, int, i);
+    }
+    coreDestroyHashMap(&map);
 }
 
 static void testRemove() {
@@ -247,20 +197,28 @@ static void testRemove() {
     //     }
 }
 
+static void testHash() {
+    u32 buffer[] = {0xFFAA00BB, 0x00000000, 0x00FF00FF};
+    CORE_TEST_SIZE(0xFF550044, coreHash(buffer, sizeof(buffer)));
+
+    const char* s = "wusi";
+    CORE_TEST_TRUE(coreHashString(&s, sizeof(&s)) != 0);
+    CORE_TEST_SIZE(0, coreHashString(&s, 1));
+}
+
 void coreTestHashMap(bool light) {
     testAdd();
     testMultipleAdd();
     testSearch();
+    testSearchEmpty();
     testAddReplace();
     testClear();
+    testClearEmpty();
     testOverflow(light);
     testToString();
     testEntryForEach();
-    testKeyForEach();
-    testValueForEach();
-    testInvalid();
     testInvalidPut();
     testAddCollisions();
-    testEmplace();
     testRemove();
+    testHash();
 }