Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ packages

.idea/
.cache/
cmake-build-debug-visual-studio/
cmake-build-debug-visual-studio/

# macOS AppleDouble metadata sidecar files (created on non-HFS volumes)
._*
.DS_Store
26 changes: 24 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,34 @@ target_compile_definitions(core-options INTERFACE
$<$<PLATFORM_ID:Darwin>:PLATFORM_MACOS=1>
)
target_compile_options(core-options INTERFACE
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>: -Werror -Wall -Wno-c++2b-extensions -Wno-enum-constexpr-conversion -Wno-c++11-narrowing -Wno-deprecated-declarations -Wno-invalid-offsetof>
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>: -Werror -Wall -Wno-c++2b-extensions -Wno-c++11-narrowing -Wno-deprecated-declarations -Wno-invalid-offsetof -Wno-missing-braces>
$<$<CXX_COMPILER_ID:GNU>: -Werror -Wall -Wextra -std=c++2b -Wno-invalid-offsetof -Wno-missing-field-initializers>
$<$<CXX_COMPILER_ID:MSVC>: -WX -W4 -Zc:preprocessor>
$<$<CXX_COMPILER_ID:MSVC>: -WX -W4 -Zc:preprocessor -wd4201>
)
target_include_directories(core-options INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/)

# SIMD arch gates — compile-time selection per target architecture.
# ARM64 (Apple Silicon, Linux/Windows ARM): NEON, always available on the ISA.
# x86_64 (Windows/Linux): AVX, Sandy Bridge (2011+) required. Anything beyond AVX
# (AVX2, AVX-512) is not guaranteed and stays out of scope.
#
# `CORE_SIMD_FORCE_SCALAR` overrides arch detection for parity testing — the
# arch flags are not emitted when it's on, so every math op falls through to its
# scalar branch.
option(CORE_SIMD_FORCE_SCALAR "Force scalar SIMD fallback for parity testing." OFF)
if(CORE_SIMD_FORCE_SCALAR)
target_compile_definitions(core-options INTERFACE SIMD_FORCE_SCALAR=1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)$")
target_compile_definitions(core-options INTERFACE SIMD_NEON=1)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|AMD64|x64)$")
target_compile_definitions(core-options INTERFACE SIMD_AVX=1)
if(MSVC)
target_compile_options(core-options INTERFACE /arch:AVX)
else()
target_compile_options(core-options INTERFACE -mavx)
endif()
endif()

add_subdirectory(core)
add_subdirectory(test)

Expand Down
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,20 @@

| Module | Description |
|---|---|
| `core/memory/` | Allocator interface, heap, arena, pool, and temp allocators |
| `core/defines.h` | Primitive aliases (`I8`..`I64`, `U8`..`U64`, `F32`, `F64`) and macro utilities |
| `core/memory/` | Allocator interface, heap, arena, pool, and temp allocators (with alignment) |
| `core/containers/array.h` | Dynamic array (`Array<T>`) |
| `core/containers/stack_array.h` | Fixed-capacity stack array (`Stack_Array<T, N>`) |
| `core/containers/span.h` | Non-owning view (`Span<T>`) |
| `core/containers/string.h` | Heap-allocated string (`String`) |
| `core/containers/hash_table.h` | Open-addressing hash table (`Hash_Table<K, V>`) |
| `core/containers/hash_set.h` | Hash set (`Hash_Set<K>`) |
| `core/containers/string_interner.h` | String deduplication (`String_Interner`) |
| `core/formatter.h` | Type-safe string formatting (`format()`) |
| `core/math/` | Vectors, matrices, quaternion, scalar helpers, random — NEON / AVX / scalar |
| `core/formatter.h` | Type-safe string formatting (`format()`) — math types format natively |
| `core/print.h` / `core/log.h` | Colored output and log levels |
| `core/defer.h` | Scope-exit macro (`DEFER`) |
| `core/tester.h` | Minimal unit-test framework (`TESTER_TEST`, `TESTER_CHECK`) |
| `core/validate.h` | Runtime assertions with source location |
| `core/result.h` | Error-returning pattern (`Error`, `Result<T>`) |
| `core/hash.h` | FNV-32 and type-generic `hash()` |
Expand All @@ -50,22 +53,25 @@

```cpp
#include <core/containers/array.h>
#include <core/math/f32x3.h>
#include <core/math/f32x4x4.h>
#include <core/defer.h>
#include <core/log.h>

struct Vertex
{
float x, y, z;
float nx, ny, nz;
F32x3 position;
F32x3 normal;
};

auto vertices = array_init<Vertex>();
DEFER(array_deinit(vertices));

array_push(vertices, Vertex{1.0f, 2.0f, 3.0f, 0.0f, 0.0f, 1.0f});
array_push(vertices, Vertex{4.0f, 5.0f, 6.0f, 0.0f, 1.0f, 0.0f});
array_push(vertices, Vertex{F32x3{1.0f, 2.0f, 3.0f}, F32X3_UP});
array_push(vertices, Vertex{F32x3{4.0f, 5.0f, 6.0f}, F32X3_FORWARD});

log_info("loaded {} vertices", vertices.count);
F32x4x4 view = f32x4x4_look_at(F32x3{0, 0, 5}, F32X3_ZERO, F32X3_UP);
log_info("loaded {} vertices, view matrix:\n{}", vertices.count, view);
```

