Browse Source

Migrate C core

Kajetan Johannes Hammerle 2 months ago
parent
commit
c24f4165ef
100 changed files with 1918 additions and 212 deletions
  1. 0 3
      .clangd
  2. 99 209
      CMakeLists.txt
  3. 60 0
      cmake/clang_warnings.cmake
  4. 70 0
      cmake/gcc_warnings.cmake
  5. 23 0
      include/core/BitArray.h
  6. 23 0
      include/core/Box.h
  7. 19 0
      include/core/Buffer.h
  8. 19 0
      include/core/Check.h
  9. 127 0
      include/core/Components.h
  10. 14 0
      include/core/File.h
  11. 23 0
      include/core/Frustum.h
  12. 134 0
      include/core/Generic.h
  13. 237 0
      include/core/HashMap.h
  14. 131 0
      include/core/List.h
  15. 59 0
      include/core/Logger.h
  16. 32 0
      include/core/Matrix.h
  17. 15 0
      include/core/Plane.h
  18. 20 0
      include/core/Quaternion.h
  19. 85 0
      include/core/Queue.h
  20. 18 0
      include/core/Random.h
  21. 10 0
      include/core/ReadLine.h
  22. 14 0
      include/core/SpinLock.h
  23. 117 0
      include/core/Terminal.h
  24. 65 0
      include/core/Test.h
  25. 8 0
      include/core/Thread.h
  26. 13 0
      include/core/ToString.h
  27. 19 0
      include/core/Types.h
  28. 16 0
      include/core/Unicode.h
  29. 84 0
      include/core/Utility.h
  30. 95 0
      include/core/Vector.h
  31. 21 0
      include/core/View.h
  32. 248 0
      old/CMakeLists.txt
  33. 0 0
      old/include/core/data/Array.hpp
  34. 0 0
      old/include/core/data/ArrayList.hpp
  35. 0 0
      old/include/core/data/BitArray.hpp
  36. 0 0
      old/include/core/data/Components.hpp
  37. 0 0
      old/include/core/data/HashMap.hpp
  38. 0 0
      old/include/core/data/LinkedList.hpp
  39. 0 0
      old/include/core/data/List.hpp
  40. 0 0
      old/include/core/data/ProbingHashMap.hpp
  41. 0 0
      old/include/core/data/RingBuffer.hpp
  42. 0 0
      old/include/core/data/Stack.hpp
  43. 0 0
      old/include/core/io/File.hpp
  44. 0 0
      old/include/core/io/FileReader.hpp
  45. 0 0
      old/include/core/math/Box.hpp
  46. 0 0
      old/include/core/math/BufferedValue.hpp
  47. 0 0
      old/include/core/math/Frustum.hpp
  48. 0 0
      old/include/core/math/Math.hpp
  49. 0 0
      old/include/core/math/Matrix.hpp
  50. 0 0
      old/include/core/math/MatrixStack.hpp
  51. 0 0
      old/include/core/math/Plane.hpp
  52. 0 0
      old/include/core/math/Quaternion.hpp
  53. 0 0
      old/include/core/math/Vector.hpp
  54. 0 0
      old/include/core/math/View.hpp
  55. 0 0
      old/include/core/thread/Mutex.hpp
  56. 0 0
      old/include/core/thread/SpinLock.hpp
  57. 0 0
      old/include/core/thread/Thread.hpp
  58. 0 0
      old/include/core/utils/AlignedData.hpp
  59. 0 0
      old/include/core/utils/ArrayString.hpp
  60. 0 0
      old/include/core/utils/Buffer.hpp
  61. 0 0
      old/include/core/utils/Check.hpp
  62. 0 0
      old/include/core/utils/Clock.hpp
  63. 0 0
      old/include/core/utils/Color.hpp
  64. 0 0
      old/include/core/utils/Error.hpp
  65. 0 0
      old/include/core/utils/HashCode.hpp
  66. 0 0
      old/include/core/utils/HashedString.hpp
  67. 0 0
      old/include/core/utils/Logger.hpp
  68. 0 0
      old/include/core/utils/Meta.hpp
  69. 0 0
      old/include/core/utils/New.hpp
  70. 0 0
      old/include/core/utils/Random.hpp
  71. 0 0
      old/include/core/utils/Types.hpp
  72. 0 0
      old/include/core/utils/UniquePointer.hpp
  73. 0 0
      old/include/core/utils/Utility.hpp
  74. 0 0
      old/performance/Main.cpp
  75. 0 0
      old/src/ArrayString.cpp
  76. 0 0
      old/src/BitArray.cpp
  77. 0 0
      old/src/Box.cpp
  78. 0 0
      old/src/Buffer.cpp
  79. 0 0
      old/src/Clock.cpp
  80. 0 0
      old/src/Error.cpp
  81. 0 0
      old/src/ErrorSimulator.cpp
  82. 0 0
      old/src/ErrorSimulator.hpp
  83. 0 0
      old/src/FileReader.cpp
  84. 0 0
      old/src/Frustum.cpp
  85. 0 0
      old/src/Logger.cpp
  86. 0 0
      old/src/Matrix.cpp
  87. 0 0
      old/src/Mutex.cpp
  88. 0 0
      old/src/New.cpp
  89. 0 0
      old/src/Plane.cpp
  90. 0 0
      old/src/Quaternion.cpp
  91. 0 0
      old/src/Random.cpp
  92. 0 0
      old/src/SpinLock.cpp
  93. 0 0
      old/src/Thread.cpp
  94. 0 0
      old/src/Utility.cpp
  95. 0 0
      old/src/Vector.cpp
  96. 0 0
      old/src/View.cpp
  97. 0 0
      old/tasks
  98. 0 0
      old/test/Main.cpp
  99. 0 0
      old/test/Test.cpp
  100. 0 0
      old/test/Test.hpp

+ 0 - 3
.clangd

@@ -1,3 +0,0 @@
-CompileFlags:
-  Add: [-ferror-limit=0, -std=c++20, -DERROR_SIMULATOR=true]
-  CompilationDatabase: ./build_debug/

+ 99 - 209
CMakeLists.txt

@@ -1,248 +1,138 @@
 cmake_minimum_required(VERSION 3.25)
-project(core)
+project(core C)
 
