Kajetan Johannes Hammerle 2 kuukautta sitten
vanhempi
commit
c3f8e6fd71
87 muutettua tiedostoa jossa 792 lisäystä ja 705 poistoa
  1. 3 0
      .clangd
  2. 83 83
      CMakeLists.txt
  3. 32 9
      cmake/gcc_warnings.cmake
  4. 1 1
      include/core/BitArray.hpp
  5. 1 1
      include/core/Box.hpp
  6. 0 0
      include/core/Buffer.hpp
  7. 0 0
      include/core/Check.hpp
  8. 2 2
      include/core/Components.hpp
  9. 3 3
      include/core/File.hpp
  10. 2 2
      include/core/Frustum.hpp
  11. 1 1
      include/core/Generic.hpp
  12. 3 3
      include/core/HashMap.hpp
  13. 3 3
      include/core/List.hpp
  14. 0 59
      include/core/Logger.h
  15. 84 0
      include/core/Logger.hpp
  16. 2 2
      include/core/Matrix.hpp
  17. 0 0
      include/core/Meta.hpp
  18. 1 1
      include/core/Plane.hpp
  19. 1 1
      include/core/Quaternion.hpp
  20. 3 3
      include/core/Queue.hpp
  21. 1 1
      include/core/Random.hpp
  22. 0 0
      include/core/ReadLine.hpp
  23. 0 0
      include/core/SpinLock.hpp
  24. 1 1
      include/core/Terminal.hpp
  25. 0 65
      include/core/Test.h
  26. 44 0
      include/core/Test.hpp
  27. 0 0
      include/core/Thread.hpp
  28. 0 13
      include/core/ToString.h
  29. 53 0
      include/core/ToString.hpp
  30. 4 4
      include/core/Types.hpp
  31. 1 1
      include/core/Unicode.hpp
  32. 0 84
      include/core/Utility.h
  33. 96 0
      include/core/Utility.hpp
  34. 1 15
      include/core/Vector.hpp
  35. 1 1
      include/core/View.hpp
  36. 0 0
      performance/Main.cpp
  37. 3 3
      src/BitArray.cpp
  38. 3 3
      src/Box.cpp
  39. 2 2
      src/Buffer.cpp
  40. 1 1
      src/Components.cpp
  41. 2 1
      src/ErrorSimulator.cpp
  42. 16 2
      src/ErrorSimulator.hpp
  43. 13 13
      src/File.cpp
  44. 2 2
      src/Frustum.cpp
  45. 1 1
      src/HashMap.cpp
  46. 0 56
      src/Logger.c
  47. 27 0
      src/Logger.cpp
  48. 2 2
      src/Matrix.cpp
  49. 3 3
      src/Plane.cpp
  50. 2 2
      src/Quaternion.cpp
  51. 1 1
      src/Random.cpp
  52. 6 6
      src/ReadLine.cpp
  53. 1 1
      src/SpinLock.cpp
  54. 3 3
      src/Terminal.cpp
  55. 8 45
      src/Test.cpp
  56. 3 3
      src/Thread.cpp
  57. 0 30
      src/ToString.c
  58. 47 0
      src/ToString.cpp
  59. 1 1
      src/Unicode.cpp
  60. 78 48
      src/Utility.cpp
  61. 2 2
      src/Vector.cpp
  62. 2 2
      src/View.cpp
  63. 34 28
      test/Main.cpp
  64. 5 3
      test/Tests.hpp
  65. 0 0
      test/modules/BitArrayTests.cpp
  66. 0 0
      test/modules/BoxTests.cpp
  67. 0 0
      test/modules/BufferTests.cpp
  68. 0 0
      test/modules/ComponentsTests.cpp
  69. 10 10
      test/modules/FileTests.cpp
  70. 0 0
      test/modules/FrustumTests.cpp
  71. 0 0
      test/modules/HashMapTests.cpp
  72. 0 0
      test/modules/ListTests.cpp
  73. 0 0
      test/modules/MatrixTests.cpp
  74. 0 0
      test/modules/PlaneTests.cpp
  75. 0 0
      test/modules/QuaternionTests.cpp
  76. 0 0
      test/modules/QueueTests.cpp
  77. 0 0
      test/modules/RandomTests.cpp
  78. 0 0
      test/modules/ReadLineTests.cpp
  79. 0 0
      test/modules/SpinLockTests.cpp
  80. 0 0
      test/modules/TerminalTests.cpp
  81. 0 20
      test/modules/TestTests.c
  82. 17 0
      test/modules/TestTests.cpp
  83. 0 0
      test/modules/UnicodeTests.cpp
  84. 68 40
      test/modules/UtilityTests.cpp
  85. 0 0
      test/modules/VectorTests.cpp
  86. 0 0
      test/modules/ViewTests.cpp
  87. 2 12
      testData/ignoredCoverageFunctions

+ 3 - 0
.clangd

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

+ 83 - 83
CMakeLists.txt

@@ -1,60 +1,60 @@
 cmake_minimum_required(VERSION 3.25)
-project(core C)
+project(core CXX)
 
-set(CMAKE_C_STANDARD 23)
+set(CMAKE_CXX_STANDARD 23)
 
 set(SRC
-    "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"
+    #"src/BitArray.cpp"
+    #"src/Box.cpp"
+    #"src/Buffer.cpp"
+    #"src/Components.cpp"
+    "src/File.cpp"
+    #"src/Frustum.cpp"
+    #"src/HashMap.cpp"
+    "src/Logger.cpp"
+    #"src/Matrix.cpp"
+    #"src/Plane.cpp"
+    #"src/Quaternion.cpp"
+    #"src/Random.cpp"
+    #"src/ReadLine.cpp"
+    #"src/SpinLock.cpp"
+    #"src/Terminal.cpp"
+    "src/Test.cpp"
+    #"src/Thread.cpp"
+    "src/ToString.cpp"
+    #"src/Unicode.cpp"
+    "src/Utility.cpp"
+    #"src/Vector.cpp"
+    #"src/View.cpp"
 )
 
 set(SRC_TESTS
-    "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"
+    "test/Main.cpp"
+    #"test/modules/BitArrayTests.cpp"
+    #"test/modules/BoxTests.cpp"
+    #"test/modules/BufferTests.cpp"
+    #"test/modules/ComponentsTests.cpp"
+    "test/modules/FileTests.cpp"
+    #"test/modules/FrustumTests.cpp"
+    #"test/modules/HashMapTests.cpp"
+    #"test/modules/ListTests.cpp"
+    #"test/modules/MatrixTests.cpp"
+    #"test/modules/PlaneTests.cpp"
+    #"test/modules/QuaternionTests.cpp"
+    #"test/modules/QueueTests.cpp"
+    #"test/modules/RandomTests.cpp"
+    #"test/modules/ReadLineTests.cpp"
+    #"test/modules/SpinLockTests.cpp"
+    #"test/modules/TerminalTests.cpp"
+    "test/modules/TestTests.cpp"
+    #"test/modules/UnicodeTests.cpp"
+    "test/modules/UtilityTests.cpp"
+    #"test/modules/VectorTests.cpp"
+    #"test/modules/ViewTests.cpp"
 )
 
 set(SRC_PERFORMANCE
-    "performance/Main.c"
+    "performance/Main.cpp"
 )
 
 if("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
@@ -64,20 +64,20 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
     set(DEFINITIONS CHECK_MEMORY)
 else()
     set(DEFINITIONS ERROR_SIMULATOR CHECK_MEMORY)
-    if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
+    if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
         set(COMPILE_OPTIONS --coverage)
         set(LINK_OPTIONS gcov)
-    elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+    elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
         set(COMPILE_OPTIONS -fprofile-instr-generate -fcoverage-mapping)
         set(LINK_OPTIONS ${COMPILE_OPTIONS})
     endif()
     set(LOG_LEVEL 4)
-    list(APPEND SRC "src/ErrorSimulator.c")
+    list(APPEND SRC "src/ErrorSimulator.cpp")
 endif()
 
-if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
     include("cmake/gcc_warnings.cmake")
-elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang")
+elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
     include("cmake/clang_warnings.cmake")
 endif()
 
@@ -98,33 +98,33 @@ target_sources(core PUBLIC
     FILE_SET HEADERS
     BASE_DIRS include
     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
+        ./include/core/BitArray.hpp
+        ./include/core/Box.hpp
+        ./include/core/Buffer.hpp
+        ./include/core/Check.hpp
+        ./include/core/Components.hpp
+        ./include/core/File.hpp
+        ./include/core/Frustum.hpp
+        ./include/core/Generic.hpp
+        ./include/core/HashMap.hpp
+        ./include/core/List.hpp
+        ./include/core/Logger.hpp
+        ./include/core/Matrix.hpp
+        ./include/core/Plane.hpp
+        ./include/core/Quaternion.hpp
+        ./include/core/Queue.hpp
+        ./include/core/Random.hpp
+        ./include/core/ReadLine.hpp
+        ./include/core/SpinLock.hpp
+        ./include/core/Terminal.hpp
+        ./include/core/Test.hpp
+        ./include/core/Thread.hpp
+        ./include/core/ToString.hpp
+        ./include/core/Types.hpp
+        ./include/core/Unicode.hpp
+        ./include/core/Utility.hpp
+        ./include/core/Vector.hpp
+        ./include/core/View.hpp
 )
 install(TARGETS core FILE_SET HEADERS)
 
@@ -132,7 +132,7 @@ add_executable(test ${SRC_TESTS})
 target_link_libraries(test PRIVATE core)
 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})
