diff --git a/build_file.c b/build_file.c index 337f265..4ea8a5c 100644 --- a/build_file.c +++ b/build_file.c @@ -1,7 +1,7 @@ // don't ever include stuff that build_file will generate code for! #define DONT_INCLUDE_GENERATED_MATH -#include "src/core/core_inc.h" -#include "src/core/core_inc.c" +#include "src/core/core.h" +#include "src/core/core.c" #define BUILD_TOOL_LIB #define S8_String s8_t @@ -15,6 +15,7 @@ #include "src/ui/ui.meta.c" #include "src/render/render.meta.c" #include "src/wasm_app/wasm_app.meta.c" +#include "src/testing/testing.meta.c" int main(int argc, char **argv) { core_init(); @@ -34,10 +35,11 @@ int main(int argc, char **argv) { mt_app(tcx->temp); mt_wasm_app(tcx->temp); mt_render(tcx->temp); + mt_testing(tcx->temp); b32 run_server = false; b32 core_test_target = true; - b32 win32_target = true; + b32 win32_target = false; b32 standalone_w32_target = false; b32 wasm_target = false; @@ -77,10 +79,10 @@ int main(int argc, char **argv) { ); } - if (core_test_target && cache_code_modified(s8_lit("../src/core/core_test_entry.c"), s8_lit("core_test.exe"))) { - os_delete_file(s8_lit("core_test.pdb")); + if (core_test_target && cache_code_modified(s8_lit("../src/testing/testing_main.c"), s8_lit("testing.exe"))) { + os_delete_file(s8_lit("testing.pdb")); ok = os_systemf( - "cl ../src/core/core_test_entry.c -Fe:core_test.exe -Fd:core_test.pdb" + "cl ../src/testing/testing_main.c -Fe:testing.exe -Fd:testing.pdb" " -I ../src" " /Zi /FC /nologo /Oi" " /WX /W3 /wd4200 /diagnostics:column" @@ -88,7 +90,7 @@ int main(int argc, char **argv) { ); if (ok != 0) return ok; - ok = os_systemf("core_test.exe"); + ok = os_systemf("testing.exe"); if (ok != 0) return ok; } diff --git a/src/app/app_win32.c b/src/app/app_win32.c index 706c30f..f484848 100644 --- a/src/app/app_win32.c +++ b/src/app/app_win32.c @@ -281,36 +281,6 @@ struct w32_library_t { app_update_t *update_fn; }; -fn b32 os_copy(s8_t from, s8_t to, b32 overwrite) { - ma_temp_t scratch = ma_begin_scratch(); - s16_t from16 = s16_from_s8(scratch.arena, from); - s16_t to16 = s16_from_s8(scratch.arena, to); - - BOOL fail_if_exists = !overwrite; - BOOL success = CopyFileW(from16.str, to16.str, fail_if_exists); - b32 result = success ? true : false; - ma_end_scratch(scratch); - return result; -} - -fn i64 os_get_file_mod_time(s8_t file) { - FILETIME time = {0}; - WIN32_FIND_DATAW data; - - ma_temp_t scratch = ma_begin_scratch(); - s16_t wpath = s16_from_s8(scratch.arena, file); - HANDLE handle = FindFirstFileW(wpath.str, &data); - if (handle != INVALID_HANDLE_VALUE) { - FindClose(handle); - time = data.ftLastWriteTime; - } else { - return -1; - } - i64 result = (i64)time.dwHighDateTime << 32 | time.dwLowDateTime; - ma_end_scratch(scratch); - return result; -} - fn void w32_set_event(app_frame_t *frame, app_event_t ev) { frame->first_event = frame->last_event = NULL; frame->event_count = 0; @@ -370,137 +340,6 @@ fn void w32_try_reloading_library(w32_library_t *lib, app_frame_t frame) { end_of_lib_load:; } -/////////////////////////////// -// file ops -fn s8_t os_abs(ma_arena_t *arena, s8_t rel) { - const int buffer_size = 2048; - ma_temp_t scratch = ma_begin_scratch1(arena); - s16_t rel16 = s16_from_s8(scratch.arena, rel); - wchar_t *buffer = ma_push_array(scratch.arena, wchar_t, buffer_size); - DWORD written = GetFullPathNameW(rel16.str, buffer_size, buffer, 0); - assert(written != 0); - assert((i64)written < (i64)buffer_size); - s8_t result = s8_from_s16(arena, s16(buffer, written)); - ma_end_scratch(scratch); - return result; -} - -fn s8_t os_exe(ma_arena_t *arena) { - const int buffer_size = 2048; - ma_temp_t scratch = ma_begin_scratch1(arena); - wchar_t *buffer = ma_push_array(scratch.arena, wchar_t, buffer_size); - DWORD wsize = GetModuleFileNameW(0, buffer, buffer_size); - assert(wsize != 0); - s8_t result = s8_from_s16(arena, s16(buffer, wsize)); - s8_normalize_path_unsafe(result); - ma_end_scratch(scratch); - return result; -} - -fn s8_t os_exe_dir(ma_arena_t *arena) { - ma_temp_t scratch = ma_begin_scratch1(arena); - s8_t exe = os_exe(scratch.arena); - s8_t path = s8_chop_last_slash(exe); - s8_t result = s8_copy(arena, path); - ma_end_scratch(scratch); - return result; -} - -fn b32 os_delete(s8_t path) { - ma_temp_t scratch = ma_begin_scratch(); - s16_t path16 = s16_from_s8(scratch.arena, path); - BOOL success = DeleteFileW(path16.str); - b32 result = true; - if (success == 0) { - result = false; // path not found - } - ma_end_scratch(scratch); - return result; -} - -/////////////////////////////// -// file iter -typedef struct w32_file_iter_t w32_file_iter_t; -struct w32_file_iter_t { - HANDLE handle; - WIN32_FIND_DATAW data; -}; - -typedef struct os_file_iter_t os_file_iter_t; -struct os_file_iter_t { - s8_t abs; - s8_t rel; - s8_t name; - b8 is_directory; - b8 is_valid; - - s8_t path; - ma_arena_t *arena; - - union { - w32_file_iter_t *w32; - void *platform; - }; -}; - -fn void os_advance(os_file_iter_t *it) { - while (FindNextFileW(it->w32->handle, &it->w32->data) != 0) { - WIN32_FIND_DATAW *data = &it->w32->data; - - // Skip '.' and '..' - if (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0) continue; - if (data->cFileName[0] == '.' && data->cFileName[1] == 0) continue; - - it->is_directory = data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; - it->name = s8_from_s16(it->arena, s16(data->cFileName, wstr_len(data->cFileName))); - - const char *is_dir = it->is_directory ? "/" : ""; - const char *separator = it->path.str[it->path.len - 1] == '/' ? "" : "/"; - - it->rel = s8_printf(it->arena, "%S%s%S%s", it->path, separator, it->name, is_dir); - it->abs = os_abs(it->arena, it->rel); - it->is_valid = true; - - if (it->is_directory) { - assert(it->rel.str[it->rel.len - 1] == '/'); - assert(it->abs.str[it->abs.len - 1] == '/'); - } - - return; - } - - it->is_valid = false; - DWORD error = GetLastError(); - assert(error == ERROR_NO_MORE_FILES); - FindClose(it->w32->handle); -} - -fn os_file_iter_t *os_iterate_files(ma_arena_t *arena, s8_t path) { - os_file_iter_t *it = ma_push_type(arena, os_file_iter_t); - it->w32 = ma_push_type(arena, w32_file_iter_t); - it->arena = arena; - it->path = path; - it->is_valid = true; - - ma_temp_t scratch = ma_begin_scratch1(arena); - s8_t mod_path = s8_printf(scratch.arena, "%S\\*", path); - s16_t mod_path16 = s16_from_s8(scratch.arena, mod_path); - - it->w32->handle = FindFirstFileW(mod_path16.str, &it->w32->data); - if (it->w32->handle == INVALID_HANDLE_VALUE) { - it->is_valid = false; - } - - if (it->is_valid) { - assert(it->w32->data.cFileName[0] == '.' && it->w32->data.cFileName[1] == 0); - os_advance(it); - } - - ma_end_scratch(scratch); - return it; -} - - int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { core_init(); diff --git a/src/app/app_win32_exe.c b/src/app/app_win32_exe.c index ab78be0..1381080 100644 --- a/src/app/app_win32_exe.c +++ b/src/app/app_win32_exe.c @@ -1,7 +1,7 @@ #define APP_HOT_RELOAD -#include "core/core_inc.h" +#include "core/core.h" #include "app/app.h" -#include "core/core_inc.c" +#include "core/core.c" #include "app/app.c" diff --git a/src/core/core_inc.c b/src/core/core.c similarity index 100% rename from src/core/core_inc.c rename to src/core/core.c diff --git a/src/core/core.h b/src/core/core.h index 5ea8cdd..336026d 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -1,297 +1,16 @@ -typedef uintptr_t usize; -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint16_t u16; -typedef uint8_t u8; - -typedef intptr_t isize; -typedef int64_t i64; -typedef int32_t i32; -typedef int16_t i16; -typedef int8_t i8; - -typedef int64_t b64; -typedef int32_t b32; -typedef int16_t b16; -typedef int8_t b8; - -typedef float f32; -typedef double f64; - -#define f32_max FLT_MAX -#define f32_min FLT_MIN -#define f64_max DBL_MAX -#define f64_min DBL_MIN - -#define i8_max INT8_MAX -#define i8_min INT8_MIN -#define i16_max INT16_MAX -#define i16_min INT16_MIN -#define i32_max INT32_MAX -#define i32_min INT32_MIN -#define i64_max INT64_MAX -#define i64_min INT64_MIN - -#define u8_max UINT8_MAX -#define u8_min 0 -#define u16_max UINT16_MAX -#define u16_min 0 -#define u32_max UINT32_MAX -#define u32_min 0 -#define u64_max UINT64_MAX -#define u64_min 0 - - -#ifndef true -#define true 1 -#endif -#ifndef false -#define false 0 -#endif - -#define fn -#define fn_test -#define gb -#define locl static - -typedef union convert_f64_u64_t convert_f64_u64_t; -union convert_f64_u64_t { f64 f; u64 i; }; -typedef union convert_f64_i64_t convert_f64_i64_t; -union convert_f64_i64_t { f64 f; i64 i; }; -typedef union convert_f32_u32_t convert_f32_u32_t; -union convert_f32_u32_t { f32 f; u32 i; }; -typedef union convert_f32_i32_t convert_f32_i32_t; -union convert_f32_i32_t { f32 f; i32 i; }; - - -#define U64_TO_F64(x) (((convert_f64_u64_t) { .i = (x) }).f) -#define U32_TO_F32(x) (((convert_f32_u32_t) { .i = (x) }).f) -#define F64_TO_U64(x) (((convert_f64_u64_t) { .f = (x) }).i) -#define F32_TO_U32(x) (((convert_f32_u32_t) { .f = (x) }).i) - -#define I64_TO_F64(x) (((convert_f64_i64_t) { .i = (x) }).f) -#define I32_TO_F32(x) (((convert_f32_i32_t) { .i = (x) }).f) -#define F64_TO_I64(x) (((convert_f64_i64_t) { .f = (x) }).i) -#define F32_TO_I32(x) (((convert_f32_i32_t) { .f = (x) }).i) - -#define MIN(x,y) ((x) > (y) ? (y) : (x)) -#define MAX(x,y) ((x) > (y) ? (x) : (y)) - -#define CLAMP_TOP(A,X) MIN(A,X) -#define CLAMP_BOT(X,B) MAX(X,B) -#define CLAMP(x,a,b) (((x)<(a))?(a):((x)>(b))?(b):(x)) - -#define set_bit(x) (1ULL << (x)) -#define lengthof(x) (sizeof((x))/sizeof((x)[0])) -#ifndef offsetof -#define offsetof(st, m) ((usize)&(((st *)0)->m)) -#endif -#define expect(x) if (!(x)) -#define unused(x) (void)(x) - -#define kib(x) (1024ULL * (x##ULL)) -#define mib(x) (1024ULL * kib(x)) -#define gib(x) (1024ULL * mib(x)) -#define thousand(n) ((n)*1000) -#define million(n) ((n)*1000000) -#define billion(n) ((n)*1000000000) - -#define zero_struct(x) memory_zero((x), sizeof(*(x))) - - -#define defer_if(begin, cond_end) for (b32 PASTE(_i_, __LINE__) = !!begin; PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) = (cond_end, 0)) -#define defer_block(begin, end) for (i32 PASTE(_i_, __LINE__) = (begin, 0); !PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) += (end, 1)) - -#define stack_t(type, size) struct { type data[size]; i32 len; } -#define STACK_CAP(stack) (lengthof((stack).data)) -#define STACK_EMPTY(stack) ((stack).len == 0) -#define STACK_FULL(stack) ((stack).len == STACK_CAP(stack)) -#define STACK_PUSH(stack, ...) (assert(!STACK_FULL(stack)), (stack).data[(stack).len++] = __VA_ARGS__) -#define STACK_POP(stack) (assert(!STACK_EMPTY(stack)), (stack).data[--(stack).len]) -#define STACK_TOP(stack) (assert(!STACK_EMPTY(stack)), (stack).data[((stack).len-1)]) - -#define STRINGIFY_(S) #S -#define STRINGIFY(S) STRINGIFY_(S) -#define PASTE_(a, b) a##b -#define PASTE(a, b) PASTE_(a, b) -#define SWAP(t, a, b) do { t PASTE(temp__, __LINE__) = a; a = b; b = PASTE(temp__, __LINE__); } while(0) -#define CODE(...) #__VA_ARGS__ - -#if PLATFORM_CL || (PLATFORM_CLANG && PLATFORM_WINDOWS) - #pragma section(".rdata$", read) - #define gb_read_only __declspec(allocate(".rdata$")) -#elif PLATFORM_CLANG && PLATFORM_LINUX - #define gb_read_only __attribute__((section(".rodata"))) -#else - #define gb_read_only -#endif - -#if PLATFORM_CL - #define fn_inline __forceinline -#elif PLATFORM_CLANG || PLATFORM_GCC - #define fn_inline __attribute__((always_inline)) -#else - #define fn_inline -#endif - -#ifndef FILE_AND_LINE_GCC_FORMAT -#define FILE_AND_LINE __FILE__"("STRINGIFY(__LINE__)")" -#else -#define FILE_AND_LINE __FILE__":"STRINGIFY(__LINE__) -#endif - -#if PLATFORM_CL - #define debug__break() __debugbreak() -#else - #define debug__break() __builtin_trap() -#endif -#define debug_break() (debug__break(), 0) - -#if PLATFORM_WASM - #define gb_thread -#elif PLATFORM_GCC | PLATFORM_CLANG - #define gb_thread __thread -#elif PLATFORM_CL - #define gb_thread __declspec(thread) -#else - #define gb_thread _Thread_local -#endif - -#if PLATFORM_CL - #pragma warning(disable: 4116) -#endif - -// Single linked list Queue -#define SLLQ_APPEND_EX(f, l, n, next) \ - do { \ - assert((n)->next == NULL); \ - if ((f) == 0) { \ - (f) = (l) = (n); \ - } else { \ - (l) = (l)->next = (n); \ - } \ - } while (0) -#define SLLQ_APPEND(f, l, n) SLLQ_APPEND_EX(f, l, n, next) - -#define SLLQ_PREPEND_EX(f, l, n, next) \ - do { \ - assert((n)->next == NULL); \ - if ((f) == 0) { \ - (f) = (l) = (n); \ - } else { \ - (n)->next = (f); \ - (f) = (n); \ - } \ - } while (0) -#define SLLQ_PREPEND(f, l, n) SLLQ_PREPEND_EX(f, l, n, next) - -#define SLLQ_REMOVE_FIRST_EX(f, l, next) \ - do { \ - if ((f) == (l)) { \ - (f) = (l) = 0; \ - } else { \ - (f) = (f)->next; \ - } \ - } while (0) -#define SLLQ_REMOVE_FIRST(f, l) SLLQ_REMOVE_FIRST_EX(f, l, next) - -// Singly linked list stack -#define SLLS_PUSH_EX(stack_base, new_stack_base, next) \ - do { \ - (new_stack_base)->next = (stack_base); \ - (stack_base) = (new_stack_base); \ - } while (0) -#define SLLS_PUSH(stack_base, new_stack_base) \ - SLLS_PUSH_EX(stack_base, new_stack_base, next) - -#define SLLS_POP(stack_base) ((stack_base) = (stack_base)->next) -#define SLLS_POP_AND_STORE(stack_base, out_node) \ - do { \ - if (stack_base) { \ - (out_node) = (stack_base); \ - (stack_base) = (stack_base)->next; \ - (out_node)->next = 0; \ - } \ - } while (0) - -// Doubly linked list Queue -#define DLLQ_APPEND_EX(f, l, node, next, prev) \ - do { \ - assert((node)->next == NULL); \ - assert((node)->prev == NULL); \ - if ((f) == 0) { \ - (f) = (l) = (node); \ - } else { \ - (l)->next = (node); \ - (node)->prev = (l); \ - (l) = (node); \ - } \ - } while (0) -#define DLLQ_APPEND(f, l, node) DLLQ_APPEND_EX(f, l, node, next, prev) - -#define DLLQ_PREPEND_EX(f, l, node, next, prev) \ - do { \ - assert((node)->next == NULL); \ - assert((node)->prev == NULL); \ - if ((f) == 0) { \ - (f) = (l) = (node); \ - } else { \ - (node)->next = (f); \ - (f)->prev = (node); \ - (f) = (node); \ - } \ - } while (0) -#define DLLQ_PREPEND(f, l, node) DLLQ_PREPEND_EX(f, l, node, next, prev) - -#define DLLQ_CONTAINS(f, l, n, next, prev) for ( - -#define DLLQ_REMOVE_EX(first, last, node, next, prev) \ - do { \ - if ((first) == (last)) { \ - assert((node) == (first)); \ - (first) = (last) = 0; \ - } else if ((last) == (node)) { \ - (last) = (last)->prev; \ - (last)->next = 0; \ - } else if ((first) == (node)) { \ - (first) = (first)->next; \ - (first)->prev = 0; \ - } else { \ - (node)->prev->next = (node)->next; \ - (node)->next->prev = (node)->prev; \ - } \ - if (node) { \ - (node)->prev = 0; \ - (node)->next = 0; \ - } \ - } while (0) -#define DLLQ_REMOVE(first, last, node) DLLQ_REMOVE_EX(first, last, node, next, prev) - -// Doubly linked list Stack -#define DLLS_PUSH_EX(first, node, next, prev) \ - do { \ - assert((node)->next == NULL); \ - assert((node)->prev == NULL); \ - (node)->next = (first); \ - if ((first)) \ - (first)->prev = (node); \ - (first) = (node); \ - } while (0) -#define DLLS_PUSH(first, node) DLLS_PUSH_EX(first, node, next, prev) -#define DLLS_REMOVE_EX(first, node, next, prev) \ - do { \ - if ((node) == (first)) { \ - (first) = (first)->next; \ - if ((first)) \ - (first)->prev = 0; \ - } else { \ - (node)->prev->next = (node)->next; \ - if ((node)->next) \ - (node)->next->prev = (node)->prev; \ - } \ - if (node) { \ - (node)->prev = 0; \ - (node)->next = 0; \ - } \ - } while (0) -#define DLLS_REMOVE(first, node) DLLS_REMOVE_EX(first, node, next, prev) +#include "core_platform_defines.h" +#include +#include +#include +#include "core_basic.h" +#include "core_unicode.h" +#include "core_arena.h" +#include "core_string.h" +#include "core_math.h" +#include "core_type_info.h" +#include "core_lexer.h" +#include "core_log.h" +#include "core_intrin.h" +#include "core_platform.h" +#include "core_hash_table.h" +#include "core_ctx.h" \ No newline at end of file diff --git a/src/core/core_basic.h b/src/core/core_basic.h new file mode 100644 index 0000000..5ea8cdd --- /dev/null +++ b/src/core/core_basic.h @@ -0,0 +1,297 @@ +typedef uintptr_t usize; +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; + +typedef intptr_t isize; +typedef int64_t i64; +typedef int32_t i32; +typedef int16_t i16; +typedef int8_t i8; + +typedef int64_t b64; +typedef int32_t b32; +typedef int16_t b16; +typedef int8_t b8; + +typedef float f32; +typedef double f64; + +#define f32_max FLT_MAX +#define f32_min FLT_MIN +#define f64_max DBL_MAX +#define f64_min DBL_MIN + +#define i8_max INT8_MAX +#define i8_min INT8_MIN +#define i16_max INT16_MAX +#define i16_min INT16_MIN +#define i32_max INT32_MAX +#define i32_min INT32_MIN +#define i64_max INT64_MAX +#define i64_min INT64_MIN + +#define u8_max UINT8_MAX +#define u8_min 0 +#define u16_max UINT16_MAX +#define u16_min 0 +#define u32_max UINT32_MAX +#define u32_min 0 +#define u64_max UINT64_MAX +#define u64_min 0 + + +#ifndef true +#define true 1 +#endif +#ifndef false +#define false 0 +#endif + +#define fn +#define fn_test +#define gb +#define locl static + +typedef union convert_f64_u64_t convert_f64_u64_t; +union convert_f64_u64_t { f64 f; u64 i; }; +typedef union convert_f64_i64_t convert_f64_i64_t; +union convert_f64_i64_t { f64 f; i64 i; }; +typedef union convert_f32_u32_t convert_f32_u32_t; +union convert_f32_u32_t { f32 f; u32 i; }; +typedef union convert_f32_i32_t convert_f32_i32_t; +union convert_f32_i32_t { f32 f; i32 i; }; + + +#define U64_TO_F64(x) (((convert_f64_u64_t) { .i = (x) }).f) +#define U32_TO_F32(x) (((convert_f32_u32_t) { .i = (x) }).f) +#define F64_TO_U64(x) (((convert_f64_u64_t) { .f = (x) }).i) +#define F32_TO_U32(x) (((convert_f32_u32_t) { .f = (x) }).i) + +#define I64_TO_F64(x) (((convert_f64_i64_t) { .i = (x) }).f) +#define I32_TO_F32(x) (((convert_f32_i32_t) { .i = (x) }).f) +#define F64_TO_I64(x) (((convert_f64_i64_t) { .f = (x) }).i) +#define F32_TO_I32(x) (((convert_f32_i32_t) { .f = (x) }).i) + +#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#define MAX(x,y) ((x) > (y) ? (x) : (y)) + +#define CLAMP_TOP(A,X) MIN(A,X) +#define CLAMP_BOT(X,B) MAX(X,B) +#define CLAMP(x,a,b) (((x)<(a))?(a):((x)>(b))?(b):(x)) + +#define set_bit(x) (1ULL << (x)) +#define lengthof(x) (sizeof((x))/sizeof((x)[0])) +#ifndef offsetof +#define offsetof(st, m) ((usize)&(((st *)0)->m)) +#endif +#define expect(x) if (!(x)) +#define unused(x) (void)(x) + +#define kib(x) (1024ULL * (x##ULL)) +#define mib(x) (1024ULL * kib(x)) +#define gib(x) (1024ULL * mib(x)) +#define thousand(n) ((n)*1000) +#define million(n) ((n)*1000000) +#define billion(n) ((n)*1000000000) + +#define zero_struct(x) memory_zero((x), sizeof(*(x))) + + +#define defer_if(begin, cond_end) for (b32 PASTE(_i_, __LINE__) = !!begin; PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) = (cond_end, 0)) +#define defer_block(begin, end) for (i32 PASTE(_i_, __LINE__) = (begin, 0); !PASTE(_i_, __LINE__); PASTE(_i_, __LINE__) += (end, 1)) + +#define stack_t(type, size) struct { type data[size]; i32 len; } +#define STACK_CAP(stack) (lengthof((stack).data)) +#define STACK_EMPTY(stack) ((stack).len == 0) +#define STACK_FULL(stack) ((stack).len == STACK_CAP(stack)) +#define STACK_PUSH(stack, ...) (assert(!STACK_FULL(stack)), (stack).data[(stack).len++] = __VA_ARGS__) +#define STACK_POP(stack) (assert(!STACK_EMPTY(stack)), (stack).data[--(stack).len]) +#define STACK_TOP(stack) (assert(!STACK_EMPTY(stack)), (stack).data[((stack).len-1)]) + +#define STRINGIFY_(S) #S +#define STRINGIFY(S) STRINGIFY_(S) +#define PASTE_(a, b) a##b +#define PASTE(a, b) PASTE_(a, b) +#define SWAP(t, a, b) do { t PASTE(temp__, __LINE__) = a; a = b; b = PASTE(temp__, __LINE__); } while(0) +#define CODE(...) #__VA_ARGS__ + +#if PLATFORM_CL || (PLATFORM_CLANG && PLATFORM_WINDOWS) + #pragma section(".rdata$", read) + #define gb_read_only __declspec(allocate(".rdata$")) +#elif PLATFORM_CLANG && PLATFORM_LINUX + #define gb_read_only __attribute__((section(".rodata"))) +#else + #define gb_read_only +#endif + +#if PLATFORM_CL + #define fn_inline __forceinline +#elif PLATFORM_CLANG || PLATFORM_GCC + #define fn_inline __attribute__((always_inline)) +#else + #define fn_inline +#endif + +#ifndef FILE_AND_LINE_GCC_FORMAT +#define FILE_AND_LINE __FILE__"("STRINGIFY(__LINE__)")" +#else +#define FILE_AND_LINE __FILE__":"STRINGIFY(__LINE__) +#endif + +#if PLATFORM_CL + #define debug__break() __debugbreak() +#else + #define debug__break() __builtin_trap() +#endif +#define debug_break() (debug__break(), 0) + +#if PLATFORM_WASM + #define gb_thread +#elif PLATFORM_GCC | PLATFORM_CLANG + #define gb_thread __thread +#elif PLATFORM_CL + #define gb_thread __declspec(thread) +#else + #define gb_thread _Thread_local +#endif + +#if PLATFORM_CL + #pragma warning(disable: 4116) +#endif + +// Single linked list Queue +#define SLLQ_APPEND_EX(f, l, n, next) \ + do { \ + assert((n)->next == NULL); \ + if ((f) == 0) { \ + (f) = (l) = (n); \ + } else { \ + (l) = (l)->next = (n); \ + } \ + } while (0) +#define SLLQ_APPEND(f, l, n) SLLQ_APPEND_EX(f, l, n, next) + +#define SLLQ_PREPEND_EX(f, l, n, next) \ + do { \ + assert((n)->next == NULL); \ + if ((f) == 0) { \ + (f) = (l) = (n); \ + } else { \ + (n)->next = (f); \ + (f) = (n); \ + } \ + } while (0) +#define SLLQ_PREPEND(f, l, n) SLLQ_PREPEND_EX(f, l, n, next) + +#define SLLQ_REMOVE_FIRST_EX(f, l, next) \ + do { \ + if ((f) == (l)) { \ + (f) = (l) = 0; \ + } else { \ + (f) = (f)->next; \ + } \ + } while (0) +#define SLLQ_REMOVE_FIRST(f, l) SLLQ_REMOVE_FIRST_EX(f, l, next) + +// Singly linked list stack +#define SLLS_PUSH_EX(stack_base, new_stack_base, next) \ + do { \ + (new_stack_base)->next = (stack_base); \ + (stack_base) = (new_stack_base); \ + } while (0) +#define SLLS_PUSH(stack_base, new_stack_base) \ + SLLS_PUSH_EX(stack_base, new_stack_base, next) + +#define SLLS_POP(stack_base) ((stack_base) = (stack_base)->next) +#define SLLS_POP_AND_STORE(stack_base, out_node) \ + do { \ + if (stack_base) { \ + (out_node) = (stack_base); \ + (stack_base) = (stack_base)->next; \ + (out_node)->next = 0; \ + } \ + } while (0) + +// Doubly linked list Queue +#define DLLQ_APPEND_EX(f, l, node, next, prev) \ + do { \ + assert((node)->next == NULL); \ + assert((node)->prev == NULL); \ + if ((f) == 0) { \ + (f) = (l) = (node); \ + } else { \ + (l)->next = (node); \ + (node)->prev = (l); \ + (l) = (node); \ + } \ + } while (0) +#define DLLQ_APPEND(f, l, node) DLLQ_APPEND_EX(f, l, node, next, prev) + +#define DLLQ_PREPEND_EX(f, l, node, next, prev) \ + do { \ + assert((node)->next == NULL); \ + assert((node)->prev == NULL); \ + if ((f) == 0) { \ + (f) = (l) = (node); \ + } else { \ + (node)->next = (f); \ + (f)->prev = (node); \ + (f) = (node); \ + } \ + } while (0) +#define DLLQ_PREPEND(f, l, node) DLLQ_PREPEND_EX(f, l, node, next, prev) + +#define DLLQ_CONTAINS(f, l, n, next, prev) for ( + +#define DLLQ_REMOVE_EX(first, last, node, next, prev) \ + do { \ + if ((first) == (last)) { \ + assert((node) == (first)); \ + (first) = (last) = 0; \ + } else if ((last) == (node)) { \ + (last) = (last)->prev; \ + (last)->next = 0; \ + } else if ((first) == (node)) { \ + (first) = (first)->next; \ + (first)->prev = 0; \ + } else { \ + (node)->prev->next = (node)->next; \ + (node)->next->prev = (node)->prev; \ + } \ + if (node) { \ + (node)->prev = 0; \ + (node)->next = 0; \ + } \ + } while (0) +#define DLLQ_REMOVE(first, last, node) DLLQ_REMOVE_EX(first, last, node, next, prev) + +// Doubly linked list Stack +#define DLLS_PUSH_EX(first, node, next, prev) \ + do { \ + assert((node)->next == NULL); \ + assert((node)->prev == NULL); \ + (node)->next = (first); \ + if ((first)) \ + (first)->prev = (node); \ + (first) = (node); \ + } while (0) +#define DLLS_PUSH(first, node) DLLS_PUSH_EX(first, node, next, prev) +#define DLLS_REMOVE_EX(first, node, next, prev) \ + do { \ + if ((node) == (first)) { \ + (first) = (first)->next; \ + if ((first)) \ + (first)->prev = 0; \ + } else { \ + (node)->prev->next = (node)->next; \ + if ((node)->next) \ + (node)->next->prev = (node)->prev; \ + } \ + if (node) { \ + (node)->prev = 0; \ + (node)->next = 0; \ + } \ + } while (0) +#define DLLS_REMOVE(first, node) DLLS_REMOVE_EX(first, node, next, prev) diff --git a/src/core/core_hash_table.c b/src/core/core_hash_table.c index 42604c8..20f6ded 100644 --- a/src/core/core_hash_table.c +++ b/src/core/core_hash_table.c @@ -110,3 +110,57 @@ fn s8i_t *internf(ht_t *ht, char *str, ...) { S8_FMT(ht->arena, str, string); return intern_string(ht, string); } + +/////////////////////////////// +// testing + +fn_test void test_hash_table(void) { + ma_temp_t scratch = ma_begin_scratch(); + { + ht_t *ht = ht_create(scratch.arena, 16); + + for (u64 i = 0; i < 128; i += 1) { + ht_insert_u64(ht, i, i); + ht_node_t *node = ht_search_u64_ex(ht, i); + assert(node->kv.value_u64 == i); + assert(node->kv.key_u64 == i); + } + for (u64 i = 0; i < 128; i += 1) { + ht_node_t *node = ht_search_u64_ex(ht, i); + assert(node->kv.value_u64 == i); + assert(node->kv.key_u64 == i); + } + + ht_node_t *node = ht_search_u64_ex(ht, 1111); + assert(node == NULL); + } + { + ht_t *ht = ht_create(scratch.arena, 16); + + for (i32 i = 0; i < 128; i += 1) { + s8_t s = s8_printf(scratch.arena, "%d", i); + ht_insert_string(ht, s, s); + ht_node_t *node = ht_search_string_ex(ht, s); + assert(s8_are_equal(node->kv.value_string, s)); + assert(s8_are_equal(node->kv.key_string, s)); + } + + ht_node_t *node = ht_search_string_ex(ht, s8_lit("memes")); + assert(node == NULL); + } + + ma_end_scratch(scratch); +} + +fn_test void test_intern_table(void) { + ma_temp_t scratch = ma_begin_scratch(); + ht_t *ht = ht_create(scratch.arena, 4); + assert(internf(ht, "asd") == internf(ht, "asd")); + assert(internf(ht, "asdf") != internf(ht, "asd")); + assert(internf(ht, "asdf") == internf(ht, "asdf")); + assert(internf(ht, "123asdf") == internf(ht, "123asdf")); + assert(internf(ht, "123asdf") != internf(ht, "133asdf")); + assert(internf(ht, "") == internf(ht, "")); + assert(internf(ht, "") != internf(ht, "a")); + ma_end_scratch(scratch); +} diff --git a/src/core/core_inc.h b/src/core/core_inc.h deleted file mode 100644 index a4c0840..0000000 --- a/src/core/core_inc.h +++ /dev/null @@ -1,16 +0,0 @@ -#include "core_platform_defines.h" -#include -#include -#include -#include "core.h" -#include "core_unicode.h" -#include "core_arena.h" -#include "core_string.h" -#include "core_math.h" -#include "core_type_info.h" -#include "core_lexer.h" -#include "core_log.h" -#include "core_intrin.h" -#include "core_platform.h" -#include "core_hash_table.h" -#include "core_ctx.h" \ No newline at end of file diff --git a/src/core/core_string.c b/src/core/core_string.c index 547a926..210d871 100644 --- a/src/core/core_string.c +++ b/src/core/core_string.c @@ -380,6 +380,7 @@ fn sb8_node_t *sb8_create_node(ma_arena_t *ma, s8_t str) { } fn sb8_node_t *sb8_append(sb8_t *list, s8_t string) { + assert(list->arena != NULL); sb8_node_t *node = sb8_create_node(list->arena, string); SLLQ_APPEND(list->first, list->last, node); return node; @@ -530,4 +531,99 @@ fn fuzzy_pair_t *fuzzy_rate_array(ma_arena_t *arena, s8_t needle, s8_t *array, i } return pairs; -} \ No newline at end of file +} + +fn_test void test_s8(void) { + ma_arena_t *arena = ma_create(ma_default_reserve_size); + + { + ma_temp_t temp = ma_begin_temp(arena); + sb8_t *sb = &(sb8_t){arena}; + + s8_t memes = s8_lit("memes"); + sb8_printf(sb, "%S", memes); + assert(sb->first == sb->last); + assert(sb->first->len == 5); + assert(s8_are_equal(sb->first->string, memes)); + + sb8_printf(sb, "%S", s8_lit("things are going fine")); + s8_t string = sb8_merge(temp.arena, sb); + assert(s8_are_equal(string, s8_lit("memesthings are going fine"))); + + ma_end_temp(temp); + } + + { + s8_t str = s8_lit("thing|another|"); + sb8_t sb = s8_split(arena, str, s8_lit("|"), s8_split_none); + + assert(s8_are_equal(sb.first->string, s8_lit("thing"))); + assert(s8_are_equal(sb.first->next->string, s8_lit("another"))); + assert(sb.first->next->next == NULL); + } + + { + s8_t str = s8_lit("thing|another|"); + sb8_t sb = s8_split(arena, str, s8_lit("|"), s8_split_inclusive); + + assert(s8_are_equal(sb.first->string, s8_lit("thing"))); + assert(s8_are_equal(sb.first->next->string, s8_lit("|"))); + assert(s8_are_equal(sb.first->next->next->string, s8_lit("another"))); + assert(s8_are_equal(sb.first->next->next->next->string, s8_lit("|"))); + assert(sb.first->next->next->next->next == NULL); + } + + { + s8_t str = s8_lit("aabaaBaa"); + sb8_t sb = s8_split(arena, str, s8_lit("b"), s8_split_inclusive | s8_split_ignore_case); + + assert(s8_are_equal(sb.first->string, s8_lit("aa"))); + assert(s8_are_equal(sb.first->next->string, s8_lit("b"))); + assert(s8_are_equal(sb.first->next->next->string, s8_lit("aa"))); + assert(s8_are_equal(sb.first->next->next->next->string, s8_lit("B"))); + assert(s8_are_equal(sb.first->next->next->next->next->string, s8_lit("aa"))); + assert(sb.first->next->next->next->next->next == NULL); + } + + { + s8_t str = s8_lit("aabaaBaa"); + sb8_t sb = s8_split(arena, str, s8_lit("b"), s8_split_inclusive); + + assert(s8_are_equal(sb.first->string, s8_lit("aa"))); + assert(s8_are_equal(sb.first->next->string, s8_lit("b"))); + assert(s8_are_equal(sb.first->next->next->string, s8_lit("aaBaa"))); + } + + { + s8_t s = s8_lit("0123456789"); + assert(s8_are_equal(s8_slice(s, 0, 4), s8_lit("0123"))); + assert(s8_are_equal(s8_slice(s, -2, -1), s8_lit("89"))); + assert(s8_are_equal(s8_slice(s, -2, 10), s8_lit("89"))); + assert(s8_are_equal(s8_slice(s, 8, 10), s8_lit("89"))); + } + + { + s8_t s = s8_lit(" a \n"); + s = s8_trim(s); + assert(s8_are_equal(s, s8_lit("a"))); + } + + { + s8_t s = s8_lit("C:/memes/the_thing.c"); + s8_t ss = s8_get_name_no_ext(s); + assert(s8_are_equal(ss, s8_lit("the_thing"))); + } + + { + s8_t s = s8_printf(arena, "%d%Sv%s", 32, s8_lit("|"), ">"); + assert(s8_are_equal(s, s8_lit("32|v>"))); + } + + { + s8_t s0 = s8_lit("0123456789"); + s8_t s1 = s8_cut_start(&s0, 2); + assert(s8_are_equal(s0, s8_lit("23456789"))); + assert(s8_are_equal(s1, s8_lit("01"))); + } + ma_destroy(arena); +} diff --git a/src/core/core_test_entry.c b/src/core/core_test_entry.c deleted file mode 100644 index bf34874..0000000 --- a/src/core/core_test_entry.c +++ /dev/null @@ -1,171 +0,0 @@ -#include "core/core_inc.h" -#include "core/core_inc.c" - -void test_s8(void) { - ma_arena_t *arena = ma_create(ma_default_reserve_size); - - { - ma_temp_t temp = ma_begin_temp(arena); - sb8_t *sb = &(sb8_t){arena}; - - s8_t memes = s8_lit("memes"); - sb8_printf(sb, "%S", memes); - assert(sb->first == sb->last); - assert(sb->first->len == 5); - assert(s8_are_equal(sb->first->string, memes)); - - sb8_printf(sb, "%S", s8_lit("things are going fine")); - s8_t string = sb8_merge(temp.arena, sb); - assert(s8_are_equal(string, s8_lit("memesthings are going fine"))); - - ma_end_temp(temp); - } - - { - s8_t str = s8_lit("thing|another|"); - sb8_t sb = s8_split(arena, str, s8_lit("|"), s8_split_none); - - assert(s8_are_equal(sb.first->string, s8_lit("thing"))); - assert(s8_are_equal(sb.first->next->string, s8_lit("another"))); - assert(sb.first->next->next == NULL); - } - - { - s8_t str = s8_lit("thing|another|"); - sb8_t sb = s8_split(arena, str, s8_lit("|"), s8_split_inclusive); - - assert(s8_are_equal(sb.first->string, s8_lit("thing"))); - assert(s8_are_equal(sb.first->next->string, s8_lit("|"))); - assert(s8_are_equal(sb.first->next->next->string, s8_lit("another"))); - assert(s8_are_equal(sb.first->next->next->next->string, s8_lit("|"))); - assert(sb.first->next->next->next->next == NULL); - } - - { - s8_t str = s8_lit("aabaaBaa"); - sb8_t sb = s8_split(arena, str, s8_lit("b"), s8_split_inclusive | s8_split_ignore_case); - - assert(s8_are_equal(sb.first->string, s8_lit("aa"))); - assert(s8_are_equal(sb.first->next->string, s8_lit("b"))); - assert(s8_are_equal(sb.first->next->next->string, s8_lit("aa"))); - assert(s8_are_equal(sb.first->next->next->next->string, s8_lit("B"))); - assert(s8_are_equal(sb.first->next->next->next->next->string, s8_lit("aa"))); - assert(sb.first->next->next->next->next->next == NULL); - } - - { - s8_t str = s8_lit("aabaaBaa"); - sb8_t sb = s8_split(arena, str, s8_lit("b"), s8_split_inclusive); - - assert(s8_are_equal(sb.first->string, s8_lit("aa"))); - assert(s8_are_equal(sb.first->next->string, s8_lit("b"))); - assert(s8_are_equal(sb.first->next->next->string, s8_lit("aaBaa"))); - } - - { - s8_t s = s8_lit("0123456789"); - assert(s8_are_equal(s8_slice(s, 0, 4), s8_lit("0123"))); - assert(s8_are_equal(s8_slice(s, -2, -1), s8_lit("89"))); - assert(s8_are_equal(s8_slice(s, -2, 10), s8_lit("89"))); - assert(s8_are_equal(s8_slice(s, 8, 10), s8_lit("89"))); - } - - { - s8_t s = s8_lit(" a \n"); - s = s8_trim(s); - assert(s8_are_equal(s, s8_lit("a"))); - } - - { - s8_t s = s8_lit("C:/memes/the_thing.c"); - s8_t ss = s8_get_name_no_ext(s); - assert(s8_are_equal(ss, s8_lit("the_thing"))); - } - - { - s8_t s = s8_printf(arena, "%d%Sv%s", 32, s8_lit("|"), ">"); - assert(s8_are_equal(s, s8_lit("32|v>"))); - } - - { - s8_t s0 = s8_lit("0123456789"); - s8_t s1 = s8_cut_start(&s0, 2); - assert(s8_are_equal(s0, s8_lit("23456789"))); - assert(s8_are_equal(s1, s8_lit("01"))); - } - ma_destroy(arena); -} - -void test_hash_table(void) { - ma_temp_t scratch = ma_begin_scratch(); - { - ht_t *ht = ht_create(scratch.arena, 16); - - for (u64 i = 0; i < 128; i += 1) { - ht_insert_u64(ht, i, i); - ht_node_t *node = ht_search_u64_ex(ht, i); - assert(node->kv.value_u64 == i); - assert(node->kv.key_u64 == i); - } - for (u64 i = 0; i < 128; i += 1) { - ht_node_t *node = ht_search_u64_ex(ht, i); - assert(node->kv.value_u64 == i); - assert(node->kv.key_u64 == i); - } - - ht_node_t *node = ht_search_u64_ex(ht, 1111); - assert(node == NULL); - } - { - ht_t *ht = ht_create(scratch.arena, 16); - - for (i32 i = 0; i < 128; i += 1) { - s8_t s = s8_printf(scratch.arena, "%d", i); - ht_insert_string(ht, s, s); - ht_node_t *node = ht_search_string_ex(ht, s); - assert(s8_are_equal(node->kv.value_string, s)); - assert(s8_are_equal(node->kv.key_string, s)); - } - - ht_node_t *node = ht_search_string_ex(ht, s8_lit("memes")); - assert(node == NULL); - } - - ma_end_scratch(scratch); -} - -void test_intern_table(void) { - ma_temp_t scratch = ma_begin_scratch(); - ht_t *ht = ht_create(scratch.arena, 4); - assert(internf(ht, "asd") == internf(ht, "asd")); - assert(internf(ht, "asdf") != internf(ht, "asd")); - assert(internf(ht, "asdf") == internf(ht, "asdf")); - assert(internf(ht, "123asdf") == internf(ht, "123asdf")); - assert(internf(ht, "123asdf") != internf(ht, "133asdf")); - assert(internf(ht, "") == internf(ht, "")); - assert(internf(ht, "") != internf(ht, "a")); - ma_end_scratch(scratch); -} - -#include - - -int main(int argc, char **argv) { - core_init(); - printf("PLATFORM_WASM = %d\n", PLATFORM_WASM); - printf("PLATFORM_WINDOWS = %d\n", PLATFORM_WINDOWS); - printf("PLATFORM_LINUX = %d\n", PLATFORM_LINUX); - printf("PLATFORM_POSIX = %d\n", PLATFORM_POSIX); - printf("PLATFORM_MAC_OS = %d\n", PLATFORM_MAC_OS); - printf("PLATFORM_CLANG = %d\n", PLATFORM_CLANG); - printf("PLATFORM_GCC = %d\n", PLATFORM_GCC); - printf("PLATFORM_CL = %d\n", PLATFORM_CL); - printf("PLATFORM_TCC = %d\n", PLATFORM_TCC); - - - test_s8(); - test_hash_table(); - test_intern_table(); - - printf("all done!\n"); -} \ No newline at end of file diff --git a/src/meta/meta_cfiles.c b/src/meta/meta_cfiles.c index 5438b83..69d5969 100644 --- a/src/meta/meta_cfiles.c +++ b/src/meta/meta_cfiles.c @@ -116,10 +116,24 @@ fn s8_t mt_serial_to_cbyte_array(ma_arena_t *arena, s8_t file, s8_t var_name) { return result; } -#define mt_cpath(arena) mt_gen_filename(arena, s8_lit(__FILE__), s8_lit("c")) -#define mt_hpath(arena) mt_gen_filename(arena, s8_lit(__FILE__), s8_lit("h")) +#define mt_cpath(arena) mt_gen_filename(arena, S8_FILE, s8_lit("c")) +#define mt_hpath(arena) mt_gen_filename(arena, S8_FILE, s8_lit("h")) fn s8_t mt_gen_filename(ma_arena_t *arena, s8_t lit_file, s8_t ext) { s8_t file_noext = s8_chop_last_period(s8_chop_last_period(lit_file)); s8_t file = s8_printf(arena, "%S.gen.%S", file_noext, ext); return file; +} + +#define mt_main_path(arena) mt__main_path(arena, S8_FILE) +fn s8_t mt__main_path(ma_arena_t *arena, s8_t file) { + s8_t file_noext = s8_chop_last_period(s8_chop_last_period(file)); + s8_t path = s8_printf(arena, "%S_main.c", file_noext); + return path; +} + +fn sb8_t *mt_get_include_paths(ma_arena_t *arena) { + sb8_t *result = ma_push_type(arena, sb8_t); + result->arena = arena; + sb8_append(result, OS_GetAbsolutePath(&Perm, s8_lit("../src"))); + return result; } \ No newline at end of file diff --git a/src/os/os.c b/src/os/os.c index 13e6817..545a1d1 100644 --- a/src/os/os.c +++ b/src/os/os.c @@ -4,4 +4,28 @@ #include "os_win32.c" #else #include "os_unix.c" -#endif \ No newline at end of file +#endif + + +fn_test void os_test(void) { + os_date_t local_time = os_local_time(); + os_date_t universal_time = os_universal_time(); + debugf("local_time = %S | universal_time = %S", os_format_date(tcx->temp, local_time), os_format_date(tcx->temp, universal_time)); + + s8_t exe_dir = os_exe_dir(tcx->temp); + assert(exe_dir.str[exe_dir.len - 1] == '/'); + s8_t exe = os_exe(tcx->temp); + s8_t cwd = os_cwd(tcx->temp); + assert(exe_dir.str[cwd.len - 1] == '/'); + assert(os_is_dir(exe_dir)); + assert(os_is_file(exe)); + assert(os_is_dir(cwd)); + assert(os_exists(exe_dir)); + assert(os_exists(exe)); + assert(os_exists(cwd)); + assert(os_is_abs(exe_dir)); + assert(os_is_abs(exe)); + assert(os_is_abs(cwd)); + assert(!os_is_abs(s8_lit("../path/"))); + debugf("%S %S %S", exe_dir, exe, cwd); +} diff --git a/src/os/os.h b/src/os/os.h index 1a5a2d9..47b786a 100644 --- a/src/os/os.h +++ b/src/os/os.h @@ -9,42 +9,73 @@ struct os_date_t { u16 year; }; -fn os_date_t os_local_time_now(void); -fn os_date_t os_universal_time_now(void); -fn f64 os_milliseconds_now(void); +typedef struct os_iter_t os_iter_t; +struct os_iter_t { + s8_t abs; + s8_t rel; + s8_t name; + b8 is_directory; + b8 is_valid; -#if 0 -fn u64 os_microseconds_now(); -fn f64 os_seconds_now(); -fn u32 os_unix_time_now(); + s8_t path; + ma_arena_t *arena; -fn os_date_t os_local_time_to_universal_time(); -fn os_date_t os_universal_time_to_local_time(); + union { + struct w32_file_iter_t *w32; + void *platform; + }; +}; -fn void os_sleep_milliseconds(); +typedef enum { + os_mkdir_success, + os_mkdir_file_exists, + os_mkdir_path_not_found, + os_mkdir_other_error, +} os_mkdir_t; + +typedef enum { + os_write_success, + os_write_path_not_found, + os_write_other_error, +} os_write_t; + +fn os_date_t os_local_time(void); +fn os_date_t os_universal_time(void); +fn s8_t os_format_date(ma_arena_t *arena, os_date_t date); +fn f64 os_seconds(void); +fn f64 os_milliseconds(void); + +fn b32 os_copy(s8_t from, s8_t to, b32 overwrite); +fn b32 os_delete(s8_t path); +fn os_mkdir_t os_mkdir(s8_t path); +fn os_write_t os_write(s8_t path, s8_t content); + +fn void os_advance(os_iter_t *it); +fn os_iter_t *os_iter(ma_arena_t *arena, s8_t path); + +fn i64 os_mod_time(s8_t file); +fn s8_t os_abs(ma_arena_t *arena, s8_t rel); +fn s8_t os_exe(ma_arena_t *arena); +fn s8_t os_exe_dir(ma_arena_t *arena); +fn b32 os_is_dir(s8_t path); +fn b32 os_is_file(s8_t path); +fn b32 os_is_abs(s8_t path); +fn b32 os_exists(s8_t path); + +fn s8_t os_cwd(ma_arena_t *arena); +fn void os_set_cwd(s8_t new_cwd); -fn s8_t os_list_files(arena, path, recursive); -fn os_file_iter_t os_iterate_files(); -fn void os_advance() -fn b32 os_is_valid(); +typedef i32 os_thread_fn_t(void *user_data); +typedef struct os_thread_t os_thread_t; +struct os_thread_t { + b32 exited; + i32 exit_code; + union { + struct w32_thread_t *w32; + void *ptr; + }; +}; -fn s8_t os_read_file(ma_arena_t *arena, s8_t path); -fn void os_write_file(s8_t path, s8_t content); -fn void os_make_dir(s8_t path); -fn os_result_t os_copy_file(s8_t from, s8_t to, b32 overwrite); -fn os_result_t os_delete_file(s8_t path); -fn i64 os_get_file_mod_time(s8_t path); - -fn b32 os_path_exists(s8_t path); -fn b32 os_path_is_dir(s8_t path); -fn b32 os_path_is_file(s8_t path); -fn b32 os_path_is_abs(s8_t path); -fn b32 os_path_is_rel(s8_t path); -fn s8_t os_path_to_abs(ma_arena_t *arena, s8_t path); - -fn s8_t os_path_exe(ma_arena_t *arena); -fn s8_t os_path_exe_dir(ma_arena_t *arena); -fn s8_t os_path_cwd(ma_arena_t *arena); -fn void os_path_set_cwd(s8_t path); -#endif \ No newline at end of file +fn os_thread_t os_thread_create(ma_arena_t *arena, os_thread_fn_t *func, void *user_data); +fn i32 os_thread_wait_for_exit(os_thread_t *thread); diff --git a/src/os/os_wasm.c b/src/os/os_wasm.c deleted file mode 100644 index 3ac34a8..0000000 --- a/src/os/os_wasm.c +++ /dev/null @@ -1,20 +0,0 @@ -fn_wasm_import void wasm_local_time_now(void *buff, i32 size); -fn_wasm_import void wasm_universal_time_now(void *buff, i32 size); -fn_wasm_import f64 wasm_milliseconds_now(void); - -fn os_date_t os_local_time_now(void) { - os_date_t result = {0}; - wasm_local_time_now(&result, sizeof(result)); - return result; -} - -fn os_date_t os_universal_time_now(void) { - os_date_t result = {0}; - wasm_universal_time_now(&result, sizeof(result)); - return result; -} - -fn f64 os_milliseconds_now(void) { - return wasm_milliseconds_now(); -} - diff --git a/src/os/os_win32.c b/src/os/os_win32.c index 6ddf2ed..361b110 100644 --- a/src/os/os_win32.c +++ b/src/os/os_win32.c @@ -1,18 +1,39 @@ -fn os_date_t os_local_time_now(void) { - os_date_t result = {0}; +/////////////////////////////// +// time +fn os_date_t os_local_time(void) { SYSTEMTIME lt; GetLocalTime(<); - result.ms = lt.wMilliseconds; - result.sec = lt.wSecond; - result.min = lt.wMinute; - result.hour = lt.wHour; - result.day = lt.wDay; - result.month = lt.wMonth; - result.year = lt.wYear; + os_date_t result = {0}; + result.ms = lt.wMilliseconds; + result.sec = lt.wSecond; + result.min = lt.wMinute; + result.hour = lt.wHour; + result.day = lt.wDay; + result.month = lt.wMonth; + result.year = lt.wYear; return result; } -fn f64 os_seconds_now(void) { +fn os_date_t os_universal_time(void) { + SYSTEMTIME lt; + GetSystemTime(<); + os_date_t result = {0}; + result.ms = lt.wMilliseconds; + result.sec = lt.wSecond; + result.min = lt.wMinute; + result.hour = lt.wHour; + result.day = lt.wDay; + result.month = lt.wMonth; + result.year = lt.wYear; + return result; +} + +fn s8_t os_format_date(ma_arena_t *arena, os_date_t date) { + s8_t result = s8_printf(arena, "%04u-%02u-%02u %02u:%02u:%02u.%03u", date.year, date.month, date.day, date.hour, date.min, date.sec, date.ms); + return result; +} + +fn f64 os_seconds(void) { static int64_t counts_per_second; if (counts_per_second == 0) { LARGE_INTEGER freq; @@ -26,9 +47,297 @@ fn f64 os_seconds_now(void) { return result; } -fn f64 os_get_milliseconds(void) { - f64 secs = os_seconds_now(); +fn f64 os_milliseconds(void) { + f64 secs = os_seconds(); f64 result = secs * 1000; return result; } +fn void os_sleep(u32 milliseconds) { + Sleep(milliseconds); +} + +/////////////////////////////// +// files +fn b32 os_copy(s8_t from, s8_t to, b32 overwrite) { + BOOL fail_if_exists = true; + if (overwrite) fail_if_exists = false; + ma_temp_t scratch = ma_begin_scratch(); + s16_t from16 = s16_from_s8(scratch.arena, from); + s16_t to16 = s16_from_s8(scratch.arena, to); + BOOL success = CopyFileW(from16.str, to16.str, fail_if_exists); + ma_end_scratch(scratch); + return success ? true : false; +} + +fn b32 os_delete(s8_t path) { + ma_temp_t scratch = ma_begin_scratch(); + s16_t path16 = s16_from_s8(scratch.arena, path); + BOOL success = DeleteFileW(path16.str); + ma_end_scratch(scratch); + return success ? true : false; +} + +fn os_mkdir_t os_mkdir(s8_t path) { + os_mkdir_t result = os_mkdir_success; + ma_temp_t scratch = ma_begin_scratch(); + s16_t path16 = s16_from_s8(scratch.arena, path); + BOOL success = CreateDirectoryW(path16.str, NULL); + if (success == 0) { + DWORD error = GetLastError(); + if (error == ERROR_ALREADY_EXISTS) result = os_mkdir_file_exists; + else if (error == ERROR_PATH_NOT_FOUND) result = os_mkdir_path_not_found; + else result = os_mkdir_other_error; + } + ma_end_scratch(scratch); + return result; +} + +fn os_write_t os_write(s8_t path, s8_t content) { + os_write_t result = os_write_other_error; + ma_temp_t scratch = ma_begin_scratch(); + s16_t path16 = s16_from_s8(scratch.arena, path); + HANDLE handle = CreateFileW(path16.str, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle != INVALID_HANDLE_VALUE) { + assert(content.len == (DWORD)content.len); + DWORD bytes_written = 0; + BOOL error = WriteFile(handle, content.str, (DWORD)content.len, &bytes_written, NULL); + if (error == TRUE) { + if (bytes_written == content.len) { + result = os_write_success; + } + } + CloseHandle(handle); + } else result = os_write_path_not_found; + ma_end_scratch(scratch); + return result; +} + +typedef struct w32_file_iter_t w32_file_iter_t; +struct w32_file_iter_t { + HANDLE handle; + WIN32_FIND_DATAW data; +}; + +fn void os_advance(os_iter_t *it) { + while (FindNextFileW(it->w32->handle, &it->w32->data) != 0) { + WIN32_FIND_DATAW *data = &it->w32->data; + + // Skip '.' and '..' + if (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0) continue; + if (data->cFileName[0] == '.' && data->cFileName[1] == 0) continue; + + it->is_directory = data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; + it->name = s8_from_s16(it->arena, s16(data->cFileName, wstr_len(data->cFileName))); + char *is_dir = it->is_directory ? "/" : ""; + char *separator = it->path.str[it->path.len - 1] == '/' ? "" : "/"; + it->rel = s8_printf(it->arena, "%S%s%S%s", it->path, separator, it->name, is_dir); + it->abs = os_abs(it->arena, it->rel); + it->is_valid = true; + + if (it->is_directory) { + assert(it->rel.str[it->rel.len - 1] == '/'); + assert(it->abs.str[it->abs.len - 1] == '/'); + } + + return; + } + + it->is_valid = false; + DWORD error = GetLastError(); + assert(error == ERROR_NO_MORE_FILES); + FindClose(it->w32->handle); +} + +fn os_iter_t *os_iter(ma_arena_t *arena, s8_t path) { + os_iter_t *it = ma_push_type(arena, os_iter_t); + it->w32 = ma_push_type(arena, w32_file_iter_t); + it->arena = arena; + it->path = path; + it->is_valid = true; + + ma_temp_t scratch = ma_begin_scratch1(arena); + s8_t mod_path = s8_printf(scratch.arena, "%S\\*", path); + s16_t mod_path16 = s16_from_s8(scratch.arena, mod_path); + + it->w32->handle = FindFirstFileW(mod_path16.str, &it->w32->data); + if (it->w32->handle == INVALID_HANDLE_VALUE) { + it->is_valid = false; + } + + if (it->is_valid) { + assert(it->w32->data.cFileName[0] == '.' && it->w32->data.cFileName[1] == 0); + os_advance(it); + } + + ma_end_scratch(scratch); + return it; +} + +fn i64 os_mod_time(s8_t file) { + WIN32_FIND_DATAW data; + ma_temp_t scratch = ma_begin_scratch(); + s16_t wpath = s16_from_s8(scratch.arena, file); + HANDLE handle = FindFirstFileW(wpath.str, &data); + i64 result = -1; + if (handle != INVALID_HANDLE_VALUE) { + FindClose(handle); + FILETIME time = data.ftLastWriteTime; + result = (i64)time.dwHighDateTime << 32 | time.dwLowDateTime; + } + ma_end_scratch(scratch); + return result; +} + +fn s8_t os_abs(ma_arena_t *arena, s8_t rel) { + const int buffer_size = 2048; + ma_temp_t scratch = ma_begin_scratch1(arena); + s16_t rel16 = s16_from_s8(scratch.arena, rel); + wchar_t *buffer = ma_push_array(scratch.arena, wchar_t, buffer_size); + DWORD written = GetFullPathNameW(rel16.str, buffer_size, buffer, 0); + assert(written != 0); + assert((i64)written < (i64)buffer_size); + s8_t result = s8_from_s16(arena, s16(buffer, written)); + ma_end_scratch(scratch); + return result; +} + +fn s8_t os_exe(ma_arena_t *arena) { + const int buffer_size = 2048; + ma_temp_t scratch = ma_begin_scratch1(arena); + wchar_t *buffer = ma_push_array(scratch.arena, wchar_t, buffer_size); + DWORD wsize = GetModuleFileNameW(0, buffer, buffer_size); + assert(wsize != 0); + s8_t result = s8_from_s16(arena, s16(buffer, wsize)); + s8_normalize_path_unsafe(result); + ma_end_scratch(scratch); + return result; +} + +fn s8_t os_exe_dir(ma_arena_t *arena) { + ma_temp_t scratch = ma_begin_scratch1(arena); + s8_t exe = os_exe(scratch.arena); + s8_t path = s8_chop_last_slash(exe); + s8_t result = s8_printf(arena, "%S/", path); + ma_end_scratch(scratch); + return result; +} + +fn b32 os_is_dir(s8_t path) { + ma_temp_t scratch = ma_begin_scratch(); + s16_t path16 = s16_from_s8(scratch.arena, path); + DWORD dwAttrib = GetFileAttributesW(path16.str); + ma_end_scratch(scratch); + return dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY); +} + +fn b32 os_is_file(s8_t path) { + ma_temp_t scratch = ma_begin_scratch(); + s16_t path16 = s16_from_s8(scratch.arena, path); + DWORD dwAttrib = GetFileAttributesW(path16.str); + ma_end_scratch(scratch); + b32 is_file = (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) == 0; + return dwAttrib != INVALID_FILE_ATTRIBUTES && is_file; +} + +fn b32 os_is_abs(s8_t path) { + b32 result = path.len > 3 && char_is_alphabetic(path.str[0]) && path.str[1] == ':' && path.str[2] == '/'; + return result; +} + +fn b32 os_exists(s8_t path) { + ma_temp_t scratch = ma_begin_scratch(); + s16_t path16 = s16_from_s8(scratch.arena, path); + DWORD attribs = GetFileAttributesW(path16.str); + ma_end_scratch(scratch); + return attribs == INVALID_FILE_ATTRIBUTES ? false : true; +} + +fn s8_t os_cwd(ma_arena_t *arena) { + ma_temp_t scratch = ma_begin_scratch1(arena); + const u32 buffer_size = 1024; + wchar_t *buffer = ma_push_array(scratch.arena, wchar_t, buffer_size); + DWORD wsize = GetCurrentDirectoryW(buffer_size, buffer); + assert(wsize != 0); + assert(wsize <= buffer_size); + s8_t path = s8_from_s16(scratch.arena, s16(buffer, wsize)); + s8_normalize_path_unsafe(path); + s8_t result = s8_printf(arena, "%S/", path); + ma_end_scratch(scratch); + return result; +} + +fn void os_set_cwd(s8_t path) { + ma_temp_t scratch = ma_begin_scratch(); + s16_t path16 = s16_from_s8(scratch.arena, path); + SetCurrentDirectoryW(path16.str); + ma_end_scratch(scratch); +} + +/////////////////////////////// +// threading + +typedef struct w32_thread_t w32_thread_t; +struct w32_thread_t { + HANDLE handle; + DWORD id; +}; + +fn os_thread_t os_thread_create(ma_arena_t *arena, os_thread_fn_t *func, void *user_data) { + assert(func); + + LPSECURITY_ATTRIBUTES security_attribs = NULL; + SIZE_T stack_size = 0; + DWORD creation_flags = 0; + DWORD thread_id = 0; + HANDLE thread_handle = CreateThread(security_attribs, stack_size, func, user_data, creation_flags, &thread_id); + if (thread_handle == NULL) { + debugf(__FUNCTION__"CreatedThread failed: %d", GetLastError()); + return (os_thread_t){.exited = true}; + } + + os_thread_t result = {0}; + result.w32 = ma_push_type(arena, w32_thread_t); + result.w32->handle = thread_handle; + result.w32->id = thread_id; + return result; +} + +fn i32 os_join(os_thread_t *thread) { + DWORD return_value_indicates_event = WaitForSingleObject(thread->w32->handle, INFINITE); + if (return_value_indicates_event != WAIT_OBJECT_0) { + debugf(__FUNCTION__".WaitForSingleObject failed: %d", GetLastError()); + } + + DWORD exit_code = 0; + BOOL if_fails_then_zero = GetExitCodeThread(thread->w32->handle, &exit_code); + if (if_fails_then_zero == 0) { + debugf(__FUNCTION__".GetExitCodeThread failed: %d", GetLastError()); + } else { + thread->exit_code = exit_code; + } + + CloseHandle(thread->w32->handle); + thread->exited = true; + return thread->exit_code; +} + +// @todo: +// This will probably create 16 arenas or more XD +// fn i32 os__thread_log(void *data) { +// core_init(); +// debugf("testing"); +// return 0; +// } + +// fn void os_test_threads(void) { +// os_thread_t threads[16]; +// ma_temp_t scratch = ma_begin_scratch(); +// for (int i = 0; i < lengthof(threads); i += 1) { +// threads[i] = os_thread_create(scratch.arena, os__thread_log, NULL); +// } +// for (int i = 0; i < lengthof(threads); i += 1) { +// os_join(&threads[i]); +// } +// ma_end_scratch(scratch); +// } \ No newline at end of file diff --git a/src/render/render.c b/src/render/render.c index 44fc8fb..9c271ee 100644 --- a/src/render/render.c +++ b/src/render/render.c @@ -1,129 +1,30 @@ -fn rn_cmd_t *rn_get_cmd(rn_cmd_kind_t kind) { - b32 alloc_new = false; - if (rn->last_cmd == NULL) { - alloc_new = true; - } else if (rn->last_cmd->kind != kind) { - alloc_new = true; - } +#if PLATFORM_WINDOWS +#include "render.h" +#define STB_TRUETYPE_IMPLEMENTATION +#define STBTT_ifloor(x) ((int)f64_floor(x)) +#define STBTT_iceil(x) ((int)f64_ceil(x)) +#define STBTT_sqrt(x) (f64_sqrt(x)) +#define STBTT_pow(x,y) (f64_pow(x,y)) +#define STBTT_fmod(x,y) (f64_mod(x,y)) +#define STBTT_cos(x) (f64_cos(x)) +#define STBTT_acos(x) (f64_acos(x)) +#define STBTT_fabs(x) (f64_abs(x)) +#define STBTT_assert(x) (assert(x)) +#define STBTT_malloc(x,u) (ma_push_size(tcx->temp, x)) +#define STBTT_free(x,u) +#define STBTT_strlen(x) (str_len(x)) +#define STBTT_memcpy memory_copy +#define STBTT_memset memory_set +#include "stb_truetype.h" - rn_cmd_t *result = rn->last_cmd; - if (alloc_new) { - result = ma_push_type(tcx->temp, rn_cmd_t); - result->kind = kind; - SLLQ_APPEND(rn->first_cmd, rn->last_cmd, result); +#include +#include "glad/glad.h" +#include "glad/glad.c" - if (rn_cmd_kind_quad) { - result->vertex = rn->vertices + rn->len; - } - } - - return result; -} - -fn rn_vertex_t *rn_push_vertex(rn_cmd_t *cmd, u32 count) { - rn_vertex_t *result = cmd->vertex + cmd->len; - assert(rn->cap >= rn->len + count); - rn->len += count; - - cmd->len += count; - return result; -} - -fn void rn_push_quad(r2f32_t rect, r2f32_t tex, v4f32_t color) { - rn_cmd_t *cmd = rn_get_cmd(rn_cmd_kind_quad); - rn_vertex_t *v = rn_push_vertex(cmd, 6); - v[0] = (rn_vertex_t){ - {rect.min.x, rect.max.y}, - { tex.min.x, tex.max.y}, - color - }; - v[1] = (rn_vertex_t){ - {rect.max.x, rect.max.y}, - { tex.max.x, tex.max.y}, - color - }; - v[2] = (rn_vertex_t){ - {rect.min.x, rect.min.y}, - { tex.min.x, tex.min.y}, - color - }; - v[3] = (rn_vertex_t){ - {rect.min.x, rect.min.y}, - { tex.min.x, tex.min.y}, - color - }; - v[4] = (rn_vertex_t){ - {rect.max.x, rect.max.y}, - { tex.max.x, tex.max.y}, - color - }; - v[5] = (rn_vertex_t){ - {rect.max.x, rect.min.y}, - { tex.max.x, tex.min.y}, - color - }; -} - -fn void rn_draw_rect(r2f32_t rect, v4f32_t color) { - rn_push_quad(rect, rn->main_font->white_texture_bounding_box, color); -} - -fn void rn_draw_rect_border(r2f32_t rect, v4f32_t color, f32 border_thickness) { - r2f32_t left = r2f32_cut_left(&rect, border_thickness); - r2f32_t right = r2f32_cut_right(&rect, border_thickness); - r2f32_t top = r2f32_cut_top(&rect, border_thickness); - r2f32_t bottom = r2f32_cut_bottom(&rect, border_thickness); - rn_push_quad(left, rn->main_font->white_texture_bounding_box, color); - rn_push_quad(right, rn->main_font->white_texture_bounding_box, color); - rn_push_quad(top, rn->main_font->white_texture_bounding_box, color); - rn_push_quad(bottom, rn->main_font->white_texture_bounding_box, color); -} - -fn i64 rn_get_char_spacing(rn_font_t *font, u32 codepoint) { - rn_glyph_t *g = rn_get_glyph(font, codepoint); - if (g->xadvance) return (i64)g->xadvance; - return (i64)g->size.x; -} - -fn i64 rn_get_line_spacing(rn_font_t *font) { - i64 result = (i64)(font->ascent - font->descent + font->line_gap); - return result; -} - -fn v2f32_t rn_base_draw_string(rn_font_t *font, s8_t string, v2f32_t pos, v4f32_t color, b32 draw) { - // old formula :: pos.y += rn_get_line_spacing(font) + font->descent; - pos.y += font->ascent; - v2f32_t original_pos = pos; - - for (utf8_iter_t iter = utf8_iterate_ex(string.str, (int)string.len); iter.item; utf8_advance(&iter)) { - u32 codepoint = iter.item; - rn_glyph_t *g = rn_get_glyph(font, codepoint); - r2f32_t rect = r2f32_min_dim(v2f32_add(pos, g->offset), g->size); - if (draw && codepoint != '\n' && codepoint != ' ' && codepoint != '\t') { - rn_push_quad(rect, g->atlas_bounding_box, color); - } - pos.x += g->xadvance; - } - - - v2f32_t result = {pos.x - original_pos.x, font->size}; - return result; -} - -fn v2f32_t rn_draw_string(rn_font_t *font, v2f32_t pos, v4f32_t color, s8_t string) { - return rn_base_draw_string(font, string, pos, color, true); -} - -fn v2f32_t rn_draw_stringf(rn_font_t *font, v2f32_t pos, v4f32_t color, char *str, ...) { - S8_FMT(tcx->temp, str, result); - return rn_draw_string(font, pos, color, result); -} - -fn v2f32_t rn_measure_string(rn_font_t *font, s8_t string) { - return rn_base_draw_string(font, string, v2f32(0,0), v4f32(0,0,0,0), false); -} - -fn void rn_set_clip(r2f32_t rect) { - rn_cmd_t *cmd = rn_get_cmd(rn_cmd_kind_set_clip); - cmd->rect = rect; -} +#include "render_font.c" +#include "render_basic.c" +#include "render.gen.c" +#include "render_opengl.c" +#else +#include "render_wasm_canvas.c" +#endif \ No newline at end of file diff --git a/src/render/render_basic.c b/src/render/render_basic.c new file mode 100644 index 0000000..44fc8fb --- /dev/null +++ b/src/render/render_basic.c @@ -0,0 +1,129 @@ +fn rn_cmd_t *rn_get_cmd(rn_cmd_kind_t kind) { + b32 alloc_new = false; + if (rn->last_cmd == NULL) { + alloc_new = true; + } else if (rn->last_cmd->kind != kind) { + alloc_new = true; + } + + rn_cmd_t *result = rn->last_cmd; + if (alloc_new) { + result = ma_push_type(tcx->temp, rn_cmd_t); + result->kind = kind; + SLLQ_APPEND(rn->first_cmd, rn->last_cmd, result); + + if (rn_cmd_kind_quad) { + result->vertex = rn->vertices + rn->len; + } + } + + return result; +} + +fn rn_vertex_t *rn_push_vertex(rn_cmd_t *cmd, u32 count) { + rn_vertex_t *result = cmd->vertex + cmd->len; + assert(rn->cap >= rn->len + count); + rn->len += count; + + cmd->len += count; + return result; +} + +fn void rn_push_quad(r2f32_t rect, r2f32_t tex, v4f32_t color) { + rn_cmd_t *cmd = rn_get_cmd(rn_cmd_kind_quad); + rn_vertex_t *v = rn_push_vertex(cmd, 6); + v[0] = (rn_vertex_t){ + {rect.min.x, rect.max.y}, + { tex.min.x, tex.max.y}, + color + }; + v[1] = (rn_vertex_t){ + {rect.max.x, rect.max.y}, + { tex.max.x, tex.max.y}, + color + }; + v[2] = (rn_vertex_t){ + {rect.min.x, rect.min.y}, + { tex.min.x, tex.min.y}, + color + }; + v[3] = (rn_vertex_t){ + {rect.min.x, rect.min.y}, + { tex.min.x, tex.min.y}, + color + }; + v[4] = (rn_vertex_t){ + {rect.max.x, rect.max.y}, + { tex.max.x, tex.max.y}, + color + }; + v[5] = (rn_vertex_t){ + {rect.max.x, rect.min.y}, + { tex.max.x, tex.min.y}, + color + }; +} + +fn void rn_draw_rect(r2f32_t rect, v4f32_t color) { + rn_push_quad(rect, rn->main_font->white_texture_bounding_box, color); +} + +fn void rn_draw_rect_border(r2f32_t rect, v4f32_t color, f32 border_thickness) { + r2f32_t left = r2f32_cut_left(&rect, border_thickness); + r2f32_t right = r2f32_cut_right(&rect, border_thickness); + r2f32_t top = r2f32_cut_top(&rect, border_thickness); + r2f32_t bottom = r2f32_cut_bottom(&rect, border_thickness); + rn_push_quad(left, rn->main_font->white_texture_bounding_box, color); + rn_push_quad(right, rn->main_font->white_texture_bounding_box, color); + rn_push_quad(top, rn->main_font->white_texture_bounding_box, color); + rn_push_quad(bottom, rn->main_font->white_texture_bounding_box, color); +} + +fn i64 rn_get_char_spacing(rn_font_t *font, u32 codepoint) { + rn_glyph_t *g = rn_get_glyph(font, codepoint); + if (g->xadvance) return (i64)g->xadvance; + return (i64)g->size.x; +} + +fn i64 rn_get_line_spacing(rn_font_t *font) { + i64 result = (i64)(font->ascent - font->descent + font->line_gap); + return result; +} + +fn v2f32_t rn_base_draw_string(rn_font_t *font, s8_t string, v2f32_t pos, v4f32_t color, b32 draw) { + // old formula :: pos.y += rn_get_line_spacing(font) + font->descent; + pos.y += font->ascent; + v2f32_t original_pos = pos; + + for (utf8_iter_t iter = utf8_iterate_ex(string.str, (int)string.len); iter.item; utf8_advance(&iter)) { + u32 codepoint = iter.item; + rn_glyph_t *g = rn_get_glyph(font, codepoint); + r2f32_t rect = r2f32_min_dim(v2f32_add(pos, g->offset), g->size); + if (draw && codepoint != '\n' && codepoint != ' ' && codepoint != '\t') { + rn_push_quad(rect, g->atlas_bounding_box, color); + } + pos.x += g->xadvance; + } + + + v2f32_t result = {pos.x - original_pos.x, font->size}; + return result; +} + +fn v2f32_t rn_draw_string(rn_font_t *font, v2f32_t pos, v4f32_t color, s8_t string) { + return rn_base_draw_string(font, string, pos, color, true); +} + +fn v2f32_t rn_draw_stringf(rn_font_t *font, v2f32_t pos, v4f32_t color, char *str, ...) { + S8_FMT(tcx->temp, str, result); + return rn_draw_string(font, pos, color, result); +} + +fn v2f32_t rn_measure_string(rn_font_t *font, s8_t string) { + return rn_base_draw_string(font, string, v2f32(0,0), v4f32(0,0,0,0), false); +} + +fn void rn_set_clip(r2f32_t rect) { + rn_cmd_t *cmd = rn_get_cmd(rn_cmd_kind_set_clip); + cmd->rect = rect; +} diff --git a/src/render/render_inc.c b/src/render/render_inc.c deleted file mode 100644 index 1937a64..0000000 --- a/src/render/render_inc.c +++ /dev/null @@ -1,31 +0,0 @@ - -#if PLATFORM_WINDOWS -#include "render.h" -#define STB_TRUETYPE_IMPLEMENTATION -#define STBTT_ifloor(x) ((int)f64_floor(x)) -#define STBTT_iceil(x) ((int)f64_ceil(x)) -#define STBTT_sqrt(x) (f64_sqrt(x)) -#define STBTT_pow(x,y) (f64_pow(x,y)) -#define STBTT_fmod(x,y) (f64_mod(x,y)) -#define STBTT_cos(x) (f64_cos(x)) -#define STBTT_acos(x) (f64_acos(x)) -#define STBTT_fabs(x) (f64_abs(x)) -#define STBTT_assert(x) (assert(x)) -#define STBTT_malloc(x,u) (ma_push_size(tcx->temp, x)) -#define STBTT_free(x,u) -#define STBTT_strlen(x) (str_len(x)) -#define STBTT_memcpy memory_copy -#define STBTT_memset memory_set -#include "stb_truetype.h" - -#include -#include "glad/glad.h" -#include "glad/glad.c" - -#include "render_font.c" -#include "render.c" -#include "render.gen.c" -#include "render_opengl.c" -#else -#include "render_wasm_canvas.c" -#endif \ No newline at end of file diff --git a/src/testing/testing.gen.c b/src/testing/testing.gen.c new file mode 100644 index 0000000..7aac4d5 --- /dev/null +++ b/src/testing/testing.gen.c @@ -0,0 +1,6 @@ +fn void run_tests(void) { + test_s8(); + test_hash_table(); + test_intern_table(); + os_test(); +} diff --git a/src/testing/testing.meta.c b/src/testing/testing.meta.c new file mode 100644 index 0000000..7b1944e --- /dev/null +++ b/src/testing/testing.meta.c @@ -0,0 +1,32 @@ +void mt_testing(ma_arena_t *arena) { + mt_files_t files = mt_lex_files(arena, mt_main_path(arena), mt_get_include_paths(arena)); + sb8_t *tests = sb8_serial_begin(arena); + + for (mt_file_t *it = files.first; it; it = it->next) { + parser_t *par = parser_make(arena, it->tokens.data); + for (;par->at->kind != lex_kind_eof;) { + b32 matched = false; + + if (par->at->inside_macro == false && parser_matchi(par, s8_lit("fn_test"))) { + parser_expecti(par, s8_lit("void")); + lex_t *ident = parser_match(par, lex_kind_ident); + sb8_append(tests, ident->string); + matched = true; + } + + if (!matched) { + parser_next(par); + } + } + } + + sb8_t *c = sb8_serial_begin(arena); + sb8_printf(c, "fn void run_tests(void) {\n"); + for (sb8_node_t *it = tests->first; it; it = it->next) { + sb8_printf(c, " %S();\n", it->string); + } + sb8_printf(c, "}\n"); + + s8_t result = sb8_serial_end(arena, c); + os_write_file(mt_cpath(arena), result); +} \ No newline at end of file diff --git a/src/testing/testing_main.c b/src/testing/testing_main.c new file mode 100644 index 0000000..63a2d02 --- /dev/null +++ b/src/testing/testing_main.c @@ -0,0 +1,12 @@ +#include "core/core.h" +#include "os/os.h" +#include "core/core.c" +#include "os/os.c" + +#include "testing.gen.c" + +int main() { + core_init(); + run_tests(); + return 0; +} \ No newline at end of file diff --git a/src/ui/ui.c b/src/ui/ui.c index d564d1f..85f27a1 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -1,3 +1,5 @@ +#include "ui.gen.c" + fn ui_caret_t ui_caret_clamp(ui_caret_t c, i32 min, i32 max) { return (ui_caret_t){CLAMP(c.e[0],min,max), CLAMP(c.e[1],min,max), c.ifront}; } diff --git a/src/ui/ui_inc.c b/src/ui/ui_inc.c deleted file mode 100644 index 2d5fc93..0000000 --- a/src/ui/ui_inc.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "ui.gen.c" -#include "ui.c" \ No newline at end of file diff --git a/src/ui/ui_inc.h b/src/ui/ui_inc.h deleted file mode 100644 index f0e3847..0000000 --- a/src/ui/ui_inc.h +++ /dev/null @@ -1 +0,0 @@ -#include "ui.h" \ No newline at end of file diff --git a/src/wasm_app/main.c b/src/wasm_app/main.c index c963645..61710e8 100644 --- a/src/wasm_app/main.c +++ b/src/wasm_app/main.c @@ -1,11 +1,11 @@ -#include "core/core_inc.h" +#include "core/core.h" #include "app/app.h" -#include "ui/ui_inc.h" +#include "ui/ui.h" -#include "core/core_inc.c" +#include "core/core.c" #include "app/app.c" -#include "render/render_inc.c" -#include "ui/ui_inc.c" +#include "render/render.c" +#include "ui/ui.c" #include "wasm_app.gen.c" diff --git a/src/wasm_app/wasm_app.gen.c b/src/wasm_app/wasm_app.gen.c index ac14cdf..8a15c28 100644 --- a/src/wasm_app/wasm_app.gen.c +++ b/src/wasm_app/wasm_app.gen.c @@ -7,5 +7,8 @@ gb_read_only mt_tweak_t tweak_table[] = { }; void run_all_tests(void) { + test_s8(); + test_hash_table(); + test_intern_table(); ui_test_text_replace(); }// run_all_tests() diff --git a/todo.txt b/todo.txt index e37e4ed..c9f0d02 100644 --- a/todo.txt +++ b/todo.txt @@ -75,6 +75,8 @@ [ ] json format [ ] ini format [x] remove dates and time from core + [ ] build system + [ ] threads [ ] meta [x] parser errors should not point to location of fatalf call but to the code!!!!!!!!! [x] prototype something like templates, readable string generation