-set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_C_STANDARD 23)
 
 set(SRC
-    "src/Logger.cpp"
-    "src/Utility.cpp"
-    "src/Error.cpp"
-    "src/New.cpp"
-    "src/Buffer.cpp"
-    "src/Clock.cpp"
-    "src/Random.cpp"
-    "src/BitArray.cpp"
-    "src/Vector.cpp"
-    "src/Quaternion.cpp"
-    "src/Matrix.cpp"
-    "src/Box.cpp"
-    "src/Plane.cpp"
-    "src/Frustum.cpp"
-    "src/View.cpp"
-    "src/Thread.cpp"
-    "src/Mutex.cpp"
-    "src/SpinLock.cpp"
-    "src/FileReader.cpp"
-    "src/ErrorSimulator.cpp"
-    "src/ArrayString.cpp"
+    "src/BitArray.c"
+    "src/Box.c"
+    "src/Buffer.c"
+    "src/Components.c"
+    "src/File.c"
+    "src/Frustum.c"
+    "src/HashMap.c"
+    "src/Logger.c"
+    "src/Matrix.c"
+    "src/Plane.c"
+    "src/Quaternion.c"
+    "src/Random.c"
+    "src/ReadLine.c"
+    "src/SpinLock.c"
+    "src/Terminal.c"
+    "src/Test.c"
+    "src/Thread.c"
+    "src/ToString.c"
+    "src/Unicode.c"
+    "src/Utility.c"
+    "src/Vector.c"
+    "src/View.c"
 )
 
 set(SRC_TESTS
-    "test/Main.cpp"
-    "test/Test.cpp"
-    "test/modules/ArrayTests.cpp"
-    "test/modules/ArrayStringTests.cpp"
-    "test/modules/UtilityTests.cpp"
-    "test/modules/ArrayListTests.cpp"
-    "test/modules/BitArrayTests.cpp"
-    "test/modules/MathTests.cpp"
-    "test/modules/ListTests.cpp"
-    "test/modules/LinkedListTests.cpp"
-    "test/modules/UniquePointerTests.cpp"
-    "test/modules/HashMapTests.cpp"
-    "test/modules/StackTests.cpp"
-    "test/modules/RingBufferTests.cpp"
-    "test/modules/ComponentsTests.cpp"
-    "test/modules/VectorTests.cpp"
-    "test/modules/QuaternionTests.cpp"
-    "test/modules/MatrixTests.cpp"
-    "test/modules/BoxTests.cpp"
-    "test/modules/BufferedValueTests.cpp"
-    "test/modules/PlaneTests.cpp"
-    "test/modules/FrustumTests.cpp"
-    "test/modules/ViewTests.cpp"
-    "test/modules/MatrixStackTests.cpp"
-    "test/modules/ColorTests.cpp"
-    "test/modules/BufferTests.cpp"
-    "test/modules/ClockTests.cpp"
-    "test/modules/RandomTests.cpp"
-    "test/modules/ThreadTests.cpp"
-    "test/modules/FileReaderTests.cpp"
-    "test/modules/ErrorTests.cpp"
-    "test/modules/NewTests.cpp"
-    "test/modules/HashedStringTests.cpp"
+    "test/Main.c"
+    "test/modules/BitArrayTests.c"
+    "test/modules/BoxTests.c"
+    "test/modules/BufferTests.c"
+    "test/modules/ComponentsTests.c"
+    "test/modules/FileTests.c"
+    "test/modules/FrustumTests.c"
+    "test/modules/HashMapTests.c"
+    "test/modules/ListTests.c"
+    "test/modules/MatrixTests.c"
+    "test/modules/PlaneTests.c"
+    "test/modules/QuaternionTests.c"
+    "test/modules/QueueTests.c"
+    "test/modules/RandomTests.c"
+    "test/modules/ReadLineTests.c"
+    "test/modules/SpinLockTests.c"
+    "test/modules/TerminalTests.c"
+    "test/modules/TestTests.c"
+    "test/modules/UnicodeTests.c"
+    "test/modules/UtilityTests.c"
+    "test/modules/VectorTests.c"
+    "test/modules/ViewTests.c"
 )
 
 set(SRC_PERFORMANCE
-    "performance/Main.cpp"
-    "test/Test.cpp"
+    "performance/Main.c"
 )
 
 if("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
-    set(COMPILE_OPTIONS -flto)
-    set(LINK_OPTIONS -flto)
+    set(COMPILE_OPTIONS "")
+    set(LINK_OPTIONS "")
     set(LOG_LEVEL 2)
-    set(ERROR_SIMULATOR "")
+    set(DEFINITIONS CHECK_MEMORY)
 else()
-    if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+    set(DEFINITIONS ERROR_SIMULATOR CHECK_MEMORY)
+    if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
         set(COMPILE_OPTIONS --coverage)
+        set(LINK_OPTIONS gcov)
+    elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+        set(COMPILE_OPTIONS -fprofile-instr-generate -fcoverage-mapping)
+        set(LINK_OPTIONS ${COMPILE_OPTIONS})
     endif()
-    set(LINK_OPTIONS gcov)
     set(LOG_LEVEL 4)
-    set(ERROR_SIMULATOR "ERROR_SIMULATOR")
+    list(APPEND SRC "src/ErrorSimulator.c")
 endif()
 
-if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-    set(MORE_WARNINGS
-        -Waligned-new=all
-        -Walloc-zero
-        -Wanalyzer-too-complex
-        -Warith-conversion
-        -Warray-bounds=2
-        -Wattribute-alias=2
-        -Wbidi-chars=any
-        -Wcast-align=strict
-        -Wcatch-value=3
-        -Wcomma-subscript
-        -Wconditionally-supported
-        -Wduplicated-branches
-        -Wduplicated-cond
-        -Wformat-overflow=2
-        -Wformat-signedness
-        -Wformat-truncation=2
-        -Wimplicit-fallthrough=5
-        -Winvalid-imported-macros
-        -Wlogical-op
-        -Wmultiple-inheritance
-        -Wnoexcept
-        -Wnormalized=nfkc
-        -Wplacement-new=2
-        -Wredundant-tags
-        -Wshift-overflow=2
-        -Wstack-usage=8388608
-        -Wstrict-null-sentinel
-        -Wstringop-overflow=4
-        -Wsuggest-final-methods
-        -Wsuggest-final-types
-        -Wtrampolines
-        -Wtrivial-auto-var-init
-        -Wunused-const-variable=2
-        -Wuse-after-free=3
-        -Wvirtual-inheritance
-        -Wvolatile
-    )
+if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
+    include("cmake/gcc_warnings.cmake")
+elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+    include("cmake/clang_warnings.cmake")
 endif()
 
 add_library(core STATIC ${SRC})
 target_compile_options(core PUBLIC
     ${COMPILE_OPTIONS}
+    ${WARNINGS}
     -fdiagnostics-color=always
-    -fno-exceptions
-    -fno-rtti
-    -fno-threadsafe-statics
-    # deactivated due to the need for <atomic>
-    #-nostdinc++
-    -pedantic
-    -pedantic-errors
-    -Wall
-    -Walloca
-    -Warray-parameter
-    -Wcast-qual
-    -Wconversion
-    -Wctad-maybe-unsupported
-    -Wctor-dtor-privacy
-    -Wdate-time
-    -Wdeprecated-copy-dtor
-    -Wdeprecated-enum-enum-conversion
-    -Wdeprecated-enum-float-conversion
-    -Wdisabled-optimization
-    -Wdouble-promotion
-    -Weffc++
-    -Wenum-compare
-    -Wenum-conversion
-    -Werror
-    -Wextra
-    -Wextra-semi
-    -Wfloat-equal
-    -Wformat=2
-    -Wframe-larger-than=8388608
-    -Winfinite-recursion
-    -Winit-self
-    -Winvalid-pch
-    -Wlarger-than=1073741824
-    -Wmismatched-tags
-    -Wmissing-braces
-    -Wmissing-declarations
-    -Wmissing-include-dirs
-    -Wmultichar
-    -Wnon-virtual-dtor
-    -Wnull-dereference
-    -Wold-style-cast
-    -Woverlength-strings
-    -Woverloaded-virtual
-    -Wredundant-decls
-    -Wregister
-    -Wshadow
-    -Wsign-conversion
-    -Wsign-promo
-    -Wstack-protector
-    -Wstrict-overflow=2
-    -Wsuggest-override
-    -Wswitch-enum
-    -Wsynth
-    -Wundef
-    -Wunreachable-code
-    -Wvla
-    -Wwrite-strings
-    -Wzero-as-null-pointer-constant
-    ${MORE_WARNINGS}
 )
-target_compile_definitions(core 
-    PUBLIC CORE_LOG_LEVEL=${LOG_LEVEL}
-    PRIVATE ${ERROR_SIMULATOR}
+target_compile_definitions(core
+    PUBLIC LOG_LEVEL=${LOG_LEVEL}
+    PRIVATE ${DEFINITIONS}
 )
-target_link_libraries(core 
-    PUBLIC -nodefaultlibs c m
-    PRIVATE ${LINK_OPTIONS}
+target_link_libraries(core
+    PRIVATE m ${LINK_OPTIONS}
 )
-target_sources(core PUBLIC 
+target_sources(core PUBLIC
     FILE_SET HEADERS
     BASE_DIRS include
-    FILES 
-        ./include/core/data/Stack.hpp
-        ./include/core/data/HashMap.hpp
-        ./include/core/data/Components.hpp
-        ./include/core/data/ArrayList.hpp
-        ./include/core/data/ProbingHashMap.hpp
-        ./include/core/data/List.hpp
-        ./include/core/data/LinkedList.hpp
-        ./include/core/data/BitArray.hpp
-        ./include/core/data/Array.hpp
-        ./include/core/data/RingBuffer.hpp
-        ./include/core/thread/Thread.hpp
-        ./include/core/utils/HashCode.hpp
-        ./include/core/utils/New.hpp
-        ./include/core/utils/Check.hpp
-        ./include/core/utils/Buffer.hpp
-        ./include/core/utils/Random.hpp
-        ./include/core/utils/UniquePointer.hpp
-        ./include/core/utils/Types.hpp
-        ./include/core/utils/Color.hpp
-        ./include/core/utils/Logger.hpp
-        ./include/core/utils/ArrayString.hpp
-        ./include/core/utils/Utility.hpp
-        ./include/core/utils/Meta.hpp
-        ./include/core/utils/AlignedData.hpp
-        ./include/core/utils/Clock.hpp
-        ./include/core/utils/Error.hpp
-        ./include/core/math/Quaternion.hpp
-        ./include/core/math/Box.hpp
-        ./include/core/math/Frustum.hpp
-        ./include/core/math/Vector.hpp
-        ./include/core/math/Matrix.hpp
-        ./include/core/math/View.hpp
-        ./include/core/math/BufferedValue.hpp
-        ./include/core/math/Plane.hpp
-        ./include/core/math/MatrixStack.hpp
-        ./include/core/math/Math.hpp
-        ./include/core/io/File.hpp
-        ./include/core/io/FileReader.hpp
+    FILES
+        ./include/core/BitArray.h
+        ./include/core/Box.h
+        ./include/core/Buffer.h
+        ./include/core/Check.h
+        ./include/core/Components.h
+        ./include/core/File.h
+        ./include/core/Frustum.h
+        ./include/core/Generic.h
+        ./include/core/HashMap.h
+        ./include/core/List.h
+        ./include/core/Logger.h
+        ./include/core/Matrix.h
+        ./include/core/Plane.h
+        ./include/core/Quaternion.h
+        ./include/core/Queue.h
+        ./include/core/Random.h
+        ./include/core/ReadLine.h
+        ./include/core/SpinLock.h
+        ./include/core/Terminal.h
+        ./include/core/Test.h
+        ./include/core/Thread.h
+        ./include/core/ToString.h
+        ./include/core/Types.h
+        ./include/core/Unicode.h
+        ./include/core/Utility.h
+        ./include/core/Vector.h
+        ./include/core/View.h
 )
 install(TARGETS core FILE_SET HEADERS)
 
 add_executable(test ${SRC_TESTS})
 target_link_libraries(test PRIVATE core)
-target_compile_definitions(test PRIVATE ${ERROR_SIMULATOR})
+target_compile_definitions(test PRIVATE ${DEFINITIONS})
 
 add_executable(performance ${SRC_PERFORMANCE})
 target_link_libraries(performance PRIVATE core)
+target_include_directories(performance PRIVATE include)
+target_compile_definitions(performance PRIVATE ${DEFINITIONS})

+ 60 - 0
cmake/clang_warnings.cmake

@@ -0,0 +1,60 @@
+set(WARNINGS
+    -Wall
+    -Walloca
+    -Warray-parameter
+    -Wbad-function-cast
+    -Wcast-qual
+    -Wconditional-uninitialized
+    -Wconversion
+    -Wdate-time
+    -Wdisabled-optimization
+    -Wdouble-promotion
+    -Wenum-compare
+    -Wenum-conversion
+    -Werror
+    -Wextra
+    -Wextra-semi-stmt
+    -Wfloat-equal
+    -Wformat=2
+    -Wframe-larger-than=8388608
+    -Winfinite-recursion
+    -Winit-self
+    -Winvalid-pch
+    -Wlarger-than=1073741824
+    -Wmissing-braces
+    -Wmissing-declarations
+    -Wmissing-include-dirs
+    -Wmissing-noreturn 
+    -Wmissing-prototypes
+    -Wmissing-variable-declarations
+    -Wmultichar
+    -Wnarrowing
+    -Wnested-externs
+    -Wnull-dereference
+    -Wold-style-definition
+    -Woverlength-strings
+    -Wredundant-decls
+    -Wshadow
+    -Wsign-conversion
+    -Wstack-protector
+    -Wstrict-overflow=2
+    -Wstrict-prototypes
+    -Wswitch-enum
+    -Wundef
+    -Wunreachable-code
+    -Wvla
+    -Wwrite-strings
+    -pedantic
+    -pedantic-errors
+)
+
+if(0)
+    set(WARNINGS ${WARNINGS} 
+        -Weverything
+        -Wno-unsafe-buffer-usage
+        -Wno-c++98-compat
+        -Wno-declaration-after-statement
+        -Wno-pre-c2x-compat
+        -Wno-padded
+    )
+endif()

+ 70 - 0
cmake/gcc_warnings.cmake

@@ -0,0 +1,70 @@
+set(WARNINGS
+    -Wno-attributes
+
+    -Wall
+    -Walloc-zero
+    -Walloca
+    -Wanalyzer-too-complex
+    -Warith-conversion
+    -Warray-bounds=2
+    -Warray-parameter
+    -Wattribute-alias=2
+    -Wbad-function-cast
+    -Wbidi-chars=any
+    -Wcast-align=strict
+    -Wcast-qual
+    -Wconversion
+    -Wdate-time
+    -Wdisabled-optimization
+    -Wdouble-promotion
+    -Wduplicated-branches
+    -Wduplicated-cond
+    -Wenum-compare
+    -Wenum-conversion
+    -Werror
+    -Wextra
+    -Wfloat-equal
+    -Wformat-overflow=2
+    -Wformat-signedness
+    -Wformat-truncation=2
+    -Wformat=2
+    -Wframe-larger-than=8388608
+    -Wimplicit-fallthrough=5
+    -Winfinite-recursion
+    -Winit-self
+    -Winvalid-pch
+    -Wjump-misses-init
+    -Wlarger-than=1073741824
+    -Wlogical-op
+    -Wmissing-braces
+    -Wmissing-declarations
+    -Wmissing-include-dirs
+    -Wmissing-prototypes
+    -Wmultichar
+    -Wnarrowing
+    -Wnested-externs
+    -Wnormalized=nfkc
+    -Wnull-dereference
+    -Wold-style-definition
+    -Woverlength-strings
+    -Wredundant-decls
+    -Wshadow
+    -Wshift-overflow=2
+    -Wsign-conversion
+    -Wstack-protector
+    -Wstack-usage=8388608
+    -Wstrict-overflow=2
+    -Wstrict-prototypes
+    -Wstringop-overflow=4
+    -Wswitch-enum
+    -Wtrampolines
+    -Wtrivial-auto-var-init
+    -Wundef
+    -Wunreachable-code
+    -Wunused-const-variable=2
+    -Wuse-after-free=3
+    -Wvla
+    -Wwrite-strings
+    -pedantic
+    -pedantic-errors
+)

+ 23 - 0
include/core/BitArray.h

@@ -0,0 +1,23 @@
+#ifndef CORE_BIT_ARRAY_H
+#define CORE_BIT_ARRAY_H
+
+#include "core/Types.h"
+
+typedef struct {
+    u64 length : 56;
+    u64 bits : 8;
+    u64* data;
+} BitArray;
+
+static_assert(sizeof(BitArray) == 16, "invalid bit array size");
+
+void initBitArray(BitArray* a, size_t length, size_t bits);
+void destroyBitArray(BitArray* a);
+void setBits(BitArray* a, size_t index, u64 value);
+void setAllBits(BitArray* a, u64 value);
+u64 getBits(const BitArray* a, size_t index);
+i64 selectBits(const BitArray* a, size_t index);
+void setBitLength(BitArray* a, size_t newLength, size_t newBits);
+size_t toStringBitArray(const BitArray* a, char* buffer, size_t n);
+
+#endif

+ 23 - 0
include/core/Box.h

@@ -0,0 +1,23 @@
+#ifndef CORE_BOX_H
+#define CORE_BOX_H
+
+#include "core/Vector.h"
+
+typedef union {
+    struct {
+        Vector3 min;
+        Vector3 max;
+    };
+
+    Vector3 v[2];
+} Box;
+
+#define BOX ((Box){0})
+void setBox(Box* box, const Vector3* size);
+void offsetBox(Box* box, const Vector3* offset);
+bool collidesWithBox(const Box* box, const Box* other);
+void expandBox(Box* box, const Vector3* offset);
+void growBox(Box* box, const Vector3* growth);
+size_t toStringBox(const Box* box, char* buffer, size_t n);
+
+#endif

+ 19 - 0
include/core/Buffer.h

@@ -0,0 +1,19 @@
+#ifndef CORE_BUFFER_H
+#define CORE_BUFFER_H
+
+#include <stddef.h>
+
+typedef struct {
+    size_t size;
+    size_t capacity;
+    char* buffer;
+} Buffer;
+
+void initBuffer(Buffer* b);
+void destroyBuffer(Buffer* b);
+void addSizedBufferData(Buffer* b, const void* data, size_t size);
+#define addTypedBufferData(buffer, type, ...)                      \
+    addSizedBufferData(buffer, &(type){__VA_ARGS__}, sizeof(type))
+void clearBuffer(Buffer* b);
+
+#endif

+ 19 - 0
include/core/Check.h

@@ -0,0 +1,19 @@
+#ifndef CORE_CHECK_H
+#define CORE_CHECK_H
+
+#if defined(__GNUC__)
+#define check_format(format_index, arg_start_index)                \
+    __attribute__((format(printf, format_index, arg_start_index)))
+#else
+#error "please add a 'check_format' option"
+#endif
+
+#if defined(__GNUC__)
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+#define likely(x) x
+#define unlikely(x) x
+#endif
+
+#endif

+ 127 - 0
include/core/Components.h

@@ -0,0 +1,127 @@
+#ifndef CORE_COMPONENTS_H
+#define CORE_COMPONENTS_H
+
+#include "core/HashMap.h"
+#include "core/List.h"
+
+#define isInvalidKeySize(key) ((key) == 0)
+#define equalSize(a, b) ((a) == (b))
+#define hashSize(key) (key)
+
+LIST(size_t, Size)
+HASHMAP(size_t, size_t, Size)
+
+typedef size_t Entity;
+
+#define COMPONENTS(T, N)                                                       \
+    typedef struct {                                                           \
+        HashMapSize entityToIndex;                                             \
+        ListSize indexToEntity;                                                \
+        List##N components;                                                    \
+    } Components##N;                                                           \
+                                                                               \
+    typedef struct {                                                           \
+        Entity entity;                                                         \
+        T* component;                                                          \
+    } ComponentNode##N;                                                        \
+                                                                               \
+    typedef struct {                                                           \
+        const Entity* indexToEntity;                                           \
+        const Entity* indexToEntityEnd;                                        \
+        T* component;                                                          \
+        T* componentEnd;                                                       \
+        ComponentNode##N node;                                                 \
+    } ComponentIterator##N;                                                    \
+                                                                               \
+    void initComponents##N(Components##N* c);                                  \
+    void destroyComponents##N(Components##N* c);                               \
+    T* getOrAddComponent##N(Components##N* c, Entity e);                       \
+    T* searchComponent##N(Components##N* c, Entity e);                         \
+    bool removeComponent##N(Components##N* c, Entity e);                       \
+    void initComponentIterator##N(ComponentIterator##N* ci, Components##N* c); \
+    bool hasNextComponentNode##N(ComponentIterator##N* ci);                    \
+    ComponentNode##N* nextComponentNode##N(ComponentIterator##N* ci);          \
+    T* getComponentsStart##N(Components##N* c);                                \
+    T* getComponentsEnd##N(Components##N* c);
+
+#define COMPONENTS_SOURCE(T, N)                                         \
+    void initComponents##N(Components##N* c) {                          \
+        initHashMapSize(&c->entityToIndex);                             \
+        initListSize(&c->indexToEntity);                                \
+        initList##N(&c->components);                                    \
+    }                                                                   \
+                                                                        \
+    void destroyComponents##N(Components##N* c) {                       \
+        destroyHashMapSize(&c->entityToIndex);                          \
+        destroyListSize(&c->indexToEntity);                             \
+        destroyList##N(&c->components);                                 \
+    }                                                                   \
+                                                                        \
+    T* getOrAddComponent##N(Components##N* c, Entity e) {               \
+        void* component = searchComponent##N(c, e);                     \
+        if(component != nullptr) {                                      \
+            return component;                                           \
+        }                                                               \
+        size_t index = c->components.length;                            \
+        *putHashMapKeySize(&c->entityToIndex, e) = index;               \
+        addListDataSize(&c->indexToEntity, e);                          \
+        return addEmptyListData##N(&c->components);                     \
+    }                                                                   \
+                                                                        \
+    T* searchComponent##N(Components##N* c, Entity e) {                 \
+        size_t* index = searchHashMapKeySize(&c->entityToIndex, e);     \
+        if(index == nullptr) {                                          \
+            return nullptr;                                             \
+        }                                                               \
+        return getListIndex##N(&c->components, *index);                 \
+    }                                                                   \
+                                                                        \
+    bool removeComponent##N(Components##N* c, Entity e) {               \
+        size_t* indexP = searchHashMapKeySize(&c->entityToIndex, e);    \
+        if(indexP == nullptr) {                                         \
+            return false;                                               \
+        }                                                               \
+        size_t lastIndex = c->components.length - 1;                    \
+        size_t index = *indexP;                                         \
+        removeHashMapKeySize(&c->entityToIndex, e);                     \
+        removeListIndexBySwap##N(&c->components, index);                \
+        if(index == lastIndex) {                                        \
+            removeListIndexBySwapSize(&c->indexToEntity, index);        \
+            return true;                                                \
+        }                                                               \
+        Entity other = *getListIndexSize(&c->indexToEntity, lastIndex); \
+        removeListIndexBySwapSize(&c->indexToEntity, index);            \
+        *putHashMapKeySize(&c->entityToIndex, other) = index;           \
+        return true;                                                    \
+    }                                                                   \
+                                                                        \
+    void initComponentIterator##N(                                      \
+        ComponentIterator##N* ci, Components##N* c) {                   \
+        ci->indexToEntity = getListStartSize(&c->indexToEntity);        \
+        ci->indexToEntityEnd = getListEndSize(&c->indexToEntity);       \
+        ci->component = getListStart##N(&c->components);                \
+        ci->componentEnd = getListEnd##N(&c->components);               \
+        ci->node = (ComponentNode##N){0};                               \
+    }                                                                   \
+                                                                        \
+    bool hasNextComponentNode##N(ComponentIterator##N* ci) {            \
+        return ci->indexToEntity != ci->indexToEntityEnd;               \
+    }                                                                   \
+                                                                        \
+    ComponentNode##N* nextComponentNode##N(ComponentIterator##N* ci) {  \
+        ci->node.component = ci->component;                             \
+        ci->node.entity = *ci->indexToEntity;                           \
+        ci->indexToEntity++;                                            \
+        ci->component++;                                                \
+        return &ci->node;                                               \
+    }                                                                   \
+                                                                        \
+    T* getComponentsStart##N(Components##N* c) {                        \
+        return getListStart##N(&c->components);                         \
+    }                                                                   \
+                                                                        \
+    T* getComponentsEnd##N(Components##N* c) {                          \
+        return getListEnd##N(&c->components);                           \
+    }
+
+#endif

