Browse Source

RingBuffer and tests

Kajetan Johannes Hammerle 4 weeks ago
parent
commit
451524d233
5 changed files with 245 additions and 3 deletions
  1. 3 2
      CMakeLists.txt
  2. 38 0
      include/core/RingBuffer.h
  3. 78 0
      src/RingBuffer.c
  4. 1 1
      test/Main.c
  5. 125 0
      test/modules/RingBufferTests.c

+ 3 - 2
CMakeLists.txt

@@ -15,6 +15,7 @@ set(SRC
     "src/Plane.c"
     "src/Quaternion.c"
     "src/Random.c"
+    "src/RingBuffer.c"
     "src/SpinLock.c"
     "src/Utility.c"
     "src/Vector.c"
@@ -34,13 +35,13 @@ set(SRC_TESTS
     "test/modules/PlaneTests.c"
     "test/modules/QuaternionTests.c"
     "test/modules/RandomTests.c"
+    "test/modules/RingBufferTests.c"
     "test/modules/SpinLockTests.c"
     "test/modules/UtilityTests.c"
     "test/modules/VectorTests.c"
     "test/modules/ViewTests.c"
     #"test/modules/ComponentsTests.cpp"
     #"test/modules/HashMapTests.cpp"
-    #"test/modules/RingBufferTests.cpp"
 )
 
 set(SRC_PERFORMANCE
@@ -116,7 +117,7 @@ target_sources(core PUBLIC
 #        ./include/core/Components.hpp
 #        ./include/core/HashMap.hpp
 #        ./include/core/ProbingHashMap.hpp
-#        ./include/core/RingBuffer.hpp
+        ./include/core/RingBuffer.h
 )
 install(TARGETS core FILE_SET HEADERS)
 

+ 38 - 0
include/core/RingBuffer.h

@@ -0,0 +1,38 @@
+#ifndef CORE_RINGBUFFER_H
+#define CORE_RINGBUFFER_H
+
+#include "core/Types.h"
+
+typedef struct {
+    size_t writeIndex;
+    size_t readIndex;
+    size_t length;
+    size_t capacity;
+    size_t dataSize;
+    void* data;
+} CoreRingBuffer;
+
+#define CORE_RING_BUFFER(capacity, dataSize)                                   \
+    ((CoreRingBuffer){0, 0, 0, capacity, dataSize, nullptr})
+void coreDestroyRingBuffer(CoreRingBuffer* r);
+CoreRingBuffer* coreRingBufferAddPointer(CoreRingBuffer* r, const void* data);
+#define coreRingBufferAdd(l, type, ...)                                        \
+    coreRingBufferAddPointer(l, &(type){__VA_ARGS__})
+void* coreRingBufferGetVoidPointer(CoreRingBuffer* r, size_t index);
+#define coreRingBufferGetPointer(r, index, type)                               \
+    ((type*)coreRingBufferGetVoidPointer(r, index))
+#define coreRingBufferGet(r, index, type)                                      \
+    (*coreRingBufferGetPointer(r, index, type))
+const void* coreRingBufferGetVoidPointerC(const CoreRingBuffer* r,
+                                          size_t index);
+#define coreRingBufferGetPointerC(r, index, type)                              \
+    ((const type*)coreRingBufferGetVoidPointerC(r, index))
+#define coreRingBufferGetC(r, index, type)                                     \
+    (*coreRingBufferGetPointerC(r, index, type))
+void coreClearRingBuffer(CoreRingBuffer* r);
+void coreRingBufferRemove(CoreRingBuffer* r);
+size_t coreToStringRingBuffer(CoreRingBuffer* r, char* buffer, size_t n,
+                              CoreToString c);
+void coreSwapRingBuffer(CoreRingBuffer* a, CoreRingBuffer* b);
+
+#endif

+ 78 - 0
src/RingBuffer.c

@@ -0,0 +1,78 @@
+#include "core/RingBuffer.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "core/Utility.h"
+
+void coreDestroyRingBuffer(CoreRingBuffer* r) {
+    coreClearRingBuffer(r);
+    r->dataSize = 0;
+    r->capacity = 0;
+    coreFree(r->data);
+    r->data = nullptr;
+}
+
+static void* getPointer(CoreRingBuffer* r, size_t index) {
+    return (char*)r->data + r->dataSize * index;
+}
+
+CoreRingBuffer* coreRingBufferAddPointer(CoreRingBuffer* r, const void* data) {
+    if(r->length >= r->capacity) {
+        return nullptr;
+    } else if(r->data == nullptr) {
+        r->data = coreAllocate(r->capacity * r->dataSize);
+    }
+    memcpy(getPointer(r, r->writeIndex), data, r->dataSize);
+    r->writeIndex = (r->writeIndex + 1) % r->capacity;
+    r->length++;
+    return r;
+}
+
+void* coreRingBufferGetVoidPointer(CoreRingBuffer* r, size_t index) {
+    return getPointer(r, (index + r->readIndex) % r->capacity);
+}
+
+const void* coreRingBufferGetVoidPointerC(const CoreRingBuffer* r,
+                                          size_t index) {
+    return (char*)r->data +
+           r->dataSize * ((index + r->readIndex) % r->capacity);
+}
+
+void coreClearRingBuffer(CoreRingBuffer* r) {
+    r->writeIndex = 0;
+    r->readIndex = 0;
+    r->length = 0;
+}
+
+void coreRingBufferRemove(CoreRingBuffer* r) {
+    assert(r->length > 0);
+    r->length--;
+    r->readIndex = (r->readIndex + 1) % r->capacity;
+}
+
+size_t coreToStringRingBuffer(CoreRingBuffer* r, char* buffer, size_t n,
+                              CoreToString c) {
+    size_t w = 0;
+    coreStringAddI(&w, &buffer, &n, snprintf(buffer, n, "["));
+    size_t end = r->length;
+    if(end > 0) {
+        end--;
+        for(size_t i = 0; i < end; i++) {
+            coreStringAdd(&w, &buffer, &n,
+                          c(coreRingBufferGetVoidPointer(r, i), buffer, n));
+            coreStringAddI(&w, &buffer, &n, snprintf(buffer, n, ", "));
+        }
+        coreStringAdd(&w, &buffer, &n,
+                      c(coreRingBufferGetVoidPointer(r, end), buffer, n));
+    }
+    coreStringAddI(&w, &buffer, &n, snprintf(buffer, n, "]"));
+    return w;
+}
+
+void coreSwapRingBuffer(CoreRingBuffer* a, CoreRingBuffer* b) {
+    CoreRingBuffer tmp = *a;
+    *a = *b;
+    *b = tmp;
+}

+ 1 - 1
test/Main.c

@@ -33,7 +33,6 @@ int main(int argAmount, const char** args) {
 
     // coreTestComponents();
     // coreTestHashMap(light);
-    // coreTestRingBuffer();
     coreTestBitArray();
     coreTestBox();
     coreTestBuffer(light);
@@ -44,6 +43,7 @@ int main(int argAmount, const char** args) {
     coreTestPlane();
     coreTestQuaternion();
     coreTestRandom(light);
+    coreTestRingBuffer();
     coreTestSpinLock();
     coreTestUtility(light);
     coreTestVector();

+ 125 - 0
test/modules/RingBufferTests.c

@@ -0,0 +1,125 @@
+#include "../Tests.h"
+#include "core/RingBuffer.h"
+#include "core/Utility.h"
+
+static void testReadAndWrite() {
+    CoreRingBuffer r = CORE_RING_BUFFER(5, sizeof(size_t));
+    CORE_TEST_SIZE(0, r.length);
+    coreRingBufferAdd(&r, size_t, 4);
+    CORE_TEST_SIZE(1, r.length);
+    CORE_TEST_SIZE(4, coreRingBufferGet(&r, 0, size_t));
+    CORE_TEST_SIZE(4, coreRingBufferGetC(&r, 0, size_t));
+    coreRingBufferRemove(&r);
+    CORE_TEST_SIZE(0, r.length);
+    coreDestroyRingBuffer(&r);
+}
+
+static void testOverflow() {
+    CoreRingBuffer r = CORE_RING_BUFFER(3, sizeof(size_t));
+    coreRingBufferAdd(&r, size_t, 1);
+    coreRingBufferAdd(&r, size_t, 2);
+    coreRingBufferAdd(&r, size_t, 3);
+    coreRingBufferAdd(&r, size_t, 4);
+    coreRingBufferAdd(&r, size_t, 5);
+    CORE_TEST_SIZE(3, r.length);
+    CORE_TEST_SIZE(1, coreRingBufferGet(&r, 0, size_t));
+    coreRingBufferRemove(&r);
+    CORE_TEST_SIZE(2, r.length);
+    CORE_TEST_SIZE(2, coreRingBufferGet(&r, 0, size_t));
+    coreRingBufferRemove(&r);
+    CORE_TEST_SIZE(1, r.length);
+    CORE_TEST_SIZE(3, coreRingBufferGet(&r, 0, size_t));
+    coreRingBufferRemove(&r);
+    CORE_TEST_SIZE(0, r.length);
+    coreDestroyRingBuffer(&r);
+}
+
+static void testRefill() {
+    CoreRingBuffer r = CORE_RING_BUFFER(3, sizeof(size_t));
+    coreRingBufferAdd(&r, size_t, 1);
+    coreRingBufferAdd(&r, size_t, 2);
+    coreRingBufferAdd(&r, size_t, 3);
+    coreRingBufferAdd(&r, size_t, 4);
+    CORE_TEST_SIZE(3, r.length);
+    CORE_TEST_SIZE(1, coreRingBufferGet(&r, 0, size_t));
+    coreRingBufferRemove(&r);
+    CORE_TEST_SIZE(2, coreRingBufferGet(&r, 0, size_t));
+    coreRingBufferRemove(&r);
+    CORE_TEST_SIZE(3, coreRingBufferGet(&r, 0, size_t));
+    coreRingBufferRemove(&r);
+    CORE_TEST_SIZE(0, r.length);
+    coreRingBufferAdd(&r, size_t, 5);
+    coreRingBufferAdd(&r, size_t, 6);
+    CORE_TEST_SIZE(2, r.length);
+    CORE_TEST_SIZE(5, coreRingBufferGet(&r, 0, size_t));
+    coreRingBufferRemove(&r);
+    CORE_TEST_SIZE(6, coreRingBufferGet(&r, 0, size_t));
+    coreRingBufferRemove(&r);
+    CORE_TEST_SIZE(0, r.length);
+    coreDestroyRingBuffer(&r);
+}
+
+static void testClear() {
+    CoreRingBuffer r = CORE_RING_BUFFER(3, sizeof(size_t));
+    coreRingBufferAdd(&r, size_t, 1);
+    coreRingBufferAdd(&r, size_t, 2);
+    CORE_TEST_SIZE(2, r.length);
+    coreClearRingBuffer(&r);
+    CORE_TEST_SIZE(0, r.length);
+    coreDestroyRingBuffer(&r);
+}
+
+static void testOverall() {
+    CoreRingBuffer ri = CORE_RING_BUFFER(3, sizeof(size_t));
+    coreRingBufferAdd(&ri, size_t, 1);
+    coreRingBufferAdd(&ri, size_t, 2);
+    coreRingBufferAdd(&ri, size_t, 3);
+
+    CoreRingBuffer r = CORE_RING_BUFFER(0, 0);
+    coreSwapRingBuffer(&r, &ri);
+    char buffer[128];
+    coreToStringRingBuffer(&r, buffer, sizeof(buffer), coreToStringSize);
+    CORE_TEST_STRING("[1, 2, 3]", buffer);
+    CORE_TEST_SIZE(3, r.length);
+
+    coreRingBufferRemove(&r);
+    coreToStringRingBuffer(&r, buffer, sizeof(buffer), coreToStringSize);
+    CORE_TEST_STRING("[2, 3]", buffer);
+    CORE_TEST_SIZE(2, r.length);
+
+    coreRingBufferAdd(&r, size_t, 4);
+    coreToStringRingBuffer(&r, buffer, sizeof(buffer), coreToStringSize);
+    CORE_TEST_STRING("[2, 3, 4]", buffer);
+    CORE_TEST_SIZE(3, r.length);
+
+    coreRingBufferRemove(&r);
+    coreToStringRingBuffer(&r, buffer, sizeof(buffer), coreToStringSize);
+    CORE_TEST_STRING("[3, 4]", buffer);
+    CORE_TEST_SIZE(2, r.length);
+
+    coreRingBufferAdd(&r, size_t, 5);
+    coreToStringRingBuffer(&r, buffer, sizeof(buffer), coreToStringSize);
+    CORE_TEST_STRING("[3, 4, 5]", buffer);
+    CORE_TEST_SIZE(3, r.length);
+
+    coreRingBufferRemove(&r);
+    coreToStringRingBuffer(&r, buffer, sizeof(buffer), coreToStringSize);
+    CORE_TEST_STRING("[4, 5]", buffer);
+    CORE_TEST_SIZE(2, r.length);
+
+    coreClearRingBuffer(&r);
+    coreToStringRingBuffer(&r, buffer, sizeof(buffer), coreToStringSize);
+    CORE_TEST_STRING("[]", buffer);
+    CORE_TEST_SIZE(0, r.length);
+
+    coreDestroyRingBuffer(&r);
+    coreDestroyRingBuffer(&ri);
+}
+
+void coreTestRingBuffer() {
+    testReadAndWrite();
+    testOverflow();
+    testRefill();
+    testClear();
+    testOverall();
+}