---
Expand Down
26 changes: 26 additions & 0 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,32 @@ set(HEADER_FILES
containers/stack_array.h
containers/string_interner.h
containers/string.h
math/f32.h
math/f64.h
math/i32.h
math/i64.h
math/u32.h
math/u64.h
math/f32x2.h
math/f32x3.h
math/f32x4.h
math/f64x2.h
math/f64x3.h
math/f64x4.h
math/i32x2.h
math/i32x3.h
math/i32x4.h
math/u32x2.h
math/u32x3.h
math/u32x4.h
math/f32x2x2.h
math/f32x3x3.h
math/f32x4x4.h
math/f64x2x2.h
math/f64x3x3.h
math/f64x4x4.h
math/quaternion.h
math/random.h
memory/memory.h
memory/heap_allocator.h
memory/arena_allocator.h
Expand Down
36 changes: 18 additions & 18 deletions core/base64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@
inline static constexpr const char *BASE64_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

String
base64_encode(const u8 *data, u64 size, memory::Allocator *allocator)
base64_encode(const U8 *data, U64 size, memory::Allocator *allocator)
{
String out = string_init(allocator);

for (u64 i = 0; i < size; i += 3)
for (U64 i = 0; i < size; i += 3)
{
i32 value = (data[i] << 16) + (data[i + 1] << 8) + (data[i + 2]);
I32 value = (data[i] << 16) + (data[i + 1] << 8) + (data[i + 2]);

for (u64 j = 0; j < 4; ++j)
for (U64 j = 0; j < 4; ++j)
{
i32 x = (value >> ((3 - j) * 6)) & 0x3F;
I32 x = (value >> ((3 - j) * 6)) & 0x3F;
string_append(out, BASE64_CHARACTERS[x]);
}
}

i32 padding = size % 3;
I32 padding = size % 3;
if (padding > 0)
{
for (i32 i = 0; i < (3 - padding); ++i)
for (I32 i = 0; i < (3 - padding); ++i)
{
out[out.count - i - 1] = '=';
}
Expand All @@ -33,8 +33,8 @@ base64_encode(const u8 *data, u64 size, memory::Allocator *allocator)
String
base64_decode(const String &data, memory::Allocator *allocator)
{
constexpr auto index = [](const String &data, char c) -> u8 {
for (u8 i = 0; i < data.count; ++i)
constexpr auto index = [](const String &data, char c) -> U8 {
for (U8 i = 0; i < data.count; ++i)
{
if (data[i] == c)
{
Expand All @@ -47,26 +47,26 @@ base64_decode(const String &data, memory::Allocator *allocator)

String out = string_init(allocator);

for (u64 i = 0; i < data.count; i += 4)
for (U64 i = 0; i < data.count; i += 4)
{
i32 a = index(string_literal(BASE64_CHARACTERS), data[i + 0]);
i32 b = index(string_literal(BASE64_CHARACTERS), data[i + 1]);
i32 c = index(string_literal(BASE64_CHARACTERS), data[i + 2]);
i32 d = index(string_literal(BASE64_CHARACTERS), data[i + 3]);
I32 a = index(string_literal(BASE64_CHARACTERS), data[i + 0]);
I32 b = index(string_literal(BASE64_CHARACTERS), data[i + 1]);
I32 c = index(string_literal(BASE64_CHARACTERS), data[i + 2]);
I32 d = index(string_literal(BASE64_CHARACTERS), data[i + 3]);

u32 value = (a << 18) |
U32 value = (a << 18) |
(b << 12) |
(c << 6) |
(d);

for (u64 j = 0; j < 3; ++j)
for (U64 j = 0; j < 3; ++j)
{
char byte = (value >> ((2 - j) * 8)) & 0xFF;
string_append(out, byte);
}
}

u64 padding = 0;
U64 padding = 0;
for (char c : data)
{
if (c == '=')
Expand All @@ -75,7 +75,7 @@ base64_decode(const String &data, memory::Allocator *allocator)
}
}

for (u64 i = 0; i < padding; ++i)
for (U64 i = 0; i < padding; ++i)
{
string_remove_last(out);
}
Expand Down
10 changes: 5 additions & 5 deletions core/base64.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,29 @@

/*
TODO:
- [ ] Should decode return a String or an Array<u8>?
- [ ] Should decode return a String or an Array<U8>?
- [ ] Should use Result<T>?
*/

CORE_API String
base64_encode(const u8 *data, u64 size, memory::Allocator *allocator = memory::heap_allocator());
base64_encode(const U8 *data, U64 size, memory::Allocator *allocator = memory::heap_allocator());

inline static String
base64_encode(const Block &data, memory::Allocator *allocator = memory::heap_allocator())
{
return base64_encode((const u8 *)data.data, data.size, allocator);
return base64_encode((const U8 *)data.data, data.size, allocator);
}

inline static String
base64_encode(const Array<u8> &data, memory::Allocator *allocator = memory::heap_allocator())
base64_encode(const Array<U8> &data, memory::Allocator *allocator = memory::heap_allocator())
{
return base64_encode(data.data, data.count, allocator);
}

inline static String
base64_encode(const String &data, memory::Allocator *allocator = memory::heap_allocator())
{
return base64_encode((const u8 *)data.data, data.count, allocator);
return base64_encode((const U8 *)data.data, data.count, allocator);
}

inline static String
Expand Down
Loading
Loading