+ 14 - 0
include/core/File.h

@@ -0,0 +1,14 @@
+#ifndef CORE_FILE_H
+#define CORE_FILE_H
+
+#include <stddef.h>
+
+typedef struct {
+    char* data;
+    size_t length;
+} FileContent;
+
+bool readFile(FileContent* f, const char* path);
+void destroyFileContent(FileContent* f);
+
+#endif

+ 23 - 0
include/core/Frustum.h

@@ -0,0 +1,23 @@
+#ifndef CORE_FRUSTUM_H
+#define CORE_FRUSTUM_H
+
+#include "core/Matrix.h"
+#include "core/Plane.h"
+
+typedef struct {
+    Matrix projection;
+    Plane planes[6];
+    float tan;
+    float nearClip;
+    float farClip;
+} Frustum;
+
+void initFrustum(Frustum* f, float fieldOfView, float nearClip, float farClip);
+const Matrix* updateProjection(Frustum* f, const IntVector2* size);
+void updateFrustumPlanes(
+    Frustum* f, const Vector3* pos, const Vector3* right, const Vector3* up,
+    const Vector3* front, const IntVector2* size);
+bool isInsideFrustum(const Frustum* f, const Vector3* pos);
+bool isInsideFrustumRadius(const Frustum* f, const Vector3* pos, float radius);
+
+#endif

+ 134 - 0
include/core/Generic.h

