diff --git a/build.bat b/build.bat index 3049d1b..9104f1f 100644 --- a/build.bat +++ b/build.bat @@ -1,37 +1,53 @@ @echo OFF -setlocal +setlocal EnableDelayedExpansion + +set script_dir_backslash=%~dp0 +set script_dir=%script_dir_backslash:~0,-1% -set code_dir=%~dp0 if not exist Build mkdir Build pushd Build REM Flags ====================================================================================== - REM MT Static CRT - REM EHa- Disable exception handling - REM GR- Disable C RTTI - REM O2 Optimisation Level 2 - REM Oi Use CPU Intrinsics - REM Z7 Combine multi-debug files to one debug file - REM wd4201 Nonstandard extension used: nameless struct/union - REM Tp Treat header file as CPP source file - set compile_flags=-MT -EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -WX -D DQN_TEST_WITH_MAIN -nologo - set link_flags=-link - set msvc_flags=-fsanitize=address -analyze - set clang_flags=-fsanitize=address,undefined + REM MT Static CRT + REM EHa- Disable exception handling + REM GR- Disable C RTTI + REM O2 Optimisation Level 2 + REM Oi Use CPU Intrinsics + REM Z7 Combine multi-debug files to one debug file + set common_flags=-D DQN_TEST_WITH_MAIN -I %script_dir% %script_dir%\Misc\dqn_unit_tests.cpp - REM Compiler: MSVC cl ========================================================================== - where /q cl || ( - echo [ERROR] cl is not found, please put MSVC's cl on the path - exit /b 1 - ) - cl %compile_flags% %msvc_flags% %code_dir%\Misc\dqn_unit_tests.cpp -I %code_dir% /Fe:dqn_unit_tests_msvc %link_flags% || exit /b 1 + set msvc_driver_flags=%common_flags% -MT -EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -WX -nologo + set msvc_compile_flags=%msvc_driver_flags% -fsanitize=address -analyze /Fe:dqn_unit_tests_msvc + set clang_compile_flags=%msvc_driver_flags% -fsanitize=address -fsanitize=undefined /Fe:dqn_unit_tests_clang + set zig_compile_flags=%common_flags% -fsanitize=address -fsanitize=undefined -o dqn_unit_tests_zig - REM Compiler: clang-cl ========================================================================= - where /q clang-cl || ( - echo [WARN] Optional clang compile via clang-cl if it's in the path, please put clang-cl on the path for this feature - exit /b 0 - ) - clang-cl %compile_flags% %clang_flags% %code_dir%\Misc\dqn_unit_tests.cpp -I %code_dir% /Fe:dqn_unit_tests_clang %link_flags% || exit /b 1 + set msvc_link_flags=-link + set clang_link_flags=%msvc_link_flags% - REM Compiler: zig ============================================================================== - REM zig c++ -g -D DQN_TEST_WITH_MAIN -I %code_dir% %code_dir%\Misc\dqn_unit_tests.cpp -o dqn_unit_tests_zig || exit /b 1 + REM msvc ======================================================================================= + REM set has_msvc=1 + REM where /q cl || set has_msvc=0 + REM if %has_msvc% == 1 ( + REM echo [BUILD] MSVC's cl detected, compiling ... + REM set msvc_cmd=cl %msvc_compile_flags% %msvc_link_flags% + REM powershell -Command "$time = Measure-Command { !msvc_cmd! | Out-Default }; Write-Host '[BUILD] msvc:'$time.TotalSeconds's'; exit $LASTEXITCODE" || exit /b 1 + REM ) + + REM REM clang-cl =================================================================================== + REM set has_clang_cl=1 + REM where /q clang-cl || set has_clang_cl=0 + REM if %has_clang_cl% == 1 ( + REM echo [BUILD] clang-cl detected, compiling ... + REM set clang_cmd=clang-cl %clang_compile_flags% %clang_link_flags% + REM powershell -Command "$time = Measure-Command { !clang_cmd! | Out-Default }; Write-Host '[BUILD] clang-cl:'$time.TotalSeconds's'; exit $LASTEXITCODE" || exit /b 1 + REM ) + + REM zig ======================================================================================== + REM TODO(doyle):Can't build "Misc\dqn_unit_tests.cpp|1 col 1| error: unable to build C object: FileNotFound" + REM set has_zig=1 + REM where /q zig || set has_zig=0 + REM if %has_zig% == 1 ( + REM echo [BUILD] zig detected, compiling ... + REM set zig_cmd=zig c++ %zig_compile_flags% + REM powershell -Command "$time = Measure-Command { !zig_cmd! | Out-Default }; Write-Host '[BUILD] zig:'$time.TotalSeconds's'; exit $LASTEXITCODE" || exit /b 1 + REM ) popd diff --git a/dqn.h b/dqn.h index a269d67..ec6da34 100644 --- a/dqn.h +++ b/dqn.h @@ -191,6 +191,10 @@ // [$ACAT] Dqn_ArenaCatalog | | Collate, create & manage arenas in a catalog #include "dqn_memory.h" +// NOTE: Dqn_Platform Print ======================================================================== +// [$PRIN] Dqn_Print | | Console printing +#include "dqn_platform_print.h" + // NOTE: Dqn_Debug ================================================================================= // [$DEBM] Debug Macros | | // [$CALL] Dqn_CallSite | | Source code location/tracing @@ -244,7 +248,6 @@ #include "dqn_containers.h" // NOTE: Dqn_Platform ============================================================================== -// [$PRIN] Dqn_Print | | Console printing // [$FSYS] Dqn_Fs | DQN_FS | Filesystem helpers // [$DATE] Dqn_Date | | Date-time helpers // [$WIND] Dqn_Win | | Windows OS helpers diff --git a/dqn.rdbg b/dqn.rdbg index a09c161..59baf9f 100644 Binary files a/dqn.rdbg and b/dqn.rdbg differ diff --git a/dqn_base.cpp b/dqn_base.cpp index 3006331..6d45c75 100644 --- a/dqn_base.cpp +++ b/dqn_base.cpp @@ -7,7 +7,7 @@ Dqn_CPUIDRegisters Dqn_CPUID(int function_id) { Dqn_CPUIDRegisters result = {}; - #if defined(DQN_COMPILER_W32_MSVC) + #if defined(DQN_COMPILER_MSVC) __cpuid(DQN_CAST(int *)result.array, function_id); #elif defined(DQN_COMPILER_GCC) || defined(DQN_COMPILER_CLANG) __get_cpuid(function_id, &result.array[0] /*eax*/, &result.array[1] /*ebx*/, &result.array[2] /*ecx*/ , &result.array[3] /*edx*/); @@ -55,7 +55,7 @@ DQN_API bool Dqn_TicketMutex_CanLock(Dqn_TicketMutex const *mutex, Dqn_uint tick return result; } -#if defined(DQN_COMPILER_W32_MSVC) || defined(DQN_COMPILER_W32_CLANG) +#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) #if !defined(DQN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED) #undef _CRT_SECURE_NO_WARNINGS #endif diff --git a/dqn_base.h b/dqn_base.h index 3791791..e12a7f8 100644 --- a/dqn_base.h +++ b/dqn_base.h @@ -1,11 +1,16 @@ +// NOTE: Preprocessor Token Tricks ================================================================= +#define DQN_STRINGIFY(x) #x +#define DQN_TOKEN_COMBINE2(x, y) x ## y +#define DQN_TOKEN_COMBINE(x, y) DQN_TOKEN_COMBINE2(x, y) + // NOTE: [$CMAC] Compiler macros =================================================================== // NOTE: Warning! Order is important here, clang-cl on Windows defines _MSC_VER #if defined(_MSC_VER) #if defined(__clang__) - #define DQN_COMPILER_W32_CLANG + #define DQN_COMPILER_CLANG_CL #define DQN_COMPILER_CLANG #else - #define DQN_COMPILER_W32_MSVC + #define DQN_COMPILER_MSVC #endif #elif defined(__clang__) #define DQN_COMPILER_CLANG @@ -40,7 +45,7 @@ #define DQN_OS_UNIX #endif -#if defined(DQN_COMPILER_W32_MSVC) || defined(DQN_COMPILER_W32_CLANG) +#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) #if defined(_CRT_SECURE_NO_WARNINGS) #define DQN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED #else @@ -48,7 +53,7 @@ #endif #endif -#if defined(DQN_COMPILER_W32_MSVC) +#if defined(DQN_COMPILER_MSVC) #define DQN_FMT_STRING_ANNOTATE _Printf_format_string_ #define DQN_MSVC_WARNING_PUSH __pragma(warning(push)) #define DQN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable: ##__VA_ARGS__)) @@ -60,6 +65,17 @@ #define DQN_MSVC_WARNING_POP #endif +#if defined(DQN_COMPILER_CLANG) || defined(DQN_COMPILER_GCC) || defined(DQN_COMPILER_CLANG_CL) + #define DQN_GCC_WARNING_PUSH _Pragma("GCC diagnostic push") + #define DQN_GCC_WARNING_DISABLE(warning) DQN_GCC_WARNING_DISABLE_HELPER(GCC diagnostic ignored warning) + #define DQN_GCC_WARNING_DISABLE_HELPER(warning) _Pragma(#warning) + #define DQN_GCC_WARNING_POP _Pragma("GCC diagnostic pop") +#else + #define DQN_GCC_WARNING_PUSH + #define DQN_GCC_WARNING_DISABLE(...) + #define DQN_GCC_WARNING_POP +#endif + // NOTE: [$MACR] Macros ============================================================================ #define DQN_FOR_UINDEX(index, size) for (Dqn_usize index = 0; index < size; index++) #define DQN_FOR_IINDEX(index, size) for (Dqn_isize index = 0; index < size; index++) @@ -122,6 +138,14 @@ #define DQN_CLAMP(val, lo, hi) DQN_MAX(DQN_MIN(val, hi), lo) #define DQN_SQUARED(val) ((val) * (val)) +#define DQN_SWAP(a, b) \ + do \ + { \ + auto temp = a; \ + a = b; \ + b = temp; \ + } while (0) + // NOTE: Function/Variable Annotations ============================================================= #if defined(DQN_STATIC_API) #define DQN_API static @@ -133,24 +157,12 @@ #define DQN_FILE_SCOPE static #define DQN_CAST(val) (val) -#if defined(DQN_COMPILER_W32_MSVC) || defined(DQN_COMPILER_W32_CLANG) +#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) #define DQN_FORCE_INLINE __forceinline #else #define DQN_FORCE_INLINE inline __attribute__((always_inline)) #endif -// NOTE: Preprocessor Token Tricks ================================================================= -#define DQN_TOKEN_COMBINE2(x, y) x ## y -#define DQN_TOKEN_COMBINE(x, y) DQN_TOKEN_COMBINE2(x, y) - -#define DQN_SWAP(a, b) \ - do \ - { \ - auto temp = a; \ - a = b; \ - b = temp; \ - } while (0) - // NOTE: Size Macros =============================================================================== #define DQN_ISIZEOF(val) DQN_CAST(ptrdiff_t)sizeof(val) #define DQN_ARRAY_UCOUNT(array) (sizeof(array)/(sizeof((array)[0]))) @@ -314,7 +326,7 @@ struct Dqn_String8 // Execute 'CPUID' instruction to query the capabilities of the current CPU. // NOTE: Dqn_Atomic_Add/Exchange return the previous value store in the target -#if defined(DQN_COMPILER_W32_MSVC) || defined(DQN_COMPILER_W32_CLANG) +#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) #include #define Dqn_Atomic_CompareExchange64(dest, desired_val, prev_val) _InterlockedCompareExchange64((__int64 volatile *)dest, desired_val, prev_val) #define Dqn_Atomic_CompareExchange32(dest, desired_val, prev_val) _InterlockedCompareExchange((long volatile *)dest, desired_val, prev_val) @@ -347,7 +359,7 @@ struct Dqn_String8 DQN_FORCE_INLINE uint64_t Dqn_Atomic_SetValue64(uint64_t volatile *target, uint64_t value) { - #if defined(DQN_COMPILER_W32_MSVC) || defined(DQN_COMPILER_W32_CLANG) + #if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) __int64 result; do { result = *target; @@ -363,7 +375,7 @@ DQN_FORCE_INLINE uint64_t Dqn_Atomic_SetValue64(uint64_t volatile *target, uint6 DQN_FORCE_INLINE long Dqn_Atomic_SetValue32(long volatile *target, long value) { - #if defined(DQN_COMPILER_W32_MSVC) || defined(DQN_COMPILER_W32_CLANG) + #if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) long result; do { result = *target; diff --git a/dqn_debug.h b/dqn_debug.h index 0705029..59b767f 100644 --- a/dqn_debug.h +++ b/dqn_debug.h @@ -3,8 +3,10 @@ #if defined(NDEBUG) #define DQN_DEBUG_BREAK #else - #if defined(DQN_COMPILER_W32_MSVC) || defined(DQN_COMPILER_W32_CLANG) + #if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) #define DQN_DEBUG_BREAK __debugbreak() + #elif defined(DQN_COMPILER_CLANG) + #define DQN_DEBUG_BREAK __builtin_debugtrap() #elif defined(DQN_COMPILER_CLANG) || defined(DQN_COMPILER_GCC) #include #define DQN_DEBUG_BREAK raise(SIGTRAP) diff --git a/dqn_hash.cpp b/dqn_hash.cpp index 79af65f..3eb7ae9 100644 --- a/dqn_hash.cpp +++ b/dqn_hash.cpp @@ -29,7 +29,7 @@ DQN_API uint64_t Dqn_FNV1A64_Hash(void const *bytes, Dqn_usize size) } // NOTE: [$MMUR] Dqn_MurmurHash3 =================================================================== -#if defined(DQN_COMPILER_W32_MSVC) || defined(DQN_COMPILER_W32_CLANG) +#if defined(DQN_COMPILER_MSVC) || defined(DQN_COMPILER_CLANG_CL) #define DQN_MMH3_ROTL32(x, y) _rotl(x, y) #define DQN_MMH3_ROTL64(x, y) _rotl64(x, y) #else diff --git a/dqn_memory.cpp b/dqn_memory.cpp index 56bbf40..2a06558 100644 --- a/dqn_memory.cpp +++ b/dqn_memory.cpp @@ -428,17 +428,9 @@ DQN_API Dqn_ArenaStatString Dqn_Arena_StatString(Dqn_ArenaStat const *stat) { // NOTE: We use a non-standard format string that is only usable via // stb sprintf that GCC warns about as an error. This pragma mutes that. - #if defined(DQN_COMPILER_GCC) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wformat=" - #pragma GCC diagnostic ignored "-Wformat-extra-args" - #elif defined(DQN_COMPILER_W32_CLANG) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wformat" - #pragma GCC diagnostic ignored "-Wformat-invalid-specifier" - #pragma GCC diagnostic ignored "-Wformat-extra-args" - #endif - + DQN_GCC_WARNING_PUSH + DQN_GCC_WARNING_DISABLE("-Wformat-invalid-specifier") + DQN_GCC_WARNING_DISABLE("-Wformat-extra-args") Dqn_ArenaStatString result = {}; int size16 = STB_SPRINTF_DECORATE(snprintf)(result.data, DQN_ARRAY_ICOUNT(result.data), "ArenaStat{" @@ -454,13 +446,7 @@ DQN_API Dqn_ArenaStatString Dqn_Arena_StatString(Dqn_ArenaStat const *stat) stat->blocks, stat->blocks_hwm, stat->syscalls); result.size = Dqn_Safe_SaturateCastIntToU16(size16); - - #if defined(DQN_COMPILER_GCC) - #pragma GCC diagnostic pop - #elif defined(DQN_COMPILER_W32_CLANG) - #pragma GCC diagnostic pop - #endif - + DQN_GCC_WARNING_POP return result; } diff --git a/dqn_platform.cpp b/dqn_platform.cpp index e92cd0d..1d517c2 100644 --- a/dqn_platform.cpp +++ b/dqn_platform.cpp @@ -1,197 +1,3 @@ -// NOTE: [$PRIN] Dqn_Print ========================================================================= -DQN_API Dqn_PrintStyle Dqn_Print_StyleColour(uint8_t r, uint8_t g, uint8_t b, Dqn_PrintBold bold) -{ - Dqn_PrintStyle result = {}; - result.bold = bold; - result.colour = true; - result.r = r; - result.g = g; - result.b = b; - return result; -} - -DQN_API Dqn_PrintStyle Dqn_Print_StyleColourU32(uint32_t rgb, Dqn_PrintBold bold) -{ - uint8_t r = (rgb >> 24) & 0xFF; - uint8_t g = (rgb >> 16) & 0xFF; - uint8_t b = (rgb >> 8) & 0xFF; - Dqn_PrintStyle result = Dqn_Print_StyleColour(r, g, b, bold); - return result; -} - -DQN_API Dqn_PrintStyle Dqn_Print_StyleBold() -{ - Dqn_PrintStyle result = {}; - result.bold = Dqn_PrintBold_Yes; - return result; -} - -DQN_API void Dqn_Print_Std(Dqn_PrintStd std_handle, Dqn_String8 string) -{ - DQN_ASSERT(std_handle == Dqn_PrintStd_Out || std_handle == Dqn_PrintStd_Err); - - #if defined(DQN_OS_WIN32) - // NOTE: Get the output handles from kernel - // ========================================================================= - DQN_THREAD_LOCAL void *std_out_print_handle = nullptr; - DQN_THREAD_LOCAL void *std_err_print_handle = nullptr; - DQN_THREAD_LOCAL bool std_out_print_to_console = false; - DQN_THREAD_LOCAL bool std_err_print_to_console = false; - - if (!std_out_print_handle) { - unsigned long mode = 0; (void)mode; - std_out_print_handle = GetStdHandle(STD_OUTPUT_HANDLE); - std_out_print_to_console = GetConsoleMode(std_out_print_handle, &mode) != 0; - - std_err_print_handle = GetStdHandle(STD_ERROR_HANDLE); - std_err_print_to_console = GetConsoleMode(std_err_print_handle, &mode) != 0; - } - - // NOTE: Select the output handle - // ========================================================================= - void *print_handle = std_out_print_handle; - bool print_to_console = std_out_print_to_console; - if (std_handle == Dqn_PrintStd_Err) { - print_handle = std_err_print_handle; - print_to_console = std_err_print_to_console; - } - - // NOTE: Write the string - // ========================================================================= - DQN_ASSERT(string.size < DQN_CAST(unsigned long)-1); - unsigned long bytes_written = 0; (void)bytes_written; - if (print_to_console) { - WriteConsoleA(print_handle, string.data, DQN_CAST(unsigned long)string.size, &bytes_written, nullptr); - } else { - WriteFile(print_handle, string.data, DQN_CAST(unsigned long)string.size, &bytes_written, nullptr); - } - #else - fprintf(std_handle == Dqn_PrintStd_Out ? stdout : stderr, "%.*s", DQN_STRING_FMT(string)); - #endif -} - -DQN_API void Dqn_Print_StdStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_String8 string) -{ - if (string.data && string.size) { - if (style.colour) - Dqn_Print_Std(std_handle, Dqn_Print_ESCColourFgString(style.r, style.g, style.b)); - if (style.bold == Dqn_PrintBold_Yes) - Dqn_Print_Std(std_handle, Dqn_Print_ESCBoldString); - Dqn_Print_Std(std_handle, string); - if (style.colour || style.bold == Dqn_PrintBold_Yes) - Dqn_Print_Std(std_handle, Dqn_Print_ESCResetString); - } -} - -DQN_FILE_SCOPE char *Dqn_Print_VSPrintfChunker_(const char *buf, void *user, int len) -{ - Dqn_String8 string = {}; - string.data = DQN_CAST(char *)buf; - string.size = len; - - Dqn_PrintStd std_handle = DQN_CAST(Dqn_PrintStd)DQN_CAST(uintptr_t)user; - Dqn_Print_Std(std_handle, string); - return (char *)buf; -} - -DQN_API void Dqn_Print_StdF(Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - Dqn_Print_StdFV(std_handle, fmt, args); - va_end(args); -} - -DQN_API void Dqn_Print_StdFStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - Dqn_Print_StdFVStyle(std_handle, style, fmt, args); - va_end(args); -} - -DQN_API void Dqn_Print_StdFV(Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args) -{ - char buffer[STB_SPRINTF_MIN]; - STB_SPRINTF_DECORATE(vsprintfcb)(Dqn_Print_VSPrintfChunker_, DQN_CAST(void *)DQN_CAST(uintptr_t)std_handle, buffer, fmt, args); -} - -DQN_API void Dqn_Print_StdFVStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args) -{ - if (fmt) { - if (style.colour) - Dqn_Print_Std(std_handle, Dqn_Print_ESCColourFgString(style.r, style.g, style.b)); - if (style.bold == Dqn_PrintBold_Yes) - Dqn_Print_Std(std_handle, Dqn_Print_ESCBoldString); - Dqn_Print_StdFV(std_handle, fmt, args); - if (style.colour || style.bold == Dqn_PrintBold_Yes) - Dqn_Print_Std(std_handle, Dqn_Print_ESCResetString); - } -} - -DQN_API void Dqn_Print_StdLn(Dqn_PrintStd std_handle, Dqn_String8 string) -{ - Dqn_Print_Std(std_handle, string); - Dqn_Print_Std(std_handle, DQN_STRING8("\n")); -} - -DQN_API void Dqn_Print_StdLnF(Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - Dqn_Print_StdLnFV(std_handle, fmt, args); - va_end(args); -} - -DQN_API void Dqn_Print_StdLnFV(Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args) -{ - Dqn_Print_StdFV(std_handle, fmt, args); - Dqn_Print_Std(std_handle, DQN_STRING8("\n")); -} - -DQN_API void Dqn_Print_StdLnStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_String8 string) -{ - Dqn_Print_StdStyle(std_handle, style, string); - Dqn_Print_Std(std_handle, DQN_STRING8("\n")); -} - -DQN_API void Dqn_Print_StdLnFStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, ...) -{ - va_list args; - va_start(args, fmt); - Dqn_Print_StdLnFVStyle(std_handle, style, fmt, args); - va_end(args); -} - -DQN_API void Dqn_Print_StdLnFVStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args) -{ - Dqn_Print_StdFVStyle(std_handle, style, fmt, args); - Dqn_Print_Std(std_handle, DQN_STRING8("\n")); -} - -DQN_API Dqn_String8 Dqn_Print_ESCColourString(Dqn_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b) -{ - DQN_THREAD_LOCAL char buffer[32]; - buffer[0] = 0; - Dqn_String8 result = {}; - result.size = STB_SPRINTF_DECORATE(snprintf)(buffer, - DQN_ARRAY_UCOUNT(buffer), - "\x1b[%d;2;%u;%u;%um", - colour == Dqn_PrintESCColour_Fg ? 38 : 48, - r, g, b); - result.data = buffer; - return result; -} - -DQN_API Dqn_String8 Dqn_Print_ESCColourU32String(Dqn_PrintESCColour colour, uint32_t value) -{ - uint8_t r = DQN_CAST(uint8_t)(value >> 24); - uint8_t g = DQN_CAST(uint8_t)(value >> 16); - uint8_t b = DQN_CAST(uint8_t)(value >> 8); - Dqn_String8 result = Dqn_Print_ESCColourString(colour, r, g, b); - return result; -} - // TODO(doyle): Use our temp scratch arenas instead of a massive array on the // stack. // NOTE: Max size from MSDN, using \\? syntax, but the ? bit can be expanded diff --git a/dqn_platform.h b/dqn_platform.h index cdd4413..c060776 100644 --- a/dqn_platform.h +++ b/dqn_platform.h @@ -1,87 +1,3 @@ -// NOTE: [$PRIN] Dqn_Print ========================================================================= -enum Dqn_PrintStd -{ - Dqn_PrintStd_Out, - Dqn_PrintStd_Err, -}; - -enum Dqn_PrintBold -{ - Dqn_PrintBold_No, - Dqn_PrintBold_Yes, -}; - -struct Dqn_PrintStyle -{ - Dqn_PrintBold bold; - bool colour; - uint8_t r, g, b; -}; - -enum Dqn_PrintESCColour -{ - Dqn_PrintESCColour_Fg, - Dqn_PrintESCColour_Bg, -}; - -// NOTE: Print Style =============================================================================== -DQN_API Dqn_PrintStyle Dqn_Print_StyleColour (uint8_t r, uint8_t g, uint8_t b, Dqn_PrintBold bold); -DQN_API Dqn_PrintStyle Dqn_Print_StyleColourU32 (uint32_t rgb, Dqn_PrintBold bold); -DQN_API Dqn_PrintStyle Dqn_Print_StyleBold (); - -// NOTE: Print Standard Out ======================================================================== -#define Dqn_Print(string) Dqn_Print_Std(Dqn_PrintStd_Out, string) -#define Dqn_Print_F(fmt, ...) Dqn_Print_StdF(Dqn_PrintStd_Out, fmt, ## __VA_ARGS__) -#define Dqn_Print_FV(fmt, args) Dqn_Print_StdFV(Dqn_PrintStd_Out, fmt, args) - -#define Dqn_Print_Style(style, string) Dqn_Print_StdStyle(Dqn_PrintStd_Out, style, string) -#define Dqn_Print_FStyle(style, fmt, ...) Dqn_Print_StdFStyle(Dqn_PrintStd_Out, style, fmt, ## __VA_ARGS__) -#define Dqn_Print_FVStyle(style, fmt, args, ...) Dqn_Print_StdFVStyle(Dqn_PrintStd_Out, style, fmt, args) - -#define Dqn_Print_Ln(string) Dqn_Print_StdLn(Dqn_PrintStd_Out, string) -#define Dqn_Print_LnF(fmt, ...) Dqn_Print_StdLnF(Dqn_PrintStd_Out, fmt, ## __VA_ARGS__) -#define Dqn_Print_LnFV(fmt, args) Dqn_Print_StdLnFV(Dqn_PrintStd_Out, fmt, args) - -#define Dqn_Print_LnStyle(style, string) Dqn_Print_StdLnStyle(Dqn_PrintStd_Out, style, string); -#define Dqn_Print_LnFStyle(style, fmt, ...) Dqn_Print_StdLnFStyle(Dqn_PrintStd_Out, style, fmt, ## __VA_ARGS__); -#define Dqn_Print_LnFVStyle(style, fmt, args) Dqn_Print_StdLnFVStyle(Dqn_PrintStd_Out, style, fmt, args); - -// NOTE: Print ===================================================================================== -DQN_API void Dqn_Print_Std (Dqn_PrintStd std_handle, Dqn_String8 string); -DQN_API void Dqn_Print_StdF (Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, ...); -DQN_API void Dqn_Print_StdFV (Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args); - -DQN_API void Dqn_Print_StdStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_String8 string); -DQN_API void Dqn_Print_StdFStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, ...); -DQN_API void Dqn_Print_StdFVStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args); - -DQN_API void Dqn_Print_StdLn (Dqn_PrintStd std_handle, Dqn_String8 string); -DQN_API void Dqn_Print_StdLnF (Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, ...); -DQN_API void Dqn_Print_StdLnFV (Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args); - -DQN_API void Dqn_Print_StdLnStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_String8 string); -DQN_API void Dqn_Print_StdLnFStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, ...); -DQN_API void Dqn_Print_StdLnFVStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args); - -// NOTE: ANSI Formatting Codes ===================================================================== -Dqn_String8 Dqn_Print_ESCColourString (Dqn_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b); -Dqn_String8 Dqn_Print_ESCColourU32String(Dqn_PrintESCColour colour, uint32_t value); - -#define Dqn_Print_ESCColourFgString(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Fg, r, g, b) -#define Dqn_Print_ESCColourBgString(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Bg, r, g, b) -#define Dqn_Print_ESCColourFg(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Fg, r, g, b).data -#define Dqn_Print_ESCColourBg(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Bg, r, g, b).data - -#define Dqn_Print_ESCColourFgU32String(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Fg, value) -#define Dqn_Print_ESCColourBgU32String(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Bg, value) -#define Dqn_Print_ESCColourFgU32(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Fg, value).data -#define Dqn_Print_ESCColourBgU32(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Bg, value).data - -#define Dqn_Print_ESCReset "\x1b[0m" -#define Dqn_Print_ESCBold "\x1b[1m" -#define Dqn_Print_ESCResetString DQN_STRING8(Dqn_Print_ESCReset) -#define Dqn_Print_ESCBoldString DQN_STRING8(Dqn_Print_ESCBold) - #if !defined(DQN_NO_FS) #if defined(DQN_OS_WIN32) && defined(DQN_NO_WIN) #error "Filesystem APIs requires Windows API, DQN_NO_WIN must not be defined" diff --git a/dqn_platform_print.cpp b/dqn_platform_print.cpp new file mode 100644 index 0000000..cfbf2cf --- /dev/null +++ b/dqn_platform_print.cpp @@ -0,0 +1,194 @@ +// NOTE: [$PRIN] Dqn_Print ========================================================================= +DQN_API Dqn_PrintStyle Dqn_Print_StyleColour(uint8_t r, uint8_t g, uint8_t b, Dqn_PrintBold bold) +{ + Dqn_PrintStyle result = {}; + result.bold = bold; + result.colour = true; + result.r = r; + result.g = g; + result.b = b; + return result; +} + +DQN_API Dqn_PrintStyle Dqn_Print_StyleColourU32(uint32_t rgb, Dqn_PrintBold bold) +{ + uint8_t r = (rgb >> 24) & 0xFF; + uint8_t g = (rgb >> 16) & 0xFF; + uint8_t b = (rgb >> 8) & 0xFF; + Dqn_PrintStyle result = Dqn_Print_StyleColour(r, g, b, bold); + return result; +} + +DQN_API Dqn_PrintStyle Dqn_Print_StyleBold() +{ + Dqn_PrintStyle result = {}; + result.bold = Dqn_PrintBold_Yes; + return result; +} + +DQN_API void Dqn_Print_Std(Dqn_PrintStd std_handle, Dqn_String8 string) +{ + DQN_ASSERT(std_handle == Dqn_PrintStd_Out || std_handle == Dqn_PrintStd_Err); + + #if defined(DQN_OS_WIN32) + // NOTE: Get the output handles from kernel + // ========================================================================= + DQN_THREAD_LOCAL void *std_out_print_handle = nullptr; + DQN_THREAD_LOCAL void *std_err_print_handle = nullptr; + DQN_THREAD_LOCAL bool std_out_print_to_console = false; + DQN_THREAD_LOCAL bool std_err_print_to_console = false; + + if (!std_out_print_handle) { + unsigned long mode = 0; (void)mode; + std_out_print_handle = GetStdHandle(STD_OUTPUT_HANDLE); + std_out_print_to_console = GetConsoleMode(std_out_print_handle, &mode) != 0; + + std_err_print_handle = GetStdHandle(STD_ERROR_HANDLE); + std_err_print_to_console = GetConsoleMode(std_err_print_handle, &mode) != 0; + } + + // NOTE: Select the output handle + // ========================================================================= + void *print_handle = std_out_print_handle; + bool print_to_console = std_out_print_to_console; + if (std_handle == Dqn_PrintStd_Err) { + print_handle = std_err_print_handle; + print_to_console = std_err_print_to_console; + } + + // NOTE: Write the string + // ========================================================================= + DQN_ASSERT(string.size < DQN_CAST(unsigned long)-1); + unsigned long bytes_written = 0; (void)bytes_written; + if (print_to_console) { + WriteConsoleA(print_handle, string.data, DQN_CAST(unsigned long)string.size, &bytes_written, nullptr); + } else { + WriteFile(print_handle, string.data, DQN_CAST(unsigned long)string.size, &bytes_written, nullptr); + } + #else + fprintf(std_handle == Dqn_PrintStd_Out ? stdout : stderr, "%.*s", DQN_STRING_FMT(string)); + #endif +} + +DQN_API void Dqn_Print_StdStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_String8 string) +{ + if (string.data && string.size) { + if (style.colour) + Dqn_Print_Std(std_handle, Dqn_Print_ESCColourFgString(style.r, style.g, style.b)); + if (style.bold == Dqn_PrintBold_Yes) + Dqn_Print_Std(std_handle, Dqn_Print_ESCBoldString); + Dqn_Print_Std(std_handle, string); + if (style.colour || style.bold == Dqn_PrintBold_Yes) + Dqn_Print_Std(std_handle, Dqn_Print_ESCResetString); + } +} + +DQN_FILE_SCOPE char *Dqn_Print_VSPrintfChunker_(const char *buf, void *user, int len) +{ + Dqn_String8 string = {}; + string.data = DQN_CAST(char *)buf; + string.size = len; + + Dqn_PrintStd std_handle = DQN_CAST(Dqn_PrintStd)DQN_CAST(uintptr_t)user; + Dqn_Print_Std(std_handle, string); + return (char *)buf; +} + +DQN_API void Dqn_Print_StdF(Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Dqn_Print_StdFV(std_handle, fmt, args); + va_end(args); +} + +DQN_API void Dqn_Print_StdFStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Dqn_Print_StdFVStyle(std_handle, style, fmt, args); + va_end(args); +} + +DQN_API void Dqn_Print_StdFV(Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args) +{ + char buffer[STB_SPRINTF_MIN]; + STB_SPRINTF_DECORATE(vsprintfcb)(Dqn_Print_VSPrintfChunker_, DQN_CAST(void *)DQN_CAST(uintptr_t)std_handle, buffer, fmt, args); +} + +DQN_API void Dqn_Print_StdFVStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args) +{ + if (fmt) { + if (style.colour) + Dqn_Print_Std(std_handle, Dqn_Print_ESCColourFgString(style.r, style.g, style.b)); + if (style.bold == Dqn_PrintBold_Yes) + Dqn_Print_Std(std_handle, Dqn_Print_ESCBoldString); + Dqn_Print_StdFV(std_handle, fmt, args); + if (style.colour || style.bold == Dqn_PrintBold_Yes) + Dqn_Print_Std(std_handle, Dqn_Print_ESCResetString); + } +} + +DQN_API void Dqn_Print_StdLn(Dqn_PrintStd std_handle, Dqn_String8 string) +{ + Dqn_Print_Std(std_handle, string); + Dqn_Print_Std(std_handle, DQN_STRING8("\n")); +} + +DQN_API void Dqn_Print_StdLnF(Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Dqn_Print_StdLnFV(std_handle, fmt, args); + va_end(args); +} + +DQN_API void Dqn_Print_StdLnFV(Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args) +{ + Dqn_Print_StdFV(std_handle, fmt, args); + Dqn_Print_Std(std_handle, DQN_STRING8("\n")); +} + +DQN_API void Dqn_Print_StdLnStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_String8 string) +{ + Dqn_Print_StdStyle(std_handle, style, string); + Dqn_Print_Std(std_handle, DQN_STRING8("\n")); +} + +DQN_API void Dqn_Print_StdLnFStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, ...) +{ + va_list args; + va_start(args, fmt); + Dqn_Print_StdLnFVStyle(std_handle, style, fmt, args); + va_end(args); +} + +DQN_API void Dqn_Print_StdLnFVStyle(Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args) +{ + Dqn_Print_StdFVStyle(std_handle, style, fmt, args); + Dqn_Print_Std(std_handle, DQN_STRING8("\n")); +} + +DQN_API Dqn_String8 Dqn_Print_ESCColourString(Dqn_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b) +{ + DQN_THREAD_LOCAL char buffer[32]; + buffer[0] = 0; + Dqn_String8 result = {}; + result.size = STB_SPRINTF_DECORATE(snprintf)(buffer, + DQN_ARRAY_UCOUNT(buffer), + "\x1b[%d;2;%u;%u;%um", + colour == Dqn_PrintESCColour_Fg ? 38 : 48, + r, g, b); + result.data = buffer; + return result; +} + +DQN_API Dqn_String8 Dqn_Print_ESCColourU32String(Dqn_PrintESCColour colour, uint32_t value) +{ + uint8_t r = DQN_CAST(uint8_t)(value >> 24); + uint8_t g = DQN_CAST(uint8_t)(value >> 16); + uint8_t b = DQN_CAST(uint8_t)(value >> 8); + Dqn_String8 result = Dqn_Print_ESCColourString(colour, r, g, b); + return result; +} + diff --git a/dqn_platform_print.h b/dqn_platform_print.h new file mode 100644 index 0000000..b0e37fb --- /dev/null +++ b/dqn_platform_print.h @@ -0,0 +1,84 @@ +// NOTE: [$PRIN] Dqn_Print ========================================================================= +enum Dqn_PrintStd +{ + Dqn_PrintStd_Out, + Dqn_PrintStd_Err, +}; + +enum Dqn_PrintBold +{ + Dqn_PrintBold_No, + Dqn_PrintBold_Yes, +}; + +struct Dqn_PrintStyle +{ + Dqn_PrintBold bold; + bool colour; + uint8_t r, g, b; +}; + +enum Dqn_PrintESCColour +{ + Dqn_PrintESCColour_Fg, + Dqn_PrintESCColour_Bg, +}; + +// NOTE: Print Style =============================================================================== +DQN_API Dqn_PrintStyle Dqn_Print_StyleColour (uint8_t r, uint8_t g, uint8_t b, Dqn_PrintBold bold); +DQN_API Dqn_PrintStyle Dqn_Print_StyleColourU32 (uint32_t rgb, Dqn_PrintBold bold); +DQN_API Dqn_PrintStyle Dqn_Print_StyleBold (); + +// NOTE: Print Standard Out ======================================================================== +#define Dqn_Print(string) Dqn_Print_Std(Dqn_PrintStd_Out, string) +#define Dqn_Print_F(fmt, ...) Dqn_Print_StdF(Dqn_PrintStd_Out, fmt, ## __VA_ARGS__) +#define Dqn_Print_FV(fmt, args) Dqn_Print_StdFV(Dqn_PrintStd_Out, fmt, args) + +#define Dqn_Print_Style(style, string) Dqn_Print_StdStyle(Dqn_PrintStd_Out, style, string) +#define Dqn_Print_FStyle(style, fmt, ...) Dqn_Print_StdFStyle(Dqn_PrintStd_Out, style, fmt, ## __VA_ARGS__) +#define Dqn_Print_FVStyle(style, fmt, args, ...) Dqn_Print_StdFVStyle(Dqn_PrintStd_Out, style, fmt, args) + +#define Dqn_Print_Ln(string) Dqn_Print_StdLn(Dqn_PrintStd_Out, string) +#define Dqn_Print_LnF(fmt, ...) Dqn_Print_StdLnF(Dqn_PrintStd_Out, fmt, ## __VA_ARGS__) +#define Dqn_Print_LnFV(fmt, args) Dqn_Print_StdLnFV(Dqn_PrintStd_Out, fmt, args) + +#define Dqn_Print_LnStyle(style, string) Dqn_Print_StdLnStyle(Dqn_PrintStd_Out, style, string); +#define Dqn_Print_LnFStyle(style, fmt, ...) Dqn_Print_StdLnFStyle(Dqn_PrintStd_Out, style, fmt, ## __VA_ARGS__); +#define Dqn_Print_LnFVStyle(style, fmt, args) Dqn_Print_StdLnFVStyle(Dqn_PrintStd_Out, style, fmt, args); + +// NOTE: Print ===================================================================================== +DQN_API void Dqn_Print_Std (Dqn_PrintStd std_handle, Dqn_String8 string); +DQN_API void Dqn_Print_StdF (Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, ...); +DQN_API void Dqn_Print_StdFV (Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args); + +DQN_API void Dqn_Print_StdStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_String8 string); +DQN_API void Dqn_Print_StdFStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, ...); +DQN_API void Dqn_Print_StdFVStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args); + +DQN_API void Dqn_Print_StdLn (Dqn_PrintStd std_handle, Dqn_String8 string); +DQN_API void Dqn_Print_StdLnF (Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, ...); +DQN_API void Dqn_Print_StdLnFV (Dqn_PrintStd std_handle, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args); + +DQN_API void Dqn_Print_StdLnStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, Dqn_String8 string); +DQN_API void Dqn_Print_StdLnFStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, ...); +DQN_API void Dqn_Print_StdLnFVStyle (Dqn_PrintStd std_handle, Dqn_PrintStyle style, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args); + +// NOTE: ANSI Formatting Codes ===================================================================== +Dqn_String8 Dqn_Print_ESCColourString (Dqn_PrintESCColour colour, uint8_t r, uint8_t g, uint8_t b); +Dqn_String8 Dqn_Print_ESCColourU32String(Dqn_PrintESCColour colour, uint32_t value); + +#define Dqn_Print_ESCColourFgString(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Fg, r, g, b) +#define Dqn_Print_ESCColourBgString(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Bg, r, g, b) +#define Dqn_Print_ESCColourFg(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Fg, r, g, b).data +#define Dqn_Print_ESCColourBg(r, g, b) Dqn_Print_ESCColourString(Dqn_PrintESCColour_Bg, r, g, b).data + +#define Dqn_Print_ESCColourFgU32String(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Fg, value) +#define Dqn_Print_ESCColourBgU32String(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Bg, value) +#define Dqn_Print_ESCColourFgU32(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Fg, value).data +#define Dqn_Print_ESCColourBgU32(value) Dqn_Print_ESCColourU32String(Dqn_PrintESCColour_Bg, value).data + +#define Dqn_Print_ESCReset "\x1b[0m" +#define Dqn_Print_ESCBold "\x1b[1m" +#define Dqn_Print_ESCResetString DQN_STRING8(Dqn_Print_ESCReset) +#define Dqn_Print_ESCBoldString DQN_STRING8(Dqn_Print_ESCBold) + diff --git a/dqn_strings.h b/dqn_strings.h index 27ab46a..8c2d971 100644 --- a/dqn_strings.h +++ b/dqn_strings.h @@ -541,7 +541,6 @@ template bool Dqn_FString8_AppendFV(Dqn_FString8 *string, DQN_F if (!string || !fmt) return result; - DQN_HARD_ASSERT(string->size >= 0); Dqn_usize require = Dqn_CString8_FVSize(fmt, args) + 1 /*null_terminate*/; Dqn_usize space = (N + 1) - string->size; result = require <= space; @@ -558,9 +557,6 @@ template bool Dqn_FString8_AppendF(Dqn_FString8 *string, DQN_FM bool result = false; if (!string || !fmt) return result; - - DQN_HARD_ASSERT(string->size >= 0); - va_list args; va_start(args, fmt); result = Dqn_FString8_AppendFV(string, fmt, args);