+#add_executable(performance ${SRC_PERFORMANCE})
+#target_link_libraries(performance PRIVATE core)
+#target_include_directories(performance PRIVATE include)
+#target_compile_definitions(performance PRIVATE ${DEFINITIONS})

+ 32 - 9
cmake/gcc_warnings.cmake

@@ -1,6 +1,5 @@
 set(WARNINGS
-    -Wno-attributes
-
+    -Waligned-new=all
     -Wall
     -Walloc-zero
     -Walloca
@@ -9,20 +8,29 @@ set(WARNINGS
     -Warray-bounds=2
     -Warray-parameter
     -Wattribute-alias=2
-    -Wbad-function-cast
     -Wbidi-chars=any
     -Wcast-align=strict
     -Wcast-qual
+    -Wcatch-value=3
+    -Wcomma-subscript
+    -Wconditionally-supported
     -Wconversion
+    -Wctad-maybe-unsupported
+    -Wctor-dtor-privacy
     -Wdate-time
+    -Wdeprecated-copy-dtor
+    -Wdeprecated-enum-enum-conversion
+    -Wdeprecated-enum-float-conversion
     -Wdisabled-optimization
     -Wdouble-promotion
     -Wduplicated-branches
     -Wduplicated-cond
+    -Weffc++
     -Wenum-compare
     -Wenum-conversion
     -Werror
     -Wextra
+    -Wextra-semi
     -Wfloat-equal
     -Wformat-overflow=2
     -Wformat-signedness
@@ -32,39 +40,54 @@ set(WARNINGS
     -Wimplicit-fallthrough=5
     -Winfinite-recursion
     -Winit-self
+    -Winvalid-constexpr
+    -Winvalid-imported-macros
     -Winvalid-pch
-    -Wjump-misses-init
+    -Winvalid-utf8
     -Wlarger-than=1073741824
     -Wlogical-op
+    -Wmismatched-tags
     -Wmissing-braces
     -Wmissing-declarations
     -Wmissing-include-dirs
-    -Wmissing-prototypes
     -Wmultichar
-    -Wnarrowing
-    -Wnested-externs
+    -Wmultiple-inheritance
+    -Wnoexcept
+    -Wnon-virtual-dtor
     -Wnormalized=nfkc
     -Wnull-dereference
-    -Wold-style-definition
+    -Wold-style-cast
     -Woverlength-strings
+    -Woverloaded-virtual
+    -Wplacement-new=2
     -Wredundant-decls
+    -Wredundant-tags
+    -Wregister
     -Wshadow
     -Wshift-overflow=2
     -Wsign-conversion
+    -Wsign-promo
     -Wstack-protector
     -Wstack-usage=8388608
+    -Wstrict-null-sentinel
     -Wstrict-overflow=2
-    -Wstrict-prototypes
     -Wstringop-overflow=4
+    -Wsuggest-final-methods
+    -Wsuggest-final-types
+    -Wsuggest-override
     -Wswitch-enum
+    -Wsynth
     -Wtrampolines
     -Wtrivial-auto-var-init
     -Wundef
     -Wunreachable-code
     -Wunused-const-variable=2
     -Wuse-after-free=3
+    -Wvirtual-inheritance
     -Wvla
+    -Wvolatile
     -Wwrite-strings
+    -Wzero-as-null-pointer-constant
     -pedantic
     -pedantic-errors
 )

+ 1 - 1
include/core/BitArray.h → include/core/BitArray.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_BIT_ARRAY_H
 #define CORE_BIT_ARRAY_H
 
-#include "core/Types.h"
+#include "core/Types.hpp"
 
 typedef struct {
     u64 length : 56;

+ 1 - 1
include/core/Box.h → include/core/Box.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_BOX_H
 #define CORE_BOX_H
 
-#include "core/Vector.h"
+#include "core/Vector.hpp"
 
 typedef union {
     struct {

+ 0 - 0
include/core/Buffer.h → include/core/Buffer.hpp


+ 0 - 0
include/core/Check.h → include/core/Check.hpp


+ 2 - 2
include/core/Components.h → include/core/Components.hpp

@@ -1,8 +1,8 @@
 #ifndef CORE_COMPONENTS_H
 #define CORE_COMPONENTS_H
 
-#include "core/HashMap.h"
-#include "core/List.h"
+#include "core/HashMap.hpp"
+#include "core/List.hpp"
 
 #define isInvalidKeySize(key) ((key) == 0)
 #define equalSize(a, b) ((a) == (b))

+ 3 - 3
include/core/File.h → include/core/File.hpp

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

+ 2 - 2
include/core/Frustum.h → include/core/Frustum.hpp

@@ -1,8 +1,8 @@
 #ifndef CORE_FRUSTUM_H
 #define CORE_FRUSTUM_H
 
-#include "core/Matrix.h"
-#include "core/Plane.h"
+#include "core/Matrix.hpp"
+#include "core/Plane.hpp"
 
 typedef struct {
     Matrix projection;

+ 1 - 1
include/core/Generic.h → include/core/Generic.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_GENERIC_H
 #define CORE_GENERIC_H
 
-#include "core/Matrix.h"
+#include "core/Matrix.hpp"
 
 // clang-format off
 #define GENERIC_PAIR(type, name) type: name, const type : name

+ 3 - 3
include/core/HashMap.h → include/core/HashMap.hpp

@@ -1,9 +1,9 @@
 #ifndef CORE_HASHMAP_H
 #define CORE_HASHMAP_H
 
-#include "core/ToString.h"
-#include "core/Types.h"
-#include "core/Utility.h"
+#include "core/ToString.hpp"
+#include "core/Types.hpp"
+#include "core/Utility.hpp"
 
 size_t hashString(const char* key);
 size_t roundUp2(size_t n);

+ 3 - 3
include/core/List.h → include/core/List.hpp

@@ -3,9 +3,9 @@
 
 #include <assert.h>
 
-#include "core/ToString.h"
-#include "core/Types.h"
-#include "core/Utility.h"
+#include "core/ToString.hpp"
+#include "core/Types.hpp"
+#include "core/Utility.hpp"
 
 #define LIST(T, N)                                                        \
     struct ListT##N {                                                     \

+ 0 - 59
include/core/Logger.h

@@ -1,59 +0,0 @@
-#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

+ 84 - 0
include/core/Logger.hpp

@@ -0,0 +1,84 @@
+#ifndef CORE_LOGGER_HPP
+#define CORE_LOGGER_HPP
+
+#include <cstdio>
+
+#include "core/Terminal.hpp"
+#include "core/ToString.hpp"
+
+enum class LogLevel { NONE, ERROR, WARNING, INFO, DEBUG };
+
+extern LogLevel logLevel;
+
+using ReportHandler = void (*)(
+    LogLevel l, const char* file, int line, void* data, const char* message);
+void callReportHandler(
+    LogLevel l, const char* file, int line, const char* report);
+void setReportHandler(ReportHandler h, void* data);
+
+template<typename... Args>
+void callReportHandler(
+    LogLevel l, const char* file, int line, const char* format,
+    Args&&... args) {
+    char buffer[512];
+    formatBuffer(buffer, sizeof(buffer), format, Core::forward<Args>(args)...);
+    callReportHandler(l, file, line, buffer);
+}
+
+#define REPORT(l, ...) callReportHandler(l, __FILE__, __LINE__, __VA_ARGS__)
+
+const char* getShortFileName(const char* s);
+
+template<typename... Args>
+void printLog(
+    LogLevel l, const char* file, int line, const char* prefix,
+    const char* format, Args&&... args) {
+    if(logLevel < l) {
+        return;
+    }
+    file = getShortFileName(file);
+    fputs(prefix, stdout);
+    printf("%s:%d | ", file, line);
+    char buffer[512];
+    formatBuffer(buffer, sizeof(buffer), format, Core::forward<Args>(args)...);
+    fputs(buffer, stdout);
+    puts(TERMINAL_RESET);
+}
+
+#if defined(LOG_LEVEL) && LOG_LEVEL >= 1
+#define LOG_ERROR(...)                                                       \
+    printLog(                                                                \
+        LogLevel::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(                                             \
+        LogLevel::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(                                                        \
+        LogLevel::INFO, __FILE__, __LINE__, TERMINAL_BOLD "[INFO] ", \
+        __VA_ARGS__)
+#else
+#define LOG_INFO(...)
+#endif
+
+#if defined(LOG_LEVEL) && LOG_LEVEL >= 4
+#define LOG_DEBUG(...)                                               \
+    printLog(                                                        \
+        LogLevel::DEBUG, __FILE__, __LINE__,                         \
+        TERMINAL_BOLD TERMINAL_BRIGHT_BLACK "[DEBUG] ", __VA_ARGS__)
+#else
+#define LOG_DEBUG(...)
+#endif
+
+#endif

+ 2 - 2
include/core/Matrix.h → include/core/Matrix.hpp

@@ -1,8 +1,8 @@
 #ifndef CORE_MATRIX_H
 #define CORE_MATRIX_H
 
-#include "core/Quaternion.h"
-#include "core/Vector.h"
+#include "core/Quaternion.hpp"
+#include "core/Vector.hpp"
 
 typedef struct {
     Vector4 data[4];

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


+ 1 - 1
include/core/Plane.h → include/core/Plane.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_PLANE_H
 #define CORE_PLANE_H
 
-#include "core/Vector.h"
+#include "core/Vector.hpp"
 
 typedef struct {
     Vector3 abc;

+ 1 - 1
include/core/Quaternion.h → include/core/Quaternion.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_QUATERNION_H
 #define CORE_QUATERNION_H
 
-#include "core/Vector.h"
+#include "core/Vector.hpp"
 
 typedef struct {
     Vector4 v;

+ 3 - 3
include/core/Queue.h → include/core/Queue.hpp

@@ -3,9 +3,9 @@
 
 #include <assert.h>
 
-#include "core/ToString.h"
-#include "core/Types.h"
-#include "core/Utility.h"
+#include "core/ToString.hpp"
+#include "core/Types.hpp"
+#include "core/Utility.hpp"
 
 #define QUEUE(T, N)                                                       \
     typedef struct {                                                      \

+ 1 - 1
include/core/Random.h → include/core/Random.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_RANDOM_H
 #define CORE_RANDOM_H
 
-#include "core/Types.h"
+#include "core/Types.hpp"
 
 typedef struct {
     u32 data[25];

+ 0 - 0
include/core/ReadLine.h → include/core/ReadLine.hpp


+ 0 - 0
include/core/SpinLock.h → include/core/SpinLock.hpp


+ 1 - 1
include/core/Terminal.h → include/core/Terminal.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_TERMINAL_H
 #define CORE_TERMINAL_H
 
-#include "core/Vector.h"
+#include "core/Vector.hpp"
 
 #define ESC "\33["
 #define TERMINAL_RESET ESC "0m"

+ 0 - 65
include/core/Test.h

@@ -1,65 +0,0 @@
-#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

+ 44 - 0
include/core/Test.hpp

@@ -0,0 +1,44 @@
+#ifndef CORE_TEST_H
+#define CORE_TEST_H
+
+#include "core/Logger.hpp"
+#include "core/Types.hpp"
+
+void finalizeTests(void);
+bool addToResult(const char* file, bool comparison);
+
+template<typename T>
+bool testEqual(const char* file, int line, const T& wanted, const T& actual) {
+    file = getShortFileName(file);
+    if(addToResult(file, wanted == actual)) {
+        return true;
+    }
+    char buffer[512];
+    formatBuffer(
+        buffer, sizeof(buffer),
+        TERMINAL_RED "#:# - expected '#' got '#'" TERMINAL_RESET, file, line,
+        wanted, actual);
+    puts(buffer);
+    return false;
+}
+
+#define TEST_ARGS const char *file, int line
+
+bool testString(TEST_ARGS, const char* wanted, const char* actual);
+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_FLOAT(wanted, actual, error)                \
+    testFloat(__FILE__, __LINE__, wanted, actual, error)
+
+#define TEST(wanted, actual)                                        \
+    testEqual<decltype(wanted)>(__FILE__, __LINE__, wanted, actual)
+#define TEST_STRING(wanted, actual)                \
+    testString(__FILE__, __LINE__, wanted, actual)
+#define TEST_FALSE(actual) TEST(false, actual)
+#define TEST_TRUE(actual) TEST(true, actual)
+#define TEST_NULL(actual) testNull(__FILE__, __LINE__, actual)
+#define TEST_NOT_NULL(actual) testNotNull(__FILE__, __LINE__, actual)
+
+#endif

+ 0 - 0
include/core/Thread.h → include/core/Thread.hpp


+ 0 - 13
include/core/ToString.h

@@ -1,13 +0,0 @@
-#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

+ 53 - 0
include/core/ToString.hpp

@@ -0,0 +1,53 @@
+#ifndef CORE_TO_STRING_HPP
+#define CORE_TO_STRING_HPP
+
+#include <cstdio>
+#include <cstring>
+
+#include "core/Utility.hpp"
+
+size_t toString(int v, char* s, size_t n);
+size_t toString(long v, char* s, size_t n);
+size_t toString(long long v, char* s, size_t n);
+size_t toString(unsigned int v, char* s, size_t n);
+size_t toString(unsigned long v, char* s, size_t n);
+size_t toString(unsigned long long v, char* s, size_t n);
+size_t toString(const char* v, char* s, size_t n);
+size_t toString(bool v, char* s, size_t n);
+
+template<typename T>
+size_t toString(const T& t, char* s, size_t n) {
+    return t.toString(s, n);
+}
+
+void copyFormatUntil(const char*& format, char*& s, size_t& n);
+void copyFormat(const char*& format, char*& s, size_t& n);
+
+template<typename T, typename... Args>
+void formatR(
+    const char*& format, char*& s, size_t& n, const T& t, Args&&... args) {
+    copyFormatUntil(format, s, n);
+    if(n > 1) {
+        size_t w = min(toString(t, s, n - 1), n - 1);
+        s += w;
+        n -= w;
+    }
+    *s = '\0';
+    if constexpr(sizeof...(args) > 0) {
+        formatR(format, s, n, Core::forward<Args>(args)...);
+    }
+}
+
+template<typename... Args>
+size_t formatBuffer(char* s, size_t n, const char* format, Args&&... args) {
+    if constexpr(sizeof...(args) > 0) {
+        formatR(format, s, n, Core::forward<Args>(args)...);
+        copyFormat(format, s, n);
+    } else {
+        memcpy(s, format, min(n, strlen(format)));
+        s[n - (n > 0)] = 0;
+    }
+    return 0;
+}
+
+#endif

+ 4 - 4
include/core/Types.h → include/core/Types.hpp

@@ -1,8 +1,8 @@
-#ifndef CORE_TYPES_H
-#define CORE_TYPES_H
+#ifndef CORE_TYPES_HPP
+#define CORE_TYPES_HPP
 
-#include <stddef.h>
-#include <stdint.h>
+#include <cstddef>
+#include <cstdint>
 
 typedef int64_t i64;
 typedef int32_t i32;

+ 1 - 1
include/core/Unicode.h → include/core/Unicode.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_UNICODE_H
 #define CORE_UNICODE_H
 
-#include "core/Types.h"
+#include "core/Types.hpp"
 
 typedef struct {
     u8 data[4];

+ 0 - 84
include/core/Utility.h

@@ -1,84 +0,0 @@
-#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

+ 96 - 0
include/core/Utility.hpp

@@ -0,0 +1,96 @@
+#ifndef CORE_UTILITY_HPP
+#define CORE_UTILITY_HPP
+
+#include "core/Meta.hpp"
+#include "core/Types.hpp"
+
+size_t popCount(u64 u);
+
+template<typename T>
+inline T interpolate(const T& a, const T& b, float factor) {
+    return a * (1.0f - factor) + b * factor;
+}
+
+static constexpr float PI = 3.14159265358979323846f;
+
+template<typename T>
+inline T radianToDegree(const T& radians) {
+    return radians * static_cast<T>(180.0f / PI);
+}
+
+template<typename T>
+inline T degreeToRadian(const T& radians) {
+    return radians * static_cast<T>(PI / 180.0f);
+}
+
+template<typename T>
+inline T max(const T& a, const T& b) {
+    return a > b ? a : b;
+}
+
+template<typename T>
+inline T min(const T& a, const T& b) {
+    return a < b ? a : b;
+}
+
+template<typename T>
+inline T clamp(const T& t, const T& from, const T& to) {
+    return max(min(t, to), from);
+}
+
+using ExitHandler = void (*)(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)
+
+using OutOfMemoryHandler = void (*)(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(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(p)
+void* operator new(size_t count, const char* file, int line);
+void* operator new[](size_t count, const char* file, int line);
+#define coreNew(type, ...) new(__FILE__, __LINE__) type(__VA_ARGS__)
+#define coreNewN(type, n) new(__FILE__, __LINE__) type[n]
+#define coreDelete(p) delete(p)
+#define coreDeleteN(p) delete[](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()
+#define coreNew(type, ...) new type(__VA_ARGS__)
+#define coreNewN(type, n) new type[n]
+#define coreDelete(p) delete(p)
+#define coreDeleteN(p) delete[](p)
+#endif
+
+bool sleepMillis(i64 millis);
+bool sleepNanos(i64 nanos);
+i64 getNanos(void);
+
+template<typename T>
+void bubbleSort(T* data, size_t n) {
+    bool swapped = true;
+    while(swapped && n > 0) {
+        swapped = false;
+        n--;
+        for(size_t i = 0; i < n; i++) {
+            if(data[i] > data[i + 1]) {
+                Core::swap(data[i], data[i + 1]);
+                swapped = true;
+            }
+        }
+    }
+}
+
+#endif

+ 1 - 15
include/core/Vector.h → include/core/Vector.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_VECTOR_H
 #define CORE_VECTOR_H
 
-#include "core/Types.h"
+#include "core/Types.hpp"
 
 #define VECTOR_OP2(name) name *r, const name *a
 #define VECTOR_OP3(name) VECTOR_OP2(name), const name* b
@@ -9,26 +9,12 @@
 #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);

+ 1 - 1
include/core/View.h → include/core/View.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_VIEW_H
 #define CORE_VIEW_H
 
-#include "core/Matrix.h"
+#include "core/Matrix.hpp"
 
 typedef struct {
     Matrix view;

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


+ 3 - 3
src/BitArray.c → src/BitArray.cpp

@@ -1,11 +1,11 @@
-#include "core/BitArray.h"
+#include "core/BitArray.hpp"
 
 #include <assert.h>
 #include <inttypes.h>
 #include <string.h>
 
-#include "core/ToString.h"
-#include "core/Utility.h"
+#include "core/ToString.hpp"
+#include "core/Utility.hpp"
 
 static constexpr size_t U64_BITS = 64;
 static constexpr size_t DIVIDE_BITS = 6;

+ 3 - 3
src/Box.c → src/Box.cpp

@@ -1,7 +1,7 @@
-#include "core/Box.h"
+#include "core/Box.hpp"
 
-#include "core/Generic.h"
-#include "core/ToString.h"
+#include "core/Generic.hpp"
+#include "core/ToString.hpp"
 
 void setBox(Box* box, const Vector3* size) {
     for(size_t i = 0; i < 3; i++) {

+ 2 - 2
src/Buffer.c → src/Buffer.cpp

@@ -1,8 +1,8 @@
-#include "core/Buffer.h"
+#include "core/Buffer.hpp"
 
 #include <string.h>
 
-#include "core/Utility.h"
+#include "core/Utility.hpp"
 
 void initBuffer(Buffer* b) {
     b->buffer = nullptr;

+ 1 - 1
src/Components.c → src/Components.cpp

@@ -1,4 +1,4 @@
-#include "core/Components.h"
+#include "core/Components.hpp"
 
 LIST_SOURCE(size_t, Size)
 HASHMAP_SOURCE(size_t, size_t, Size)

+ 2 - 1
src/ErrorSimulator.c → src/ErrorSimulator.cpp

@@ -1,6 +1,6 @@
 #ifdef ERROR_SIMULATOR
 
-#include "ErrorSimulator.h"
+#include "ErrorSimulator.hpp"
 
 bool failTimeGet = false;
 bool failThreadInit = false;
@@ -9,5 +9,6 @@ bool failMutexInit = false;
 bool failMutexLock = false;
 bool failMutexUnlock = false;
 int failStep = -1;
+int failStepThrow = -1;
 
 #endif

+ 16 - 2
src/ErrorSimulator.h → src/ErrorSimulator.hpp

@@ -1,5 +1,7 @@
-#ifndef CORE_ERROR_SIMULATOR_H
-#define CORE_ERROR_SIMULATOR_H
+#ifndef CORE_ERROR_SIMULATOR_HPP
+#define CORE_ERROR_SIMULATOR_HPP
+
+#include <stdexcept>
 
 #ifdef ERROR_SIMULATOR
 extern bool failTimeGet;
@@ -9,6 +11,7 @@ extern bool failMutexInit;
 extern bool failMutexLock;
 extern bool failMutexUnlock;
 extern int failStep;
+extern int failStepThrow;
 #define TIME_GET_FAIL failTimeGet
 #define THREAD_INIT_FAIL failThreadInit
 #define THREAD_JOIN_FAIL failThreadJoin
@@ -16,6 +19,14 @@ extern int failStep;
 #define MUTEX_LOCK_FAIL failMutexLock
 #define MUTEX_UNLOCK_FAIL failMutexUnlock
 #define FAIL_STEP (--failStep == 0)
+
+inline void debugThrow() {
+    if(--failStepThrow == 0) {
+        throw std::runtime_error("not a real error");
+    }
+}
+
+#define FAIL_STEP_THROW() debugThrow()
 #else
 #define TIME_GET_FAIL false
 #define THREAD_INIT_FAIL false
@@ -24,6 +35,9 @@ extern int failStep;
 #define MUTEX_LOCK_FAIL false
 #define MUTEX_UNLOCK_FAIL false
 #define FAIL_STEP false
+#define FAIL_STEP_THROW() \
+    do {                  \
+    } while(false)
 #endif
 
 #endif

+ 13 - 13
src/File.c → src/File.cpp

@@ -1,32 +1,32 @@
-#include "core/File.h"
+#include "core/File.hpp"
 
 #include <stdio.h>
 
-#include "ErrorSimulator.h"
-#include "core/Logger.h"
-#include "core/Utility.h"
+#include "ErrorSimulator.hpp"
+#include "core/Logger.hpp"
+#include "core/Utility.hpp"
 
 static bool readOpenFile(FILE* file, FileContent* f, const char* path) {
     if(FAIL_STEP || fseek(file, 0, SEEK_END)) {
-        REPORT(LOG_ERROR, "cannot seek file end of '%s'", path);
+        REPORT(LogLevel::ERROR, "cannot seek file end of '#'", path);
         return true;
     }
     long l = ftell(file);
     if(FAIL_STEP || l < 0) {
-        REPORT(LOG_ERROR, "cannot tell file position of '%s'", path);
+        REPORT(LogLevel::ERROR, "cannot tell file position of '#'", path);
         return true;
     }
     f->length = (size_t)l;
     if(FAIL_STEP || fseek(file, 0, SEEK_SET)) {
-        REPORT(LOG_ERROR, "cannot seek file start of '%s'", path);
+        REPORT(LogLevel::ERROR, "cannot seek file start of '#'", path);
         return true;
     }
-    f->data = coreAllocate(f->length + 1);
+    f->data = coreNewN(char, f->length + 1);
     size_t read = fread(f->data, 1, f->length, file);
     f->data[f->length] = 0;
     if(FAIL_STEP || read != f->length) {
         REPORT(
-            LOG_ERROR, "expected to read %zu bytes from '%s' but read %zu",
+            LogLevel::ERROR, "expected to read # bytes from '#' but read #",
             f->length, path, read);
         return true;
     }
@@ -36,12 +36,12 @@ static bool readOpenFile(FILE* file, FileContent* f, const char* path) {
 bool readFile(FileContent* f, const char* path) {
     FILE* file = fopen(path, "rb");
     if(file == nullptr) {
-        REPORT(LOG_ERROR, "cannot read file '%s'", path);
+        REPORT(LogLevel::ERROR, "cannot read file '#'", path);
         return true;
     }
     bool r = readOpenFile(file, f, path);
     if(FAIL_STEP || fclose(file)) {
-        REPORT(LOG_ERROR, "cannot close file '%s'", path);
+        REPORT(LogLevel::ERROR, "cannot close file '#'", path);
         r = true;
     }
     if(r) {
@@ -51,6 +51,6 @@ bool readFile(FileContent* f, const char* path) {
 }
 
 void destroyFileContent(FileContent* f) {
-    coreFree(f->data);
-    *f = (FileContent){0};
+    coreDeleteN(f->data);
+    *f = {};
 }

+ 2 - 2
src/Frustum.c → src/Frustum.cpp

@@ -1,8 +1,8 @@
-#include "core/Frustum.h"
+#include "core/Frustum.hpp"
 
 #include <math.h>
 
-#include "core/Generic.h"
+#include "core/Generic.hpp"
 
 void initFrustum(Frustum* f, float fieldOfView, float nearClip, float farClip) {
     f->tan = tanf(fieldOfView * 0.5f);

+ 1 - 1
src/HashMap.c → src/HashMap.cpp

@@ -1,4 +1,4 @@
-#include "core/HashMap.h"
+#include "core/HashMap.hpp"
 
 size_t hashString(const char* key) {
     size_t h = 0;

+ 0 - 56
src/Logger.c

@@ -1,56 +0,0 @@
-#include "core/Logger.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-
-LogLevel logLevel = LOG_DEBUG;
-static ReportHandler reportHandler = nullptr;
-static void* reportData = nullptr;
-
-void setReportHandler(ReportHandler h, void* data) {
-    reportHandler = h;
-    reportData = data;
-}
-
-void callReportHandler(
-    LogLevel l, const char* file, int line, const char* format, ...) {
-    char buffer[512];
-
-    va_list args;
-    va_start(args, format);
-    vsnprintf(buffer, sizeof(buffer), format, args);
-    va_end(args);
-
-    if(reportHandler != nullptr) {
-        reportHandler(l, file, line, reportData, buffer);
-    }
-}
-
-const char* getShortFileName(const char* s) {
-    const char* r = s;
-    while(*s != '\0') {
-        if(*(s++) == '/') {
-            r = s;
-        }
-    }
-    return r;
-}
-
-void printLog(
-    LogLevel l, const char* file, int line, const char* prefix, const char* tag,
-    const char* format, ...) {
-    if(logLevel < l) {
-        return;
-    }
-    file = getShortFileName(file);
-    fputs(prefix, stdout);
-    fputs(tag, stdout);
-    printf("%s:%d | ", file, line);
-
-    va_list args;
-    va_start(args, format);
-    vprintf(format, args);
-    va_end(args);
-
-    puts(TERMINAL_RESET);
-}

+ 27 - 0
src/Logger.cpp

@@ -0,0 +1,27 @@
+#include "core/Logger.hpp"
+
+LogLevel logLevel = LogLevel::DEBUG;
+static ReportHandler reportHandler = nullptr;
+static void* reportData = nullptr;
+
+void setReportHandler(ReportHandler h, void* data) {
+    reportHandler = h;
+    reportData = data;
+}
+
+void callReportHandler(
+    LogLevel l, const char* file, int line, const char* report) {
+    if(reportHandler != nullptr) {
+        reportHandler(l, file, line, reportData, report);
+    }
+}
+
+const char* getShortFileName(const char* s) {
+    const char* r = s;
+    while(*s != '\0') {
+        if(*(s++) == '/') {
+            r = s;
+        }
+    }
+    return r;
+}

+ 2 - 2
src/Matrix.c → src/Matrix.cpp

@@ -1,8 +1,8 @@
 #include <math.h>
 #include <stdio.h>
 
-#include "core/Generic.h"
-#include "core/ToString.h"
+#include "core/Generic.hpp"
+#include "core/ToString.hpp"
 
 #define M(m, x, y) ((m)->data[x].data[y])
 

+ 3 - 3
src/Plane.c → src/Plane.cpp

@@ -1,7 +1,7 @@
-#include "core/Plane.h"
+#include "core/Plane.hpp"
 
-#include "core/Generic.h"
-#include "core/ToString.h"
+#include "core/Generic.hpp"
+#include "core/ToString.hpp"
 
 void initPlane(Plane* p, const Vector3* a, const Vector3* b, const Vector3* c) {
     cross(&p->abc, sub(b, a), sub(c, a));

+ 2 - 2
src/Quaternion.c → src/Quaternion.cpp

@@ -1,7 +1,7 @@
 #include <math.h>
 
-#include "core/Generic.h"
-#include "core/ToString.h"
+#include "core/Generic.hpp"
+#include "core/ToString.hpp"
 
 typedef Quaternion Q;
 

+ 1 - 1
src/Random.c → src/Random.cpp

@@ -1,4 +1,4 @@
-#include "core/Random.h"
+#include "core/Random.hpp"
 
 static const size_t M = 7;
 

+ 6 - 6
src/ReadLine.c → src/ReadLine.cpp

@@ -1,4 +1,4 @@
-#include "core/ReadLine.h"
+#include "core/ReadLine.hpp"
 
 #include <ctype.h>
 #include <stdatomic.h>
@@ -6,11 +6,11 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "ErrorSimulator.h"
-#include "core/Logger.h"
-#include "core/Queue.h"
-#include "core/Thread.h"
-#include "core/Unicode.h"
+#include "ErrorSimulator.hpp"
+#include "core/Logger.hpp"
+#include "core/Queue.hpp"
+#include "core/Thread.hpp"
+#include "core/Unicode.hpp"
 
 static constexpr size_t HISTORY_LENGTH = 10;
 static constexpr size_t CONSOLE_BUFFER_SIZE = 256;

+ 1 - 1
src/SpinLock.c → src/SpinLock.cpp

@@ -1,4 +1,4 @@
-#include "core/SpinLock.h"
+#include "core/SpinLock.hpp"
 
 #include <threads.h>
 

+ 3 - 3
src/Terminal.c → src/Terminal.cpp

@@ -1,12 +1,12 @@
-#include "core/Terminal.h"
+#include "core/Terminal.hpp"
 
 #include <stdio.h>
 #include <sys/ioctl.h>
 #include <termios.h>
 #include <unistd.h>
 
-#include "core/Logger.h"
-#include "core/Unicode.h"
+#include "core/Logger.hpp"
+#include "core/Unicode.hpp"
 
 #define ESC "\33["
 #define esc(s) fputs(ESC s, stdout)

+ 8 - 45
src/Test.c → src/Test.cpp

@@ -1,12 +1,12 @@
-#include "core/Test.h"
+#include "core/Test.hpp"
 
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-#include "core/Logger.h"
-#include "core/Utility.h"
+#include "core/Logger.hpp"
+#include "core/Utility.hpp"
 
 typedef struct {
     char* file;
@@ -27,7 +27,8 @@ static Result* getResult(const char* file) {
     }
     while(resultsIndex >= resultsCapacity) {
         size_t newCapacity = resultsCapacity == 0 ? 8 : resultsCapacity * 2;
-        results = coreReallocate(results, newCapacity * sizeof(Result));
+        results = static_cast<Result*>(
+            coreReallocate(results, newCapacity * sizeof(Result)));
         resultsCapacity = newCapacity;
     }
     Result* r = results + (resultsIndex++);
@@ -53,7 +54,7 @@ void finalizeTests(void) {
     resultsCapacity = 0;
 }
 
-static bool addToResult(const char* file, bool comparison) {
+bool addToResult(const char* file, bool comparison) {
     Result* r = getResult(file);
     r->tests++;
     if(comparison) {
@@ -69,25 +70,6 @@ static bool addToResult(const char* file, bool comparison) {
         return true;                \
     }
 
-#define TEST_NAMED_COMPARE(name, type, format)                            \
-    bool test##name(TEST_ARGS, type wanted, type actual) {                \
-        TEST_SUCCESS(wanted == actual)                                    \
-        fputs(TERMINAL_RED, stdout);                                      \
-        printf(                                                           \
-            "%s:%d - expected '" format "' got '" format "'", file, line, \
-            wanted, actual);                                              \
-        puts(TERMINAL_RESET);                                             \
-        return false;                                                     \
-    }
-
-TEST_NAMED_COMPARE(Int, int, "%d")
-TEST_NAMED_COMPARE(I32, i32, "%" PRId32)
-TEST_NAMED_COMPARE(I64, i64, "%" PRId64)
-TEST_NAMED_COMPARE(U32, u32, "%" PRIu32)
-TEST_NAMED_COMPARE(U64, u64, "%" PRIu64)
-TEST_NAMED_COMPARE(Size, size_t, "%zu")
-TEST_NAMED_COMPARE(Bool, bool, "%d")
-
 bool testString(TEST_ARGS, const char* wanted, const char* actual) {
     TEST_SUCCESS(strcmp(wanted, actual) == 0)
     fputs(TERMINAL_RED, stdout);
@@ -102,8 +84,8 @@ bool testFloat(TEST_ARGS, float wanted, float actual, float error) {
     TEST_SUCCESS(diff <= error)
     fputs(TERMINAL_RED, stdout);
     printf(
-        "%s:%d - expected '%.3f' got '%.3f'", file, line, (double)wanted,
-        (double)actual);
+        "%s:%d - expected '%.3f' got '%.3f'", file, line,
+        static_cast<double>(wanted), static_cast<double>(actual));
     puts(TERMINAL_RESET);
     return false;
 }
@@ -123,22 +105,3 @@ bool testNotNull(TEST_ARGS, const void* actual) {
     puts(TERMINAL_RESET);
     return false;
 }
-
-bool testVectorN(
-    TEST_ARGS, const float* wanted, const float* actual, size_t n) {
-    for(size_t i = 0; i < n; i++) {
-        if(!testFloat(file, line, wanted[i], actual[i], 0.01f)) {
-            return false;
-        }
-    }
-    return true;
-}
-
-bool testIntVectorN(TEST_ARGS, const int* wanted, const int* actual, size_t n) {
-    for(size_t i = 0; i < n; i++) {
-        if(!testInt(file, line, wanted[i], actual[i])) {
-            return false;
-        }
-    }
-    return true;
-}

+ 3 - 3
src/Thread.c → src/Thread.cpp

@@ -1,9 +1,9 @@
-#include "core/Thread.h"
+#include "core/Thread.hpp"
 
 #include <string.h>
 
-#include "ErrorSimulator.h"
-#include "core/Logger.h"
+#include "ErrorSimulator.hpp"
+#include "core/Logger.hpp"
 
 bool joinThreadSafe(thrd_t* t) {
     static thrd_t nullThread = {0};

+ 0 - 30
src/ToString.c

@@ -1,30 +0,0 @@
-#include "core/ToString.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-
-size_t toString(char* buffer, size_t n, const char* format, ...) {
-    va_list args;
-    va_start(args, format);
-    int w = vsnprintf(buffer, n, format, args);
-    va_end(args);
-    return w < 0 ? 0 : (size_t)w;
-}
-
-size_t toStringSize(const size_t* p, char* buffer, size_t n) {
-    return toString(buffer, n, "%zu", *p);
-}
-
-size_t toStringInt(const int* p, char* buffer, size_t n) {
-    return toString(buffer, n, "%d", *p);
-}
-
-void stringAdd(size_t* w, char** buffer, size_t* n, size_t shift) {
-    *w += shift;
-    if(*n > shift) {
-        *buffer += shift;
-        *n -= shift;
-    } else {
-        *n = 0;
-    }
-}

+ 47 - 0
src/ToString.cpp

@@ -0,0 +1,47 @@
+#include "core/ToString.hpp"
+
+#include <cstdarg>
+#include <cstdio>
+
+#define TO_STRING(type, format)                    \
+    size_t toString(type v, char* s, size_t n) {   \
+        int e = snprintf(s, n, format, v);         \
+        return e < 0 ? 0 : static_cast<size_t>(e); \
+    }
+
+TO_STRING(int, "%d")
+TO_STRING(long, "%ld")
+TO_STRING(long long, "%lld")
+TO_STRING(unsigned int, "%u")
+TO_STRING(unsigned long, "%lu")
+TO_STRING(unsigned long long, "%llu")
+TO_STRING(const char*, "%s")
+
+size_t toString(bool v, char* s, size_t n) {
+    int e = snprintf(s, n, "%s", v ? "true" : "false");
+    return e < 0 ? 0 : static_cast<size_t>(e);
+}
+
+void copyFormatUntil(const char*& format, char*& s, size_t& n) {
+    while(*format != '\0' && n > 1) {
+        char u = *(format++);
+        if(u == '#') {
+            if(*format != '#') {
+                return;
+            }
+            format++;
+        }
+        *s = u;
+        s++;
+        n--;
+    }
+    *s = '\0';
+}
+
+void copyFormat(const char*& format, char*& s, size_t& n) {
+    while(*format != '\0' && n > 1) {
+        *(s++) = *(format++);
+        n--;
+    }
+    *s = '\0';
+}

+ 1 - 1
src/Unicode.c → src/Unicode.cpp

@@ -1,4 +1,4 @@
-#include "core/Unicode.h"
+#include "core/Unicode.hpp"
 
 UTF8 convertUnicodeToUTF8(u32 c) {
     UTF8 u = {0};

+ 78 - 48
src/Utility.c → src/Utility.cpp

@@ -1,22 +1,14 @@
-#include "core/Utility.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <threads.h>
-#include <time.h>
-
-#include "ErrorSimulator.h"
-#include "core/Logger.h"
-
-#define MIN_MAX_DEF(type, name)                                \
-    extern inline type max##name(type a, type b);              \
-    extern inline type min##name(type a, type b);              \
-    extern inline type clamp##name(type t, type from, type to)
-MIN_MAX_DEF(size_t, Size);
-MIN_MAX_DEF(u32, U32);
-MIN_MAX_DEF(i32, I32);
-MIN_MAX_DEF(float, Float);
+#include "core/Utility.hpp"
+
+#include <chrono>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <thread>
+
+#include "ErrorSimulator.hpp"
+#include "core/Logger.hpp"
 
 static ExitHandler exitHandler = nullptr;
 static void* exitData = nullptr;
@@ -35,7 +27,7 @@ size_t popCount(u64 u) {
 [[noreturn]] void exitWithHandler(const char* file, int line, int value) {
     if(value != 0) {
         file = getShortFileName(file);
-        LOG_ERROR("Exit from %s:%d with value %d", file, line, value);
+        LOG_ERROR("Exit from #:# with value #", file, line, value);
     }
     if(exitHandler != nullptr) {
         exitHandler(value, exitData);
@@ -55,7 +47,7 @@ void setOutOfMemoryHandler(OutOfMemoryHandler h, void* data) {
 
 static void* exitOnNull(void* p, size_t n) {
     if(p == nullptr) {
-        LOG_ERROR("Out of memory, requested '%zu' bytes", n);
+        LOG_ERROR("Out of memory, requested '#' bytes", n);
         EXIT(1);
     }
     return p;
@@ -93,9 +85,6 @@ static void RealFree(void* p) {
 static const u8 CANARY[16] = {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
                               0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF};
 
-struct MemoryInfo;
-typedef struct MemoryInfo MemoryInfo;
-
 struct MemoryInfo {
     MemoryInfo* next;
     MemoryInfo* previous;
@@ -116,7 +105,9 @@ static void addMemoryInfo(
     info->line = line;
     snprintf(info->buffer, sizeof(info->buffer), "%s", getShortFileName(file));
     memcpy(info->canary, CANARY, sizeof(CANARY));
-    memcpy((char*)info + n - sizeof(CANARY), CANARY, sizeof(CANARY));
+    memcpy(
+        reinterpret_cast<char*>(info) + n - sizeof(CANARY), CANARY,
+        sizeof(CANARY));
     if(headMemoryInfo == nullptr) {
         headMemoryInfo = info;
     } else {
@@ -147,8 +138,8 @@ static void removeMemoryInfo(MemoryInfo* info) {
 void* coreDebugAllocate(const char* file, int line, size_t n) {
     n += sizeof(MemoryInfo) + sizeof(CANARY);
     void* p = RealAllocate(n + sizeof(CANARY));
-    addMemoryInfo(p, file, line, n);
-    return (char*)p + sizeof(MemoryInfo);
+    addMemoryInfo(static_cast<MemoryInfo*>(p), file, line, n);
+    return static_cast<char*>(p) + sizeof(MemoryInfo);
 }
 
 void* coreDebugZeroAllocate(const char* file, int line, size_t n) {
@@ -161,36 +152,36 @@ void* coreDebugReallocate(const char* file, int line, void* p, size_t n) {
     if(n > 0) {
         n += sizeof(MemoryInfo) + sizeof(CANARY);
     }
-    void* rp = (void*)p;
+    void* rp = p;
     if(rp != nullptr) {
-        rp = (char*)rp - sizeof(MemoryInfo);
-        removeMemoryInfo(rp);
+        rp = static_cast<char*>(rp) - sizeof(MemoryInfo);
+        removeMemoryInfo(static_cast<MemoryInfo*>(rp));
     }
     void* np = RealReallocate(rp, n);
     if(np == nullptr) {
         return nullptr;
     }
-    addMemoryInfo(np, file, line, n);
-    return (char*)np + sizeof(MemoryInfo);
+    addMemoryInfo(static_cast<MemoryInfo*>(np), file, line, n);
+    return static_cast<char*>(np) + sizeof(MemoryInfo);
 }
 
 static bool checkCanary(void* p) {
     return memcmp(p, CANARY, sizeof(CANARY)) != 0;
 }
 
-void coreFreeDebug(const char* file, int line, void* p) {
+void coreFreeDebug(void* p) {
     if(p == nullptr) {
         return;
     }
-    void* w = (char*)p - sizeof(MemoryInfo);
-    MemoryInfo* rp = w;
+    void* w = static_cast<char*>(p) - sizeof(MemoryInfo);
+    MemoryInfo* rp = static_cast<MemoryInfo*>(w);
+    rp->buffer[sizeof(rp->buffer) - 1] = '\0'; // end might be broken
     if(checkCanary(rp->canary)) {
-        file = getShortFileName(file);
-        LOG_ERROR("Free at %s:%d violated pre canary", file, line);
+        LOG_ERROR("Free at #:# violated pre canary", rp->buffer, rp->line);
         EXIT(1);
-    } else if(checkCanary((char*)rp + rp->size - sizeof(CANARY))) {
-        file = getShortFileName(file);
-        LOG_ERROR("Free at %s:%d violated post canary", file, line);
+    } else if(checkCanary(
+                  reinterpret_cast<char*>(rp) + rp->size - sizeof(CANARY))) {
+        LOG_ERROR("Free at #:# violated post canary", rp->buffer, rp->line);
         EXIT(1);
     }
     removeMemoryInfo(rp);
@@ -199,10 +190,42 @@ void coreFreeDebug(const char* file, int line, void* p) {
 
 void printMemoryReport() {
     for(MemoryInfo* i = headMemoryInfo; i != nullptr; i = i->next) {
-        LOG_ERROR("%s:%d was not freed", i->buffer, i->line);
+        LOG_ERROR("#:# was not freed", i->buffer, i->line);
     }
 }
 
+void* operator new(size_t count) {
+    return coreDebugAllocate("unknown", -1, count);
+}
+
+void* operator new(size_t count, const char* file, int line) {
+    return coreDebugAllocate(file, line, count);
+}
+
+void* operator new[](size_t count) {
+    return coreDebugAllocate("unknown", -1, count);
+}
+
+void* operator new[](size_t count, const char* file, int line) {
+    return coreDebugAllocate(file, line, count);
+}
+
+void operator delete(void* p) noexcept {
+    coreFreeDebug(p);
+}
+
+void operator delete(void* p, size_t) noexcept {
+    coreFreeDebug(p);
+}
+
+void operator delete[](void* p) noexcept {
+    coreFreeDebug(p);
+}
+
+void operator delete[](void* p, size_t) noexcept {
+    coreFreeDebug(p);
+}
+
 #else
 
 void* coreAllocate(size_t n) {
@@ -226,10 +249,13 @@ void coreFree(void* p) {
 #endif
 
 bool sleepNanos(i64 nanos) {
-    struct timespec t;
-    t.tv_nsec = nanos % 1'000'000'000;
-    t.tv_sec = nanos / 1'000'000'000;
-    return thrd_sleep(&t, nullptr) != 0;
+    try {
+        FAIL_STEP_THROW();
+        std::this_thread::sleep_for(std::chrono::nanoseconds(nanos));
+    } catch(...) {
+        return true;
+    }
+    return false;
 }
 
 bool sleepMillis(i64 millis) {
@@ -237,9 +263,13 @@ bool sleepMillis(i64 millis) {
 }
 
 i64 getNanos(void) {
-    struct timespec ts;
-    if(timespec_get(&ts, TIME_UTC) == 0 || TIME_GET_FAIL) {
+    try {
+        FAIL_STEP_THROW();
+        using namespace std::chrono;
+        return duration_cast<nanoseconds>(
+                   high_resolution_clock::now().time_since_epoch())
+            .count();
+    } catch(std::exception& e) {
         return -1;
     }
-    return (i64)ts.tv_sec * 1'000'000'000L + (i64)ts.tv_nsec;
 }

+ 2 - 2
src/Vector.c → src/Vector.cpp

@@ -1,8 +1,8 @@
-#include "core/Vector.h"
+#include "core/Vector.hpp"
 
 #include <math.h>
 
-#include "core/ToString.h"
+#include "core/ToString.hpp"
 
 typedef Vector2 V2;
 typedef Vector3 V3;

+ 2 - 2
src/View.c → src/View.cpp

@@ -1,6 +1,6 @@
-#include "core/View.h"
+#include "core/View.hpp"
 
-#include "core/Generic.h"
+#include "core/Generic.hpp"
 
 void initView(View* v) {
     *v = (View){0};

+ 34 - 28
test/Main.c → test/Main.cpp

@@ -3,10 +3,10 @@
 #include <string.h>
 #include <threads.h>
 
-#include "Tests.h"
-#include "core/Logger.h"
-#include "core/Test.h"
-#include "core/Utility.h"
+#include "Tests.hpp"
+#include "core/Logger.hpp"
+#include "core/Test.hpp"
+#include "core/Utility.hpp"
 
 static void finalize() {
     finalizeTests();
@@ -14,8 +14,8 @@ static void finalize() {
 }
 
 static void onExit(int code, void* data) {
-    unsigned int i = *(unsigned int*)(data);
-    LOG_WARNING("Hello from exit %d: %u", code, i);
+    unsigned int i = *static_cast<unsigned int*>(data);
+    LOG_WARNING("Hello from exit #: #", code, i);
     finalize();
 }
 
@@ -24,6 +24,8 @@ int main(int argAmount, const char** args) {
         puts("alloc");
         puts("realloc");
         puts("pre_canary");
+        puts("pre_canary_new");
+        puts("pre_canary_new_array");
         puts("post_canary");
         puts("test;ignore");
         puts("terminal");
@@ -41,47 +43,51 @@ int main(int argAmount, const char** args) {
             testInvalidReallocate();
         } else if(strcmp(args[i], "pre_canary") == 0) {
             testPreCanary();
+        } else if(strcmp(args[i], "pre_canary_new") == 0) {
+            testPreCanaryNew();
+        } else if(strcmp(args[i], "pre_canary_new_array") == 0) {
+            testPreCanaryNewArray();
         } else if(strcmp(args[i], "post_canary") == 0) {
             testPostCanary();
         } else if(strcmp(args[i], "test") == 0) {
             testTest();
             return 0;
         } else if(strcmp(args[i], "terminal") == 0) {
-            testTerminal(true);
+            // testTerminal(true);
             finalize();
             return 0;
         } else if(strcmp(args[i], "iterminal") == 0) {
-            testInteractiveTerminal();
+            // testInteractiveTerminal();
             return 0;
         }
     }
 
-    testBitArray();
-    testBox();
-    testBuffer(light);
-    testComponents();
+    // testBitArray();
+    // testBox();
+    // testBuffer(light);
+    // testComponents();
     testFile();
-    testFrustum();
-    testHashMap(light);
-    testList(light);
-    testMatrix();
-    testPlane();
-    testQuaternion();
-    testQueue();
-    testRandom(light);
+    // testFrustum();
+    // testHashMap(light);
+    // testList(light);
+    // testMatrix();
+    // testPlane();
+    // testQuaternion();
+    // testQueue();
+    // testRandom(light);
     if(light) {
-        testReadLine();
+        // testReadLine();
     }
-    testSpinLock();
-    testTerminal(!light);
-    testUnicode();
+    // testSpinLock();
+    // testTerminal(!light);
+    // testUnicode();
     testUtility(light);
-    testVector();
-    testView();
+    // testVector();
+    // testView();
 
-    logLevel = LOG_WARNING;
+    logLevel = LogLevel::WARNING;
     LOG_DEBUG("You won't see this!");
-    logLevel = LOG_DEBUG;
+    logLevel = LogLevel::DEBUG;
 
     unsigned int data = 123'456'789;
     setExitHandler(onExit, &data);

+ 5 - 3
test/Tests.h → test/Tests.hpp

@@ -1,7 +1,7 @@
 #ifndef CORE_TESTS_H
 #define CORE_TESTS_H
 
-#include "core/Test.h"
+#include "core/Test.hpp"
 
 [[noreturn]] void testInvalidAllocate(void);
 [[noreturn]] void testInvalidReallocate(void);
@@ -16,8 +16,10 @@ void testInteractiveTerminal(void);
 void testList(bool light);
 void testMatrix(void);
 void testPlane(void);
-void testPostCanary(void);
-void testPreCanary(void);
+[[noreturn]] void testPostCanary(void);
+[[noreturn]] void testPreCanary(void);
+[[noreturn]] void testPreCanaryNew(void);
+[[noreturn]] void testPreCanaryNewArray(void);
 void testQuaternion(void);
 void testQueue(void);
 void testRandom(bool light);

+ 0 - 0
test/modules/BitArrayTests.c → test/modules/BitArrayTests.cpp


+ 0 - 0
test/modules/BoxTests.c → test/modules/BoxTests.cpp


+ 0 - 0
test/modules/BufferTests.c → test/modules/BufferTests.cpp


+ 0 - 0
test/modules/ComponentsTests.c → test/modules/ComponentsTests.cpp


+ 10 - 10
test/modules/FileTests.c → test/modules/FileTests.cpp

@@ -1,9 +1,9 @@
-#include <string.h>
+#include <cstring>
 
-#include "../Tests.h"
-#include "../src/ErrorSimulator.h"
-#include "core/File.h"
-#include "core/Logger.h"
+#include "../Tests.hpp"
+#include "../src/ErrorSimulator.hpp"
+#include "core/File.hpp"
+#include "core/Logger.hpp"
 
 static int failIndex = 0;
 static const char* fails[] = {
@@ -16,18 +16,18 @@ static const char* fails[] = {
 
 static void printReport(
     LogLevel l, const char*, int, void*, const char* message) {
-    TEST_INT(LOG_ERROR, (int)l);
+    TEST(static_cast<int>(LogLevel::ERROR), static_cast<int>(l));
     if(!TEST_TRUE(strstr(message, fails[failIndex]) != nullptr)) {
-        LOG_ERROR("'%s' does not contain '%s'", message, fails[failIndex]);
+        LOG_ERROR("'#' does not contain '#'", message, fails[failIndex]);
     }
 }
 
 static void testExistingFile() {
-    FileContent f = {0};
+    FileContent f = {};
     if(!TEST_FALSE(readFile(&f, "testData/someFile"))) {
         return;
     }
-    TEST_SIZE(20, f.length);
+    TEST(20lu, f.length);
     TEST_STRING("Just\nSome\nTest File\n", f.data);
     destroyFileContent(&f);
 }
@@ -42,7 +42,7 @@ static void testFails(int steps) {
 #ifdef ERROR_SIMULATOR
     failStep = steps;
     failIndex = steps;
-    FileContent c = {0};
+    FileContent c = {};
     TEST_TRUE(readFile(&c, "testData/someFile"));
     failStep = -1;
 #endif

+ 0 - 0
test/modules/FrustumTests.c → test/modules/FrustumTests.cpp


+ 0 - 0
test/modules/HashMapTests.c → test/modules/HashMapTests.cpp


+ 0 - 0
test/modules/ListTests.c → test/modules/ListTests.cpp


+ 0 - 0
test/modules/MatrixTests.c → test/modules/MatrixTests.cpp


+ 0 - 0
test/modules/PlaneTests.c → test/modules/PlaneTests.cpp


+ 0 - 0
test/modules/QuaternionTests.c → test/modules/QuaternionTests.cpp


+ 0 - 0
test/modules/QueueTests.c → test/modules/QueueTests.cpp


+ 0 - 0
test/modules/RandomTests.c → test/modules/RandomTests.cpp


+ 0 - 0
test/modules/ReadLineTests.c → test/modules/ReadLineTests.cpp


+ 0 - 0
test/modules/SpinLockTests.c → test/modules/SpinLockTests.cpp


+ 0 - 0
test/modules/TerminalTests.c → test/modules/TerminalTests.cpp


+ 0 - 20
test/modules/TestTests.c

@@ -1,20 +0,0 @@
-#include "../Tests.h"
-#include "core/Vector.h"
-
-void testTest() {
-    TEST_BOOL(false, true);
-    TEST_INT(0, 1);
-    TEST_I32(0, 1);
-    TEST_I64(0, 1);
-    TEST_U64(0, 1);
-    TEST_SIZE(0, 1);
-    TEST_STRING("a", "b");
-    TEST_FALSE(true);
-    TEST_TRUE(false);
-    TEST_NULL(&(int){0});
-    TEST_NOT_NULL(nullptr);
-    TEST_FLOAT(0.0f, 1.0f, 0.1f);
-    TEST_V2(&V(0, 1), &V(2, 3));
-    TEST_IV2(&IV(0, 1), &IV(2, 3));
-    finalizeTests();
-}

+ 17 - 0
test/modules/TestTests.cpp

@@ -0,0 +1,17 @@
+#include "../Tests.hpp"
+
+void testTest() {
+    TEST(false, true);
+    TEST(0, 1);
+    TEST(0l, 1);
+    TEST(0lu, 1);
+    TEST(0llu, 1);
+    TEST_STRING("a", "b");
+    TEST_FALSE(true);
+    TEST_TRUE(false);
+    int i = 0;
+    TEST_NULL(&i);
+    TEST_NOT_NULL(nullptr);
+    TEST_FLOAT(0.0f, 1.0f, 0.1f);
+    finalizeTests();
+}

+ 0 - 0
test/modules/UnicodeTests.c → test/modules/UnicodeTests.cpp


+ 68 - 40
test/modules/UtilityTests.c → test/modules/UtilityTests.cpp

@@ -1,18 +1,21 @@
-#include "../../src/ErrorSimulator.h"
-#include "../Tests.h"
-#include "core/Utility.h"
+#include <cstring>
+
+#include "../../src/ErrorSimulator.hpp"
+#include "../Tests.hpp"
+#include "core/ToString.hpp"
+#include "core/Utility.hpp"
 
 static const float eps = 0.0001f;
 
 static void testPopCount() {
-    TEST_U64(4, popCount(0xF));
-    TEST_U64(0, popCount(0x0));
-    TEST_U64(2, popCount(0x6));
-    TEST_U64(7, popCount(0x7F));
-    TEST_U64(3, popCount(0x2A));
-    TEST_U64(32, popCount(0xFFFF'FFFF));
-    TEST_U64(64, popCount(0xFFFF'FFFF'FFFF'FFFF));
-    TEST_U64(44, popCount(0xFFFF'0FFF'FFFF));
+    TEST(4lu, popCount(0xF));
+    TEST(0lu, popCount(0x0));
+    TEST(2lu, popCount(0x6));
+    TEST(7lu, popCount(0x7F));
+    TEST(3lu, popCount(0x2A));
+    TEST(32lu, popCount(0xFFFF'FFFF));
+    TEST(64lu, popCount(0xFFFF'FFFF'FFFF'FFFF));
+    TEST(44lu, popCount(0xFFFF'0FFF'FFFF));
 }
 
 static void testZeroRellocate() {
@@ -89,48 +92,46 @@ typedef struct {
 static void testSwap() {
     SwapTest a = {3, 20};
     SwapTest b = {7, 30};
-    swap(&a, &b);
-    TEST_INT(7, a.i);
-    TEST_INT(3, b.i);
-    TEST_I64(30, a.d);
-    TEST_I64(20, b.d);
+    Core::swap(a, b);
+    TEST(7, a.i);
+    TEST(3, b.i);
+    TEST(30l, a.d);
+    TEST(20l, b.d);
 }
 
 static void testFail() {
 #ifdef ERROR_SIMULATOR
-    failTimeGet = true;
-    TEST_I64(-1, getNanos());
-    failTimeGet = false;
+    failStepThrow = 1;
+    TEST(-1l, getNanos());
+    failStepThrow = 1;
+    TEST_TRUE(sleepMillis(5));
+    failStepThrow = 0;
 #endif
 }
 
-BUBBLE_SORT(size_t, Size)
-#define greateThanSize(a, b) ((a) > (b))
-BUBBLE_SORT_SOURCE(size_t, Size, greateThanSize)
-
 static void testSort() {
     size_t data[] = {9, 0, 3, 1, 8, 4, 6, 2, 5, 7};
     size_t n = ARRAY_LENGTH(data);
-    bubbleSortSize(data, n);
-    bubbleSortSize(data, n);
-    bubbleSortSize(data, 0);
+    bubbleSort(data, n);
+    bubbleSort(data, n);
+    bubbleSort(data, 0);
     for(size_t i = 0; i < n; i++) {
-        TEST_SIZE(data[i], i);
+        TEST(data[i], i);
     }
 }
 
-#define TEST_MIN_MAX(Name, NAME, ...)                                \
-    TEST_##NAME(5, min##Name(5, 7) __VA_OPT__(, ) __VA_ARGS__);      \
-    TEST_##NAME(7, max##Name(5, 7) __VA_OPT__(, ) __VA_ARGS__);      \
-    TEST_##NAME(5, clamp##Name(3, 5, 7) __VA_OPT__(, ) __VA_ARGS__); \
-    TEST_##NAME(7, clamp##Name(9, 5, 7) __VA_OPT__(, ) __VA_ARGS__); \
-    TEST_##NAME(6, clamp##Name(6, 5, 7) __VA_OPT__(, ) __VA_ARGS__)
-
 static void testMinMax() {
-    TEST_MIN_MAX(Size, SIZE);
-    TEST_MIN_MAX(U32, U32);
-    TEST_MIN_MAX(I32, I32);
-    TEST_MIN_MAX(Float, FLOAT, 0.0f);
+    TEST(5, min<int>(5, 7));
+    TEST(7, max<int>(5, 7));
+    TEST(5, clamp<int>(3, 5, 7));
+    TEST(7, clamp<int>(9, 5, 7));
+    TEST(6, clamp<int>(6, 5, 7));
+}
+
+static void testToString() {
+    char buffer[512];
+    formatBuffer(buffer, sizeof(buffer), "aa##a", 1, 2, 3);
+    TEST_STRING("aa#a123", buffer);
 }
 
 void testUtility(bool light) {
@@ -149,6 +150,7 @@ void testUtility(bool light) {
     testFail();
     testSort();
     testMinMax();
+    testToString();
 }
 
 static void outOfMemory(void*) {
@@ -175,7 +177,7 @@ void testInvalidReallocate(void) {
 
 [[noreturn]] void testPreCanary(void) {
 #ifdef CHECK_MEMORY
-    char* p = coreAllocate(16);
+    char* p = static_cast<char*>(coreAllocate(16));
     p[-1] = 0;
     coreFree(p);
     TEST_TRUE(false);
@@ -184,9 +186,35 @@ void testInvalidReallocate(void) {
     EXIT(0);
 }
 
+[[noreturn]] void testPreCanaryNew(void) {
+#ifdef CHECK_MEMORY
+    volatile char* p2 = new char[3];
+    volatile char* p = coreNewN(char, 16);
+    delete[] p2;
+    coreDeleteN(p);
+    p = coreNewN(char, 16);
+    p[-1] = 0;
+    coreDeleteN(p);
+    TEST_TRUE(false);
+#endif
+    finalizeTests();
+    EXIT(0);
+}
+
+[[noreturn]] void testPreCanaryNewArray(void) {
+#ifdef CHECK_MEMORY
+    volatile char* p = coreNew(char);
+    p[-1] = 0;
+    coreDelete(p);
+    TEST_TRUE(false);
+#endif
+    finalizeTests();
+    EXIT(0);
+}
+
 [[noreturn]] void testPostCanary(void) {
 #ifdef CHECK_MEMORY
-    char* p = coreAllocate(16);
+    char* p = static_cast<char*>(coreAllocate(16));
     p[17] = 0;
     coreFree(p);
     TEST_TRUE(false);

+ 0 - 0
test/modules/VectorTests.c → test/modules/VectorTests.cpp


+ 0 - 0
test/modules/ViewTests.c → test/modules/ViewTests.cpp


+ 2 - 12
testData/ignoredCoverageFunctions

@@ -1,12 +1,2 @@
-QueueCL
-QueueDataCL
-testInt
-testI32
-testI64
-testU32
-testU64
-testSize
-testBool
-getListIndexSize
-removeListIndexBySwapSize
-removeListIndexSize
+printLog
+_ZdaPvm