@@ -0,0 +1,134 @@
+#ifndef CORE_GENERIC_H
+#define CORE_GENERIC_H
+
+#include "core/Matrix.h"
+
+// clang-format off
+#define GENERIC_PAIR(type, name) type: name, const type : name
+// clang-format on
+
+#define GENERIC_FLOAT_VECTOR(a, name)     \
+    _Generic(                             \
+        (a),                              \
+        GENERIC_PAIR(Vector2*, name##V2), \
+        GENERIC_PAIR(Vector3*, name##V3), \
+        GENERIC_PAIR(Vector4*, name##V4))
+
+#define GENERIC_VECTOR(a, name)               \
+    _Generic(                                 \
+        (a),                                  \
+        GENERIC_PAIR(Vector2*, name##V2),     \
+        GENERIC_PAIR(Vector3*, name##V3),     \
+        GENERIC_PAIR(Vector4*, name##V4),     \
+        GENERIC_PAIR(IntVector2*, name##IV2), \
+        GENERIC_PAIR(IntVector3*, name##IV3), \
+        GENERIC_PAIR(IntVector4*, name##IV4))
+
+#define ZERO_VECTOR(a)                               \
+    _Generic(                                        \
+        (a),                                         \
+        GENERIC_PAIR(Matrix*, &(Vector3){0}),        \
+        GENERIC_PAIR(Vector2*, &(Vector2){0}),       \
+        GENERIC_PAIR(Vector3*, &(Vector3){0}),       \
+        GENERIC_PAIR(Vector4*, &(Vector4){0}),       \
+        GENERIC_PAIR(IntVector2*, &(IntVector2){0}), \
+        GENERIC_PAIR(IntVector3*, &(IntVector3){0}), \
+        GENERIC_PAIR(IntVector4*, &(IntVector4){0}))
+
+#define GENERIC_FACTOR(b, type, base, factor)                \
+    type:                                                    \
+    _Generic((b), GENERIC_PAIR(type, base), default: factor)
+
+#define SELECT_OP(_1, _2, _3, name, ...) name
+
+#define addSet(a, b) GENERIC_VECTOR(a, addSet)(a, b)
+#define add3(a, b, c) GENERIC_VECTOR(a, add)(a, b, c)
+#define add2(a, b) add3(ZERO_VECTOR(a), a, b)
+#define add(...) SELECT_OP(__VA_ARGS__, add3, add2, 0)(__VA_ARGS__)
+
+#define subSet(a, b) GENERIC_VECTOR(a, subSet)(a, b)
+#define sub3(a, b, c) GENERIC_VECTOR(a, sub)(a, b, c)
+#define sub2(a, b) sub3(ZERO_VECTOR(a), a, b)
+#define sub(...) SELECT_OP(__VA_ARGS__, sub3, sub2, 0)(__VA_ARGS__)
+
+#define mulSet(a, b)                                                 \
+    _Generic(                                                        \
+        (a),                                                         \
+        Matrix *: mulSetMatrix,                                      \
+        Quaternion *: mulSetQ,                                       \
+        GENERIC_FACTOR(b, Vector2*, mulSetV2, mulSetV2F),            \
+        GENERIC_FACTOR(b, Vector3*, mulSetV3, mulSetV3F),            \
+        GENERIC_FACTOR(b, Vector4*, mulSetV4, mulSetV4F),            \
+        GENERIC_FACTOR(b, IntVector2*, mulSetIV2, mulSetIV2F),       \
+        GENERIC_FACTOR(b, IntVector3*, mulSetIV3, mulSetIV3F),       \
+        GENERIC_FACTOR(b, IntVector4*, mulSetIV4, mulSetIV4F))(a, b)
+
+#define mul3(a, b, c)                                             \
+    _Generic(                                                     \
+        (a),                                                      \
+        Matrix *: mulMatrix,                                      \
+        Quaternion *: mulQ,                                       \
+        GENERIC_FACTOR(c, Vector2*, mulV2, mulV2F),               \
+        Vector3 *: _Generic(                                      \
+                     (c),                                         \
+                Vector3 *: _Generic(                              \
+                             (b),                                 \
+                        GENERIC_PAIR(Quaternion*, mulQV3),        \
+                        GENERIC_PAIR(Matrix*, mulMatrixV3),       \
+                        default: mulV3),                          \
+                default: mulV3F),                                 \
+        GENERIC_FACTOR(c, Vector4*, mulV4, mulV4F),               \
+        GENERIC_FACTOR(c, IntVector2*, mulIV2, mulIV2F),          \
+        GENERIC_FACTOR(c, IntVector3*, mulIV3, mulIV3F),          \
+        GENERIC_FACTOR(c, IntVector4*, mulIV4, mulIV4F))(a, b, c)
+#define mul2(a, b) mul3(ZERO_VECTOR(a), a, b)
+#define mul(...) SELECT_OP(__VA_ARGS__, mul3, mul2, 0)(__VA_ARGS__)
+
+#define divSet(a, b)                                                 \
+    _Generic(                                                        \
+        (a),                                                         \
+        GENERIC_FACTOR(b, Vector2*, divSetV2, divSetV2F),            \
+        GENERIC_FACTOR(b, Vector3*, divSetV3, divSetV3F),            \
+        GENERIC_FACTOR(b, Vector4*, divSetV4, divSetV4F),            \
+        GENERIC_FACTOR(b, IntVector2*, divSetIV2, divSetIV2F),       \
+        GENERIC_FACTOR(b, IntVector3*, divSetIV3, divSetIV3F),       \
+        GENERIC_FACTOR(b, IntVector4*, divSetIV4, divSetIV4F))(a, b)
+
+#define div3(a, b, c)                                             \
+    _Generic(                                                     \
+        (a),                                                      \
+        GENERIC_FACTOR(c, Vector2*, divV2, divV2F),               \
+        GENERIC_FACTOR(c, Vector3*, divV3, divV3F),               \
+        GENERIC_FACTOR(c, Vector4*, divV4, divV4F),               \
+        GENERIC_FACTOR(c, IntVector2*, divIV2, divIV2F),          \
+        GENERIC_FACTOR(c, IntVector3*, divIV3, divIV3F),          \
+        GENERIC_FACTOR(c, IntVector4*, divIV4, divIV4F))(a, b, c)
+#define div2(a, b) div3(ZERO_VECTOR(a), a, b)
+#define div(...) SELECT_OP(__VA_ARGS__, div3, div2, 0)(__VA_ARGS__)
+
+#define invertSet(a) GENERIC_VECTOR(a, invertSet)(a)
+#define invert2(a, b) GENERIC_VECTOR(a, invert)(a, b)
+#define invert1(a) invert2(ZERO_VECTOR(a), a)
+#define invert(...) SELECT_OP(0, __VA_ARGS__, invert2, invert1, 0)(__VA_ARGS__)
+#define dot(a, b) GENERIC_FLOAT_VECTOR(a, dot)(a, b)
+#define squareLength(a) GENERIC_FLOAT_VECTOR(a, squareLength)(a)
+#define length(a) GENERIC_FLOAT_VECTOR(a, length)(a)
+#define normalize(a) GENERIC_FLOAT_VECTOR(a, normalize)(a)
+
+#undef cross
+#define SELECT_OP(_1, _2, _3, name, ...) name
+#define cross3(a, b, c) cross(a, b, c)
+#define cross2(a, b) cross(&(Vector3){0}, a, b)
+#define cross(...) SELECT_OP(__VA_ARGS__, cross3, cross2, 0)(__VA_ARGS__)
+
+#define convert(a, b)                  \
+    _Generic(                          \
+        (a),                           \
+        Vector2 *: convertIV2,         \
+        Vector3 *: convertIV3,         \
+        Vector4 *: convertIV4,         \
+        IntVector2 *: convertV2,       \
+        IntVector3 *: convertV3,       \
+        IntVector4 *: convertV4)(a, b)
+
+#endif

+ 237 - 0
include/core/HashMap.h

@@ -0,0 +1,237 @@
+#ifndef CORE_HASHMAP_H
+#define CORE_HASHMAP_H
+
+#include "core/ToString.h"
+#include "core/Types.h"
+#include "core/Utility.h"
+
+size_t hashString(const char* key);
+size_t roundUp2(size_t n);
+
+#define isInvalidKeyInt(key) ((key) == 0)
+#define equalInt(a, b) ((a) == (b))
+#define hashInt(key) ((size_t)key)
+#define isInvalidKeySize(key) ((key) == 0)
+#define equalSize(a, b) ((a) == (b))
+#define hashSize(key) (key)
+
+#define HASHMAP(K, V, N)                                                       \
+    typedef struct {                                                           \
+        K* keys;                                                               \
+        V* values;                                                             \
+        size_t capacity;                                                       \
+        size_t entries;                                                        \
+    } HashMap##N;                                                              \
+                                                                               \
+    void initHashMap##N(HashMap##N* m);                                        \
+    void destroyHashMap##N(HashMap##N* m);                                     \
+    void rehashHashMap##N(HashMap##N* m, size_t minCapacity);                  \
+    V* putHashMapKey##N(HashMap##N* m, K key);                                 \
+    V* searchHashMapKey##N(const HashMap##N* m, K key);                        \
+    void clearHashMap##N(HashMap##N* m);                                       \
+    bool removeHashMapKey##N(HashMap##N* m, K key);                            \
+                                                                               \
+    typedef struct {                                                           \
+        const K* key;                                                          \
+        V* value;                                                              \
+    } HashMapNode##N;                                                          \
+                                                                               \
+    typedef struct {                                                           \
+        K* key;                                                                \
+        K* endKey;                                                             \
+        V* value;                                                              \
+        V* endValue;                                                           \
+        const HashMap##N* map;                                                 \
+        HashMapNode##N node;                                                   \
+    } HashMapIterator##N;                                                      \
+                                                                               \
+    void initHashMapIterator##N(HashMapIterator##N* mi, const HashMap##N* m);  \
+    bool hasNextHashMapNode##N(HashMapIterator##N* mi);                        \
+    HashMapNode##N* nextHashMapNode##N(HashMapIterator##N* mi);                \
+    typedef size_t (*ToStringKey##N)(                                          \
+        K const* const data, char* buffer, size_t n);                          \
+    typedef size_t (*ToStringValue##N)(                                        \
+        V const* const data, char* buffer, size_t n);                          \
+    size_t toStringHashMap##N(                                                 \
+        const HashMap##N* m, char* buffer, size_t n, ToStringKey##N keyString, \
+        ToStringValue##N valueString);
+
+#define HASHMAP_SOURCE(K, V, N)                                                \
+    static size_t searchSlot##N(HashMap##N* m, K key) {                        \
+        size_t rehashFactor = 2;                                               \
+        while(true) {                                                          \
+            rehashHashMap##N(m, m->entries* rehashFactor + 1);                 \
+            if(isInvalidKey##N(key)) {                                         \
+                return m->capacity - 1;                                        \
+            }                                                                  \
+            size_t baseHash = hash##N(key) * 514'685'581u;                     \
+            size_t end = m->capacity - 2;                                      \
+            /* rehash on bad clustering */                                     \
+            for(size_t i = 0; i <= 5; i++) {                                   \
+                size_t hash = (baseHash + i) & end;                            \
+                K keyEntry = m->keys[hash];                                    \
+                if(isInvalidKey##N(keyEntry) || equal##N(keyEntry, key)) {     \
+                    return hash;                                               \
+                }                                                              \
+            }                                                                  \
+            rehashFactor *= 2;                                                 \
+        }                                                                      \
+    }                                                                          \
+                                                                               \
+    void initHashMap##N(HashMap##N* m) {                                       \
+        m->keys = nullptr;                                                     \
+        m->values = nullptr;                                                   \
+        m->capacity = 0;                                                       \
+        m->entries = 0;                                                        \
+    }                                                                          \
+                                                                               \
+    void destroyHashMap##N(HashMap##N* m) {                                    \
+        coreFree(m->keys);                                                     \
+        coreFree(m->values);                                                   \
+        *m = (HashMap##N){0};                                                  \
+    }                                                                          \
+                                                                               \
+    void rehashHashMap##N(HashMap##N* m, size_t minCapacity) {                 \
+        if(minCapacity <= m->capacity) {                                       \
+            return;                                                            \
+        }                                                                      \
+        size_t l = roundUp2(maxSize(minCapacity, 8lu)) + 1;                    \
+        HashMap##N map;                                                        \
+        initHashMap##N(&map);                                                  \
+        size_t keyBytes = l * sizeof(K);                                       \
+        map.keys = coreAllocate(keyBytes);                                     \
+        memset(map.keys, 0, keyBytes);                                         \
+        memset(map.keys + (l - 1), 1, sizeof(K));                              \
+        map.values = coreAllocate(l * sizeof(V));                              \
+        map.capacity = l;                                                      \
+                                                                               \
+        size_t length = m->capacity;                                           \
+        if(length > 0) {                                                       \
+            length--;                                                          \
+            for(size_t i = 0; i < length; i++) {                               \
+                K keyEntry = m->keys[i];                                       \
+                if(!isInvalidKey##N(keyEntry)) {                               \
+                    *putHashMapKey##N(&map, keyEntry) = m->values[i];          \
+                }                                                              \
+            }                                                                  \
+            K keyEntry = m->keys[length];                                      \
+            if(isInvalidKey##N(keyEntry)) {                                    \
+                *putHashMapKey##N(&map, keyEntry) = m->values[length];         \
+            }                                                                  \
+        }                                                                      \
+        swap(&map, m);                                                         \
+        destroyHashMap##N(&map);                                               \
+    }                                                                          \
+                                                                               \
+    V* putHashMapKey##N(HashMap##N* m, K key) {                                \
+        size_t index = searchSlot##N(m, key);                                  \
+        K* keyEntry = m->keys + index;                                         \
+        if(equal##N(*keyEntry, key)) {                                         \
+            return m->values + index;                                          \
+        }                                                                      \
+        m->entries++;                                                          \
+        *keyEntry = key;                                                       \
+        return m->values + index;                                              \
+    }                                                                          \
+                                                                               \
+    V* searchHashMapKey##N(const HashMap##N* m, K key) {                       \
+        if(m->capacity != 0) {                                                 \
+            if(isInvalidKey##N(key)) {                                         \
+                size_t i = m->capacity - 1;                                    \
+                return isInvalidKey##N(m->keys[i]) ? m->values + i : nullptr;  \
+            }                                                                  \
+            size_t baseHash = hash##N(key) * 514'685'581u;                     \
+            size_t end = m->capacity - 2;                                      \
+            for(size_t i = 0; i <= end; i++) {                                 \
+                size_t hash = (baseHash + i) & end;                            \
+                K keyEntry = m->keys[hash];                                    \
+                if(equal##N(keyEntry, key)) {                                  \
+                    return m->values + hash;                                   \
+                } else if(isInvalidKey##N(keyEntry)) {                         \
+                    return nullptr;                                            \
+                }                                                              \
+            }                                                                  \
+        }                                                                      \
+        return nullptr;                                                        \
+    }                                                                          \
+                                                                               \
+    void clearHashMap##N(HashMap##N* m) {                                      \
+        if(m->keys == nullptr) {                                               \
+            return;                                                            \
+        }                                                                      \
+        m->entries = 0;                                                        \
+        memset(m->keys, 0, m->capacity * sizeof(K));                           \
+        memset(m->keys + (m->capacity - 1), 1, sizeof(K));                     \
+    }                                                                          \
+                                                                               \
+    bool removeHashMapKey##N(HashMap##N* m, K key) {                           \
+        /* ToDo: This is a very slow remove */                                 \
+        HashMap##N n;                                                          \
+        initHashMap##N(&n);                                                    \
+        HashMapIterator##N i;                                                  \
+        initHashMapIterator##N(&i, m);                                         \
+        bool r = false;                                                        \
+        while(hasNextHashMapNode##N(&i)) {                                     \
+            HashMapNode##N* node = nextHashMapNode##N(&i);                     \
+            if(!equal##N(key, *node->key)) {                                   \
+                *putHashMapKey##N(&n, *node->key) = *node->value;              \
+            } else {                                                           \
+                r = true;                                                      \
+            }                                                                  \
+        }                                                                      \
+        swap(&n, m);                                                           \
+        destroyHashMap##N(&n);                                                 \
+        return r;                                                              \
+    }                                                                          \
+                                                                               \
+    void initHashMapIterator##N(HashMapIterator##N* mi, const HashMap##N* m) { \
+        mi->key = m->keys;                                                     \
+        mi->endKey = mi->key + m->capacity;                                    \
+        mi->value = m->values;                                                 \
+        mi->endValue = mi->value + m->capacity;                                \
+        mi->map = m;                                                           \
+    }                                                                          \
+                                                                               \
+    bool hasNextHashMapNode##N(HashMapIterator##N* mi) {                       \
+        while(mi->key != mi->endKey) {                                         \
+            K* nextKey = mi->key + 1;                                          \
+            if(isInvalidKey##N(*mi->key) == (nextKey == mi->endKey)) {         \
+                break;                                                         \
+            }                                                                  \
+            mi->key = nextKey;                                                 \
+            mi->value++;                                                       \
+        }                                                                      \
+        return mi->key != mi->endKey;                                          \
+    }                                                                          \
+                                                                               \
+    HashMapNode##N* nextHashMapNode##N(HashMapIterator##N* mi) {               \
+        mi->node.key = mi->key;                                                \
+        mi->node.value = mi->value;                                            \
+        mi->key++;                                                             \
+        mi->value++;                                                           \
+        return &mi->node;                                                      \
+    }                                                                          \
+                                                                               \
+    size_t toStringHashMap##N(                                                 \
+        const HashMap##N* m, char* buffer, size_t n, ToStringKey##N keyString, \
+        ToStringValue##N valueString) {                                        \
+        size_t w = 0;                                                          \
+        stringAdd(&w, &buffer, &n, toString(buffer, n, "["));                  \
+        bool notFirst = false;                                                 \
+        HashMapIterator##N i;                                                  \
+        initHashMapIterator##N(&i, m);                                         \
+        while(hasNextHashMapNode##N(&i)) {                                     \
+            HashMapNode##N* node = nextHashMapNode##N(&i);                     \
+            if(notFirst) {                                                     \
+                stringAdd(&w, &buffer, &n, toString(buffer, n, ", "));         \
+            }                                                                  \
+            notFirst = true;                                                   \
+            stringAdd(&w, &buffer, &n, keyString(node->key, buffer, n));       \
+            stringAdd(&w, &buffer, &n, toString(buffer, n, " = "));            \
+            stringAdd(&w, &buffer, &n, valueString(node->value, buffer, n));   \
+        }                                                                      \
+        stringAdd(&w, &buffer, &n, toString(buffer, n, "]"));                  \
+        return w;                                                              \
+    }
+
+#endif

+ 131 - 0
include/core/List.h

