Parcourir la source

List iterator, Components and tests

Kajetan Johannes Hammerle il y a 10 mois
Parent
commit
d3ac438096
8 fichiers modifiés avec 250 ajouts et 10 suppressions
  1. 3 2
      CMakeLists.txt
  2. 50 0
      include/core/Components.h
  3. 3 0
      include/core/List.h
  4. 61 0
      src/Components.c
  5. 17 5
      src/List.c
  6. 1 1
      test/Main.c
  7. 115 0
      test/modules/ComponentsTests.c
  8. 0 2
      test/modules/resources/test

+ 3 - 2
CMakeLists.txt

@@ -7,6 +7,7 @@ set(SRC
     "src/BitArray.c"
     "src/Box.c"
     "src/Buffer.c"
+    "src/Components.c"
     "src/Frustum.c"
     "src/HashMap.c"
     "src/LinkedList.c"
@@ -29,6 +30,7 @@ set(SRC_TESTS
     "test/modules/BitArrayTests.c"
     "test/modules/BoxTests.c"
     "test/modules/BufferTests.c"
+    "test/modules/ComponentsTests.c"
     "test/modules/FrustumTests.c"
     "test/modules/HashMapTests.c"
     "test/modules/LinkedListTests.c"
@@ -42,7 +44,6 @@ set(SRC_TESTS
     "test/modules/UtilityTests.c"
     "test/modules/VectorTests.c"
     "test/modules/ViewTests.c"
-    #"test/modules/ComponentsTests.cpp"
 )
 
 set(SRC_PERFORMANCE
@@ -102,6 +103,7 @@ target_sources(core PUBLIC
         ./include/core/Box.h
         ./include/core/Buffer.h
         ./include/core/Check.h
+        ./include/core/Components.h
         ./include/core/Frustum.h
         ./include/core/HashMap.h
         ./include/core/LinkedList.h
@@ -117,7 +119,6 @@ target_sources(core PUBLIC
         ./include/core/Utility.h
         ./include/core/Vector.h
         ./include/core/View.h
-#        ./include/core/Components.hpp
 )
 install(TARGETS core FILE_SET HEADERS)
 

+ 50 - 0
include/core/Components.h

@@ -0,0 +1,50 @@
+#ifndef CORE_COMPONENTS_H
+#define CORE_COMPONENTS_H
+
+#include "core/HashMap.h"
+#include "core/List.h"
+
+typedef size_t CoreEntity;
+
+typedef struct {
+    CoreHashMap entityToIndex;
+    CoreList indexToEntity;
+    CoreList components;
+} CoreComponents;
+
+typedef struct {
+    CoreEntity entity;
+    void* component;
+} CoreComponentNode;
+
+typedef struct {
+    const CoreEntity* indexToEntity;
+    const CoreEntity* indexToEntityEnd;
+    void* component;
+    void* componentEnd;
+    size_t componentSize;
+    CoreComponentNode node;
+} CoreComponentIterator;
+
+#define CORE_COMPONENTS(componentSize)                                         \
+    ((CoreComponents){CORE_HASH_MAP(sizeof(CoreEntity), sizeof(size_t),        \
+                                    coreHash, coreEqual),                      \
+                      CORE_LIST(sizeof(CoreEntity)),                           \
+                      CORE_LIST(componentSize)})
+void coreDestroyComponents(CoreComponents* c);
+void* coreComponentsGetOrAdd(CoreComponents* c, CoreEntity e);
+void* coreComponentsSearch(CoreComponents* c, CoreEntity e);
+bool coreComponentsRemove(CoreComponents* c, CoreEntity e);
+#define CORE_COMPONENTS_ITERATOR(c)                                            \
+    ((CoreComponentIterator){coreListBegin(&(c)->indexToEntity),               \
+                             coreListEnd(&(c)->indexToEntity),                 \
+                             coreListBegin(&(c)->components),                  \
+                             coreListEnd(&(c)->components),                    \
+                             (c)->components.dataSize,                         \
+                             {0}})
+#define coreComponentsHasNext(ci) (ci.indexToEntity != ci.indexToEntityEnd)
+CoreComponentNode* coreComponentsNext(CoreComponentIterator* ci);
+void* coreComponentsBegin(CoreComponents* c);
+void* coreComponentsEnd(CoreComponents* c);
+
+#endif

+ 3 - 0
include/core/List.h

@@ -23,6 +23,7 @@ void coreResizeListPointer(CoreList* l, size_t n, const void* data);
 CoreList* coreListAddPointer(CoreList* l, const void* data);
 #define coreListAdd(l, type, ...) coreListAddPointer(l, &(type){__VA_ARGS__})
 CoreList* coreListAddLast(CoreList* l);
+void* coreListAddEmpty(CoreList* l);
 void* coreListGetVoidPointer(CoreList* l, size_t index);
 #define coreListGetPointer(l, index, type)                                     \
     ((type*)coreListGetVoidPointer(l, index))
@@ -43,5 +44,7 @@ void coreListRemove(CoreList* l, size_t index);
 void coreListRemoveLast(CoreList* l);
 size_t coreToStringList(CoreList* l, char* buffer, size_t n, CoreToString c);
 void coreSwapList(CoreList* a, CoreList* b);
+void* coreListBegin(CoreList* l);
+void* coreListEnd(CoreList* l);
 
 #endif

+ 61 - 0
src/Components.c

@@ -0,0 +1,61 @@
+#include "core/Components.h"
+
+void coreDestroyComponents(CoreComponents* c) {
+    coreDestroyHashMap(&c->entityToIndex);
+    coreDestroyList(&c->indexToEntity);
+    coreDestroyList(&c->components);
+}
+
+void* coreComponentsGetOrAdd(CoreComponents* c, CoreEntity e) {
+    void* component = coreComponentsSearch(c, e);
+    if(component != nullptr) {
+        return component;
+    }
+    size_t index = c->components.length;
+    coreHashMapPutPointer(&c->entityToIndex, &e, &index);
+    coreListAddPointer(&c->indexToEntity, &e);
+    return coreListAddEmpty(&c->components);
+}
+
+void* coreComponentsSearch(CoreComponents* c, CoreEntity e) {
+    size_t* index = coreHashMapSearchPointer(&c->entityToIndex, &e);
+    if(index == nullptr) {
+        return nullptr;
+    }
+    return coreListGetVoidPointer(&c->components, *index);
+}
+
+bool coreComponentsRemove(CoreComponents* c, CoreEntity e) {
+    size_t* indexP = coreHashMapSearchPointer(&c->entityToIndex, &e);
+    if(indexP == nullptr) {
+        return false;
+    }
+    size_t lastIndex = c->components.length - 1;
+    size_t index = *indexP;
+    coreHashMapRemovePointer(&c->entityToIndex, &e);
+    coreListRemoveBySwap(&c->components, index);
+    if(index == lastIndex) {
+        coreListRemoveBySwap(&c->indexToEntity, index);
+        return true;
+    }
+    CoreEntity other = coreListGet(&c->indexToEntity, lastIndex, CoreEntity);
+    coreListRemoveBySwap(&c->indexToEntity, index);
+    coreHashMapPutPointer(&c->entityToIndex, &other, &index);
+    return true;
+}
+
+CoreComponentNode* coreComponentsNext(CoreComponentIterator* ci) {
+    ci->node.component = ci->component;
+    ci->node.entity = *ci->indexToEntity;
+    ci->indexToEntity++;
+    ci->component = (char*)ci->component + ci->componentSize;
+    return &ci->node;
+}
+
+void* coreComponentsBegin(CoreComponents* c) {
+    return coreListBegin(&c->components);
+}
+
+void* coreComponentsEnd(CoreComponents* c) {
+    return coreListEnd(&c->components);
+}

+ 17 - 5
src/List.c

@@ -81,8 +81,7 @@ void coreResizeListPointer(CoreList* l, size_t n, const void* data) {
 }
 
 CoreList* coreListAddPointer(CoreList* l, const void* data) {
-    ensureCapacity(l);
-    memcpy(getPointer(l, l->length++), data, l->dataSize);
+    memcpy(coreListAddEmpty(l), data, l->dataSize);
     return l;
 }
 
@@ -90,6 +89,11 @@ CoreList* coreListAddLast(CoreList* l) {
     return coreListAddPointer(l, coreListLastVoidPointer(l));
 }
 
+void* coreListAddEmpty(CoreList* l) {
+    ensureCapacity(l);
+    return getPointer(l, l->length++);
+}
+
 void* coreListGetVoidPointer(CoreList* l, size_t index) {
     assert(index < l->length);
     return getPointer(l, index);
@@ -125,7 +129,7 @@ void coreListRemove(CoreList* l, size_t index) {
     assert(index < l->length);
     l->length--;
     char* p = getPointer(l, index);
-    char* end = getPointer(l, l->length);
+    char* end = coreListEnd(l);
     while(p != end) {
         *p = *(p + l->dataSize);
         p++;
@@ -139,8 +143,8 @@ void coreListRemoveLast(CoreList* l) {
 size_t coreToStringList(CoreList* l, char* buffer, size_t n, CoreToString c) {
     size_t w = 0;
     coreStringAddI(&w, &buffer, &n, snprintf(buffer, n, "["));
-    char* end = getPointer(l, l->length);
-    char* p = l->data;
+    char* end = coreListEnd(l);
+    char* p = coreListBegin(l);
     while(p != end) {
         coreStringAdd(&w, &buffer, &n, c(p, buffer, n));
         p += l->dataSize;
@@ -157,3 +161,11 @@ void coreSwapList(CoreList* a, CoreList* b) {
     *a = *b;
     *b = tmp;
 }
+
+void* coreListBegin(CoreList* l) {
+    return l->data;
+}
+
+void* coreListEnd(CoreList* l) {
+    return getPointer(l, l->length);
+}

+ 1 - 1
test/Main.c

@@ -31,10 +31,10 @@ int main(int argAmount, const char** args) {
         }
     }
 
-    // coreTestComponents();
     coreTestBitArray();
     coreTestBox();
     coreTestBuffer(light);
+    coreTestComponents();
     coreTestFrustum();
     coreTestHashMap(light);
     coreTestLinkedList(light);

+ 115 - 0
test/modules/ComponentsTests.c

@@ -0,0 +1,115 @@
+#include "../Tests.h"
+#include "core/Components.h"
+
+static void testAddForEach() {
+    CoreComponents c = CORE_COMPONENTS(sizeof(int));
+    int* i1 = coreComponentsGetOrAdd(&c, 1);
+    if(CORE_TEST_NOT_NULL(i1)) {
+        *i1 = 10;
+    }
+    int* i2 = coreComponentsGetOrAdd(&c, 1);
+    if(CORE_TEST_NOT_NULL(i2)) {
+        *i2 = 15;
+    }
+    int* i3 = coreComponentsGetOrAdd(&c, 5);
+    if(CORE_TEST_NOT_NULL(i3)) {
+        *i3 = 20;
+    }
+    int* i4 = coreComponentsGetOrAdd(&c, 10);
+    if(CORE_TEST_NOT_NULL(i4)) {
+        *i4 = 30;
+    }
+    CORE_TEST_TRUE(i1 == i2);
+
+    CoreComponentIterator iter = CORE_COMPONENTS_ITERATOR(&c);
+    if(CORE_TEST_TRUE(coreComponentsHasNext(iter))) {
+        CoreComponentNode* n = coreComponentsNext(&iter);
+        CORE_TEST_SIZE(1, n->entity);
+        CORE_TEST_INT(15, *(int*)n->component);
+    }
+    if(CORE_TEST_TRUE(coreComponentsHasNext(iter))) {
+        CoreComponentNode* n = coreComponentsNext(&iter);
+        CORE_TEST_SIZE(5, n->entity);
+        CORE_TEST_INT(20, *(int*)n->component);
+    }
+    if(CORE_TEST_TRUE(coreComponentsHasNext(iter))) {
+        CoreComponentNode* n = coreComponentsNext(&iter);
+        CORE_TEST_SIZE(10, n->entity);
+        CORE_TEST_INT(30, *(int*)n->component);
+    }
+    CORE_TEST_FALSE(coreComponentsHasNext(iter));
+    coreDestroyComponents(&c);
+}
+
+static void testAddComponentForEach() {
+    CoreComponents c = CORE_COMPONENTS(sizeof(int));
+    int* i1 = coreComponentsGetOrAdd(&c, 1);
+    if(CORE_TEST_NOT_NULL(i1)) {
+        *i1 = 10;
+    }
+    int* i2 = coreComponentsGetOrAdd(&c, 5);
+    if(CORE_TEST_NOT_NULL(i2)) {
+        *i2 = 20;
+    }
+    int* i3 = coreComponentsGetOrAdd(&c, 10);
+    if(CORE_TEST_NOT_NULL(i3)) {
+        *i3 = 30;
+    }
+
+    int* iter = coreComponentsBegin(&c);
+    int* end = coreComponentsEnd(&c);
+    if(CORE_TEST_TRUE(iter != end)) {
+        CORE_TEST_INT(10, *(iter++));
+    }
+    if(CORE_TEST_TRUE(iter != end)) {
+        CORE_TEST_INT(20, *(iter++));
+    }
+    if(CORE_TEST_TRUE(iter != end)) {
+        CORE_TEST_INT(30, *(iter++));
+    }
+    CORE_TEST_TRUE(iter == end);
+    coreDestroyComponents(&c);
+}
+
+static void testRemove() {
+    CoreComponents c = CORE_COMPONENTS(sizeof(int));
+    *(int*)coreComponentsGetOrAdd(&c, 1) = 10;
+    *(int*)coreComponentsGetOrAdd(&c, 5) = 20;
+    *(int*)coreComponentsGetOrAdd(&c, 10) = 30;
+
+    CORE_TEST_FALSE(coreComponentsRemove(&c, 20));
+    CORE_TEST_TRUE(coreComponentsRemove(&c, 5));
+    CORE_TEST_FALSE(coreComponentsRemove(&c, 30));
+
+    *(int*)coreComponentsGetOrAdd(&c, 20) = 40;
+    CORE_TEST_TRUE(coreComponentsRemove(&c, 20));
+
+    int* i1 = coreComponentsSearch(&c, 1);
+    int* i3 = coreComponentsSearch(&c, 10);
+    CORE_TEST_NULL(coreComponentsSearch(&c, 5));
+    if(CORE_TEST_NOT_NULL(i1) && CORE_TEST_NOT_NULL(i3)) {
+        CORE_TEST_INT(10, *i1);
+        CORE_TEST_INT(30, *i3);
+    }
+
+    CORE_TEST_TRUE(coreComponentsRemove(&c, 10));
+    i1 = coreComponentsSearch(&c, 1);
+    CORE_TEST_NULL(coreComponentsSearch(&c, 5));
+    CORE_TEST_NULL(coreComponentsSearch(&c, 10));
+    if(CORE_TEST_NOT_NULL(i1)) {
+        CORE_TEST_INT(10, *i1);
+    }
+
+    CORE_TEST_TRUE(coreComponentsRemove(&c, 1));
+    CORE_TEST_NULL(coreComponentsSearch(&c, 1));
+    CORE_TEST_NULL(coreComponentsSearch(&c, 5));
+    CORE_TEST_NULL(coreComponentsSearch(&c, 10));
+
+    coreDestroyComponents(&c);
+}
+
+void coreTestComponents() {
+    testAddForEach();
+    testAddComponentForEach();
+    testRemove();
+}

+ 0 - 2
test/modules/resources/test

@@ -1,2 +0,0 @@
-abc
-Baum