dqn: Fix poison vet check, use FsFile for logs, various cleanup
This commit is contained in:
parent
0872da026a
commit
d756a26b42
@ -15,7 +15,7 @@
|
||||
#endif
|
||||
|
||||
#define DQN_ASAN_POISON 1
|
||||
#define DQN_ASAN_VET_POISON
|
||||
#define DQN_ASAN_VET_POISON 1
|
||||
#define DQN_NO_CHECK_BREAK
|
||||
#define DQN_IMPLEMENTATION
|
||||
#include "dqn.h"
|
||||
|
@ -16,7 +16,10 @@ pushd Build
|
||||
set common_flags=-D DQN_TEST_WITH_MAIN -I %script_dir% %script_dir%\Misc\dqn_unit_tests.cpp
|
||||
|
||||
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
|
||||
|
||||
REM Optionally pass `-analyze` to `msvc_compile_flags` for more checks, but,
|
||||
REM it slows down compilation by around 5s on my old laptop.
|
||||
set msvc_compile_flags=%msvc_driver_flags% -fsanitize=address /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
|
||||
|
||||
|
22
dqn.h
22
dqn.h
@ -116,6 +116,7 @@
|
||||
// [$TYPE] Types | | Basic types and typedefs
|
||||
// [$INTR] Intrinsics | | Atomics, cpuid, ticket mutex
|
||||
// [$TMUT] Dqn_TicketMutex | | Userland mutex via spinlocking atomics
|
||||
// [$PRIN] Dqn_Print | | Console printing
|
||||
|
||||
// NOTE: Additional Configuration
|
||||
// - Override the default heap-allocation routine that is called when the
|
||||
@ -191,10 +192,6 @@
|
||||
// [$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
|
||||
@ -219,8 +216,10 @@
|
||||
//
|
||||
// DQN_DUMP_STACK_TRACE
|
||||
//
|
||||
// - Enable memory leak tracking when requesting memory from the OS via this
|
||||
// library. For example calls to Dqn_VMem_Reserve or DQN_ALLOC are recorded.
|
||||
// - Define this macro to enable emory leak tracking when requesting memory
|
||||
// from the OS via this library. For example calls to Dqn_VMem_Reserve or
|
||||
// DQN_ALLOC are recorded to the leak table.
|
||||
//
|
||||
// Allocations are stored in a global hash-table and their respective stack
|
||||
// traces for the allocation location. Memory leaks can be dumped at the end
|
||||
// of the program or some epoch by calling Dqn_Library_DumpLeaks()
|
||||
@ -239,13 +238,13 @@
|
||||
//
|
||||
// DQN_ASAN_POISON 1
|
||||
//
|
||||
// - Define this macro to enable sanity checks for manually poisoned memory in
|
||||
// - Define this macro 1 to enable sanity checks for manually poisoned memory in
|
||||
// this library when ASAN `-fsanitize=address` is enabled. These sanity checks
|
||||
// ensure that memory from arenas are correctly un/poisoned when pointers are
|
||||
// allocated and returned to the memory arena's. This is a no-op if we are not
|
||||
// compiled with ASAN or `DQN_ASAN_POISON` is not set to `1`.
|
||||
//
|
||||
// DQN_ASAN_VET_POISON
|
||||
// DQN_ASAN_VET_POISON 1
|
||||
//
|
||||
|
||||
// NOTE: Dqn_Strings ===============================================================================
|
||||
@ -280,12 +279,6 @@
|
||||
// and padded to atleast DQN_ASAN_POISON_ALIGNMENT (e.g. 8 bytes).
|
||||
//
|
||||
// DQN_ASAN_POISON 1
|
||||
//
|
||||
// - Define this macro to record allocation stats for arenas used in the
|
||||
// thread context. The thread context arena stats can be printed by using
|
||||
// Dqn_Library_DumpThreadContextArenaStat.
|
||||
//
|
||||
// DQN_DEBUG_THREAD_CONTEXT
|
||||
|
||||
#include "dqn_platform.h"
|
||||
|
||||
@ -319,7 +312,6 @@
|
||||
#include "dqn_base.cpp"
|
||||
#include "dqn_external.cpp"
|
||||
#include "dqn_memory.cpp"
|
||||
#include "dqn_platform_print.cpp"
|
||||
#include "dqn_debug.cpp"
|
||||
#include "dqn_strings.cpp"
|
||||
#include "dqn_containers.cpp"
|
||||
|
192
dqn_base.cpp
192
dqn_base.cpp
@ -60,3 +60,195 @@ DQN_API bool Dqn_TicketMutex_CanLock(Dqn_TicketMutex const *mutex, Dqn_uint tick
|
||||
#undef _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
115
dqn_base.h
115
dqn_base.h
@ -290,24 +290,21 @@ typedef int32_t Dqn_b32;
|
||||
#define DQN_ISIZE_MAX INTPTR_MAX
|
||||
#define DQN_ISIZE_MIN INTPTR_MIN
|
||||
|
||||
typedef enum Dqn_ZeroMem
|
||||
enum Dqn_ZeroMem
|
||||
{
|
||||
Dqn_ZeroMem_No, // Memory can be handed out without zero-ing it out
|
||||
Dqn_ZeroMem_Yes, // Memory should be zero-ed out before giving to the callee
|
||||
}
|
||||
Dqn_ZeroMem;
|
||||
};
|
||||
|
||||
struct Dqn_String8
|
||||
{
|
||||
char *data; // The bytes of the string
|
||||
char *data; // The bytes of the string
|
||||
Dqn_usize size; // The number of bytes in the string
|
||||
|
||||
#if defined(__cplusplus)
|
||||
char const *begin() const { return data; }
|
||||
char const *end () const { return data + size; }
|
||||
char *begin() { return data; }
|
||||
char *end () { return data + size; }
|
||||
#endif
|
||||
};
|
||||
|
||||
// NOTE: [$INTR] Intrinsics ========================================================================
|
||||
@ -439,8 +436,8 @@ Dqn_CPUIDRegisters Dqn_CPUID(int function_id);
|
||||
|
||||
struct Dqn_TicketMutex
|
||||
{
|
||||
unsigned int volatile ticket; ///< The next ticket to give out to the thread taking the mutex
|
||||
unsigned int volatile serving; ///< The ticket ID to block the mutex on until it is returned
|
||||
unsigned int volatile ticket; // The next ticket to give out to the thread taking the mutex
|
||||
unsigned int volatile serving; // The ticket ID to block the mutex on until it is returned
|
||||
};
|
||||
|
||||
void Dqn_TicketMutex_Begin (Dqn_TicketMutex *mutex);
|
||||
@ -448,3 +445,105 @@ void Dqn_TicketMutex_End (Dqn_TicketMutex *mutex);
|
||||
Dqn_uint Dqn_TicketMutex_MakeTicket (Dqn_TicketMutex *mutex);
|
||||
void Dqn_TicketMutex_BeginTicket(Dqn_TicketMutex const *mutex, Dqn_uint ticket);
|
||||
bool Dqn_TicketMutex_CanLock (Dqn_TicketMutex const *mutex, Dqn_uint ticket);
|
||||
|
||||
// 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);
|
||||
|
||||
#define Dqn_Print_Err(string) Dqn_Print_Std(Dqn_PrintStd_Err, string)
|
||||
#define Dqn_Print_ErrF(fmt, ...) Dqn_Print_StdF(Dqn_PrintStd_Err, fmt, ## __VA_ARGS__)
|
||||
#define Dqn_Print_ErrFV(fmt, args) Dqn_Print_StdFV(Dqn_PrintStd_Err, fmt, args)
|
||||
|
||||
#define Dqn_Print_ErrStyle(style, string) Dqn_Print_StdStyle(Dqn_PrintStd_Err, style, string)
|
||||
#define Dqn_Print_ErrFStyle(style, fmt, ...) Dqn_Print_StdFStyle(Dqn_PrintStd_Err, style, fmt, ## __VA_ARGS__)
|
||||
#define Dqn_Print_ErrFVStyle(style, fmt, args, ...) Dqn_Print_StdFVStyle(Dqn_PrintStd_Err, style, fmt, args)
|
||||
|
||||
#define Dqn_Print_ErrLn(string) Dqn_Print_StdLn(Dqn_PrintStd_Err, string)
|
||||
#define Dqn_Print_ErrLnF(fmt, ...) Dqn_Print_StdLnF(Dqn_PrintStd_Err, fmt, ## __VA_ARGS__)
|
||||
#define Dqn_Print_ErrLnFV(fmt, args) Dqn_Print_StdLnFV(Dqn_PrintStd_Err, fmt, args)
|
||||
|
||||
#define Dqn_Print_ErrLnStyle(style, string) Dqn_Print_StdLnStyle(Dqn_PrintStd_Err, style, string);
|
||||
#define Dqn_Print_ErrLnFStyle(style, fmt, ...) Dqn_Print_StdLnFStyle(Dqn_PrintStd_Err, style, fmt, ## __VA_ARGS__);
|
||||
#define Dqn_Print_ErrLnFVStyle(style, fmt, args) Dqn_Print_StdLnFVStyle(Dqn_PrintStd_Err, 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)
|
||||
|
||||
|
@ -1,3 +1,30 @@
|
||||
// NOTE: [$ASAN] Dqn_Asan ========================================================================== ===
|
||||
void Dqn_ASAN_PoisonMemoryRegion(void const volatile *ptr, Dqn_usize size)
|
||||
{
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
__asan_poison_memory_region(ptr, size);
|
||||
if (DQN_ASAN_VET_POISON) {
|
||||
DQN_HARD_ASSERT(__asan_address_is_poisoned(ptr));
|
||||
DQN_HARD_ASSERT(__asan_address_is_poisoned((char *)ptr + (size - 1)));
|
||||
}
|
||||
#else
|
||||
(void)ptr; (void)size;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Dqn_ASAN_UnpoisonMemoryRegion(void const volatile *ptr, Dqn_usize size)
|
||||
{
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
__asan_unpoison_memory_region(ptr, size);
|
||||
if (DQN_ASAN_VET_POISON) {
|
||||
DQN_HARD_ASSERT(__asan_region_is_poisoned((void *)ptr, size) == 0);
|
||||
}
|
||||
#else
|
||||
(void)ptr; (void)size;
|
||||
#endif
|
||||
}
|
||||
|
||||
// NOTE: [$DEBG] Dqn_Debug =========================================================================
|
||||
DQN_API Dqn_String8 Dqn_Debug_CleanStackTrace(Dqn_String8 stack_trace)
|
||||
{
|
||||
// NOTE: Remove the stacktrace's library invocations from the stack trace
|
||||
@ -164,7 +191,7 @@ DQN_API void Dqn_Debug_DumpLeaks()
|
||||
Dqn_Log_WarningF("There were %I64u leaked allocations totalling %_$$I64u", leak_count, leaked_bytes);
|
||||
}
|
||||
}
|
||||
#endif /// defined(DQN_LEAK_TRACING)
|
||||
#endif // defined(DQN_LEAK_TRACING)
|
||||
|
||||
// NOTE: [$LLOG] Dqn_Log ==========================================================================
|
||||
DQN_API Dqn_String8 Dqn_Log_MakeString(Dqn_Allocator allocator,
|
||||
@ -239,27 +266,23 @@ DQN_API Dqn_String8 Dqn_Log_MakeString(Dqn_Allocator allocator,
|
||||
|
||||
DQN_FILE_SCOPE void Dqn_Log_FVDefault_(Dqn_String8 type, int log_type, void *user_data, Dqn_CallSite call_site, char const *fmt, va_list args)
|
||||
{
|
||||
Dqn_Library *lib = g_dqn_library;
|
||||
(void)log_type;
|
||||
(void)user_data;
|
||||
|
||||
// NOTE: Open log file for appending if requested ==========================
|
||||
Dqn_TicketMutex_Begin(&g_dqn_library->log_file_mutex);
|
||||
if (g_dqn_library->log_to_file && !g_dqn_library->log_file) {
|
||||
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
|
||||
#if (defined(DQN_OS_WIN32) && !defined(DQN_NO_WIN)) || !defined(DQN_OS_WIN32)
|
||||
Dqn_String8 exe_dir = Dqn_OS_EXEDir(scratch.arena);
|
||||
#else
|
||||
Dqn_String8 exe_dir = DQN_STRING8(".");
|
||||
#endif
|
||||
Dqn_String8 log_file = Dqn_String8_InitF(scratch.allocator, "%.*s/dqn.log", DQN_STRING_FMT(exe_dir));
|
||||
fopen_s(DQN_CAST(FILE **)&g_dqn_library->log_file, log_file.data, "a");
|
||||
Dqn_TicketMutex_Begin(&lib->log_file_mutex);
|
||||
if (lib->log_to_file && !lib->log_file.handle && lib->log_file.error_size == 0) {
|
||||
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
|
||||
Dqn_String8 log_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/dqn.log", DQN_STRING_FMT(lib->exe_dir));
|
||||
lib->log_file = Dqn_Fs_OpenFile(log_path, Dqn_FsFileOpen_CreateAlways, Dqn_FsFileAccess_AppendOnly);
|
||||
}
|
||||
Dqn_TicketMutex_End(&g_dqn_library->log_file_mutex);
|
||||
Dqn_TicketMutex_End(&lib->log_file_mutex);
|
||||
|
||||
// NOTE: Generate the log header ===========================================
|
||||
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
|
||||
Dqn_String8 log_line = Dqn_Log_MakeString(scratch.allocator,
|
||||
!g_dqn_library->log_no_colour,
|
||||
!lib->log_no_colour,
|
||||
type,
|
||||
log_type,
|
||||
call_site,
|
||||
@ -269,11 +292,10 @@ DQN_FILE_SCOPE void Dqn_Log_FVDefault_(Dqn_String8 type, int log_type, void *use
|
||||
// NOTE: Print log =========================================================
|
||||
Dqn_Print_StdLn(Dqn_PrintStd_Out, log_line);
|
||||
|
||||
Dqn_TicketMutex_Begin(&g_dqn_library->log_file_mutex);
|
||||
if (g_dqn_library->log_to_file && g_dqn_library->log_file) {
|
||||
fprintf(DQN_CAST(FILE *)g_dqn_library->log_file, "%.*s\n", DQN_STRING_FMT(log_line));
|
||||
}
|
||||
Dqn_TicketMutex_End(&g_dqn_library->log_file_mutex);
|
||||
Dqn_TicketMutex_Begin(&lib->log_file_mutex);
|
||||
Dqn_Fs_WriteFile(&lib->log_file, log_line);
|
||||
Dqn_Fs_WriteFile(&lib->log_file, DQN_STRING8("\n"));
|
||||
Dqn_TicketMutex_End(&lib->log_file_mutex);
|
||||
}
|
||||
|
||||
DQN_API void Dqn_Log_FVCallSite(Dqn_String8 type, Dqn_CallSite call_site, char const *fmt, va_list args)
|
||||
|
29
dqn_debug.h
29
dqn_debug.h
@ -34,6 +34,10 @@
|
||||
#define DQN_ASAN_POISON 0
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_ASAN_POISON_VET)
|
||||
#define DQN_ASAN_POISON_VET 0
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_ASAN_POISON_ALIGNMENT)
|
||||
#define DQN_ASAN_POISON_ALIGNMENT 8
|
||||
#endif
|
||||
@ -44,31 +48,14 @@
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
// NOTE: [$ASAN] Dqn_Asan ========================================================================== ===
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
#include <sanitizer/asan_interface.h>
|
||||
#if defined(DQN_ASAN_VET_POISON)
|
||||
#define DQN_ASAN_POISON_MEMORY_REGION(ptr, size) \
|
||||
do { \
|
||||
__asan_poison_memory_region((ptr), (size)); \
|
||||
DQN_ASSERT(__asan_address_is_poisoned((ptr))); \
|
||||
DQN_ASSERT(__asan_address_is_poisoned((char *)(ptr) + ((size) - 1))); \
|
||||
DQN_ASSERT(!__asan_address_is_poisoned((char *)(ptr) + (size))); \
|
||||
} while (0)
|
||||
|
||||
#define DQN_ASAN_UNPOISON_MEMORY_REGION(ptr, size) \
|
||||
do { \
|
||||
__asan_unpoison_memory_region((ptr), (size)); \
|
||||
DQN_ASSERT(__asan_region_is_poisoned((ptr), (size)) == 0); \
|
||||
} while (0)
|
||||
#else
|
||||
#define DQN_ASAN_POISON_MEMORY_REGION(ptr, size) __asan_poison_memory_region(ptr, size)
|
||||
#define DQN_ASAN_UNPOISON_MEMORY_REGION(ptr, size) __asan_unpoison_memory_region(ptr, size)
|
||||
#endif
|
||||
#else
|
||||
#define DQN_ASAN_POISON_MEMORY_REGION(ptr, size) (void)(ptr); (void)(size)
|
||||
#define DQN_ASAN_UNPOISON_MEMORY_REGION(ptr, size) (void)(ptr); (void)(size)
|
||||
#endif
|
||||
|
||||
void Dqn_ASAN_PoisonMemoryRegion(void const volatile *ptr, Dqn_usize size);
|
||||
void Dqn_ASAN_UnpoisonMemoryRegion(void const volatile *ptr, Dqn_usize size);
|
||||
|
||||
// NOTE: [$CALL] Dqn_CallSite ======================================================================
|
||||
struct Dqn_CallSite
|
||||
{
|
||||
|
@ -141,6 +141,10 @@ static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uin
|
||||
return (stbsp__uint32)(sn - s);
|
||||
}
|
||||
|
||||
|
||||
#if defined(__clang__)
|
||||
__attribute__((no_sanitize("undefined")))
|
||||
#endif
|
||||
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va)
|
||||
{
|
||||
static char hex[] = "0123456789abcdefxp";
|
||||
|
@ -794,24 +794,17 @@ DQN_API Dqn_Library *Dqn_Library_Init()
|
||||
g_dqn_library = &default_instance;
|
||||
}
|
||||
|
||||
// NOTE: Init check ===========================================================================
|
||||
|
||||
Dqn_Library *result = g_dqn_library;
|
||||
Dqn_TicketMutex_Begin(&result->lib_mutex);
|
||||
DQN_DEFER { Dqn_TicketMutex_End(&result->lib_mutex); };
|
||||
if (result->lib_init)
|
||||
return result;
|
||||
|
||||
// =============================================================================================
|
||||
// NOTE: Query OS page size ====================================================================
|
||||
|
||||
Dqn_ArenaCatalog_Init(&result->arena_catalog, &result->arena_catalog_backup_arena);
|
||||
result->lib_init = true;
|
||||
|
||||
#if !defined(DQN_NO_PROFILER)
|
||||
result->profiler = &result->profiler_default_instance;
|
||||
#endif
|
||||
|
||||
// =============================================================================================
|
||||
|
||||
{ // NOTE: Query OS page size
|
||||
{
|
||||
SYSTEM_INFO system_info = {};
|
||||
#if defined(DQN_OS_WIN32)
|
||||
GetSystemInfo(&system_info);
|
||||
@ -824,7 +817,17 @@ DQN_API Dqn_Library *Dqn_Library_Init()
|
||||
#endif
|
||||
}
|
||||
|
||||
// =============================================================================================
|
||||
// NOTE Initialise fields ======================================================================
|
||||
|
||||
#if !defined(DQN_NO_PROFILER)
|
||||
result->profiler = &result->profiler_default_instance;
|
||||
#endif
|
||||
|
||||
result->lib_init = true;
|
||||
Dqn_ArenaCatalog_Init(&result->arena_catalog, &result->arena);
|
||||
result->exe_dir = Dqn_OS_EXEDir(&result->arena);
|
||||
|
||||
// NOTE: Leak tracing ==========================================================================
|
||||
|
||||
#if defined(DQN_LEAK_TRACING) // NOTE: Initialise the allocation leak tracker
|
||||
{
|
||||
@ -840,17 +843,23 @@ DQN_API Dqn_Library *Dqn_Library_Init()
|
||||
}
|
||||
#endif
|
||||
|
||||
// ============================================================================================
|
||||
// NOTE: Print out init features ===============================================================
|
||||
|
||||
Dqn_Log_DebugF("Dqn Library initialised with features\n");
|
||||
Dqn_Log_DebugF("Dqn Library initialised:\n");
|
||||
Dqn_Print_StdLnF(Dqn_PrintStd_Err, " OS Page Size/Alloc Granularity: %$$_I32u/%$$_I32u", result->os_page_size, result->os_alloc_granularity);
|
||||
|
||||
if (DQN_ASAN_POISON)
|
||||
Dqn_Print_StdLnF(Dqn_PrintStd_Err, " - ASAN manual poisoning");
|
||||
Dqn_Print_StdLnF(Dqn_PrintStd_Err, " ASAN manual poisoning%s", DQN_ASAN_VET_POISON ? " (+vet sanity checks)" : "");
|
||||
|
||||
#if defined(DQN_ASAN_VET_POISON)
|
||||
Dqn_Print_StdLnF(Dqn_PrintStd_Err, " - ASAN manual poisoning vetting");
|
||||
#if defined(DQN_LEAK_TRACING)
|
||||
Dqn_Print_StdLnF(Dqn_PrintStd_Err, " Allocation leak tracing");
|
||||
#endif
|
||||
|
||||
#if !defined(DQN_NO_PROFILER)
|
||||
Dqn_Print_StdLnF(Dqn_PrintStd_Err, " TSC profiler available");
|
||||
#endif
|
||||
|
||||
Dqn_Print_StdLnF(Dqn_PrintStd_Err, "");
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -874,14 +883,6 @@ DQN_API void Dqn_Library_SetLogCallback(Dqn_LogProc *proc, void *user_data)
|
||||
g_dqn_library->log_user_data = user_data;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_Library_SetLogFile(FILE *file)
|
||||
{
|
||||
Dqn_TicketMutex_Begin(&g_dqn_library->log_file_mutex);
|
||||
g_dqn_library->log_file = file;
|
||||
g_dqn_library->log_to_file = file ? true : false;
|
||||
Dqn_TicketMutex_End(&g_dqn_library->log_file_mutex);
|
||||
}
|
||||
|
||||
DQN_API void Dqn_Library_DumpThreadContextArenaStat(Dqn_String8 file_path)
|
||||
{
|
||||
#if defined(DQN_DEBUG_THREAD_CONTEXT)
|
||||
|
@ -587,20 +587,20 @@ void Dqn_Profiler_SwapAnchorBuffer (uint32_t anchor_count);
|
||||
|
||||
struct Dqn_Library
|
||||
{
|
||||
bool lib_init;
|
||||
bool lib_init; // True if the library has been initialised via `Dqn_Library_Init`
|
||||
Dqn_TicketMutex lib_mutex;
|
||||
Dqn_String8 exe_dir; // The directory of the current executable
|
||||
|
||||
Dqn_LogProc *log_callback; ///< Set this pointer to override the logging routine
|
||||
void * log_user_data;
|
||||
bool log_to_file; ///< Output logs to file as well as standard out
|
||||
void * log_file; ///< TODO(dqn): Hmmm, how should we do this... ?
|
||||
Dqn_TicketMutex log_file_mutex; ///< Is locked when instantiating the log_file for the first time
|
||||
bool log_no_colour; ///< Disable colours in the logging output
|
||||
|
||||
/// The backup arena to use if no arena is passed into Dqn_Library_Init
|
||||
Dqn_Arena arena_catalog_backup_arena;
|
||||
Dqn_Arena arena;
|
||||
Dqn_ArenaCatalog arena_catalog;
|
||||
|
||||
Dqn_LogProc *log_callback; // Set this pointer to override the logging routine
|
||||
void * log_user_data;
|
||||
bool log_to_file; // Output logs to file as well as standard out
|
||||
Dqn_FsFile log_file; // TODO(dqn): Hmmm, how should we do this... ?
|
||||
Dqn_TicketMutex log_file_mutex; // Is locked when instantiating the log_file for the first time
|
||||
bool log_no_colour; // Disable colours in the logging output
|
||||
|
||||
// NOTE: Leak Tracing ==========================================================================
|
||||
|
||||
bool allocs_are_allowed_to_leak;
|
||||
@ -627,14 +627,6 @@ struct Dqn_Library
|
||||
uint32_t os_page_size;
|
||||
uint32_t os_alloc_granularity;
|
||||
|
||||
// NOTE: Thread Context ========================================================================
|
||||
|
||||
#if defined(DQN_DEBUG_THREAD_CONTEXT)
|
||||
Dqn_TicketMutex thread_context_mutex;
|
||||
Dqn_ArenaStat thread_context_arena_stats[256];
|
||||
uint8_t thread_context_arena_stats_count;
|
||||
#endif
|
||||
|
||||
// NOTE: Profiler ==============================================================================
|
||||
|
||||
#if !defined(DQN_NO_PROFILER)
|
||||
@ -650,6 +642,5 @@ DQN_API void Dqn_Library_SetPointer (Dqn_Library *library
|
||||
DQN_API void Dqn_Library_SetProfiler (Dqn_Profiler *profiler);
|
||||
#endif
|
||||
DQN_API void Dqn_Library_SetLogCallback (Dqn_LogProc *proc, void *user_data);
|
||||
DQN_API void Dqn_Library_SetLogFile (void *file);
|
||||
DQN_API void Dqn_Library_DumpThreadContextArenaStat(Dqn_String8 file_path);
|
||||
|
||||
|
@ -237,7 +237,7 @@ DQN_API Dqn_MemBlock *Dqn_MemBlock_Init(Dqn_usize reserve, Dqn_usize commit, uin
|
||||
DQN_ASSERT(Dqn_IsPowerOfTwoAligned(result->size, DQN_ASAN_POISON_ALIGNMENT));
|
||||
void *poison_ptr = DQN_CAST(void *)Dqn_AlignUpPowerOfTwo(DQN_CAST(char *)result + sizeof(Dqn_MemBlock), DQN_ASAN_POISON_ALIGNMENT);
|
||||
Dqn_usize bytes_to_poison = g_dqn_library->os_page_size + result->size;
|
||||
DQN_ASAN_POISON_MEMORY_REGION(poison_ptr, bytes_to_poison);
|
||||
Dqn_ASAN_PoisonMemoryRegion(poison_ptr, bytes_to_poison);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -261,7 +261,7 @@ DQN_API void *Dqn_MemBlock_Alloc(Dqn_MemBlock *block, Dqn_usize size, uint8_t al
|
||||
DQN_ASSERT(Dqn_IsPowerOfTwoAligned(result, alignment));
|
||||
|
||||
if (DQN_ASAN_POISON)
|
||||
DQN_ASAN_UNPOISON_MEMORY_REGION(result, size);
|
||||
Dqn_ASAN_UnpoisonMemoryRegion(result, size);
|
||||
|
||||
if (zero_mem == Dqn_ZeroMem_Yes) {
|
||||
Dqn_usize reused_bytes = DQN_MIN(block->commit - size_required.data_offset, size);
|
||||
@ -285,7 +285,7 @@ DQN_API void Dqn_MemBlock_Free(Dqn_MemBlock *block)
|
||||
return;
|
||||
Dqn_usize release_size = block->size + Dqn_MemBlock_MetadataSize();
|
||||
if (DQN_ASAN_POISON)
|
||||
DQN_ASAN_UNPOISON_MEMORY_REGION(block, release_size);
|
||||
Dqn_ASAN_UnpoisonMemoryRegion(block, release_size);
|
||||
Dqn_VMem_Release(block, release_size);
|
||||
}
|
||||
|
||||
@ -307,7 +307,7 @@ DQN_API void Dqn_MemBlock_PopTo(Dqn_MemBlock *block, Dqn_usize to)
|
||||
void *poison_ptr = DQN_CAST(char *)block->data + to;
|
||||
void *end_ptr = DQN_CAST(void *)Dqn_AlignUpPowerOfTwo((DQN_CAST(uintptr_t)block->data + block->used), DQN_ASAN_POISON_ALIGNMENT);
|
||||
uintptr_t bytes_to_poison = DQN_CAST(uintptr_t)end_ptr - DQN_CAST(uintptr_t)poison_ptr;
|
||||
DQN_ASAN_POISON_MEMORY_REGION(poison_ptr, bytes_to_poison);
|
||||
Dqn_ASAN_PoisonMemoryRegion(poison_ptr, bytes_to_poison);
|
||||
}
|
||||
block->used = to;
|
||||
}
|
||||
|
@ -295,9 +295,6 @@ struct Dqn_ArenaTempMemoryScope
|
||||
~Dqn_ArenaTempMemoryScope();
|
||||
Dqn_ArenaTempMemory temp_memory;
|
||||
bool cancel = false;
|
||||
#if defined(DQN_LEAK_TRACING)
|
||||
Dqn_CallSite leak_site_;
|
||||
#endif
|
||||
};
|
||||
|
||||
enum Dqn_ArenaCommit
|
||||
|
@ -645,15 +645,15 @@ DQN_API Dqn_FsFile Dqn_Fs_OpenFile(Dqn_String8 path, Dqn_FsFileOpen open_mode, u
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_Fs_WriteFile(Dqn_FsFile *file, char const *buffer, Dqn_usize size)
|
||||
DQN_API bool Dqn_Fs_WriteFileBuffer(Dqn_FsFile *file, void const *buffer, Dqn_usize size)
|
||||
{
|
||||
if (!file || !file->handle || !buffer || size <= 0 || file->error_size)
|
||||
return false;
|
||||
|
||||
bool result = true;
|
||||
#if defined(DQN_OS_WIN32)
|
||||
char const *end = buffer + size;
|
||||
for (char const *ptr = buffer; result && ptr != end; ) {
|
||||
char const *end = DQN_CAST(char *)buffer + size;
|
||||
for (char const *ptr = DQN_CAST(char const *)buffer; result && ptr != end; ) {
|
||||
unsigned long write_size = DQN_CAST(unsigned long)DQN_MIN((unsigned long)-1, end - ptr);
|
||||
unsigned long bytes_written = 0;
|
||||
result = WriteFile(file->handle, ptr, write_size, &bytes_written, nullptr /*lpOverlapped*/) != 0;
|
||||
@ -675,6 +675,32 @@ DQN_API bool Dqn_Fs_WriteFile(Dqn_FsFile *file, char const *buffer, Dqn_usize si
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_Fs_WriteFile(Dqn_FsFile *file, Dqn_String8 buffer)
|
||||
{
|
||||
bool result = Dqn_Fs_WriteFileBuffer(file, buffer.data, buffer.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_Fs_WriteFileFV(Dqn_FsFile *file, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args)
|
||||
{
|
||||
bool result = false;
|
||||
if (!file || !fmt)
|
||||
return result;
|
||||
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
|
||||
Dqn_String8 buffer = Dqn_String8_InitFV(scratch.allocator, fmt, args);
|
||||
result = Dqn_Fs_WriteFileBuffer(file, buffer.data, buffer.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API bool Dqn_Fs_WriteFileF(Dqn_FsFile *file, DQN_FMT_STRING_ANNOTATE char const *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
bool result = Dqn_Fs_WriteFileFV(file, fmt, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_Fs_CloseFile(Dqn_FsFile *file)
|
||||
{
|
||||
if (!file || !file->handle || file->error_size)
|
||||
@ -1902,17 +1928,14 @@ DQN_API uint64_t Dqn_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_tsc_f
|
||||
// NOTE: [$TCTX] Dqn_ThreadContext =================================================================
|
||||
Dqn_ThreadScratch::Dqn_ThreadScratch(Dqn_ThreadContext *context, uint8_t context_index)
|
||||
{
|
||||
index = context_index;
|
||||
allocator = context->temp_allocators[index];
|
||||
arena = context->temp_arenas[index];
|
||||
allocator = context->scratch_allocators[context_index];
|
||||
arena = context->scratch_arenas[context_index];
|
||||
temp_memory = Dqn_Arena_BeginTempMemory(arena);
|
||||
destructed = false;
|
||||
}
|
||||
|
||||
Dqn_ThreadScratch::~Dqn_ThreadScratch()
|
||||
{
|
||||
#if defined(DQN_DEBUG_THREAD_CONTEXT)
|
||||
temp_arenas_stat[index] = arena->stats;
|
||||
#endif
|
||||
DQN_ASSERT(destructed == false);
|
||||
Dqn_Arena_EndTempMemory(temp_memory, /*cancel*/ false);
|
||||
destructed = true;
|
||||
@ -1933,27 +1956,19 @@ DQN_API Dqn_ThreadContext *Dqn_Thread_GetContext()
|
||||
{
|
||||
DQN_THREAD_LOCAL Dqn_ThreadContext result = {};
|
||||
if (!result.init) {
|
||||
result.init = true;
|
||||
result.init = true;
|
||||
Dqn_ArenaCatalog *catalog = &g_dqn_library->arena_catalog;
|
||||
DQN_ASSERTF(g_dqn_library->lib_init, "Library must be initialised by calling Dqn_Library_Init(nullptr)");
|
||||
|
||||
// NOTE: Setup permanent arena
|
||||
Dqn_ArenaCatalog *catalog = &g_dqn_library->arena_catalog;
|
||||
result.allocator = Dqn_Arena_Allocator(result.arena);
|
||||
result.arena = Dqn_ArenaCatalog_AllocF(catalog,
|
||||
DQN_GIGABYTES(1) /*size*/,
|
||||
DQN_KILOBYTES(64) /*commit*/,
|
||||
"Thread %u Arena",
|
||||
Dqn_Thread_GetID());
|
||||
|
||||
// NOTE: Setup temporary arenas
|
||||
for (uint8_t index = 0; index < DQN_THREAD_CONTEXT_ARENAS; index++) {
|
||||
result.temp_arenas[index] = Dqn_ArenaCatalog_AllocF(catalog,
|
||||
DQN_GIGABYTES(1) /*size*/,
|
||||
DQN_KILOBYTES(64) /*commit*/,
|
||||
"Thread %u Temp Arena %u",
|
||||
Dqn_Thread_GetID(),
|
||||
index);
|
||||
result.temp_allocators[index] = Dqn_Arena_Allocator(result.temp_arenas[index]);
|
||||
// NOTE: Setup scratch arenas
|
||||
for (uint8_t index = 0; index < DQN_ARRAY_UCOUNT(result.scratch_arenas); index++) {
|
||||
result.scratch_arenas[index] = Dqn_ArenaCatalog_AllocF(catalog,
|
||||
DQN_GIGABYTES(1) /*size*/,
|
||||
DQN_KILOBYTES(64) /*commit*/,
|
||||
"Thread %u Scratch Arena %u",
|
||||
Dqn_Thread_GetID(),
|
||||
index);
|
||||
result.scratch_allocators[index] = Dqn_Arena_Allocator(result.scratch_arenas[index]);
|
||||
}
|
||||
}
|
||||
return &result;
|
||||
@ -1963,11 +1978,10 @@ DQN_API Dqn_ThreadContext *Dqn_Thread_GetContext()
|
||||
// manually pass it in?
|
||||
DQN_API Dqn_ThreadScratch Dqn_Thread_GetScratch(void const *conflict_arena)
|
||||
{
|
||||
static_assert(DQN_THREAD_CONTEXT_ARENAS < (uint8_t)-1, "We use UINT8_MAX as a sentinel value");
|
||||
Dqn_ThreadContext *context = Dqn_Thread_GetContext();
|
||||
uint8_t context_index = (uint8_t)-1;
|
||||
for (uint8_t index = 0; index < DQN_THREAD_CONTEXT_ARENAS; index++) {
|
||||
Dqn_Arena *arena = context->temp_arenas[index];
|
||||
for (uint8_t index = 0; index < DQN_ARRAY_UCOUNT(context->scratch_arenas); index++) {
|
||||
Dqn_Arena *arena = context->scratch_arenas[index];
|
||||
if (!conflict_arena || arena != conflict_arena) {
|
||||
context_index = index;
|
||||
break;
|
||||
@ -1977,4 +1991,3 @@ DQN_API Dqn_ThreadScratch Dqn_Thread_GetScratch(void const *conflict_arena)
|
||||
DQN_ASSERT(context_index != (uint8_t)-1);
|
||||
return Dqn_ThreadScratch(context, context_index);
|
||||
}
|
||||
|
||||
|
@ -70,9 +70,9 @@ struct Dqn_FsFile
|
||||
|
||||
enum Dqn_FsFileOpen
|
||||
{
|
||||
Dqn_FsFileOpen_CreateAlways, ///< Create file if it does not exist, otherwise, zero out the file and open
|
||||
Dqn_FsFileOpen_OpenIfExist, ///< Open file at path only if it exists
|
||||
Dqn_FsFileOpen_OpenAlways, ///< Open file at path, create file if it does not exist
|
||||
Dqn_FsFileOpen_CreateAlways, // Create file if it does not exist, otherwise, zero out the file and open
|
||||
Dqn_FsFileOpen_OpenIfExist, // Open file at path only if it exists
|
||||
Dqn_FsFileOpen_OpenAlways, // Open file at path, create file if it does not exist
|
||||
};
|
||||
|
||||
enum Dqn_FsFileAccess
|
||||
@ -80,14 +80,17 @@ enum Dqn_FsFileAccess
|
||||
Dqn_FsFileAccess_Read = 1 << 0,
|
||||
Dqn_FsFileAccess_Write = 1 << 1,
|
||||
Dqn_FsFileAccess_Execute = 1 << 2,
|
||||
Dqn_FsFileAccess_AppendOnly = 1 << 3, ///< This flag cannot be combined with any other acess mode
|
||||
Dqn_FsFileAccess_AppendOnly = 1 << 3, // This flag cannot be combined with any other access mode
|
||||
Dqn_FsFileAccess_ReadWrite = Dqn_FsFileAccess_Read | Dqn_FsFileAccess_Write,
|
||||
Dqn_FsFileAccess_All = Dqn_FsFileAccess_ReadWrite | Dqn_FsFileAccess_Execute,
|
||||
};
|
||||
|
||||
DQN_API Dqn_FsFile Dqn_Fs_OpenFile (Dqn_String8 path, Dqn_FsFileOpen open_mode, uint32_t access);
|
||||
DQN_API bool Dqn_Fs_WriteFile(Dqn_FsFile *file, char const *buffer, Dqn_usize size);
|
||||
DQN_API void Dqn_Fs_CloseFile(Dqn_FsFile *file);
|
||||
DQN_API Dqn_FsFile Dqn_Fs_OpenFile (Dqn_String8 path, Dqn_FsFileOpen open_mode, uint32_t access);
|
||||
DQN_API bool Dqn_Fs_WriteFileBuffer(Dqn_FsFile *file, void const *data, Dqn_usize size);
|
||||
DQN_API bool Dqn_Fs_WriteFile (Dqn_FsFile *file, Dqn_String8 buffer);
|
||||
DQN_API bool Dqn_Fs_WriteFileFV (Dqn_FsFile *file, DQN_FMT_STRING_ANNOTATE char const *fmt, va_list args);
|
||||
DQN_API bool Dqn_Fs_WriteFileF (Dqn_FsFile *file, DQN_FMT_STRING_ANNOTATE char const *fmt, ...);
|
||||
DQN_API void Dqn_Fs_CloseFile (Dqn_FsFile *file);
|
||||
#endif // !defined(DQN_NO_FS)
|
||||
|
||||
// NOTE: File system paths =========================================================================
|
||||
@ -459,27 +462,16 @@ DQN_API uint64_t Dqn_OS_EstimateTSCPerSecond(uint64_t duration_ms_to_gauge_ts
|
||||
// @param[in] conflict_arena A pointer to the arena currently being used in the
|
||||
// function
|
||||
|
||||
#if !defined(DQN_THREAD_CONTEXT_ARENAS)
|
||||
#define DQN_THREAD_CONTEXT_ARENAS 2
|
||||
#endif
|
||||
|
||||
struct Dqn_ThreadContext
|
||||
{
|
||||
Dqn_b32 init;
|
||||
|
||||
Dqn_Arena *arena; ///< Per thread arena
|
||||
Dqn_Allocator allocator; ///< Allocator that uses the arena
|
||||
// Scratch memory arena's for the calling thread
|
||||
Dqn_Arena *scratch_arenas[2];
|
||||
|
||||
/// Temp memory arena's for the calling thread
|
||||
Dqn_Arena *temp_arenas[DQN_THREAD_CONTEXT_ARENAS];
|
||||
|
||||
/// Allocators that use the corresponding arena from the thread context.
|
||||
/// Provided for convenience when interfacing with allocator interfaces.
|
||||
Dqn_Allocator temp_allocators[DQN_THREAD_CONTEXT_ARENAS];
|
||||
|
||||
#if defined(DQN_DEBUG_THREAD_CONTEXT)
|
||||
Dqn_ArenaStat temp_arenas_stat[DQN_THREAD_CONTEXT_ARENAS];
|
||||
#endif
|
||||
// Allocators that use the corresponding arena from the thread context.
|
||||
// Provided for convenience when interfacing with allocator interfaces.
|
||||
Dqn_Allocator scratch_allocators[2];
|
||||
};
|
||||
|
||||
struct Dqn_ThreadScratch
|
||||
@ -487,16 +479,10 @@ struct Dqn_ThreadScratch
|
||||
Dqn_ThreadScratch(Dqn_ThreadContext *context, uint8_t context_index);
|
||||
~Dqn_ThreadScratch();
|
||||
|
||||
/// Index into the arena/allocator/stat array in the thread context
|
||||
/// specifying what arena was assigned.
|
||||
uint8_t index;
|
||||
Dqn_Allocator allocator;
|
||||
Dqn_Arena *arena;
|
||||
Dqn_b32 destructed = false; /// Detect copies of the scratch
|
||||
Dqn_b32 destructed;
|
||||
Dqn_ArenaTempMemory temp_memory;
|
||||
#if defined(DQN_LEAK_TRACING)
|
||||
Dqn_CallSite leak_site__;
|
||||
#endif
|
||||
};
|
||||
|
||||
// NOTE: Context ===================================================================================
|
||||
|
@ -1,191 +0,0 @@
|
||||
// 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;
|
||||
}
|
||||
|
@ -1,84 +0,0 @@
|
||||
// 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)
|
||||
|
Loading…
Reference in New Issue
Block a user