@@ -0,0 +1,131 @@
+#ifndef CORE_LIST_H
+#define CORE_LIST_H
+
+#include <assert.h>
+
+#include "core/ToString.h"
+#include "core/Types.h"
+#include "core/Utility.h"
+
+#define LIST(T, N)                                                        \
+    struct ListT##N {                                                     \
+        size_t length;                                                    \
+        size_t capacity;                                                  \
+        T* data;                                                          \
+    };                                                                    \
+    typedef struct ListT##N List##N;                                      \
+                                                                          \
+    void initList##N(List##N* l);                                         \
+    void destroyList##N(List##N* l);                                      \
+    void reserveListEntries##N(List##N* l, size_t n);                     \
+    void addListData##N(List##N* l, T data);                              \
+    void addLastListData##N(List##N* l);                                  \
+    T* addEmptyListData##N(List##N* l);                                   \
+    T* getListIndex##N(const List##N* l, size_t index);                   \
+    T* getListLast##N(const List##N* l);                                  \
+    void clearList##N(List##N* l);                                        \
+    void removeListIndexBySwap##N(List##N* l, size_t index);              \
+    void removeListIndex##N(List##N* l, size_t index);                    \
+    void removeListLast##N(List##N* l);                                   \
+    T* getListStart##N(const List##N* l);                                 \
+    T* getListEnd##N(const List##N* l);                                   \
+    typedef size_t (*ToString##N)(const T* data, char* buffer, size_t n); \
+    size_t toStringList##N(                                               \
+        const List##N* l, char* buffer, size_t n, ToString##N c);
+
+#define LIST_SOURCE(T, N)                                              \
+    void initList##N(List##N* l) {                                     \
+        *l = (List##N){0, 0, nullptr};                                 \
+    }                                                                  \
+                                                                       \
+    void destroyList##N(List##N* l) {                                  \
+        coreFree(l->data);                                             \
+        *l = (List##N){0};                                             \
+    }                                                                  \
+                                                                       \
+    void reserveListEntries##N(List##N* l, size_t n) {                 \
+        if(n > l->capacity) {                                          \
+            l->capacity = n;                                           \
+            l->data = coreReallocate(l->data, sizeof(T) * n);          \
+        }                                                              \
+    }                                                                  \
+                                                                       \
+    void addListData##N(List##N* l, T data) {                          \
+        *addEmptyListData##N(l) = data;                                \
+    }                                                                  \
+                                                                       \
+    void addLastListData##N(List##N* l) {                              \
+        addListData##N(l, *getListLast##N(l));                         \
+    }                                                                  \
+                                                                       \
+    T* addEmptyListData##N(List##N* l) {                               \
+        if(l->length >= l->capacity) {                                 \
+            reserveListEntries##N(                                     \
+                l, l->capacity + maxSize(4lu, l->capacity / 4));       \
+        }                                                              \
+        return l->data + l->length++;                                  \
+    }                                                                  \
+                                                                       \
+    T* getListIndex##N(const List##N* l, size_t index) {               \
+        assert(index < l->length);                                     \
+        return l->data + index;                                        \
+    }                                                                  \
+                                                                       \
+    T* getListLast##N(const List##N* l) {                              \
+        return getListIndex##N(l, l->length - 1);                      \
+    }                                                                  \
+                                                                       \
+    void clearList##N(List##N* l) {                                    \
+        l->length = 0;                                                 \
+    }                                                                  \
+                                                                       \
+    void removeListIndexBySwap##N(List##N* l, size_t index) {          \
+        assert(index < l->length);                                     \
+        size_t length = l->length - 1;                                 \
+        if(index != length) {                                          \
+            l->data[index] = l->data[length];                          \
+        }                                                              \
+        l->length = length;                                            \
+    }                                                                  \
+                                                                       \
+    void removeListIndex##N(List##N* l, size_t index) {                \
+        assert(index < l->length);                                     \
+        l->length--;                                                   \
+        T* p = l->data + index;                                        \
+        T* end = getListEnd##N(l);                                     \
+        while(p != end) {                                              \
+            *p = *(p + 1);                                             \
+            p++;                                                       \
+        }                                                              \
+    }                                                                  \
+                                                                       \
+    void removeListLast##N(List##N* l) {                               \
+        removeListIndexBySwap##N(l, l->length - 1);                    \
+    }                                                                  \
+                                                                       \
+    T* getListStart##N(const List##N* l) {                             \
+        return l->data;                                                \
+    }                                                                  \
+                                                                       \
+    T* getListEnd##N(const List##N* l) {                               \
+        return l->data + l->length;                                    \
+    }                                                                  \
+                                                                       \
+    size_t toStringList##N(                                            \
+        const List##N* l, char* buffer, size_t n, ToString##N c) {     \
+        size_t w = 0;                                                  \
+        stringAdd(&w, &buffer, &n, toString(buffer, n, "["));          \
+        T* end = getListEnd##N(l);                                     \
+        T* p = getListStart##N(l);                                     \
+        while(p != end) {                                              \
+            stringAdd(&w, &buffer, &n, c(p, buffer, n));               \
+            p++;                                                       \
+            if(p != end) {                                             \
+                stringAdd(&w, &buffer, &n, toString(buffer, n, ", ")); \
+            }                                                          \
+        }                                                              \
+        stringAdd(&w, &buffer, &n, toString(buffer, n, "]"));          \
+        return w;                                                      \
+    }
+
+#endif

+ 59 - 0
include/core/Logger.h

@@ -0,0 +1,59 @@
+#ifndef CORE_LOGGER_H
+#define CORE_LOGGER_H
+
+#include "core/Check.h"
+#include "core/Terminal.h"
+
+typedef enum { LOG_NONE, LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG } LogLevel;
+
+extern LogLevel logLevel;
+
+typedef void (*ReportHandler)(
+    LogLevel l, const char* file, int line, void* data, const char* message);
+check_format(4, 5) void callReportHandler(
+    LogLevel l, const char* file, int line, const char* format, ...);
+void setReportHandler(ReportHandler h, void* data);
+#define REPORT(l, ...) callReportHandler(l, __FILE__, __LINE__, __VA_ARGS__)
+
+const char* getShortFileName(const char* s);
+
+check_format(6, 7) void printLog(
+    LogLevel l, const char* file, int line, const char* prefix, const char* tag,
+    const char* format, ...);
+
+#if defined(LOG_LEVEL) && LOG_LEVEL >= 1
+#define LOG_ERROR(...)                                                  \
+    printLog(                                                           \
+        LOG_ERROR, __FILE__, __LINE__, TERMINAL_BRIGHT_RED, "[ERROR] ", \
+        __VA_ARGS__)
+#else
+#define LOG_ERROR(...)
+#endif
+
+#if defined(LOG_LEVEL) && LOG_LEVEL >= 2
+#define LOG_WARNING(...)                                                       \
+    printLog(                                                                  \
+        LOG_WARNING, __FILE__, __LINE__, TERMINAL_BRIGHT_YELLOW, "[WARNING] ", \
+        __VA_ARGS__)
+#else
+#define LOG_WARNING(...)
+#endif
+
+#if defined(LOG_LEVEL) && LOG_LEVEL >= 3
+#define LOG_INFO(...)                                                        \
+    printLog(                                                                \
+        LOG_INFO, __FILE__, __LINE__, TERMINAL_BOLD, "[INFO] ", __VA_ARGS__)
+#else
+#define LOG_INFO(...)
+#endif
+
+#if defined(LOG_LEVEL) && LOG_LEVEL >= 4
+#define LOG_DEBUG(...)                                                      \
+    printLog(                                                               \
+        LOG_DEBUG, __FILE__, __LINE__, TERMINAL_BOLD TERMINAL_BRIGHT_BLACK, \
+        "[DEBUG] ", __VA_ARGS__)
+#else
+#define LOG_DEBUG(...)
+#endif
+
+#endif

+ 32 - 0
include/core/Matrix.h

@@ -0,0 +1,32 @@
+#ifndef CORE_MATRIX_H
+#define CORE_MATRIX_H
+
+#include "core/Quaternion.h"
+#include "core/Vector.h"
+
+typedef struct {
+    Vector4 data[4];
+} Matrix;
+
+#define ZERO_MATRIX ((Matrix){0})
+#define UNIT_MATRIX \
+    ((Matrix){{{{1, 0, 0, 0}}, {{0, 1, 0, 0}}, {{0, 0, 1, 0}}, {{0, 0, 0, 1}}}})
+
+Matrix* transposeMatrix(Matrix* m);
+Matrix* mulSetMatrix(Matrix* m, const Matrix* a);
+Matrix* mulMatrix(Matrix* m, const Matrix* a, const Matrix* b);
+Vector3* mulMatrixV3(Vector3* v, const Matrix* m, const Vector3* a);
+Matrix* scaleMatrix(Matrix* m, const Vector3* v);
+Matrix* scaleMatrixF(Matrix* m, float f);
+Matrix* translateMatrix(Matrix* m, const Vector3* v);
+Matrix* translateMatrixX(Matrix* m, float tx);
+Matrix* translateMatrixY(Matrix* m, float ty);
+Matrix* translateMatrixZ(Matrix* m, float tz);
+Matrix* translateMatrixTo(Matrix* m, const Vector3* v);
+Matrix* rotateMatrixX(Matrix* m, float radians);
+Matrix* rotateMatrixY(Matrix* m, float radians);
+Matrix* rotateMatrixZ(Matrix* m, float radians);
+Matrix* rotateMatrix(Matrix* m, const Quaternion* q);
+size_t toStringMatrix(const Matrix* m, char* buffer, size_t n);
+
+#endif

+ 15 - 0
include/core/Plane.h

@@ -0,0 +1,15 @@
+#ifndef CORE_PLANE_H
+#define CORE_PLANE_H
+
+#include "core/Vector.h"
+
+typedef struct {
+    Vector3 abc;
+    float d;
+} Plane;
+
+void initPlane(Plane* p, const Vector3* a, const Vector3* b, const Vector3* c);
+float signedDistance(const Plane* p, const Vector3* v);
+size_t toStringPlane(const Plane* p, char* buffer, size_t n);
+
+#endif

+ 20 - 0
include/core/Quaternion.h

@@ -0,0 +1,20 @@
+#ifndef CORE_QUATERNION_H
+#define CORE_QUATERNION_H
+
+#include "core/Vector.h"
+
+typedef struct {
+    Vector4 v;
+} Quaternion;
+
+#define UNIT_QUATERNION ((Quaternion){{{0.0f, 0.0f, 0.0f, 1.0f}}})
+
+Quaternion* axisAngleQ(Quaternion* q, const Vector3* axis, float angle);
+Quaternion* lerpQ(
+    Quaternion* q, const Quaternion* a, float f, const Quaternion* b);
+Quaternion* mulSetQ(Quaternion* q, const Quaternion* other);
+Quaternion* mulQ(Quaternion* q, const Quaternion* a, const Quaternion* b);
+Vector3* mulQV3(Vector3* r, const Quaternion* q, const Vector3* v);
+size_t toStringQ(const Quaternion* q, char* buffer, size_t n);
+
+#endif

+ 85 - 0
include/core/Queue.h

