Get latest tely changes, w/ new OS primitives from internal project
This commit is contained in:
+1368
-472
File diff suppressed because it is too large
Load Diff
+729
-189
File diff suppressed because it is too large
Load Diff
@@ -1057,6 +1057,36 @@ DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync(DN_Str8Slice cmd_line, DN_OSExecArgs
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DN_API void DN_OS_W32Init(DN_OSW32Core *w32)
|
||||||
|
{
|
||||||
|
InitializeCriticalSection(&w32->sync_primitive_free_list_mutex);
|
||||||
|
QueryPerformanceFrequency(&w32->qpc_frequency);
|
||||||
|
|
||||||
|
// NOTE: DPI
|
||||||
|
HMODULE user32 = LoadLibraryA("user32.dll");
|
||||||
|
if (user32) {
|
||||||
|
w32->get_dpi_for_window = (DN_OSW32GetDpiForWindowFunc* )GetProcAddress(user32, "GetDpiForWindow");
|
||||||
|
w32->get_dpi_for_monitor = (DN_OSW32GetDpiForMonitorFunc * )GetProcAddress(user32, "GetDpiForMonitor");
|
||||||
|
w32->get_system_metrics_for_dpi = (DN_OSW32GetSystemMetricsForDpiFunc *)GetProcAddress(user32, "GetSystemMetricsForDpi");
|
||||||
|
FreeLibrary(user32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: SetThreadDesc
|
||||||
|
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
||||||
|
if (kernel32) {
|
||||||
|
w32->set_thread_description = DN_Cast(DN_OSW32SetThreadDescriptionFunc *) GetProcAddress(kernel32, "SetThreadDescription");
|
||||||
|
FreeLibrary(kernel32);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: win32 bcrypt
|
||||||
|
wchar_t const BCRYPT_ALGORITHM[] = L"RNG";
|
||||||
|
long /*NTSTATUS*/ init_status = BCryptOpenAlgorithmProvider(&w32->bcrypt_rng_handle, BCRYPT_ALGORITHM, nullptr /*implementation*/, 0 /*flags*/);
|
||||||
|
if (w32->bcrypt_rng_handle && init_status == 0)
|
||||||
|
w32->bcrypt_init_success = true;
|
||||||
|
else
|
||||||
|
DN_LogErrorF("Failed to initialise Windows secure random number generator, error: %d", init_status);
|
||||||
|
}
|
||||||
|
|
||||||
DN_API DN_OSW32Core *DN_OS_W32GetCore()
|
DN_API DN_OSW32Core *DN_OS_W32GetCore()
|
||||||
{
|
{
|
||||||
DN_Core *dn = DN_Get();
|
DN_Core *dn = DN_Get();
|
||||||
@@ -1456,6 +1486,160 @@ DN_API void DN_OS_W32ThreadSetName(DN_Str8 name)
|
|||||||
DN_TcScratchEnd(&scratch);
|
DN_TcScratchEnd(&scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DN_API DN_OSW32Window* DN_OS_W32WindowFromHwndMaybeAlloc(DN_OSW32Core *w32, HWND hwnd, DN_Arena *arena)
|
||||||
|
{
|
||||||
|
DN_OSW32Window *result = nullptr;
|
||||||
|
for (DN_OSW32Window *check = w32->windows; !result && check; check = check->next) {
|
||||||
|
if (check->hwnd == hwnd)
|
||||||
|
result = check;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result && arena) {
|
||||||
|
result = DN_ArenaNewZ(arena, DN_OSW32Window);
|
||||||
|
if (result) {
|
||||||
|
result->hwnd = hwnd;
|
||||||
|
if (w32->windows)
|
||||||
|
w32->windows->next = result;
|
||||||
|
result->next = w32->windows;
|
||||||
|
w32->windows = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API LRESULT __stdcall DN_OS_W32WindowProcCustomTitlebar(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
|
||||||
|
{
|
||||||
|
DN_OSW32Core *w32 = DN_OS_W32GetCore();
|
||||||
|
DN_AssertF(w32, "Using this window proc requires that DN's OS layer has been initialised");
|
||||||
|
|
||||||
|
LRESULT result = 0;
|
||||||
|
bool handled = true;
|
||||||
|
switch (msg) {
|
||||||
|
// NOTE: Sent when the size and position of a window's client area must be calculated. By
|
||||||
|
// processing this message, an application can control the content of the window's client area
|
||||||
|
// when the size or position of the window changes.
|
||||||
|
case WM_NCCALCSIZE: {
|
||||||
|
DN_OSW32Window *w32_window = DN_OS_W32WindowFromHwndMaybeAlloc(w32, hwnd, nullptr);
|
||||||
|
if (w32_window && w32_window->custom_title_bar) {
|
||||||
|
// NOTE: Code adapted from raddebugger
|
||||||
|
// https://github.com/EpicGames/raddebugger/blob/7a5a649b89f6a06abdbaee61540468fca9db58f9/src/win32/window_manager/win32_window_manager.c#L668
|
||||||
|
//
|
||||||
|
// The goal here is to subtract away the title bar from the window and restore the pixel
|
||||||
|
// border that native Windows renders windows with. Note that on Windows 11 a non-maximised
|
||||||
|
// window has rounded corners which eats into the available client space that is normally
|
||||||
|
// otherwise eaten into from the native titlebar.
|
||||||
|
DWORD window_style = GetWindowLongW(hwnd, GWL_STYLE);
|
||||||
|
bool is_fullscreen = !(window_style & WS_OVERLAPPEDWINDOW);
|
||||||
|
if (is_fullscreen) {
|
||||||
|
handled = false;
|
||||||
|
} else {
|
||||||
|
DN_UInt dpi = w32->get_dpi_for_window ? w32->get_dpi_for_window(hwnd) : 96;
|
||||||
|
int frame_x = w32->get_system_metrics_for_dpi ? w32->get_system_metrics_for_dpi(SM_CXFRAME, dpi) : GetSystemMetrics(SM_CXFRAME);
|
||||||
|
int frame_y = w32->get_system_metrics_for_dpi ? w32->get_system_metrics_for_dpi(SM_CYFRAME, dpi) : GetSystemMetrics(SM_CYFRAME);
|
||||||
|
int padding = w32->get_system_metrics_for_dpi ? w32->get_system_metrics_for_dpi(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||||
|
|
||||||
|
RECT *rect = w_param == 0 ? DN_Cast(RECT *)l_param : (DN_Cast(NCCALCSIZE_PARAMS *)l_param)->rgrc;
|
||||||
|
rect->right -= frame_x + padding;
|
||||||
|
rect->left += frame_x + padding;
|
||||||
|
rect->bottom -= frame_y + padding;
|
||||||
|
bool is_maximised = IsZoomed(hwnd) != 0;
|
||||||
|
if (is_maximised) {
|
||||||
|
rect->top += frame_y + padding;
|
||||||
|
// If we do not do this hidden taskbar can not be unhidden on mouse hover
|
||||||
|
// Unfortunately it can create an ugly bottom border when maximized...
|
||||||
|
rect->bottom -= 1;
|
||||||
|
} else {
|
||||||
|
int edge_height = w32->get_system_metrics_for_dpi ? w32->get_system_metrics_for_dpi(SM_CYEDGE, dpi) : GetSystemMetrics(SM_CYEDGE);
|
||||||
|
rect->top += edge_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handled = false;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
// NOTE: Sent to a window in order to determine what part of the window corresponds to a
|
||||||
|
// particular screen coordinate. This can happen, for example, when the cursor moves, when a
|
||||||
|
// mouse button is pressed or released, or in response to a call to a function such as
|
||||||
|
// WindowFromPoint. If the mouse is not captured, the message is sent to the window beneath
|
||||||
|
// the cursor. Otherwise, the message is sent to the window that has captured the mouse.
|
||||||
|
case WM_NCHITTEST: {
|
||||||
|
DN_OSW32Window *w32_window = DN_OS_W32WindowFromHwndMaybeAlloc(w32, hwnd, nullptr);
|
||||||
|
if (w32_window && w32_window->custom_title_bar) {
|
||||||
|
// NOTE: Code adapted from raddebugger
|
||||||
|
// https://github.com/EpicGames/raddebugger/blob/7a5a649b89f6a06abdbaee61540468fca9db58f9/src/win32/window_manager/win32_window_manager.c#L668
|
||||||
|
//
|
||||||
|
// Since we removed the titlebar from the window, the resize handlers/grabbers at the top of
|
||||||
|
// the window are no longer functional. We have to reimplement it ourselves.
|
||||||
|
DWORD window_style = GetWindowLongW(hwnd, GWL_STYLE);
|
||||||
|
bool is_fullscreen = !(window_style & WS_OVERLAPPEDWINDOW);
|
||||||
|
handled = false;
|
||||||
|
if (!is_fullscreen) {
|
||||||
|
// Let the default procedure handle resizing areas
|
||||||
|
if (w32->fallback_wnd_proc)
|
||||||
|
result = CallWindowProcW(w32->fallback_wnd_proc, hwnd, msg, w_param, l_param);
|
||||||
|
else
|
||||||
|
result = DefWindowProcW(hwnd, msg, w_param, l_param);
|
||||||
|
|
||||||
|
switch (result) {
|
||||||
|
case HTNOWHERE:
|
||||||
|
case HTRIGHT:
|
||||||
|
case HTLEFT:
|
||||||
|
case HTTOPLEFT:
|
||||||
|
case HTTOPRIGHT:
|
||||||
|
case HTBOTTOMRIGHT:
|
||||||
|
case HTBOTTOM:
|
||||||
|
case HTBOTTOMLEFT: {
|
||||||
|
handled = true;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
POINT pos_monitor = {};
|
||||||
|
pos_monitor.x = GET_X_LPARAM(l_param);
|
||||||
|
pos_monitor.y = GET_Y_LPARAM(l_param);
|
||||||
|
handled = true;
|
||||||
|
|
||||||
|
POINT pos_client = pos_monitor;
|
||||||
|
ScreenToClient(hwnd, &pos_client);
|
||||||
|
|
||||||
|
DN_V2F32 title_bar_min = w32_window->custom_title_bar_rect_that_is_draggable.pos;
|
||||||
|
DN_V2F32 title_bar_max = title_bar_min + w32_window->custom_title_bar_rect_that_is_draggable.size;
|
||||||
|
DN_UInt dpi = w32->get_dpi_for_window ? w32->get_dpi_for_window(hwnd) : 96;
|
||||||
|
int frame_y = w32->get_system_metrics_for_dpi ? w32->get_system_metrics_for_dpi(SM_CYFRAME, dpi) : GetSystemMetrics(SM_CYFRAME);
|
||||||
|
int padding = w32->get_system_metrics_for_dpi ? w32->get_system_metrics_for_dpi(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||||
|
bool is_over_top_resize = pos_client.y >= 0 && pos_client.y < (frame_y + padding);
|
||||||
|
bool is_over_title_bar = pos_client.x >= title_bar_min.x && pos_client.x < title_bar_max.x &&
|
||||||
|
pos_client.y >= title_bar_min.y && pos_client.y < title_bar_max.y;
|
||||||
|
bool is_maximised = IsZoomed(hwnd) != 0;
|
||||||
|
if (!is_maximised && is_over_top_resize)
|
||||||
|
result = HTTOP;
|
||||||
|
else if (is_over_title_bar)
|
||||||
|
result = HTCAPTION;
|
||||||
|
else
|
||||||
|
result = HTCLIENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handled = false;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
handled = false;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
if (w32->fallback_wnd_proc) {
|
||||||
|
result = CallWindowProcW(w32->fallback_wnd_proc, hwnd, msg, w_param, l_param);
|
||||||
|
} else {
|
||||||
|
result = DefWindowProcW(hwnd, msg, w_param, l_param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code)
|
DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code)
|
||||||
{
|
{
|
||||||
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
|
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
|
||||||
|
|||||||
+33
-4
@@ -20,6 +20,18 @@ struct DN_OSW32FolderIteratorW
|
|||||||
wchar_t file_name_buf[512];
|
wchar_t file_name_buf[512];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DN_OSW32Window
|
||||||
|
{
|
||||||
|
HWND hwnd;
|
||||||
|
// NOTE: For windows with custom title bars, this should be the rect in framebuffer units that
|
||||||
|
// when the mouse is down will move the window, or if the mouse is double-clicked then toggle the
|
||||||
|
// maximisation of the window. This rect should not include any custom drawn menu buttons so that
|
||||||
|
// those buttons can be handled by your application.
|
||||||
|
DN_Rect custom_title_bar_rect_that_is_draggable;
|
||||||
|
bool custom_title_bar;
|
||||||
|
DN_OSW32Window *next;
|
||||||
|
};
|
||||||
|
|
||||||
enum DN_OSW32SyncPrimitiveType
|
enum DN_OSW32SyncPrimitiveType
|
||||||
{
|
{
|
||||||
DN_OSW32SyncPrimitiveType_Semaphore,
|
DN_OSW32SyncPrimitiveType_Semaphore,
|
||||||
@@ -41,21 +53,38 @@ struct DN_OSW32SyncPrimitive
|
|||||||
DN_OSW32SyncPrimitive *next;
|
DN_OSW32SyncPrimitive *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef HRESULT DN_OSW32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription);
|
typedef HRESULT DN_OSW32SetThreadDescriptionFunc (HANDLE hThread, PWSTR const lpThreadDescription);
|
||||||
|
typedef BOOL DN_OSW32SetProcessDpiAwarenessContextFunc(void* value);
|
||||||
|
typedef UINT DN_OSW32GetDpiForWindowFunc (HWND hwnd);
|
||||||
|
typedef HRESULT DN_OSW32GetDpiForMonitorFunc (HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT *dpiX, UINT *dpiY);
|
||||||
|
typedef int DN_OSW32GetSystemMetricsForDpiFunc (int nIndex, UINT dpi);
|
||||||
|
|
||||||
|
#define DN_OSW32DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((void*)-4)
|
||||||
struct DN_OSW32Core
|
struct DN_OSW32Core
|
||||||
{
|
{
|
||||||
|
// NOTE: These functions are dynamically loaded because they might not be present on the user's
|
||||||
|
// machine. For example the GetDpiForWindow is Windows 10+ only.
|
||||||
DN_OSW32SetThreadDescriptionFunc *set_thread_description;
|
DN_OSW32SetThreadDescriptionFunc *set_thread_description;
|
||||||
|
DN_OSW32GetDpiForWindowFunc *get_dpi_for_window;
|
||||||
|
DN_OSW32GetDpiForMonitorFunc *get_dpi_for_monitor;
|
||||||
|
DN_OSW32GetSystemMetricsForDpiFunc *get_system_metrics_for_dpi;
|
||||||
|
|
||||||
LARGE_INTEGER qpc_frequency;
|
LARGE_INTEGER qpc_frequency;
|
||||||
void *bcrypt_rng_handle;
|
void* bcrypt_rng_handle;
|
||||||
bool bcrypt_init_success;
|
bool bcrypt_init_success;
|
||||||
bool sym_initialised;
|
bool sym_initialised;
|
||||||
|
|
||||||
CRITICAL_SECTION sync_primitive_free_list_mutex;
|
CRITICAL_SECTION sync_primitive_free_list_mutex;
|
||||||
DN_OSW32SyncPrimitive *sync_primitive_free_list;
|
DN_OSW32SyncPrimitive* sync_primitive_free_list;
|
||||||
|
|
||||||
|
DN_OSW32Window* windows;
|
||||||
|
WNDPROC fallback_wnd_proc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DN_API void DN_OS_W32Init (DN_OSW32Core *w32);
|
||||||
DN_API DN_OSW32Core* DN_OS_W32GetCore ();
|
DN_API DN_OSW32Core* DN_OS_W32GetCore ();
|
||||||
DN_API void DN_OS_W32ThreadSetName (DN_Str8 name);
|
DN_API void DN_OS_W32ThreadSetName (DN_Str8 name);
|
||||||
|
DN_API DN_OSW32Window* DN_OS_W32WindowFromHwndMaybeAlloc(DN_OSW32Core *w32, HWND hwnd, DN_Arena *arena);
|
||||||
|
DN_API LRESULT __stdcall DN_OS_W32WindowProcCustomTitlebar(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param);
|
||||||
|
|
||||||
DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code);
|
DN_API DN_Str16 DN_OS_W32ErrorCodeToMsg16Alloc(DN_U32 error_code);
|
||||||
DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code);
|
DN_API DN_OSW32Error DN_OS_W32ErrorCodeToMsg (DN_Arena *arena, DN_U32 error_code);
|
||||||
|
|||||||
@@ -13,19 +13,27 @@
|
|||||||
#pragma comment(lib, "pathcch")
|
#pragma comment(lib, "pathcch")
|
||||||
#pragma comment(lib, "Shell32") // ShellExecuteW
|
#pragma comment(lib, "Shell32") // ShellExecuteW
|
||||||
#pragma comment(lib, "shlwapi")
|
#pragma comment(lib, "shlwapi")
|
||||||
|
#pragma comment(lib, "user32")
|
||||||
|
|
||||||
|
// TODO: Technically we only need this library for custom window titlebars to get access to DWM
|
||||||
|
// functions. Otherwise this API surface is not used in the DN OS layer.
|
||||||
|
#pragma comment(lib, "dwmapi")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(DN_NO_WINDOWS_H_REPLACEMENT_HEADER) || defined(_INC_WINDOWS)
|
#if defined(DN_NO_WINDOWS_H_REPLACEMENT_HEADER) || defined(_INC_WINDOWS)
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h> // LONG
|
#include <Windows.h> // LONG
|
||||||
|
#include <dwmapi.h> // DwmExtendFrameIntoClientArea...
|
||||||
#include <bcrypt.h> // DN_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc
|
#include <bcrypt.h> // DN_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc
|
||||||
#include <shellapi.h> // DN_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc
|
#include <shellapi.h> // DN_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc
|
||||||
|
#include <ShellScalingApi.h> // MONITOR_DPI_TYPE
|
||||||
#include <shlwapi.h> // PathRelativePathTO
|
#include <shlwapi.h> // PathRelativePathTO
|
||||||
#include <pathcch.h> // PathCchCanonicalizeEx
|
#include <pathcch.h> // PathCchCanonicalizeEx
|
||||||
#include <winhttp.h> // WinHttp*
|
#include <winhttp.h> // WinHttp*
|
||||||
#include <psapi.h> // PROCESS_MEMORY_COUNTERS_EX2
|
#include <psapi.h> // PROCESS_MEMORY_COUNTERS_EX2
|
||||||
#include <commdlg.h> // OPENFILENAMEW
|
#include <commdlg.h> // OPENFILENAMEW
|
||||||
#include <DbgHelp.h>
|
#include <DbgHelp.h>
|
||||||
|
#include <windowsx.h> // GET_X_PARAM
|
||||||
#else
|
#else
|
||||||
DN_MSVC_WARNING_PUSH
|
DN_MSVC_WARNING_PUSH
|
||||||
DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
|
DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
|
||||||
@@ -60,6 +68,7 @@
|
|||||||
typedef unsigned __int64 WPARAM;
|
typedef unsigned __int64 WPARAM;
|
||||||
typedef LONG_PTR LPARAM;
|
typedef LONG_PTR LPARAM;
|
||||||
typedef LONG_PTR LRESULT;
|
typedef LONG_PTR LRESULT;
|
||||||
|
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
|
||||||
|
|
||||||
#define MAX_PATH 260
|
#define MAX_PATH 260
|
||||||
|
|
||||||
@@ -68,6 +77,11 @@
|
|||||||
DWORD dwHighDateTime;
|
DWORD dwHighDateTime;
|
||||||
} FILETIME, *PFILETIME, *LPFILETIME;
|
} FILETIME, *PFILETIME, *LPFILETIME;
|
||||||
|
|
||||||
|
#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff))
|
||||||
|
#define HIWORD(l) ((WORD)((((DWORD_PTR)(l)) >> 16) & 0xffff))
|
||||||
|
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
|
||||||
|
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
|
||||||
|
|
||||||
// NOTE: shared/winerror.h /////////////////////////////////////////////////////////////////////
|
// NOTE: shared/winerror.h /////////////////////////////////////////////////////////////////////
|
||||||
// NOTE: GetModuleFileNameW
|
// NOTE: GetModuleFileNameW
|
||||||
#define ERROR_INSUFFICIENT_BUFFER 122L // dderror
|
#define ERROR_INSUFFICIENT_BUFFER 122L // dderror
|
||||||
@@ -87,6 +101,7 @@
|
|||||||
typedef wchar_t WCHAR; // wc, 16-bit UNICODE character
|
typedef wchar_t WCHAR; // wc, 16-bit UNICODE character
|
||||||
typedef CHAR * NPSTR, *LPSTR, *PSTR;
|
typedef CHAR * NPSTR, *LPSTR, *PSTR;
|
||||||
typedef WCHAR * NWPSTR, *LPWSTR, *PWSTR;
|
typedef WCHAR * NWPSTR, *LPWSTR, *PWSTR;
|
||||||
|
typedef const WCHAR* LPCWSTR, *PCWSTR;
|
||||||
typedef long HRESULT;
|
typedef long HRESULT;
|
||||||
|
|
||||||
// NOTE: VirtualAlloc: Allocation Type
|
// NOTE: VirtualAlloc: Allocation Type
|
||||||
@@ -372,6 +387,11 @@
|
|||||||
LONG y;
|
LONG y;
|
||||||
} POINT, *PPOINT, *NPPOINT, *LPPOINT;
|
} POINT, *PPOINT, *NPPOINT, *LPPOINT;
|
||||||
|
|
||||||
|
struct HMONITOR__ {
|
||||||
|
int unused;
|
||||||
|
};
|
||||||
|
typedef struct HMONITOR__ *HMONITOR;
|
||||||
|
|
||||||
// NOTE: handleapi.h ///////////////////////////////////////////////////////////////////////////
|
// NOTE: handleapi.h ///////////////////////////////////////////////////////////////////////////
|
||||||
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
|
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
|
||||||
|
|
||||||
@@ -670,7 +690,59 @@
|
|||||||
RECT rcDevice;
|
RECT rcDevice;
|
||||||
#endif
|
#endif
|
||||||
} WINDOWPLACEMENT;
|
} WINDOWPLACEMENT;
|
||||||
|
|
||||||
|
typedef struct tagWINDOWPOS {
|
||||||
|
HWND hwnd;
|
||||||
|
HWND hwndInsertAfter;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int cx;
|
||||||
|
int cy;
|
||||||
|
UINT flags;
|
||||||
|
} WINDOWPOS, *LPWINDOWPOS, *PWINDOWPOS;
|
||||||
|
|
||||||
|
typedef struct tagNCCALCSIZE_PARAMS {
|
||||||
|
RECT rgrc[3];
|
||||||
|
PWINDOWPOS lppos;
|
||||||
|
} NCCALCSIZE_PARAMS, *LPNCCALCSIZE_PARAMS;
|
||||||
|
|
||||||
typedef WINDOWPLACEMENT *PWINDOWPLACEMENT, *LPWINDOWPLACEMENT;
|
typedef WINDOWPLACEMENT *PWINDOWPLACEMENT, *LPWINDOWPLACEMENT;
|
||||||
|
typedef LRESULT (__stdcall* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
|
#define WM_NCHITTEST 0x0084
|
||||||
|
|
||||||
|
#define WS_OVERLAPPED 0x00000000L
|
||||||
|
#define WS_POPUP 0x80000000L
|
||||||
|
#define WS_CHILD 0x40000000L
|
||||||
|
#define WS_MINIMIZE 0x20000000L
|
||||||
|
#define WS_VISIBLE 0x10000000L
|
||||||
|
#define WS_DISABLED 0x08000000L
|
||||||
|
#define WS_CLIPSIBLINGS 0x04000000L
|
||||||
|
#define WS_CLIPCHILDREN 0x02000000L
|
||||||
|
#define WS_MAXIMIZE 0x01000000L
|
||||||
|
#define WS_CAPTION 0x00C00000L /* WS_BORDER | WS_DLGFRAME */
|
||||||
|
#define WS_BORDER 0x00800000L
|
||||||
|
#define WS_DLGFRAME 0x00400000L
|
||||||
|
#define WS_VSCROLL 0x00200000L
|
||||||
|
#define WS_HSCROLL 0x00100000L
|
||||||
|
#define WS_SYSMENU 0x00080000L
|
||||||
|
#define WS_THICKFRAME 0x00040000L
|
||||||
|
#define WS_GROUP 0x00020000L
|
||||||
|
#define WS_TABSTOP 0x00010000L
|
||||||
|
#define WS_MINIMIZEBOX 0x00020000L
|
||||||
|
#define WS_MAXIMIZEBOX 0x00010000L
|
||||||
|
#define WS_TILED WS_OVERLAPPED
|
||||||
|
#define WS_ICONIC WS_MINIMIZE
|
||||||
|
#define WS_SIZEBOX WS_THICKFRAME
|
||||||
|
#define WS_TILEDWINDOW WS_OVERLAPPEDWINDOW
|
||||||
|
|
||||||
|
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | \
|
||||||
|
WS_CAPTION | \
|
||||||
|
WS_SYSMENU | \
|
||||||
|
WS_THICKFRAME | \
|
||||||
|
WS_MINIMIZEBOX | \
|
||||||
|
WS_MAXIMIZEBOX)
|
||||||
|
|
||||||
|
|
||||||
#define SW_HIDE 0
|
#define SW_HIDE 0
|
||||||
#define SW_NORMAL 1
|
#define SW_NORMAL 1
|
||||||
@@ -678,9 +750,71 @@
|
|||||||
#define SW_MAXIMIZE 3
|
#define SW_MAXIMIZE 3
|
||||||
#define SW_SHOWNOACTIVATE 4
|
#define SW_SHOWNOACTIVATE 4
|
||||||
#define SW_SHOW 5
|
#define SW_SHOW 5
|
||||||
|
#define SW_MINIMIZE 6
|
||||||
#define SW_RESTORE 9
|
#define SW_RESTORE 9
|
||||||
#define SW_FORCEMINIMIZE 11
|
#define SW_FORCEMINIMIZE 11
|
||||||
|
|
||||||
|
#define SWP_NOSIZE 0x0001
|
||||||
|
#define SWP_NOMOVE 0x0002
|
||||||
|
#define SWP_NOZORDER 0x0004
|
||||||
|
#define SWP_NOREDRAW 0x0008
|
||||||
|
#define SWP_NOACTIVATE 0x0010
|
||||||
|
#define SWP_FRAMECHANGED 0x0020 /* The frame changed: send WM_NCCALCSIZE */
|
||||||
|
#define SWP_SHOWWINDOW 0x0040
|
||||||
|
#define SWP_HIDEWINDOW 0x0080
|
||||||
|
#define SWP_NOCOPYBITS 0x0100
|
||||||
|
#define SWP_NOOWNERZORDER 0x0200 /* Don't do owner Z ordering */
|
||||||
|
#define SWP_NOSENDCHANGING 0x0400 /* Don't send WM_WINDOWPOSCHANGING */
|
||||||
|
#define SWP_DRAWFRAME SWP_FRAMECHANGED
|
||||||
|
#define SWP_NOREPOSITION SWP_NOOWNERZORDER
|
||||||
|
|
||||||
|
#define SM_CXEDGE 45
|
||||||
|
#define SM_CYEDGE 46
|
||||||
|
#define SM_CXFRAME 32
|
||||||
|
#define SM_CYFRAME 33
|
||||||
|
#define SM_CXPADDEDBORDER 92
|
||||||
|
|
||||||
|
#define GWLP_WNDPROC (-4)
|
||||||
|
|
||||||
|
#define GWL_STYLE (-16)
|
||||||
|
|
||||||
|
#define WS_OVERLAPPED 0x00000000L
|
||||||
|
|
||||||
|
#define WM_NCCALCSIZE 0x0083
|
||||||
|
|
||||||
|
// WM_NCHITTEST and MOUSEHOOKSTRUCT Mouse Position Codes
|
||||||
|
#define HTERROR (-2)
|
||||||
|
#define HTTRANSPARENT (-1)
|
||||||
|
#define HTNOWHERE 0
|
||||||
|
#define HTCLIENT 1
|
||||||
|
#define HTCAPTION 2
|
||||||
|
#define HTSYSMENU 3
|
||||||
|
#define HTGROWBOX 4
|
||||||
|
#define HTSIZE HTGROWBOX
|
||||||
|
#define HTMENU 5
|
||||||
|
#define HTHSCROLL 6
|
||||||
|
#define HTVSCROLL 7
|
||||||
|
#define HTMINBUTTON 8
|
||||||
|
#define HTMAXBUTTON 9
|
||||||
|
#define HTLEFT 10
|
||||||
|
#define HTRIGHT 11
|
||||||
|
#define HTTOP 12
|
||||||
|
#define HTTOPLEFT 13
|
||||||
|
#define HTTOPRIGHT 14
|
||||||
|
#define HTBOTTOM 15
|
||||||
|
#define HTBOTTOMLEFT 16
|
||||||
|
#define HTBOTTOMRIGHT 17
|
||||||
|
#define HTBORDER 18
|
||||||
|
#define HTREDUCE HTMINBUTTON
|
||||||
|
#define HTZOOM HTMAXBUTTON
|
||||||
|
#define HTSIZEFIRST HTLEFT
|
||||||
|
#define HTSIZELAST HTBOTTOMRIGHT
|
||||||
|
#if(WINVER >= 0x0400)
|
||||||
|
#define HTOBJECT 19
|
||||||
|
#define HTCLOSE 20
|
||||||
|
#define HTHELP 21
|
||||||
|
#endif /* WINVER >= 0x0400 */
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
__declspec(dllimport) BOOL __stdcall GetWindowRect (HWND hWnd, RECT *lpRect);
|
__declspec(dllimport) BOOL __stdcall GetWindowRect (HWND hWnd, RECT *lpRect);
|
||||||
@@ -689,11 +823,34 @@
|
|||||||
__declspec(dllimport) BOOL __stdcall ShowWindow (HWND hWnd, int nCmdShow);
|
__declspec(dllimport) BOOL __stdcall ShowWindow (HWND hWnd, int nCmdShow);
|
||||||
__declspec(dllimport) BOOL __stdcall GetWindowPlacement (HWND hWnd, WINDOWPLACEMENT *lpwndpl);
|
__declspec(dllimport) BOOL __stdcall GetWindowPlacement (HWND hWnd, WINDOWPLACEMENT *lpwndpl);
|
||||||
__declspec(dllimport) BOOL __stdcall IsIconic (HWND hWnd);
|
__declspec(dllimport) BOOL __stdcall IsIconic (HWND hWnd);
|
||||||
|
__declspec(dllimport) BOOL __stdcall IsZoomed (HWND hWnd);
|
||||||
__declspec(dllimport) BOOL __stdcall BringWindowToTop (HWND hWnd);
|
__declspec(dllimport) BOOL __stdcall BringWindowToTop (HWND hWnd);
|
||||||
__declspec(dllimport) BOOL __stdcall SetForegroundWindow (HWND hWnd);
|
__declspec(dllimport) BOOL __stdcall SetForegroundWindow (HWND hWnd);
|
||||||
__declspec(dllimport) HWND __stdcall SetFocus (HWND hWnd);
|
__declspec(dllimport) HWND __stdcall SetFocus (HWND hWnd);
|
||||||
__declspec(dllimport) HWND __stdcall GetForegroundWindow ();
|
__declspec(dllimport) HWND __stdcall GetForegroundWindow ();
|
||||||
__declspec(dllimport) BOOL __stdcall SetWindowTextW (HWND hWnd, LPCWSTR lpString);
|
__declspec(dllimport) BOOL __stdcall SetWindowTextW (HWND hWnd, LPCWSTR lpString);
|
||||||
|
__declspec(dllimport) UINT __stdcall GetDoubleClickTime ();
|
||||||
|
__declspec(dllimport) LONG_PTR __stdcall GetWindowLongPtrW (HWND hWnd, int nIndex);
|
||||||
|
__declspec(dllimport) LONG_PTR __stdcall SetWindowLongPtrW (HWND hWnd, int nIndex, LONG_PTR dwNewLong);
|
||||||
|
__declspec(dllimport) LONG __stdcall GetWindowLongW (HWND hWnd, int nIndex);
|
||||||
|
__declspec(dllimport) LRESULT __stdcall CallWindowProcW (WNDPROC lpPrevWndFunc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
__declspec(dllimport) int __stdcall GetSystemMetrics (int nIndex);
|
||||||
|
__declspec(dllimport) BOOL __stdcall ScreenToClient (HWND hWnd, LPPOINT lpPoint);
|
||||||
|
__declspec(dllimport) LRESULT __stdcall DefWindowProcW (HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: um/dwmapi.h //////////////////////////////////////////////////////////////////////////
|
||||||
|
typedef struct _MARGINS
|
||||||
|
{
|
||||||
|
int cxLeftWidth; // width of left border that retains its size
|
||||||
|
int cxRightWidth; // width of right border that retains its size
|
||||||
|
int cyTopHeight; // height of top border that retains its size
|
||||||
|
int cyBottomHeight; // height of bottom border that retains its size
|
||||||
|
} MARGINS, *PMARGINS;
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
__declspec(dllimport) HRESULT __stdcall DwmExtendFrameIntoClientArea(HWND hWnd, const MARGINS* pMarInset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: um/wininet.h //////////////////////////////////////////////////////////////////////////
|
// NOTE: um/wininet.h //////////////////////////////////////////////////////////////////////////
|
||||||
@@ -1363,6 +1520,14 @@
|
|||||||
#define EXCEPTION_CONTINUE_SEARCH 0
|
#define EXCEPTION_CONTINUE_SEARCH 0
|
||||||
#define EXCEPTION_CONTINUE_EXECUTION (-1)
|
#define EXCEPTION_CONTINUE_EXECUTION (-1)
|
||||||
|
|
||||||
|
// NOTE: um/shellscalingapi.h
|
||||||
|
typedef enum MONITOR_DPI_TYPE {
|
||||||
|
MDT_EFFECTIVE_DPI = 0,
|
||||||
|
MDT_ANGULAR_DPI = 1,
|
||||||
|
MDT_RAW_DPI = 2,
|
||||||
|
MDT_DEFAULT = MDT_EFFECTIVE_DPI
|
||||||
|
} MONITOR_DPI_TYPE;
|
||||||
|
|
||||||
DN_MSVC_WARNING_POP
|
DN_MSVC_WARNING_POP
|
||||||
#endif // !defined(_INC_WINDOWS)
|
#endif // !defined(_INC_WINDOWS)
|
||||||
#endif // !defined(DN_OS_WINDOWS_H)
|
#endif // !defined(DN_OS_WINDOWS_H)
|
||||||
|
|||||||
@@ -800,7 +800,7 @@ DN_TestCore DN_SHA3_TestSuite(DN_Arena *arena)
|
|||||||
|
|
||||||
void DN_SHA3_TestSuiteThenOutput(DN_Str8FromTestCoreFlags flags)
|
void DN_SHA3_TestSuiteThenOutput(DN_Str8FromTestCoreFlags flags)
|
||||||
{
|
{
|
||||||
DN_Arena arena = DN_ArenaFromHeap(DN_Megabytes(1), DN_Kilobytes(64), DN_MemFlags_Nil, DN_OS_HeapInitDefault());
|
DN_Arena arena = DN_ArenaFromHeap(DN_Megabytes(1), DN_Kilobytes(64), DN_MemFlags_Nil, DN_OS_HeapInitDefault(), "DN SHA3 Tests");
|
||||||
DN_TestCore test = DN_SHA3_TestSuite(&arena);
|
DN_TestCore test = DN_SHA3_TestSuite(&arena);
|
||||||
DN_Str8 output = DN_Str8FromTestCore(&test, &arena, flags);
|
DN_Str8 output = DN_Str8FromTestCore(&test, &arena, flags);
|
||||||
printf("%.*s", DN_Str8PrintFmt(output));
|
printf("%.*s", DN_Str8PrintFmt(output));
|
||||||
|
|||||||
+841
-360
File diff suppressed because it is too large
Load Diff
+406
-117
@@ -182,11 +182,17 @@
|
|||||||
// the stacktrace that is stored per region to report to the user when a UAF guard violation
|
// the stacktrace that is stored per region to report to the user when a UAF guard violation
|
||||||
// occurs.
|
// occurs.
|
||||||
|
|
||||||
|
// Memory Debugger
|
||||||
|
// Set `DN_MEM_DEBUGGER` to `1` to enable memory debugging which enables the `DN_Core`'s
|
||||||
|
// `mem_debugger` field, tracks all allocations in the application and reports leaks.
|
||||||
|
//
|
||||||
|
// #define DN_MEM_DEBUGGER 1
|
||||||
|
|
||||||
// Paranoia Level
|
// Paranoia Level
|
||||||
// Set the `DN_PARANOIA_LEVEL` to an integer value to enable various validation layers and
|
// Set the `DN_PARANOIA_LEVEL` to an integer value to enable various validation layers and
|
||||||
// error checking mechanisms in the codebase and primitives exposed by the library
|
// error checking mechanisms in the codebase and primitives exposed by the library
|
||||||
// (default: PARANOID level 1 in debug builds, 0 otherwise)
|
// (default: PARANOIA level 1 in debug builds, 0 otherwise) paranoia level 0 in release builds
|
||||||
// paranoia level 0 in release builds and level 1 for debug.
|
// and level 1 for debug.
|
||||||
//
|
//
|
||||||
// #define DN_PARANOIA_LEVEL 1
|
// #define DN_PARANOIA_LEVEL 1
|
||||||
//
|
//
|
||||||
@@ -559,7 +565,7 @@
|
|||||||
#define DN_ForIndexU(index, count) DN_USize index = 0; index < count; index++
|
#define DN_ForIndexU(index, count) DN_USize index = 0; index < count; index++
|
||||||
#define DN_ForIndexI(index, count) DN_ISize index = 0; index < count; index++
|
#define DN_ForIndexI(index, count) DN_ISize index = 0; index < count; index++
|
||||||
#define DN_ForItSize(it, T, array, count) struct { DN_USize index; T *data; } it = {0, &(array)[0]}; it.index < (count); it.index++, it.data = (array) + it.index
|
#define DN_ForItSize(it, T, array, count) struct { DN_USize index; T *data; } it = {0, &(array)[0]}; it.index < (count); it.index++, it.data = (array) + it.index
|
||||||
#define DN_ForItSizeReverse(it, T, array, count) struct { DN_USize index; T *data; } it = {(count) - 1, &(array)[count - 1]}; it.index < (count); it.index--, it.data = (array) + it.index
|
#define DN_ForItSizeReverse(it, T, array, count) struct { DN_USize index; T *data; } it = {(count) ? (count) - 1 : 0, (count) ? &(array)[count - 1] : 0}; it.index < (count); it.index--, it.data = (array) + it.index
|
||||||
#define DN_ForIt(it, T, array) struct { DN_USize index; T *data; } it = {0, &(array)->data[0]}; it.index < (array)->count; it.index++, it.data = ((array)->data) + it.index
|
#define DN_ForIt(it, T, array) struct { DN_USize index; T *data; } it = {0, &(array)->data[0]}; it.index < (array)->count; it.index++, it.data = ((array)->data) + it.index
|
||||||
#define DN_ForLinkedListIt(it, T, list) struct { DN_USize index; T *data; } it = {0, list}; it.data; it.index++, it.data = ((it).data->next)
|
#define DN_ForLinkedListIt(it, T, list) struct { DN_USize index; T *data; } it = {0, list}; it.data; it.index++, it.data = ((it).data->next)
|
||||||
#define DN_ForItCArray(it, T, array) struct { DN_USize index; T *data; } it = {0, &(array)[0]}; it.index < DN_ArrayCountU(array); it.index++, it.data = (array) + it.index
|
#define DN_ForItCArray(it, T, array) struct { DN_USize index; T *data; } it = {0, &(array)[0]}; it.index < DN_ArrayCountU(array); it.index++, it.data = (array) + it.index
|
||||||
@@ -786,6 +792,14 @@ typedef enum DN_ZMem {
|
|||||||
DN_ZMem_Yes, // Memory should be zero-ed out before giving to the callee
|
DN_ZMem_Yes, // Memory should be zero-ed out before giving to the callee
|
||||||
} DN_ZMem;
|
} DN_ZMem;
|
||||||
|
|
||||||
|
typedef enum DN_Side {
|
||||||
|
DN_Side_Left,
|
||||||
|
DN_Side_Right,
|
||||||
|
DN_Side_Top,
|
||||||
|
DN_Side_Bottom,
|
||||||
|
DN_Side_Count,
|
||||||
|
} DN_Side;
|
||||||
|
|
||||||
typedef enum DN_AddType {
|
typedef enum DN_AddType {
|
||||||
DN_AddType_Prepend,
|
DN_AddType_Prepend,
|
||||||
DN_AddType_Append,
|
DN_AddType_Append,
|
||||||
@@ -1000,12 +1014,14 @@ DN_MSVC_WARNING_POP
|
|||||||
typedef struct DN_CallSite DN_CallSite;
|
typedef struct DN_CallSite DN_CallSite;
|
||||||
struct DN_CallSite
|
struct DN_CallSite
|
||||||
{
|
{
|
||||||
|
DN_Str8 name;
|
||||||
DN_Str8 file;
|
DN_Str8 file;
|
||||||
DN_Str8 function;
|
DN_Str8 function;
|
||||||
DN_U32 line;
|
DN_U32 line;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DN_CallSiteNow DN_Literal(DN_CallSite){DN_Str8Lit(__FILE__), DN_Str8Lit(__func__), __LINE__ }
|
#define DN_CallSiteNow DN_Literal(DN_CallSite){DN_Str8Lit(""), DN_Str8Lit(__FILE__), DN_Str8Lit(__func__), __LINE__ }
|
||||||
|
#define DN_CallSiteNowNamed(name_cstr) DN_Literal(DN_CallSite){DN_Str8Lit(name_cstr), DN_Str8Lit(__FILE__), DN_Str8Lit(__func__), __LINE__ }
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
template <typename Procedure>
|
template <typename Procedure>
|
||||||
@@ -1131,9 +1147,9 @@ enum DN_MemPage_
|
|||||||
// This flag must only be used in DN_Mem_Protect
|
// This flag must only be used in DN_Mem_Protect
|
||||||
DN_MemPage_Guard = 1 << 3,
|
DN_MemPage_Guard = 1 << 3,
|
||||||
|
|
||||||
// If leak tracing is enabled, this flag will allow the allocation recorded
|
// If memory debugging is enabled, this flag will allow the allocation
|
||||||
// from the reserve call to be leaked, e.g. not printed when leaks are
|
// recorded from the reserve call to be leaked, e.g. not printed when leaks
|
||||||
// dumped to the console.
|
// are dumped to the console.
|
||||||
DN_MemPage_AllocRecordLeakPermitted = 1 << 4,
|
DN_MemPage_AllocRecordLeakPermitted = 1 << 4,
|
||||||
|
|
||||||
// If leak tracing is enabled this flag will prevent any allocation record
|
// If leak tracing is enabled this flag will prevent any allocation record
|
||||||
@@ -1165,15 +1181,31 @@ typedef enum DN_HeapType {
|
|||||||
DN_HeapType_Virtual,
|
DN_HeapType_Virtual,
|
||||||
} DN_HeapType;
|
} DN_HeapType;
|
||||||
|
|
||||||
|
typedef DN_U32 DN_HeapAllocFlag;
|
||||||
|
enum DN_HeapAllocFlag_ {
|
||||||
|
DN_HeapAllocFlag_Nil = 0,
|
||||||
|
DN_HeapAllocFlag_MemDebuggerCanLeakPtr = 1 << 0,
|
||||||
|
DN_HeapAllocFlag_MemDebuggerExcludePtr = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef DN_U32 DN_HeapFlags;
|
||||||
|
enum DN_HeapFlags_ {
|
||||||
|
DN_HeapFlags_Nil = 0,
|
||||||
|
DN_HeapFlags_ExcludeFromMemDebugger = 1 << 0,
|
||||||
|
DN_HeapFlags_MemDebuggerCanLeakPtr = 1 << 1,
|
||||||
|
};
|
||||||
|
|
||||||
typedef void *(DN_HeapBasicAllocFunc) (DN_USize count);
|
typedef void *(DN_HeapBasicAllocFunc) (DN_USize count);
|
||||||
typedef void (DN_HeapBasicDeallocFunc)(void *ptr);
|
typedef void (DN_HeapBasicDeallocFunc)(void *ptr);
|
||||||
|
|
||||||
typedef void *(DN_HeapVirtualReserveFunc)(DN_USize count, DN_MemCommit commit, DN_MemPage page_flags);
|
typedef void *(DN_HeapVirtualReserveFunc)(DN_USize count, DN_MemCommit commit, DN_MemPage page_flags);
|
||||||
typedef bool (DN_HeapVirtualCommitFunc)(void *ptr, DN_USize count, DN_U32 page_flags);
|
typedef bool (DN_HeapVirtualCommitFunc)(void *ptr, DN_USize count, DN_U32 page_flags);
|
||||||
typedef void (DN_HeapVirtualReleaseFunc)(void *ptr, DN_USize count);
|
typedef void (DN_HeapVirtualReleaseFunc)(void *ptr, DN_USize count);
|
||||||
|
|
||||||
typedef struct DN_Heap DN_Heap;
|
typedef struct DN_Heap DN_Heap;
|
||||||
struct DN_Heap
|
struct DN_Heap
|
||||||
{
|
{
|
||||||
|
DN_HeapFlags flags;
|
||||||
DN_HeapType type;
|
DN_HeapType type;
|
||||||
DN_USize bytes_alloc_total;
|
DN_USize bytes_alloc_total;
|
||||||
DN_USize bytes_alloc;
|
DN_USize bytes_alloc;
|
||||||
@@ -1220,8 +1252,6 @@ enum DN_MemFlags_
|
|||||||
DN_MemFlags_Nil = 0,
|
DN_MemFlags_Nil = 0,
|
||||||
DN_MemFlags_NoGrow = 1 << 0,
|
DN_MemFlags_NoGrow = 1 << 0,
|
||||||
DN_MemFlags_NoPoison = 1 << 1,
|
DN_MemFlags_NoPoison = 1 << 1,
|
||||||
DN_MemFlags_NoAllocTrack = 1 << 2,
|
|
||||||
DN_MemFlags_AllocCanLeak = 1 << 3,
|
|
||||||
DN_MemFlags_SimAlloc = 1 << 4,
|
DN_MemFlags_SimAlloc = 1 << 4,
|
||||||
|
|
||||||
// NOTE: Records stack traces of temp memory regions on construction to provide more diagnostics
|
// NOTE: Records stack traces of temp memory regions on construction to provide more diagnostics
|
||||||
@@ -1251,12 +1281,16 @@ enum DN_MemFlags_
|
|||||||
typedef struct DN_MemList DN_MemList;
|
typedef struct DN_MemList DN_MemList;
|
||||||
struct DN_MemList
|
struct DN_MemList
|
||||||
{
|
{
|
||||||
DN_MemBlock* curr;
|
DN_MemBlock* curr; // Contiguous blocks of memory, chained for growth, parcelled for object allocation
|
||||||
DN_MemFlags flags;
|
DN_MemFlags flags;
|
||||||
DN_Heap heap;
|
DN_Heap heap; // Backing allocator for the memory blocks
|
||||||
DN_MemStats stats;
|
DN_MemStats stats;
|
||||||
DN_Str8 label;
|
DN_Str8 label;
|
||||||
|
|
||||||
|
#if DN_MEM_DEBUGGER
|
||||||
|
DN_USize mem_debugger_id;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if DN_ARENA_TEMP_MEM_UAF_GUARD
|
#if DN_ARENA_TEMP_MEM_UAF_GUARD
|
||||||
DN_U32 uaf_guard_next_id;
|
DN_U32 uaf_guard_next_id;
|
||||||
DN_U32 uaf_guard_active_id;
|
DN_U32 uaf_guard_active_id;
|
||||||
@@ -1387,7 +1421,8 @@ struct DN_Utf32FromIterator
|
|||||||
bool init;
|
bool init;
|
||||||
bool success;
|
bool success;
|
||||||
DN_Str8 remaining;
|
DN_Str8 remaining;
|
||||||
DN_USize bytes_decoded;
|
DN_USize bytes_decoded_;
|
||||||
|
DN_USize bytes_decoded_total;
|
||||||
DN_USize codepoint_index;
|
DN_USize codepoint_index;
|
||||||
DN_U32 codepoint;
|
DN_U32 codepoint;
|
||||||
};
|
};
|
||||||
@@ -1635,6 +1670,97 @@ struct DN_Profiler
|
|||||||
DN_F64 frame_avg_tsc;
|
DN_F64 frame_avg_tsc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DN_Profiler2Marker
|
||||||
|
{
|
||||||
|
DN_Str8 name;
|
||||||
|
DN_U64 tsc_begin;
|
||||||
|
DN_U64 tsc_end;
|
||||||
|
DN_U64 tsc_children_duration;
|
||||||
|
DN_CallSite call_site;
|
||||||
|
DN_U32 parent_index;
|
||||||
|
DN_U32 next_index;
|
||||||
|
DN_U32 first_child_index;
|
||||||
|
DN_U32 last_child_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DN_Profiler2Frame
|
||||||
|
{
|
||||||
|
// NOTE: The frame number that this frame was part of. Frame number is incremented each time
|
||||||
|
// frame-begin is called.
|
||||||
|
DN_U32 frame_num;
|
||||||
|
|
||||||
|
// NOTE: The markers array is not contiguous. We using a ring-buffer so accessing the marker must
|
||||||
|
// be done like `profiler->markers + ((frame->begin_offset + i) % profiler->markers_max)`. A
|
||||||
|
// helper function is available `DN_Profiler2MarkerFromFrameIndex(profiler, frame, i)`
|
||||||
|
DN_U32 begin_offset;
|
||||||
|
DN_U32 count;
|
||||||
|
DN_U32 max;
|
||||||
|
|
||||||
|
// NOTE: The profiling marker that the profiler makes and closes when frame-begin is called.
|
||||||
|
// Encapsulates essentially the duration of 1 update loop in an interactive application.
|
||||||
|
DN_Profiler2Marker* begin_marker;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DN_Profiler2Zone
|
||||||
|
{
|
||||||
|
struct DN_Profiler2* profiler;
|
||||||
|
DN_Profiler2Marker* marker;
|
||||||
|
bool ended;
|
||||||
|
bool scope_once;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DN_Profiler2State
|
||||||
|
{
|
||||||
|
DN_Profiler2State_Run,
|
||||||
|
DN_Profiler2State_Paused,
|
||||||
|
DN_Profiler2State_UnpauseEnqueued,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DN_Profiler2
|
||||||
|
{
|
||||||
|
DN_Profiler2State state;
|
||||||
|
DN_U32 frame_num;
|
||||||
|
DN_ProfilerTscNowFunc* tsc_now;
|
||||||
|
DN_U64 tsc_frequency;
|
||||||
|
|
||||||
|
DN_Profiler2Frame* frames;
|
||||||
|
DN_U32 frames_max;
|
||||||
|
DN_U32 frames_write_index_unwrapped;
|
||||||
|
|
||||||
|
DN_Profiler2Marker* markers;
|
||||||
|
DN_U32 markers_max;
|
||||||
|
|
||||||
|
DN_Profiler2Frame* active_frame;
|
||||||
|
DN_U32 active_parent_index;
|
||||||
|
|
||||||
|
struct DN_Profiler2Zone frame_begin_zone;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DN_Profiler2Iterator
|
||||||
|
{
|
||||||
|
bool init;
|
||||||
|
DN_USize iteration_count;
|
||||||
|
DN_U32 marker_index;
|
||||||
|
DN_U32 last_visited_index;
|
||||||
|
DN_Profiler2Marker* marker;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DN_Profiler2FunctionTime
|
||||||
|
{
|
||||||
|
DN_CallSite call_site;
|
||||||
|
DN_Str8 name;
|
||||||
|
DN_USize hit_count;
|
||||||
|
DN_U64 tsc_total;
|
||||||
|
DN_U64 tsc_children_total;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DN_Profiler2FunctionTimes
|
||||||
|
{
|
||||||
|
DN_Profiler2FunctionTime *data;
|
||||||
|
DN_USize count;
|
||||||
|
DN_USize max;
|
||||||
|
};
|
||||||
|
|
||||||
typedef bool (DN_QSortCompareFunc) (void const *lhs, void const *rhs, void *user_context);
|
typedef bool (DN_QSortCompareFunc) (void const *lhs, void const *rhs, void *user_context);
|
||||||
typedef bool (DN_BSearchLessThanFunc)(void const *lhs, void const *rhs, void *user_context);
|
typedef bool (DN_BSearchLessThanFunc)(void const *lhs, void const *rhs, void *user_context);
|
||||||
enum DN_BSearchType
|
enum DN_BSearchType
|
||||||
@@ -1761,8 +1887,13 @@ typedef enum DN_TcDeinitArenas {
|
|||||||
typedef struct DN_Pcg32 DN_Pcg32;
|
typedef struct DN_Pcg32 DN_Pcg32;
|
||||||
struct DN_Pcg32 { DN_U64 state; };
|
struct DN_Pcg32 { DN_U64 state; };
|
||||||
|
|
||||||
typedef struct DN_Murmur3 DN_Murmur3;
|
typedef struct DN_Murmur3Context DN_Murmur3Context;
|
||||||
struct DN_Murmur3 { DN_U64 e[2]; };
|
struct DN_Murmur3Context
|
||||||
|
{
|
||||||
|
DN_U32 it;
|
||||||
|
DN_U32 carry;
|
||||||
|
DN_U32 bytes_count;
|
||||||
|
};
|
||||||
|
|
||||||
typedef enum DN_LogType {
|
typedef enum DN_LogType {
|
||||||
DN_LogType_Debug,
|
DN_LogType_Debug,
|
||||||
@@ -1941,18 +2072,11 @@ typedef enum DN_RectCutClip {
|
|||||||
DN_RectCutClip_Yes,
|
DN_RectCutClip_Yes,
|
||||||
} DN_RectCutClip;
|
} DN_RectCutClip;
|
||||||
|
|
||||||
typedef enum DN_RectCutSide {
|
|
||||||
DN_RectCutSide_Left,
|
|
||||||
DN_RectCutSide_Right,
|
|
||||||
DN_RectCutSide_Top,
|
|
||||||
DN_RectCutSide_Bottom,
|
|
||||||
} DN_RectCutSide;
|
|
||||||
|
|
||||||
typedef struct DN_RectCut DN_RectCut;
|
typedef struct DN_RectCut DN_RectCut;
|
||||||
struct DN_RectCut
|
struct DN_RectCut
|
||||||
{
|
{
|
||||||
DN_Rect* rect;
|
DN_Rect* rect;
|
||||||
DN_RectCutSide side;
|
DN_Side side;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct DN_RaycastV2 DN_RaycastV2;
|
typedef struct DN_RaycastV2 DN_RaycastV2;
|
||||||
@@ -2110,39 +2234,56 @@ enum DN_HTableAllowTombstone
|
|||||||
DN_HTableAllowTombstone_Yes,
|
DN_HTableAllowTombstone_Yes,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DN_LeakAllocFlag
|
enum DN_MemDebuggerPtrFlag
|
||||||
{
|
{
|
||||||
DN_LeakAllocFlag_Freed = 1 << 0,
|
DN_MemDebuggerPtrFlag_Freed = 1 << 0,
|
||||||
DN_LeakAllocFlag_LeakPermitted = 1 << 1,
|
DN_MemDebuggerPtrFlag_LeakPermitted = 1 << 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct DN_LeakAlloc DN_LeakAlloc;
|
typedef struct DN_MemDebuggerPtrData DN_MemDebuggerPtrData;
|
||||||
struct DN_LeakAlloc
|
struct DN_MemDebuggerPtrData
|
||||||
{
|
{
|
||||||
void *ptr; // 8 Pointer to the allocation being tracked
|
DN_CallSite call_site;
|
||||||
DN_USize size; // 16 Size of the allocation
|
DN_U16 flags; // Bit flags from `DN_MemDebuggerPtrFlag`
|
||||||
DN_USize freed_size; // 24 Store the size of the allocation when it is freed
|
void* ptr; // Pointer to the allocation being tracked
|
||||||
DN_Str8 stack_trace; // 40 Stack trace at the point of allocation
|
DN_USize size; // Size of the allocation
|
||||||
DN_Str8 freed_stack_trace; // 56 Stack trace of where the allocation was freed
|
DN_USize freed_size; // Store the size of the allocation when it is freed
|
||||||
DN_U16 flags; // 72 Bit flags from `DN_LeakAllocFlag`
|
DN_Str8 stack_trace; // Stack trace at the point of allocation
|
||||||
|
DN_Str8 freed_stack_trace; // Stack trace of where the allocation was freed
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: We aim to keep the allocation record as light as possible as memory tracking can get
|
typedef struct DN_MemDebuggerKV DN_MemDebuggerKV;
|
||||||
// expensive. Enforce that there is no unexpected padding.
|
struct DN_MemDebuggerKV
|
||||||
DN_StaticAssert(sizeof(DN_LeakAlloc) == 64 || sizeof(DN_LeakAlloc) == 32); // NOTE: 64 bit vs 32 bit pointers respectively
|
|
||||||
|
|
||||||
typedef struct DN_LeakTrackerKV DN_LeakTrackerKV;
|
|
||||||
struct DN_LeakTrackerKV
|
|
||||||
{
|
{
|
||||||
DN_HTableHashType hash;
|
DN_HTableHashType hash;
|
||||||
DN_UPtr key;
|
DN_UPtr key;
|
||||||
DN_LeakAlloc value;
|
DN_MemDebuggerPtrData value;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct DN_LeakTracker DN_LeakTracker;
|
typedef struct DN_MemDebuggerSnapshotPtrData DN_MemDebuggerSnapshotPtrData;
|
||||||
struct DN_LeakTracker
|
struct DN_MemDebuggerSnapshotPtrData
|
||||||
{
|
{
|
||||||
DN_LeakTrackerKV *alloc_table_kvs;
|
void* ptr;
|
||||||
|
DN_USize size;
|
||||||
|
DN_U16 flags;
|
||||||
|
DN_CallSite call_site;
|
||||||
|
DN_Str8 stack_trace;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct DN_MemDebuggerSnapshot DN_MemDebuggerSnapshot;
|
||||||
|
struct DN_MemDebuggerSnapshot
|
||||||
|
{
|
||||||
|
DN_MemDebuggerSnapshotPtrData *data;
|
||||||
|
DN_USize count;
|
||||||
|
DN_U64 active_bytes;
|
||||||
|
DN_U64 freed_count;
|
||||||
|
DN_U64 freed_bytes;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct DN_MemDebugger DN_MemDebugger;
|
||||||
|
struct DN_MemDebugger
|
||||||
|
{
|
||||||
|
DN_MemDebuggerKV *alloc_table_kvs;
|
||||||
DN_HTable alloc_table;
|
DN_HTable alloc_table;
|
||||||
DN_TicketMutex alloc_table_mutex;
|
DN_TicketMutex alloc_table_mutex;
|
||||||
DN_U64 alloc_table_bytes_allocated_for_stack_traces;
|
DN_U64 alloc_table_bytes_allocated_for_stack_traces;
|
||||||
@@ -2156,7 +2297,6 @@ enum DN_InitFlags_
|
|||||||
// NOTE: Query the OS for information and enable functionality that requires the OS (like virtual
|
// NOTE: Query the OS for information and enable functionality that requires the OS (like virtual
|
||||||
// memory APIs, mutexes, secure RNG) as well as per-thread persistent and scratch allocators.
|
// memory APIs, mutexes, secure RNG) as well as per-thread persistent and scratch allocators.
|
||||||
DN_InitFlags_OS = (1 << 0),
|
DN_InitFlags_OS = (1 << 0),
|
||||||
DN_InitFlags_LeakTracker = (1 << 1) | DN_InitFlags_OS,
|
|
||||||
DN_InitFlags_LogLibFeatures = (1 << 2),
|
DN_InitFlags_LogLibFeatures = (1 << 2),
|
||||||
DN_InitFlags_LogCPUFeatures = (1 << 3) | DN_InitFlags_OS,
|
DN_InitFlags_LogCPUFeatures = (1 << 3) | DN_InitFlags_OS,
|
||||||
DN_InitFlags_LogAllFeatures = DN_InitFlags_LogLibFeatures | DN_InitFlags_LogCPUFeatures,
|
DN_InitFlags_LogAllFeatures = DN_InitFlags_LogLibFeatures | DN_InitFlags_LogCPUFeatures,
|
||||||
@@ -2653,7 +2793,8 @@ struct DN_Core
|
|||||||
DN_InitFlags init_flags;
|
DN_InitFlags init_flags;
|
||||||
DN_TcCore main_tc;
|
DN_TcCore main_tc;
|
||||||
DN_USize mem_allocs_frame;
|
DN_USize mem_allocs_frame;
|
||||||
DN_LeakTracker leak;
|
DN_MemDebugger mem_debugger;
|
||||||
|
DN_USize mem_debugger_mem_list_id_counter;
|
||||||
|
|
||||||
DN_LogType log_level_to_show_from;
|
DN_LogType log_level_to_show_from;
|
||||||
DN_LogPrintFunc* print_func;
|
DN_LogPrintFunc* print_func;
|
||||||
@@ -2850,14 +2991,17 @@ DN_API DN_MemStats DN_MemStatsSumArray
|
|||||||
|
|
||||||
// API
|
// API
|
||||||
// DN_HeapAlloc
|
// DN_HeapAlloc
|
||||||
// DN_HeapDealloc
|
// Allocate memory using the given heap's configured allocation functions. For a heap using the
|
||||||
// Allocate and deallocate memory. Note that `DN_HeapAlloc` takes reserve and commit even for
|
// basic allocation routines, `commit` is ignored, `reserve` is the amount of bytes to be
|
||||||
// the basic allocator. In the basic allocator which does not have a concept of reserving and
|
// allocated and implicitly committed. For virtual memory then `reserve` is the amount of
|
||||||
// committing, the `commit` value is ignored and the `reserve` amount is the amount that will be
|
// address space to reserve for the application from the OS. `commit` is the amount of memory in
|
||||||
// allocated.
|
// pages that the OS will give your application.
|
||||||
|
|
||||||
|
#define DN_MemMetadataInit(name_cstr) DN_Literal(DN_MemMetadata){DN_CallSiteNow, DN_Str8Lit(name_cstr)}
|
||||||
DN_API DN_Heap DN_HeapInitBasic (DN_HeapBasicAllocFunc *basic_alloc, DN_HeapBasicDeallocFunc *basic_dealloc);
|
DN_API DN_Heap DN_HeapInitBasic (DN_HeapBasicAllocFunc *basic_alloc, DN_HeapBasicDeallocFunc *basic_dealloc);
|
||||||
DN_API DN_Heap DN_HeapInitVirtual (DN_U32 page_size, DN_HeapVirtualReserveFunc *virtual_reserve, DN_HeapVirtualCommitFunc *virtual_commit, DN_HeapVirtualReleaseFunc *virtual_release);
|
DN_API DN_Heap DN_HeapInitVirtual (DN_U32 page_size, DN_HeapVirtualReserveFunc *virtual_reserve, DN_HeapVirtualCommitFunc *virtual_commit, DN_HeapVirtualReleaseFunc *virtual_release);
|
||||||
DN_API void* DN_HeapAlloc (DN_Heap *heap, DN_USize reserve, DN_USize commit);
|
DN_API void* DN_HeapAllocCallSite (DN_Heap *heap, DN_USize reserve, DN_USize commit, DN_HeapAllocFlag flags, DN_CallSite call_site);
|
||||||
|
#define DN_HeapAlloc(heap, reserve, commit, flags, name_cstr) DN_HeapAllocMetadata(heap, reserve, commit, flags, DN_MemMetadataInit(name_cstr));
|
||||||
DN_API void DN_HeapDealloc (DN_Heap *heap, void *ptr, DN_USize size);
|
DN_API void DN_HeapDealloc (DN_Heap *heap, void *ptr, DN_USize size);
|
||||||
|
|
||||||
// NOTE: MemList
|
// NOTE: MemList
|
||||||
@@ -2870,7 +3014,8 @@ DN_API void DN_HeapDealloc
|
|||||||
// In general for 99% of use-cases you want an `Arena` and if some API is not exposed on the
|
// In general for 99% of use-cases you want an `Arena` and if some API is not exposed on the
|
||||||
// `Arena` to then use the `MemList` API on the embedded `mem_list` backing the Arena.
|
// `Arena` to then use the `MemList` API on the embedded `mem_list` backing the Arena.
|
||||||
DN_API DN_MemList DN_MemListFromBuffer (void *buffer, DN_USize size, DN_MemFlags flags);
|
DN_API DN_MemList DN_MemListFromBuffer (void *buffer, DN_USize size, DN_MemFlags flags);
|
||||||
DN_API DN_MemList DN_MemListFromHeap (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags, DN_Heap heap);
|
DN_API DN_MemList DN_MemListFromHeapCallSite (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags, DN_Heap heap, DN_CallSite call_site);
|
||||||
|
#define DN_MemListFromHeap(reserve, commit, flags, heap, name_cstr) DN_MemListFromHeapCallSite(reserve, commit, flags, heap, DN_CallSiteNowNamed(name_cstr))
|
||||||
DN_API void DN_MemListDeinit (DN_MemList *mem);
|
DN_API void DN_MemListDeinit (DN_MemList *mem);
|
||||||
DN_API bool DN_MemListCommit (DN_MemList *mem, DN_U64 size);
|
DN_API bool DN_MemListCommit (DN_MemList *mem, DN_U64 size);
|
||||||
DN_API bool DN_MemListCommitTo (DN_MemList *mem, DN_U64 pos);
|
DN_API bool DN_MemListCommitTo (DN_MemList *mem, DN_U64 pos);
|
||||||
@@ -2941,7 +3086,8 @@ DN_API void DN_MemListTempEnd
|
|||||||
DN_ArenaDeinit(&arena); // Frees the memory
|
DN_ArenaDeinit(&arena); // Frees the memory
|
||||||
*/
|
*/
|
||||||
DN_API DN_Arena DN_ArenaFromMemList (DN_MemList *mem);
|
DN_API DN_Arena DN_ArenaFromMemList (DN_MemList *mem);
|
||||||
DN_API DN_Arena DN_ArenaFromHeap (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags, DN_Heap heap);
|
DN_API DN_Arena DN_ArenaFromHeapCallSite (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags, DN_Heap heap, DN_CallSite call_site);
|
||||||
|
#define DN_ArenaFromHeap(reserve, commit, flags, heap, name_cstr) DN_ArenaFromHeapCallSite(reserve, commit, flags, heap, DN_CallSiteNowNamed(name_cstr))
|
||||||
DN_API DN_Arena DN_ArenaTempBeginFromMemList (DN_MemList *mem);
|
DN_API DN_Arena DN_ArenaTempBeginFromMemList (DN_MemList *mem);
|
||||||
DN_API DN_Arena DN_ArenaTempBeginFromArena (DN_Arena *arena);
|
DN_API DN_Arena DN_ArenaTempBeginFromArena (DN_Arena *arena);
|
||||||
DN_API void DN_ArenaTempEnd (DN_Arena *arena, DN_ArenaReset reset);
|
DN_API void DN_ArenaTempEnd (DN_Arena *arena, DN_ArenaReset reset);
|
||||||
@@ -3055,6 +3201,12 @@ DN_API DN_Allocator DN_AllocatorFromMemList
|
|||||||
DN_API DN_Allocator DN_AllocatorFromArena (DN_Arena *arena);
|
DN_API DN_Allocator DN_AllocatorFromArena (DN_Arena *arena);
|
||||||
DN_API DN_Allocator DN_AllocatorFromPool (DN_Pool *pool);
|
DN_API DN_Allocator DN_AllocatorFromPool (DN_Pool *pool);
|
||||||
DN_API void* DN_AllocatorAlloc (DN_Allocator allocator, DN_USize count, DN_U8 align, DN_ZMem z_mem);
|
DN_API void* DN_AllocatorAlloc (DN_Allocator allocator, DN_USize count, DN_U8 align, DN_ZMem z_mem);
|
||||||
|
#define DN_AllocatorNew(allocator, T, zmem) (T *)DN_AllocatorAlloc(allocator, sizeof(T), alignof(T), zmem)
|
||||||
|
#define DN_AllocatorNewZ(allocator, T) (T *)DN_AllocatorAlloc(allocator, sizeof(T), alignof(T), DN_ZMem_Yes)
|
||||||
|
#define DN_AllocatorNewNoZ(allocator, T) (T *)DN_AllocatorAlloc(allocator, sizeof(T), alignof(T), DN_ZMem_No)
|
||||||
|
#define DN_AllocatorNewArray(allocator, T, count, zmem) (T *)DN_AllocatorAlloc(allocator, sizeof(T) * (count), alignof(T), zmem)
|
||||||
|
#define DN_AllocatorNewArrayZ(allocator, T, count) (T *)DN_AllocatorAlloc(allocator, sizeof(T) * (count), alignof(T), DN_ZMem_Yes)
|
||||||
|
#define DN_AllocatorNewArrayNoZ(allocator, T, count) (T *)DN_AllocatorAlloc(allocator, sizeof(T) * (count), alignof(T), DN_ZMem_No)
|
||||||
|
|
||||||
DN_API DN_USize DN_FmtVCount (DN_FMT_ATTRIB char const *fmt, va_list args);
|
DN_API DN_USize DN_FmtVCount (DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||||
DN_API DN_USize DN_FmtCount (DN_FMT_ATTRIB char const *fmt, ...);
|
DN_API DN_USize DN_FmtCount (DN_FMT_ATTRIB char const *fmt, ...);
|
||||||
@@ -3361,6 +3513,17 @@ DN_API void DN_ProfilerFmtToStdout
|
|||||||
DN_API DN_F64 DN_ProfilerSecFromTsc (DN_Profiler *profiler, DN_U64 duration_tsc);
|
DN_API DN_F64 DN_ProfilerSecFromTsc (DN_Profiler *profiler, DN_U64 duration_tsc);
|
||||||
DN_API DN_F64 DN_ProfilerMsFromTsc (DN_Profiler *profiler, DN_U64 duration_tsc);
|
DN_API DN_F64 DN_ProfilerMsFromTsc (DN_Profiler *profiler, DN_U64 duration_tsc);
|
||||||
|
|
||||||
|
DN_API DN_Profiler2 DN_Profiler2Init (DN_ProfilerTscNowFunc *tsc_now_func, DN_U64 tsc_frequency, DN_Profiler2Marker *markers, DN_U32 markers_count, DN_Profiler2Frame *frames, DN_U32 frames_count);
|
||||||
|
DN_API void DN_Profiler2FrameBegin (DN_Profiler2 *profiler);
|
||||||
|
DN_API DN_Profiler2Zone DN_Profiler2ZoneBegin (DN_Profiler2 *profiler, DN_Str8 name, DN_CallSite call_site);
|
||||||
|
DN_API void DN_Profiler2ZoneEnd (DN_Profiler2Zone *zone);
|
||||||
|
#define DN_Profiler2ZoneBeginName(profiler, name_cstr) DN_Profiler2ZoneBegin(profiler, DN_Str8Lit(name_cstr), DN_CallSiteNow)
|
||||||
|
#define DN_Profiler2ZoneBeginUnnamed(profiler) DN_Profiler2ZoneBegin(profiler, DN_Str8Lit(""), DN_CallSiteNow)
|
||||||
|
#define DN_Profiler2ZoneScopeName(profiler, name_cstr) DN_Profiler2Zone DN_UniqueName(zone) = DN_Profiler2ZoneBeginName(profiler, name_cstr); !DN_UniqueName(zone).scope_once; DN_Profiler2ZoneEnd(DN_UniqueName(&zone))
|
||||||
|
DN_API bool DN_Profiler2MarkerWalkDfsPreOrder (DN_Profiler2 *profiler, DN_Profiler2Iterator *it);
|
||||||
|
DN_API DN_V2USize DN_Profiler2MarkerOffsetFromFrame (DN_Profiler2 const *profiler, DN_Profiler2Frame const *frame);
|
||||||
|
DN_API DN_Profiler2Marker* DN_Profiler2MarkerFromFrameIndex (DN_Profiler2 *profiler, DN_Profiler2Frame *frame, DN_U32 index);
|
||||||
|
|
||||||
DN_API void DN_QSort_ (void *array, DN_USize array_size, DN_USize elem_size, void *user_context, DN_QSortCompareFunc *compare);
|
DN_API void DN_QSort_ (void *array, DN_USize array_size, DN_USize elem_size, void *user_context, DN_QSortCompareFunc *compare);
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
template <typename T> void DN_QSortT (T *array, DN_USize array_size, void *user_context, DN_QSortCompareFunc *compare);
|
template <typename T> void DN_QSortT (T *array, DN_USize array_size, void *user_context, DN_QSortCompareFunc *compare);
|
||||||
@@ -3408,16 +3571,12 @@ DN_API void DN_Pcg32Advance
|
|||||||
DN_API DN_U32 DN_Fnv1aHashU32FromBytes (void const *bytes, DN_USize count, DN_U32 seed);
|
DN_API DN_U32 DN_Fnv1aHashU32FromBytes (void const *bytes, DN_USize count, DN_U32 seed);
|
||||||
DN_API DN_U64 DN_Fnv1aHashU64FromBytes (void const *bytes, DN_USize count, DN_U64 seed);
|
DN_API DN_U64 DN_Fnv1aHashU64FromBytes (void const *bytes, DN_USize count, DN_U64 seed);
|
||||||
|
|
||||||
DN_API DN_U32 DN_Murmur3HashU32FromBytesX86 (void const *bytes, int len, DN_U32 seed);
|
DN_API void DN_Murmur3HashRawProcess (DN_U32 *ph1, DN_U32 *pcarry, const void *key, int len);
|
||||||
DN_API DN_Murmur3 DN_Murmur3HashU128FromBytesX64 (void const *bytes, int len, DN_U32 seed);
|
DN_API DN_U32 DN_Murmur3HashRawResult (DN_U32 h1, DN_U32 carry, DN_U32 total_length);
|
||||||
DN_API DN_U64 DN_Murmur3HashU64FromBytesX64 (void const *bytes, int len, DN_U32 seed);
|
DN_API DN_U32 DN_Murmur3Hash (DN_U32 seed, const void *key, int len);
|
||||||
DN_API DN_U32 DN_Murmur3HashU32FromBytesX64 (void const *bytes, int len, DN_U32 seed);
|
DN_API DN_Murmur3Context DN_Murmur3HashInit (DN_U32 seed);
|
||||||
|
DN_API void DN_Murmur3HashUpdate (DN_Murmur3Context *ctx, const void *key, int len);
|
||||||
#if defined(DN_64_BIT)
|
DN_API DN_U32 DN_Murmur3HashFinish (DN_Murmur3Context const *ctx);
|
||||||
#define DN_Murmur3HashU32FromBytes(bytes, len, seed) DN_Murmur3HashU32FromBytesX64(bytes, len, seed)
|
|
||||||
#else
|
|
||||||
#define DN_Murmur3HashU32FromBytes(bytes, len, seed) DN_Murmur3HashU32FromBytesX86(bytes, len, seed)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DN_AnsiCodeBoldLit "\x1b[1m"
|
#define DN_AnsiCodeBoldLit "\x1b[1m"
|
||||||
#define DN_AnsiCodeResetLit "\x1b[0m"
|
#define DN_AnsiCodeResetLit "\x1b[0m"
|
||||||
@@ -3668,17 +3827,17 @@ DN_API DN_V3F32 DN_V3F32Normalise
|
|||||||
|
|
||||||
#define DN_V4F32From1N(x) DN_Literal(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}}
|
#define DN_V4F32From1N(x) DN_Literal(DN_V4F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}}
|
||||||
#define DN_V4F32From4N(x, y, z, w) DN_Literal(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}}
|
#define DN_V4F32From4N(x, y, z, w) DN_Literal(DN_V4F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z), (DN_F32)(w)}}
|
||||||
#define DN_V4F32FromV3And1N(xyz, w) DN_Literal(DN_V4F32){{xyz.x, xyz.y, xyz.z, w}}
|
#define DN_V4F32FromV3And1N(xyz, w) DN_Literal(DN_V4F32){{(xyz).x, (xyz).y, (xyz).z, (w)}}
|
||||||
#define DN_V4F32Rgba01FromRgbaU8(r, g, b, a) DN_Literal(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, a / 255.f}}
|
#define DN_V4F32FromRgba255ToRgba01(r, g, b, a) DN_Literal(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, a / 255.f}}
|
||||||
#define DN_V4F32Rgba01FromRgbU8(r, g, b) DN_Literal(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, 1.f}}
|
#define DN_V4F32FromRgb255ToRgba01(r, g, b) DN_Literal(DN_V4F32){{r / 255.f, g / 255.f, b / 255.f, 1.f}}
|
||||||
|
|
||||||
DN_API DN_V4F32 DN_V4F32Lerp (DN_V4F32 lhs, DN_F32 t01, DN_V4F32 rhs);
|
DN_API DN_V4F32 DN_V4F32Lerp (DN_V4F32 lhs, DN_F32 t01, DN_V4F32 rhs);
|
||||||
DN_API bool DN_V4F32Rgba01IsValid (DN_V4F32 rgba01);
|
DN_API bool DN_V4F32Rgba01IsValid (DN_V4F32 rgba01);
|
||||||
DN_API DN_V4F32 DN_V4F32Rgba01FromRgbU32 (DN_U32 u32);
|
DN_API DN_V4F32 DN_V4F32FromRgbU32ToRgba01 (DN_U32 u32);
|
||||||
DN_API DN_V4F32 DN_V4F32Rgba01FromRgbaU32 (DN_U32 u32);
|
DN_API DN_V4F32 DN_V4F32FromRgbaU32ToRgba01 (DN_U32 u32);
|
||||||
DN_API DN_V4F32 DN_V4F32Linear01FromSrgb01 (DN_V4F32 rgb01);
|
DN_API DN_V4F32 DN_V4F32FromSrgb01ToLinear01 (DN_V4F32 rgb01);
|
||||||
DN_API DN_V4F32 DN_V4F32Linear01Desaturate (DN_V4F32 linear01, DN_F32 t01);
|
DN_API DN_V4F32 DN_V4F32Linear01Desaturate (DN_V4F32 linear01, DN_F32 t01);
|
||||||
DN_API DN_V4F32 DN_V4F32Srgb01FromLinear01 (DN_V4F32 linear01);
|
DN_API DN_V4F32 DN_V4F32FromLinear01ToSrgb01 (DN_V4F32 linear01);
|
||||||
|
|
||||||
#define DN_V4F32FromV4Alpha(v4, alpha) DN_V4F32FromV3And1N(v4.xyz, alpha)
|
#define DN_V4F32FromV4Alpha(v4, alpha) DN_V4F32FromV3And1N(v4.xyz, alpha)
|
||||||
|
|
||||||
@@ -3723,6 +3882,7 @@ DN_API DN_Str8x256 DN_M4ColumnMajorString
|
|||||||
DN_API bool DN_M2x3Eq (DN_M2x3 const *lhs, DN_M2x3 const *rhs);
|
DN_API bool DN_M2x3Eq (DN_M2x3 const *lhs, DN_M2x3 const *rhs);
|
||||||
DN_API bool DN_M2x3NotEq (DN_M2x3 const *lhs, DN_M2x3 const *rhs);
|
DN_API bool DN_M2x3NotEq (DN_M2x3 const *lhs, DN_M2x3 const *rhs);
|
||||||
DN_API DN_M2x3 DN_M2x3Identity ();
|
DN_API DN_M2x3 DN_M2x3Identity ();
|
||||||
|
DN_API bool DN_M2x3IsIdentity (DN_M2x3 m2x3);
|
||||||
DN_API DN_M2x3 DN_M2x3Translate (DN_V2F32 offset);
|
DN_API DN_M2x3 DN_M2x3Translate (DN_V2F32 offset);
|
||||||
DN_API DN_V2F32 DN_M2x3ScaleGet (DN_M2x3 m2x3);
|
DN_API DN_V2F32 DN_M2x3ScaleGet (DN_M2x3 m2x3);
|
||||||
DN_API DN_M2x3 DN_M2x3Scale (DN_V2F32 scale);
|
DN_API DN_M2x3 DN_M2x3Scale (DN_V2F32 scale);
|
||||||
@@ -3778,50 +3938,175 @@ DN_API DN_Rect DN_RectCutCut
|
|||||||
|
|
||||||
DN_API DN_RaycastV2 DN_RaycastLineIntersectV2 (DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b);
|
DN_API DN_RaycastV2 DN_RaycastLineIntersectV2 (DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b);
|
||||||
|
|
||||||
// NOTE: Containers that are imlpemented using primarily macros for operating on data structures
|
// NOTE: Containers that are implemented using primarily macros for operating on data structures
|
||||||
// that are embedded into a C style struct or from a set of defined variables from the available
|
// that are embedded into a C style struct or from a set of defined variables from the available
|
||||||
// scope. Keep it stupid simple, structs and functions. Minimal amount of container types with
|
// scope. Keep it stupid simple, structs and functions. Minimal amount of container types with
|
||||||
// flexible construction leads to less duplicated container code and less template meta-programming.
|
// flexible construction leads to less duplicated container code and less template meta-programming.
|
||||||
|
|
||||||
// NOTE: Intrusive Singly Linked List
|
// NOTE: Lists (Linked, Queue, Stack)
|
||||||
// Define a struct with the members `next`:
|
|
||||||
//
|
//
|
||||||
// struct MyLinkItem {
|
// 1. Fully double-linked with first and last pointers (linked list)
|
||||||
// int data;
|
// 2. Singly linked with first and last pointers from the list head (queue list)
|
||||||
// MyLinkItem *next;
|
// 3. Singly linked with just a single first pointer from the header (stack list)
|
||||||
// } my_link = {};
|
|
||||||
//
|
|
||||||
// MyLinkItem *first_item = DN_ISinglyLLDetach(&my_link, MyLinkItem);
|
|
||||||
#define DN_ISinglyLLDetach(list) (decltype(list))DN_SinglyLLDetach((void **)&(list), (void **)&(list)->next)
|
|
||||||
|
|
||||||
// NOTE: Singly Linked List with Head and Tail pointer
|
#if defined(NDEBUG)
|
||||||
/*
|
#define DN_ListDebugVerifyListContainsPtr(Type, first_ptr, field_for_next, check_ptr)
|
||||||
struct MyLinkItem {
|
#else
|
||||||
int data;
|
#define DN_ListDebugVerifyListContainsPtr(Type, first_ptr, field_for_next, check_ptr) \
|
||||||
MyLinkItem *next;
|
bool DN_UniqueName(dbg_verify_pointer_in_list) = false; \
|
||||||
} my_list = {};
|
for (Type *dbg_it_ = first_ptr; dbg_it_; dbg_it_ = dbg_it_->field_for_next) { \
|
||||||
|
if (dbg_it_ == check_ptr) { \
|
||||||
|
DN_UniqueName(dbg_verify_pointer_in_list) = true; \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
DN_AssertF(DN_UniqueName(dbg_verify_pointer_in_list), "Pointer %p is not a part of the linked list at %p", check_ptr, first_ptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
struct MyContainer {
|
#define DN_ForList(Type, var_it_name, first_ptr, field_for_next) \
|
||||||
MyLinkItem *head;
|
Type *var_it_name = (first_ptr), *var_it_name##_next = nullptr; (var_it_name ? (var_it_name##_next = var_it_name->field_for_next, 1) : 0); var_it_name = var_it_name##_next
|
||||||
MyLinkItem *tail;
|
|
||||||
};
|
|
||||||
|
|
||||||
MyLinkItem item = {};
|
#define DN_ListQueueAdd(Type, first_ptr, last_ptr, field_for_next, item_to_add_ptr, add) \
|
||||||
MyContainer container = {};
|
|
||||||
DN_ISinglyHeadTailLLAppend(container, item);
|
|
||||||
// ... or alternatively, DN_SinglyHeadTailLLAppend(container.head, container.tail, item);
|
|
||||||
|
|
||||||
for (MyLinkItem *it = container.head; it; it = it->next) { }
|
|
||||||
*/
|
|
||||||
#define DN_SinglyHeadTailLLAppend(head, tail, to_append) \
|
|
||||||
do { \
|
do { \
|
||||||
if (!head) \
|
if (first_ptr) { \
|
||||||
head = to_append; \
|
DN_AssertF(last_ptr, "Invalid list: first is set (%p) but last is null", first_ptr); \
|
||||||
if (tail) \
|
DN_ListDebugVerifyListContainsPtr(Type, first_ptr, field_for_next, last_ptr); \
|
||||||
tail->next = to_append; \
|
} else { \
|
||||||
tail = to_append; \
|
DN_AssertF(!last_ptr, "Invalid list: first is null but last is set (%p)"); \
|
||||||
|
} \
|
||||||
|
DN_AssertF(!item_to_add_ptr->field_for_next, "Invalid list: pointer to add already has next set (%p), should be null", item_to_add_ptr->field_for_next); \
|
||||||
|
if (add == DN_AddType_Append) { \
|
||||||
|
if (!first_ptr) \
|
||||||
|
first_ptr = item_to_add_ptr; \
|
||||||
|
if (last_ptr) \
|
||||||
|
last_ptr->field_for_next = item_to_add_ptr; \
|
||||||
|
last_ptr = item_to_add_ptr; \
|
||||||
|
} else { \
|
||||||
|
DN_Assert(add == DN_AddType_Prepend); \
|
||||||
|
item_to_add_ptr->field_for_next = first_ptr; \
|
||||||
|
first_ptr = item_to_add_ptr; \
|
||||||
|
if (!last_ptr) \
|
||||||
|
last_ptr = item_to_add_ptr; \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define DN_ISinglyHeadTailLLAppend(container_ptr, to_append) DN_SinglyHeadTailLLAppend((container_ptr)->head, (container_ptr)->tail, to_append)
|
|
||||||
|
#define DN_ListQueueAppend(Type, first_ptr, last_ptr, field_for_next, item_to_add_ptr) DN_ListQueueAdd(Type, first_ptr, last_ptr, field_for_next, item_to_add_ptr, DN_AddType_Append)
|
||||||
|
#define DN_ListQueuePrepend(Type, first_ptr, last_ptr, field_for_next, item_to_add_ptr) DN_ListQueueAdd(Type, first_ptr, last_ptr, field_for_next, item_to_add_ptr, DN_AddType_Prepend)
|
||||||
|
|
||||||
|
#define DN_ListQueueDetach(Type, first_ptr, last_ptr, field_for_next, detach_ptr) \
|
||||||
|
do { \
|
||||||
|
if ((detach_ptr)) { \
|
||||||
|
DN_ListDebugVerifyListContainsPtr(Type, first_ptr, field_for_next, detach_ptr); \
|
||||||
|
if ((detach_ptr) == (first_ptr)) { \
|
||||||
|
if ((first_ptr) == (last_ptr)) \
|
||||||
|
(last_ptr) = nullptr; \
|
||||||
|
(first_ptr) = (detach_ptr)->field_for_next; \
|
||||||
|
} else { \
|
||||||
|
Type *prev_ = (first_ptr); \
|
||||||
|
while (prev_ && prev_->field_for_next != (detach_ptr)) \
|
||||||
|
prev_ = prev_->field_for_next; \
|
||||||
|
prev_->field_for_next = (detach_ptr)->field_for_next; \
|
||||||
|
if ((detach_ptr) == (last_ptr)) \
|
||||||
|
(last_ptr) = prev_; \
|
||||||
|
} \
|
||||||
|
(detach_ptr)->field_for_next = nullptr; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DN_ListLinkedAddTo(Type, first_ptr, last_ptr, field_for_next, field_for_prev, src_ptr, dest_ptr, add) \
|
||||||
|
do { \
|
||||||
|
if ((first_ptr)) { \
|
||||||
|
DN_AssertF((last_ptr), "Invalid list: first is set (%p) but last is null", (first_ptr)); \
|
||||||
|
} else { \
|
||||||
|
DN_AssertF(!(last_ptr), "Invalid list: first is null but last is set (%p)", (last_ptr)); \
|
||||||
|
(first_ptr) = (dest_ptr); \
|
||||||
|
(last_ptr) = (dest_ptr); \
|
||||||
|
DN_AssertF(!(dest_ptr)->field_for_next, "Invalid list: First and last is being initialised to dest (%p) but dest has next (%p) set, dest cannot be assigned as the last pointer", (dest_ptr), (dest_ptr)->field_for_next); \
|
||||||
|
DN_AssertF(!(dest_ptr)->field_for_prev, "Invalid list: First and last is being initialised to dest (%p) but dest has prev (%p) set, dest cannot be assigned as the first pointer", (dest_ptr), (dest_ptr)->field_for_prev); \
|
||||||
|
} \
|
||||||
|
if ((src_ptr)) { \
|
||||||
|
if (add == DN_AddType_Append) { \
|
||||||
|
(src_ptr)->field_for_next = (dest_ptr) ? (dest_ptr)->field_for_next : nullptr; \
|
||||||
|
(src_ptr)->field_for_prev = (dest_ptr); \
|
||||||
|
} else { \
|
||||||
|
DN_Assert(add == DN_AddType_Prepend); \
|
||||||
|
(src_ptr)->field_for_next = (dest_ptr); \
|
||||||
|
(src_ptr)->field_for_prev = (dest_ptr) ? (dest_ptr)->field_for_prev : nullptr; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if ((dest_ptr)) { \
|
||||||
|
DN_ListDebugVerifyListContainsPtr(Type, first_ptr, field_for_next, dest_ptr); \
|
||||||
|
if (add == DN_AddType_Append) { \
|
||||||
|
if ((dest_ptr)->field_for_next) \
|
||||||
|
(dest_ptr)->field_for_next->field_for_prev = (src_ptr); \
|
||||||
|
(dest_ptr)->field_for_next = (src_ptr); \
|
||||||
|
} else { \
|
||||||
|
DN_Assert(add == DN_AddType_Prepend); \
|
||||||
|
if ((dest_ptr)->field_for_prev) \
|
||||||
|
(dest_ptr)->field_for_prev->field_for_next = (src_ptr); \
|
||||||
|
(dest_ptr)->field_for_prev = (src_ptr); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if ((dest_ptr) == (first_ptr) && add == DN_AddType_Prepend) \
|
||||||
|
(first_ptr) = (src_ptr); \
|
||||||
|
if ((dest_ptr) == (last_ptr) && add == DN_AddType_Append) \
|
||||||
|
(last_ptr) = (src_ptr); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DN_ListLinkedAppendTo(Type, first_ptr, last_ptr, field_for_next, field_for_prev, src_ptr, dest_ptr) DN_ListLinkedAddTo(Type, first_ptr, last_ptr, field_for_next, field_for_prev, src_ptr, dest_ptr, DN_AddType_Append)
|
||||||
|
#define DN_ListLinkedPrependTo(Type, first_ptr, last_ptr, field_for_next, field_for_prev, src_ptr, dest_ptr) DN_ListLinkedAddTo(Type, first_ptr, last_ptr, field_for_next, field_for_prev, src_ptr, dest_ptr, DN_AddType_Prepend)
|
||||||
|
#define DN_ListLinkedAppend(Type, first_ptr, last_ptr, field_for_next, field_for_prev, src_ptr) DN_ListLinkedAddTo(Type, first_ptr, last_ptr, field_for_next, field_for_prev, src_ptr, last_ptr, DN_AddType_Append)
|
||||||
|
#define DN_ListLinkedPrepend(Type, first_ptr, last_ptr, field_for_next, field_for_prev, src_ptr) DN_ListLinkedAddTo(Type, first_ptr, last_ptr, field_for_next, field_for_prev, src_ptr, first_ptr, DN_AddType_Prepend)
|
||||||
|
#define DN_ListLinkedDetach(Type, first_ptr, last_ptr, field_for_next, field_for_prev, detach_ptr) \
|
||||||
|
do { \
|
||||||
|
if ((first_ptr) && (last_ptr) && (detach_ptr)) { \
|
||||||
|
DN_ListDebugVerifyListContainsPtr(Type, first_ptr, field_for_next, detach_ptr); \
|
||||||
|
if ((detach_ptr) == (first_ptr)) \
|
||||||
|
(first_ptr) = (detach_ptr)->field_for_next; \
|
||||||
|
if ((detach_ptr) == (last_ptr)) \
|
||||||
|
(last_ptr) = (detach_ptr)->field_for_prev; \
|
||||||
|
if ((detach_ptr)->field_for_prev) \
|
||||||
|
(detach_ptr)->field_for_prev->field_for_next = (detach_ptr)->field_for_next; \
|
||||||
|
if ((detach_ptr)->field_for_next) \
|
||||||
|
(detach_ptr)->field_for_next->field_for_prev = (detach_ptr)->field_for_prev; \
|
||||||
|
(detach_ptr)->field_for_next = nullptr; \
|
||||||
|
(detach_ptr)->field_for_prev = nullptr; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DN_ListStackPush(Type, first_ptr, field_for_next, item_ptr) \
|
||||||
|
do { \
|
||||||
|
DN_AssertF(!(item_ptr)->field_for_next, \
|
||||||
|
"Invalid list: pointer to push already has next set (%p), should be null", \
|
||||||
|
(void *)(item_ptr)->field_for_next); \
|
||||||
|
(item_ptr)->field_for_next = (first_ptr); \
|
||||||
|
(first_ptr) = (item_ptr); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DN_ListStackDetach(Type, first_ptr, field_for_next, detach_ptr) \
|
||||||
|
do { \
|
||||||
|
/* NOTE: `detach_` caches `detach_ptr` into a local because `detach_ptr` can alias `first_ptr`. \
|
||||||
|
DN_ListStackPop() passes `first_ptr` as both arguments and mutates `first_ptr` which would \
|
||||||
|
also modify `detach_ptr` causing unwanted side-effects like a null-ptr deref. */ \
|
||||||
|
Type *detach_ = (detach_ptr); \
|
||||||
|
if ((first_ptr) && (detach_)) { \
|
||||||
|
DN_ListDebugVerifyListContainsPtr(Type, first_ptr, field_for_next, detach_); \
|
||||||
|
if (detach_ == (first_ptr)) { \
|
||||||
|
(first_ptr) = detach_->field_for_next; \
|
||||||
|
} else { \
|
||||||
|
Type *prev_ = (first_ptr); \
|
||||||
|
while (prev_ && prev_->field_for_next != detach_) \
|
||||||
|
prev_ = prev_->field_for_next; \
|
||||||
|
DN_Assert(prev_); \
|
||||||
|
if (prev_) \
|
||||||
|
prev_->field_for_next = detach_->field_for_next; \
|
||||||
|
} \
|
||||||
|
detach_->field_for_next = nullptr; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define DN_ListStackPop(Type, first_ptr, field_for_next) \
|
||||||
|
DN_ListStackDetach(Type, first_ptr, field_for_next, first_ptr)
|
||||||
|
|
||||||
// NOTE: Sentinel Doubly Linked List
|
// NOTE: Sentinel Doubly Linked List
|
||||||
// Uses a sentinel/dummy node as the list head. The sentinel points to itself when empty.
|
// Uses a sentinel/dummy node as the list head. The sentinel points to itself when empty.
|
||||||
@@ -4294,7 +4579,6 @@ template <typename T> DN_USize DN_TArrayCopyPtrPool (T **da
|
|||||||
template <typename T> DN_USize DN_TArrayCopyPtrPoolAssert (T **data, T const *src, DN_USize count, DN_Pool *pool, DN_CallSite call_site);
|
template <typename T> DN_USize DN_TArrayCopyPtrPoolAssert (T **data, T const *src, DN_USize count, DN_Pool *pool, DN_CallSite call_site);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DN_API void* DN_SinglyLLDetach (void **link, void **next);
|
|
||||||
DN_API bool DN_RingHasSpace (DN_Ring const *ring, DN_U64 size);
|
DN_API bool DN_RingHasSpace (DN_Ring const *ring, DN_U64 size);
|
||||||
DN_API bool DN_RingHasData (DN_Ring const *ring, DN_U64 size);
|
DN_API bool DN_RingHasData (DN_Ring const *ring, DN_U64 size);
|
||||||
DN_API void DN_RingWrite (DN_Ring *ring, void const *src, DN_U64 src_size);
|
DN_API void DN_RingWrite (DN_Ring *ring, void const *src, DN_U64 src_size);
|
||||||
@@ -4561,18 +4845,20 @@ DN_API void DN_TestVerifyBytesF
|
|||||||
DN_API DN_TestCore DN_TestSuite (DN_Arena *arena_);
|
DN_API DN_TestCore DN_TestSuite (DN_Arena *arena_);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DN_API void DN_LeakTrackAlloc_ (DN_LeakTracker *leak, void *ptr, DN_USize size, bool alloc_can_leak);
|
DN_API DN_MemDebuggerSnapshot DN_MemDebuggerSnapshotMake (DN_MemDebugger *debugger, DN_Arena *arena);
|
||||||
DN_API void DN_LeakTrackDealloc_ (DN_LeakTracker *leak, void *ptr);
|
DN_API bool DN_MemDebuggerSnapshotPtrDataQSortComparePtrLT (void const *lhs, void const *rhs, void*);
|
||||||
DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
|
DN_API void DN_MemDebuggerAlloc_ (DN_MemDebugger *debugger, void *ptr, DN_USize size, bool alloc_can_leak, DN_CallSite call_site);
|
||||||
|
DN_API void DN_MemDebuggerDealloc_ (DN_MemDebugger *debugger, void *ptr);
|
||||||
|
DN_API void DN_MemDebuggerDump_ (DN_MemDebugger *debugger);
|
||||||
|
|
||||||
#if defined(DN_LEAK_TRACKING)
|
#if defined(DN_MEM_DEBUGGER)
|
||||||
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) DN_LeakTrackAlloc_(leak, ptr, size, alloc_can_leak)
|
#define DN_MemDebuggerAlloc(debugger, ptr, size, alloc_can_leak, call_site) DN_MemDebuggerAlloc_(debugger, ptr, size, alloc_can_leak, call_site)
|
||||||
#define DN_LeakTrackDealloc(leak, ptr) DN_LeakTrackDealloc_(leak, ptr)
|
#define DN_MemDebuggerDealloc(debugger, ptr) DN_MemDebuggerDealloc_(debugger, ptr)
|
||||||
#define DN_LeakDump(leak) DN_LeakDump_(leak)
|
#define DN_MemDebuggerDump(debugger) DN_MemDebuggerDump_(debugger)
|
||||||
#else
|
#else
|
||||||
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
#define DN_MemDebuggerAlloc(debugger, ptr, size, alloc_can_leak, call_site) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
||||||
#define DN_LeakTrackDealloc(leak, ptr) do { (void)ptr; } while (0)
|
#define DN_MemDebuggerDealloc(debugger, ptr) do { (void)ptr; } while (0)
|
||||||
#define DN_LeakDump(leak) do { } while (0)
|
#define DN_MemDebuggerDump(debugger) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DN_WITH_OS
|
#if DN_WITH_OS
|
||||||
@@ -4639,8 +4925,10 @@ DN_API DN_Heap DN_OS_HeapInitBasic ()
|
|||||||
DN_API DN_Heap DN_OS_HeapInitVirtual ();
|
DN_API DN_Heap DN_OS_HeapInitVirtual ();
|
||||||
DN_API DN_Heap DN_OS_HeapInitDefault ();
|
DN_API DN_Heap DN_OS_HeapInitDefault ();
|
||||||
|
|
||||||
DN_API DN_Arena DN_OS_ArenaFromHeapVirtual (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags);
|
DN_API DN_Arena DN_OS_ArenaFromHeapVirtualCallSite (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags);
|
||||||
DN_API DN_Arena DN_OS_ArenaFromHeapBasic (DN_U64 size, DN_MemFlags flags);
|
#define DN_OS_ArenaFromHeapVirtual(reserve, commit, flags, name_cstr) DN_OS_ArenaFromHeapVirtualCallSite(reserve, commit, flags, DN_CallSiteNowNamed(name_cstr))
|
||||||
|
DN_API DN_Arena DN_OS_ArenaFromHeapBasicCallSite (DN_U64 size, DN_MemFlags flags);
|
||||||
|
#define DN_OS_ArenaFromHeapBasic(size, flags, name_cstr) DN_OS_ArenaFromHeapBasic(size, flags, DN_CallSiteNowNamed(name_cstr))
|
||||||
|
|
||||||
DN_API void * DN_OS_MemReserve (DN_USize count, DN_MemCommit commit, DN_MemPage page_flags);
|
DN_API void * DN_OS_MemReserve (DN_USize count, DN_MemCommit commit, DN_MemPage page_flags);
|
||||||
DN_API bool DN_OS_MemCommit (void *ptr, DN_USize count, DN_U32 page_flags);
|
DN_API bool DN_OS_MemCommit (void *ptr, DN_USize count, DN_U32 page_flags);
|
||||||
@@ -4793,6 +5081,7 @@ DN_API void DN_OS_WindowMinimise (D
|
|||||||
DN_API void DN_OS_WindowBringToFront (DN_OSWindow *window);
|
DN_API void DN_OS_WindowBringToFront (DN_OSWindow *window);
|
||||||
DN_API void DN_OS_WindowFocus (DN_OSWindow *window);
|
DN_API void DN_OS_WindowFocus (DN_OSWindow *window);
|
||||||
DN_API bool DN_OS_WindowIsFocused (DN_OSWindow *window);
|
DN_API bool DN_OS_WindowIsFocused (DN_OSWindow *window);
|
||||||
|
DN_API void DN_OS_WindowCustomTitlebarSet (DN_OSWindow *window, bool custom_titlebar);
|
||||||
|
|
||||||
// NOTE: Thread
|
// NOTE: Thread
|
||||||
// Overview
|
// Overview
|
||||||
|
|||||||
@@ -34,17 +34,18 @@ pushd %build_dir%
|
|||||||
:: GR- Disable C RTTI
|
:: GR- Disable C RTTI
|
||||||
:: Oi Use CPU Intrinsics
|
:: Oi Use CPU Intrinsics
|
||||||
:: Z7 Combine multi-debug files to one debug file
|
:: Z7 Combine multi-debug files to one debug file
|
||||||
|
set flags=
|
||||||
set flags=%flags% %script_dir%\Source\dn_tests.cpp
|
set flags=%flags% %script_dir%\Source\dn_tests.cpp
|
||||||
set msvc_driver_flags=-EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -nologo %flags% -fsanitize=address
|
set msvc_driver_flags=-EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -nologo %flags% -fsanitize=address
|
||||||
|
|
||||||
where /q emcc && (
|
where /q emcc && (
|
||||||
echo [BUILD] Emscripten emcc detected, compiling ...
|
echo [BUILD] Emscripten emcc detected, compiling ...
|
||||||
call emcc -g -msimd128 -msse2 %flags% -o %build_dir%\dn_tests_emcc.js -s FETCH=1 -pthread -s ASYNCIFY=1 -lwebsocket -Wall || echo EMCC build failed&& exit /b 1
|
call emcc -g -msimd128 -msse2 !flags! -o %build_dir%\dn_tests_emcc.js -s FETCH=1 -pthread -s ASYNCIFY=1 -lwebsocket -Wall || echo EMCC build failed&& exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
where /q cl && (
|
where /q cl && (
|
||||||
echo [BUILD] MSVC cl detected, compiling ...
|
echo [BUILD] MSVC cl detected, compiling ...
|
||||||
set msvc_cmd=cl -MTd %msvc_driver_flags% -analyze -Fe:dn_tests_msvc -Fo:dn_tests_msvc
|
set msvc_cmd=cl -MTd !msvc_driver_flags! -analyze -Fe:dn_tests_msvc -Fo:dn_tests_msvc
|
||||||
if exist %build_dir%/Curl/Install/lib/libcurl-d.lib (
|
if exist %build_dir%/Curl/Install/lib/libcurl-d.lib (
|
||||||
set msvc_cmd=!msvc_cmd! -D DN_WITH_NET_CURL=1 -I %build_dir%/Curl/Install/include %build_dir%/Curl/Install/lib/libcurl-d.lib crypt32.lib ws2_32.lib advapi32.lib wldap32.lib iphlpapi.lib secur32.lib
|
set msvc_cmd=!msvc_cmd! -D DN_WITH_NET_CURL=1 -I %build_dir%/Curl/Install/include %build_dir%/Curl/Install/lib/libcurl-d.lib crypt32.lib ws2_32.lib advapi32.lib wldap32.lib iphlpapi.lib secur32.lib
|
||||||
)
|
)
|
||||||
@@ -52,20 +53,21 @@ pushd %build_dir%
|
|||||||
|
|
||||||
REM Build the single header
|
REM Build the single header
|
||||||
powershell -Command "$time = Measure-Command { !msvc_cmd! | Out-Default }; Write-Host '[BUILD] msvc:'$time.TotalSeconds's'; exit $LASTEXITCODE" || echo MSVC build failed&& exit /b 1
|
powershell -Command "$time = Measure-Command { !msvc_cmd! | Out-Default }; Write-Host '[BUILD] msvc:'$time.TotalSeconds's'; exit $LASTEXITCODE" || echo MSVC build failed&& exit /b 1
|
||||||
echo [BUILD] Single header generator ...
|
echo [BUILD] Single header generator: USE_SINGLE_HEADER not defined...
|
||||||
call cl %script_dir%\single_header_generator.cpp -Z7 -nologo -link || echo Single header generator build failed&& exit /b 1
|
call cl %script_dir%\single_header_generator.cpp -Z7 -nologo -link || echo Single header generator build failed&& exit /b 1
|
||||||
call %build_dir%\single_header_generator.exe %script_dir%\Source %script_dir%\Single-Header || echo Single header generation failed&& exit /b 1
|
call %build_dir%\single_header_generator.exe %script_dir%\Source %script_dir%\Single-Header || echo Single header generation failed&& exit /b 1
|
||||||
|
|
||||||
REM Build the single header using the single header (to test that the generated single header)
|
REM Build the single header using the single header (to test that the generated single header)
|
||||||
|
echo [BUILD] Single header generator: USE_SINGLE_HEADER defined...
|
||||||
call cl %script_dir%\single_header_generator.cpp -Z7 -nologo -D USE_SINGLE_HEADER -link || echo Single header generator build failed&& exit /b 1
|
call cl %script_dir%\single_header_generator.cpp -Z7 -nologo -D USE_SINGLE_HEADER -link || echo Single header generator build failed&& exit /b 1
|
||||||
call %build_dir%\single_header_generator.exe %script_dir%\Source %script_dir%\Single-Header || echo Single header generation failed&& exit /b 1
|
call %build_dir%\single_header_generator.exe %script_dir%\Source %script_dir%\Single-Header || echo Single header generation failed&& exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
where /q clang-cl && (
|
where /q clang-cl && (
|
||||||
echo [BUILD] LLVM clang-cl detected, compiling ...
|
echo [BUILD] LLVM clang-cl detected, compiling ...
|
||||||
set clang_cmd=clang-cl -MT %msvc_driver_flags% -fsanitize=undefined -Fe:dn_tests_clang -link
|
set clang_cmd=clang-cl -MT !msvc_driver_flags! -fsanitize=undefined -Fe:dn_tests_clang -link
|
||||||
powershell -Command "$time = Measure-Command { !clang_cmd! | Out-Default }; Write-Host '[BUILD] clang-cl:'$time.TotalSeconds's'; exit $LASTEXITCODE" || echo CLANG build failed&& exit /b 1
|
powershell -Command "$time = Measure-Command { !clang_cmd! | Out-Default }; Write-Host '[BUILD] clang-cl:'$time.TotalSeconds's'; exit $LASTEXITCODE" || echo CLANG build failed&& exit /b 1
|
||||||
)
|
)
|
||||||
|
|
||||||
exit /b 1
|
popd
|
||||||
popd
|
exit /b 0
|
||||||
|
|||||||
Reference in New Issue
Block a user