From 5c150c08dc4da3366959912e4b7bbf9e14a9b428 Mon Sep 17 00:00:00 2001 From: doylet Date: Sun, 7 Sep 2025 18:46:37 +1000 Subject: [PATCH] More revising of the API from The Bar --- Single_Header/dn_single_header.cpp | 1243 ++++++++++++++++++---------- Single_Header/dn_single_header.h | 414 +++++---- Source/Base/dn_base_compiler.h | 4 +- Source/Base/dn_base_convert.h | 2 +- Source/Base/dn_base_mem.h | 6 + Source/Base/dn_base_string.cpp | 25 + Source/Base/dn_base_string.h | 9 +- Source/Core/dn_core_demo.cpp | 6 +- Source/Extra/dn_math.cpp | 32 +- Source/Extra/dn_math.h | 123 ++- Source/Extra/dn_tests.cpp | 28 +- Source/OS/dn_os.cpp | 116 ++- Source/OS/dn_os.h | 217 +++-- Source/OS/dn_os_allocator.h | 2 +- Source/OS/dn_os_posix.cpp | 310 ++++--- Source/OS/dn_os_tls.h | 49 +- Source/OS/dn_os_w32.cpp | 380 +++++---- 17 files changed, 1676 insertions(+), 1290 deletions(-) diff --git a/Single_Header/dn_single_header.cpp b/Single_Header/dn_single_header.cpp index 9db193c..7406d1b 100644 --- a/Single_Header/dn_single_header.cpp +++ b/Single_Header/dn_single_header.cpp @@ -1,4 +1,4 @@ -// Generated by the DN single header generator 2025-09-03 22:49:07 +// Generated by the DN single header generator 2025-09-07 18:46:16 #define DN_BASE_INC_CPP @@ -3261,6 +3261,16 @@ DN_API DN_Str8 DN_Str8_Alloc(DN_Arena *arena, DN_USize size, DN_ZeroMem zero_mem return result; } +DN_API DN_Str8 DN_Str8_AllocPool(DN_Pool *pool, DN_USize size) +{ + DN_Str8 result = {}; + result.data = DN_Pool_NewArray(pool, char, size + 1); + if (result.data) + result.size = size; + result.data[result.size] = 0; + return result; +} + DN_API DN_Str8 DN_Str8_FromCStr8(char const *src) { DN_USize size = DN_CStr8_Size(src); @@ -3277,6 +3287,21 @@ DN_API DN_Str8 DN_Str8_FromF(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ... return result; } +DN_API DN_Str8 DN_Str8_FromFPool(DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_USize size = DN_CStr8_FVSize(fmt, args); + va_end(args); + + DN_Str8 result = {}; + if (size) + result = DN_Str8_AllocPool(pool, size); + if (result.data) + DN_VSNPrintF(result.data, DN_SaturateCastISizeToInt(size + 1 /*null-terminator*/), fmt, args); + return result; +} + DN_API DN_Str8 DN_Str8_FromFV(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args) { DN_Str8 result = {}; @@ -4888,6 +4913,9 @@ DN_API void DN_OS_ErrSinkAppendF_(DN_OSErrSink *err, DN_U32 error_code, DN_FMT_A // DN: Single header generator inlined this file => #include "OS/dn_os.cpp" #define DN_OS_CPP +// DN: Single header generator commented out this header => #include "../dn_base_inc.h" +// DN: Single header generator commented out this header => #include "../dn_os_inc.h" + #if defined(DN_PLATFORM_POSIX) #include // get_nprocs #include // getpagesize @@ -5277,11 +5305,9 @@ DN_API uint64_t DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_fre return result; } -#if !defined(DN_NO_OS_FILE_API) -// NOTE: DN_OSPathInfo/File //////////////////////////////////////////////////////////////////////// -DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against) +DN_API bool DN_OS_PathIsOlderThan(DN_Str8 path, DN_Str8 check_against) { - DN_OSPathInfo file_info = DN_OS_PathInfo(file); + DN_OSPathInfo file_info = DN_OS_PathInfo(path); DN_OSPathInfo check_against_info = DN_OS_PathInfo(check_against); bool result = !file_info.exists || file_info.last_write_time_in_s < check_against_info.last_write_time_in_s; return result; @@ -5333,44 +5359,69 @@ DN_API bool DN_OS_FileWriteF(DN_OSFile *file, DN_OSErrSink *error, DN_FMT_ATTRIB return result; } -// NOTE: R/W Entire File /////////////////////////////////////////////////////////////////////////// -DN_API DN_Str8 DN_OS_ReadAll(DN_Arena *arena, DN_Str8 path, DN_OSErrSink *error) +DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err) { - DN_Str8 result = {}; - if (!arena) - return result; - - // NOTE: Query file size + allocate buffer ///////////////////////////////////////////////////// + // NOTE: Query file size + DN_Str8 result = {}; DN_OSPathInfo path_info = DN_OS_PathInfo(path); if (!path_info.exists) { - DN_OS_ErrSinkAppendF(error, 1, "File does not exist/could not be queried for reading '%.*s'", DN_STR_FMT(path)); + DN_OS_ErrSinkAppendF(err, 1, "File does not exist/could not be queried for reading '%.*s'", DN_STR_FMT(path)); return result; } - DN_ArenaTempMem temp_mem = DN_Arena_TempMemBegin(arena); - result = DN_Str8_Alloc(arena, path_info.size, DN_ZeroMem_No); - if (!DN_Str8_HasData(result)) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 buffer_size_str8 = DN_CVT_BytesStr8FromU64AutoTLS(path_info.size); - DN_OS_ErrSinkAppendF(error, 1 /*error_code*/, "Failed to allocate %.*s for reading file '%.*s'", DN_STR_FMT(buffer_size_str8), DN_STR_FMT(path)); - DN_Arena_TempMemEnd(temp_mem); - result = {}; + // NOTE: Allocate + DN_ArenaTempMem arena_tmp = {}; + if (alloc_type == DN_Allocator_Arena) { + DN_Arena *arena = DN_CAST(DN_Arena *) allocator; + arena_tmp = DN_Arena_TempMemBegin(arena); + result = DN_Str8_Alloc(arena, path_info.size, DN_ZeroMem_No); + } else { + DN_Pool *pool = DN_CAST(DN_Pool *) allocator; + result = DN_Str8_AllocPool(pool, path_info.size); + } + + if (!result.data) { + DN_CVTU64Bytes bytes_str = DN_CVT_BytesFromU64Auto(path_info.size); + DN_OS_ErrSinkAppendF(err, 1 /*err_code*/, "Failed to allocate %.1f %.*s for reading file '%.*s'", bytes_str.bytes, DN_STR_FMT(bytes_str.suffix), DN_STR_FMT(path)); return result; } - // NOTE: Read the file from disk /////////////////////////////////////////////////////////////// - DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, error); - DN_OSFileRead read = DN_OS_FileRead(&file, result.data, result.size, error); + // NOTE: Read all + DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, err); + DN_OSFileRead read = DN_OS_FileRead(&file, result.data, result.size, err); if (file.error || !read.success) { - DN_Arena_TempMemEnd(temp_mem); + if (alloc_type == DN_Allocator_Arena) { + DN_Arena_TempMemEnd(arena_tmp); + } else { + DN_Pool *pool = DN_CAST(DN_Pool *) allocator; + DN_Pool_Dealloc(pool, result.data); + } result = {}; } - DN_OS_FileClose(&file); + DN_OS_FileClose(&file); return result; } -DN_API bool DN_OS_WriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) +DN_API DN_Str8 DN_OS_FileReadAllArena(DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err) +{ + DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Arena, arena, path, err); + return result; +} + +DN_API DN_Str8 DN_OS_FileReadAllPool(DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err) +{ + DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Pool, pool, path, err); + return result; +} + +DN_API DN_Str8 DN_OS_FileReadAllTLS(DN_Str8 path, DN_OSErrSink *err) +{ + DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Arena, DN_OS_TLSArena(), path, err); + return result; +} + +DN_API bool DN_OS_FileWriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) { DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_Write, error); bool result = DN_OS_FileWrite(&file, buffer, error); @@ -5378,54 +5429,52 @@ DN_API bool DN_OS_WriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) return result; } -DN_API bool DN_OS_WriteAllFV(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) +DN_API bool DN_OS_FileWriteAllFV(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) { DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 buffer = DN_Str8_FromFV(tmem.arena, fmt, args); - bool result = DN_OS_WriteAll(file_path, buffer, error); + DN_Str8 buffer = DN_Str8_FromFV(tmem.arena, fmt, args); + bool result = DN_OS_FileWriteAll(file_path, buffer, error); return result; } -DN_API bool DN_OS_WriteAllF(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_OS_FileWriteAllF(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - bool result = DN_OS_WriteAllFV(file_path, error, fmt, args); + bool result = DN_OS_FileWriteAllFV(file_path, error, fmt, args); va_end(args); return result; } -DN_API bool DN_OS_WriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) +DN_API bool DN_OS_FileWriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) { DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_Str8 tmp_path = DN_Str8_FromF(tmem.arena, "%.*s.tmp", DN_STR_FMT(path)); - if (!DN_OS_WriteAll(tmp_path, buffer, error)) + if (!DN_OS_FileWriteAll(tmp_path, buffer, error)) return false; - if (!DN_OS_CopyFile(tmp_path, path, true /*overwrite*/, error)) + if (!DN_OS_FileCopy(tmp_path, path, true /*overwrite*/, error)) return false; if (!DN_OS_PathDelete(tmp_path)) return false; return true; } -DN_API bool DN_OS_WriteAllSafeFV(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) +DN_API bool DN_OS_FileWriteAllSafeFV(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) { DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_Str8 buffer = DN_Str8_FromFV(tmem.arena, fmt, args); - bool result = DN_OS_WriteAllSafe(path, buffer, error); + bool result = DN_OS_FileWriteAllSafe(path, buffer, error); return result; } -DN_API bool DN_OS_WriteAllSafeF(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_OS_FileWriteAllSafeF(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - bool result = DN_OS_WriteAllSafeFV(path, error, fmt, args); + bool result = DN_OS_FileWriteAllSafeFV(path, error, fmt, args); return result; } -#endif // !defined(DN_NO_OS_FILE_API) -// NOTE: DN_OSPath ///////////////////////////////////////////////////////////////////////////////// DN_API bool DN_OS_PathAddRef(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path) { if (!arena || !fs_path || !DN_Str8_HasData(path)) @@ -5469,6 +5518,18 @@ DN_API bool DN_OS_PathAddRef(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path) return true; } +DN_API bool DN_OS_PathAddRefTLS(DN_OSPath *fs_path, DN_Str8 path) +{ + bool result = DN_OS_PathAddRef(DN_OS_TLSTopArena(), fs_path, path); + return result; +} + +DN_API bool DN_OS_PathAddRefFrame(DN_OSPath *fs_path, DN_Str8 path) +{ + bool result = DN_OS_PathAddRef(DN_OS_TLSFrameArena(), fs_path, path); + return result; +} + DN_API bool DN_OS_PathAdd(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path) { DN_Str8 copy = DN_Str8_FromStr8(arena, path); @@ -6557,7 +6618,7 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path) { DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_OSDiskSpace result = {}; - DN_Str8 path_z_terminated = DN_Str8_Copy(tmem.arena, path); + DN_Str8 path_z_terminated = DN_Str8_FromStr8(tmem.arena, path); struct statvfs info = {}; if (statvfs(path_z_terminated.data, &info) != 0) @@ -6658,52 +6719,7 @@ DN_API DN_U64 DN_OS_PerfCounterNow() return result; } -#if !defined(DN_NO_OS_FILE_API) -DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) -{ - DN_OSPathInfo result = {}; - if (!DN_Str8_HasData(path)) - return result; - - struct stat file_stat; - if (lstat(path.data, &file_stat) != -1) { - result.exists = true; - result.size = file_stat.st_size; - result.last_access_time_in_s = file_stat.st_atime; - result.last_write_time_in_s = file_stat.st_mtime; - // TODO(dn): Seems linux does not support creation time via stat. We - // shoddily deal with this. - result.create_time_in_s = DN_Min(result.last_access_time_in_s, result.last_write_time_in_s); - - if (S_ISDIR(file_stat.st_mode)) - result.type = DN_OSPathInfoType_Directory; - else if (S_ISREG(file_stat.st_mode)) - result.type = DN_OSPathInfoType_File; - } - return result; -} - -DN_API bool DN_OS_PathDelete(DN_Str8 path) -{ - bool result = false; - if (DN_Str8_HasData(path)) - result = remove(path.data) == 0; - return result; -} - -DN_API bool DN_OS_FileExists(DN_Str8 path) -{ - bool result = false; - if (!DN_Str8_HasData(path)) - return result; - - struct stat stat_result; - if (lstat(path.data, &stat_result) != -1) - result = S_ISREG(stat_result.st_mode) || S_ISLNK(stat_result.st_mode); - return result; -} - -DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) +DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) { bool result = false; #if defined(DN_PLATFORM_EMSCRIPTEN) @@ -6778,7 +6794,7 @@ DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi return result; } -DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) +DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) { // See: https://github.com/gingerBill/gb/blob/master/gb.h bool result = false; @@ -6786,7 +6802,7 @@ DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi if (link(src.data, dest.data) == -1) { // NOTE: Link can fail if we're trying to link across different volumes // so we fall back to a binary directory. - file_moved |= DN_OS_CopyFile(src, dest, overwrite, error); + file_moved |= DN_OS_FileCopy(src, dest, overwrite, error); } if (file_moved) { @@ -6806,108 +6822,6 @@ DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi return result; } -DN_API bool DN_OS_MakeDir(DN_Str8 path) -{ - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - bool result = true; - - // TODO(doyle): Implement this without using the path indexes, it's not - // necessary. See Windows implementation. - DN_USize path_indexes_size = 0; - uint16_t path_indexes[64] = {}; - - DN_Str8 copy = DN_Str8_Copy(tmem.arena, path); - for (DN_USize index = copy.size - 1; index < copy.size; index--) { - bool first_char = index == (copy.size - 1); - char ch = copy.data[index]; - if (ch == '/' || first_char) { - char temp = copy.data[index]; - - if (!first_char) - copy.data[index] = 0; // Temporarily null terminate it - - bool is_file = DN_OS_FileExists(copy); - - if (!first_char) - copy.data[index] = temp; // Undo null termination - - if (is_file) { - // NOTE: There's something that exists in at this path, but - // it's not a directory. This request to make a directory is - // invalid. - return false; - } else if (DN_OS_DirExists(copy)) { - // NOTE: We found a directory, we can stop here and start - // building up all the directories that didn't exist up to - // this point. - break; - } else { - // NOTE: There's nothing that exists at this path, we can - // create a directory here - path_indexes[path_indexes_size++] = DN_CAST(uint16_t) index; - } - } - } - - for (DN_USize index = path_indexes_size - 1; result && index < path_indexes_size; index--) { - uint16_t path_index = path_indexes[index]; - char temp = copy.data[path_index]; - - if (index != 0) - copy.data[path_index] = 0; - result |= mkdir(copy.data, 0774) == 0; - if (index != 0) - copy.data[path_index] = temp; - } - return result; -} - -DN_API bool DN_OS_DirExists(DN_Str8 path) -{ - bool result = false; - if (!DN_Str8_HasData(path)) - return result; - - struct stat stat_result; - if (lstat(path.data, &stat_result) != -1) - result = S_ISDIR(stat_result.st_mode); - return result; -} - -DN_API bool DN_OS_DirIterate(DN_Str8 path, DN_OSDirIterator *it) -{ - if (!it->handle) { - it->handle = opendir(path.data); - if (!it->handle) - return false; - } - - struct dirent *entry; - for (;;) { - entry = readdir(DN_CAST(DIR *) it->handle); - if (entry == NULL) - break; - - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - DN_USize name_size = DN_CStr8_Size(entry->d_name); - DN_USize clamped_size = DN_Min(sizeof(it->buffer) - 1, name_size); - DN_AssertF(name_size == clamped_size, "name: %s, name_size: %zu, clamped_size: %zu", entry->d_name, name_size, clamped_size); - DN_Memcpy(it->buffer, entry->d_name, clamped_size); - it->buffer[clamped_size] = 0; - it->file_name = DN_Str8_Init(it->buffer, clamped_size); - return true; - } - - closedir(DN_CAST(DIR *) it->handle); - it->handle = NULL; - it->file_name = {}; - it->buffer[0] = 0; - return false; -} - -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, @@ -7039,9 +6953,152 @@ DN_API void DN_OS_FileClose(DN_OSFile *file) fclose(DN_CAST(FILE *) file->handle); *file = {}; } -#endif // !defined(DN_NO_OS_FILE_API) -// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// +DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) +{ + DN_OSPathInfo result = {}; + if (!DN_Str8_HasData(path)) + return result; + + struct stat file_stat; + if (lstat(path.data, &file_stat) != -1) { + result.exists = true; + result.size = file_stat.st_size; + result.last_access_time_in_s = file_stat.st_atime; + result.last_write_time_in_s = file_stat.st_mtime; + // TODO(dn): Seems linux does not support creation time via stat. We + // shoddily deal with this. + result.create_time_in_s = DN_Min(result.last_access_time_in_s, result.last_write_time_in_s); + + if (S_ISDIR(file_stat.st_mode)) + result.type = DN_OSPathInfoType_Directory; + else if (S_ISREG(file_stat.st_mode)) + result.type = DN_OSPathInfoType_File; + } + return result; +} + +DN_API bool DN_OS_PathDelete(DN_Str8 path) +{ + bool result = false; + if (DN_Str8_HasData(path)) + result = remove(path.data) == 0; + return result; +} + +DN_API bool DN_OS_PathIsFile(DN_Str8 path) +{ + bool result = false; + if (!DN_Str8_HasData(path)) + return result; + + struct stat stat_result; + if (lstat(path.data, &stat_result) != -1) + result = S_ISREG(stat_result.st_mode) || S_ISLNK(stat_result.st_mode); + return result; +} + +DN_API bool DN_OS_PathIsDir(DN_Str8 path) +{ + bool result = false; + if (!DN_Str8_HasData(path)) + return result; + + struct stat stat_result; + if (lstat(path.data, &stat_result) != -1) + result = S_ISDIR(stat_result.st_mode); + return result; +} + +DN_API bool DN_OS_PathMakeDir(DN_Str8 path) +{ + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + bool result = true; + + // TODO(doyle): Implement this without using the path indexes, it's not + // necessary. See Windows implementation. + DN_USize path_indexes_size = 0; + uint16_t path_indexes[64] = {}; + + DN_Str8 copy = DN_Str8_FromStr8(tmem.arena, path); + for (DN_USize index = copy.size - 1; index < copy.size; index--) { + bool first_char = index == (copy.size - 1); + char ch = copy.data[index]; + if (ch == '/' || first_char) { + char temp = copy.data[index]; + + if (!first_char) + copy.data[index] = 0; // Temporarily null terminate it + + bool is_file = DN_OS_PathIsFile(copy); + + if (!first_char) + copy.data[index] = temp; // Undo null termination + + if (is_file) { + // NOTE: There's something that exists in at this path, but + // it's not a directory. This request to make a directory is + // invalid. + return false; + } else if (DN_OS_PathIsDir(copy)) { + // NOTE: We found a directory, we can stop here and start + // building up all the directories that didn't exist up to + // this point. + break; + } else { + // NOTE: There's nothing that exists at this path, we can + // create a directory here + path_indexes[path_indexes_size++] = DN_CAST(uint16_t) index; + } + } + } + + for (DN_USize index = path_indexes_size - 1; result && index < path_indexes_size; index--) { + uint16_t path_index = path_indexes[index]; + char temp = copy.data[path_index]; + + if (index != 0) + copy.data[path_index] = 0; + result |= mkdir(copy.data, 0774) == 0; + if (index != 0) + copy.data[path_index] = temp; + } + return result; +} + +DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it) +{ + if (!it->handle) { + it->handle = opendir(path.data); + if (!it->handle) + return false; + } + + struct dirent *entry; + for (;;) { + entry = readdir(DN_CAST(DIR *) it->handle); + if (entry == NULL) + break; + + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + + DN_USize name_size = DN_CStr8_Size(entry->d_name); + DN_USize clamped_size = DN_Min(sizeof(it->buffer) - 1, name_size); + DN_AssertF(name_size == clamped_size, "name: %s, name_size: %zu, clamped_size: %zu", entry->d_name, name_size, clamped_size); + DN_Memcpy(it->buffer, entry->d_name, clamped_size); + it->buffer[clamped_size] = 0; + it->file_name = DN_Str8_Init(it->buffer, clamped_size); + return true; + } + + closedir(DN_CAST(DIR *) it->handle); + it->handle = NULL; + it->file_name = {}; + it->buffer[0] = 0; + return false; +} + DN_API void DN_OS_Exit(int32_t exit_code) { exit(DN_CAST(int) exit_code); @@ -7275,7 +7332,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, for (DN_ForIndexU(arg_index, cmd_line.size)) { DN_Str8 arg = cmd_line.data[arg_index]; - argv[arg_index] = DN_Str8_Copy(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated + argv[arg_index] = DN_Str8_FromStr8(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated } // NOTE: Change the working directory if there is one @@ -7293,7 +7350,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, if (args->working_dir.size) { prev_working_dir = get_current_dir_name(); - DN_Str8 working_dir = DN_Str8_Copy(tmem.arena, args->working_dir); + DN_Str8 working_dir = DN_Str8_FromStr8(tmem.arena, args->working_dir); if (chdir(working_dir.data) == -1) { result.os_error_code = errno; DN_OS_ErrSinkAppendF( @@ -7659,7 +7716,7 @@ DN_API void DN_Posix_ThreadSetName(DN_Str8 name) (void)name; #else DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); - DN_Str8 copy = DN_Str8_Copy(tmem.arena, name); + DN_Str8 copy = DN_Str8_FromStr8(tmem.arena, name); pthread_t thread = pthread_self(); pthread_setname_np(thread, (char *)copy.data); #endif @@ -7683,7 +7740,7 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus() if (!file.error) { char buf[256]; - DN_Str8Builder builder = DN_Str8Builder_InitFromTLS(); + DN_Str8Builder builder = DN_Str8Builder_FromTLS(); for (;;) { DN_OSFileRead read = DN_OS_FileRead(&file, buf, sizeof(buf), nullptr); if (!read.success || read.bytes_read == 0) @@ -8182,7 +8239,6 @@ DN_API DN_U64 DN_OS_PerfCounterNow() return result; } -#if !defined(DN_NO_OS_FILE_API) static DN_U64 DN_W32_FileTimeToSeconds_(FILETIME const *time) { ULARGE_INTEGER time_large_int = {}; @@ -8192,73 +8248,7 @@ static DN_U64 DN_W32_FileTimeToSeconds_(FILETIME const *time) return result; } -DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) -{ - DN_OSPathInfo result = {}; - if (!DN_Str8_HasData(path)) - return result; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); - - WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; - if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) - return result; - - result.exists = true; - result.create_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftCreationTime); - result.last_access_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastAccessTime); - result.last_write_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastWriteTime); - - LARGE_INTEGER large_int = {}; - large_int.u.HighPart = DN_CAST(int32_t) attrib_data.nFileSizeHigh; - large_int.u.LowPart = attrib_data.nFileSizeLow; - result.size = (DN_U64)large_int.QuadPart; - - if (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { - if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - result.type = DN_OSPathInfoType_Directory; - else - result.type = DN_OSPathInfoType_File; - } - - return result; -} - -DN_API bool DN_OS_PathDelete(DN_Str8 path) -{ - bool result = false; - if (!DN_Str8_HasData(path)) - return result; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); - if (path16.size) { - result = DeleteFileW(path16.data); - if (!result) - result = RemoveDirectoryW(path16.data); - } - return result; -} - -DN_API bool DN_OS_FileExists(DN_Str8 path) -{ - bool result = false; - if (!DN_Str8_HasData(path)) - return result; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); - if (path16.size) { - WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; - if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) - result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && - !(attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); - } - return result; -} - -DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err) +DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err) { bool result = false; DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); @@ -8281,12 +8271,12 @@ DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi return result; } -DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err) +DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err) { - bool result = false; + bool result = false; DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 src16 = DN_W32_Str8ToStr16(tmem.arena, src); - DN_Str16 dest16 = DN_W32_Str8ToStr16(tmem.arena, dest); + DN_Str16 src16 = DN_W32_Str8ToStr16(tmem.arena, src); + DN_Str16 dest16 = DN_W32_Str8ToStr16(tmem.arena, dest); unsigned long flags = MOVEFILE_COPY_ALLOWED; if (overwrite) @@ -8296,128 +8286,16 @@ DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi if (!result) { DN_W32Error win_error = DN_W32_LastError(tmem.arena); DN_OS_ErrSinkAppendF(err, - win_error.code, - "Failed to move file '%.*s' to '%.*s': (%u) %.*s", - DN_STR_FMT(src), - DN_STR_FMT(dest), - win_error.code, - DN_STR_FMT(win_error.msg)); + win_error.code, + "Failed to move file '%.*s' to '%.*s': (%u) %.*s", + DN_STR_FMT(src), + DN_STR_FMT(dest), + win_error.code, + DN_STR_FMT(win_error.msg)); } return result; } -DN_API bool DN_OS_MakeDir(DN_Str8 path) -{ - bool result = true; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); - - // NOTE: Go back from the end of the string to all the directories in the - // string, and try to create them. Since Win32 API cannot create - // intermediate directories that don't exist in a path we need to go back - // and record all the directories until we encounter one that exists. - // - // From that point onwards go forwards and make all the directories - // inbetween by null-terminating the string temporarily, creating the - // directory and so forth until we reach the end. - // - // If we find a file at some point in the path we fail out because the - // series of directories can not be made if a file exists with the same - // name. - for (DN_USize index = 0; index < path16.size; index++) { - bool first_char = index == (path16.size - 1); - wchar_t ch = path16.data[index]; - if (ch == '/' || ch == '\\' || first_char) { - wchar_t temp = path16.data[index]; - if (!first_char) - path16.data[index] = 0; // Temporarily null terminate it - - WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; - bool successful = GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data); // Check - - if (successful) { - if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - // NOTE: The directory exists, continue iterating the path - } else { - // NOTE: There's some kind of file that exists at the path - // but it's not a directory. This request to make a - // directory is invalid. - return false; - } - } else { - // NOTE: There's nothing that exists at this path, we can create - // a directory here - result |= (CreateDirectoryW(path16.data, nullptr) == 0); - } - - if (!first_char) - path16.data[index] = temp; // Undo null termination - } - } - return result; -} - -DN_API bool DN_OS_DirExists(DN_Str8 path) -{ - bool result = false; - if (!DN_Str8_HasData(path)) - return result; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); - if (path16.size) { - WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; - if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) - result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && - (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); - } - - return result; -} - -DN_API bool DN_OS_DirIterate(DN_Str8 path, DN_OSDirIterator *it) -{ - if (!DN_Str8_HasData(path) || !it || path.size <= 0) - return false; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_W32FolderIteratorW wide_it = {}; - DN_Str16 path16 = {}; - if (it->handle) { - wide_it.handle = it->handle; - } else { - bool needs_asterisks = DN_Str8_EndsWith(path, DN_STR8("\\")) || - DN_Str8_EndsWith(path, DN_STR8("/")); - bool has_glob = DN_Str8_EndsWith(path, DN_STR8("\\*")) || - DN_Str8_EndsWith(path, DN_STR8("/*")); - - DN_Str8 adjusted_path = path; - if (!has_glob) { - // NOTE: We are missing the glob for enumerating the files, we will - // add those characters in this branch, so overwrite the null - // character, add the glob and re-null terminate the buffer. - if (needs_asterisks) - adjusted_path = DN_OS_PathF(tmem.arena, "%.*s*", DN_STR_FMT(path)); - else - adjusted_path = DN_OS_PathF(tmem.arena, "%.*s/*", DN_STR_FMT(path)); - } - - path16 = DN_W32_Str8ToStr16(tmem.arena, adjusted_path); - if (path16.size <= 0) // Conversion error - return false; - } - - bool result = DN_W32_DirWIterate(path16, &wide_it); - it->handle = wide_it.handle; - if (result) { - int size = DN_W32_Str16ToStr8Buffer(wide_it.file_name, it->buffer, DN_ArrayCountU(it->buffer)); - it->file_name = DN_Str8_Init(it->buffer, size); - } - - return result; -} - -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 access, DN_OSErrSink *err) { DN_OSFile result = {}; @@ -8564,7 +8442,184 @@ DN_API void DN_OS_FileClose(DN_OSFile *file) CloseHandle(file->handle); *file = {}; } -#endif // !defined(DN_NO_OS_FILE_API) + +DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) +{ + DN_OSPathInfo result = {}; + if (!DN_Str8_HasData(path)) + return result; + + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + + WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; + if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) + return result; + + result.exists = true; + result.create_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftCreationTime); + result.last_access_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastAccessTime); + result.last_write_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastWriteTime); + + LARGE_INTEGER large_int = {}; + large_int.u.HighPart = DN_CAST(int32_t) attrib_data.nFileSizeHigh; + large_int.u.LowPart = attrib_data.nFileSizeLow; + result.size = (DN_U64)large_int.QuadPart; + + if (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { + if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + result.type = DN_OSPathInfoType_Directory; + else + result.type = DN_OSPathInfoType_File; + } + + return result; +} + +DN_API bool DN_OS_PathDelete(DN_Str8 path) +{ + bool result = false; + if (!DN_Str8_HasData(path)) + return result; + + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + if (path16.size) { + result = DeleteFileW(path16.data); + if (!result) + result = RemoveDirectoryW(path16.data); + } + return result; +} + +DN_API bool DN_OS_PathIsFile(DN_Str8 path) +{ + bool result = false; + if (!DN_Str8_HasData(path)) + return result; + + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + if (path16.size) { + WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; + if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) + result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && + !(attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + } + return result; +} + +DN_API bool DN_OS_PathIsDir(DN_Str8 path) +{ + bool result = false; + if (!DN_Str8_HasData(path)) + return result; + + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + if (path16.size) { + WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; + if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) + result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && + (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + } + + return result; +} + +DN_API bool DN_OS_PathMakeDir(DN_Str8 path) +{ + bool result = true; + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + + // NOTE: Go back from the end of the string to all the directories in the + // string, and try to create them. Since Win32 API cannot create + // intermediate directories that don't exist in a path we need to go back + // and record all the directories until we encounter one that exists. + // + // From that point onwards go forwards and make all the directories + // inbetween by null-terminating the string temporarily, creating the + // directory and so forth until we reach the end. + // + // If we find a file at some point in the path we fail out because the + // series of directories can not be made if a file exists with the same + // name. + for (DN_USize index = 0; index < path16.size; index++) { + bool first_char = index == (path16.size - 1); + wchar_t ch = path16.data[index]; + if (ch == '/' || ch == '\\' || first_char) { + wchar_t temp = path16.data[index]; + if (!first_char) + path16.data[index] = 0; // Temporarily null terminate it + + WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; + bool successful = GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data); // Check + + if (successful) { + if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + // NOTE: The directory exists, continue iterating the path + } else { + // NOTE: There's some kind of file that exists at the path + // but it's not a directory. This request to make a + // directory is invalid. + return false; + } + } else { + // NOTE: There's nothing that exists at this path, we can create + // a directory here + result |= (CreateDirectoryW(path16.data, nullptr) == 0); + } + + if (!first_char) + path16.data[index] = temp; // Undo null termination + } + } + return result; +} + +DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it) +{ + if (!DN_Str8_HasData(path) || !it || path.size <= 0) + return false; + + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_W32FolderIteratorW wide_it = {}; + DN_Str16 path16 = {}; + if (it->handle) { + wide_it.handle = it->handle; + } else { + bool needs_asterisks = DN_Str8_EndsWith(path, DN_STR8("\\")) || + DN_Str8_EndsWith(path, DN_STR8("/")); + bool has_glob = DN_Str8_EndsWith(path, DN_STR8("\\*")) || + DN_Str8_EndsWith(path, DN_STR8("/*")); + + DN_Str8 adjusted_path = path; + if (!has_glob) { + // NOTE: We are missing the glob for enumerating the files, we will + // add those characters in this branch, so overwrite the null + // character, add the glob and re-null terminate the buffer. + if (needs_asterisks) + adjusted_path = DN_OS_PathF(tmem.arena, "%.*s*", DN_STR_FMT(path)); + else + adjusted_path = DN_OS_PathF(tmem.arena, "%.*s/*", DN_STR_FMT(path)); + } + + path16 = DN_W32_Str8ToStr16(tmem.arena, adjusted_path); + if (path16.size <= 0) // Conversion error + return false; + } + + bool result = DN_W32_DirWIterate(path16, &wide_it); + it->handle = wide_it.handle; + if (result) { + int size = DN_W32_Str16ToStr8Buffer(wide_it.file_name, it->buffer, DN_ArrayCountU(it->buffer)); + it->file_name = DN_Str8_Init(it->buffer, size); + } + + return result; +} + // NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// DN_API void DN_OS_Exit(int32_t exit_code) @@ -10597,7 +10652,7 @@ void DN_Docs_Demo() // NOTE: My error sinks are thread-local, so the returned 'error' is // the same as the 'error' value above. DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); - DN_OS_WriteAll(DN_STR8("/path/to/another/file"), DN_STR8("123"), error); + DN_OS_FileWriteAll(DN_STR8("/path/to/another/file"), DN_STR8("123"), error); DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to another file"); } @@ -10726,7 +10781,7 @@ void DN_Docs_Demo() // NOTE: DN_OS_DirIterate ///////////////////////////////////////////////////////////////////// // // Iterate the files within the passed in folder - for (DN_OSDirIterator it = {}; DN_OS_DirIterate(DN_STR8("."), &it);) { + for (DN_OSDirIterator it = {}; DN_OS_PathIterateDir(DN_STR8("."), &it);) { // printf("%.*s\n", DN_STR_FMT(it.file_name)); } @@ -10748,7 +10803,7 @@ void DN_Docs_Demo() if (0) { DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); - DN_OS_WriteAllSafe(/*path*/ DN_STR8("C:/Home/my.txt"), /*buffer*/ DN_STR8("Hello world"), error); + DN_OS_FileWriteAllSafe(/*path*/ DN_STR8("C:/Home/my.txt"), /*buffer*/ DN_STR8("Hello world"), error); DN_OS_ErrSinkEndAndLogErrorF(error, ""); } @@ -11482,9 +11537,380 @@ void DN_Docs_Demo() DN_MSVC_WARNING_POP #define DN_MATH_CPP -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: DN_V2I32 +// DN: Single header generator commented out this header => #include "dn_math.h" +#if !defined(DN_MATH_H) +#define DN_MATH_H + +// DN: Single header generator commented out this header => #include "../dn_base_inc.h" + +DN_MSVC_WARNING_PUSH +DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union +union DN_V2I32 +{ + struct { DN_I32 x, y; }; + struct { DN_I32 w, h; }; + DN_I32 data[2]; +}; + +union DN_V2U16 +{ + struct { DN_U16 x, y; }; + struct { DN_U16 w, h; }; + DN_U16 data[2]; +}; + +union DN_V2U32 +{ + struct { DN_U32 x, y; }; + struct { DN_U32 w, h; }; + DN_U32 data[2]; +}; + +union DN_V2F32 +{ + struct { DN_F32 x, y; }; + struct { DN_F32 w, h; }; + DN_F32 data[2]; +}; + +union DN_V3F32 +{ + struct { DN_F32 x, y, z; }; + struct { DN_F32 r, g, b; }; + DN_F32 data[3]; +}; + + +union DN_V4F32 +{ + struct { DN_F32 x, y, z, w; }; + struct { DN_F32 r, g, b, a; }; + #if !defined(DN_NO_V3) + DN_V3F32 rgb; + DN_V3F32 xyz; + #endif + DN_F32 data[4]; +}; +DN_MSVC_WARNING_POP + +struct DN_M4 +{ + DN_F32 columns[4][4]; // Column major matrix +}; + +union DN_M2x3 +{ + DN_F32 e[6]; + DN_F32 row[2][3]; +}; + +struct DN_Rect +{ + DN_V2F32 pos, size; +}; + +struct DN_RectMinMax +{ + DN_V2F32 min, max; +}; + +enum DN_RectCutClip +{ + DN_RectCutClip_No, + DN_RectCutClip_Yes, +}; + +enum DN_RectCutSide +{ + DN_RectCutSide_Left, + DN_RectCutSide_Right, + DN_RectCutSide_Top, + DN_RectCutSide_Bottom, +}; + +struct DN_RectCut +{ + DN_Rect* rect; + DN_RectCutSide side; +}; + +struct DN_RaycastLineIntersectV2Result +{ + bool hit; // True if there was an intersection, false if the lines are parallel + DN_F32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)` + DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` +}; + +#define DN_V2I32_Zero DN_Literal(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} +#define DN_V2I32_One DN_Literal(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} +#define DN_V2I32_From1N(x) DN_Literal(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} +#define DN_V2I32_From2N(x, y) DN_Literal(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} +#define DN_V2I32_InitV2(xy) DN_Literal(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} + +DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API DN_V2I32 operator- (DN_V2I32 lhs); +DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs); +DN_API DN_V2I32 operator* (DN_V2I32 lhs, int32_t rhs); +DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs); +DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs); +DN_API DN_V2I32 operator/ (DN_V2I32 lhs, int32_t rhs); +DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_V2I32 rhs); +DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, DN_F32 rhs); +DN_API DN_V2I32 & operator*= (DN_V2I32& lhs, int32_t rhs); +DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_V2I32 rhs); +DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, DN_F32 rhs); +DN_API DN_V2I32 & operator/= (DN_V2I32& lhs, int32_t rhs); +DN_API DN_V2I32 & operator-= (DN_V2I32& lhs, DN_V2I32 rhs); +DN_API DN_V2I32 & operator+= (DN_V2I32& lhs, DN_V2I32 rhs); + +DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN_V2I32 b); +DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); +DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); + +#define DN_V2U16_Zero DN_Literal(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} +#define DN_V2U16_One DN_Literal(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} +#define DN_V2U16_From1N(x) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} +#define DN_V2U16_From2N(x, y) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} + +DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs); +DN_API DN_V2U16 operator* (DN_V2U16 lhs, int32_t rhs); +DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs); +DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs); +DN_API DN_V2U16 operator/ (DN_V2U16 lhs, int32_t rhs); +DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_V2U16 rhs); +DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, DN_F32 rhs); +DN_API DN_V2U16 & operator*= (DN_V2U16& lhs, int32_t rhs); +DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_V2U16 rhs); +DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_F32 rhs); +DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, int32_t rhs); +DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); +DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); + +#define DN_V2F32_Zero DN_Literal(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} +#define DN_V2F32_One DN_Literal(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} +#define DN_V2F32_From1N(x) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} +#define DN_V2F32_From2N(x, y) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} +#define DN_V2F32_FromV2I32(xy) DN_Literal(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} + +DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs); + +DN_API DN_V2F32 operator- (DN_V2F32 lhs); +DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs); +DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs); +DN_API DN_V2F32 operator- (DN_V2F32 lhs, int32_t rhs); + +DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs); +DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs); +DN_API DN_V2F32 operator+ (DN_V2F32 lhs, int32_t rhs); + +DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs); +DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs); +DN_API DN_V2F32 operator* (DN_V2F32 lhs, int32_t rhs); + +DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs); +DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs); +DN_API DN_V2F32 operator/ (DN_V2F32 lhs, int32_t rhs); + +DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2F32 rhs); +DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_V2I32 rhs); +DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, DN_F32 rhs); +DN_API DN_V2F32 & operator*= (DN_V2F32& lhs, int32_t rhs); + +DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2F32 rhs); +DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_V2I32 rhs); +DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, DN_F32 rhs); +DN_API DN_V2F32 & operator/= (DN_V2F32& lhs, int32_t rhs); + +DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2F32 rhs); +DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_V2I32 rhs); +DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, DN_F32 rhs); +DN_API DN_V2F32 & operator-= (DN_V2F32& lhs, int32_t rhs); + +DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2F32 rhs); +DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_V2I32 rhs); +DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, DN_F32 rhs); +DN_API DN_V2F32 & operator+= (DN_V2F32& lhs, int32_t rhs); + +DN_API DN_V2F32 DN_V2F32_Min (DN_V2F32 a, DN_V2F32 b); +DN_API DN_V2F32 DN_V2F32_Max (DN_V2F32 a, DN_V2F32 b); +DN_API DN_V2F32 DN_V2F32_Abs (DN_V2F32 a); +DN_API DN_F32 DN_V2F32_Dot (DN_V2F32 a, DN_V2F32 b); +DN_API DN_F32 DN_V2F32_LengthSq2V2 (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API bool DN_V2F32_LengthSqIsWithin2V2 (DN_V2F32 lhs, DN_V2F32 rhs, DN_F32 within_amount_sq); +DN_API DN_F32 DN_V2F32_Length2V2 (DN_V2F32 lhs, DN_V2F32 rhs); +DN_API DN_F32 DN_V2F32_LengthSq (DN_V2F32 lhs); +DN_API DN_F32 DN_V2F32_Length (DN_V2F32 lhs); +DN_API DN_V2F32 DN_V2F32_Normalise (DN_V2F32 a); +DN_API DN_V2F32 DN_V2F32_Perpendicular (DN_V2F32 a); +DN_API DN_V2F32 DN_V2F32_Reflect (DN_V2F32 in, DN_V2F32 surface); +DN_API DN_F32 DN_V2F32_Area (DN_V2F32 a); + +#define DN_V3F32_From1N(x) DN_Literal(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} +#define DN_V3F32_From3N(x, y, z) DN_Literal(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} +#define DN_V3F32_FromV2F32And1N(xy, z) DN_Literal(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} + +DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API DN_V3F32 operator- (DN_V3F32 lhs); +DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs); +DN_API DN_V3F32 operator* (DN_V3F32 lhs, int32_t rhs); +DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs); +DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs); +DN_API DN_V3F32 operator/ (DN_V3F32 lhs, int32_t rhs); +DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_V3F32 rhs); +DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, DN_F32 rhs); +DN_API DN_V3F32 & operator*= (DN_V3F32 &lhs, int32_t rhs); +DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_V3F32 rhs); +DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, DN_F32 rhs); +DN_API DN_V3F32 & operator/= (DN_V3F32 &lhs, int32_t rhs); +DN_API DN_V3F32 & operator-= (DN_V3F32 &lhs, DN_V3F32 rhs); +DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_V3F32 rhs); +DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a); +DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a); +DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a); + +DN_U32 const DN_V4_R_MASK_U32 = 0xFF000000; +DN_U32 const DN_V4_G_MASK_U32 = 0x00FF0000; +DN_U32 const DN_V4_B_MASK_U32 = 0x0000FF00; +DN_U32 const DN_V4_A_MASK_U32 = 0x000000FF; + +#define DN_V4F32_From1N(x) DN_Literal(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} +#define DN_V4F32_From4N(x, y, z, w) DN_Literal(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} +#define DN_V4F32_FromV3And1N(xyz, w) DN_Literal(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} +#define DN_V4F32_FromRGBAU8(r, g, b, a) DN_Literal(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, a / 255.f}} +#define DN_V4F32_FromRGBU8(r, g, b) DN_Literal(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, 1.f}} +DN_API DN_V4F32 DN_V4F32_FromRGBU32(DN_U32 u32); +DN_API DN_V4F32 DN_V4F32_FromRGBAU32(DN_U32 u32); +#define DN_V4F32_FromV4Alpha(v4, alpha) DN_V4F32_FromV3And1N(v4.xyz, alpha) +DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API DN_V4F32 operator- (DN_V4F32 lhs); +DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs); +DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs); +DN_API DN_V4F32 operator* (DN_V4F32 lhs, int32_t rhs); +DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs); +DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_V4F32 rhs); +DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_F32 rhs); +DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, int32_t rhs); +DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs); +DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs); +DN_API DN_F32 DN_V4F32_Dot (DN_V4F32 a, DN_V4F32 b); + +DN_API DN_M4 DN_M4_Identity (); +DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z); +DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz); +DN_API DN_M4 DN_M4_TranslateF (DN_F32 x, DN_F32 y, DN_F32 z); +DN_API DN_M4 DN_M4_Translate (DN_V3F32 xyz); +DN_API DN_M4 DN_M4_Transpose (DN_M4 mat); +DN_API DN_M4 DN_M4_Rotate (DN_V3F32 axis, DN_F32 radians); +DN_API DN_M4 DN_M4_Orthographic (DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far); +DN_API DN_M4 DN_M4_Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far); +DN_API DN_M4 DN_M4_Add (DN_M4 lhs, DN_M4 rhs); +DN_API DN_M4 DN_M4_Sub (DN_M4 lhs, DN_M4 rhs); +DN_API DN_M4 DN_M4_Mul (DN_M4 lhs, DN_M4 rhs); +DN_API DN_M4 DN_M4_Div (DN_M4 lhs, DN_M4 rhs); +DN_API DN_M4 DN_M4_AddF (DN_M4 lhs, DN_F32 rhs); +DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_F32 rhs); +DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs); +DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs); +DN_API DN_Str8x256 DN_M4_ColumnMajorString (DN_M4 mat); + +DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs); +DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); +DN_API DN_M2x3 DN_M2x3_Identity (); +DN_API DN_M2x3 DN_M2x3_Translate (DN_V2F32 offset); +DN_API DN_M2x3 DN_M2x3_Scale (DN_V2F32 scale); +DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians); +DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); +DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y); +DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2); + +#define DN_Rect_From2V2(pos, size) DN_Literal(DN_Rect){(pos), (size)} +#define DN_Rect_From4N(x, y, w, h) DN_Literal(DN_Rect){DN_Literal(DN_V2F32){{x, y}}, DN_Literal(DN_V2F32){{w, h}}} + +DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); +DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); +DN_API bool DN_Rect_ContainsPoint (DN_Rect rect, DN_V2F32 p); +DN_API bool DN_Rect_ContainsRect (DN_Rect a, DN_Rect b); +DN_API DN_Rect DN_Rect_Expand (DN_Rect a, DN_F32 amount); +DN_API DN_Rect DN_Rect_ExpandV2 (DN_Rect a, DN_V2F32 amount); +DN_API bool DN_Rect_Intersects (DN_Rect a, DN_Rect b); +DN_API DN_Rect DN_Rect_Intersection (DN_Rect a, DN_Rect b); +DN_API DN_Rect DN_Rect_Union (DN_Rect a, DN_Rect b); +DN_API DN_RectMinMax DN_Rect_MinMax (DN_Rect a); +DN_API DN_F32 DN_Rect_Area (DN_Rect a); +DN_API DN_V2F32 DN_Rect_InterpolatedPoint (DN_Rect rect, DN_V2F32 t01); +DN_API DN_V2F32 DN_Rect_TopLeft (DN_Rect rect); +DN_API DN_V2F32 DN_Rect_TopRight (DN_Rect rect); +DN_API DN_V2F32 DN_Rect_BottomLeft (DN_Rect rect); +DN_API DN_V2F32 DN_Rect_BottomRight (DN_Rect rect); + +DN_API DN_Rect DN_Rect_CutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); +DN_API DN_Rect DN_Rect_CutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); +DN_API DN_Rect DN_Rect_CutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); +DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip); + +#define DN_Rect_CutLeft(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_Yes) +#define DN_Rect_CutRight(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_Yes) +#define DN_Rect_CutTop(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_Yes) +#define DN_Rect_CutBottom(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_Yes) + +#define DN_Rect_CutLeftNoClip(rect, amount) DN_Rect_CutLeftClip(rect, amount, DN_RectCutClip_No) +#define DN_Rect_CutRightNoClip(rect, amount) DN_Rect_CutRightClip(rect, amount, DN_RectCutClip_No) +#define DN_Rect_CutTopNoClip(rect, amount) DN_Rect_CutTopClip(rect, amount, DN_RectCutClip_No) +#define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No) + +DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip); +#define DN_RectCut_Init(rect, side) DN_Literal(DN_RectCut){rect, side} +#define DN_RectCut_Left(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Left} +#define DN_RectCut_Right(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Right} +#define DN_RectCut_Top(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Top} +#define DN_RectCut_Bottom(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Bottom} + +DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b); +DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b); +DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); + +#endif // !defined(DN_MATH_H) + DN_API bool operator==(DN_V2I32 lhs, DN_V2I32 rhs) { bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); @@ -11641,7 +12067,6 @@ DN_API DN_V2I32 DN_V2I32_Abs(DN_V2I32 a) return result; } -// NOTE: DN_V2U16 DN_API bool operator!=(DN_V2U16 lhs, DN_V2U16 rhs) { bool result = !(lhs == rhs); @@ -11774,7 +12199,6 @@ DN_API DN_V2U16 &operator+=(DN_V2U16 &lhs, DN_V2U16 rhs) return lhs; } -// NOTE: DN_V2 DN_API bool operator!=(DN_V2F32 lhs, DN_V2F32 rhs) { bool result = !(lhs == rhs); @@ -11811,7 +12235,6 @@ DN_API bool operator>(DN_V2F32 lhs, DN_V2F32 rhs) return result; } -// NOTE: DN_V2F32 operator- ////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 operator-(DN_V2F32 lhs) { DN_V2F32 result = DN_V2F32_From2N(-lhs.x, -lhs.y); @@ -11842,7 +12265,6 @@ DN_API DN_V2F32 operator-(DN_V2F32 lhs, int32_t rhs) return result; } -// NOTE: DN_V2F32 operator+ ////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2F32 rhs) { DN_V2F32 result = DN_V2F32_From2N(lhs.x + rhs.x, lhs.y + rhs.y); @@ -11867,7 +12289,6 @@ DN_API DN_V2F32 operator+(DN_V2F32 lhs, int32_t rhs) return result; } -// NOTE: DN_V2F32 operator* ////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2F32 rhs) { DN_V2F32 result = DN_V2F32_From2N(lhs.x * rhs.x, lhs.y * rhs.y); @@ -11892,7 +12313,6 @@ DN_API DN_V2F32 operator*(DN_V2F32 lhs, int32_t rhs) return result; } -// NOTE: DN_V2F32 operator/ ////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2F32 rhs) { DN_V2F32 result = DN_V2F32_From2N(lhs.x / rhs.x, lhs.y / rhs.y); @@ -11917,7 +12337,6 @@ DN_API DN_V2F32 operator/(DN_V2F32 lhs, int32_t rhs) return result; } -// NOTE: DN_V2F32 operator*/ ///////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs * rhs; @@ -11942,7 +12361,6 @@ DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, int32_t rhs) return lhs; } -// NOTE: DN_V2F32 operator// ///////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs / rhs; @@ -11967,7 +12385,6 @@ DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, int32_t rhs) return lhs; } -// NOTE: DN_V2F32 operator-/ ///////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs - rhs; @@ -11992,7 +12409,6 @@ DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, int32_t rhs) return lhs; } -// NOTE: DN_V2F32 operator+/ ///////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs + rhs; @@ -12164,10 +12580,7 @@ DN_API DN_F32 DN_V2F32_Area(DN_V2F32 a) DN_F32 result = a.w * a.h; return result; } -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// DN_API bool operator!=(DN_V3F32 lhs, DN_V3F32 rhs) { bool result = !(lhs == rhs); @@ -12325,10 +12738,7 @@ DN_API DN_V3F32 DN_V3_Normalise(DN_V3F32 a) DN_V3F32 result = a / length; return result; } -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// DN_API DN_V4F32 DN_V4F32_FromRGBU32(DN_U32 u32) { DN_U8 r = (DN_U8)(((u32 << 8) & DN_V4_R_MASK_U32) >> 24); @@ -12461,10 +12871,7 @@ DN_API DN_F32 DN_V4F32Dot(DN_V4F32 a, DN_V4F32 b) DN_F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); return result; } -#endif // !defined(DN_NO_V4) -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// DN_API DN_M4 DN_M4_Identity() { DN_M4 result = @@ -12713,9 +13120,7 @@ DN_API DN_Str8x256 DN_M4_ColumnMajorString(DN_M4 mat) return result; } -#endif // !defined(DN_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// DN_API bool operator==(DN_M2x3 const &lhs, DN_M2x3 const &rhs) { bool result = DN_Memcmp(lhs.e, rhs.e, sizeof(lhs.e[0]) * DN_ArrayCountU(lhs.e)) == 0; @@ -12837,8 +13242,6 @@ DN_API DN_V2F32 DN_M2x3_MulV2(DN_M2x3 m1, DN_V2F32 v2) return result; } -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// DN_API bool operator==(const DN_Rect &lhs, const DN_Rect &rhs) { bool result = (lhs.pos == rhs.pos) && (lhs.size == rhs.size); @@ -13043,9 +13446,6 @@ DN_API DN_V2F32 DN_Rect_BottomRight(DN_Rect rect) DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_From2N(1, 1)); return result; } -#endif // !defined(DN_NO_RECT) - -// NOTE: Raycast /////////////////////////////////////////////////////////////////////////////////// DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b) { @@ -13078,7 +13478,6 @@ DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origi return result; } -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 DN_Lerp_V2F32(DN_V2F32 a, DN_F32 t, DN_V2F32 b) { DN_V2F32 result = {}; diff --git a/Single_Header/dn_single_header.h b/Single_Header/dn_single_header.h index 26c471c..8596a47 100644 --- a/Single_Header/dn_single_header.h +++ b/Single_Header/dn_single_header.h @@ -1,4 +1,4 @@ -// Generated by the DN single header generator 2025-09-03 22:49:06 +// Generated by the DN single header generator 2025-09-07 18:46:16 #if !defined(DN_BASE_INC_H) #define DN_BASE_INC_H @@ -166,9 +166,9 @@ #endif #if defined(__cplusplus) - #define DN_LITERAL(T) T + #define DN_Literal(T) T #else - #define DN_LITERAL(T) (T) + #define DN_Literal(T) (T) #endif // NOTE: Thread Locals ///////////////////////////////////////////////////////////////////////////// @@ -893,6 +893,12 @@ enum DN_MemPage_ #define DN_ARENA_COMMIT_SIZE DN_Kilobytes(64) #endif +enum DN_Allocator +{ + DN_Allocator_Arena, + DN_Allocator_Pool, +}; + struct DN_ArenaBlock { DN_ArenaBlock *prev; @@ -3213,16 +3219,17 @@ DN_API DN_Str8 DN_Str8_Alloc (DN_Arena *aren DN_API DN_Str8 DN_Str8_FromCStr8 (char const *src); DN_API DN_Str8 DN_Str8_FromF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_Str8_FromFV (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_Str8 DN_Str8_FromFPool (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_Str8_FromStr8 (DN_Arena *arena, DN_Str8 string); DN_API bool DN_Str8_IsAll (DN_Str8 string, DN_Str8IsAll is_all); DN_API char * DN_Str8_End (DN_Str8 string); DN_API DN_Str8 DN_Str8_Slice (DN_Str8 string, DN_USize offset, DN_USize size); DN_API DN_Str8 DN_Str8_Advance (DN_Str8 string, DN_USize amount); DN_API DN_Str8 DN_Str8_NextLine (DN_Str8 string); -DN_API DN_Str8BSplitResult DN_Str8_BSplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); -DN_API DN_Str8BSplitResult DN_Str8_BSplit (DN_Str8 string, DN_Str8 find); -DN_API DN_Str8BSplitResult DN_Str8_BSplitLastArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); -DN_API DN_Str8BSplitResult DN_Str8_BSplitLast (DN_Str8 string, DN_Str8 find); +DN_API DN_Str8BSplitResult DN_Str8_BSplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); +DN_API DN_Str8BSplitResult DN_Str8_BSplit (DN_Str8 string, DN_Str8 find); +DN_API DN_Str8BSplitResult DN_Str8_BSplitLastArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); +DN_API DN_Str8BSplitResult DN_Str8_BSplitLast (DN_Str8 string, DN_Str8 find); DN_API DN_USize DN_Str8_Split (DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode); DN_API DN_Slice DN_Str8_SplitAlloc (DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode); DN_API DN_Str8FindResult DN_Str8_FindStr8Array (DN_Str8 string, DN_Str8 const *find, DN_USize find_size, DN_Str8EqCase eq_case); @@ -3841,8 +3848,8 @@ DN_API DN_CVTU64Str8 DN_CVT_Str8FromU64 (DN_U6 DN_API DN_CVTU64Bytes DN_CVT_BytesFromU64 (DN_U64 bytes, DN_CVTBytesType type); #define DN_CVT_BytesFromU64Auto(bytes) DN_CVT_BytesFromU64(bytes, DN_CVTBytesType_Auto) DN_API DN_Str8 DN_CVT_BytesStr8FromU64 (DN_Arena *arena, DN_U64 bytes, DN_CVTBytesType type); -#define DN_CVT_BytesStr8FromU64Auto(arena, bytes) DN_CVT_BytesStr8FromU64(arena, bytes, DN_CVTBytesType_Auto) #define DN_CVT_BytesStr8FromTLS(bytes, type) DN_CVT_BytesStr8FromU64(DN_OS_TLSTopArena(), bytes, type) +#define DN_CVT_BytesStr8FromU64Auto(arena, bytes) DN_CVT_BytesStr8FromU64(arena, bytes, DN_CVTBytesType_Auto) #define DN_CVT_BytesStr8FromU64AutoTLS(bytes) DN_CVT_BytesStr8FromU64(DN_OS_TLSTopArena(), bytes, DN_CVTBytesType_Auto) #define DN_CVT_BytesStr8FromU64Frame(bytes, type) DN_CVT_BytesStr8FromU64(DN_OS_TLSFrameArena(), bytes, type) #define DN_CVT_BytesStr8FromU64AutoFrame(bytes) DN_CVT_BytesStr8FromU64(DN_OS_TLSFrameArena(), bytes, DN_CVTBytesType_Auto) @@ -5372,6 +5379,9 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus(); #if !defined(DN_OS_TLS_H) #define DN_OS_TLS_H +// DN: Single header generator commented out this header => #include "../dn_base_inc.h" +// DN: Single header generator commented out this header => #include "../dn_os_inc.h" + // NOTE: DN_OSErrSink ///////////////////////////////////////////////////////////////////////////// enum DN_OSErrSinkMode { @@ -5458,7 +5468,6 @@ struct DN_OSTLSInitArgs DN_U64 err_sink_commit; }; -// NOTE: DN_OSTLS //////////////////////////////////////////////////////////////////////////////////// DN_API void DN_OS_TLSInit (DN_OSTLS *tls, DN_OSTLSInitArgs args); DN_API void DN_OS_TLSDeinit (DN_OSTLS *tls); DN_API DN_OSTLS * DN_OS_TLSGet (); @@ -5470,30 +5479,29 @@ DN_API void DN_OS_TLSPopArena (); DN_API DN_Arena * DN_OS_TLSTopArena (); DN_API void DN_OS_TLSBeginFrame (DN_Arena *frame_arena); DN_API DN_Arena * DN_OS_TLSFrameArena (); -#define DN_OS_TLSSaveCallSite do { DN_OS_TLSGet()->call_site = DN_CALL_SITE; } while (0) -#define DN_OS_TLSTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_No) -#define DN_OS_TLSPushTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_Yes) +#define DN_OS_TLSSaveCallSite do { DN_OS_TLSGet()->call_site = DN_CALL_SITE; } while (0) +#define DN_OS_TLSTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_No) +#define DN_OS_TLSPushTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_Yes) -// NOTE: DN_OS_ErrSink //////////////////////////////////////////////////////////////////////////// -DN_API DN_OSErrSink * DN_OS_ErrSinkBegin_ (DN_OSErrSinkMode mode, DN_CallSite call_site); -#define DN_OS_ErrSinkBegin(mode) DN_OS_ErrSinkBegin_(mode, DN_CALL_SITE) -#define DN_OS_ErrSinkBeginDefault() DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil) -DN_API bool DN_OS_ErrSinkHasError (DN_OSErrSink *err); -DN_API DN_OSErrSinkMsg *DN_OS_ErrSinkEnd (DN_Arena *arena, DN_OSErrSink *err); -DN_API DN_Str8 DN_OS_ErrSinkEndStr8 (DN_Arena *arena, DN_OSErrSink *err); -DN_API void DN_OS_ErrSinkEndAndIgnore (DN_OSErrSink *err); -DN_API bool DN_OS_ErrSinkEndAndLogError_ (DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 msg); -DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_ErrSinkEndAndLogErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); -DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...); -DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API void DN_OS_ErrSinkAppendFV_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...); -#define DN_OS_ErrSinkEndAndLogError(err, err_msg) DN_OS_ErrSinkEndAndLogError_(err, DN_CALL_SITE, err_msg) -#define DN_OS_ErrSinkEndAndLogErrorFV(err, fmt, args) DN_OS_ErrSinkEndAndLogErrorFV_(err, DN_CALL_SITE, fmt, args) -#define DN_OS_ErrSinkEndAndLogErrorF(err, fmt, ...) DN_OS_ErrSinkEndAndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__) -#define DN_OS_ErrSinkEndAndExitIfErrorFV(err, exit_val, fmt, args) DN_OS_ErrSinkEndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args) -#define DN_OS_ErrSinkEndAndExitIfErrorF(err, exit_val, fmt, ...) DN_OS_ErrSinkEndAndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__) +DN_API DN_OSErrSink * DN_OS_ErrSinkBegin_ (DN_OSErrSinkMode mode, DN_CallSite call_site); +#define DN_OS_ErrSinkBegin(mode) DN_OS_ErrSinkBegin_(mode, DN_CALL_SITE) +#define DN_OS_ErrSinkBeginDefault() DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil) +DN_API bool DN_OS_ErrSinkHasError (DN_OSErrSink *err); +DN_API DN_OSErrSinkMsg * DN_OS_ErrSinkEnd (DN_Arena *arena, DN_OSErrSink *err); +DN_API DN_Str8 DN_OS_ErrSinkEndStr8 (DN_Arena *arena, DN_OSErrSink *err); +DN_API void DN_OS_ErrSinkEndAndIgnore (DN_OSErrSink *err); +DN_API bool DN_OS_ErrSinkEndAndLogError_ (DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 msg); +DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_ErrSinkEndAndLogErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_OS_ErrSinkAppendFV_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...); +#define DN_OS_ErrSinkEndAndLogError(err, err_msg) DN_OS_ErrSinkEndAndLogError_(err, DN_CALL_SITE, err_msg) +#define DN_OS_ErrSinkEndAndLogErrorFV(err, fmt, args) DN_OS_ErrSinkEndAndLogErrorFV_(err, DN_CALL_SITE, fmt, args) +#define DN_OS_ErrSinkEndAndLogErrorF(err, fmt, ...) DN_OS_ErrSinkEndAndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__) +#define DN_OS_ErrSinkEndAndExitIfErrorFV(err, exit_val, fmt, args) DN_OS_ErrSinkEndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args) +#define DN_OS_ErrSinkEndAndExitIfErrorF(err, exit_val, fmt, ...) DN_OS_ErrSinkEndAndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__) #define DN_OS_ErrSinkAppendFV(error, error_code, fmt, args) \ do { \ @@ -5512,6 +5520,9 @@ DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, #if !defined(DN_OS_H) #define DN_OS_H +// DN: Single header generator commented out this header => #include "../dn_base_inc.h" +// DN: Single header generator commented out this header => #include "../dn_os_inc.h" + #include // operator new #if !defined(DN_OS_WIN32) || defined(DN_OS_WIN32_USE_PTHREADS) @@ -5813,94 +5824,87 @@ struct DN_OSDiskSpace DN_U64 size; }; -DN_API void DN_OS_Init (DN_OSCore *os, DN_OSInitArgs *args); -DN_API void DN_OS_EmitLogsWithOSPrintFunctions(DN_OSCore *os); -DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path); +DN_API void DN_OS_Init (DN_OSCore *os, DN_OSInitArgs *args); +DN_API void DN_OS_EmitLogsWithOSPrintFunctions (DN_OSCore *os); +DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path); -// NOTE: Memory //////////////////////////////////////////////////////////////////////////////////// -DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags); -DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags); -DN_API void DN_OS_MemDecommit(void *ptr, DN_USize size); -DN_API void DN_OS_MemRelease (void *ptr, DN_USize size); -DN_API int DN_OS_MemProtect (void *ptr, DN_USize size, DN_U32 page_flags); +DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags); +DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags); +DN_API void DN_OS_MemDecommit (void *ptr, DN_USize size); +DN_API void DN_OS_MemRelease (void *ptr, DN_USize size); +DN_API int DN_OS_MemProtect (void *ptr, DN_USize size, DN_U32 page_flags); -// NOTE: Heap -DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZeroMem zero_mem); -DN_API void DN_OS_MemDealloc (void *ptr); +DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZeroMem zero_mem); +DN_API void DN_OS_MemDealloc (void *ptr); -// NOTE: DN_OSDate ///////////////////////////////////////////////////////////////////////////////// -DN_API DN_OSDateTime DN_OS_DateLocalTimeNow (); -DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator = '-', char hms_separator = ':'); -DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':'); -DN_API DN_U64 DN_OS_DateUnixTimeNs (); -#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000) -#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000)) -#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000)) -DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time); -DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date); -DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date); -DN_API bool DN_OS_DateIsValid (DN_OSDateTime date); +DN_API DN_OSDateTime DN_OS_DateLocalTimeNow (); +DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':'); +DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':'); +DN_API DN_U64 DN_OS_DateUnixTimeNs (); +#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000) +#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000)) +#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000)) +DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time); +DN_API DN_U64 DN_OS_DateLocalToUnixTimeS (DN_OSDateTime date); +DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date); +DN_API bool DN_OS_DateIsValid (DN_OSDateTime date); -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); -DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); -DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path); -DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena); -DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena); -#define DN_OS_EXEDirFromTLS() DN_OS_EXEDir(DN_OS_TLSTopArena()) -DN_API void DN_OS_SleepMs (DN_UInt milliseconds); +DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); +DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); +DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path); +DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena); +DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena); +#define DN_OS_EXEDirFromTLS() DN_OS_EXEDir(DN_OS_TLSTopArena()) +DN_API void DN_OS_SleepMs (DN_UInt milliseconds); -// NOTE: Counters ////////////////////////////////////////////////////////////////////////////////// -DN_API DN_U64 DN_OS_PerfCounterNow (); -DN_API DN_U64 DN_OS_PerfCounterFrequency(); -DN_API DN_F64 DN_OS_PerfCounterS (DN_U64 begin, uint64_t end); -DN_API DN_F64 DN_OS_PerfCounterMs (DN_U64 begin, uint64_t end); -DN_API DN_F64 DN_OS_PerfCounterUs (DN_U64 begin, uint64_t end); -DN_API DN_F64 DN_OS_PerfCounterNs (DN_U64 begin, uint64_t end); -DN_API DN_OSTimer DN_OS_TimerBegin (); -DN_API void DN_OS_TimerEnd (DN_OSTimer *timer); -DN_API DN_F64 DN_OS_TimerS (DN_OSTimer timer); -DN_API DN_F64 DN_OS_TimerMs (DN_OSTimer timer); -DN_API DN_F64 DN_OS_TimerUs (DN_OSTimer timer); -DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer); -DN_API DN_U64 DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency); -#if !defined(DN_NO_OS_FILE_API) -// NOTE: File system paths ///////////////////////////////////////////////////////////////////////// -DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path); -DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against); -DN_API bool DN_OS_PathDelete (DN_Str8 path); -DN_API bool DN_OS_FileExists (DN_Str8 path); -DN_API bool DN_OS_CopyFile (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); -DN_API bool DN_OS_MoveFile (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); -DN_API bool DN_OS_MakeDir (DN_Str8 path); -DN_API bool DN_OS_DirExists (DN_Str8 path); -DN_API bool DN_OS_DirIterate (DN_Str8 path, DN_OSDirIterator *it); +DN_API DN_U64 DN_OS_PerfCounterNow (); +DN_API DN_U64 DN_OS_PerfCounterFrequency (); +DN_API DN_F64 DN_OS_PerfCounterS (DN_U64 begin, uint64_t end); +DN_API DN_F64 DN_OS_PerfCounterMs (DN_U64 begin, uint64_t end); +DN_API DN_F64 DN_OS_PerfCounterUs (DN_U64 begin, uint64_t end); +DN_API DN_F64 DN_OS_PerfCounterNs (DN_U64 begin, uint64_t end); +DN_API DN_OSTimer DN_OS_TimerBegin (); +DN_API void DN_OS_TimerEnd (DN_OSTimer *timer); +DN_API DN_F64 DN_OS_TimerS (DN_OSTimer timer); +DN_API DN_F64 DN_OS_TimerMs (DN_OSTimer timer); +DN_API DN_F64 DN_OS_TimerUs (DN_OSTimer timer); +DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer); +DN_API DN_U64 DN_OS_EstimateTSCPerSecond (uint64_t duration_ms_to_gauge_tsc_frequency); -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// -DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_OSErrSink *err); -DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err); -DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *data, DN_USize size, DN_OSErrSink *err); -DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *err); -DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); -DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_OSErrSink *err); -DN_API void DN_OS_FileClose (DN_OSFile *file); +DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); +DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); -// NOTE: R/W Entire File /////////////////////////////////////////////////////////////////////////// -DN_API DN_Str8 DN_OS_ReadAll (DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err); -#define DN_OS_ReadAllFromTLS(...) DN_OS_ReadAll(DN_OS_TLSTopArena(), ##__VA_ARGS__) -DN_API bool DN_OS_WriteAll (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); -DN_API bool DN_OS_WriteAllFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_WriteAllF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); -DN_API bool DN_OS_WriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); -DN_API bool DN_OS_WriteAllSafeFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_WriteAllSafeF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); -#endif // !defined(DN_NO_OS_FILE_API) +DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_OSErrSink *err); +DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err); +DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_OSErrSink *err); +DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *err); +DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_OSErrSink *err); +DN_API void DN_OS_FileClose (DN_OSFile *file); + +DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err); +DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err); +DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err); +DN_API DN_Str8 DN_OS_FileReadAllTLS (DN_Str8 path, DN_OSErrSink *err); +DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); +DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); +DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); + +DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path); +DN_API bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against); +DN_API bool DN_OS_PathDelete (DN_Str8 path); +DN_API bool DN_OS_PathIsFile (DN_Str8 path); +DN_API bool DN_OS_PathIsDir (DN_Str8 path); +DN_API bool DN_OS_PathMakeDir (DN_Str8 path); +DN_API bool DN_OS_PathIterateDir (DN_Str8 path, DN_OSDirIterator *it); -// NOTE: File system paths ///////////////////////////////////////////////////////////////////////// DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); -#define DN_OS_PathAddRefFromTLS(...) DN_OS_PathAddRef(DN_OS_TLSTopArena(), ##__VA_ARGS__) -#define DN_OS_PathAddRefFromFrame(...) DN_OS_PathAddRef(DN_OS_TLSFrameArena(), ##__VA_ARGS__) +DN_API bool DN_OS_PathAddRefTLS (DN_OSPath *fs_path, DN_Str8 path); +DN_API bool DN_OS_PathAddRefFrame (DN_OSPath *fs_path, DN_Str8 path); DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); #define DN_OS_PathAddFromTLS(...) DN_OS_PathAdd(DN_OS_TLSTopArena(), ##__VA_ARGS__) #define DN_OS_PathAddFromFrame(...) DN_OS_PathAdd(DN_OS_TLSFrameArena(), ##__VA_ARGS__) @@ -5928,49 +5932,48 @@ DN_API DN_Str8 DN_OS_PathF (D #define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_STR8("\\")) #define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString) -// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// -DN_API void DN_OS_Exit (int32_t exit_code); -DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_OSErrSink *err); -DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err); -DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err); -DN_API DN_OSExecResult DN_OS_Exec (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_OSErrSink *err); -DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena); -#define DN_OS_ExecOrAbortFromTLS(...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena()) +DN_API void DN_OS_Exit (int32_t exit_code); +DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_OSErrSink *err); +DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err); +DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err); +DN_API DN_OSExecResult DN_OS_Exec (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_OSErrSink *err); +DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena); +#define DN_OS_ExecOrAbortFromTLS (...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena()) -DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count); -DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore); -DN_API void DN_OS_SemaphoreDeinit (DN_OSSemaphore *semaphore); -DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount); -DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait (DN_OSSemaphore *semaphore, DN_U32 timeout_ms); +DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count); +DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore); +DN_API void DN_OS_SemaphoreDeinit (DN_OSSemaphore *semaphore); +DN_API void DN_OS_SemaphoreIncrement (DN_OSSemaphore *semaphore, DN_U32 amount); +DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait (DN_OSSemaphore *semaphore, DN_U32 timeout_ms); -DN_API DN_OSMutex DN_OS_MutexInit (); -DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex); -DN_API void DN_OS_MutexLock (DN_OSMutex *mutex); -DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex); -#define DN_OS_MutexScope(mutex) DN_DeferLoop(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex)) +DN_API DN_OSMutex DN_OS_MutexInit (); +DN_API void DN_OS_MutexDeinit (DN_OSMutex *mutex); +DN_API void DN_OS_MutexLock (DN_OSMutex *mutex); +DN_API void DN_OS_MutexUnlock (DN_OSMutex *mutex); +#define DN_OS_MutexScope (mutex) DN_DeferLoop(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex)) -DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit (); -DN_API void DN_OS_ConditionVariableDeinit (DN_OSConditionVariable *cv); -DN_API bool DN_OS_ConditionVariableWait (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 sleep_ms); -DN_API bool DN_OS_ConditionVariableWaitUntil(DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 end_ts_ms); -DN_API void DN_OS_ConditionVariableSignal (DN_OSConditionVariable *cv); -DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv); +DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit (); +DN_API void DN_OS_ConditionVariableDeinit (DN_OSConditionVariable *cv); +DN_API bool DN_OS_ConditionVariableWait (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 sleep_ms); +DN_API bool DN_OS_ConditionVariableWaitUntil (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 end_ts_ms); +DN_API void DN_OS_ConditionVariableSignal (DN_OSConditionVariable *cv); +DN_API void DN_OS_ConditionVariableBroadcast (DN_OSConditionVariable *cv); -DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context); -DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread); -DN_API DN_U32 DN_OS_ThreadID (); -DN_API void DN_OS_ThreadSetName(DN_Str8 name); +DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context); +DN_API void DN_OS_ThreadDeinit (DN_OSThread *thread); +DN_API DN_U32 DN_OS_ThreadID (); +DN_API void DN_OS_ThreadSetName (DN_Str8 name); -DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); -DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response); -DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response); -DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); +DN_API void DN_OS_HttpRequestAsync (DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); +DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response); +DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response); +DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); #endif // !defined(DN_OS_H) // DN: Single header generator inlined this file => #include "OS/dn_os_allocator.h" #if !defined(DN_OS_ALLOCATOR_H) #define DN_OS_ALLOCATOR_H -DN_API DN_Arena DN_Arena_FromOSHeap(DN_U64 size, DN_ArenaFlags flags); +DN_API DN_Arena DN_Arena_FromHeap(DN_U64 size, DN_ArenaFlags flags); DN_API DN_Arena DN_Arena_FromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags); #endif // !defined(DN_OS_ALLOCATOR_H) @@ -6316,22 +6319,29 @@ DN_API void DN_Core_SetProfiler (DN_Profiler #if !defined(DN_MATH_H) #define DN_MATH_H +// DN: Single header generator commented out this header => #include "../dn_base_inc.h" + DN_MSVC_WARNING_PUSH DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// union DN_V2I32 { - struct { int32_t x, y; }; - struct { int32_t w, h; }; - int32_t data[2]; + struct { DN_I32 x, y; }; + struct { DN_I32 w, h; }; + DN_I32 data[2]; }; union DN_V2U16 { - struct { uint16_t x, y; }; - struct { uint16_t w, h; }; - uint16_t data[2]; + struct { DN_U16 x, y; }; + struct { DN_U16 w, h; }; + DN_U16 data[2]; +}; + +union DN_V2U32 +{ + struct { DN_U32 x, y; }; + struct { DN_U32 w, h; }; + DN_U32 data[2]; }; union DN_V2F32 @@ -6340,10 +6350,7 @@ union DN_V2F32 struct { DN_F32 w, h; }; DN_F32 data[2]; }; -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// union DN_V3F32 { struct { DN_F32 x, y, z; }; @@ -6351,10 +6358,7 @@ union DN_V3F32 DN_F32 data[3]; }; -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// union DN_V4F32 { struct { DN_F32 x, y, z, w; }; @@ -6365,29 +6369,19 @@ union DN_V4F32 #endif DN_F32 data[4]; }; -#endif // !defined(DN_NO_V4) DN_MSVC_WARNING_POP -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// struct DN_M4 { DN_F32 columns[4][4]; // Column major matrix }; -#endif // !defined(DN_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// union DN_M2x3 { DN_F32 e[6]; DN_F32 row[2][3]; }; -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#if !defined(DN_NO_RECT) -#if defined(DN_NO_V2) - #error "Rectangles requires V2, DN_NO_V2 must not be defined" -#endif struct DN_Rect { DN_V2F32 pos, size; @@ -6417,10 +6411,7 @@ struct DN_RectCut DN_Rect* rect; DN_RectCutSide side; }; -#endif // !defined(DN_NO_RECT) -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: API struct DN_RaycastLineIntersectV2Result { bool hit; // True if there was an intersection, false if the lines are parallel @@ -6428,13 +6419,11 @@ struct DN_RaycastLineIntersectV2Result DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` }; -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} -#define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} -#define DN_V2I32_From1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} -#define DN_V2I32_From2N(x, y) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} -#define DN_V2I32_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} +#define DN_V2I32_Zero DN_Literal(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} +#define DN_V2I32_One DN_Literal(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} +#define DN_V2I32_From1N(x) DN_Literal(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} +#define DN_V2I32_From2N(x, y) DN_Literal(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} +#define DN_V2I32_InitV2(xy) DN_Literal(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs); DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs); @@ -6464,10 +6453,10 @@ DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); -#define DN_V2U16_Zero DN_LITERAL(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} -#define DN_V2U16_One DN_LITERAL(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} -#define DN_V2U16_From1N(x) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} -#define DN_V2U16_From2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} +#define DN_V2U16_Zero DN_Literal(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} +#define DN_V2U16_One DN_Literal(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} +#define DN_V2U16_From1N(x) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} +#define DN_V2U16_From2N(x, y) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); @@ -6492,11 +6481,11 @@ DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); -#define DN_V2F32_Zero DN_LITERAL(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} -#define DN_V2F32_One DN_LITERAL(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} -#define DN_V2F32_From1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} -#define DN_V2F32_From2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} -#define DN_V2F32_FromV2I32(xy) DN_LITERAL(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} +#define DN_V2F32_Zero DN_Literal(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} +#define DN_V2F32_One DN_Literal(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} +#define DN_V2F32_From1N(x) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} +#define DN_V2F32_From2N(x, y) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} +#define DN_V2F32_FromV2I32(xy) DN_Literal(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs); DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs); @@ -6559,12 +6548,10 @@ DN_API DN_V2F32 DN_V2F32_Normalise (DN_V2F32 a); DN_API DN_V2F32 DN_V2F32_Perpendicular (DN_V2F32 a); DN_API DN_V2F32 DN_V2F32_Reflect (DN_V2F32 in, DN_V2F32 surface); DN_API DN_F32 DN_V2F32_Area (DN_V2F32 a); -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V3F32_From1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V3F32_From3N(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} -#define DN_V3F32_FromV2F32And1N(xy, z) DN_LITERAL(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} + +#define DN_V3F32_From1N(x) DN_Literal(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} +#define DN_V3F32_From3N(x, y, z) DN_Literal(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} +#define DN_V3F32_FromV2F32And1N(xy, z) DN_Literal(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs); DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs); @@ -6592,19 +6579,17 @@ DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a); DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a); DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a); -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) + DN_U32 const DN_V4_R_MASK_U32 = 0xFF000000; DN_U32 const DN_V4_G_MASK_U32 = 0x00FF0000; DN_U32 const DN_V4_B_MASK_U32 = 0x0000FF00; DN_U32 const DN_V4_A_MASK_U32 = 0x000000FF; -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V4F32_From1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V4F32_From4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} -#define DN_V4F32_FromV3And1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} -#define DN_V4F32_FromRGBAU8(r, g, b, a) DN_LITERAL(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, a / 255.f}} -#define DN_V4F32_FromRGBU8(r, g, b) DN_LITERAL(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, 1.f}} +#define DN_V4F32_From1N(x) DN_Literal(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} +#define DN_V4F32_From4N(x, y, z, w) DN_Literal(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} +#define DN_V4F32_FromV3And1N(xyz, w) DN_Literal(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} +#define DN_V4F32_FromRGBAU8(r, g, b, a) DN_Literal(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, a / 255.f}} +#define DN_V4F32_FromRGBU8(r, g, b) DN_Literal(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, 1.f}} DN_API DN_V4F32 DN_V4F32_FromRGBU32(DN_U32 u32); DN_API DN_V4F32 DN_V4F32_FromRGBAU32(DN_U32 u32); #define DN_V4F32_FromV4Alpha(v4, alpha) DN_V4F32_FromV3And1N(v4.xyz, alpha) @@ -6626,9 +6611,7 @@ DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs); DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs); DN_API DN_F32 DN_V4F32_Dot (DN_V4F32 a, DN_V4F32 b); -#endif // !defined(DN_NO_V4) -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// + DN_API DN_M4 DN_M4_Identity (); DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z); DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz); @@ -6647,8 +6630,7 @@ DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_ DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs); DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs); DN_API DN_Str8x256 DN_M4_ColumnMajorString (DN_M4 mat); -#endif // !defined(DN_NO_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// + DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs); DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); DN_API DN_M2x3 DN_M2x3_Identity (); @@ -6658,10 +6640,9 @@ DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y); DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2); -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#define DN_Rect_From2V2(pos, size) DN_LITERAL(DN_Rect){(pos), (size)} -#define DN_Rect_From4N(x, y, w, h) DN_LITERAL(DN_Rect){DN_LITERAL(DN_V2F32){{x, y}}, DN_LITERAL(DN_V2F32){{w, h}}} + +#define DN_Rect_From2V2(pos, size) DN_Literal(DN_Rect){(pos), (size)} +#define DN_Rect_From4N(x, y, w, h) DN_Literal(DN_Rect){DN_Literal(DN_V2F32){{x, y}}, DN_Literal(DN_V2F32){{w, h}}} DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); @@ -6696,13 +6677,12 @@ DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, #define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No) DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip); -#define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side} -#define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left} -#define DN_RectCut_Right(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Right} -#define DN_RectCut_Top(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Top} -#define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom} -#endif // !defined(DN_NO_RECT) -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// +#define DN_RectCut_Init(rect, side) DN_Literal(DN_RectCut){rect, side} +#define DN_RectCut_Left(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Left} +#define DN_RectCut_Right(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Right} +#define DN_RectCut_Top(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Top} +#define DN_RectCut_Bottom(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Bottom} + DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b); DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b); DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); diff --git a/Source/Base/dn_base_compiler.h b/Source/Base/dn_base_compiler.h index cd8ff40..1f1bb28 100644 --- a/Source/Base/dn_base_compiler.h +++ b/Source/Base/dn_base_compiler.h @@ -109,9 +109,9 @@ #endif #if defined(__cplusplus) - #define DN_LITERAL(T) T + #define DN_Literal(T) T #else - #define DN_LITERAL(T) (T) + #define DN_Literal(T) (T) #endif // NOTE: Thread Locals ///////////////////////////////////////////////////////////////////////////// diff --git a/Source/Base/dn_base_convert.h b/Source/Base/dn_base_convert.h index 16ea878..ea13cbd 100644 --- a/Source/Base/dn_base_convert.h +++ b/Source/Base/dn_base_convert.h @@ -68,8 +68,8 @@ DN_API DN_CVTU64Str8 DN_CVT_Str8FromU64 (DN_U6 DN_API DN_CVTU64Bytes DN_CVT_BytesFromU64 (DN_U64 bytes, DN_CVTBytesType type); #define DN_CVT_BytesFromU64Auto(bytes) DN_CVT_BytesFromU64(bytes, DN_CVTBytesType_Auto) DN_API DN_Str8 DN_CVT_BytesStr8FromU64 (DN_Arena *arena, DN_U64 bytes, DN_CVTBytesType type); -#define DN_CVT_BytesStr8FromU64Auto(arena, bytes) DN_CVT_BytesStr8FromU64(arena, bytes, DN_CVTBytesType_Auto) #define DN_CVT_BytesStr8FromTLS(bytes, type) DN_CVT_BytesStr8FromU64(DN_OS_TLSTopArena(), bytes, type) +#define DN_CVT_BytesStr8FromU64Auto(arena, bytes) DN_CVT_BytesStr8FromU64(arena, bytes, DN_CVTBytesType_Auto) #define DN_CVT_BytesStr8FromU64AutoTLS(bytes) DN_CVT_BytesStr8FromU64(DN_OS_TLSTopArena(), bytes, DN_CVTBytesType_Auto) #define DN_CVT_BytesStr8FromU64Frame(bytes, type) DN_CVT_BytesStr8FromU64(DN_OS_TLSFrameArena(), bytes, type) #define DN_CVT_BytesStr8FromU64AutoFrame(bytes) DN_CVT_BytesStr8FromU64(DN_OS_TLSFrameArena(), bytes, DN_CVTBytesType_Auto) diff --git a/Source/Base/dn_base_mem.h b/Source/Base/dn_base_mem.h index 12acba1..3f25f64 100644 --- a/Source/Base/dn_base_mem.h +++ b/Source/Base/dn_base_mem.h @@ -59,6 +59,12 @@ enum DN_MemPage_ #define DN_ARENA_COMMIT_SIZE DN_Kilobytes(64) #endif +enum DN_Allocator +{ + DN_Allocator_Arena, + DN_Allocator_Pool, +}; + struct DN_ArenaBlock { DN_ArenaBlock *prev; diff --git a/Source/Base/dn_base_string.cpp b/Source/Base/dn_base_string.cpp index 2a09b6e..9f8088c 100644 --- a/Source/Base/dn_base_string.cpp +++ b/Source/Base/dn_base_string.cpp @@ -68,6 +68,16 @@ DN_API DN_Str8 DN_Str8_Alloc(DN_Arena *arena, DN_USize size, DN_ZeroMem zero_mem return result; } +DN_API DN_Str8 DN_Str8_AllocPool(DN_Pool *pool, DN_USize size) +{ + DN_Str8 result = {}; + result.data = DN_Pool_NewArray(pool, char, size + 1); + if (result.data) + result.size = size; + result.data[result.size] = 0; + return result; +} + DN_API DN_Str8 DN_Str8_FromCStr8(char const *src) { DN_USize size = DN_CStr8_Size(src); @@ -84,6 +94,21 @@ DN_API DN_Str8 DN_Str8_FromF(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ... return result; } +DN_API DN_Str8 DN_Str8_FromFPool(DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + DN_USize size = DN_CStr8_FVSize(fmt, args); + va_end(args); + + DN_Str8 result = {}; + if (size) + result = DN_Str8_AllocPool(pool, size); + if (result.data) + DN_VSNPrintF(result.data, DN_SaturateCastISizeToInt(size + 1 /*null-terminator*/), fmt, args); + return result; +} + DN_API DN_Str8 DN_Str8_FromFV(DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args) { DN_Str8 result = {}; diff --git a/Source/Base/dn_base_string.h b/Source/Base/dn_base_string.h index 4a475fe..5a89d52 100644 --- a/Source/Base/dn_base_string.h +++ b/Source/Base/dn_base_string.h @@ -138,16 +138,17 @@ DN_API DN_Str8 DN_Str8_Alloc (DN_Arena *aren DN_API DN_Str8 DN_Str8_FromCStr8 (char const *src); DN_API DN_Str8 DN_Str8_FromF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_Str8_FromFV (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API DN_Str8 DN_Str8_FromFPool (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...); DN_API DN_Str8 DN_Str8_FromStr8 (DN_Arena *arena, DN_Str8 string); DN_API bool DN_Str8_IsAll (DN_Str8 string, DN_Str8IsAll is_all); DN_API char * DN_Str8_End (DN_Str8 string); DN_API DN_Str8 DN_Str8_Slice (DN_Str8 string, DN_USize offset, DN_USize size); DN_API DN_Str8 DN_Str8_Advance (DN_Str8 string, DN_USize amount); DN_API DN_Str8 DN_Str8_NextLine (DN_Str8 string); -DN_API DN_Str8BSplitResult DN_Str8_BSplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); -DN_API DN_Str8BSplitResult DN_Str8_BSplit (DN_Str8 string, DN_Str8 find); -DN_API DN_Str8BSplitResult DN_Str8_BSplitLastArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); -DN_API DN_Str8BSplitResult DN_Str8_BSplitLast (DN_Str8 string, DN_Str8 find); +DN_API DN_Str8BSplitResult DN_Str8_BSplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); +DN_API DN_Str8BSplitResult DN_Str8_BSplit (DN_Str8 string, DN_Str8 find); +DN_API DN_Str8BSplitResult DN_Str8_BSplitLastArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size); +DN_API DN_Str8BSplitResult DN_Str8_BSplitLast (DN_Str8 string, DN_Str8 find); DN_API DN_USize DN_Str8_Split (DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitIncludeEmptyStrings mode); DN_API DN_Slice DN_Str8_SplitAlloc (DN_Arena *arena, DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitIncludeEmptyStrings mode); DN_API DN_Str8FindResult DN_Str8_FindStr8Array (DN_Str8 string, DN_Str8 const *find, DN_USize find_size, DN_Str8EqCase eq_case); diff --git a/Source/Core/dn_core_demo.cpp b/Source/Core/dn_core_demo.cpp index 0cfd5ca..3611734 100644 --- a/Source/Core/dn_core_demo.cpp +++ b/Source/Core/dn_core_demo.cpp @@ -322,7 +322,7 @@ void DN_Docs_Demo() // NOTE: My error sinks are thread-local, so the returned 'error' is // the same as the 'error' value above. DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); - DN_OS_WriteAll(DN_STR8("/path/to/another/file"), DN_STR8("123"), error); + DN_OS_FileWriteAll(DN_STR8("/path/to/another/file"), DN_STR8("123"), error); DN_OS_ErrSinkEndAndLogErrorF(error, "Failed to write to another file"); } @@ -451,7 +451,7 @@ void DN_Docs_Demo() // NOTE: DN_OS_DirIterate ///////////////////////////////////////////////////////////////////// // // Iterate the files within the passed in folder - for (DN_OSDirIterator it = {}; DN_OS_DirIterate(DN_STR8("."), &it);) { + for (DN_OSDirIterator it = {}; DN_OS_PathIterateDir(DN_STR8("."), &it);) { // printf("%.*s\n", DN_STR_FMT(it.file_name)); } @@ -473,7 +473,7 @@ void DN_Docs_Demo() if (0) { DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_OSErrSink *error = DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil); - DN_OS_WriteAllSafe(/*path*/ DN_STR8("C:/Home/my.txt"), /*buffer*/ DN_STR8("Hello world"), error); + DN_OS_FileWriteAllSafe(/*path*/ DN_STR8("C:/Home/my.txt"), /*buffer*/ DN_STR8("Hello world"), error); DN_OS_ErrSinkEndAndLogErrorF(error, ""); } diff --git a/Source/Extra/dn_math.cpp b/Source/Extra/dn_math.cpp index bb2c417..caad8aa 100644 --- a/Source/Extra/dn_math.cpp +++ b/Source/Extra/dn_math.cpp @@ -1,8 +1,7 @@ #define DN_MATH_CPP -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: DN_V2I32 +#include "dn_math.h" + DN_API bool operator==(DN_V2I32 lhs, DN_V2I32 rhs) { bool result = (lhs.x == rhs.x) && (lhs.y == rhs.y); @@ -159,7 +158,6 @@ DN_API DN_V2I32 DN_V2I32_Abs(DN_V2I32 a) return result; } -// NOTE: DN_V2U16 DN_API bool operator!=(DN_V2U16 lhs, DN_V2U16 rhs) { bool result = !(lhs == rhs); @@ -292,7 +290,6 @@ DN_API DN_V2U16 &operator+=(DN_V2U16 &lhs, DN_V2U16 rhs) return lhs; } -// NOTE: DN_V2 DN_API bool operator!=(DN_V2F32 lhs, DN_V2F32 rhs) { bool result = !(lhs == rhs); @@ -329,7 +326,6 @@ DN_API bool operator>(DN_V2F32 lhs, DN_V2F32 rhs) return result; } -// NOTE: DN_V2F32 operator- ////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 operator-(DN_V2F32 lhs) { DN_V2F32 result = DN_V2F32_From2N(-lhs.x, -lhs.y); @@ -360,7 +356,6 @@ DN_API DN_V2F32 operator-(DN_V2F32 lhs, int32_t rhs) return result; } -// NOTE: DN_V2F32 operator+ ////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 operator+(DN_V2F32 lhs, DN_V2F32 rhs) { DN_V2F32 result = DN_V2F32_From2N(lhs.x + rhs.x, lhs.y + rhs.y); @@ -385,7 +380,6 @@ DN_API DN_V2F32 operator+(DN_V2F32 lhs, int32_t rhs) return result; } -// NOTE: DN_V2F32 operator* ////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 operator*(DN_V2F32 lhs, DN_V2F32 rhs) { DN_V2F32 result = DN_V2F32_From2N(lhs.x * rhs.x, lhs.y * rhs.y); @@ -410,7 +404,6 @@ DN_API DN_V2F32 operator*(DN_V2F32 lhs, int32_t rhs) return result; } -// NOTE: DN_V2F32 operator/ ////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 operator/(DN_V2F32 lhs, DN_V2F32 rhs) { DN_V2F32 result = DN_V2F32_From2N(lhs.x / rhs.x, lhs.y / rhs.y); @@ -435,7 +428,6 @@ DN_API DN_V2F32 operator/(DN_V2F32 lhs, int32_t rhs) return result; } -// NOTE: DN_V2F32 operator*/ ///////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs * rhs; @@ -460,7 +452,6 @@ DN_API DN_V2F32 &operator*=(DN_V2F32 &lhs, int32_t rhs) return lhs; } -// NOTE: DN_V2F32 operator// ///////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs / rhs; @@ -485,7 +476,6 @@ DN_API DN_V2F32 &operator/=(DN_V2F32 &lhs, int32_t rhs) return lhs; } -// NOTE: DN_V2F32 operator-/ ///////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs - rhs; @@ -510,7 +500,6 @@ DN_API DN_V2F32 &operator-=(DN_V2F32 &lhs, int32_t rhs) return lhs; } -// NOTE: DN_V2F32 operator+/ ///////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 &operator+=(DN_V2F32 &lhs, DN_V2F32 rhs) { lhs = lhs + rhs; @@ -682,10 +671,7 @@ DN_API DN_F32 DN_V2F32_Area(DN_V2F32 a) DN_F32 result = a.w * a.h; return result; } -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// DN_API bool operator!=(DN_V3F32 lhs, DN_V3F32 rhs) { bool result = !(lhs == rhs); @@ -843,10 +829,7 @@ DN_API DN_V3F32 DN_V3_Normalise(DN_V3F32 a) DN_V3F32 result = a / length; return result; } -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// DN_API DN_V4F32 DN_V4F32_FromRGBU32(DN_U32 u32) { DN_U8 r = (DN_U8)(((u32 << 8) & DN_V4_R_MASK_U32) >> 24); @@ -979,10 +962,7 @@ DN_API DN_F32 DN_V4F32Dot(DN_V4F32 a, DN_V4F32 b) DN_F32 result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w); return result; } -#endif // !defined(DN_NO_V4) -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// DN_API DN_M4 DN_M4_Identity() { DN_M4 result = @@ -1231,9 +1211,7 @@ DN_API DN_Str8x256 DN_M4_ColumnMajorString(DN_M4 mat) return result; } -#endif // !defined(DN_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// DN_API bool operator==(DN_M2x3 const &lhs, DN_M2x3 const &rhs) { bool result = DN_Memcmp(lhs.e, rhs.e, sizeof(lhs.e[0]) * DN_ArrayCountU(lhs.e)) == 0; @@ -1355,8 +1333,6 @@ DN_API DN_V2F32 DN_M2x3_MulV2(DN_M2x3 m1, DN_V2F32 v2) return result; } -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// DN_API bool operator==(const DN_Rect &lhs, const DN_Rect &rhs) { bool result = (lhs.pos == rhs.pos) && (lhs.size == rhs.size); @@ -1561,9 +1537,6 @@ DN_API DN_V2F32 DN_Rect_BottomRight(DN_Rect rect) DN_V2F32 result = DN_Rect_InterpolatedPoint(rect, DN_V2F32_From2N(1, 1)); return result; } -#endif // !defined(DN_NO_RECT) - -// NOTE: Raycast /////////////////////////////////////////////////////////////////////////////////// DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b) { @@ -1596,7 +1569,6 @@ DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origi return result; } -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// DN_API DN_V2F32 DN_Lerp_V2F32(DN_V2F32 a, DN_F32 t, DN_V2F32 b) { DN_V2F32 result = {}; diff --git a/Source/Extra/dn_math.h b/Source/Extra/dn_math.h index 1fa34c7..62a72a0 100644 --- a/Source/Extra/dn_math.h +++ b/Source/Extra/dn_math.h @@ -1,22 +1,29 @@ #if !defined(DN_MATH_H) #define DN_MATH_H +#include "../dn_base_inc.h" + DN_MSVC_WARNING_PUSH DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// union DN_V2I32 { - struct { int32_t x, y; }; - struct { int32_t w, h; }; - int32_t data[2]; + struct { DN_I32 x, y; }; + struct { DN_I32 w, h; }; + DN_I32 data[2]; }; union DN_V2U16 { - struct { uint16_t x, y; }; - struct { uint16_t w, h; }; - uint16_t data[2]; + struct { DN_U16 x, y; }; + struct { DN_U16 w, h; }; + DN_U16 data[2]; +}; + +union DN_V2U32 +{ + struct { DN_U32 x, y; }; + struct { DN_U32 w, h; }; + DN_U32 data[2]; }; union DN_V2F32 @@ -25,10 +32,7 @@ union DN_V2F32 struct { DN_F32 w, h; }; DN_F32 data[2]; }; -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// union DN_V3F32 { struct { DN_F32 x, y, z; }; @@ -36,10 +40,7 @@ union DN_V3F32 DN_F32 data[3]; }; -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// union DN_V4F32 { struct { DN_F32 x, y, z, w; }; @@ -50,29 +51,19 @@ union DN_V4F32 #endif DN_F32 data[4]; }; -#endif // !defined(DN_NO_V4) DN_MSVC_WARNING_POP -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// struct DN_M4 { DN_F32 columns[4][4]; // Column major matrix }; -#endif // !defined(DN_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// union DN_M2x3 { DN_F32 e[6]; DN_F32 row[2][3]; }; -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#if !defined(DN_NO_RECT) -#if defined(DN_NO_V2) - #error "Rectangles requires V2, DN_NO_V2 must not be defined" -#endif struct DN_Rect { DN_V2F32 pos, size; @@ -102,10 +93,7 @@ struct DN_RectCut DN_Rect* rect; DN_RectCutSide side; }; -#endif // !defined(DN_NO_RECT) -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -// NOTE: API struct DN_RaycastLineIntersectV2Result { bool hit; // True if there was an intersection, false if the lines are parallel @@ -113,13 +101,11 @@ struct DN_RaycastLineIntersectV2Result DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)` }; -#if !defined(DN_NO_V2) -// NOTE: DN_V2 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V2I32_Zero DN_LITERAL(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} -#define DN_V2I32_One DN_LITERAL(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} -#define DN_V2I32_From1N(x) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} -#define DN_V2I32_From2N(x, y) DN_LITERAL(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} -#define DN_V2I32_InitV2(xy) DN_LITERAL(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} +#define DN_V2I32_Zero DN_Literal(DN_V2I32){{(int32_t)(0), (int32_t)(0)}} +#define DN_V2I32_One DN_Literal(DN_V2I32){{(int32_t)(1), (int32_t)(1)}} +#define DN_V2I32_From1N(x) DN_Literal(DN_V2I32){{(int32_t)(x), (int32_t)(x)}} +#define DN_V2I32_From2N(x, y) DN_Literal(DN_V2I32){{(int32_t)(x), (int32_t)(y)}} +#define DN_V2I32_InitV2(xy) DN_Literal(DN_V2I32){{(int32_t)(xy).x, (int32_t)(xy).y}} DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs); DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs); @@ -149,10 +135,10 @@ DN_API DN_V2I32 DN_V2I32_Min (DN_V2I32 a, DN DN_API DN_V2I32 DN_V2I32_Max (DN_V2I32 a, DN_V2I32 b); DN_API DN_V2I32 DN_V2I32_Abs (DN_V2I32 a); -#define DN_V2U16_Zero DN_LITERAL(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} -#define DN_V2U16_One DN_LITERAL(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} -#define DN_V2U16_From1N(x) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} -#define DN_V2U16_From2N(x, y) DN_LITERAL(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} +#define DN_V2U16_Zero DN_Literal(DN_V2U16){{(uint16_t)(0), (uint16_t)(0)}} +#define DN_V2U16_One DN_Literal(DN_V2U16){{(uint16_t)(1), (uint16_t)(1)}} +#define DN_V2U16_From1N(x) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(x)}} +#define DN_V2U16_From2N(x, y) DN_Literal(DN_V2U16){{(uint16_t)(x), (uint16_t)(y)}} DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs); DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs); @@ -177,11 +163,11 @@ DN_API DN_V2U16 & operator/= (DN_V2U16& lhs, DN_API DN_V2U16 & operator-= (DN_V2U16& lhs, DN_V2U16 rhs); DN_API DN_V2U16 & operator+= (DN_V2U16& lhs, DN_V2U16 rhs); -#define DN_V2F32_Zero DN_LITERAL(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} -#define DN_V2F32_One DN_LITERAL(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} -#define DN_V2F32_From1N(x) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} -#define DN_V2F32_From2N(x, y) DN_LITERAL(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} -#define DN_V2F32_FromV2I32(xy) DN_LITERAL(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} +#define DN_V2F32_Zero DN_Literal(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}} +#define DN_V2F32_One DN_Literal(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}} +#define DN_V2F32_From1N(x) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}} +#define DN_V2F32_From2N(x, y) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}} +#define DN_V2F32_FromV2I32(xy) DN_Literal(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}} DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs); DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs); @@ -244,12 +230,10 @@ DN_API DN_V2F32 DN_V2F32_Normalise (DN_V2F32 a); DN_API DN_V2F32 DN_V2F32_Perpendicular (DN_V2F32 a); DN_API DN_V2F32 DN_V2F32_Reflect (DN_V2F32 in, DN_V2F32 surface); DN_API DN_F32 DN_V2F32_Area (DN_V2F32 a); -#endif // !defined(DN_NO_V2) -#if !defined(DN_NO_V3) -// NOTE: DN_V3 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V3F32_From1N(x) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V3F32_From3N(x, y, z) DN_LITERAL(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} -#define DN_V3F32_FromV2F32And1N(xy, z) DN_LITERAL(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} + +#define DN_V3F32_From1N(x) DN_Literal(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} +#define DN_V3F32_From3N(x, y, z) DN_Literal(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}} +#define DN_V3F32_FromV2F32And1N(xy, z) DN_Literal(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}} DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs); DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs); @@ -277,19 +261,17 @@ DN_API DN_V3F32 & operator+= (DN_V3F32 &lhs, DN_API DN_F32 DN_V3F32_LengthSq (DN_V3F32 a); DN_API DN_F32 DN_V3F32_Length (DN_V3F32 a); DN_API DN_V3F32 DN_V3F32_Normalise (DN_V3F32 a); -#endif // !defined(DN_NO_V3) -#if !defined(DN_NO_V4) + DN_U32 const DN_V4_R_MASK_U32 = 0xFF000000; DN_U32 const DN_V4_G_MASK_U32 = 0x00FF0000; DN_U32 const DN_V4_B_MASK_U32 = 0x0000FF00; DN_U32 const DN_V4_A_MASK_U32 = 0x000000FF; -// NOTE: DN_V4 ///////////////////////////////////////////////////////////////////////////////////// -#define DN_V4F32_From1N(x) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} -#define DN_V4F32_From4N(x, y, z, w) DN_LITERAL(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} -#define DN_V4F32_FromV3And1N(xyz, w) DN_LITERAL(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} -#define DN_V4F32_FromRGBAU8(r, g, b, a) DN_LITERAL(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, a / 255.f}} -#define DN_V4F32_FromRGBU8(r, g, b) DN_LITERAL(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, 1.f}} +#define DN_V4F32_From1N(x) DN_Literal(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}} +#define DN_V4F32_From4N(x, y, z, w) DN_Literal(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}} +#define DN_V4F32_FromV3And1N(xyz, w) DN_Literal(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}} +#define DN_V4F32_FromRGBAU8(r, g, b, a) DN_Literal(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, a / 255.f}} +#define DN_V4F32_FromRGBU8(r, g, b) DN_Literal(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, 1.f}} DN_API DN_V4F32 DN_V4F32_FromRGBU32(DN_U32 u32); DN_API DN_V4F32 DN_V4F32_FromRGBAU32(DN_U32 u32); #define DN_V4F32_FromV4Alpha(v4, alpha) DN_V4F32_FromV3And1N(v4.xyz, alpha) @@ -311,9 +293,7 @@ DN_API DN_V4F32 & operator*= (DN_V4F32 &lhs, DN_API DN_V4F32 & operator-= (DN_V4F32 &lhs, DN_V4F32 rhs); DN_API DN_V4F32 & operator+= (DN_V4F32 &lhs, DN_V4F32 rhs); DN_API DN_F32 DN_V4F32_Dot (DN_V4F32 a, DN_V4F32 b); -#endif // !defined(DN_NO_V4) -#if !defined(DN_NO_M4) -// NOTE: DN_M4 ///////////////////////////////////////////////////////////////////////////////////// + DN_API DN_M4 DN_M4_Identity (); DN_API DN_M4 DN_M4_ScaleF (DN_F32 x, DN_F32 y, DN_F32 z); DN_API DN_M4 DN_M4_Scale (DN_V3F32 xyz); @@ -332,8 +312,7 @@ DN_API DN_M4 DN_M4_SubF (DN_M4 lhs, DN_ DN_API DN_M4 DN_M4_MulF (DN_M4 lhs, DN_F32 rhs); DN_API DN_M4 DN_M4_DivF (DN_M4 lhs, DN_F32 rhs); DN_API DN_Str8x256 DN_M4_ColumnMajorString (DN_M4 mat); -#endif // !defined(DN_NO_M4) -// NOTE: DN_M2x3 /////////////////////////////////////////////////////////////////////////////////// + DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs); DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs); DN_API DN_M2x3 DN_M2x3_Identity (); @@ -343,10 +322,9 @@ DN_API DN_M2x3 DN_M2x3_Rotate (DN_F32 radians DN_API DN_M2x3 DN_M2x3_Mul (DN_M2x3 m1, DN_M2x3 m2); DN_API DN_V2F32 DN_M2x3_Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y); DN_API DN_V2F32 DN_M2x3_MulV2 (DN_M2x3 m1, DN_V2F32 v2); -#if !defined(DN_NO_RECT) -// NOTE: DN_Rect /////////////////////////////////////////////////////////////////////////////////// -#define DN_Rect_From2V2(pos, size) DN_LITERAL(DN_Rect){(pos), (size)} -#define DN_Rect_From4N(x, y, w, h) DN_LITERAL(DN_Rect){DN_LITERAL(DN_V2F32){{x, y}}, DN_LITERAL(DN_V2F32){{w, h}}} + +#define DN_Rect_From2V2(pos, size) DN_Literal(DN_Rect){(pos), (size)} +#define DN_Rect_From4N(x, y, w, h) DN_Literal(DN_Rect){DN_Literal(DN_V2F32){{x, y}}, DN_Literal(DN_V2F32){{w, h}}} DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs); DN_API DN_V2F32 DN_Rect_Center (DN_Rect rect); @@ -381,13 +359,12 @@ DN_API DN_Rect DN_Rect_CutBottomClip (DN_Rect *rect, #define DN_Rect_CutBottomNoClip(rect, amount) DN_Rect_CutBottomClip(rect, amount, DN_RectCutClip_No) DN_API DN_Rect DN_RectCut_Cut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip); -#define DN_RectCut_Init(rect, side) DN_LITERAL(DN_RectCut){rect, side} -#define DN_RectCut_Left(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Left} -#define DN_RectCut_Right(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Right} -#define DN_RectCut_Top(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Top} -#define DN_RectCut_Bottom(rect) DN_LITERAL(DN_RectCut){rect, DN_RectCutSide_Bottom} -#endif // !defined(DN_NO_RECT) -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// +#define DN_RectCut_Init(rect, side) DN_Literal(DN_RectCut){rect, side} +#define DN_RectCut_Left(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Left} +#define DN_RectCut_Right(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Right} +#define DN_RectCut_Top(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Top} +#define DN_RectCut_Bottom(rect) DN_Literal(DN_RectCut){rect, DN_RectCutSide_Bottom} + DN_API DN_RaycastLineIntersectV2Result DN_Raycast_LineIntersectV2(DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b); DN_API DN_V2F32 DN_Lerp_V2F32 (DN_V2F32 a, DN_F32 t, DN_V2F32 b); DN_API DN_F32 DN_Lerp_F32 (DN_F32 a, DN_F32 t, DN_F32 b); diff --git a/Source/Extra/dn_tests.cpp b/Source/Extra/dn_tests.cpp index f4e5809..367695d 100644 --- a/Source/Extra/dn_tests.cpp +++ b/Source/Extra/dn_tests.cpp @@ -1814,7 +1814,7 @@ static DN_UTCore DN_Tests_OS() DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_Str8 os_result = DN_OS_EXEDir(tmem.arena); DN_UT_Assert(&result, DN_Str8_HasData(os_result)); - DN_UT_AssertF(&result, DN_OS_DirExists(os_result), "result(%zu): %.*s", os_result.size, DN_STR_FMT(os_result)); + DN_UT_AssertF(&result, DN_OS_PathIsDir(os_result), "result(%zu): %.*s", os_result.size, DN_STR_FMT(os_result)); } for (DN_UT_Test(&result, "DN_OS_PerfCounterNow")) { @@ -1844,11 +1844,11 @@ static DN_UTCore DN_Tests_OS() DN_UT_LogF(&result, "\nDN_OS Filesystem\n"); { for (DN_UT_Test(&result, "Make directory recursive \"abcd/efgh\"")) { - DN_UT_AssertF(&result, DN_OS_MakeDir(DN_STR8("abcd/efgh")), "Failed to make directory"); - DN_UT_AssertF(&result, DN_OS_DirExists(DN_STR8("abcd")), "Directory was not made"); - DN_UT_AssertF(&result, DN_OS_DirExists(DN_STR8("abcd/efgh")), "Subdirectory was not made"); - DN_UT_AssertF(&result, DN_OS_FileExists(DN_STR8("abcd")) == false, "This function should only return true for files"); - DN_UT_AssertF(&result, DN_OS_FileExists(DN_STR8("abcd/efgh")) == false, "This function should only return true for files"); + DN_UT_AssertF(&result, DN_OS_PathMakeDir(DN_STR8("abcd/efgh")), "Failed to make directory"); + DN_UT_AssertF(&result, DN_OS_PathIsDir(DN_STR8("abcd")), "Directory was not made"); + DN_UT_AssertF(&result, DN_OS_PathIsDir(DN_STR8("abcd/efgh")), "Subdirectory was not made"); + DN_UT_AssertF(&result, DN_OS_PathIsFile(DN_STR8("abcd")) == false, "This function should only return true for files"); + DN_UT_AssertF(&result, DN_OS_PathIsFile(DN_STR8("abcd/efgh")) == false, "This function should only return true for files"); DN_UT_AssertF(&result, DN_OS_PathDelete(DN_STR8("abcd/efgh")), "Failed to delete directory"); DN_UT_AssertF(&result, DN_OS_PathDelete(DN_STR8("abcd")), "Failed to cleanup directory"); } @@ -1856,29 +1856,29 @@ static DN_UTCore DN_Tests_OS() for (DN_UT_Test(&result, "File write, read, copy, move and delete")) { // NOTE: Write step DN_Str8 const SRC_FILE = DN_STR8("dn_result_file"); - DN_B32 write_result = DN_OS_WriteAll(SRC_FILE, DN_STR8("1234"), nullptr); + DN_B32 write_result = DN_OS_FileWriteAll(SRC_FILE, DN_STR8("1234"), nullptr); DN_UT_Assert(&result, write_result); - DN_UT_Assert(&result, DN_OS_FileExists(SRC_FILE)); + DN_UT_Assert(&result, DN_OS_PathIsFile(SRC_FILE)); // NOTE: Read step DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 read_file = DN_OS_ReadAll(tmem.arena, SRC_FILE, nullptr); + DN_Str8 read_file = DN_OS_FileReadAllArena(tmem.arena, SRC_FILE, nullptr); DN_UT_AssertF(&result, DN_Str8_HasData(read_file), "Failed to load file"); DN_UT_AssertF(&result, read_file.size == 4, "File read wrong amount of bytes (%zu)", read_file.size); DN_UT_AssertF(&result, DN_Str8_Eq(read_file, DN_STR8("1234")), "Read %zu bytes instead of the expected 4: '%.*s'", read_file.size, DN_STR_FMT(read_file)); // NOTE: Copy step DN_Str8 const COPY_FILE = DN_STR8("dn_result_file_copy"); - DN_B32 copy_result = DN_OS_CopyFile(SRC_FILE, COPY_FILE, true /*overwrite*/, nullptr); + DN_B32 copy_result = DN_OS_FileCopy(SRC_FILE, COPY_FILE, true /*overwrite*/, nullptr); DN_UT_Assert(&result, copy_result); - DN_UT_Assert(&result, DN_OS_FileExists(COPY_FILE)); + DN_UT_Assert(&result, DN_OS_PathIsFile(COPY_FILE)); // NOTE: Move step DN_Str8 const MOVE_FILE = DN_STR8("dn_result_file_move"); - DN_B32 move_result = DN_OS_MoveFile(COPY_FILE, MOVE_FILE, true /*overwrite*/, nullptr); + DN_B32 move_result = DN_OS_FileMove(COPY_FILE, MOVE_FILE, true /*overwrite*/, nullptr); DN_UT_Assert(&result, move_result); - DN_UT_Assert(&result, DN_OS_FileExists(MOVE_FILE)); - DN_UT_AssertF(&result, DN_OS_FileExists(COPY_FILE) == false, "Moving a file should remove the original"); + DN_UT_Assert(&result, DN_OS_PathIsFile(MOVE_FILE)); + DN_UT_AssertF(&result, DN_OS_PathIsFile(COPY_FILE) == false, "Moving a file should remove the original"); // NOTE: Delete step DN_B32 delete_src_file = DN_OS_PathDelete(SRC_FILE); diff --git a/Source/OS/dn_os.cpp b/Source/OS/dn_os.cpp index a1ae50d..a9e3379 100644 --- a/Source/OS/dn_os.cpp +++ b/Source/OS/dn_os.cpp @@ -1,5 +1,8 @@ #define DN_OS_CPP +#include "../dn_base_inc.h" +#include "../dn_os_inc.h" + #if defined(DN_PLATFORM_POSIX) #include // get_nprocs #include // getpagesize @@ -389,11 +392,9 @@ DN_API uint64_t DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_fre return result; } -#if !defined(DN_NO_OS_FILE_API) -// NOTE: DN_OSPathInfo/File //////////////////////////////////////////////////////////////////////// -DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against) +DN_API bool DN_OS_PathIsOlderThan(DN_Str8 path, DN_Str8 check_against) { - DN_OSPathInfo file_info = DN_OS_PathInfo(file); + DN_OSPathInfo file_info = DN_OS_PathInfo(path); DN_OSPathInfo check_against_info = DN_OS_PathInfo(check_against); bool result = !file_info.exists || file_info.last_write_time_in_s < check_against_info.last_write_time_in_s; return result; @@ -445,44 +446,69 @@ DN_API bool DN_OS_FileWriteF(DN_OSFile *file, DN_OSErrSink *error, DN_FMT_ATTRIB return result; } -// NOTE: R/W Entire File /////////////////////////////////////////////////////////////////////////// -DN_API DN_Str8 DN_OS_ReadAll(DN_Arena *arena, DN_Str8 path, DN_OSErrSink *error) +DN_API DN_Str8 DN_OS_FileReadAll(DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err) { - DN_Str8 result = {}; - if (!arena) - return result; - - // NOTE: Query file size + allocate buffer ///////////////////////////////////////////////////// + // NOTE: Query file size + DN_Str8 result = {}; DN_OSPathInfo path_info = DN_OS_PathInfo(path); if (!path_info.exists) { - DN_OS_ErrSinkAppendF(error, 1, "File does not exist/could not be queried for reading '%.*s'", DN_STR_FMT(path)); + DN_OS_ErrSinkAppendF(err, 1, "File does not exist/could not be queried for reading '%.*s'", DN_STR_FMT(path)); return result; } - DN_ArenaTempMem temp_mem = DN_Arena_TempMemBegin(arena); - result = DN_Str8_Alloc(arena, path_info.size, DN_ZeroMem_No); - if (!DN_Str8_HasData(result)) { - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 buffer_size_str8 = DN_CVT_BytesStr8FromU64AutoTLS(path_info.size); - DN_OS_ErrSinkAppendF(error, 1 /*error_code*/, "Failed to allocate %.*s for reading file '%.*s'", DN_STR_FMT(buffer_size_str8), DN_STR_FMT(path)); - DN_Arena_TempMemEnd(temp_mem); - result = {}; + // NOTE: Allocate + DN_ArenaTempMem arena_tmp = {}; + if (alloc_type == DN_Allocator_Arena) { + DN_Arena *arena = DN_CAST(DN_Arena *) allocator; + arena_tmp = DN_Arena_TempMemBegin(arena); + result = DN_Str8_Alloc(arena, path_info.size, DN_ZeroMem_No); + } else { + DN_Pool *pool = DN_CAST(DN_Pool *) allocator; + result = DN_Str8_AllocPool(pool, path_info.size); + } + + if (!result.data) { + DN_CVTU64Bytes bytes_str = DN_CVT_BytesFromU64Auto(path_info.size); + DN_OS_ErrSinkAppendF(err, 1 /*err_code*/, "Failed to allocate %.1f %.*s for reading file '%.*s'", bytes_str.bytes, DN_STR_FMT(bytes_str.suffix), DN_STR_FMT(path)); return result; } - // NOTE: Read the file from disk /////////////////////////////////////////////////////////////// - DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, error); - DN_OSFileRead read = DN_OS_FileRead(&file, result.data, result.size, error); + // NOTE: Read all + DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_OpenIfExist, DN_OSFileAccess_Read, err); + DN_OSFileRead read = DN_OS_FileRead(&file, result.data, result.size, err); if (file.error || !read.success) { - DN_Arena_TempMemEnd(temp_mem); + if (alloc_type == DN_Allocator_Arena) { + DN_Arena_TempMemEnd(arena_tmp); + } else { + DN_Pool *pool = DN_CAST(DN_Pool *) allocator; + DN_Pool_Dealloc(pool, result.data); + } result = {}; } - DN_OS_FileClose(&file); + DN_OS_FileClose(&file); return result; } -DN_API bool DN_OS_WriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) +DN_API DN_Str8 DN_OS_FileReadAllArena(DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err) +{ + DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Arena, arena, path, err); + return result; +} + +DN_API DN_Str8 DN_OS_FileReadAllPool(DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err) +{ + DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Pool, pool, path, err); + return result; +} + +DN_API DN_Str8 DN_OS_FileReadAllTLS(DN_Str8 path, DN_OSErrSink *err) +{ + DN_Str8 result = DN_OS_FileReadAll(DN_Allocator_Arena, DN_OS_TLSArena(), path, err); + return result; +} + +DN_API bool DN_OS_FileWriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) { DN_OSFile file = DN_OS_FileOpen(path, DN_OSFileOpen_CreateAlways, DN_OSFileAccess_Write, error); bool result = DN_OS_FileWrite(&file, buffer, error); @@ -490,54 +516,52 @@ DN_API bool DN_OS_WriteAll(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) return result; } -DN_API bool DN_OS_WriteAllFV(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) +DN_API bool DN_OS_FileWriteAllFV(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) { DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str8 buffer = DN_Str8_FromFV(tmem.arena, fmt, args); - bool result = DN_OS_WriteAll(file_path, buffer, error); + DN_Str8 buffer = DN_Str8_FromFV(tmem.arena, fmt, args); + bool result = DN_OS_FileWriteAll(file_path, buffer, error); return result; } -DN_API bool DN_OS_WriteAllF(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_OS_FileWriteAllF(DN_Str8 file_path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - bool result = DN_OS_WriteAllFV(file_path, error, fmt, args); + bool result = DN_OS_FileWriteAllFV(file_path, error, fmt, args); va_end(args); return result; } -DN_API bool DN_OS_WriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) +DN_API bool DN_OS_FileWriteAllSafe(DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *error) { DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_Str8 tmp_path = DN_Str8_FromF(tmem.arena, "%.*s.tmp", DN_STR_FMT(path)); - if (!DN_OS_WriteAll(tmp_path, buffer, error)) + if (!DN_OS_FileWriteAll(tmp_path, buffer, error)) return false; - if (!DN_OS_CopyFile(tmp_path, path, true /*overwrite*/, error)) + if (!DN_OS_FileCopy(tmp_path, path, true /*overwrite*/, error)) return false; if (!DN_OS_PathDelete(tmp_path)) return false; return true; } -DN_API bool DN_OS_WriteAllSafeFV(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) +DN_API bool DN_OS_FileWriteAllSafeFV(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, va_list args) { DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); DN_Str8 buffer = DN_Str8_FromFV(tmem.arena, fmt, args); - bool result = DN_OS_WriteAllSafe(path, buffer, error); + bool result = DN_OS_FileWriteAllSafe(path, buffer, error); return result; } -DN_API bool DN_OS_WriteAllSafeF(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) +DN_API bool DN_OS_FileWriteAllSafeF(DN_Str8 path, DN_OSErrSink *error, DN_FMT_ATTRIB char const *fmt, ...) { va_list args; va_start(args, fmt); - bool result = DN_OS_WriteAllSafeFV(path, error, fmt, args); + bool result = DN_OS_FileWriteAllSafeFV(path, error, fmt, args); return result; } -#endif // !defined(DN_NO_OS_FILE_API) -// NOTE: DN_OSPath ///////////////////////////////////////////////////////////////////////////////// DN_API bool DN_OS_PathAddRef(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path) { if (!arena || !fs_path || !DN_Str8_HasData(path)) @@ -581,6 +605,18 @@ DN_API bool DN_OS_PathAddRef(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path) return true; } +DN_API bool DN_OS_PathAddRefTLS(DN_OSPath *fs_path, DN_Str8 path) +{ + bool result = DN_OS_PathAddRef(DN_OS_TLSTopArena(), fs_path, path); + return result; +} + +DN_API bool DN_OS_PathAddRefFrame(DN_OSPath *fs_path, DN_Str8 path) +{ + bool result = DN_OS_PathAddRef(DN_OS_TLSFrameArena(), fs_path, path); + return result; +} + DN_API bool DN_OS_PathAdd(DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path) { DN_Str8 copy = DN_Str8_FromStr8(arena, path); diff --git a/Source/OS/dn_os.h b/Source/OS/dn_os.h index ff427bf..15115ca 100644 --- a/Source/OS/dn_os.h +++ b/Source/OS/dn_os.h @@ -1,6 +1,9 @@ #if !defined(DN_OS_H) #define DN_OS_H +#include "../dn_base_inc.h" +#include "../dn_os_inc.h" + #include // operator new #if !defined(DN_OS_WIN32) || defined(DN_OS_WIN32_USE_PTHREADS) @@ -302,94 +305,87 @@ struct DN_OSDiskSpace DN_U64 size; }; -DN_API void DN_OS_Init (DN_OSCore *os, DN_OSInitArgs *args); -DN_API void DN_OS_EmitLogsWithOSPrintFunctions(DN_OSCore *os); -DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path); +DN_API void DN_OS_Init (DN_OSCore *os, DN_OSInitArgs *args); +DN_API void DN_OS_EmitLogsWithOSPrintFunctions (DN_OSCore *os); +DN_API void DN_OS_DumpThreadContextArenaStat (DN_Str8 file_path); -// NOTE: Memory //////////////////////////////////////////////////////////////////////////////////// -DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags); -DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags); -DN_API void DN_OS_MemDecommit(void *ptr, DN_USize size); -DN_API void DN_OS_MemRelease (void *ptr, DN_USize size); -DN_API int DN_OS_MemProtect (void *ptr, DN_USize size, DN_U32 page_flags); +DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags); +DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags); +DN_API void DN_OS_MemDecommit (void *ptr, DN_USize size); +DN_API void DN_OS_MemRelease (void *ptr, DN_USize size); +DN_API int DN_OS_MemProtect (void *ptr, DN_USize size, DN_U32 page_flags); -// NOTE: Heap -DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZeroMem zero_mem); -DN_API void DN_OS_MemDealloc (void *ptr); +DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZeroMem zero_mem); +DN_API void DN_OS_MemDealloc (void *ptr); -// NOTE: DN_OSDate ///////////////////////////////////////////////////////////////////////////////// -DN_API DN_OSDateTime DN_OS_DateLocalTimeNow (); -DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now(char date_separator = '-', char hms_separator = ':'); -DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':'); -DN_API DN_U64 DN_OS_DateUnixTimeNs (); -#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000) -#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000)) -#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000)) -DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time); -DN_API DN_U64 DN_OS_DateLocalToUnixTimeS(DN_OSDateTime date); -DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date); -DN_API bool DN_OS_DateIsValid (DN_OSDateTime date); +DN_API DN_OSDateTime DN_OS_DateLocalTimeNow (); +DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':'); +DN_API DN_OSDateTimeStr8 DN_OS_DateLocalTimeStr8 (DN_OSDateTime time, char date_separator = '-', char hms_separator = ':'); +DN_API DN_U64 DN_OS_DateUnixTimeNs (); +#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000) +#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000)) +#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000)) +DN_API DN_OSDateTime DN_OS_DateUnixTimeSToDate (DN_U64 time); +DN_API DN_U64 DN_OS_DateLocalToUnixTimeS (DN_OSDateTime date); +DN_API DN_U64 DN_OS_DateToUnixTimeS (DN_OSDateTime date); +DN_API bool DN_OS_DateIsValid (DN_OSDateTime date); -// NOTE: Other ///////////////////////////////////////////////////////////////////////////////////// -DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); -DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); -DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path); -DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena); -DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena); -#define DN_OS_EXEDirFromTLS() DN_OS_EXEDir(DN_OS_TLSTopArena()) -DN_API void DN_OS_SleepMs (DN_UInt milliseconds); +DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size); +DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value); +DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path); +DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena); +DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena); +#define DN_OS_EXEDirFromTLS() DN_OS_EXEDir(DN_OS_TLSTopArena()) +DN_API void DN_OS_SleepMs (DN_UInt milliseconds); -// NOTE: Counters ////////////////////////////////////////////////////////////////////////////////// -DN_API DN_U64 DN_OS_PerfCounterNow (); -DN_API DN_U64 DN_OS_PerfCounterFrequency(); -DN_API DN_F64 DN_OS_PerfCounterS (DN_U64 begin, uint64_t end); -DN_API DN_F64 DN_OS_PerfCounterMs (DN_U64 begin, uint64_t end); -DN_API DN_F64 DN_OS_PerfCounterUs (DN_U64 begin, uint64_t end); -DN_API DN_F64 DN_OS_PerfCounterNs (DN_U64 begin, uint64_t end); -DN_API DN_OSTimer DN_OS_TimerBegin (); -DN_API void DN_OS_TimerEnd (DN_OSTimer *timer); -DN_API DN_F64 DN_OS_TimerS (DN_OSTimer timer); -DN_API DN_F64 DN_OS_TimerMs (DN_OSTimer timer); -DN_API DN_F64 DN_OS_TimerUs (DN_OSTimer timer); -DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer); -DN_API DN_U64 DN_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_frequency); -#if !defined(DN_NO_OS_FILE_API) -// NOTE: File system paths ///////////////////////////////////////////////////////////////////////// -DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path); -DN_API bool DN_OS_FileIsOlderThan(DN_Str8 file, DN_Str8 check_against); -DN_API bool DN_OS_PathDelete (DN_Str8 path); -DN_API bool DN_OS_FileExists (DN_Str8 path); -DN_API bool DN_OS_CopyFile (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); -DN_API bool DN_OS_MoveFile (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); -DN_API bool DN_OS_MakeDir (DN_Str8 path); -DN_API bool DN_OS_DirExists (DN_Str8 path); -DN_API bool DN_OS_DirIterate (DN_Str8 path, DN_OSDirIterator *it); +DN_API DN_U64 DN_OS_PerfCounterNow (); +DN_API DN_U64 DN_OS_PerfCounterFrequency (); +DN_API DN_F64 DN_OS_PerfCounterS (DN_U64 begin, uint64_t end); +DN_API DN_F64 DN_OS_PerfCounterMs (DN_U64 begin, uint64_t end); +DN_API DN_F64 DN_OS_PerfCounterUs (DN_U64 begin, uint64_t end); +DN_API DN_F64 DN_OS_PerfCounterNs (DN_U64 begin, uint64_t end); +DN_API DN_OSTimer DN_OS_TimerBegin (); +DN_API void DN_OS_TimerEnd (DN_OSTimer *timer); +DN_API DN_F64 DN_OS_TimerS (DN_OSTimer timer); +DN_API DN_F64 DN_OS_TimerMs (DN_OSTimer timer); +DN_API DN_F64 DN_OS_TimerUs (DN_OSTimer timer); +DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer); +DN_API DN_U64 DN_OS_EstimateTSCPerSecond (uint64_t duration_ms_to_gauge_tsc_frequency); -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// -DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_OSErrSink *err); -DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err); -DN_API bool DN_OS_FileWritePtr(DN_OSFile *file, void const *data, DN_USize size, DN_OSErrSink *err); -DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *err); -DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); -DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_OSErrSink *err); -DN_API void DN_OS_FileClose (DN_OSFile *file); +DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); +DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err); -// NOTE: R/W Entire File /////////////////////////////////////////////////////////////////////////// -DN_API DN_Str8 DN_OS_ReadAll (DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err); -#define DN_OS_ReadAllFromTLS(...) DN_OS_ReadAll(DN_OS_TLSTopArena(), ##__VA_ARGS__) -DN_API bool DN_OS_WriteAll (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); -DN_API bool DN_OS_WriteAllFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_WriteAllF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); -DN_API bool DN_OS_WriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); -DN_API bool DN_OS_WriteAllSafeFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_WriteAllSafeF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); -#endif // !defined(DN_NO_OS_FILE_API) +DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_OSErrSink *err); +DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_OSErrSink *err); +DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_OSErrSink *err); +DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_OSErrSink *err); +DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_OSErrSink *err); +DN_API void DN_OS_FileClose (DN_OSFile *file); + +DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_OSErrSink *err); +DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_OSErrSink *err); +DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_OSErrSink *err); +DN_API DN_Str8 DN_OS_FileReadAllTLS (DN_Str8 path, DN_OSErrSink *err); +DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); +DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); +DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_OSErrSink *err); +DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_OSErrSink *err, DN_FMT_ATTRIB char const *fmt, ...); + +DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path); +DN_API bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against); +DN_API bool DN_OS_PathDelete (DN_Str8 path); +DN_API bool DN_OS_PathIsFile (DN_Str8 path); +DN_API bool DN_OS_PathIsDir (DN_Str8 path); +DN_API bool DN_OS_PathMakeDir (DN_Str8 path); +DN_API bool DN_OS_PathIterateDir (DN_Str8 path, DN_OSDirIterator *it); -// NOTE: File system paths ///////////////////////////////////////////////////////////////////////// DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); -#define DN_OS_PathAddRefFromTLS(...) DN_OS_PathAddRef(DN_OS_TLSTopArena(), ##__VA_ARGS__) -#define DN_OS_PathAddRefFromFrame(...) DN_OS_PathAddRef(DN_OS_TLSFrameArena(), ##__VA_ARGS__) +DN_API bool DN_OS_PathAddRefTLS (DN_OSPath *fs_path, DN_Str8 path); +DN_API bool DN_OS_PathAddRefFrame (DN_OSPath *fs_path, DN_Str8 path); DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path); #define DN_OS_PathAddFromTLS(...) DN_OS_PathAdd(DN_OS_TLSTopArena(), ##__VA_ARGS__) #define DN_OS_PathAddFromFrame(...) DN_OS_PathAdd(DN_OS_TLSFrameArena(), ##__VA_ARGS__) @@ -417,41 +413,40 @@ DN_API DN_Str8 DN_OS_PathF (D #define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_STR8("\\")) #define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString) -// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// -DN_API void DN_OS_Exit (int32_t exit_code); -DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_OSErrSink *err); -DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err); -DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err); -DN_API DN_OSExecResult DN_OS_Exec (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_OSErrSink *err); -DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena); -#define DN_OS_ExecOrAbortFromTLS(...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena()) +DN_API void DN_OS_Exit (int32_t exit_code); +DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_OSErrSink *err); +DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_OSErrSink *err); +DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Slice cmd_line, DN_OSExecArgs *args, DN_OSErrSink *err); +DN_API DN_OSExecResult DN_OS_Exec (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_OSErrSink *err); +DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena); +#define DN_OS_ExecOrAbortFromTLS (...) DN_OS_ExecOrAbort(__VA_ARGS__, DN_OS_TLSTopArena()) -DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count); -DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore); -DN_API void DN_OS_SemaphoreDeinit (DN_OSSemaphore *semaphore); -DN_API void DN_OS_SemaphoreIncrement(DN_OSSemaphore *semaphore, DN_U32 amount); -DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait (DN_OSSemaphore *semaphore, DN_U32 timeout_ms); +DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count); +DN_API bool DN_OS_SemaphoreIsValid (DN_OSSemaphore *semaphore); +DN_API void DN_OS_SemaphoreDeinit (DN_OSSemaphore *semaphore); +DN_API void DN_OS_SemaphoreIncrement (DN_OSSemaphore *semaphore, DN_U32 amount); +DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait (DN_OSSemaphore *semaphore, DN_U32 timeout_ms); -DN_API DN_OSMutex DN_OS_MutexInit (); -DN_API void DN_OS_MutexDeinit(DN_OSMutex *mutex); -DN_API void DN_OS_MutexLock (DN_OSMutex *mutex); -DN_API void DN_OS_MutexUnlock(DN_OSMutex *mutex); -#define DN_OS_MutexScope(mutex) DN_DeferLoop(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex)) +DN_API DN_OSMutex DN_OS_MutexInit (); +DN_API void DN_OS_MutexDeinit (DN_OSMutex *mutex); +DN_API void DN_OS_MutexLock (DN_OSMutex *mutex); +DN_API void DN_OS_MutexUnlock (DN_OSMutex *mutex); +#define DN_OS_MutexScope (mutex) DN_DeferLoop(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex)) -DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit (); -DN_API void DN_OS_ConditionVariableDeinit (DN_OSConditionVariable *cv); -DN_API bool DN_OS_ConditionVariableWait (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 sleep_ms); -DN_API bool DN_OS_ConditionVariableWaitUntil(DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 end_ts_ms); -DN_API void DN_OS_ConditionVariableSignal (DN_OSConditionVariable *cv); -DN_API void DN_OS_ConditionVariableBroadcast(DN_OSConditionVariable *cv); +DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit (); +DN_API void DN_OS_ConditionVariableDeinit (DN_OSConditionVariable *cv); +DN_API bool DN_OS_ConditionVariableWait (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 sleep_ms); +DN_API bool DN_OS_ConditionVariableWaitUntil (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 end_ts_ms); +DN_API void DN_OS_ConditionVariableSignal (DN_OSConditionVariable *cv); +DN_API void DN_OS_ConditionVariableBroadcast (DN_OSConditionVariable *cv); -DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context); -DN_API void DN_OS_ThreadDeinit(DN_OSThread *thread); -DN_API DN_U32 DN_OS_ThreadID (); -DN_API void DN_OS_ThreadSetName(DN_Str8 name); +DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, void *user_context); +DN_API void DN_OS_ThreadDeinit (DN_OSThread *thread); +DN_API DN_U32 DN_OS_ThreadID (); +DN_API void DN_OS_ThreadSetName (DN_Str8 name); -DN_API void DN_OS_HttpRequestAsync(DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); -DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response); -DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response); -DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); +DN_API void DN_OS_HttpRequestAsync (DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); +DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response); +DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response); +DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers); #endif // !defined(DN_OS_H) diff --git a/Source/OS/dn_os_allocator.h b/Source/OS/dn_os_allocator.h index 81a74c0..b1b5532 100644 --- a/Source/OS/dn_os_allocator.h +++ b/Source/OS/dn_os_allocator.h @@ -1,7 +1,7 @@ #if !defined(DN_OS_ALLOCATOR_H) #define DN_OS_ALLOCATOR_H -DN_API DN_Arena DN_Arena_FromOSHeap(DN_U64 size, DN_ArenaFlags flags); +DN_API DN_Arena DN_Arena_FromHeap(DN_U64 size, DN_ArenaFlags flags); DN_API DN_Arena DN_Arena_FromVMem(DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags); #endif // !defined(DN_OS_ALLOCATOR_H) diff --git a/Source/OS/dn_os_posix.cpp b/Source/OS/dn_os_posix.cpp index f454076..4ef47c1 100644 --- a/Source/OS/dn_os_posix.cpp +++ b/Source/OS/dn_os_posix.cpp @@ -196,7 +196,7 @@ DN_API DN_OSDiskSpace DN_OS_DiskSpace(DN_Str8 path) { DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); DN_OSDiskSpace result = {}; - DN_Str8 path_z_terminated = DN_Str8_Copy(tmem.arena, path); + DN_Str8 path_z_terminated = DN_Str8_FromStr8(tmem.arena, path); struct statvfs info = {}; if (statvfs(path_z_terminated.data, &info) != 0) @@ -297,52 +297,7 @@ DN_API DN_U64 DN_OS_PerfCounterNow() return result; } -#if !defined(DN_NO_OS_FILE_API) -DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) -{ - DN_OSPathInfo result = {}; - if (!DN_Str8_HasData(path)) - return result; - - struct stat file_stat; - if (lstat(path.data, &file_stat) != -1) { - result.exists = true; - result.size = file_stat.st_size; - result.last_access_time_in_s = file_stat.st_atime; - result.last_write_time_in_s = file_stat.st_mtime; - // TODO(dn): Seems linux does not support creation time via stat. We - // shoddily deal with this. - result.create_time_in_s = DN_Min(result.last_access_time_in_s, result.last_write_time_in_s); - - if (S_ISDIR(file_stat.st_mode)) - result.type = DN_OSPathInfoType_Directory; - else if (S_ISREG(file_stat.st_mode)) - result.type = DN_OSPathInfoType_File; - } - return result; -} - -DN_API bool DN_OS_PathDelete(DN_Str8 path) -{ - bool result = false; - if (DN_Str8_HasData(path)) - result = remove(path.data) == 0; - return result; -} - -DN_API bool DN_OS_FileExists(DN_Str8 path) -{ - bool result = false; - if (!DN_Str8_HasData(path)) - return result; - - struct stat stat_result; - if (lstat(path.data, &stat_result) != -1) - result = S_ISREG(stat_result.st_mode) || S_ISLNK(stat_result.st_mode); - return result; -} - -DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) +DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) { bool result = false; #if defined(DN_PLATFORM_EMSCRIPTEN) @@ -417,7 +372,7 @@ DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi return result; } -DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) +DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *error) { // See: https://github.com/gingerBill/gb/blob/master/gb.h bool result = false; @@ -425,7 +380,7 @@ DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi if (link(src.data, dest.data) == -1) { // NOTE: Link can fail if we're trying to link across different volumes // so we fall back to a binary directory. - file_moved |= DN_OS_CopyFile(src, dest, overwrite, error); + file_moved |= DN_OS_FileCopy(src, dest, overwrite, error); } if (file_moved) { @@ -445,108 +400,6 @@ DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi return result; } -DN_API bool DN_OS_MakeDir(DN_Str8 path) -{ - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - bool result = true; - - // TODO(doyle): Implement this without using the path indexes, it's not - // necessary. See Windows implementation. - DN_USize path_indexes_size = 0; - uint16_t path_indexes[64] = {}; - - DN_Str8 copy = DN_Str8_Copy(tmem.arena, path); - for (DN_USize index = copy.size - 1; index < copy.size; index--) { - bool first_char = index == (copy.size - 1); - char ch = copy.data[index]; - if (ch == '/' || first_char) { - char temp = copy.data[index]; - - if (!first_char) - copy.data[index] = 0; // Temporarily null terminate it - - bool is_file = DN_OS_FileExists(copy); - - if (!first_char) - copy.data[index] = temp; // Undo null termination - - if (is_file) { - // NOTE: There's something that exists in at this path, but - // it's not a directory. This request to make a directory is - // invalid. - return false; - } else if (DN_OS_DirExists(copy)) { - // NOTE: We found a directory, we can stop here and start - // building up all the directories that didn't exist up to - // this point. - break; - } else { - // NOTE: There's nothing that exists at this path, we can - // create a directory here - path_indexes[path_indexes_size++] = DN_CAST(uint16_t) index; - } - } - } - - for (DN_USize index = path_indexes_size - 1; result && index < path_indexes_size; index--) { - uint16_t path_index = path_indexes[index]; - char temp = copy.data[path_index]; - - if (index != 0) - copy.data[path_index] = 0; - result |= mkdir(copy.data, 0774) == 0; - if (index != 0) - copy.data[path_index] = temp; - } - return result; -} - -DN_API bool DN_OS_DirExists(DN_Str8 path) -{ - bool result = false; - if (!DN_Str8_HasData(path)) - return result; - - struct stat stat_result; - if (lstat(path.data, &stat_result) != -1) - result = S_ISDIR(stat_result.st_mode); - return result; -} - -DN_API bool DN_OS_DirIterate(DN_Str8 path, DN_OSDirIterator *it) -{ - if (!it->handle) { - it->handle = opendir(path.data); - if (!it->handle) - return false; - } - - struct dirent *entry; - for (;;) { - entry = readdir(DN_CAST(DIR *) it->handle); - if (entry == NULL) - break; - - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - - DN_USize name_size = DN_CStr8_Size(entry->d_name); - DN_USize clamped_size = DN_Min(sizeof(it->buffer) - 1, name_size); - DN_AssertF(name_size == clamped_size, "name: %s, name_size: %zu, clamped_size: %zu", entry->d_name, name_size, clamped_size); - DN_Memcpy(it->buffer, entry->d_name, clamped_size); - it->buffer[clamped_size] = 0; - it->file_name = DN_Str8_Init(it->buffer, clamped_size); - return true; - } - - closedir(DN_CAST(DIR *) it->handle); - it->handle = NULL; - it->file_name = {}; - it->buffer[0] = 0; - return false; -} - -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, @@ -678,9 +531,152 @@ DN_API void DN_OS_FileClose(DN_OSFile *file) fclose(DN_CAST(FILE *) file->handle); *file = {}; } -#endif // !defined(DN_NO_OS_FILE_API) -// NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// +DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) +{ + DN_OSPathInfo result = {}; + if (!DN_Str8_HasData(path)) + return result; + + struct stat file_stat; + if (lstat(path.data, &file_stat) != -1) { + result.exists = true; + result.size = file_stat.st_size; + result.last_access_time_in_s = file_stat.st_atime; + result.last_write_time_in_s = file_stat.st_mtime; + // TODO(dn): Seems linux does not support creation time via stat. We + // shoddily deal with this. + result.create_time_in_s = DN_Min(result.last_access_time_in_s, result.last_write_time_in_s); + + if (S_ISDIR(file_stat.st_mode)) + result.type = DN_OSPathInfoType_Directory; + else if (S_ISREG(file_stat.st_mode)) + result.type = DN_OSPathInfoType_File; + } + return result; +} + +DN_API bool DN_OS_PathDelete(DN_Str8 path) +{ + bool result = false; + if (DN_Str8_HasData(path)) + result = remove(path.data) == 0; + return result; +} + +DN_API bool DN_OS_PathIsFile(DN_Str8 path) +{ + bool result = false; + if (!DN_Str8_HasData(path)) + return result; + + struct stat stat_result; + if (lstat(path.data, &stat_result) != -1) + result = S_ISREG(stat_result.st_mode) || S_ISLNK(stat_result.st_mode); + return result; +} + +DN_API bool DN_OS_PathIsDir(DN_Str8 path) +{ + bool result = false; + if (!DN_Str8_HasData(path)) + return result; + + struct stat stat_result; + if (lstat(path.data, &stat_result) != -1) + result = S_ISDIR(stat_result.st_mode); + return result; +} + +DN_API bool DN_OS_PathMakeDir(DN_Str8 path) +{ + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + bool result = true; + + // TODO(doyle): Implement this without using the path indexes, it's not + // necessary. See Windows implementation. + DN_USize path_indexes_size = 0; + uint16_t path_indexes[64] = {}; + + DN_Str8 copy = DN_Str8_FromStr8(tmem.arena, path); + for (DN_USize index = copy.size - 1; index < copy.size; index--) { + bool first_char = index == (copy.size - 1); + char ch = copy.data[index]; + if (ch == '/' || first_char) { + char temp = copy.data[index]; + + if (!first_char) + copy.data[index] = 0; // Temporarily null terminate it + + bool is_file = DN_OS_PathIsFile(copy); + + if (!first_char) + copy.data[index] = temp; // Undo null termination + + if (is_file) { + // NOTE: There's something that exists in at this path, but + // it's not a directory. This request to make a directory is + // invalid. + return false; + } else if (DN_OS_PathIsDir(copy)) { + // NOTE: We found a directory, we can stop here and start + // building up all the directories that didn't exist up to + // this point. + break; + } else { + // NOTE: There's nothing that exists at this path, we can + // create a directory here + path_indexes[path_indexes_size++] = DN_CAST(uint16_t) index; + } + } + } + + for (DN_USize index = path_indexes_size - 1; result && index < path_indexes_size; index--) { + uint16_t path_index = path_indexes[index]; + char temp = copy.data[path_index]; + + if (index != 0) + copy.data[path_index] = 0; + result |= mkdir(copy.data, 0774) == 0; + if (index != 0) + copy.data[path_index] = temp; + } + return result; +} + +DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it) +{ + if (!it->handle) { + it->handle = opendir(path.data); + if (!it->handle) + return false; + } + + struct dirent *entry; + for (;;) { + entry = readdir(DN_CAST(DIR *) it->handle); + if (entry == NULL) + break; + + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + + DN_USize name_size = DN_CStr8_Size(entry->d_name); + DN_USize clamped_size = DN_Min(sizeof(it->buffer) - 1, name_size); + DN_AssertF(name_size == clamped_size, "name: %s, name_size: %zu, clamped_size: %zu", entry->d_name, name_size, clamped_size); + DN_Memcpy(it->buffer, entry->d_name, clamped_size); + it->buffer[clamped_size] = 0; + it->file_name = DN_Str8_Init(it->buffer, clamped_size); + return true; + } + + closedir(DN_CAST(DIR *) it->handle); + it->handle = NULL; + it->file_name = {}; + it->buffer[0] = 0; + return false; +} + DN_API void DN_OS_Exit(int32_t exit_code) { exit(DN_CAST(int) exit_code); @@ -914,7 +910,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, for (DN_ForIndexU(arg_index, cmd_line.size)) { DN_Str8 arg = cmd_line.data[arg_index]; - argv[arg_index] = DN_Str8_Copy(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated + argv[arg_index] = DN_Str8_FromStr8(tmem.arena, arg).data; // NOTE: Copy string to guarantee it is null-terminated } // NOTE: Change the working directory if there is one @@ -932,7 +928,7 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Slice cmd_line, if (args->working_dir.size) { prev_working_dir = get_current_dir_name(); - DN_Str8 working_dir = DN_Str8_Copy(tmem.arena, args->working_dir); + DN_Str8 working_dir = DN_Str8_FromStr8(tmem.arena, args->working_dir); if (chdir(working_dir.data) == -1) { result.os_error_code = errno; DN_OS_ErrSinkAppendF( @@ -1298,7 +1294,7 @@ DN_API void DN_Posix_ThreadSetName(DN_Str8 name) (void)name; #else DN_OSTLSTMem tmem = DN_OS_TLSPushTMem(nullptr); - DN_Str8 copy = DN_Str8_Copy(tmem.arena, name); + DN_Str8 copy = DN_Str8_FromStr8(tmem.arena, name); pthread_t thread = pthread_self(); pthread_setname_np(thread, (char *)copy.data); #endif @@ -1322,7 +1318,7 @@ DN_API DN_POSIXProcSelfStatus DN_Posix_ProcSelfStatus() if (!file.error) { char buf[256]; - DN_Str8Builder builder = DN_Str8Builder_InitFromTLS(); + DN_Str8Builder builder = DN_Str8Builder_FromTLS(); for (;;) { DN_OSFileRead read = DN_OS_FileRead(&file, buf, sizeof(buf), nullptr); if (!read.success || read.bytes_read == 0) diff --git a/Source/OS/dn_os_tls.h b/Source/OS/dn_os_tls.h index 01cba83..f697a89 100644 --- a/Source/OS/dn_os_tls.h +++ b/Source/OS/dn_os_tls.h @@ -1,6 +1,9 @@ #if !defined(DN_OS_TLS_H) #define DN_OS_TLS_H +#include "../dn_base_inc.h" +#include "../dn_os_inc.h" + // NOTE: DN_OSErrSink ///////////////////////////////////////////////////////////////////////////// enum DN_OSErrSinkMode { @@ -87,7 +90,6 @@ struct DN_OSTLSInitArgs DN_U64 err_sink_commit; }; -// NOTE: DN_OSTLS //////////////////////////////////////////////////////////////////////////////////// DN_API void DN_OS_TLSInit (DN_OSTLS *tls, DN_OSTLSInitArgs args); DN_API void DN_OS_TLSDeinit (DN_OSTLS *tls); DN_API DN_OSTLS * DN_OS_TLSGet (); @@ -99,30 +101,29 @@ DN_API void DN_OS_TLSPopArena (); DN_API DN_Arena * DN_OS_TLSTopArena (); DN_API void DN_OS_TLSBeginFrame (DN_Arena *frame_arena); DN_API DN_Arena * DN_OS_TLSFrameArena (); -#define DN_OS_TLSSaveCallSite do { DN_OS_TLSGet()->call_site = DN_CALL_SITE; } while (0) -#define DN_OS_TLSTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_No) -#define DN_OS_TLSPushTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_Yes) +#define DN_OS_TLSSaveCallSite do { DN_OS_TLSGet()->call_site = DN_CALL_SITE; } while (0) +#define DN_OS_TLSTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_No) +#define DN_OS_TLSPushTMem(...) DN_OS_TLSGetTMem(__VA_ARGS__, DN_OSTLSPushTMem_Yes) -// NOTE: DN_OS_ErrSink //////////////////////////////////////////////////////////////////////////// -DN_API DN_OSErrSink * DN_OS_ErrSinkBegin_ (DN_OSErrSinkMode mode, DN_CallSite call_site); -#define DN_OS_ErrSinkBegin(mode) DN_OS_ErrSinkBegin_(mode, DN_CALL_SITE) -#define DN_OS_ErrSinkBeginDefault() DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil) -DN_API bool DN_OS_ErrSinkHasError (DN_OSErrSink *err); -DN_API DN_OSErrSinkMsg *DN_OS_ErrSinkEnd (DN_Arena *arena, DN_OSErrSink *err); -DN_API DN_Str8 DN_OS_ErrSinkEndStr8 (DN_Arena *arena, DN_OSErrSink *err); -DN_API void DN_OS_ErrSinkEndAndIgnore (DN_OSErrSink *err); -DN_API bool DN_OS_ErrSinkEndAndLogError_ (DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 msg); -DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API bool DN_OS_ErrSinkEndAndLogErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); -DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...); -DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API void DN_OS_ErrSinkAppendFV_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args); -DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...); -#define DN_OS_ErrSinkEndAndLogError(err, err_msg) DN_OS_ErrSinkEndAndLogError_(err, DN_CALL_SITE, err_msg) -#define DN_OS_ErrSinkEndAndLogErrorFV(err, fmt, args) DN_OS_ErrSinkEndAndLogErrorFV_(err, DN_CALL_SITE, fmt, args) -#define DN_OS_ErrSinkEndAndLogErrorF(err, fmt, ...) DN_OS_ErrSinkEndAndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__) -#define DN_OS_ErrSinkEndAndExitIfErrorFV(err, exit_val, fmt, args) DN_OS_ErrSinkEndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args) -#define DN_OS_ErrSinkEndAndExitIfErrorF(err, exit_val, fmt, ...) DN_OS_ErrSinkEndAndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__) +DN_API DN_OSErrSink * DN_OS_ErrSinkBegin_ (DN_OSErrSinkMode mode, DN_CallSite call_site); +#define DN_OS_ErrSinkBegin(mode) DN_OS_ErrSinkBegin_(mode, DN_CALL_SITE) +#define DN_OS_ErrSinkBeginDefault() DN_OS_ErrSinkBegin(DN_OSErrSinkMode_Nil) +DN_API bool DN_OS_ErrSinkHasError (DN_OSErrSink *err); +DN_API DN_OSErrSinkMsg * DN_OS_ErrSinkEnd (DN_Arena *arena, DN_OSErrSink *err); +DN_API DN_Str8 DN_OS_ErrSinkEndStr8 (DN_Arena *arena, DN_OSErrSink *err); +DN_API void DN_OS_ErrSinkEndAndIgnore (DN_OSErrSink *err); +DN_API bool DN_OS_ErrSinkEndAndLogError_ (DN_OSErrSink *err, DN_CallSite call_site, DN_Str8 msg); +DN_API bool DN_OS_ErrSinkEndAndLogErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API bool DN_OS_ErrSinkEndAndLogErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_OS_ErrSinkEndAndExitIfErrorF_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...); +DN_API void DN_OS_ErrSinkEndAndExitIfErrorFV_ (DN_OSErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_OS_ErrSinkAppendFV_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, va_list args); +DN_API void DN_OS_ErrSinkAppendF_ (DN_OSErrSink *err, DN_U32 error_code, DN_FMT_ATTRIB char const *fmt, ...); +#define DN_OS_ErrSinkEndAndLogError(err, err_msg) DN_OS_ErrSinkEndAndLogError_(err, DN_CALL_SITE, err_msg) +#define DN_OS_ErrSinkEndAndLogErrorFV(err, fmt, args) DN_OS_ErrSinkEndAndLogErrorFV_(err, DN_CALL_SITE, fmt, args) +#define DN_OS_ErrSinkEndAndLogErrorF(err, fmt, ...) DN_OS_ErrSinkEndAndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__) +#define DN_OS_ErrSinkEndAndExitIfErrorFV(err, exit_val, fmt, args) DN_OS_ErrSinkEndAndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args) +#define DN_OS_ErrSinkEndAndExitIfErrorF(err, exit_val, fmt, ...) DN_OS_ErrSinkEndAndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__) #define DN_OS_ErrSinkAppendFV(error, error_code, fmt, args) \ do { \ diff --git a/Source/OS/dn_os_w32.cpp b/Source/OS/dn_os_w32.cpp index f1883ff..fa7ca81 100644 --- a/Source/OS/dn_os_w32.cpp +++ b/Source/OS/dn_os_w32.cpp @@ -298,7 +298,6 @@ DN_API DN_U64 DN_OS_PerfCounterNow() return result; } -#if !defined(DN_NO_OS_FILE_API) static DN_U64 DN_W32_FileTimeToSeconds_(FILETIME const *time) { ULARGE_INTEGER time_large_int = {}; @@ -308,73 +307,7 @@ static DN_U64 DN_W32_FileTimeToSeconds_(FILETIME const *time) return result; } -DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) -{ - DN_OSPathInfo result = {}; - if (!DN_Str8_HasData(path)) - return result; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); - - WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; - if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) - return result; - - result.exists = true; - result.create_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftCreationTime); - result.last_access_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastAccessTime); - result.last_write_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastWriteTime); - - LARGE_INTEGER large_int = {}; - large_int.u.HighPart = DN_CAST(int32_t) attrib_data.nFileSizeHigh; - large_int.u.LowPart = attrib_data.nFileSizeLow; - result.size = (DN_U64)large_int.QuadPart; - - if (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { - if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - result.type = DN_OSPathInfoType_Directory; - else - result.type = DN_OSPathInfoType_File; - } - - return result; -} - -DN_API bool DN_OS_PathDelete(DN_Str8 path) -{ - bool result = false; - if (!DN_Str8_HasData(path)) - return result; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); - if (path16.size) { - result = DeleteFileW(path16.data); - if (!result) - result = RemoveDirectoryW(path16.data); - } - return result; -} - -DN_API bool DN_OS_FileExists(DN_Str8 path) -{ - bool result = false; - if (!DN_Str8_HasData(path)) - return result; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); - if (path16.size) { - WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; - if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) - result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && - !(attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); - } - return result; -} - -DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err) +DN_API bool DN_OS_FileCopy(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err) { bool result = false; DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); @@ -397,12 +330,12 @@ DN_API bool DN_OS_CopyFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi return result; } -DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err) +DN_API bool DN_OS_FileMove(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSink *err) { - bool result = false; + bool result = false; DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 src16 = DN_W32_Str8ToStr16(tmem.arena, src); - DN_Str16 dest16 = DN_W32_Str8ToStr16(tmem.arena, dest); + DN_Str16 src16 = DN_W32_Str8ToStr16(tmem.arena, src); + DN_Str16 dest16 = DN_W32_Str8ToStr16(tmem.arena, dest); unsigned long flags = MOVEFILE_COPY_ALLOWED; if (overwrite) @@ -412,128 +345,16 @@ DN_API bool DN_OS_MoveFile(DN_Str8 src, DN_Str8 dest, bool overwrite, DN_OSErrSi if (!result) { DN_W32Error win_error = DN_W32_LastError(tmem.arena); DN_OS_ErrSinkAppendF(err, - win_error.code, - "Failed to move file '%.*s' to '%.*s': (%u) %.*s", - DN_STR_FMT(src), - DN_STR_FMT(dest), - win_error.code, - DN_STR_FMT(win_error.msg)); + win_error.code, + "Failed to move file '%.*s' to '%.*s': (%u) %.*s", + DN_STR_FMT(src), + DN_STR_FMT(dest), + win_error.code, + DN_STR_FMT(win_error.msg)); } return result; } -DN_API bool DN_OS_MakeDir(DN_Str8 path) -{ - bool result = true; - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); - - // NOTE: Go back from the end of the string to all the directories in the - // string, and try to create them. Since Win32 API cannot create - // intermediate directories that don't exist in a path we need to go back - // and record all the directories until we encounter one that exists. - // - // From that point onwards go forwards and make all the directories - // inbetween by null-terminating the string temporarily, creating the - // directory and so forth until we reach the end. - // - // If we find a file at some point in the path we fail out because the - // series of directories can not be made if a file exists with the same - // name. - for (DN_USize index = 0; index < path16.size; index++) { - bool first_char = index == (path16.size - 1); - wchar_t ch = path16.data[index]; - if (ch == '/' || ch == '\\' || first_char) { - wchar_t temp = path16.data[index]; - if (!first_char) - path16.data[index] = 0; // Temporarily null terminate it - - WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; - bool successful = GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data); // Check - - if (successful) { - if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - // NOTE: The directory exists, continue iterating the path - } else { - // NOTE: There's some kind of file that exists at the path - // but it's not a directory. This request to make a - // directory is invalid. - return false; - } - } else { - // NOTE: There's nothing that exists at this path, we can create - // a directory here - result |= (CreateDirectoryW(path16.data, nullptr) == 0); - } - - if (!first_char) - path16.data[index] = temp; // Undo null termination - } - } - return result; -} - -DN_API bool DN_OS_DirExists(DN_Str8 path) -{ - bool result = false; - if (!DN_Str8_HasData(path)) - return result; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); - if (path16.size) { - WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; - if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) - result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && - (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); - } - - return result; -} - -DN_API bool DN_OS_DirIterate(DN_Str8 path, DN_OSDirIterator *it) -{ - if (!DN_Str8_HasData(path) || !it || path.size <= 0) - return false; - - DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); - DN_W32FolderIteratorW wide_it = {}; - DN_Str16 path16 = {}; - if (it->handle) { - wide_it.handle = it->handle; - } else { - bool needs_asterisks = DN_Str8_EndsWith(path, DN_STR8("\\")) || - DN_Str8_EndsWith(path, DN_STR8("/")); - bool has_glob = DN_Str8_EndsWith(path, DN_STR8("\\*")) || - DN_Str8_EndsWith(path, DN_STR8("/*")); - - DN_Str8 adjusted_path = path; - if (!has_glob) { - // NOTE: We are missing the glob for enumerating the files, we will - // add those characters in this branch, so overwrite the null - // character, add the glob and re-null terminate the buffer. - if (needs_asterisks) - adjusted_path = DN_OS_PathF(tmem.arena, "%.*s*", DN_STR_FMT(path)); - else - adjusted_path = DN_OS_PathF(tmem.arena, "%.*s/*", DN_STR_FMT(path)); - } - - path16 = DN_W32_Str8ToStr16(tmem.arena, adjusted_path); - if (path16.size <= 0) // Conversion error - return false; - } - - bool result = DN_W32_DirWIterate(path16, &wide_it); - it->handle = wide_it.handle; - if (result) { - int size = DN_W32_Str16ToStr8Buffer(wide_it.file_name, it->buffer, DN_ArrayCountU(it->buffer)); - it->file_name = DN_Str8_Init(it->buffer, size); - } - - return result; -} - -// NOTE: R/W Stream API //////////////////////////////////////////////////////////////////////////// DN_API DN_OSFile DN_OS_FileOpen(DN_Str8 path, DN_OSFileOpen open_mode, DN_U32 access, DN_OSErrSink *err) { DN_OSFile result = {}; @@ -680,7 +501,184 @@ DN_API void DN_OS_FileClose(DN_OSFile *file) CloseHandle(file->handle); *file = {}; } -#endif // !defined(DN_NO_OS_FILE_API) + +DN_API DN_OSPathInfo DN_OS_PathInfo(DN_Str8 path) +{ + DN_OSPathInfo result = {}; + if (!DN_Str8_HasData(path)) + return result; + + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + + WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; + if (!GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) + return result; + + result.exists = true; + result.create_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftCreationTime); + result.last_access_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastAccessTime); + result.last_write_time_in_s = DN_W32_FileTimeToSeconds_(&attrib_data.ftLastWriteTime); + + LARGE_INTEGER large_int = {}; + large_int.u.HighPart = DN_CAST(int32_t) attrib_data.nFileSizeHigh; + large_int.u.LowPart = attrib_data.nFileSizeLow; + result.size = (DN_U64)large_int.QuadPart; + + if (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { + if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + result.type = DN_OSPathInfoType_Directory; + else + result.type = DN_OSPathInfoType_File; + } + + return result; +} + +DN_API bool DN_OS_PathDelete(DN_Str8 path) +{ + bool result = false; + if (!DN_Str8_HasData(path)) + return result; + + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + if (path16.size) { + result = DeleteFileW(path16.data); + if (!result) + result = RemoveDirectoryW(path16.data); + } + return result; +} + +DN_API bool DN_OS_PathIsFile(DN_Str8 path) +{ + bool result = false; + if (!DN_Str8_HasData(path)) + return result; + + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + if (path16.size) { + WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; + if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) + result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && + !(attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + } + return result; +} + +DN_API bool DN_OS_PathIsDir(DN_Str8 path) +{ + bool result = false; + if (!DN_Str8_HasData(path)) + return result; + + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + if (path16.size) { + WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; + if (GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data)) + result = (attrib_data.dwFileAttributes != INVALID_FILE_ATTRIBUTES) && + (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + } + + return result; +} + +DN_API bool DN_OS_PathMakeDir(DN_Str8 path) +{ + bool result = true; + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_Str16 path16 = DN_W32_Str8ToStr16(tmem.arena, path); + + // NOTE: Go back from the end of the string to all the directories in the + // string, and try to create them. Since Win32 API cannot create + // intermediate directories that don't exist in a path we need to go back + // and record all the directories until we encounter one that exists. + // + // From that point onwards go forwards and make all the directories + // inbetween by null-terminating the string temporarily, creating the + // directory and so forth until we reach the end. + // + // If we find a file at some point in the path we fail out because the + // series of directories can not be made if a file exists with the same + // name. + for (DN_USize index = 0; index < path16.size; index++) { + bool first_char = index == (path16.size - 1); + wchar_t ch = path16.data[index]; + if (ch == '/' || ch == '\\' || first_char) { + wchar_t temp = path16.data[index]; + if (!first_char) + path16.data[index] = 0; // Temporarily null terminate it + + WIN32_FILE_ATTRIBUTE_DATA attrib_data = {}; + bool successful = GetFileAttributesExW(path16.data, GetFileExInfoStandard, &attrib_data); // Check + + if (successful) { + if (attrib_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + // NOTE: The directory exists, continue iterating the path + } else { + // NOTE: There's some kind of file that exists at the path + // but it's not a directory. This request to make a + // directory is invalid. + return false; + } + } else { + // NOTE: There's nothing that exists at this path, we can create + // a directory here + result |= (CreateDirectoryW(path16.data, nullptr) == 0); + } + + if (!first_char) + path16.data[index] = temp; // Undo null termination + } + } + return result; +} + +DN_API bool DN_OS_PathIterateDir(DN_Str8 path, DN_OSDirIterator *it) +{ + if (!DN_Str8_HasData(path) || !it || path.size <= 0) + return false; + + DN_OSTLSTMem tmem = DN_OS_TLSTMem(nullptr); + DN_W32FolderIteratorW wide_it = {}; + DN_Str16 path16 = {}; + if (it->handle) { + wide_it.handle = it->handle; + } else { + bool needs_asterisks = DN_Str8_EndsWith(path, DN_STR8("\\")) || + DN_Str8_EndsWith(path, DN_STR8("/")); + bool has_glob = DN_Str8_EndsWith(path, DN_STR8("\\*")) || + DN_Str8_EndsWith(path, DN_STR8("/*")); + + DN_Str8 adjusted_path = path; + if (!has_glob) { + // NOTE: We are missing the glob for enumerating the files, we will + // add those characters in this branch, so overwrite the null + // character, add the glob and re-null terminate the buffer. + if (needs_asterisks) + adjusted_path = DN_OS_PathF(tmem.arena, "%.*s*", DN_STR_FMT(path)); + else + adjusted_path = DN_OS_PathF(tmem.arena, "%.*s/*", DN_STR_FMT(path)); + } + + path16 = DN_W32_Str8ToStr16(tmem.arena, adjusted_path); + if (path16.size <= 0) // Conversion error + return false; + } + + bool result = DN_W32_DirWIterate(path16, &wide_it); + it->handle = wide_it.handle; + if (result) { + int size = DN_W32_Str16ToStr8Buffer(wide_it.file_name, it->buffer, DN_ArrayCountU(it->buffer)); + it->file_name = DN_Str8_Init(it->buffer, size); + } + + return result; +} + // NOTE: DN_OSExec ///////////////////////////////////////////////////////////////////////////////// DN_API void DN_OS_Exit(int32_t exit_code)