@@ -0,0 +1,85 @@
+#ifndef CORE_QUEUE_H
+#define CORE_QUEUE_H
+
+#include <assert.h>
+
+#include "core/ToString.h"
+#include "core/Types.h"
+#include "core/Utility.h"
+
+#define QUEUE(T, N)                                                       \
+    typedef struct {                                                      \
+        size_t writeIndex;                                                \
+        size_t readIndex;                                                 \
+        size_t length;                                                    \
+        size_t capacity;                                                  \
+        T* data;                                                          \
+    } Queue##N;                                                           \
+                                                                          \
+    void initQueue##N(Queue##N* r, size_t capacity);                      \
+    void destroyQueue##N(Queue##N* r);                                    \
+    void pushQueueData##N(Queue##N* r, T data);                           \
+    T* getQueueIndex##N(const Queue##N* r, size_t index);                 \
+    void clearQueue##N(Queue##N* r);                                      \
+    void popQueueData##N(Queue##N* r);                                    \
+    typedef size_t (*ToString##N)(const T* data, char* buffer, size_t n); \
+    size_t toStringQueue##N(                                              \
+        const Queue##N* r, char* buffer, size_t n, ToString##N c);
+
+#define QUEUE_SOURCE(T, N)                                                  \
+    void initQueue##N(Queue##N* r, size_t capacity) {                       \
+        *r = ((Queue##N){0, 0, 0, capacity, nullptr});                      \
+    }                                                                       \
+                                                                            \
+    void destroyQueue##N(Queue##N* r) {                                     \
+        coreFree(r->data);                                                  \
+        *r = (Queue##N){0};                                                 \
+    }                                                                       \
+                                                                            \
+    void pushQueueData##N(Queue##N* r, T data) {                            \
+        if(r->length >= r->capacity) {                                      \
+            return;                                                         \
+        } else if(r->data == nullptr) {                                     \
+            r->data = coreAllocate(r->capacity * sizeof(T));                \
+        }                                                                   \
+        r->data[r->writeIndex] = data;                                      \
+        r->writeIndex = (r->writeIndex + 1) % r->capacity;                  \
+        r->length++;                                                        \
+    }                                                                       \
+                                                                            \
+    T* getQueueIndex##N(const Queue##N* r, size_t index) {                  \
+        return r->data + ((index + r->readIndex) % r->capacity);            \
+    }                                                                       \
+                                                                            \
+    void clearQueue##N(Queue##N* r) {                                       \
+        r->writeIndex = 0;                                                  \
+        r->readIndex = 0;                                                   \
+        r->length = 0;                                                      \
+    }                                                                       \
+                                                                            \
+    void popQueueData##N(Queue##N* r) {                                     \
+        assert(r->length > 0);                                              \
+        r->length--;                                                        \
+        r->readIndex = (r->readIndex + 1) % r->capacity;                    \
+    }                                                                       \
+                                                                            \
+    size_t toStringQueue##N(                                                \
+        const Queue##N* r, char* buffer, size_t n, ToString##N c) {         \
+        size_t w = 0;                                                       \
+        stringAdd(&w, &buffer, &n, toString(buffer, n, "["));               \
+        size_t end = r->length;                                             \
+        if(end > 0) {                                                       \
+            end--;                                                          \
+            for(size_t i = 0; i < end; i++) {                               \
+                stringAdd(                                                  \
+                    &w, &buffer, &n, c(getQueueIndex##N(r, i), buffer, n)); \
+                stringAdd(&w, &buffer, &n, toString(buffer, n, ", "));      \
+            }                                                               \
+            stringAdd(                                                      \
+                &w, &buffer, &n, c(getQueueIndex##N(r, end), buffer, n));   \
+        }                                                                   \
+        stringAdd(&w, &buffer, &n, toString(buffer, n, "]"));               \
+        return w;                                                           \
+    }
+
+#endif

+ 18 - 0
include/core/Random.h

@@ -0,0 +1,18 @@
+#ifndef CORE_RANDOM_H
+#define CORE_RANDOM_H
+
+#include "core/Types.h"
+
+typedef struct {
+    u32 data[25];
+    size_t index;
+} Random;
+
+void initRandom(Random* r, u32 seed);
+u32 randomU32(Random* r, u32 min, u32 exclusiveMax);
+i32 randomI32(Random* r, i32 min, i32 exclusiveMax);
+size_t randomSize(Random* r, size_t min, size_t exclusiveMax);
+bool randomBool(Random* r);
+float randomFloat(Random* r);
+
+#endif

+ 10 - 0
include/core/ReadLine.h

@@ -0,0 +1,10 @@
+#ifndef CORE_READ_LINE_H
+#define CORE_READ_LINE_H
+
+#include <stddef.h>
+
+bool startReadLine(void);
+bool readLine(char* buffer, size_t n);
+void stopReadLine(void);
+
+#endif

+ 14 - 0
include/core/SpinLock.h

@@ -0,0 +1,14 @@
+#ifndef CORE_SPIN_LOCK_H
+#define CORE_SPIN_LOCK_H
+
+#include <stdatomic.h>
+
+typedef struct {
+    atomic_bool lock;
+} SpinLock;
+
+void initSpinLock(SpinLock* l);
+void lockSpinLock(SpinLock* l);
+void unlockSpinLock(SpinLock* l);
+
+#endif

+ 117 - 0
include/core/Terminal.h

@@ -0,0 +1,117 @@
+#ifndef CORE_TERMINAL_H
+#define CORE_TERMINAL_H
+
+#include "core/Vector.h"
+
+#define ESC "\33["
+#define TERMINAL_RESET ESC "0m"
+#define TERMINAL_BOLD ESC "1m"
+
+#define TERMINAL_BLACK ESC "30m"
+#define TERMINAL_RED ESC "31m"
+#define TERMINAL_GREEN ESC "32m"
+#define TERMINAL_YELLOW ESC "33m"
+#define TERMINAL_BLUE ESC "34m"
+#define TERMINAL_MAGENTA ESC "35m"
+#define TERMINAL_CYAN ESC "36m"
+#define TERMINAL_WHITE ESC "37m"
+#define TERMINAL_BRIGHT_BLACK ESC "90m"
+#define TERMINAL_BRIGHT_RED ESC "91m"
+#define TERMINAL_BRIGHT_GREEN ESC "92m"
+#define TERMINAL_BRIGHT_YELLOW ESC "93m"
+#define TERMINAL_BRIGHT_BLUE ESC "94m"
+#define TERMINAL_BRIGHT_MAGENTA ESC "95m"
+#define TERMINAL_BRIGHT_CYAN ESC "96m"
+#define TERMINAL_BRIGHT_WHITE ESC "97m"
+
+#define TERMINAL_FG_BLACK TERMINAL_BLACK
+#define TERMINAL_FG_RED TERMINAL_RED
+#define TERMINAL_FG_GREEN TERMINAL_GREEN
+#define TERMINAL_FG_YELLOW TERMINAL_YELLOW
+#define TERMINAL_FG_BLUE TERMINAL_BLUE
+#define TERMINAL_FG_MAGENTA TERMINAL_MAGENTA
+#define TERMINAL_FG_CYAN TERMINAL_CYAN
+#define TERMINAL_FG_WHITE TERMINAL_WHITE
+#define TERMINAL_FG_BRIGHT_BLACK TERMINAL_BRIGHT_BLACK
+#define TERMINAL_FG_BRIGHT_RED TERMINAL_BRIGHT_RED
+#define TERMINAL_FG_BRIGHT_GREEN TERMINAL_BRIGHT_GREEN
+#define TERMINAL_FG_BRIGHT_YELLOW TERMINAL_BRIGHT_YELLOW
+#define TERMINAL_FG_BRIGHT_BLUE TERMINAL_BRIGHT_BLUE
+#define TERMINAL_FG_BRIGHT_MAGENTA TERMINAL_BRIGHT_MAGENTA
+#define TERMINAL_FG_BRIGHT_CYAN TERMINAL_BRIGHT_CYAN
+#define TERMINAL_FG_BRIGHT_WHITE TERMINAL_BRIGHT_WHITE
+
+#define TERMINAL_BG_BLACK ESC "40m"
+#define TERMINAL_BG_RED ESC "41m"
+#define TERMINAL_BG_GREEN ESC "42m"
+#define TERMINAL_BG_YELLOW ESC "43m"
+#define TERMINAL_BG_BLUE ESC "44m"
+#define TERMINAL_BG_MAGENTA ESC "45m"
+#define TERMINAL_BG_CYAN ESC "46m"
+#define TERMINAL_BG_WHITE ESC "47m"
+#define TERMINAL_BG_BRIGHT_BLACK ESC "100m"
+#define TERMINAL_BG_BRIGHT_RED ESC "101m"
+#define TERMINAL_BG_BRIGHT_GREEN ESC "102m"
+#define TERMINAL_BG_BRIGHT_YELLOW ESC "103m"
+#define TERMINAL_BG_BRIGHT_BLUE ESC "104m"
+#define TERMINAL_BG_BRIGHT_MAGENTA ESC "105m"
+#define TERMINAL_BG_BRIGHT_CYAN ESC "106m"
+#define TERMINAL_BG_BRIGHT_WHITE ESC "107m"
+// keycodes
+#define TERMINAL_KEY_UNKNOWN 0x1'0000'0000lu
+// default keycodes
+#define TERMINAL_KEY_ARROW_LEFT 0x1'0000'0001lu
+#define TERMINAL_KEY_ARROW_RIGHT 0x1'0000'0002lu
+#define TERMINAL_KEY_ARROW_UP 0x1'0000'0003lu
+#define TERMINAL_KEY_ARROW_DOWN 0x1'0000'0004lu
+#define TERMINAL_KEY_DELETE 0x1'0000'0005lu
+#define TERMINAL_KEY_F1 0x1'0000'0006lu
+#define TERMINAL_KEY_F2 0x1'0000'0007lu
+#define TERMINAL_KEY_F3 0x1'0000'0008lu
+#define TERMINAL_KEY_F4 0x1'0000'0009lu
+#define TERMINAL_KEY_F5 0x1'0000'000Alu
+#define TERMINAL_KEY_F6 0x1'0000'000Blu
+#define TERMINAL_KEY_F7 0x1'0000'000Clu
+#define TERMINAL_KEY_F8 0x1'0000'000Dlu
+#define TERMINAL_KEY_F9 0x1'0000'000Elu
+#define TERMINAL_KEY_F10 0x1'0000'000Flu
+#define TERMINAL_KEY_F11 0x1'0000'0010lu
+#define TERMINAL_KEY_F12 0x1'0000'0011lu
+#define TERMINAL_KEY_PAGE_UP 0x1'0000'0012lu
+#define TERMINAL_KEY_PAGE_DOWN 0x1'0000'0013lu
+#define TERMINAL_KEY_HOME 0x1'0000'0014lu
+#define TERMINAL_KEY_END 0x1'0000'0015lu
+// key modifiers
+#define TERMINAL_KEY_CTRL 0x2'0000'0000lu
+#define TERMINAL_KEY_SHIFT 0x4'0000'0000lu
+#define TERMINAL_KEY_ALT 0x8'0000'0000lu
+
+void enterAlternativeTerminal();
+void leaveAlternativeTerminal();
+IntVector2 getTerminalSize();
+void clearTerminal();
+void clearTerminalLine();
+
+void hideCursor();
+void showCursor();
+void resetCursor();
+void moveCursorLeft(int i);
+void moveCursorRight(int i);
+void moveCursorUp(int i);
+void moveCursorDown(int i);
+
+bool enterRawTerminal();
+bool leaveRawTerminal();
+u64 getRawChar();
+bool isSpecialChar(u64 u);
+
+typedef struct {
+    u64 key;
+    bool control;
+    bool shift;
+    bool alt;
+} SpecialChar;
+
+SpecialChar convertToSpecialChar(u64 u);
+
+#endif

+ 65 - 0
include/core/Test.h

@@ -0,0 +1,65 @@
+#ifndef CORE_TEST_H
+#define CORE_TEST_H
+
+#include "core/Types.h"
+
+void finalizeTests(void);
+
+#define TEST_ARGS const char *file, int line
+#define TEST_FUNCTION(name, type)                        \
+    bool test##name(TEST_ARGS, type wanted, type actual)
+
+TEST_FUNCTION(Int, int);
+TEST_FUNCTION(I32, i32);
+TEST_FUNCTION(I64, i64);
+TEST_FUNCTION(U32, u32);
+TEST_FUNCTION(U64, u64);
+TEST_FUNCTION(Size, size_t);
+TEST_FUNCTION(Bool, bool);
+TEST_FUNCTION(String, const char*);
+
+bool testFloat(TEST_ARGS, float wanted, float actual, float error);
+
+bool testNull(TEST_ARGS, const void* p);
+bool testNotNull(TEST_ARGS, const void* p);
+
+#define TEST(wanted, actual, name)                 \
+    test##name(__FILE__, __LINE__, wanted, actual)
+
+#define TEST_FLOAT(wanted, actual, error)                \
+    testFloat(__FILE__, __LINE__, wanted, actual, error)
+
+#define TEST_BOOL(wanted, actual) TEST(wanted, actual, Bool)
+#define TEST_INT(wanted, actual) TEST(wanted, actual, Int)
+#define TEST_I32(wanted, actual) TEST(wanted, actual, I32)
+#define TEST_I64(wanted, actual) TEST(wanted, actual, I64)
+#define TEST_U32(wanted, actual) TEST(wanted, actual, U32)
+#define TEST_U64(wanted, actual) TEST(wanted, actual, U64)
+#define TEST_SIZE(wanted, actual) TEST(wanted, actual, Size)
+#define TEST_STRING(wanted, actual) TEST(wanted, actual, String)
+#define TEST_FALSE(actual) TEST(false, actual, Bool)
+#define TEST_TRUE(actual) TEST(true, actual, Bool)
+#define TEST_NULL(actual) testNull(__FILE__, __LINE__, actual)
+#define TEST_NOT_NULL(actual) testNotNull(__FILE__, __LINE__, actual)
+
+bool testVectorN(TEST_ARGS, const float* wanted, const float* actual, size_t n);
+#define TEST_VN(wanted, actual, n)                                     \
+    testVectorN(__FILE__, __LINE__, (wanted)->data, (actual)->data, n)
+#define TEST_V2(wanted, actual)                        \
+    TEST_VN((Vector2*)(wanted), (Vector2*)(actual), 2)
+#define TEST_V3(wanted, actual)                        \
+    TEST_VN((Vector3*)(wanted), (Vector3*)(actual), 3)
+#define TEST_V4(wanted, actual)                        \
+    TEST_VN((Vector4*)(wanted), (Vector4*)(actual), 4)
+
+bool testIntVectorN(TEST_ARGS, const int* wanted, const int* actual, size_t n);
+#define TEST_IVN(wanted, actual, n)                                       \
+    testIntVectorN(__FILE__, __LINE__, (wanted)->data, (actual)->data, n)
+#define TEST_IV2(wanted, actual)                              \
+    TEST_IVN((IntVector2*)(wanted), (IntVector2*)(actual), 2)
+#define TEST_IV3(wanted, actual)                              \
+    TEST_IVN((IntVector3*)(wanted), (IntVector3*)(actual), 3)
+#define TEST_IV4(wanted, actual)                              \
+    TEST_IVN((IntVector4*)(wanted), (IntVector4*)(actual), 4)
+
+#endif

+ 8 - 0
include/core/Thread.h

@@ -0,0 +1,8 @@
+#ifndef CORE_THREAD_H
+#define CORE_THREAD_H
+
+#include <threads.h>
+
+bool joinThreadSafe(thrd_t* t);
+
+#endif

+ 13 - 0
include/core/ToString.h

@@ -0,0 +1,13 @@
+#ifndef CORE_TO_STRING_H
+#define CORE_TO_STRING_H
+
+#include "core/Check.h"
+#include "core/Types.h"
+
+check_format(3, 4) size_t
+    toString(char* buffer, size_t n, const char* format, ...);
+size_t toStringSize(const size_t* p, char* buffer, size_t n);
+size_t toStringInt(const int* p, char* buffer, size_t n);
+void stringAdd(size_t* w, char** buffer, size_t* n, size_t shift);
+
+#endif

+ 19 - 0
include/core/Types.h

@@ -0,0 +1,19 @@
+#ifndef CORE_TYPES_H
+#define CORE_TYPES_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef int64_t i64;
+typedef int32_t i32;
+typedef int16_t i16;
+typedef int8_t i8;
+typedef uint64_t u64;
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef uint8_t u8;
+#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(*array))
+
+typedef size_t (*ToString)(const void* data, char* buffer, size_t n);
+
+#endif

+ 16 - 0
include/core/Unicode.h

@@ -0,0 +1,16 @@
+#ifndef CORE_UNICODE_H
+#define CORE_UNICODE_H
+
+#include "core/Types.h"
+
+typedef struct {
+    u8 data[4];
+    u32 length;
+} UTF8;
+
+UTF8 convertUnicodeToUTF8(u32 c);
+u32 convertUTF8toUnicode(UTF8 c);
+bool isUTF8Remainder(u8 c);
+u32 getUTF8Length(u8 c);
+
+#endif

+ 84 - 0
include/core/Utility.h

@@ -0,0 +1,84 @@
+#ifndef CORE_UTILITY_H
+#define CORE_UTILITY_H
+
+#include <string.h>
+
+#include "core/Types.h"
+
+size_t popCount(u64 u);
+#define interpolate(a, b, factor) ((a) * (1.0f - (factor)) + (b) * (factor))
+#define PI 3.14159265358979323846f
+#define radianToDegree(radians) ((radians) * (180.0f / PI))
+#define degreeToRadian(degrees) ((degrees) * (PI / 180.0f))
+
+#define MIN_MAX(type, name)                               \
+    inline type max##name(type a, type b) {               \
+        return a > b ? a : b;                             \
+    }                                                     \
+    inline type min##name(type a, type b) {               \
+        return a < b ? a : b;                             \
+    }                                                     \
+    inline type clamp##name(type t, type from, type to) { \
+        return max##name(min##name(t, to), from);         \
+    }
+MIN_MAX(size_t, Size)
+MIN_MAX(u32, U32)
+MIN_MAX(i32, I32)
+MIN_MAX(float, Float)
+
+typedef void (*ExitHandler)(int, void*);
+[[noreturn]] void exitWithHandler(const char* file, int line, int value);
+void setExitHandler(ExitHandler h, void* data);
+#define EXIT(exitValue) exitWithHandler(__FILE__, __LINE__, exitValue)
+
+typedef void (*OutOfMemoryHandler)(void*);
+void setOutOfMemoryHandler(OutOfMemoryHandler h, void* data);
+
+#ifdef CHECK_MEMORY
+void* coreDebugAllocate(const char* file, int line, size_t n);
+void* coreDebugZeroAllocate(const char* file, int line, size_t n);
+void* coreDebugReallocate(const char* file, int line, void* p, size_t n);
+void coreFreeDebug(const char* file, int line, void* p);
+void printMemoryReport(void);
+#define coreAllocate(n) coreDebugAllocate(__FILE__, __LINE__, n)
+#define coreZeroAllocate(n) coreDebugZeroAllocate(__FILE__, __LINE__, n)
+#define coreReallocate(p, n) coreDebugReallocate(__FILE__, __LINE__, p, n)
+#define coreFree(p) coreFreeDebug(__FILE__, __LINE__, p)
+#else
+void* coreAllocate(size_t n);
+void* coreZeroAllocate(size_t n);
+void* coreReallocate(void* p, size_t n);
+void coreFree(void* p);
+#define printMemoryReport()
+#endif
+
+bool sleepMillis(i64 millis);
+bool sleepNanos(i64 nanos);
+i64 getNanos(void);
+
+#define swap(a, b)             \
+    do {                       \
+        auto aPointer = (a);   \
+        auto bPointer = (b);   \
+        auto tmp = *aPointer;  \
+        *aPointer = *bPointer; \
+        *bPointer = tmp;       \
+    } while(0)
+
+#define BUBBLE_SORT(type, Type) void bubbleSort##Type(type* data, size_t n);
+#define BUBBLE_SORT_SOURCE(type, Type, greaterThan)     \
+    void bubbleSort##Type(type* data, size_t n) {       \
+        bool swapped = true;                            \
+        while(swapped && n > 0) {                       \
+            swapped = false;                            \
+            n--;                                        \
+            for(size_t i = 0; i < n; i++) {             \
+                if(greaterThan(data[i], data[i + 1])) { \
+                    swap(data + i, data + i + 1);       \
+                    swapped = true;                     \
+                }                                       \
+            }                                           \
+        }                                               \
+    }
+
+#endif

+ 95 - 0
include/core/Vector.h

@@ -0,0 +1,95 @@
+#ifndef CORE_VECTOR_H
+#define CORE_VECTOR_H
+
+#include "core/Types.h"
+
+#define VECTOR_OP2(name) name *r, const name *a
+#define VECTOR_OP3(name) VECTOR_OP2(name), const name* b
+
+#define VECTOR_TYPE(type, Type) \
+    typedef union {             \
+        type data[2];           \
+        struct {                \
+            type x, y;          \
+        };                      \
+    } Type##2;                  \
+    typedef union {             \
+        type data[3];           \
+        struct {                \
+            type x, y, z;       \
+        };                      \
+        Type##2 xy;             \
+    } Type##3;                  \
+    typedef union {             \
+        type data[4];           \
+        struct {                \
+            type x, y, z, w;    \
+        };                      \
+        struct {                \
+            Type##2 xy, zw;     \
+        };                      \
+        Type##3 xyz;            \
+    } Type##4
+
+VECTOR_TYPE(float, Vector);
+VECTOR_TYPE(int, IntVector);
+
+#define DEFINE_VECTOR(N, name, sname, type)                        \
+    name* addSet##sname(VECTOR_OP2(name));                         \
+    name* add##sname(VECTOR_OP3(name));                            \
+    name* subSet##sname(VECTOR_OP2(name));                         \
+    name* sub##sname(VECTOR_OP3(name));                            \
+    name* mulSet##sname(VECTOR_OP2(name));                         \
+    name* mul##sname(VECTOR_OP3(name));                            \
+    name* divSet##sname(VECTOR_OP2(name));                         \
+    name* div##sname(VECTOR_OP3(name));                            \
+    name* mulSet##sname##F(name* r, type f);                       \
+    name* mul##sname##F(name* r, const name* a, type f);           \
+    name* divSet##sname##F(name* r, type f);                       \
+    name* div##sname##F(name* r, const name* a, type f);           \
+    name* invertSet##sname(name* r);                               \
+    name* invert##sname(name* r, const name* a);                   \
+    size_t toString##sname(const name* a, char* buffer, size_t n);
+
+#define DEFINE_FVECTOR(N, name)                  \
+    float dotV##N(const name* a, const name* b); \
+    float squareLengthV##N(const name* a);       \
+    float lengthV##N(const name* a);             \
+    name* normalizeV##N(name* r);
+
+DEFINE_VECTOR(2, Vector2, V2, float)
+DEFINE_VECTOR(3, Vector3, V3, float)
+DEFINE_VECTOR(4, Vector4, V4, float)
+DEFINE_FVECTOR(2, Vector2)
+DEFINE_FVECTOR(3, Vector3)
+DEFINE_FVECTOR(4, Vector4)
+DEFINE_VECTOR(2, IntVector2, IV2, int)
+DEFINE_VECTOR(3, IntVector3, IV3, int)
+DEFINE_VECTOR(4, IntVector4, IV4, int)
+
+Vector3* angles(Vector3* r, float lengthAngle, float widthAngle);
+Vector3* cross(VECTOR_OP3(Vector3));
+
+#define DEFINE_VECTOR_CONVERSION(a, nameA, b, nameB) \
+    a* convert##nameB(a* r, const b* c);             \
+    b* convert##nameA(b* r, const a* c)
+
+DEFINE_VECTOR_CONVERSION(Vector2, V2, IntVector2, IV2);
+DEFINE_VECTOR_CONVERSION(Vector3, V3, IntVector3, IV3);
+DEFINE_VECTOR_CONVERSION(Vector4, V4, IntVector4, IV4);
+
+#define VECTOR2 ((Vector2){0})
+#define VECTOR3 ((Vector3){0})
+#define VECTOR4 ((Vector4){0})
+#define INT_VECTOR2 ((IntVector2){0})
+#define INT_VECTOR3 ((IntVector3){0})
+#define INT_VECTOR4 ((IntVector4){0})
+
+#define SELECT_VECTOR(_1, _2, _3, _4, name, ...) name
+#define V(...) \
+    ((SELECT_VECTOR(__VA_ARGS__, Vector4, Vector3, Vector2, 0)){{__VA_ARGS__}})
+#define IV(...)                                                           \
+    ((SELECT_VECTOR(__VA_ARGS__, IntVector4, IntVector3, IntVector2, 0)){ \
+        {__VA_ARGS__}})
+
+#endif

+ 21 - 0
include/core/View.h

@@ -0,0 +1,21 @@
+#ifndef CORE_VIEW_H
+#define CORE_VIEW_H
+
+#include "core/Matrix.h"
+
+typedef struct {
+    Matrix view;
+    Vector3 back;
+    Vector3 down;
+    Vector3 front;
+    Vector3 left;
+    Vector3 right;
+    Vector3 up;
+} View;
+
+void initView(View* v);
+void updateDirections(View* v, float lengthAngle, float widthAngle);
+void updateDirectionsQ(View* v, const Quaternion* q);
+Matrix* updateMatrix(View* v, const Vector3* pos);
+
+#endif

+ 248 - 0
old/CMakeLists.txt

@@ -0,0 +1,248 @@
+cmake_minimum_required(VERSION 3.25)
+project(core)
+
+set(CMAKE_CXX_STANDARD 20)
+
+set(SRC
+    "src/Logger.cpp"
+    "src/Utility.cpp"
+    "src/Error.cpp"
+    "src/New.cpp"
+    "src/Buffer.cpp"
+    "src/Clock.cpp"
+    "src/Random.cpp"
+    "src/BitArray.cpp"
+    "src/Vector.cpp"
+    "src/Quaternion.cpp"
+    "src/Matrix.cpp"
+    "src/Box.cpp"
+    "src/Plane.cpp"
+    "src/Frustum.cpp"
+    "src/View.cpp"
+    "src/Thread.cpp"
+    "src/Mutex.cpp"
+    "src/SpinLock.cpp"
+    "src/FileReader.cpp"
+    "src/ErrorSimulator.cpp"
+    "src/ArrayString.cpp"
+)
+
+set(SRC_TESTS
+    "test/Main.cpp"
+    "test/Test.cpp"
+    "test/modules/ArrayTests.cpp"
+    "test/modules/ArrayStringTests.cpp"
+    "test/modules/UtilityTests.cpp"
+    "test/modules/ArrayListTests.cpp"
+    "test/modules/BitArrayTests.cpp"
+    "test/modules/MathTests.cpp"
+    "test/modules/ListTests.cpp"
+    "test/modules/LinkedListTests.cpp"
+    "test/modules/UniquePointerTests.cpp"
+    "test/modules/HashMapTests.cpp"
+    "test/modules/StackTests.cpp"
+    "test/modules/RingBufferTests.cpp"
+    "test/modules/ComponentsTests.cpp"
+    "test/modules/VectorTests.cpp"
+    "test/modules/QuaternionTests.cpp"
+    "test/modules/MatrixTests.cpp"
+    "test/modules/BoxTests.cpp"
+    "test/modules/BufferedValueTests.cpp"
+    "test/modules/PlaneTests.cpp"
+    "test/modules/FrustumTests.cpp"
+    "test/modules/ViewTests.cpp"
+    "test/modules/MatrixStackTests.cpp"
+    "test/modules/ColorTests.cpp"
+    "test/modules/BufferTests.cpp"
+    "test/modules/ClockTests.cpp"
+    "test/modules/RandomTests.cpp"
+    "test/modules/ThreadTests.cpp"
+    "test/modules/FileReaderTests.cpp"
+    "test/modules/ErrorTests.cpp"
+    "test/modules/NewTests.cpp"
+    "test/modules/HashedStringTests.cpp"
+)
+
+set(SRC_PERFORMANCE
+    "performance/Main.cpp"
+    "test/Test.cpp"
+)
+
+if("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
+    set(COMPILE_OPTIONS -flto)
+    set(LINK_OPTIONS -flto)
+    set(LOG_LEVEL 2)
+    set(ERROR_SIMULATOR "")
+else()
+    if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+        set(COMPILE_OPTIONS --coverage)
+    endif()
+    set(LINK_OPTIONS gcov)
+    set(LOG_LEVEL 4)
+    set(ERROR_SIMULATOR "ERROR_SIMULATOR")
+endif()
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+    set(MORE_WARNINGS
+        -Waligned-new=all
+        -Walloc-zero
+        -Wanalyzer-too-complex
+        -Warith-conversion
+        -Warray-bounds=2
+        -Wattribute-alias=2
+        -Wbidi-chars=any
+        -Wcast-align=strict
+        -Wcatch-value=3
+        -Wcomma-subscript
+        -Wconditionally-supported
+        -Wduplicated-branches
+        -Wduplicated-cond
+        -Wformat-overflow=2
+        -Wformat-signedness
+        -Wformat-truncation=2
+        -Wimplicit-fallthrough=5
+        -Winvalid-imported-macros
+        -Wlogical-op
+        -Wmultiple-inheritance
+        -Wnoexcept
+        -Wnormalized=nfkc
+        -Wplacement-new=2
+        -Wredundant-tags
+        -Wshift-overflow=2
+        -Wstack-usage=8388608
+        -Wstrict-null-sentinel
+        -Wstringop-overflow=4
+        -Wsuggest-final-methods
+        -Wsuggest-final-types
+        -Wtrampolines
+        -Wtrivial-auto-var-init
+        -Wunused-const-variable=2
+        -Wuse-after-free=3
+        -Wvirtual-inheritance
+        -Wvolatile
+    )
+endif()
+
+add_library(core STATIC ${SRC})
+target_compile_options(core PUBLIC
+    ${COMPILE_OPTIONS}
+    -fdiagnostics-color=always
+    -fno-exceptions
+    -fno-rtti
+    -fno-threadsafe-statics
+    # deactivated due to the need for <atomic>
+    #-nostdinc++
+    -pedantic
+    -pedantic-errors
+    -Wall
+    -Walloca
+    -Warray-parameter
+    -Wcast-qual
+    -Wconversion
+    -Wctad-maybe-unsupported
+    -Wctor-dtor-privacy
+    -Wdate-time
+    -Wdeprecated-copy-dtor
+    -Wdeprecated-enum-enum-conversion
+    -Wdeprecated-enum-float-conversion
+    -Wdisabled-optimization
+    -Wdouble-promotion
+    -Weffc++
+    -Wenum-compare
+    -Wenum-conversion
+    -Werror
+    -Wextra
+    -Wextra-semi
+    -Wfloat-equal
+    -Wformat=2
+    -Wframe-larger-than=8388608
+    -Winfinite-recursion
+    -Winit-self
+    -Winvalid-pch
+    -Wlarger-than=1073741824
+    -Wmismatched-tags
+    -Wmissing-braces
+    -Wmissing-declarations
+    -Wmissing-include-dirs
+    -Wmultichar
+    -Wnon-virtual-dtor
+    -Wnull-dereference
+    -Wold-style-cast
+    -Woverlength-strings
+    -Woverloaded-virtual
+    -Wredundant-decls
+    -Wregister
+    -Wshadow
+    -Wsign-conversion
+    -Wsign-promo
+    -Wstack-protector
+    -Wstrict-overflow=2
+    -Wsuggest-override
+    -Wswitch-enum
+    -Wsynth
+    -Wundef
+    -Wunreachable-code
+    -Wvla
+    -Wwrite-strings
+    -Wzero-as-null-pointer-constant
+    ${MORE_WARNINGS}
+)
+target_compile_definitions(core 
+    PUBLIC CORE_LOG_LEVEL=${LOG_LEVEL}
+    PRIVATE ${ERROR_SIMULATOR}
+)
+target_link_libraries(core 
+    PUBLIC -nodefaultlibs c m
+    PRIVATE ${LINK_OPTIONS}
+)
+target_sources(core PUBLIC 
+    FILE_SET HEADERS
+    BASE_DIRS include
+    FILES 
+        ./include/core/data/Stack.hpp
+        ./include/core/data/HashMap.hpp
+        ./include/core/data/Components.hpp
+        ./include/core/data/ArrayList.hpp
+        ./include/core/data/ProbingHashMap.hpp
+        ./include/core/data/List.hpp
+        ./include/core/data/LinkedList.hpp
+        ./include/core/data/BitArray.hpp
+        ./include/core/data/Array.hpp
+        ./include/core/data/RingBuffer.hpp
+        ./include/core/thread/Thread.hpp
+        ./include/core/utils/HashCode.hpp
+        ./include/core/utils/New.hpp
+        ./include/core/utils/Check.hpp
+        ./include/core/utils/Buffer.hpp
+        ./include/core/utils/Random.hpp
+        ./include/core/utils/UniquePointer.hpp
+        ./include/core/utils/Types.hpp
+        ./include/core/utils/Color.hpp
+        ./include/core/utils/Logger.hpp
+        ./include/core/utils/ArrayString.hpp
+        ./include/core/utils/Utility.hpp
+        ./include/core/utils/Meta.hpp
+        ./include/core/utils/AlignedData.hpp
+        ./include/core/utils/Clock.hpp
+        ./include/core/utils/Error.hpp
+        ./include/core/math/Quaternion.hpp
+        ./include/core/math/Box.hpp
+        ./include/core/math/Frustum.hpp
+        ./include/core/math/Vector.hpp
+        ./include/core/math/Matrix.hpp
+        ./include/core/math/View.hpp
+        ./include/core/math/BufferedValue.hpp
+        ./include/core/math/Plane.hpp
+        ./include/core/math/MatrixStack.hpp
+        ./include/core/math/Math.hpp
+        ./include/core/io/File.hpp
+        ./include/core/io/FileReader.hpp
+)
+install(TARGETS core FILE_SET HEADERS)
+
+add_executable(test ${SRC_TESTS})
+target_link_libraries(test PRIVATE core)
+target_compile_definitions(test PRIVATE ${ERROR_SIMULATOR})
+
+add_executable(performance ${SRC_PERFORMANCE})
+target_link_libraries(performance PRIVATE core)

+ 0 - 0
include/core/data/Array.hpp → old/include/core/data/Array.hpp


+ 0 - 0
include/core/data/ArrayList.hpp → old/include/core/data/ArrayList.hpp


+ 0 - 0
include/core/data/BitArray.hpp → old/include/core/data/BitArray.hpp


+ 0 - 0
include/core/data/Components.hpp → old/include/core/data/Components.hpp


+ 0 - 0
include/core/data/HashMap.hpp → old/include/core/data/HashMap.hpp


+ 0 - 0
include/core/data/LinkedList.hpp → old/include/core/data/LinkedList.hpp


+ 0 - 0
include/core/data/List.hpp → old/include/core/data/List.hpp


+ 0 - 0
include/core/data/ProbingHashMap.hpp → old/include/core/data/ProbingHashMap.hpp


+ 0 - 0
include/core/data/RingBuffer.hpp → old/include/core/data/RingBuffer.hpp


+ 0 - 0
include/core/data/Stack.hpp → old/include/core/data/Stack.hpp


+ 0 - 0
include/core/io/File.hpp → old/include/core/io/File.hpp


+ 0 - 0
include/core/io/FileReader.hpp → old/include/core/io/FileReader.hpp


+ 0 - 0
include/core/math/Box.hpp → old/include/core/math/Box.hpp


+ 0 - 0
include/core/math/BufferedValue.hpp → old/include/core/math/BufferedValue.hpp


+ 0 - 0
include/core/math/Frustum.hpp → old/include/core/math/Frustum.hpp


+ 0 - 0
include/core/math/Math.hpp → old/include/core/math/Math.hpp


+ 0 - 0
include/core/math/Matrix.hpp → old/include/core/math/Matrix.hpp


+ 0 - 0
include/core/math/MatrixStack.hpp → old/include/core/math/MatrixStack.hpp


+ 0 - 0
include/core/math/Plane.hpp → old/include/core/math/Plane.hpp


+ 0 - 0
include/core/math/Quaternion.hpp → old/include/core/math/Quaternion.hpp


+ 0 - 0
include/core/math/Vector.hpp → old/include/core/math/Vector.hpp


+ 0 - 0
include/core/math/View.hpp → old/include/core/math/View.hpp


+ 0 - 0
include/core/thread/Mutex.hpp → old/include/core/thread/Mutex.hpp


+ 0 - 0
include/core/thread/SpinLock.hpp → old/include/core/thread/SpinLock.hpp


+ 0 - 0
include/core/thread/Thread.hpp → old/include/core/thread/Thread.hpp


+ 0 - 0
include/core/utils/AlignedData.hpp → old/include/core/utils/AlignedData.hpp


+ 0 - 0
include/core/utils/ArrayString.hpp → old/include/core/utils/ArrayString.hpp


+ 0 - 0
include/core/utils/Buffer.hpp → old/include/core/utils/Buffer.hpp


+ 0 - 0
include/core/utils/Check.hpp → old/include/core/utils/Check.hpp


+ 0 - 0
include/core/utils/Clock.hpp → old/include/core/utils/Clock.hpp


+ 0 - 0
include/core/utils/Color.hpp → old/include/core/utils/Color.hpp


+ 0 - 0
include/core/utils/Error.hpp → old/include/core/utils/Error.hpp


+ 0 - 0
include/core/utils/HashCode.hpp → old/include/core/utils/HashCode.hpp


+ 0 - 0
include/core/utils/HashedString.hpp → old/include/core/utils/HashedString.hpp


+ 0 - 0
include/core/utils/Logger.hpp → old/include/core/utils/Logger.hpp


+ 0 - 0
include/core/utils/Meta.hpp → old/include/core/utils/Meta.hpp


+ 0 - 0
include/core/utils/New.hpp → old/include/core/utils/New.hpp


+ 0 - 0
include/core/utils/Random.hpp → old/include/core/utils/Random.hpp


+ 0 - 0
include/core/utils/Types.hpp → old/include/core/utils/Types.hpp


+ 0 - 0
include/core/utils/UniquePointer.hpp → old/include/core/utils/UniquePointer.hpp


+ 0 - 0
include/core/utils/Utility.hpp → old/include/core/utils/Utility.hpp


+ 0 - 0
performance/Main.cpp → old/performance/Main.cpp


+ 0 - 0
src/ArrayString.cpp → old/src/ArrayString.cpp


+ 0 - 0
src/BitArray.cpp → old/src/BitArray.cpp


+ 0 - 0
src/Box.cpp → old/src/Box.cpp


+ 0 - 0
src/Buffer.cpp → old/src/Buffer.cpp


+ 0 - 0
src/Clock.cpp → old/src/Clock.cpp


+ 0 - 0
src/Error.cpp → old/src/Error.cpp


+ 0 - 0
src/ErrorSimulator.cpp → old/src/ErrorSimulator.cpp


+ 0 - 0
src/ErrorSimulator.hpp → old/src/ErrorSimulator.hpp


+ 0 - 0
src/FileReader.cpp → old/src/FileReader.cpp


+ 0 - 0
src/Frustum.cpp → old/src/Frustum.cpp


+ 0 - 0
src/Logger.cpp → old/src/Logger.cpp


+ 0 - 0
src/Matrix.cpp → old/src/Matrix.cpp


+ 0 - 0
src/Mutex.cpp → old/src/Mutex.cpp


+ 0 - 0
src/New.cpp → old/src/New.cpp


+ 0 - 0
src/Plane.cpp → old/src/Plane.cpp


+ 0 - 0
src/Quaternion.cpp → old/src/Quaternion.cpp


+ 0 - 0
src/Random.cpp → old/src/Random.cpp


+ 0 - 0
src/SpinLock.cpp → old/src/SpinLock.cpp


+ 0 - 0
src/Thread.cpp → old/src/Thread.cpp


+ 0 - 0
src/Utility.cpp → old/src/Utility.cpp


+ 0 - 0
src/Vector.cpp → old/src/Vector.cpp


+ 0 - 0
src/View.cpp → old/src/View.cpp


+ 0 - 0
tasks → old/tasks


+ 0 - 0
test/Main.cpp → old/test/Main.cpp


+ 0 - 0
test/Test.cpp → old/test/Test.cpp


+ 0 - 0
test/Test.hpp → old/test/Test.hpp


Some files were not shown because too many files changed in this diff