7640 lines
354 KiB
C++
7640 lines
354 KiB
C++
// Generated by the DN single header generator 2026-05-18 14:23:35
|
|
|
|
#if !defined(DN_H)
|
|
#define DN_H
|
|
|
|
// NOTE: DN
|
|
// Getting Started
|
|
// Include this mega header `dn.h` and define the following symbols to `1` to conditionally
|
|
// enable the interfaces for those features. Additionally in the same or different translation
|
|
// unit, include `dn.cpp` with the same symbols defined to enable the implementation of these
|
|
// features.
|
|
//
|
|
// See the configuration section for more information on other symbols that can be defined.
|
|
//
|
|
// The following is a single translation unit example:
|
|
/*
|
|
#define DN_H_WITH_OS 1
|
|
#define DN_H_WITH_CORE 1
|
|
#define DN_H_WITH_HELPERS 1
|
|
#define DN_H_WITH_ASYNC 1
|
|
#define DN_H_WITH_NET 1
|
|
#include "dn.h"
|
|
|
|
#define DN_CPP_WITH_TESTS 1
|
|
#define DN_CPP_WITH_DEMO 1
|
|
#include "dn.cpp"
|
|
*/
|
|
// Then initialise the library at runtime by calling DN_Init(...). The library is laid out as:
|
|
//
|
|
// - The base layer (dn_base.h) which provides primitives that do not require a host operating
|
|
// system (e.g. freestanding) such as string manipulation, compiler intrinsics and containers.
|
|
// This layer is unconditionallly always available by compiling with this library.
|
|
//
|
|
// - The OS layer (dn_os.h) which provides primitives that use the OS such as file IO, threading
|
|
// synchronisation, memory allocation. This layer is OPTIONAL.
|
|
//
|
|
// - Extra layer provides helper utilities that are opt-in. These layers are OPTIONAL.
|
|
//
|
|
// Configuration
|
|
// Platform Target
|
|
// Define one of the following directives to configure this library to compile for that
|
|
// platform. By default, the library will auto-detect the current host platform and select that
|
|
// as the target platform.
|
|
//
|
|
// DN_PLATFORM_EMSCRIPTEN
|
|
// DN_PLATFORM_POSIX
|
|
// DN_PLATFORM_WIN32
|
|
//
|
|
// For example
|
|
//
|
|
// #define DN_PLATFORM_WIN32
|
|
//
|
|
// Will ensure that <Windows.h> is included and the OS layer is implemented using Win32
|
|
// primitives.
|
|
//
|
|
// Static functions
|
|
// All public functions in the DN library are prefixed with the macro '#define DN_API'. By
|
|
// default 'DN_API' is not defined to anything. Define
|
|
//
|
|
// DN_STATIC_API
|
|
//
|
|
// To replace all the functions prefixed with DN_API to be prefixed with 'static' ensuring that
|
|
// the functions in the library do not export an entry into the linking table.
|
|
// translation units.
|
|
//
|
|
// Disabling the in-built <Windows.h> (if #define DN_H_WITH_OS 1)
|
|
// If you are building DN for the Windows platform, <Windows.h> is a large legacy header that
|
|
// applications have to include to use Windows APIs. By default this library uses a replacement
|
|
// header for all the Windows functions that it uses in the OS layer removing the need to
|
|
// include <Windows.h> to improve compilation times. This mini header will conflict with
|
|
// <Windows.h> if it needs to be included in your project. The mini header can be disabled by
|
|
// defining:
|
|
//
|
|
// DN_NO_WINDOWS_H_REPLACEMENT_HEADER
|
|
//
|
|
// To instead use <Windows.h>. DN automatically detects if <Windows.h> is included in an earlier
|
|
// translation unit and will automatically disable the in-built replacement header in which case
|
|
// this does not need to be defined.
|
|
//
|
|
// Freestanding
|
|
// The base layer can be used without an OS implementation by defining DN_FREESTANDING like:
|
|
//
|
|
// #define DN_FREESTANDING
|
|
//
|
|
// This means functionality that relies on the OS like printing, memory allocation, stack traces
|
|
// and so forth are disabled.
|
|
//
|
|
// ASAN Arena Poisoning
|
|
// When compiled with address sanitizer (.e.g -fsanitize=address) you can optionally enable
|
|
// memory region poisoning on the inbuilt arena's to catch in certain scenarios, use-after-free
|
|
//
|
|
// #define DN_ASAN_POISON 1
|
|
//
|
|
// Since arenas manage their own block of memory it does not automatically benefit from ASAN's
|
|
// memory markup that ASAN does and so it is implemented manually by using the ASAN user-level
|
|
// poisoning APIs. Similarly, since the arena recycles its own memory rather than release back
|
|
// to the OS, poisoning is not as effective for arenas but every little bit helps.
|
|
//
|
|
// Scrub Uninitialised Memory
|
|
// If this macro is defined, temp memory that is returned to an arena, or allocations freed by
|
|
// a pool are scrubbed to this specified byte, in absence of this bytes returned to the
|
|
// allocators are left as-is or memset to 0. For example to scrub bytes to 0xCD (MSVC's
|
|
// pattern) define as follows:
|
|
//
|
|
// #define DN_SCRUB_UNINIT_MEM_BYTE 0xCD
|
|
//
|
|
// Due to the recycling of memory in arenas and pool, similarly to ASAN poisoning this reduces
|
|
// the window in which a use-after-free can be detected using this guard, however every little
|
|
// bit helps.
|
|
//
|
|
// Arena temp memory use-after-free (UAF) tooling
|
|
// UAF Guard
|
|
// Set the following preprocessor value to 1 to enable UAF protection when using
|
|
// scratch/temporary memory functionality. Defaults to off, or 0 if not specified
|
|
//
|
|
// #define DN_ARENA_TEMP_MEM_UAF_GUARD 1
|
|
//
|
|
// This enables arenas to markup itself with the active memory region and subsequent
|
|
// allocations check if the allocation belongs to the same or different region. Different
|
|
// regions cause a UAF violation.
|
|
//
|
|
// More detailed diagnostics can be enabled by setting the flag DN_ArenaFlags_TempMemUAFGuard
|
|
// on the affected arenas. Note that this incurs a performance penalty as each memory region
|
|
// will store a stacktrace of its creation. It's recommended in development builds to always
|
|
// run with temp-memory guarding, if a violation occurs, then enable tracing on the arena to
|
|
// pinpoint the issue.
|
|
//
|
|
// Enabling memory guard incurs additional memory requirements from the arena's backing
|
|
// memory block and additional book-keeping fields on each arena and their temp memory
|
|
// instances.
|
|
//
|
|
// UAF Tracing
|
|
// Set the following preprocessor value to 1 to enable tracing when the UAF guard triggers.
|
|
// Defaults to off, or 0 if not specified.
|
|
//
|
|
// #define DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT 1
|
|
//
|
|
// This opts in all arenas to tracing functionality by default globally. Arenas can opt out
|
|
// by setting the flag DN_ArenaFlags_TempMemUAFTraceDisable on the arena. The disable flag
|
|
// takes precedence over all other settings including the global preprocessor macro and the
|
|
// enablement flag (DN_ArenaFlags_TempMemUAFTrace).
|
|
//
|
|
// Tracing incurs an additional much heavier performance penalty than the UAF guard due to
|
|
// the stacktrace that is stored per region to report to the user when a UAF guard violation
|
|
// occurs.
|
|
|
|
// DN: Single header generator commented out => #include "Base/dn_base.h"
|
|
#if !defined(DN_BASE_H)
|
|
#define DN_BASE_H
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
// NOTE: Compiler identification
|
|
// Warning! Order is important here, clang-cl on Windows defines _MSC_VER
|
|
#if defined(_MSC_VER)
|
|
#if defined(__clang__)
|
|
#define DN_COMPILER_CLANG_CL
|
|
#define DN_COMPILER_CLANG
|
|
#else
|
|
#define DN_COMPILER_MSVC
|
|
#endif
|
|
#elif defined(__clang__)
|
|
#define DN_COMPILER_CLANG
|
|
#elif defined(__GNUC__)
|
|
#define DN_COMPILER_GCC
|
|
#endif
|
|
|
|
// NOTE: __has_feature
|
|
// MSVC for example does not support the feature detection macro for instance so we compile it out
|
|
#if defined(__has_feature)
|
|
#define DN_HAS_FEATURE(expr) __has_feature(expr)
|
|
#else
|
|
#define DN_HAS_FEATURE(expr) 0
|
|
#endif
|
|
|
|
// NOTE: __has_builtin
|
|
// MSVC for example does not support the feature detection macro for instance so we compile it out
|
|
#if defined(__has_builtin)
|
|
#define DN_HAS_BUILTIN(expr) __has_builtin(expr)
|
|
#else
|
|
#define DN_HAS_BUILTIN(expr) 0
|
|
#endif
|
|
|
|
// NOTE: Warning suppression macros
|
|
#if defined(DN_COMPILER_MSVC)
|
|
#define DN_MSVC_WARNING_PUSH __pragma(warning(push))
|
|
#define DN_MSVC_WARNING_DISABLE(...) __pragma(warning(disable :##__VA_ARGS__))
|
|
#define DN_MSVC_WARNING_ENABLE(...) __pragma(warning(default :##__VA_ARGS__))
|
|
#define DN_MSVC_WARNING_POP __pragma(warning(pop))
|
|
#else
|
|
#define DN_MSVC_WARNING_PUSH
|
|
#define DN_MSVC_WARNING_ENABLE(...)
|
|
#define DN_MSVC_WARNING_DISABLE(...)
|
|
#define DN_MSVC_WARNING_POP
|
|
#endif
|
|
|
|
#if defined(DN_COMPILER_CLANG) || defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG_CL)
|
|
#define DN_GCC_WARNING_PUSH _Pragma("GCC diagnostic push")
|
|
#define DN_GCC_WARNING_DISABLE_HELPER_0(x) #x
|
|
#define DN_GCC_WARNING_DISABLE_HELPER_1(y) DN_GCC_WARNING_DISABLE_HELPER_0(GCC diagnostic ignored #y)
|
|
#define DN_GCC_WARNING_DISABLE(warning) _Pragma(DN_GCC_WARNING_DISABLE_HELPER_1(warning))
|
|
#define DN_GCC_WARNING_POP _Pragma("GCC diagnostic pop")
|
|
#else
|
|
#define DN_GCC_WARNING_PUSH
|
|
#define DN_GCC_WARNING_DISABLE(...)
|
|
#define DN_GCC_WARNING_POP
|
|
#endif
|
|
|
|
// NOTE: Host OS identification
|
|
#if defined(_WIN32)
|
|
#define DN_OS_WIN32
|
|
#elif defined(__gnu_linux__) || defined(__linux__)
|
|
#define DN_OS_UNIX
|
|
#endif
|
|
|
|
// NOTE: Platform identification
|
|
#if !defined(DN_PLATFORM_EMSCRIPTEN) && \
|
|
!defined(DN_PLATFORM_POSIX) && \
|
|
!defined(DN_PLATFORM_WIN32)
|
|
#if defined(__aarch64__) || defined(_M_ARM64)
|
|
#define DN_PLATFORM_ARM64
|
|
#elif defined(__EMSCRIPTEN__)
|
|
#define DN_PLATFORM_EMSCRIPTEN
|
|
#elif defined(DN_OS_WIN32)
|
|
#define DN_PLATFORM_WIN32
|
|
#else
|
|
#define DN_PLATFORM_POSIX
|
|
#endif
|
|
#endif
|
|
|
|
// NOTE: Windows crap
|
|
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
|
#if defined(_CRT_SECURE_NO_WARNINGS)
|
|
#define DN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED
|
|
#else
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
#endif
|
|
#endif
|
|
|
|
// NOTE: Force Inline
|
|
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
|
#define DN_FORCE_INLINE __forceinline
|
|
#else
|
|
#define DN_FORCE_INLINE inline __attribute__((always_inline))
|
|
#endif
|
|
|
|
// NOTE: Function/Variable Annotations
|
|
#if defined(DN_STATIC_API)
|
|
#define DN_API static
|
|
#else
|
|
#define DN_API
|
|
#endif
|
|
|
|
// NOTE: C/CPP Literals
|
|
// Declare struct literals that work in both C and C++ because the syntax is different between
|
|
// languages.
|
|
#if 0
|
|
struct Foo { int a; }
|
|
struct Foo foo = DN_LITERAL(Foo){32}; // Works on both C and C++
|
|
#endif
|
|
|
|
#if defined(__cplusplus)
|
|
#define DN_Literal(T) T
|
|
#else
|
|
#define DN_Literal(T) (T)
|
|
#endif
|
|
|
|
// NOTE: Thread Locals
|
|
#if defined(__cplusplus)
|
|
#define DN_THREAD_LOCAL thread_local
|
|
#else
|
|
#define DN_THREAD_LOCAL _Thread_local
|
|
#endif
|
|
|
|
// NOTE: C variadic argument annotations
|
|
// TODO: Other compilers
|
|
#if defined(DN_COMPILER_MSVC)
|
|
#define DN_FMT_ATTRIB _Printf_format_string_
|
|
#else
|
|
#define DN_FMT_ATTRIB
|
|
#endif
|
|
|
|
// NOTE: Type Cast
|
|
#define DN_Cast(val) (val)
|
|
|
|
// NOTE: Zero initialisation macro
|
|
#if defined(__cplusplus)
|
|
#define DN_ZeroInit {}
|
|
#else
|
|
#define DN_ZeroInit {0}
|
|
#endif
|
|
|
|
// NOTE: Address sanitizer
|
|
#if !defined(DN_ASAN_POISON)
|
|
#define DN_ASAN_POISON 0
|
|
#endif
|
|
|
|
#if !defined(DN_ASAN_VET_POISON)
|
|
#define DN_ASAN_VET_POISON 0
|
|
#endif
|
|
|
|
#define DN_ASAN_POISON_ALIGNMENT 8
|
|
|
|
#if !defined(DN_ASAN_POISON_GUARD_SIZE)
|
|
#define DN_ASAN_POISON_GUARD_SIZE 128
|
|
#endif
|
|
|
|
#if DN_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
|
#include <sanitizer/asan_interface.h>
|
|
#endif
|
|
|
|
// NOTE: Memory
|
|
#if !defined(DN_ARENA_TEMP_MEM_UAF_GUARD)
|
|
#define DN_ARENA_TEMP_MEM_UAF_GUARD 0
|
|
#endif
|
|
|
|
#if !defined(DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT)
|
|
#define DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT 0
|
|
#endif
|
|
|
|
#if !defined(DN_SCRUB_UNINIT_MEM_BYTE)
|
|
#define DN_SCRUB_UNINIT_MEM_BYTE 0
|
|
#endif
|
|
|
|
// NOTE: Macros
|
|
#define DN_Stringify(x) #x
|
|
#define DN_TokenCombine2(x, y) x ## y
|
|
#define DN_TokenCombine(x, y) DN_TokenCombine2(x, y)
|
|
|
|
#if defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64)
|
|
#define DN_64_BIT
|
|
#else
|
|
#define DN_32_BIT
|
|
#endif
|
|
|
|
#include <stdarg.h> // va_list
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <limits.h>
|
|
#include <inttypes.h> // PRIu64...
|
|
|
|
#if !defined(DN_OS_WIN32)
|
|
#include <stdlib.h> // exit()
|
|
#endif
|
|
|
|
#define DN_ForIndexU(index, size) DN_USize index = 0; index < size; index++
|
|
#define DN_ForIndexI(index, size) DN_ISize index = 0; index < size; index++
|
|
#define DN_ForItSize(it, T, array, size) struct { DN_USize index; T *data; } it = {0, &(array)[0]}; it.index < (size); it.index++, it.data = (array) + it.index
|
|
#define DN_ForItSizeReverse(it, T, array, size) struct { DN_USize index; T *data; } it = {(size) - 1, &(array)[size - 1]}; it.index < (size); 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)->size; 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_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_AlignUpPowerOfTwo(value, pot) (((uintptr_t)(value) + ((uintptr_t)(pot) - 1)) & ~((uintptr_t)(pot) - 1))
|
|
#define DN_AlignDownPowerOfTwo(value, pot) ((uintptr_t)(value) & ~((uintptr_t)(pot) - 1))
|
|
#define DN_IsPowerOfTwo(value) ((((uintptr_t)(value)) & (((uintptr_t)(value)) - 1)) == 0)
|
|
#define DN_IsPowerOfTwoAligned(value, pot) ((((uintptr_t)value) & (((uintptr_t)pot) - 1)) == 0)
|
|
|
|
// NOTE: String.h Dependencies
|
|
#if !defined(DN_Memcpy) || !defined(DN_Memset) || !defined(DN_Memcmp) || !defined(DN_Memmove)
|
|
#include <string.h>
|
|
#if !defined(DN_Memcpy)
|
|
#define DN_Memcpy(dest, src, count) memcpy((dest), (src), (count))
|
|
#endif
|
|
#if !defined(DN_Memset)
|
|
#define DN_Memset(dest, value, count) memset((dest), (value), (count))
|
|
#endif
|
|
#if !defined(DN_Memcmp)
|
|
#define DN_Memcmp(lhs, rhs, count) memcmp((lhs), (rhs), (count))
|
|
#endif
|
|
#if !defined(DN_Memmove)
|
|
#define DN_Memmove(dest, src, count) memmove((dest), (src), (count))
|
|
#endif
|
|
#endif
|
|
|
|
// NOTE: Math.h Dependencies
|
|
#if !defined(DN_SqrtF32) || !defined(DN_SinF32) || !defined(DN_CosF32) || !defined(DN_TanF32)
|
|
#include <math.h>
|
|
#if !defined(DN_SqrtF32)
|
|
#define DN_SqrtF32(val) sqrtf(val)
|
|
#endif
|
|
#if !defined(DN_SinF32)
|
|
#define DN_SinF32(val) sinf(val)
|
|
#endif
|
|
#if !defined(DN_CosF32)
|
|
#define DN_CosF32(val) cosf(val)
|
|
#endif
|
|
#if !defined(DN_TanF32)
|
|
#define DN_TanF32(val) tanf(val)
|
|
#endif
|
|
#if !defined(DN_PowF32)
|
|
#define DN_PowF32(val, exp) powf(val, exp)
|
|
#endif
|
|
#endif
|
|
|
|
// NOTE: Math
|
|
#define DN_PiF32 3.14159265359f
|
|
|
|
#define DN_DegreesToRadsF32(degrees) ((degrees) * (DN_PiF32 / 180.0f))
|
|
#define DN_RadsToDegreesF32(radians) ((radians) * (180.f * DN_PiF32))
|
|
|
|
#define DN_Abs(val) (((val) < 0) ? (-(val)) : (val))
|
|
#define DN_Max(a, b) (((a) > (b)) ? (a) : (b))
|
|
#define DN_Min(a, b) (((a) < (b)) ? (a) : (b))
|
|
#define DN_Clamp(val, lo, hi) DN_Max(DN_Min(val, hi), lo)
|
|
#define DN_Squared(val) ((val) * (val))
|
|
|
|
#define DN_Swap(a, b) \
|
|
do { \
|
|
auto temp = a; \
|
|
a = b; \
|
|
b = temp; \
|
|
} while (0)
|
|
|
|
// NOTE: Size
|
|
#define DN_SizeOfI(val) DN_Cast(ptrdiff_t)sizeof(val)
|
|
#define DN_ArrayCountU(array) (sizeof(array)/(sizeof((array)[0])))
|
|
#define DN_ArrayCountI(array) (DN_ISize)DN_ArrayCountU(array)
|
|
#define DN_CharCountU(string) (sizeof(string) - 1)
|
|
|
|
// NOTE: SI Byte
|
|
#define DN_Bytes(val) ((DN_U64)val)
|
|
#define DN_Kilobytes(val) ((DN_U64)1024 * DN_Bytes(val))
|
|
#define DN_Megabytes(val) ((DN_U64)1024 * DN_Kilobytes(val))
|
|
#define DN_Gigabytes(val) ((DN_U64)1024 * DN_Megabytes(val))
|
|
|
|
// NOTE: Time
|
|
#define DN_MsFromSec(val) ((val) * 1000ULL)
|
|
#define DN_SecFromMins(val) ((val) * 60ULL)
|
|
#define DN_SecFromHours(val) (DN_SecFromMins(val) * 60ULL)
|
|
#define DN_SecFromDays(val) (DN_SecFromHours(val) * 24ULL)
|
|
#define DN_SecFromWeeks(val) (DN_SecFromDays(val) * 7ULL)
|
|
#define DN_SecFromYears(val) (DN_SecFromWeeks(val) * 52ULL)
|
|
|
|
// NOTE: Debug Break
|
|
#if !defined(DN_DebugBreak)
|
|
#if defined(NDEBUG)
|
|
#define DN_DebugBreak
|
|
#else
|
|
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
|
#define DN_DebugBreak __debugbreak()
|
|
#elif DN_HAS_BUILTIN(__builtin_debugtrap)
|
|
#define DN_DebugBreak __builtin_debugtrap()
|
|
#elif DN_HAS_BUILTIN(__builtin_trap) || defined(DN_COMPILER_GCC)
|
|
#define DN_DebugBreak __builtin_trap()
|
|
#else
|
|
#include <signal.h>
|
|
#if defined(SIGTRAP)
|
|
#define DN_DebugBreak raise(SIGTRAP)
|
|
#else
|
|
#define DN_DebugBreak raise(SIGABRT)
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
// NOTE: Helper macros to declare an array data structure for a given `Type`
|
|
#define DN_DArrayStructDecl(Type) \
|
|
struct Type##Array \
|
|
{ \
|
|
Type* data; \
|
|
DN_USize count; \
|
|
DN_USize max; \
|
|
}
|
|
|
|
#define DN_FixedArrayStructDecl(Type, capacity) \
|
|
struct Type##x##capacity##Array \
|
|
{ \
|
|
Type data[capacity]; \
|
|
DN_USize count; \
|
|
DN_USize max; \
|
|
}
|
|
|
|
// NOTE: Types
|
|
typedef intptr_t DN_ISize;
|
|
typedef uintptr_t DN_USize;
|
|
|
|
typedef int8_t DN_I8;
|
|
typedef int16_t DN_I16;
|
|
typedef int32_t DN_I32;
|
|
typedef int64_t DN_I64;
|
|
|
|
typedef uint8_t DN_U8;
|
|
typedef uint16_t DN_U16;
|
|
typedef uint32_t DN_U32;
|
|
typedef uint64_t DN_U64;
|
|
|
|
typedef uintptr_t DN_UPtr;
|
|
typedef float DN_F32;
|
|
typedef double DN_F64;
|
|
typedef unsigned int DN_UInt;
|
|
typedef DN_I32 DN_B32;
|
|
|
|
#define DN_F32_MAX 3.402823466e+38F
|
|
#define DN_F32_MIN 1.175494351e-38F
|
|
#define DN_F64_MAX 1.7976931348623158e+308
|
|
#define DN_F64_MIN 2.2250738585072014e-308
|
|
#define DN_USIZE_MAX UINTPTR_MAX
|
|
#define DN_ISIZE_MAX INTPTR_MAX
|
|
#define DN_ISIZE_MIN INTPTR_MIN
|
|
|
|
// NOTE: Intrinsics
|
|
// NOTE: DN_AtomicAdd/Exchange return the previous value store in the target
|
|
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
|
#include <intrin.h>
|
|
#define DN_AtomicCompareExchange64(dest, desired_val, prev_val) _InterlockedCompareExchange64((__int64 volatile *)dest, desired_val, prev_val)
|
|
#define DN_AtomicCompareExchange32(dest, desired_val, prev_val) _InterlockedCompareExchange((long volatile *)dest, desired_val, prev_val)
|
|
|
|
#define DN_AtomicLoadU64(target) *(target)
|
|
#define DN_AtomicLoadU32(target) *(target)
|
|
#define DN_AtomicAddU32(target, value) _InterlockedExchangeAdd((long volatile *)target, value)
|
|
#define DN_AtomicAddU64(target, value) _InterlockedExchangeAdd64((__int64 volatile *)target, value)
|
|
#define DN_AtomicSubU32(target, value) DN_AtomicAddU32(DN_Cast(long volatile *) target, (long)-value)
|
|
#define DN_AtomicSubU64(target, value) DN_AtomicAddU64(target, (DN_U64) - value)
|
|
|
|
#define DN_CountLeadingZerosU64(value) __lzcnt64(value)
|
|
#define DN_CountLeadingZerosU32(value) __lzcnt(value)
|
|
#define DN_CPUGetTSC() __rdtsc()
|
|
#define DN_CompilerReadBarrierAndCPUReadFence _ReadBarrier(); _mm_lfence()
|
|
#define DN_CompilerWriteBarrierAndCPUWriteFence _WriteBarrier(); _mm_sfence()
|
|
#elif defined(DN_COMPILER_GCC) || defined(DN_COMPILER_CLANG)
|
|
#if defined(__ANDROID__)
|
|
#elif defined(DN_PLATFORM_EMSCRIPTEN)
|
|
#if !defined(__wasm_simd128__)
|
|
#error DN_Base requires -msse2 to be passed to Emscripten
|
|
#endif
|
|
#include <emmintrin.h>
|
|
#else
|
|
#include <x86intrin.h>
|
|
#endif
|
|
|
|
#define DN_AtomicLoadU64(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
|
#define DN_AtomicLoadU32(target) __atomic_load_n(x, __ATOMIC_SEQ_CST)
|
|
#define DN_AtomicAddU32(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
|
#define DN_AtomicAddU64(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
|
|
#define DN_AtomicSubU32(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
|
#define DN_AtomicSubU64(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
|
|
|
|
#define DN_CountLeadingZerosU64(value) __builtin_clzll(value)
|
|
#define DN_CountLeadingZerosU32(value) __builtin_clzl(value)
|
|
|
|
#if defined(DN_COMPILER_GCC)
|
|
#define DN_CPUGetTSC() __rdtsc()
|
|
#else
|
|
#define DN_CPUGetTSC() __builtin_readcyclecounter()
|
|
#endif
|
|
|
|
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
|
#define DN_CompilerReadBarrierAndCPUReadFence
|
|
#define DN_CompilerWriteBarrierAndCPUWriteFence
|
|
#else
|
|
#define DN_CompilerReadBarrierAndCPUReadFence asm volatile("lfence" ::: "memory")
|
|
#define DN_CompilerWriteBarrierAndCPUWriteFence asm volatile("sfence" ::: "memory")
|
|
#endif
|
|
#else
|
|
#error "Compiler not supported"
|
|
#endif
|
|
|
|
#if defined(DN_64_BIT)
|
|
#define DN_CountLeadingZerosUSize(value) DN_CountLeadingZerosU64(value)
|
|
#else
|
|
#define DN_CountLeadingZerosUSize(value) DN_CountLeadingZerosU32(value)
|
|
#endif
|
|
|
|
enum DN_ZMem
|
|
{
|
|
DN_ZMem_No, // Memory can be handed out without zero-ing it out
|
|
DN_ZMem_Yes, // Memory should be zero-ed out before giving to the callee
|
|
};
|
|
|
|
struct DN_Str8
|
|
{
|
|
char *data; // The bytes of the string
|
|
DN_USize size; // The number of bytes in the string
|
|
};
|
|
|
|
struct DN_Str8Slice
|
|
{
|
|
DN_Str8 *data;
|
|
DN_USize count;
|
|
};
|
|
|
|
struct DN_Str8x16 { char data[16]; DN_USize size; };
|
|
struct DN_Str8x32 { char data[32]; DN_USize size; };
|
|
struct DN_Str8x64 { char data[64]; DN_USize size; };
|
|
struct DN_Str8x128 { char data[128]; DN_USize size; };
|
|
struct DN_Str8x256 { char data[256]; DN_USize size; };
|
|
struct DN_Str8x512 { char data[512]; DN_USize size; };
|
|
struct DN_Str8x1024 { char data[1024]; DN_USize size; };
|
|
|
|
struct DN_Str16 // A pointer and length style string that holds slices to UTF16 bytes.
|
|
{
|
|
wchar_t *data; // The UTF16 bytes of the string
|
|
DN_USize size; // The number of characters in the string
|
|
};
|
|
|
|
struct DN_Str16Slice
|
|
{
|
|
DN_Str16 *data;
|
|
DN_USize count;
|
|
};
|
|
|
|
struct DN_CPURegisters
|
|
{
|
|
int eax;
|
|
int ebx;
|
|
int ecx;
|
|
int edx;
|
|
};
|
|
|
|
union DN_CPUIDResult
|
|
{
|
|
DN_CPURegisters reg;
|
|
int values[4];
|
|
};
|
|
|
|
struct DN_CPUIDArgs { int eax; int ecx; };
|
|
|
|
#define DN_CPU_FEAT_XMACRO \
|
|
DN_CPU_FEAT_XENTRY(3DNow) \
|
|
DN_CPU_FEAT_XENTRY(3DNowExt) \
|
|
DN_CPU_FEAT_XENTRY(ABM) \
|
|
DN_CPU_FEAT_XENTRY(AES) \
|
|
DN_CPU_FEAT_XENTRY(AVX) \
|
|
DN_CPU_FEAT_XENTRY(AVX2) \
|
|
DN_CPU_FEAT_XENTRY(AVX512F) \
|
|
DN_CPU_FEAT_XENTRY(AVX512DQ) \
|
|
DN_CPU_FEAT_XENTRY(AVX512IFMA) \
|
|
DN_CPU_FEAT_XENTRY(AVX512PF) \
|
|
DN_CPU_FEAT_XENTRY(AVX512ER) \
|
|
DN_CPU_FEAT_XENTRY(AVX512CD) \
|
|
DN_CPU_FEAT_XENTRY(AVX512BW) \
|
|
DN_CPU_FEAT_XENTRY(AVX512VL) \
|
|
DN_CPU_FEAT_XENTRY(AVX512VBMI) \
|
|
DN_CPU_FEAT_XENTRY(AVX512VBMI2) \
|
|
DN_CPU_FEAT_XENTRY(AVX512VNNI) \
|
|
DN_CPU_FEAT_XENTRY(AVX512BITALG) \
|
|
DN_CPU_FEAT_XENTRY(AVX512VPOPCNTDQ) \
|
|
DN_CPU_FEAT_XENTRY(AVX5124VNNIW) \
|
|
DN_CPU_FEAT_XENTRY(AVX5124FMAPS) \
|
|
DN_CPU_FEAT_XENTRY(AVX512VP2INTERSECT) \
|
|
DN_CPU_FEAT_XENTRY(AVX512FP16) \
|
|
DN_CPU_FEAT_XENTRY(CLZERO) \
|
|
DN_CPU_FEAT_XENTRY(CMPXCHG8B) \
|
|
DN_CPU_FEAT_XENTRY(CMPXCHG16B) \
|
|
DN_CPU_FEAT_XENTRY(F16C) \
|
|
DN_CPU_FEAT_XENTRY(FMA) \
|
|
DN_CPU_FEAT_XENTRY(FMA4) \
|
|
DN_CPU_FEAT_XENTRY(FP128) \
|
|
DN_CPU_FEAT_XENTRY(FP256) \
|
|
DN_CPU_FEAT_XENTRY(FPU) \
|
|
DN_CPU_FEAT_XENTRY(MMX) \
|
|
DN_CPU_FEAT_XENTRY(MONITOR) \
|
|
DN_CPU_FEAT_XENTRY(MOVBE) \
|
|
DN_CPU_FEAT_XENTRY(MOVU) \
|
|
DN_CPU_FEAT_XENTRY(MmxExt) \
|
|
DN_CPU_FEAT_XENTRY(PCLMULQDQ) \
|
|
DN_CPU_FEAT_XENTRY(POPCNT) \
|
|
DN_CPU_FEAT_XENTRY(RDRAND) \
|
|
DN_CPU_FEAT_XENTRY(RDSEED) \
|
|
DN_CPU_FEAT_XENTRY(RDTSCP) \
|
|
DN_CPU_FEAT_XENTRY(SHA) \
|
|
DN_CPU_FEAT_XENTRY(SSE) \
|
|
DN_CPU_FEAT_XENTRY(SSE2) \
|
|
DN_CPU_FEAT_XENTRY(SSE3) \
|
|
DN_CPU_FEAT_XENTRY(SSE41) \
|
|
DN_CPU_FEAT_XENTRY(SSE42) \
|
|
DN_CPU_FEAT_XENTRY(SSE4A) \
|
|
DN_CPU_FEAT_XENTRY(SSSE3) \
|
|
DN_CPU_FEAT_XENTRY(TSC) \
|
|
DN_CPU_FEAT_XENTRY(TscInvariant) \
|
|
DN_CPU_FEAT_XENTRY(VAES) \
|
|
DN_CPU_FEAT_XENTRY(VPCMULQDQ)
|
|
|
|
enum DN_CPUFeature
|
|
{
|
|
#define DN_CPU_FEAT_XENTRY(label) DN_CPUFeature_##label,
|
|
DN_CPU_FEAT_XMACRO
|
|
#undef DN_CPU_FEAT_XENTRY
|
|
DN_CPUFeature_Count,
|
|
};
|
|
|
|
struct DN_CPUFeatureDecl
|
|
{
|
|
DN_CPUFeature value;
|
|
DN_Str8 label;
|
|
};
|
|
|
|
struct DN_CPUFeatureQuery
|
|
{
|
|
DN_CPUFeature feature;
|
|
bool available;
|
|
};
|
|
|
|
struct DN_CPUReport
|
|
{
|
|
char vendor[4 /*bytes*/ * 3 /*EDX, ECX, EBX*/ + 1 /*null*/];
|
|
char brand[48];
|
|
DN_U64 features[(DN_CPUFeature_Count / (sizeof(DN_U64) * 8)) + 1];
|
|
};
|
|
|
|
struct DN_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
|
|
};
|
|
|
|
|
|
struct DN_Hex32 { char data[32 + 1]; DN_USize size; };
|
|
struct DN_Hex64 { char data[64 + 1]; DN_USize size; };
|
|
struct DN_Hex128 { char data[128 + 1]; DN_USize size; };
|
|
|
|
struct DN_HexU64Str8
|
|
{
|
|
char data[(sizeof(DN_U64) * 2) + 1 /*null-terminator*/];
|
|
DN_U8 size;
|
|
};
|
|
|
|
enum DN_HexFromU64Type
|
|
{
|
|
DN_HexFromU64Type_Nil,
|
|
DN_HexFromU64Type_Uppercase,
|
|
};
|
|
|
|
enum DN_TrimLeadingZero
|
|
{
|
|
DN_TrimLeadingZero_No,
|
|
DN_TrimLeadingZero_Yes,
|
|
};
|
|
|
|
struct DN_U8x16 { DN_U8 data[16]; };
|
|
struct DN_U8x32 { DN_U8 data[32]; };
|
|
struct DN_U8x64 { DN_U8 data[64]; };
|
|
|
|
DN_MSVC_WARNING_PUSH
|
|
DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
|
|
union DN_V2USize
|
|
{
|
|
struct { DN_USize x, y; };
|
|
struct { DN_USize w, h; };
|
|
struct { DN_USize min, max; };
|
|
struct { DN_USize begin, end; };
|
|
DN_USize data[2];
|
|
};
|
|
|
|
union DN_V2U64
|
|
{
|
|
struct { DN_U64 x, y; };
|
|
struct { DN_U64 w, h; };
|
|
struct { DN_U64 min, max; };
|
|
struct { DN_U64 begin, end; };
|
|
DN_U64 data[2];
|
|
};
|
|
DN_MSVC_WARNING_POP
|
|
|
|
struct DN_CallSite
|
|
{
|
|
DN_Str8 file;
|
|
DN_Str8 function;
|
|
DN_U32 line;
|
|
};
|
|
|
|
#define DN_CALL_SITE DN_CallSite { DN_Str8Lit(__FILE__), DN_Str8Lit(__func__), __LINE__ }
|
|
|
|
#if defined(__cplusplus)
|
|
template <typename Procedure>
|
|
struct DN_Defer
|
|
{
|
|
Procedure proc;
|
|
DN_Defer(Procedure p) : proc(p) {}
|
|
~DN_Defer() { proc(); }
|
|
};
|
|
|
|
struct DN_DeferHelper
|
|
{
|
|
template <typename Lambda>
|
|
DN_Defer<Lambda> operator+(Lambda lambda) { return DN_Defer<Lambda>(lambda); };
|
|
};
|
|
|
|
#define DN_UniqueName(prefix) DN_TokenCombine(prefix, __LINE__)
|
|
#define DN_DEFER const auto DN_UniqueName(defer_lambda_) = DN_DeferHelper() + [&]()
|
|
#endif // defined(__cplusplus)
|
|
|
|
#define DN_DeferLoop(begin, end) \
|
|
bool DN_UniqueName(once) = (begin, true); \
|
|
DN_UniqueName(once); \
|
|
end, DN_UniqueName(once) = false
|
|
|
|
struct DN_U64FromResult
|
|
{
|
|
bool success;
|
|
DN_U64 value;
|
|
};
|
|
|
|
struct DN_USizeFromResult
|
|
{
|
|
bool success;
|
|
DN_USize value;
|
|
};
|
|
|
|
struct DN_I64FromResult
|
|
{
|
|
bool success;
|
|
DN_I64 value;
|
|
};
|
|
|
|
struct DN_U8x32FromResult
|
|
{
|
|
bool success;
|
|
DN_U8x32 value;
|
|
};
|
|
|
|
struct DN_StackTraceFrame
|
|
{
|
|
DN_U64 address;
|
|
DN_U64 line_number;
|
|
DN_Str8 file_name;
|
|
DN_Str8 function_name;
|
|
};
|
|
|
|
struct DN_StackTraceFrameSlice
|
|
{
|
|
DN_StackTraceFrame *data;
|
|
DN_USize count;
|
|
};
|
|
|
|
struct DN_StackTraceRawFrame
|
|
{
|
|
void *process;
|
|
DN_U64 base_addr;
|
|
};
|
|
|
|
struct DN_StackTraceWalkResult
|
|
{
|
|
void *process; // [Internal] Windows handle to the process
|
|
DN_U64 *base_addr; // The addresses of the functions in the stack trace
|
|
DN_U16 size; // The number of `base_addr`'s stored from the walk
|
|
};
|
|
|
|
struct DN_StackTraceWalkResultIterator
|
|
{
|
|
DN_StackTraceRawFrame raw_frame;
|
|
DN_U16 index;
|
|
};
|
|
|
|
enum DN_MemCommit
|
|
{
|
|
DN_MemCommit_No,
|
|
DN_MemCommit_Yes,
|
|
};
|
|
|
|
typedef DN_U32 DN_MemPage;
|
|
enum DN_MemPage_
|
|
{
|
|
// Exception on read/write with a page. This flag overrides the read/write
|
|
// access.
|
|
DN_MemPage_NoAccess = 1 << 0,
|
|
|
|
DN_MemPage_Read = 1 << 1, // Only read permitted on the page.
|
|
|
|
// Only write permitted on the page. On Windows this is not supported and
|
|
// will be promoted to read+write permissions.
|
|
DN_MemPage_Write = 1 << 2,
|
|
|
|
DN_MemPage_ReadWrite = DN_MemPage_Read | DN_MemPage_Write,
|
|
|
|
// Modifier used in conjunction with previous flags. Raises exception on
|
|
// first access to the page, then, the underlying protection flags are
|
|
// active. This is supported on Windows, on other OS's using this flag will
|
|
// set the OS equivalent of DN_MemPage_NoAccess.
|
|
// This flag must only be used in DN_Mem_Protect
|
|
DN_MemPage_Guard = 1 << 3,
|
|
|
|
// If leak tracing is enabled, this flag will allow the allocation recorded
|
|
// from the reserve call to be leaked, e.g. not printed when leaks are
|
|
// dumped to the console.
|
|
DN_MemPage_AllocRecordLeakPermitted = 1 << 4,
|
|
|
|
// If leak tracing is enabled this flag will prevent any allocation record
|
|
// from being created in the allocation table at all. If this flag is
|
|
// enabled, 'OSMemPage_AllocRecordLeakPermitted' has no effect since the
|
|
// record will never be created.
|
|
DN_MemPage_NoAllocRecordEntry = 1 << 5,
|
|
|
|
// [INTERNAL] Do not use. All flags together do not constitute a correct
|
|
// configuration of pages.
|
|
DN_MemPage_All = DN_MemPage_NoAccess |
|
|
DN_MemPage_ReadWrite |
|
|
DN_MemPage_Guard |
|
|
DN_MemPage_AllocRecordLeakPermitted |
|
|
DN_MemPage_NoAllocRecordEntry,
|
|
};
|
|
|
|
#if !defined(DN_ARENA_RESERVE_SIZE)
|
|
#define DN_ARENA_RESERVE_SIZE DN_Megabytes(64)
|
|
#endif
|
|
|
|
#if !defined(DN_ARENA_COMMIT_SIZE)
|
|
#define DN_ARENA_COMMIT_SIZE DN_Kilobytes(64)
|
|
#endif
|
|
|
|
enum DN_MemFuncsType
|
|
{
|
|
DN_MemFuncsType_Nil,
|
|
DN_MemFuncsType_Heap,
|
|
DN_MemFuncsType_Virtual,
|
|
};
|
|
|
|
typedef void *(DN_MemHeapAllocFunc)(DN_USize size);
|
|
typedef void (DN_MemHeapDeallocFunc)(void *ptr);
|
|
typedef void *(DN_MemVirtualReserveFunc)(DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
|
|
typedef bool (DN_MemVirtualCommitFunc)(void *ptr, DN_USize size, DN_U32 page_flags);
|
|
typedef void (DN_MemVirtualReleaseFunc)(void *ptr, DN_USize size);
|
|
struct DN_MemFuncs
|
|
{
|
|
DN_MemFuncsType type;
|
|
DN_MemHeapAllocFunc *heap_alloc;
|
|
DN_MemHeapDeallocFunc *heap_dealloc;
|
|
|
|
DN_U32 virtual_page_size;
|
|
DN_MemVirtualReserveFunc *virtual_reserve;
|
|
DN_MemVirtualCommitFunc *virtual_commit;
|
|
DN_MemVirtualReleaseFunc *virtual_release;
|
|
};
|
|
|
|
struct DN_MemBlock
|
|
{
|
|
DN_MemBlock* prev;
|
|
DN_U64 used;
|
|
DN_U64 commit;
|
|
DN_U64 reserve;
|
|
DN_U64 reserve_sum;
|
|
};
|
|
|
|
struct DN_MemListInfo
|
|
{
|
|
DN_U64 used;
|
|
DN_U64 commit;
|
|
DN_U64 reserve;
|
|
DN_U64 blocks;
|
|
};
|
|
|
|
struct DN_MemStats
|
|
{
|
|
DN_MemListInfo info;
|
|
DN_MemListInfo hwm;
|
|
};
|
|
|
|
typedef DN_U32 DN_MemFlags;
|
|
enum DN_MemFlags_
|
|
{
|
|
DN_MemFlags_Nil = 0,
|
|
DN_MemFlags_NoGrow = 1 << 0,
|
|
DN_MemFlags_NoPoison = 1 << 1,
|
|
DN_MemFlags_NoAllocTrack = 1 << 2,
|
|
DN_MemFlags_AllocCanLeak = 1 << 3,
|
|
DN_MemFlags_SimAlloc = 1 << 4,
|
|
|
|
// NOTE: Records stack traces of temp memory regions on construction to provide more diagnostics
|
|
// when UAF violation occurs in the use of a region (e.g. nested regions A and B, with A
|
|
// allocating whilst B is active would result in A's memory being wiped at the end of B). Tracing
|
|
// has a heavy performance penalty as each scratch/temp memory region triggers and stores the
|
|
// stack trace.
|
|
//
|
|
// Ignored if UAF guard is disabled at the preprocessor level
|
|
// (e.g.: #define DN_ARENA_TEMP_MEM_UAF_GUARD 0)
|
|
DN_MemFlags_TempMemUAFTrace = 1 << 5,
|
|
|
|
// NOTE: Forcibly disables TempMemUAFTrace for the arena irrespective of global settings. Globally
|
|
// UAF tracing can be enabled across all arenas via the preprocessor which turns the tracing
|
|
// feature (e.g.: #define DN_ARENA_TEMP_MEM_UAF_TRACE_ON_BY_DEFAULT 1) into an opt-out situation
|
|
// where arenas have to specify this flag, specifically to not be traced.
|
|
//
|
|
// If both TempMemUAFTrace, TempMemUAFTraceDisable and or the global preprocessor flag is set
|
|
// disabling takes precedence, always if it is set.
|
|
DN_MemFlags_TempMemUAFTraceDisable = 1 << 6,
|
|
|
|
// NOTE: Internal flags. Do not use
|
|
DN_MemFlags_UserBuffer = 1 << 7,
|
|
DN_MemFlags_MemFuncs = 1 << 8,
|
|
};
|
|
|
|
struct DN_MemList
|
|
{
|
|
DN_MemBlock* curr;
|
|
DN_MemFlags flags;
|
|
DN_MemFuncs funcs;
|
|
DN_MemStats stats;
|
|
DN_Str8 label;
|
|
|
|
#if DN_ARENA_TEMP_MEM_UAF_GUARD
|
|
DN_U32 uaf_guard_next_id;
|
|
DN_U32 uaf_guard_active_id;
|
|
struct DN_MemListTemp* uaf_guard_active_temp_mem;
|
|
#endif
|
|
};
|
|
|
|
struct DN_MemListTemp
|
|
{
|
|
DN_MemList* mem;
|
|
DN_U64 used_sum;
|
|
#if DN_ARENA_TEMP_MEM_UAF_GUARD
|
|
DN_StackTraceWalkResult trace;
|
|
#endif
|
|
};
|
|
|
|
enum DN_AllocatorType
|
|
{
|
|
DN_AllocatorType_Arena,
|
|
DN_AllocatorType_Pool,
|
|
};
|
|
|
|
struct DN_Allocator
|
|
{
|
|
DN_AllocatorType type;
|
|
void* context;
|
|
};
|
|
|
|
struct DN_ArenaStatsStr8x64
|
|
{
|
|
DN_Str8x64 info;
|
|
DN_Str8x64 hwm;
|
|
};
|
|
|
|
enum DN_ArenaReset
|
|
{
|
|
DN_ArenaReset_No,
|
|
DN_ArenaReset_Yes,
|
|
};
|
|
|
|
struct DN_Arena
|
|
{
|
|
DN_MemList* mem;
|
|
#if DN_ARENA_TEMP_MEM_UAF_GUARD
|
|
DN_U32 uaf_guard_id;
|
|
DN_MemListTemp* uaf_guard_temp_mem;
|
|
DN_U32 uaf_guard_prev_id;
|
|
DN_MemListTemp* uaf_guard_prev_temp_mem;
|
|
bool uaf_guard_is_being_checked;
|
|
#else
|
|
DN_MemListTemp temp_mem;
|
|
#endif
|
|
};
|
|
|
|
DN_USize const DN_ARENA_HEADER_SIZE = DN_AlignUpPowerOfTwo(sizeof(DN_Arena), 64);
|
|
|
|
#if !defined(DN_POOL_DEFAULT_ALIGN)
|
|
#define DN_POOL_DEFAULT_ALIGN 16
|
|
#endif
|
|
|
|
struct DN_PoolSlot
|
|
{
|
|
void *data;
|
|
DN_PoolSlot *next;
|
|
};
|
|
|
|
enum DN_PoolSlotSize
|
|
{
|
|
DN_PoolSlotSize_32B,
|
|
DN_PoolSlotSize_64B,
|
|
DN_PoolSlotSize_128B,
|
|
DN_PoolSlotSize_256B,
|
|
DN_PoolSlotSize_512B,
|
|
DN_PoolSlotSize_1KiB,
|
|
DN_PoolSlotSize_2KiB,
|
|
DN_PoolSlotSize_4KiB,
|
|
DN_PoolSlotSize_8KiB,
|
|
DN_PoolSlotSize_16KiB,
|
|
DN_PoolSlotSize_32KiB,
|
|
DN_PoolSlotSize_64KiB,
|
|
DN_PoolSlotSize_128KiB,
|
|
DN_PoolSlotSize_256KiB,
|
|
DN_PoolSlotSize_512KiB,
|
|
DN_PoolSlotSize_1MiB,
|
|
DN_PoolSlotSize_2MiB,
|
|
DN_PoolSlotSize_4MiB,
|
|
DN_PoolSlotSize_8MiB,
|
|
DN_PoolSlotSize_16MiB,
|
|
DN_PoolSlotSize_32MiB,
|
|
DN_PoolSlotSize_64MiB,
|
|
DN_PoolSlotSize_128MiB,
|
|
DN_PoolSlotSize_256MiB,
|
|
DN_PoolSlotSize_512MiB,
|
|
DN_PoolSlotSize_1GiB,
|
|
DN_PoolSlotSize_2GiB,
|
|
DN_PoolSlotSize_4GiB,
|
|
DN_PoolSlotSize_8GiB,
|
|
DN_PoolSlotSize_16GiB,
|
|
DN_PoolSlotSize_32GiB,
|
|
DN_PoolSlotSize_Count,
|
|
};
|
|
|
|
struct DN_Pool
|
|
{
|
|
DN_Arena *arena;
|
|
DN_PoolSlot *slots[DN_PoolSlotSize_Count];
|
|
DN_U8 align;
|
|
};
|
|
|
|
struct DN_UTF8DecodeResult
|
|
{
|
|
bool success;
|
|
DN_Str8 remaining;
|
|
DN_U32 codepoint;
|
|
};
|
|
|
|
struct DN_UTF8DecodeIterator
|
|
{
|
|
bool init;
|
|
bool success;
|
|
DN_Str8 remaining;
|
|
DN_USize codepoint_index;
|
|
DN_U32 codepoint;
|
|
};
|
|
|
|
typedef DN_U32 DN_CodepointCountFlags;
|
|
enum DN_CodepointCountFlags_
|
|
{
|
|
DN_CodepointCountFlags_Nil = 0,
|
|
DN_CodepointCountFlags_SkipANSICode = 1 << 0,
|
|
};
|
|
|
|
struct DN_NibbleFromU8Result
|
|
{
|
|
char nibble0;
|
|
char nibble1;
|
|
};
|
|
|
|
enum DN_Str8EqCase
|
|
{
|
|
DN_Str8EqCase_Sensitive,
|
|
DN_Str8EqCase_Insensitive,
|
|
};
|
|
|
|
enum DN_Str8IsAllType
|
|
{
|
|
DN_Str8IsAllType_Digits,
|
|
DN_Str8IsAllType_Hex,
|
|
};
|
|
|
|
struct DN_Str8BSplitResult
|
|
{
|
|
// If there are multiple strings passed to split against, this is the index into that array of
|
|
// which the string was split on. If no array was passed this is always 0.
|
|
DN_USize input_index;
|
|
DN_Str8 lhs;
|
|
DN_Str8 rhs;
|
|
};
|
|
|
|
struct DN_Str8FindResult
|
|
{
|
|
bool found; // True if string was found. If false, the subsequent fields below are not set.
|
|
DN_USize index; // Index in the buffer where the found string starts
|
|
DN_Str8 match; // Matching string in the buffer that was searched
|
|
DN_Str8 match_to_end_of_buffer; // Substring containing the found string to the end of the buffer
|
|
DN_Str8 after_match_to_end_of_buffer; // Substring starting after the found string to the end of the buffer
|
|
DN_Str8 start_to_before_match; // Substring from the start of the buffer up until the found string, not including it
|
|
};
|
|
|
|
typedef DN_USize DN_Str8FindFlag;
|
|
enum DN_Str8FindFlag_
|
|
{
|
|
DN_Str8FindFlag_Digit = 1 << 0, // 0-9
|
|
DN_Str8FindFlag_Whitespace = 1 << 1, // '\r', '\t', '\n', ' '
|
|
DN_Str8FindFlag_Alphabet = 1 << 2, // A-Z, a-z
|
|
DN_Str8FindFlag_Plus = 1 << 3, // +
|
|
DN_Str8FindFlag_Minus = 1 << 4, // -
|
|
DN_Str8FindFlag_AlphaNum = DN_Str8FindFlag_Alphabet | DN_Str8FindFlag_Digit,
|
|
};
|
|
|
|
typedef DN_USize DN_Str8SplitFlags;
|
|
enum DN_Str8SplitFlags_
|
|
{
|
|
DN_Str8SplitFlags_ExcludeEmptyStrings = 1 << 0,
|
|
DN_Str8SplitFlags_HandleQuotedStrings = 1 << 1,
|
|
};
|
|
|
|
struct DN_Str8TruncResult
|
|
{
|
|
bool truncated;
|
|
DN_Str8 str8;
|
|
DN_USize size_req; // Not including null-terminator
|
|
};
|
|
|
|
struct DN_Str8SplitResult
|
|
{
|
|
DN_Str8 *data;
|
|
DN_USize count;
|
|
};
|
|
|
|
typedef DN_USize DN_Str8TableFlags;
|
|
enum DN_Str8TableFlags_
|
|
{
|
|
DN_Str8TableFlags_None = 0,
|
|
DN_Str8TableFlags_HasHeader = 1 << 0,
|
|
DN_Str8TableFlags_RowLines = 1 << 1,
|
|
};
|
|
|
|
struct DN_Str8Link
|
|
{
|
|
DN_Str8 string; // The string
|
|
DN_Str8Link *next; // The next string in the linked list
|
|
DN_Str8Link *prev; // The prev string in the linked list
|
|
};
|
|
|
|
struct DN_Str8Builder
|
|
{
|
|
DN_Arena* arena; // Allocator to use to back the string list
|
|
DN_Str8Link* head; // First string in the linked list of strings
|
|
DN_Str8Link* tail; // Last string in the linked list of strings
|
|
DN_USize string_size; // The size in bytes necessary to construct the current string
|
|
DN_USize count; // The number of links in the linked list of strings
|
|
};
|
|
|
|
enum DN_Str8BuilderAdd
|
|
{
|
|
DN_Str8BuilderAdd_Append,
|
|
DN_Str8BuilderAdd_Prepend,
|
|
};
|
|
|
|
typedef DN_U32 DN_AgeUnit;
|
|
enum DN_AgeUnit_
|
|
{
|
|
DN_AgeUnit_Ms = 1 << 0,
|
|
DN_AgeUnit_Sec = 1 << 1,
|
|
DN_AgeUnit_Min = 1 << 2,
|
|
DN_AgeUnit_Hr = 1 << 3,
|
|
DN_AgeUnit_Day = 1 << 4,
|
|
DN_AgeUnit_Week = 1 << 5,
|
|
DN_AgeUnit_Year = 1 << 6,
|
|
DN_AgeUnit_FractionalSec = 1 << 7,
|
|
DN_AgeUnit_HMS = DN_AgeUnit_Sec | DN_AgeUnit_Min | DN_AgeUnit_Hr,
|
|
DN_AgeUnit_All = DN_AgeUnit_Ms | DN_AgeUnit_HMS | DN_AgeUnit_Day | DN_AgeUnit_Week | DN_AgeUnit_Year,
|
|
};
|
|
|
|
enum DN_ByteCountType
|
|
{
|
|
DN_ByteCountType_B,
|
|
DN_ByteCountType_KiB,
|
|
DN_ByteCountType_MiB,
|
|
DN_ByteCountType_GiB,
|
|
DN_ByteCountType_TiB,
|
|
DN_ByteCountType_Count,
|
|
DN_ByteCountType_Auto,
|
|
};
|
|
|
|
struct DN_ByteCountResult
|
|
{
|
|
DN_ByteCountType type;
|
|
DN_Str8 suffix; // "KiB", "MiB", "GiB" .. e.t.c
|
|
DN_F64 bytes;
|
|
};
|
|
|
|
struct DN_Date
|
|
{
|
|
DN_U8 day;
|
|
DN_U8 month;
|
|
DN_U16 year;
|
|
DN_U8 hour;
|
|
DN_U8 minutes;
|
|
DN_U8 seconds;
|
|
DN_U16 milliseconds;
|
|
};
|
|
|
|
struct DN_FmtAppendResult
|
|
{
|
|
DN_USize size_req;
|
|
DN_Str8 str8;
|
|
bool truncated;
|
|
};
|
|
|
|
struct DN_ProfilerAnchor
|
|
{
|
|
// Inclusive refers to the time spent to complete the function call
|
|
// including all children functions.
|
|
//
|
|
// Exclusive refers to the time spent in the function, not including any
|
|
// time spent in children functions that we call that are also being
|
|
// profiled. If we recursively call into ourselves, the time we spent in
|
|
// our function is accumulated.
|
|
DN_U64 tsc_inclusive;
|
|
DN_U64 tsc_exclusive;
|
|
DN_U16 hit_count;
|
|
DN_Str8 name;
|
|
};
|
|
|
|
struct DN_ProfilerZone
|
|
{
|
|
DN_U16 anchor_index;
|
|
DN_U64 begin_tsc;
|
|
DN_U16 parent_zone;
|
|
DN_U64 elapsed_tsc_at_zone_start;
|
|
};
|
|
|
|
struct DN_ProfilerAnchorArray
|
|
{
|
|
DN_ProfilerAnchor *data;
|
|
DN_USize count;
|
|
};
|
|
|
|
typedef DN_U64 (DN_ProfilerTSCNowFunc)();
|
|
struct DN_Profiler
|
|
{
|
|
DN_USize frame_index;
|
|
DN_ProfilerAnchor *anchors;
|
|
DN_USize anchors_count;
|
|
DN_USize anchors_per_frame;
|
|
DN_U16 parent_zone;
|
|
bool paused;
|
|
DN_ProfilerTSCNowFunc *tsc_now;
|
|
DN_U64 tsc_frequency;
|
|
DN_ProfilerZone frame_zone;
|
|
DN_F64 frame_avg_tsc;
|
|
};
|
|
|
|
enum DN_ErrSinkMode
|
|
{
|
|
DN_ErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink
|
|
DN_ErrSinkMode_DebugBreakOnErrorLog, // Debug break (int3) when error is encountered and the sink is ended by the 'end and log' functions.
|
|
DN_ErrSinkMode_ExitOnError, // When an error is encountered, exit the program with the error code of the error that was caught.
|
|
};
|
|
|
|
struct DN_ErrSinkMsg
|
|
{
|
|
DN_I32 error_code;
|
|
DN_Str8 msg;
|
|
DN_CallSite call_site;
|
|
DN_ErrSinkMsg *next;
|
|
DN_ErrSinkMsg *prev;
|
|
};
|
|
|
|
struct DN_ErrSinkNode
|
|
{
|
|
DN_CallSite call_site; // Call site that the node was created
|
|
DN_ErrSinkMode mode; // Controls how the sink behaves when an error is registered onto the sink.
|
|
DN_ErrSinkMsg *msg_sentinel; // List of error messages accumulated for the current scope
|
|
DN_U64 arena_pos; // Position to reset the arena when the scope is ended
|
|
};
|
|
|
|
struct DN_ErrSink
|
|
{
|
|
DN_Arena* arena; // Dedicated allocator from the thread's local storage
|
|
DN_ErrSinkNode stack[128]; // Each entry contains errors accumulated between a [begin, end] region of the active sink.
|
|
DN_USize stack_size;
|
|
};
|
|
|
|
struct DN_TCScratch
|
|
{
|
|
DN_Arena arena;
|
|
DN_B32 destructed;
|
|
};
|
|
|
|
#if defined(__cplusplus)
|
|
struct DN_TCScratchCpp
|
|
{
|
|
DN_TCScratchCpp(DN_Arena **conflicts, DN_USize count);
|
|
~DN_TCScratchCpp();
|
|
DN_TCScratch data;
|
|
};
|
|
#endif
|
|
|
|
struct DN_TCInitArgs
|
|
{
|
|
DN_U64 main_reserve;
|
|
DN_U64 main_commit;
|
|
DN_U64 temp_reserve;
|
|
DN_U64 temp_commit;
|
|
DN_U64 err_sink_reserve;
|
|
DN_U64 err_sink_commit;
|
|
};
|
|
|
|
struct DN_TCCore // (T)hread (C)ontext sitting in thread-local storage
|
|
{
|
|
DN_Str8x64 name;
|
|
DN_U64 thread_id;
|
|
DN_CallSite call_site;
|
|
char lane_opaque[sizeof(DN_U64) * 4];
|
|
|
|
DN_MemList main_arena_mem_;
|
|
DN_MemList temp_a_arena_mem_;
|
|
DN_MemList temp_b_arena_mem_;
|
|
DN_MemList err_sink_arena_mem_;
|
|
|
|
DN_Arena main_arena_;
|
|
DN_Arena temp_a_arena_;
|
|
DN_Arena temp_b_arena_;
|
|
DN_Arena err_sink_arena_;
|
|
|
|
DN_Arena* main_arena;
|
|
DN_Pool main_pool;
|
|
DN_Arena* temp_a_arena;
|
|
DN_Arena* temp_b_arena;
|
|
|
|
DN_ErrSink err_sink;
|
|
|
|
DN_Arena* frame_arena;
|
|
};
|
|
|
|
enum DN_TCDeinitArenas
|
|
{
|
|
DN_TCDeinitArenas_No,
|
|
DN_TCDeinitArenas_Yes,
|
|
};
|
|
|
|
struct DN_PCG32 { DN_U64 state; };
|
|
struct DN_MurmurHash3 { DN_U64 e[2]; };
|
|
|
|
enum DN_LogType
|
|
{
|
|
DN_LogType_Debug,
|
|
DN_LogType_Info,
|
|
DN_LogType_Warning,
|
|
DN_LogType_Error,
|
|
DN_LogType_Count,
|
|
};
|
|
|
|
enum DN_LogBold
|
|
{
|
|
DN_LogBold_No,
|
|
DN_LogBold_Yes,
|
|
};
|
|
|
|
struct DN_LogStyle
|
|
{
|
|
DN_LogBold bold;
|
|
bool colour;
|
|
DN_U8 r, g, b;
|
|
};
|
|
|
|
struct DN_LogTypeParam
|
|
{
|
|
bool is_u32_enum;
|
|
DN_U32 u32;
|
|
DN_Str8 str8;
|
|
};
|
|
|
|
enum DN_ANSIColourMode
|
|
{
|
|
DN_ANSIColourMode_Fg,
|
|
DN_ANSIColourMode_Bg,
|
|
};
|
|
|
|
struct DN_LogDate
|
|
{
|
|
DN_U16 year;
|
|
DN_U8 month;
|
|
DN_U8 day;
|
|
|
|
DN_U8 hour;
|
|
DN_U8 minute;
|
|
DN_U8 second;
|
|
};
|
|
|
|
struct DN_LogPrefixSize
|
|
{
|
|
DN_USize size;
|
|
DN_USize padding;
|
|
};
|
|
|
|
typedef DN_U32 DN_LogFlags;
|
|
enum DN_LogFlags_
|
|
{
|
|
DN_LogFlags_Nil = 0,
|
|
DN_LogFlags_NoNewLine = 1 << 0,
|
|
DN_LogFlags_NoPrefix = 1 << 1,
|
|
};
|
|
|
|
typedef void DN_LogPrintFunc(DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_LogFlags flags, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
|
|
DN_MSVC_WARNING_PUSH
|
|
DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
|
|
union DN_V2I32
|
|
{
|
|
struct { DN_I32 x, y; };
|
|
struct { DN_I32 w, h; };
|
|
DN_I32 data[2];
|
|
};
|
|
|
|
union DN_V2U16
|
|
{
|
|
struct { DN_U16 x, y; };
|
|
struct { DN_U16 w, h; };
|
|
DN_U16 data[2];
|
|
};
|
|
|
|
union DN_V2U32
|
|
{
|
|
struct { DN_U32 x, y; };
|
|
struct { DN_U32 w, h; };
|
|
struct { DN_U32 min, max; };
|
|
DN_U32 data[2];
|
|
};
|
|
|
|
union DN_V2F32
|
|
{
|
|
struct { DN_F32 x, y; };
|
|
struct { DN_F32 w, h; };
|
|
DN_F32 data[2];
|
|
};
|
|
|
|
struct DN_2V2F32
|
|
{
|
|
DN_V2F32 min;
|
|
DN_V2F32 max;
|
|
};
|
|
|
|
struct DN_V2F32Array
|
|
{
|
|
DN_V2F32 *data;
|
|
DN_USize count;
|
|
DN_USize max;
|
|
};
|
|
|
|
union DN_V3F32
|
|
{
|
|
struct { DN_F32 x, y, z; };
|
|
struct { DN_F32 r, g, b; };
|
|
DN_V2F32 xy;
|
|
DN_F32 data[3];
|
|
};
|
|
|
|
union DN_V4F32
|
|
{
|
|
struct { DN_F32 x, y, z, w; };
|
|
struct { DN_F32 r, g, b, a; };
|
|
DN_V3F32 rgb;
|
|
DN_V3F32 xyz;
|
|
DN_F32 data[4];
|
|
};
|
|
|
|
struct DN_V4F32Array
|
|
{
|
|
DN_V4F32* data;
|
|
DN_USize count;
|
|
DN_USize max;
|
|
};
|
|
DN_MSVC_WARNING_POP
|
|
|
|
struct DN_M4
|
|
{
|
|
DN_F32 columns[4][4]; // Column major matrix
|
|
};
|
|
|
|
union DN_M2x3
|
|
{
|
|
DN_F32 e[6];
|
|
DN_F32 row[2][3];
|
|
};
|
|
|
|
struct DN_M2x3XForm
|
|
{
|
|
DN_M2x3 forward;
|
|
DN_M2x3 inverse;
|
|
};
|
|
|
|
enum DN_M2x3ProjOrigin
|
|
{
|
|
DN_M2x3ProjOrigin_TopLeft,
|
|
DN_M2x3ProjOrigin_Center,
|
|
};
|
|
|
|
struct DN_Rect
|
|
{
|
|
DN_V2F32 pos, size;
|
|
};
|
|
|
|
enum DN_RectCutClip
|
|
{
|
|
DN_RectCutClip_No,
|
|
DN_RectCutClip_Yes,
|
|
};
|
|
|
|
enum DN_RectCutSide
|
|
{
|
|
DN_RectCutSide_Left,
|
|
DN_RectCutSide_Right,
|
|
DN_RectCutSide_Top,
|
|
DN_RectCutSide_Bottom,
|
|
};
|
|
|
|
struct DN_RectCut
|
|
{
|
|
DN_Rect* rect;
|
|
DN_RectCutSide side;
|
|
};
|
|
|
|
struct DN_RaycastV2
|
|
{
|
|
bool hit; // True if there was an intersection, false if the lines are parallel
|
|
DN_F32 t_a; // Distance along `dir_a` that the intersection occurred, e.g. `origin_a + (dir_a * t_a)`
|
|
DN_F32 t_b; // Distance along `dir_b` that the intersection occurred, e.g. `origin_b + (dir_b * t_b)`
|
|
};
|
|
|
|
#if !defined(DN_STB_SPRINTF_HEADER_ONLY)
|
|
#define STB_SPRINTF_IMPLEMENTATION
|
|
#define STB_SPRINTF_STATIC
|
|
#endif
|
|
|
|
DN_MSVC_WARNING_PUSH
|
|
DN_MSVC_WARNING_DISABLE(4505) // Unused function warning
|
|
DN_GCC_WARNING_PUSH
|
|
DN_GCC_WARNING_DISABLE(-Wunused-function)
|
|
// DN: Single header generator commented out => #include "../External/stb_sprintf.h"
|
|
// NOTE: Additional *unofficial* changes
|
|
// - Adding STBSP__ASAN to STBSP__PUBLICDEC so that MSVC's ASAN does not trigger (https://github.com/nothings/stb/pull/1350)
|
|
// - Adding __attribute__((no_sanitize("undefined"))) to STBSP__ASAN for CLANG so that UBSAN does not trigger (https://github.com/nothings/stb/pull/1477)
|
|
// - Adding '%S' for DN_Str8
|
|
// - Using defined(__wasm64__) to correctly assign stbsp__uintptr to stbsp__uint64 for a 64bit WASM target.
|
|
|
|
// stb_sprintf - v1.10 - public domain snprintf() implementation
|
|
// originally by Jeff Roberts / RAD Game Tools, 2015/10/20
|
|
// http://github.com/nothings/stb
|
|
//
|
|
// allowed types: sc uidBboXx p AaGgEef n
|
|
// lengths : hh h ll j z t I64 I32 I
|
|
//
|
|
// Contributors:
|
|
// Fabian "ryg" Giesen (reformatting)
|
|
// github:aganm (attribute format)
|
|
//
|
|
// Contributors (bugfixes):
|
|
// github:d26435
|
|
// github:trex78
|
|
// github:account-login
|
|
// Jari Komppa (SI suffixes)
|
|
// Rohit Nirmal
|
|
// Marcin Wojdyr
|
|
// Leonard Ritter
|
|
// Stefano Zanotti
|
|
// Adam Allison
|
|
// Arvid Gerstmann
|
|
// Markus Kolb
|
|
//
|
|
// LICENSE:
|
|
//
|
|
// See end of file for license information.
|
|
|
|
#ifndef STB_SPRINTF_H_INCLUDE
|
|
#define STB_SPRINTF_H_INCLUDE
|
|
|
|
/*
|
|
Single file sprintf replacement.
|
|
|
|
Originally written by Jeff Roberts at RAD Game Tools - 2015/10/20.
|
|
Hereby placed in public domain.
|
|
|
|
This is a full sprintf replacement that supports everything that
|
|
the C runtime sprintfs support, including float/double, 64-bit integers,
|
|
hex floats, field parameters (%*.*d stuff), length reads backs, etc.
|
|
|
|
Why would you need this if sprintf already exists? Well, first off,
|
|
it's *much* faster (see below). It's also much smaller than the CRT
|
|
versions code-space-wise. We've also added some simple improvements
|
|
that are super handy (commas in thousands, callbacks at buffer full,
|
|
for example). Finally, the format strings for MSVC and GCC differ
|
|
for 64-bit integers (among other small things), so this lets you use
|
|
the same format strings in cross platform code.
|
|
|
|
It uses the standard single file trick of being both the header file
|
|
and the source itself. If you just include it normally, you just get
|
|
the header file function definitions. To get the code, you include
|
|
it from a C or C++ file and define STB_SPRINTF_IMPLEMENTATION first.
|
|
|
|
It only uses va_args macros from the C runtime to do it's work. It
|
|
does cast doubles to S64s and shifts and divides U64s, which does
|
|
drag in CRT code on most platforms.
|
|
|
|
It compiles to roughly 8K with float support, and 4K without.
|
|
As a comparison, when using MSVC static libs, calling sprintf drags
|
|
in 16K.
|
|
|
|
API:
|
|
====
|
|
int stbsp_sprintf( char * buf, char const * fmt, ... )
|
|
int stbsp_snprintf( char * buf, int count, char const * fmt, ... )
|
|
Convert an arg list into a buffer. stbsp_snprintf always returns
|
|
a zero-terminated string (unlike regular snprintf).
|
|
|
|
int stbsp_vsprintf( char * buf, char const * fmt, va_list va )
|
|
int stbsp_vsnprintf( char * buf, int count, char const * fmt, va_list va )
|
|
Convert a va_list arg list into a buffer. stbsp_vsnprintf always returns
|
|
a zero-terminated string (unlike regular snprintf).
|
|
|
|
int stbsp_vsprintfcb( STBSP_SPRINTFCB * callback, void * user, char * buf, char const * fmt, va_list va )
|
|
typedef char * STBSP_SPRINTFCB( char const * buf, void * user, int len );
|
|
Convert into a buffer, calling back every STB_SPRINTF_MIN chars.
|
|
Your callback can then copy the chars out, print them or whatever.
|
|
This function is actually the workhorse for everything else.
|
|
The buffer you pass in must hold at least STB_SPRINTF_MIN characters.
|
|
// you return the next buffer to use or 0 to stop converting
|
|
|
|
void stbsp_set_separators( char comma, char period )
|
|
Set the comma and period characters to use.
|
|
|
|
FLOATS/DOUBLES:
|
|
===============
|
|
This code uses a internal float->ascii conversion method that uses
|
|
doubles with error correction (double-doubles, for ~105 bits of
|
|
precision). This conversion is round-trip perfect - that is, an atof
|
|
of the values output here will give you the bit-exact double back.
|
|
|
|
One difference is that our insignificant digits will be different than
|
|
with MSVC or GCC (but they don't match each other either). We also
|
|
don't attempt to find the minimum length matching float (pre-MSVC15
|
|
doesn't either).
|
|
|
|
If you don't need float or doubles at all, define STB_SPRINTF_NOFLOAT
|
|
and you'll save 4K of code space.
|
|
|
|
64-BIT INTS:
|
|
============
|
|
This library also supports 64-bit integers and you can use MSVC style or
|
|
GCC style indicators (%I64d or %lld). It supports the C99 specifiers
|
|
for size_t and ptr_diff_t (%jd %zd) as well.
|
|
|
|
EXTRAS:
|
|
=======
|
|
Like some GCCs, for integers and floats, you can use a ' (single quote)
|
|
specifier and commas will be inserted on the thousands: "%'d" on 12345
|
|
would print 12,345.
|
|
|
|
For integers and floats, you can use a "$" specifier and the number
|
|
will be converted to float and then divided to get kilo, mega, giga or
|
|
tera and then printed, so "%$d" 1000 is "1.0 k", "%$.2d" 2536000 is
|
|
"2.53 M", etc. For byte values, use two $:s, like "%$$d" to turn
|
|
2536000 to "2.42 Mi". If you prefer JEDEC suffixes to SI ones, use three
|
|
$:s: "%$$$d" -> "2.42 M". To remove the space between the number and the
|
|
suffix, add "_" specifier: "%_$d" -> "2.53M".
|
|
|
|
In addition to octal and hexadecimal conversions, you can print
|
|
integers in binary: "%b" for 256 would print 100.
|
|
|
|
PERFORMANCE vs MSVC 2008 32-/64-bit (GCC is even slower than MSVC):
|
|
===================================================================
|
|
"%d" across all 32-bit ints (4.8x/4.0x faster than 32-/64-bit MSVC)
|
|
"%24d" across all 32-bit ints (4.5x/4.2x faster)
|
|
"%x" across all 32-bit ints (4.5x/3.8x faster)
|
|
"%08x" across all 32-bit ints (4.3x/3.8x faster)
|
|
"%f" across e-10 to e+10 floats (7.3x/6.0x faster)
|
|
"%e" across e-10 to e+10 floats (8.1x/6.0x faster)
|
|
"%g" across e-10 to e+10 floats (10.0x/7.1x faster)
|
|
"%f" for values near e-300 (7.9x/6.5x faster)
|
|
"%f" for values near e+300 (10.0x/9.1x faster)
|
|
"%e" for values near e-300 (10.1x/7.0x faster)
|
|
"%e" for values near e+300 (9.2x/6.0x faster)
|
|
"%.320f" for values near e-300 (12.6x/11.2x faster)
|
|
"%a" for random values (8.6x/4.3x faster)
|
|
"%I64d" for 64-bits with 32-bit values (4.8x/3.4x faster)
|
|
"%I64d" for 64-bits > 32-bit values (4.9x/5.5x faster)
|
|
"%s%s%s" for 64 char strings (7.1x/7.3x faster)
|
|
"...512 char string..." ( 35.0x/32.5x faster!)
|
|
*/
|
|
|
|
#if defined(__clang__)
|
|
#if defined(__has_feature) && defined(__has_attribute)
|
|
#if __has_feature(address_sanitizer)
|
|
#if __has_attribute(__no_sanitize__)
|
|
#define STBSP__ASAN __attribute__((__no_sanitize__("address")))
|
|
#elif __has_attribute(__no_sanitize_address__)
|
|
#define STBSP__ASAN __attribute__((__no_sanitize_address__))
|
|
#elif __has_attribute(__no_address_safety_analysis__)
|
|
#define STBSP__ASAN __attribute__((__no_address_safety_analysis__))
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
|
|
#if defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__
|
|
#define STBSP__ASAN __attribute__((__no_sanitize_address__))
|
|
#endif
|
|
#elif defined(_MSC_VER)
|
|
#if defined(__SANITIZE_ADDRESS__)
|
|
#define STBSP__ASAN __declspec(no_sanitize_address)
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef STBSP__ASAN
|
|
#define STBSP__ASAN
|
|
#endif
|
|
|
|
#ifdef STB_SPRINTF_STATIC
|
|
#define STBSP__PUBLICDEC static STBSP__ASAN
|
|
#define STBSP__PUBLICDEF static STBSP__ASAN
|
|
#else
|
|
#ifdef __cplusplus
|
|
#define STBSP__PUBLICDEC extern "C" STBSP__ASAN
|
|
#define STBSP__PUBLICDEF extern "C" STBSP__ASAN
|
|
#else
|
|
#define STBSP__PUBLICDEC extern STBSP__ASAN
|
|
#define STBSP__PUBLICDEF STBSP__ASAN
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(__has_attribute)
|
|
#if __has_attribute(format)
|
|
#define STBSP__ATTRIBUTE_FORMAT(fmt,va) __attribute__((format(printf,fmt,va)))
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef STBSP__ATTRIBUTE_FORMAT
|
|
#define STBSP__ATTRIBUTE_FORMAT(fmt,va)
|
|
#endif
|
|
|
|
#ifdef _MSC_VER
|
|
#define STBSP__NOTUSED(v) (void)(v)
|
|
#else
|
|
#define STBSP__NOTUSED(v) (void)sizeof(v)
|
|
#endif
|
|
|
|
#include <stdarg.h> // for va_arg(), va_list()
|
|
#include <stddef.h> // size_t, ptrdiff_t
|
|
|
|
#ifndef STB_SPRINTF_MIN
|
|
#define STB_SPRINTF_MIN 512 // how many characters per callback
|
|
#endif
|
|
typedef char *STBSP_SPRINTFCB(const char *buf, void *user, int len);
|
|
|
|
#ifndef STB_SPRINTF_DECORATE
|
|
#define STB_SPRINTF_DECORATE(name) stbsp_##name // define this before including if you want to change the names
|
|
#endif
|
|
|
|
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va);
|
|
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsnprintf)(char *buf, int count, char const *fmt, va_list va);
|
|
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(2,3);
|
|
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...) STBSP__ATTRIBUTE_FORMAT(3,4);
|
|
|
|
STBSP__PUBLICDEC int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va);
|
|
STBSP__PUBLICDEC void STB_SPRINTF_DECORATE(set_separators)(char comma, char period);
|
|
|
|
#endif // STB_SPRINTF_H_INCLUDE
|
|
|
|
#ifdef STB_SPRINTF_IMPLEMENTATION
|
|
|
|
#define stbsp__uint32 unsigned int
|
|
#define stbsp__int32 signed int
|
|
|
|
#ifdef _MSC_VER
|
|
#define stbsp__uint64 unsigned __int64
|
|
#define stbsp__int64 signed __int64
|
|
#else
|
|
#define stbsp__uint64 unsigned long long
|
|
#define stbsp__int64 signed long long
|
|
#endif
|
|
#define stbsp__uint16 unsigned short
|
|
|
|
#ifndef stbsp__uintptr
|
|
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__aarch64__) || defined(_M_X64) || defined(__x86_64__) || defined(__x86_64) || defined(__s390x__) || defined(__wasm64__)
|
|
#define stbsp__uintptr stbsp__uint64
|
|
#else
|
|
#define stbsp__uintptr stbsp__uint32
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef STB_SPRINTF_MSVC_MODE // used for MSVC2013 and earlier (MSVC2015 matches GCC)
|
|
#if defined(_MSC_VER) && (_MSC_VER < 1900)
|
|
#define STB_SPRINTF_MSVC_MODE
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef STB_SPRINTF_NOUNALIGNED // define this before inclusion to force stbsp_sprintf to always use aligned accesses
|
|
#define STBSP__UNALIGNED(code)
|
|
#else
|
|
#define STBSP__UNALIGNED(code) code
|
|
#endif
|
|
|
|
#ifndef STB_SPRINTF_NOFLOAT
|
|
// internal float utility functions
|
|
static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits);
|
|
static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value);
|
|
#define STBSP__SPECIAL 0x7000
|
|
#endif
|
|
|
|
static char stbsp__period = '.';
|
|
static char stbsp__comma = ',';
|
|
static struct
|
|
{
|
|
short temp; // force next field to be 2-byte aligned
|
|
char pair[201];
|
|
} stbsp__digitpair =
|
|
{
|
|
0,
|
|
"00010203040506070809101112131415161718192021222324"
|
|
"25262728293031323334353637383940414243444546474849"
|
|
"50515253545556575859606162636465666768697071727374"
|
|
"75767778798081828384858687888990919293949596979899"
|
|
};
|
|
|
|
STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char pcomma, char pperiod)
|
|
{
|
|
stbsp__period = pperiod;
|
|
stbsp__comma = pcomma;
|
|
}
|
|
|
|
#define STBSP__LEFTJUST 1
|
|
#define STBSP__LEADINGPLUS 2
|
|
#define STBSP__LEADINGSPACE 4
|
|
#define STBSP__LEADING_0X 8
|
|
#define STBSP__LEADINGZERO 16
|
|
#define STBSP__INTMAX 32
|
|
#define STBSP__TRIPLET_COMMA 64
|
|
#define STBSP__NEGATIVE 128
|
|
#define STBSP__METRIC_SUFFIX 256
|
|
#define STBSP__HALFWIDTH 512
|
|
#define STBSP__METRIC_NOSPACE 1024
|
|
#define STBSP__METRIC_1024 2048
|
|
#define STBSP__METRIC_JEDEC 4096
|
|
|
|
static void stbsp__lead_sign(stbsp__uint32 fl, char *sign)
|
|
{
|
|
sign[0] = 0;
|
|
if (fl & STBSP__NEGATIVE) {
|
|
sign[0] = 1;
|
|
sign[1] = '-';
|
|
} else if (fl & STBSP__LEADINGSPACE) {
|
|
sign[0] = 1;
|
|
sign[1] = ' ';
|
|
} else if (fl & STBSP__LEADINGPLUS) {
|
|
sign[0] = 1;
|
|
sign[1] = '+';
|
|
}
|
|
}
|
|
|
|
static STBSP__ASAN stbsp__uint32 stbsp__strlen_limited(char const *s, stbsp__uint32 limit)
|
|
{
|
|
char const * sn = s;
|
|
|
|
// get up to 4-byte alignment
|
|
for (;;) {
|
|
if (((stbsp__uintptr)sn & 3) == 0)
|
|
break;
|
|
|
|
if (!limit || *sn == 0)
|
|
return (stbsp__uint32)(sn - s);
|
|
|
|
++sn;
|
|
--limit;
|
|
}
|
|
|
|
// scan over 4 bytes at a time to find terminating 0
|
|
// this will intentionally scan up to 3 bytes past the end of buffers,
|
|
// but becase it works 4B aligned, it will never cross page boundaries
|
|
// (hence the STBSP__ASAN markup; the over-read here is intentional
|
|
// and harmless)
|
|
while (limit >= 4) {
|
|
stbsp__uint32 v = *(stbsp__uint32 *)sn;
|
|
// bit hack to find if there's a 0 byte in there
|
|
if ((v - 0x01010101) & (~v) & 0x80808080UL)
|
|
break;
|
|
|
|
sn += 4;
|
|
limit -= 4;
|
|
}
|
|
|
|
// handle the last few characters to find actual size
|
|
while (limit && *sn) {
|
|
++sn;
|
|
--limit;
|
|
}
|
|
|
|
return (stbsp__uint32)(sn - s);
|
|
}
|
|
|
|
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintfcb)(STBSP_SPRINTFCB *callback, void *user, char *buf, char const *fmt, va_list va)
|
|
{
|
|
static char hex[] = "0123456789abcdefxp";
|
|
static char hexu[] = "0123456789ABCDEFXP";
|
|
char *bf;
|
|
char const *f;
|
|
int tlen = 0;
|
|
|
|
bf = buf;
|
|
f = fmt;
|
|
for (;;) {
|
|
stbsp__int32 fw, pr, tz;
|
|
stbsp__uint32 fl;
|
|
|
|
// macros for the callback buffer stuff
|
|
#define stbsp__chk_cb_bufL(bytes) \
|
|
{ \
|
|
int len = (int)(bf - buf); \
|
|
if ((len + (bytes)) >= STB_SPRINTF_MIN) { \
|
|
tlen += len; \
|
|
if (0 == (bf = buf = callback(buf, user, len))) \
|
|
goto done; \
|
|
} \
|
|
}
|
|
#define stbsp__chk_cb_buf(bytes) \
|
|
{ \
|
|
if (callback) { \
|
|
stbsp__chk_cb_bufL(bytes); \
|
|
} \
|
|
}
|
|
#define stbsp__flush_cb() \
|
|
{ \
|
|
stbsp__chk_cb_bufL(STB_SPRINTF_MIN - 1); \
|
|
} // flush if there is even one byte in the buffer
|
|
#define stbsp__cb_buf_clamp(cl, v) \
|
|
cl = v; \
|
|
if (callback) { \
|
|
int lg = STB_SPRINTF_MIN - (int)(bf - buf); \
|
|
if (cl > lg) \
|
|
cl = lg; \
|
|
}
|
|
|
|
// fast copy everything up to the next % (or end of string)
|
|
for (;;) {
|
|
while (((stbsp__uintptr)f) & 3) {
|
|
schk1:
|
|
if (f[0] == '%')
|
|
goto scandd;
|
|
schk2:
|
|
if (f[0] == 0)
|
|
goto endfmt;
|
|
stbsp__chk_cb_buf(1);
|
|
*bf++ = f[0];
|
|
++f;
|
|
}
|
|
for (;;) {
|
|
// Check if the next 4 bytes contain %(0x25) or end of string.
|
|
// Using the 'hasless' trick:
|
|
// https://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord
|
|
stbsp__uint32 v, c;
|
|
v = *(stbsp__uint32 *)f;
|
|
c = (~v) & 0x80808080;
|
|
if (((v ^ 0x25252525) - 0x01010101) & c)
|
|
goto schk1;
|
|
if ((v - 0x01010101) & c)
|
|
goto schk2;
|
|
if (callback)
|
|
if ((STB_SPRINTF_MIN - (int)(bf - buf)) < 4)
|
|
goto schk1;
|
|
#ifdef STB_SPRINTF_NOUNALIGNED
|
|
if(((stbsp__uintptr)bf) & 3) {
|
|
bf[0] = f[0];
|
|
bf[1] = f[1];
|
|
bf[2] = f[2];
|
|
bf[3] = f[3];
|
|
} else
|
|
#endif
|
|
{
|
|
*(stbsp__uint32 *)bf = v;
|
|
}
|
|
bf += 4;
|
|
f += 4;
|
|
}
|
|
}
|
|
scandd:
|
|
|
|
++f;
|
|
|
|
// ok, we have a percent, read the modifiers first
|
|
fw = 0;
|
|
pr = -1;
|
|
fl = 0;
|
|
tz = 0;
|
|
|
|
// flags
|
|
for (;;) {
|
|
switch (f[0]) {
|
|
// if we have left justify
|
|
case '-':
|
|
fl |= STBSP__LEFTJUST;
|
|
++f;
|
|
continue;
|
|
// if we have leading plus
|
|
case '+':
|
|
fl |= STBSP__LEADINGPLUS;
|
|
++f;
|
|
continue;
|
|
// if we have leading space
|
|
case ' ':
|
|
fl |= STBSP__LEADINGSPACE;
|
|
++f;
|
|
continue;
|
|
// if we have leading 0x
|
|
case '#':
|
|
fl |= STBSP__LEADING_0X;
|
|
++f;
|
|
continue;
|
|
// if we have thousand commas
|
|
case '\'':
|
|
fl |= STBSP__TRIPLET_COMMA;
|
|
++f;
|
|
continue;
|
|
// if we have kilo marker (none->kilo->kibi->jedec)
|
|
case '$':
|
|
if (fl & STBSP__METRIC_SUFFIX) {
|
|
if (fl & STBSP__METRIC_1024) {
|
|
fl |= STBSP__METRIC_JEDEC;
|
|
} else {
|
|
fl |= STBSP__METRIC_1024;
|
|
}
|
|
} else {
|
|
fl |= STBSP__METRIC_SUFFIX;
|
|
}
|
|
++f;
|
|
continue;
|
|
// if we don't want space between metric suffix and number
|
|
case '_':
|
|
fl |= STBSP__METRIC_NOSPACE;
|
|
++f;
|
|
continue;
|
|
// if we have leading zero
|
|
case '0':
|
|
fl |= STBSP__LEADINGZERO;
|
|
++f;
|
|
goto flags_done;
|
|
default: goto flags_done;
|
|
}
|
|
}
|
|
flags_done:
|
|
|
|
// get the field width
|
|
if (f[0] == '*') {
|
|
fw = va_arg(va, stbsp__uint32);
|
|
++f;
|
|
} else {
|
|
while ((f[0] >= '0') && (f[0] <= '9')) {
|
|
fw = fw * 10 + f[0] - '0';
|
|
f++;
|
|
}
|
|
}
|
|
// get the precision
|
|
if (f[0] == '.') {
|
|
++f;
|
|
if (f[0] == '*') {
|
|
pr = va_arg(va, stbsp__uint32);
|
|
++f;
|
|
} else {
|
|
pr = 0;
|
|
while ((f[0] >= '0') && (f[0] <= '9')) {
|
|
pr = pr * 10 + f[0] - '0';
|
|
f++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// handle integer size overrides
|
|
switch (f[0]) {
|
|
// are we halfwidth?
|
|
case 'h':
|
|
fl |= STBSP__HALFWIDTH;
|
|
++f;
|
|
if (f[0] == 'h')
|
|
++f; // QUARTERWIDTH
|
|
break;
|
|
// are we 64-bit (unix style)
|
|
case 'l':
|
|
fl |= ((sizeof(long) == 8) ? STBSP__INTMAX : 0);
|
|
++f;
|
|
if (f[0] == 'l') {
|
|
fl |= STBSP__INTMAX;
|
|
++f;
|
|
}
|
|
break;
|
|
// are we 64-bit on intmax? (c99)
|
|
case 'j':
|
|
fl |= (sizeof(size_t) == 8) ? STBSP__INTMAX : 0;
|
|
++f;
|
|
break;
|
|
// are we 64-bit on size_t or ptrdiff_t? (c99)
|
|
case 'z':
|
|
fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0;
|
|
++f;
|
|
break;
|
|
case 't':
|
|
fl |= (sizeof(ptrdiff_t) == 8) ? STBSP__INTMAX : 0;
|
|
++f;
|
|
break;
|
|
// are we 64-bit (msft style)
|
|
case 'I':
|
|
if ((f[1] == '6') && (f[2] == '4')) {
|
|
fl |= STBSP__INTMAX;
|
|
f += 3;
|
|
} else if ((f[1] == '3') && (f[2] == '2')) {
|
|
f += 3;
|
|
} else {
|
|
fl |= ((sizeof(void *) == 8) ? STBSP__INTMAX : 0);
|
|
++f;
|
|
}
|
|
break;
|
|
default: break;
|
|
}
|
|
|
|
// handle each replacement
|
|
switch (f[0]) {
|
|
#define STBSP__NUMSZ 512 // big enough for e308 (with commas) or e-307
|
|
char num[STBSP__NUMSZ];
|
|
char lead[8];
|
|
char tail[8];
|
|
char *s;
|
|
char const *h;
|
|
stbsp__uint32 l, n, cs;
|
|
stbsp__uint64 n64;
|
|
#ifndef STB_SPRINTF_NOFLOAT
|
|
double fv;
|
|
#endif
|
|
stbsp__int32 dp;
|
|
char const *sn;
|
|
|
|
case 's':
|
|
// get the string
|
|
s = va_arg(va, char *);
|
|
if (s == 0)
|
|
s = (char *)"null";
|
|
// get the length, limited to desired precision
|
|
// always limit to ~0u chars since our counts are 32b
|
|
l = stbsp__strlen_limited(s, (pr >= 0) ? pr : ~0u);
|
|
lead[0] = 0;
|
|
tail[0] = 0;
|
|
pr = 0;
|
|
dp = 0;
|
|
cs = 0;
|
|
// copy the string in
|
|
goto scopy;
|
|
|
|
case 'S':
|
|
{
|
|
DN_Str8 str8 = va_arg(va, DN_Str8);
|
|
s = (char *)str8.data;
|
|
l = (uint32_t)str8.size;
|
|
lead[0] = 0;
|
|
tail[0] = 0;
|
|
pr = 0;
|
|
dp = 0;
|
|
cs = 0;
|
|
}goto scopy;
|
|
|
|
case 'c': // char
|
|
// get the character
|
|
s = num + STBSP__NUMSZ - 1;
|
|
*s = (char)va_arg(va, int);
|
|
l = 1;
|
|
lead[0] = 0;
|
|
tail[0] = 0;
|
|
pr = 0;
|
|
dp = 0;
|
|
cs = 0;
|
|
goto scopy;
|
|
|
|
case 'n': // weird write-bytes specifier
|
|
{
|
|
int *d = va_arg(va, int *);
|
|
*d = tlen + (int)(bf - buf);
|
|
} break;
|
|
|
|
#ifdef STB_SPRINTF_NOFLOAT
|
|
case 'A': // float
|
|
case 'a': // hex float
|
|
case 'G': // float
|
|
case 'g': // float
|
|
case 'E': // float
|
|
case 'e': // float
|
|
case 'f': // float
|
|
va_arg(va, double); // eat it
|
|
s = (char *)"No float";
|
|
l = 8;
|
|
lead[0] = 0;
|
|
tail[0] = 0;
|
|
pr = 0;
|
|
cs = 0;
|
|
STBSP__NOTUSED(dp);
|
|
goto scopy;
|
|
#else
|
|
case 'A': // hex float
|
|
case 'a': // hex float
|
|
h = (f[0] == 'A') ? hexu : hex;
|
|
fv = va_arg(va, double);
|
|
if (pr == -1)
|
|
pr = 6; // default is 6
|
|
// read the double into a string
|
|
if (stbsp__real_to_parts((stbsp__int64 *)&n64, &dp, fv))
|
|
fl |= STBSP__NEGATIVE;
|
|
|
|
s = num + 64;
|
|
|
|
stbsp__lead_sign(fl, lead);
|
|
|
|
if (dp == -1023)
|
|
dp = (n64) ? -1022 : 0;
|
|
else
|
|
n64 |= (((stbsp__uint64)1) << 52);
|
|
n64 <<= (64 - 56);
|
|
if (pr < 15)
|
|
n64 += ((((stbsp__uint64)8) << 56) >> (pr * 4));
|
|
// add leading chars
|
|
|
|
#ifdef STB_SPRINTF_MSVC_MODE
|
|
*s++ = '0';
|
|
*s++ = 'x';
|
|
#else
|
|
lead[1 + lead[0]] = '0';
|
|
lead[2 + lead[0]] = 'x';
|
|
lead[0] += 2;
|
|
#endif
|
|
*s++ = h[(n64 >> 60) & 15];
|
|
n64 <<= 4;
|
|
if (pr)
|
|
*s++ = stbsp__period;
|
|
sn = s;
|
|
|
|
// print the bits
|
|
n = pr;
|
|
if (n > 13)
|
|
n = 13;
|
|
if (pr > (stbsp__int32)n)
|
|
tz = pr - n;
|
|
pr = 0;
|
|
while (n--) {
|
|
*s++ = h[(n64 >> 60) & 15];
|
|
n64 <<= 4;
|
|
}
|
|
|
|
// print the expo
|
|
tail[1] = h[17];
|
|
if (dp < 0) {
|
|
tail[2] = '-';
|
|
dp = -dp;
|
|
} else
|
|
tail[2] = '+';
|
|
n = (dp >= 1000) ? 6 : ((dp >= 100) ? 5 : ((dp >= 10) ? 4 : 3));
|
|
tail[0] = (char)n;
|
|
for (;;) {
|
|
tail[n] = '0' + dp % 10;
|
|
if (n <= 3)
|
|
break;
|
|
--n;
|
|
dp /= 10;
|
|
}
|
|
|
|
dp = (int)(s - sn);
|
|
l = (int)(s - (num + 64));
|
|
s = num + 64;
|
|
cs = 1 + (3 << 24);
|
|
goto scopy;
|
|
|
|
case 'G': // float
|
|
case 'g': // float
|
|
h = (f[0] == 'G') ? hexu : hex;
|
|
fv = va_arg(va, double);
|
|
if (pr == -1)
|
|
pr = 6;
|
|
else if (pr == 0)
|
|
pr = 1; // default is 6
|
|
// read the double into a string
|
|
if (stbsp__real_to_str(&sn, &l, num, &dp, fv, (pr - 1) | 0x80000000))
|
|
fl |= STBSP__NEGATIVE;
|
|
|
|
// clamp the precision and delete extra zeros after clamp
|
|
n = pr;
|
|
if (l > (stbsp__uint32)pr)
|
|
l = pr;
|
|
while ((l > 1) && (pr) && (sn[l - 1] == '0')) {
|
|
--pr;
|
|
--l;
|
|
}
|
|
|
|
// should we use %e
|
|
if ((dp <= -4) || (dp > (stbsp__int32)n)) {
|
|
if (pr > (stbsp__int32)l)
|
|
pr = l - 1;
|
|
else if (pr)
|
|
--pr; // when using %e, there is one digit before the decimal
|
|
goto doexpfromg;
|
|
}
|
|
// this is the insane action to get the pr to match %g semantics for %f
|
|
if (dp > 0) {
|
|
pr = (dp < (stbsp__int32)l) ? l - dp : 0;
|
|
} else {
|
|
pr = -dp + ((pr > (stbsp__int32)l) ? (stbsp__int32) l : pr);
|
|
}
|
|
goto dofloatfromg;
|
|
|
|
case 'E': // float
|
|
case 'e': // float
|
|
h = (f[0] == 'E') ? hexu : hex;
|
|
fv = va_arg(va, double);
|
|
if (pr == -1)
|
|
pr = 6; // default is 6
|
|
// read the double into a string
|
|
if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr | 0x80000000))
|
|
fl |= STBSP__NEGATIVE;
|
|
doexpfromg:
|
|
tail[0] = 0;
|
|
stbsp__lead_sign(fl, lead);
|
|
if (dp == STBSP__SPECIAL) {
|
|
s = (char *)sn;
|
|
cs = 0;
|
|
pr = 0;
|
|
goto scopy;
|
|
}
|
|
s = num + 64;
|
|
// handle leading chars
|
|
*s++ = sn[0];
|
|
|
|
if (pr)
|
|
*s++ = stbsp__period;
|
|
|
|
// handle after decimal
|
|
if ((l - 1) > (stbsp__uint32)pr)
|
|
l = pr + 1;
|
|
for (n = 1; n < l; n++)
|
|
*s++ = sn[n];
|
|
// trailing zeros
|
|
tz = pr - (l - 1);
|
|
pr = 0;
|
|
// dump expo
|
|
tail[1] = h[0xe];
|
|
dp -= 1;
|
|
if (dp < 0) {
|
|
tail[2] = '-';
|
|
dp = -dp;
|
|
} else
|
|
tail[2] = '+';
|
|
#ifdef STB_SPRINTF_MSVC_MODE
|
|
n = 5;
|
|
#else
|
|
n = (dp >= 100) ? 5 : 4;
|
|
#endif
|
|
tail[0] = (char)n;
|
|
for (;;) {
|
|
tail[n] = '0' + dp % 10;
|
|
if (n <= 3)
|
|
break;
|
|
--n;
|
|
dp /= 10;
|
|
}
|
|
cs = 1 + (3 << 24); // how many tens
|
|
goto flt_lead;
|
|
|
|
case 'f': // float
|
|
fv = va_arg(va, double);
|
|
doafloat:
|
|
// do kilos
|
|
if (fl & STBSP__METRIC_SUFFIX) {
|
|
double divisor;
|
|
divisor = 1000.0f;
|
|
if (fl & STBSP__METRIC_1024)
|
|
divisor = 1024.0;
|
|
while (fl < 0x4000000) {
|
|
if ((fv < divisor) && (fv > -divisor))
|
|
break;
|
|
fv /= divisor;
|
|
fl += 0x1000000;
|
|
}
|
|
}
|
|
if (pr == -1)
|
|
pr = 6; // default is 6
|
|
// read the double into a string
|
|
if (stbsp__real_to_str(&sn, &l, num, &dp, fv, pr))
|
|
fl |= STBSP__NEGATIVE;
|
|
dofloatfromg:
|
|
tail[0] = 0;
|
|
stbsp__lead_sign(fl, lead);
|
|
if (dp == STBSP__SPECIAL) {
|
|
s = (char *)sn;
|
|
cs = 0;
|
|
pr = 0;
|
|
goto scopy;
|
|
}
|
|
s = num + 64;
|
|
|
|
// handle the three decimal varieties
|
|
if (dp <= 0) {
|
|
stbsp__int32 i;
|
|
// handle 0.000*000xxxx
|
|
*s++ = '0';
|
|
if (pr)
|
|
*s++ = stbsp__period;
|
|
n = -dp;
|
|
if ((stbsp__int32)n > pr)
|
|
n = pr;
|
|
i = n;
|
|
while (i) {
|
|
if ((((stbsp__uintptr)s) & 3) == 0)
|
|
break;
|
|
*s++ = '0';
|
|
--i;
|
|
}
|
|
while (i >= 4) {
|
|
*(stbsp__uint32 *)s = 0x30303030;
|
|
s += 4;
|
|
i -= 4;
|
|
}
|
|
while (i) {
|
|
*s++ = '0';
|
|
--i;
|
|
}
|
|
if ((stbsp__int32)(l + n) > pr)
|
|
l = pr - n;
|
|
i = l;
|
|
while (i) {
|
|
*s++ = *sn++;
|
|
--i;
|
|
}
|
|
tz = pr - (n + l);
|
|
cs = 1 + (3 << 24); // how many tens did we write (for commas below)
|
|
} else {
|
|
cs = (fl & STBSP__TRIPLET_COMMA) ? ((600 - (stbsp__uint32)dp) % 3) : 0;
|
|
if ((stbsp__uint32)dp >= l) {
|
|
// handle xxxx000*000.0
|
|
n = 0;
|
|
for (;;) {
|
|
if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
|
|
cs = 0;
|
|
*s++ = stbsp__comma;
|
|
} else {
|
|
*s++ = sn[n];
|
|
++n;
|
|
if (n >= l)
|
|
break;
|
|
}
|
|
}
|
|
if (n < (stbsp__uint32)dp) {
|
|
n = dp - n;
|
|
if ((fl & STBSP__TRIPLET_COMMA) == 0) {
|
|
while (n) {
|
|
if ((((stbsp__uintptr)s) & 3) == 0)
|
|
break;
|
|
*s++ = '0';
|
|
--n;
|
|
}
|
|
while (n >= 4) {
|
|
*(stbsp__uint32 *)s = 0x30303030;
|
|
s += 4;
|
|
n -= 4;
|
|
}
|
|
}
|
|
while (n) {
|
|
if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
|
|
cs = 0;
|
|
*s++ = stbsp__comma;
|
|
} else {
|
|
*s++ = '0';
|
|
--n;
|
|
}
|
|
}
|
|
}
|
|
cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens
|
|
if (pr) {
|
|
*s++ = stbsp__period;
|
|
tz = pr;
|
|
}
|
|
} else {
|
|
// handle xxxxx.xxxx000*000
|
|
n = 0;
|
|
for (;;) {
|
|
if ((fl & STBSP__TRIPLET_COMMA) && (++cs == 4)) {
|
|
cs = 0;
|
|
*s++ = stbsp__comma;
|
|
} else {
|
|
*s++ = sn[n];
|
|
++n;
|
|
if (n >= (stbsp__uint32)dp)
|
|
break;
|
|
}
|
|
}
|
|
cs = (int)(s - (num + 64)) + (3 << 24); // cs is how many tens
|
|
if (pr)
|
|
*s++ = stbsp__period;
|
|
if ((l - dp) > (stbsp__uint32)pr)
|
|
l = pr + dp;
|
|
while (n < l) {
|
|
*s++ = sn[n];
|
|
++n;
|
|
}
|
|
tz = pr - (l - dp);
|
|
}
|
|
}
|
|
pr = 0;
|
|
|
|
// handle k,m,g,t
|
|
if (fl & STBSP__METRIC_SUFFIX) {
|
|
char idx;
|
|
idx = 1;
|
|
if (fl & STBSP__METRIC_NOSPACE)
|
|
idx = 0;
|
|
tail[0] = idx;
|
|
tail[1] = ' ';
|
|
{
|
|
if (fl >> 24) { // SI kilo is 'k', JEDEC and SI kibits are 'K'.
|
|
if (fl & STBSP__METRIC_1024)
|
|
tail[idx + 1] = "_KMGT"[fl >> 24];
|
|
else
|
|
tail[idx + 1] = "_kMGT"[fl >> 24];
|
|
idx++;
|
|
// If printing kibits and not in jedec, add the 'i'.
|
|
if (fl & STBSP__METRIC_1024 && !(fl & STBSP__METRIC_JEDEC)) {
|
|
tail[idx + 1] = 'i';
|
|
idx++;
|
|
}
|
|
tail[0] = idx;
|
|
}
|
|
}
|
|
};
|
|
|
|
flt_lead:
|
|
// get the length that we copied
|
|
l = (stbsp__uint32)(s - (num + 64));
|
|
s = num + 64;
|
|
goto scopy;
|
|
#endif
|
|
|
|
case 'B': // upper binary
|
|
case 'b': // lower binary
|
|
h = (f[0] == 'B') ? hexu : hex;
|
|
lead[0] = 0;
|
|
if (fl & STBSP__LEADING_0X) {
|
|
lead[0] = 2;
|
|
lead[1] = '0';
|
|
lead[2] = h[0xb];
|
|
}
|
|
l = (8 << 4) | (1 << 8);
|
|
goto radixnum;
|
|
|
|
case 'o': // octal
|
|
h = hexu;
|
|
lead[0] = 0;
|
|
if (fl & STBSP__LEADING_0X) {
|
|
lead[0] = 1;
|
|
lead[1] = '0';
|
|
}
|
|
l = (3 << 4) | (3 << 8);
|
|
goto radixnum;
|
|
|
|
case 'p': // pointer
|
|
fl |= (sizeof(void *) == 8) ? STBSP__INTMAX : 0;
|
|
pr = sizeof(void *) * 2;
|
|
fl &= ~STBSP__LEADINGZERO; // 'p' only prints the pointer with zeros
|
|
// fall through - to X
|
|
|
|
case 'X': // upper hex
|
|
case 'x': // lower hex
|
|
h = (f[0] == 'X') ? hexu : hex;
|
|
l = (4 << 4) | (4 << 8);
|
|
lead[0] = 0;
|
|
if (fl & STBSP__LEADING_0X) {
|
|
lead[0] = 2;
|
|
lead[1] = '0';
|
|
lead[2] = h[16];
|
|
}
|
|
radixnum:
|
|
// get the number
|
|
if (fl & STBSP__INTMAX)
|
|
n64 = va_arg(va, stbsp__uint64);
|
|
else
|
|
n64 = va_arg(va, stbsp__uint32);
|
|
|
|
s = num + STBSP__NUMSZ;
|
|
dp = 0;
|
|
// clear tail, and clear leading if value is zero
|
|
tail[0] = 0;
|
|
if (n64 == 0) {
|
|
lead[0] = 0;
|
|
if (pr == 0) {
|
|
l = 0;
|
|
cs = 0;
|
|
goto scopy;
|
|
}
|
|
}
|
|
// convert to string
|
|
for (;;) {
|
|
*--s = h[n64 & ((1 << (l >> 8)) - 1)];
|
|
n64 >>= (l >> 8);
|
|
if (!((n64) || ((stbsp__int32)((num + STBSP__NUMSZ) - s) < pr)))
|
|
break;
|
|
if (fl & STBSP__TRIPLET_COMMA) {
|
|
++l;
|
|
if ((l & 15) == ((l >> 4) & 15)) {
|
|
l &= ~15;
|
|
*--s = stbsp__comma;
|
|
}
|
|
}
|
|
};
|
|
// get the tens and the comma pos
|
|
cs = (stbsp__uint32)((num + STBSP__NUMSZ) - s) + ((((l >> 4) & 15)) << 24);
|
|
// get the length that we copied
|
|
l = (stbsp__uint32)((num + STBSP__NUMSZ) - s);
|
|
// copy it
|
|
goto scopy;
|
|
|
|
case 'u': // unsigned
|
|
case 'i':
|
|
case 'd': // integer
|
|
// get the integer and abs it
|
|
if (fl & STBSP__INTMAX) {
|
|
stbsp__int64 i64 = va_arg(va, stbsp__int64);
|
|
n64 = (stbsp__uint64)i64;
|
|
if ((f[0] != 'u') && (i64 < 0)) {
|
|
n64 = (stbsp__uint64)-i64;
|
|
fl |= STBSP__NEGATIVE;
|
|
}
|
|
} else {
|
|
stbsp__int32 i = va_arg(va, stbsp__int32);
|
|
n64 = (stbsp__uint32)i;
|
|
if ((f[0] != 'u') && (i < 0)) {
|
|
n64 = (stbsp__uint32)-i;
|
|
fl |= STBSP__NEGATIVE;
|
|
}
|
|
}
|
|
|
|
#ifndef STB_SPRINTF_NOFLOAT
|
|
if (fl & STBSP__METRIC_SUFFIX) {
|
|
if (n64 < 1024)
|
|
pr = 0;
|
|
else if (pr == -1)
|
|
pr = 1;
|
|
fv = (double)(stbsp__int64)n64;
|
|
goto doafloat;
|
|
}
|
|
#endif
|
|
|
|
// convert to string
|
|
s = num + STBSP__NUMSZ;
|
|
l = 0;
|
|
|
|
for (;;) {
|
|
// do in 32-bit chunks (avoid lots of 64-bit divides even with constant denominators)
|
|
char *o = s - 8;
|
|
if (n64 >= 100000000) {
|
|
n = (stbsp__uint32)(n64 % 100000000);
|
|
n64 /= 100000000;
|
|
} else {
|
|
n = (stbsp__uint32)n64;
|
|
n64 = 0;
|
|
}
|
|
if ((fl & STBSP__TRIPLET_COMMA) == 0) {
|
|
do {
|
|
s -= 2;
|
|
*(stbsp__uint16 *)s = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2];
|
|
n /= 100;
|
|
} while (n);
|
|
}
|
|
while (n) {
|
|
if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) {
|
|
l = 0;
|
|
*--s = stbsp__comma;
|
|
--o;
|
|
} else {
|
|
*--s = (char)(n % 10) + '0';
|
|
n /= 10;
|
|
}
|
|
}
|
|
if (n64 == 0) {
|
|
if ((s[0] == '0') && (s != (num + STBSP__NUMSZ)))
|
|
++s;
|
|
break;
|
|
}
|
|
while (s != o)
|
|
if ((fl & STBSP__TRIPLET_COMMA) && (l++ == 3)) {
|
|
l = 0;
|
|
*--s = stbsp__comma;
|
|
--o;
|
|
} else {
|
|
*--s = '0';
|
|
}
|
|
}
|
|
|
|
tail[0] = 0;
|
|
stbsp__lead_sign(fl, lead);
|
|
|
|
// get the length that we copied
|
|
l = (stbsp__uint32)((num + STBSP__NUMSZ) - s);
|
|
if (l == 0) {
|
|
*--s = '0';
|
|
l = 1;
|
|
}
|
|
cs = l + (3 << 24);
|
|
if (pr < 0)
|
|
pr = 0;
|
|
|
|
scopy:
|
|
// get fw=leading/trailing space, pr=leading zeros
|
|
if (pr < (stbsp__int32)l)
|
|
pr = l;
|
|
n = pr + lead[0] + tail[0] + tz;
|
|
if (fw < (stbsp__int32)n)
|
|
fw = n;
|
|
fw -= n;
|
|
pr -= l;
|
|
|
|
// handle right justify and leading zeros
|
|
if ((fl & STBSP__LEFTJUST) == 0) {
|
|
if (fl & STBSP__LEADINGZERO) // if leading zeros, everything is in pr
|
|
{
|
|
pr = (fw > pr) ? fw : pr;
|
|
fw = 0;
|
|
} else {
|
|
fl &= ~STBSP__TRIPLET_COMMA; // if no leading zeros, then no commas
|
|
}
|
|
}
|
|
|
|
// copy the spaces and/or zeros
|
|
if (fw + pr) {
|
|
stbsp__int32 i;
|
|
stbsp__uint32 c;
|
|
|
|
// copy leading spaces (or when doing %8.4d stuff)
|
|
if ((fl & STBSP__LEFTJUST) == 0)
|
|
while (fw > 0) {
|
|
stbsp__cb_buf_clamp(i, fw);
|
|
fw -= i;
|
|
while (i) {
|
|
if ((((stbsp__uintptr)bf) & 3) == 0)
|
|
break;
|
|
*bf++ = ' ';
|
|
--i;
|
|
}
|
|
while (i >= 4) {
|
|
*(stbsp__uint32 *)bf = 0x20202020;
|
|
bf += 4;
|
|
i -= 4;
|
|
}
|
|
while (i) {
|
|
*bf++ = ' ';
|
|
--i;
|
|
}
|
|
stbsp__chk_cb_buf(1);
|
|
}
|
|
|
|
// copy leader
|
|
sn = lead + 1;
|
|
while (lead[0]) {
|
|
stbsp__cb_buf_clamp(i, lead[0]);
|
|
lead[0] -= (char)i;
|
|
while (i) {
|
|
*bf++ = *sn++;
|
|
--i;
|
|
}
|
|
stbsp__chk_cb_buf(1);
|
|
}
|
|
|
|
// copy leading zeros
|
|
c = cs >> 24;
|
|
cs &= 0xffffff;
|
|
cs = (fl & STBSP__TRIPLET_COMMA) ? ((stbsp__uint32)(c - ((pr + cs) % (c + 1)))) : 0;
|
|
while (pr > 0) {
|
|
stbsp__cb_buf_clamp(i, pr);
|
|
pr -= i;
|
|
if ((fl & STBSP__TRIPLET_COMMA) == 0) {
|
|
while (i) {
|
|
if ((((stbsp__uintptr)bf) & 3) == 0)
|
|
break;
|
|
*bf++ = '0';
|
|
--i;
|
|
}
|
|
while (i >= 4) {
|
|
*(stbsp__uint32 *)bf = 0x30303030;
|
|
bf += 4;
|
|
i -= 4;
|
|
}
|
|
}
|
|
while (i) {
|
|
if ((fl & STBSP__TRIPLET_COMMA) && (cs++ == c)) {
|
|
cs = 0;
|
|
*bf++ = stbsp__comma;
|
|
} else
|
|
*bf++ = '0';
|
|
--i;
|
|
}
|
|
stbsp__chk_cb_buf(1);
|
|
}
|
|
}
|
|
|
|
// copy leader if there is still one
|
|
sn = lead + 1;
|
|
while (lead[0]) {
|
|
stbsp__int32 i;
|
|
stbsp__cb_buf_clamp(i, lead[0]);
|
|
lead[0] -= (char)i;
|
|
while (i) {
|
|
*bf++ = *sn++;
|
|
--i;
|
|
}
|
|
stbsp__chk_cb_buf(1);
|
|
}
|
|
|
|
// copy the string
|
|
n = l;
|
|
while (n) {
|
|
stbsp__int32 i;
|
|
stbsp__cb_buf_clamp(i, n);
|
|
n -= i;
|
|
STBSP__UNALIGNED(while (i >= 4) {
|
|
*(stbsp__uint32 volatile *)bf = *(stbsp__uint32 volatile *)s;
|
|
bf += 4;
|
|
s += 4;
|
|
i -= 4;
|
|
})
|
|
while (i) {
|
|
*bf++ = *s++;
|
|
--i;
|
|
}
|
|
stbsp__chk_cb_buf(1);
|
|
}
|
|
|
|
// copy trailing zeros
|
|
while (tz) {
|
|
stbsp__int32 i;
|
|
stbsp__cb_buf_clamp(i, tz);
|
|
tz -= i;
|
|
while (i) {
|
|
if ((((stbsp__uintptr)bf) & 3) == 0)
|
|
break;
|
|
*bf++ = '0';
|
|
--i;
|
|
}
|
|
while (i >= 4) {
|
|
*(stbsp__uint32 *)bf = 0x30303030;
|
|
bf += 4;
|
|
i -= 4;
|
|
}
|
|
while (i) {
|
|
*bf++ = '0';
|
|
--i;
|
|
}
|
|
stbsp__chk_cb_buf(1);
|
|
}
|
|
|
|
// copy tail if there is one
|
|
sn = tail + 1;
|
|
while (tail[0]) {
|
|
stbsp__int32 i;
|
|
stbsp__cb_buf_clamp(i, tail[0]);
|
|
tail[0] -= (char)i;
|
|
while (i) {
|
|
*bf++ = *sn++;
|
|
--i;
|
|
}
|
|
stbsp__chk_cb_buf(1);
|
|
}
|
|
|
|
// handle the left justify
|
|
if (fl & STBSP__LEFTJUST)
|
|
if (fw > 0) {
|
|
while (fw) {
|
|
stbsp__int32 i;
|
|
stbsp__cb_buf_clamp(i, fw);
|
|
fw -= i;
|
|
while (i) {
|
|
if ((((stbsp__uintptr)bf) & 3) == 0)
|
|
break;
|
|
*bf++ = ' ';
|
|
--i;
|
|
}
|
|
while (i >= 4) {
|
|
*(stbsp__uint32 *)bf = 0x20202020;
|
|
bf += 4;
|
|
i -= 4;
|
|
}
|
|
while (i--)
|
|
*bf++ = ' ';
|
|
stbsp__chk_cb_buf(1);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default: // unknown, just copy code
|
|
s = num + STBSP__NUMSZ - 1;
|
|
*s = f[0];
|
|
l = 1;
|
|
fw = fl = 0;
|
|
lead[0] = 0;
|
|
tail[0] = 0;
|
|
pr = 0;
|
|
dp = 0;
|
|
cs = 0;
|
|
goto scopy;
|
|
}
|
|
++f;
|
|
}
|
|
endfmt:
|
|
|
|
if (!callback)
|
|
*bf = 0;
|
|
else
|
|
stbsp__flush_cb();
|
|
|
|
done:
|
|
return tlen + (int)(bf - buf);
|
|
}
|
|
|
|
// cleanup
|
|
#undef STBSP__LEFTJUST
|
|
#undef STBSP__LEADINGPLUS
|
|
#undef STBSP__LEADINGSPACE
|
|
#undef STBSP__LEADING_0X
|
|
#undef STBSP__LEADINGZERO
|
|
#undef STBSP__INTMAX
|
|
#undef STBSP__TRIPLET_COMMA
|
|
#undef STBSP__NEGATIVE
|
|
#undef STBSP__METRIC_SUFFIX
|
|
#undef STBSP__NUMSZ
|
|
#undef stbsp__chk_cb_bufL
|
|
#undef stbsp__chk_cb_buf
|
|
#undef stbsp__flush_cb
|
|
#undef stbsp__cb_buf_clamp
|
|
|
|
// ============================================================================
|
|
// wrapper functions
|
|
|
|
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(sprintf)(char *buf, char const *fmt, ...)
|
|
{
|
|
int result;
|
|
va_list va;
|
|
va_start(va, fmt);
|
|
result = STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va);
|
|
va_end(va);
|
|
return result;
|
|
}
|
|
|
|
typedef struct stbsp__context {
|
|
char *buf;
|
|
int count;
|
|
int length;
|
|
char tmp[STB_SPRINTF_MIN];
|
|
} stbsp__context;
|
|
|
|
static char *stbsp__clamp_callback(const char *buf, void *user, int len)
|
|
{
|
|
stbsp__context *c = (stbsp__context *)user;
|
|
c->length += len;
|
|
|
|
if (len > c->count)
|
|
len = c->count;
|
|
|
|
if (len) {
|
|
if (buf != c->buf) {
|
|
const char *s, *se;
|
|
char *d;
|
|
d = c->buf;
|
|
s = buf;
|
|
se = buf + len;
|
|
do {
|
|
*d++ = *s++;
|
|
} while (s < se);
|
|
}
|
|
c->buf += len;
|
|
c->count -= len;
|
|
}
|
|
|
|
if (c->count <= 0)
|
|
return c->tmp;
|
|
return (c->count >= STB_SPRINTF_MIN) ? c->buf : c->tmp; // go direct into buffer if you can
|
|
}
|
|
|
|
static char * stbsp__count_clamp_callback( const char * buf, void * user, int len )
|
|
{
|
|
stbsp__context * c = (stbsp__context*)user;
|
|
(void) sizeof(buf);
|
|
|
|
c->length += len;
|
|
return c->tmp; // go direct into buffer if you can
|
|
}
|
|
|
|
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE( vsnprintf )( char * buf, int count, char const * fmt, va_list va )
|
|
{
|
|
stbsp__context c;
|
|
|
|
if ( (count == 0) && !buf )
|
|
{
|
|
c.length = 0;
|
|
|
|
STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__count_clamp_callback, &c, c.tmp, fmt, va );
|
|
}
|
|
else
|
|
{
|
|
int l;
|
|
|
|
c.buf = buf;
|
|
c.count = count;
|
|
c.length = 0;
|
|
|
|
STB_SPRINTF_DECORATE( vsprintfcb )( stbsp__clamp_callback, &c, stbsp__clamp_callback(0,&c,0), fmt, va );
|
|
|
|
// zero-terminate
|
|
l = (int)( c.buf - buf );
|
|
if ( l >= count ) // should never be greater, only equal (or less) than count
|
|
l = count - 1;
|
|
buf[l] = 0;
|
|
}
|
|
|
|
return c.length;
|
|
}
|
|
|
|
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(snprintf)(char *buf, int count, char const *fmt, ...)
|
|
{
|
|
int result;
|
|
va_list va;
|
|
va_start(va, fmt);
|
|
|
|
result = STB_SPRINTF_DECORATE(vsnprintf)(buf, count, fmt, va);
|
|
va_end(va);
|
|
|
|
return result;
|
|
}
|
|
|
|
STBSP__PUBLICDEF int STB_SPRINTF_DECORATE(vsprintf)(char *buf, char const *fmt, va_list va)
|
|
{
|
|
return STB_SPRINTF_DECORATE(vsprintfcb)(0, 0, buf, fmt, va);
|
|
}
|
|
|
|
// =======================================================================
|
|
// low level float utility functions
|
|
|
|
#ifndef STB_SPRINTF_NOFLOAT
|
|
|
|
// copies d to bits w/ strict aliasing (this compiles to nothing on /Ox)
|
|
#define STBSP__COPYFP(dest, src) \
|
|
{ \
|
|
int cn; \
|
|
for (cn = 0; cn < 8; cn++) \
|
|
((char *)&dest)[cn] = ((char *)&src)[cn]; \
|
|
}
|
|
|
|
// get float info
|
|
static stbsp__int32 stbsp__real_to_parts(stbsp__int64 *bits, stbsp__int32 *expo, double value)
|
|
{
|
|
double d;
|
|
stbsp__int64 b = 0;
|
|
|
|
// load value and round at the frac_digits
|
|
d = value;
|
|
|
|
STBSP__COPYFP(b, d);
|
|
|
|
*bits = b & ((((stbsp__uint64)1) << 52) - 1);
|
|
*expo = (stbsp__int32)(((b >> 52) & 2047) - 1023);
|
|
|
|
return (stbsp__int32)((stbsp__uint64) b >> 63);
|
|
}
|
|
|
|
static double const stbsp__bot[23] = {
|
|
1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009, 1e+010, 1e+011,
|
|
1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019, 1e+020, 1e+021, 1e+022
|
|
};
|
|
static double const stbsp__negbot[22] = {
|
|
1e-001, 1e-002, 1e-003, 1e-004, 1e-005, 1e-006, 1e-007, 1e-008, 1e-009, 1e-010, 1e-011,
|
|
1e-012, 1e-013, 1e-014, 1e-015, 1e-016, 1e-017, 1e-018, 1e-019, 1e-020, 1e-021, 1e-022
|
|
};
|
|
static double const stbsp__negboterr[22] = {
|
|
-5.551115123125783e-018, -2.0816681711721684e-019, -2.0816681711721686e-020, -4.7921736023859299e-021, -8.1803053914031305e-022, 4.5251888174113741e-023,
|
|
4.5251888174113739e-024, -2.0922560830128471e-025, -6.2281591457779853e-026, -3.6432197315497743e-027, 6.0503030718060191e-028, 2.0113352370744385e-029,
|
|
-3.0373745563400371e-030, 1.1806906454401013e-032, -7.7705399876661076e-032, 2.0902213275965398e-033, -7.1542424054621921e-034, -7.1542424054621926e-035,
|
|
2.4754073164739869e-036, 5.4846728545790429e-037, 9.2462547772103625e-038, -4.8596774326570872e-039
|
|
};
|
|
static double const stbsp__top[13] = {
|
|
1e+023, 1e+046, 1e+069, 1e+092, 1e+115, 1e+138, 1e+161, 1e+184, 1e+207, 1e+230, 1e+253, 1e+276, 1e+299
|
|
};
|
|
static double const stbsp__negtop[13] = {
|
|
1e-023, 1e-046, 1e-069, 1e-092, 1e-115, 1e-138, 1e-161, 1e-184, 1e-207, 1e-230, 1e-253, 1e-276, 1e-299
|
|
};
|
|
static double const stbsp__toperr[13] = {
|
|
8388608,
|
|
6.8601809640529717e+028,
|
|
-7.253143638152921e+052,
|
|
-4.3377296974619174e+075,
|
|
-1.5559416129466825e+098,
|
|
-3.2841562489204913e+121,
|
|
-3.7745893248228135e+144,
|
|
-1.7356668416969134e+167,
|
|
-3.8893577551088374e+190,
|
|
-9.9566444326005119e+213,
|
|
6.3641293062232429e+236,
|
|
-5.2069140800249813e+259,
|
|
-5.2504760255204387e+282
|
|
};
|
|
static double const stbsp__negtoperr[13] = {
|
|
3.9565301985100693e-040, -2.299904345391321e-063, 3.6506201437945798e-086, 1.1875228833981544e-109,
|
|
-5.0644902316928607e-132, -6.7156837247865426e-155, -2.812077463003139e-178, -5.7778912386589953e-201,
|
|
7.4997100559334532e-224, -4.6439668915134491e-247, -6.3691100762962136e-270, -9.436808465446358e-293,
|
|
8.0970921678014997e-317
|
|
};
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER <= 1200)
|
|
static stbsp__uint64 const stbsp__powten[20] = {
|
|
1,
|
|
10,
|
|
100,
|
|
1000,
|
|
10000,
|
|
100000,
|
|
1000000,
|
|
10000000,
|
|
100000000,
|
|
1000000000,
|
|
10000000000,
|
|
100000000000,
|
|
1000000000000,
|
|
10000000000000,
|
|
100000000000000,
|
|
1000000000000000,
|
|
10000000000000000,
|
|
100000000000000000,
|
|
1000000000000000000,
|
|
10000000000000000000U
|
|
};
|
|
#define stbsp__tento19th ((stbsp__uint64)1000000000000000000)
|
|
#else
|
|
static stbsp__uint64 const stbsp__powten[20] = {
|
|
1,
|
|
10,
|
|
100,
|
|
1000,
|
|
10000,
|
|
100000,
|
|
1000000,
|
|
10000000,
|
|
100000000,
|
|
1000000000,
|
|
10000000000ULL,
|
|
100000000000ULL,
|
|
1000000000000ULL,
|
|
10000000000000ULL,
|
|
100000000000000ULL,
|
|
1000000000000000ULL,
|
|
10000000000000000ULL,
|
|
100000000000000000ULL,
|
|
1000000000000000000ULL,
|
|
10000000000000000000ULL
|
|
};
|
|
#define stbsp__tento19th (1000000000000000000ULL)
|
|
#endif
|
|
|
|
#define stbsp__ddmulthi(oh, ol, xh, yh) \
|
|
{ \
|
|
double ahi = 0, alo, bhi = 0, blo; \
|
|
stbsp__int64 bt; \
|
|
oh = xh * yh; \
|
|
STBSP__COPYFP(bt, xh); \
|
|
bt &= ((~(stbsp__uint64)0) << 27); \
|
|
STBSP__COPYFP(ahi, bt); \
|
|
alo = xh - ahi; \
|
|
STBSP__COPYFP(bt, yh); \
|
|
bt &= ((~(stbsp__uint64)0) << 27); \
|
|
STBSP__COPYFP(bhi, bt); \
|
|
blo = yh - bhi; \
|
|
ol = ((ahi * bhi - oh) + ahi * blo + alo * bhi) + alo * blo; \
|
|
}
|
|
|
|
#define stbsp__ddtoS64(ob, xh, xl) \
|
|
{ \
|
|
double ahi = 0, alo, vh, t; \
|
|
ob = (stbsp__int64)xh; \
|
|
vh = (double)ob; \
|
|
ahi = (xh - vh); \
|
|
t = (ahi - xh); \
|
|
alo = (xh - (ahi - t)) - (vh + t); \
|
|
ob += (stbsp__int64)(ahi + alo + xl); \
|
|
}
|
|
|
|
#define stbsp__ddrenorm(oh, ol) \
|
|
{ \
|
|
double s; \
|
|
s = oh + ol; \
|
|
ol = ol - (s - oh); \
|
|
oh = s; \
|
|
}
|
|
|
|
#define stbsp__ddmultlo(oh, ol, xh, xl, yh, yl) ol = ol + (xh * yl + xl * yh);
|
|
|
|
#define stbsp__ddmultlos(oh, ol, xh, yl) ol = ol + (xh * yl);
|
|
|
|
static void stbsp__raise_to_power10(double *ohi, double *olo, double d, stbsp__int32 power) // power can be -323 to +350
|
|
{
|
|
double ph, pl;
|
|
if ((power >= 0) && (power <= 22)) {
|
|
stbsp__ddmulthi(ph, pl, d, stbsp__bot[power]);
|
|
} else {
|
|
stbsp__int32 e, et, eb;
|
|
double p2h, p2l;
|
|
|
|
e = power;
|
|
if (power < 0)
|
|
e = -e;
|
|
et = (e * 0x2c9) >> 14; /* %23 */
|
|
if (et > 13)
|
|
et = 13;
|
|
eb = e - (et * 23);
|
|
|
|
ph = d;
|
|
pl = 0.0;
|
|
if (power < 0) {
|
|
if (eb) {
|
|
--eb;
|
|
stbsp__ddmulthi(ph, pl, d, stbsp__negbot[eb]);
|
|
stbsp__ddmultlos(ph, pl, d, stbsp__negboterr[eb]);
|
|
}
|
|
if (et) {
|
|
stbsp__ddrenorm(ph, pl);
|
|
--et;
|
|
stbsp__ddmulthi(p2h, p2l, ph, stbsp__negtop[et]);
|
|
stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__negtop[et], stbsp__negtoperr[et]);
|
|
ph = p2h;
|
|
pl = p2l;
|
|
}
|
|
} else {
|
|
if (eb) {
|
|
e = eb;
|
|
if (eb > 22)
|
|
eb = 22;
|
|
e -= eb;
|
|
stbsp__ddmulthi(ph, pl, d, stbsp__bot[eb]);
|
|
if (e) {
|
|
stbsp__ddrenorm(ph, pl);
|
|
stbsp__ddmulthi(p2h, p2l, ph, stbsp__bot[e]);
|
|
stbsp__ddmultlos(p2h, p2l, stbsp__bot[e], pl);
|
|
ph = p2h;
|
|
pl = p2l;
|
|
}
|
|
}
|
|
if (et) {
|
|
stbsp__ddrenorm(ph, pl);
|
|
--et;
|
|
stbsp__ddmulthi(p2h, p2l, ph, stbsp__top[et]);
|
|
stbsp__ddmultlo(p2h, p2l, ph, pl, stbsp__top[et], stbsp__toperr[et]);
|
|
ph = p2h;
|
|
pl = p2l;
|
|
}
|
|
}
|
|
}
|
|
stbsp__ddrenorm(ph, pl);
|
|
*ohi = ph;
|
|
*olo = pl;
|
|
}
|
|
|
|
// given a float value, returns the significant bits in bits, and the position of the
|
|
// decimal point in decimal_pos. +/-INF and NAN are specified by special values
|
|
// returned in the decimal_pos parameter.
|
|
// frac_digits is absolute normally, but if you want from first significant digits (got %g and %e), or in 0x80000000
|
|
static stbsp__int32 stbsp__real_to_str(char const **start, stbsp__uint32 *len, char *out, stbsp__int32 *decimal_pos, double value, stbsp__uint32 frac_digits)
|
|
{
|
|
double d;
|
|
stbsp__int64 bits = 0;
|
|
stbsp__int32 expo, e, ng, tens;
|
|
|
|
d = value;
|
|
STBSP__COPYFP(bits, d);
|
|
expo = (stbsp__int32)((bits >> 52) & 2047);
|
|
ng = (stbsp__int32)((stbsp__uint64) bits >> 63);
|
|
if (ng)
|
|
d = -d;
|
|
|
|
if (expo == 2047) // is nan or inf?
|
|
{
|
|
*start = (bits & ((((stbsp__uint64)1) << 52) - 1)) ? "NaN" : "Inf";
|
|
*decimal_pos = STBSP__SPECIAL;
|
|
*len = 3;
|
|
return ng;
|
|
}
|
|
|
|
if (expo == 0) // is zero or denormal
|
|
{
|
|
if (((stbsp__uint64) bits << 1) == 0) // do zero
|
|
{
|
|
*decimal_pos = 1;
|
|
*start = out;
|
|
out[0] = '0';
|
|
*len = 1;
|
|
return ng;
|
|
}
|
|
// find the right expo for denormals
|
|
{
|
|
stbsp__int64 v = ((stbsp__uint64)1) << 51;
|
|
while ((bits & v) == 0) {
|
|
--expo;
|
|
v >>= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// find the decimal exponent as well as the decimal bits of the value
|
|
{
|
|
double ph, pl;
|
|
|
|
// log10 estimate - very specifically tweaked to hit or undershoot by no more than 1 of log10 of all expos 1..2046
|
|
tens = expo - 1023;
|
|
tens = (tens < 0) ? ((tens * 617) / 2048) : (((tens * 1233) / 4096) + 1);
|
|
|
|
// move the significant bits into position and stick them into an int
|
|
stbsp__raise_to_power10(&ph, &pl, d, 18 - tens);
|
|
|
|
// get full as much precision from double-double as possible
|
|
stbsp__ddtoS64(bits, ph, pl);
|
|
|
|
// check if we undershot
|
|
if (((stbsp__uint64)bits) >= stbsp__tento19th)
|
|
++tens;
|
|
}
|
|
|
|
// now do the rounding in integer land
|
|
frac_digits = (frac_digits & 0x80000000) ? ((frac_digits & 0x7ffffff) + 1) : (tens + frac_digits);
|
|
if ((frac_digits < 24)) {
|
|
stbsp__uint32 dg = 1;
|
|
if ((stbsp__uint64)bits >= stbsp__powten[9])
|
|
dg = 10;
|
|
while ((stbsp__uint64)bits >= stbsp__powten[dg]) {
|
|
++dg;
|
|
if (dg == 20)
|
|
goto noround;
|
|
}
|
|
if (frac_digits < dg) {
|
|
stbsp__uint64 r;
|
|
// add 0.5 at the right position and round
|
|
e = dg - frac_digits;
|
|
if ((stbsp__uint32)e >= 24)
|
|
goto noround;
|
|
r = stbsp__powten[e];
|
|
bits = bits + (r / 2);
|
|
if ((stbsp__uint64)bits >= stbsp__powten[dg])
|
|
++tens;
|
|
bits /= r;
|
|
}
|
|
noround:;
|
|
}
|
|
|
|
// kill long trailing runs of zeros
|
|
if (bits) {
|
|
stbsp__uint32 n;
|
|
for (;;) {
|
|
if (bits <= 0xffffffff)
|
|
break;
|
|
if (bits % 1000)
|
|
goto donez;
|
|
bits /= 1000;
|
|
}
|
|
n = (stbsp__uint32)bits;
|
|
while ((n % 1000) == 0)
|
|
n /= 1000;
|
|
bits = n;
|
|
donez:;
|
|
}
|
|
|
|
// convert to string
|
|
out += 64;
|
|
e = 0;
|
|
for (;;) {
|
|
stbsp__uint32 n;
|
|
char *o = out - 8;
|
|
// do the conversion in chunks of U32s (avoid most 64-bit divides, worth it, constant denomiators be damned)
|
|
if (bits >= 100000000) {
|
|
n = (stbsp__uint32)(bits % 100000000);
|
|
bits /= 100000000;
|
|
} else {
|
|
n = (stbsp__uint32)bits;
|
|
bits = 0;
|
|
}
|
|
while (n) {
|
|
out -= 2;
|
|
*(stbsp__uint16 *)out = *(stbsp__uint16 *)&stbsp__digitpair.pair[(n % 100) * 2];
|
|
n /= 100;
|
|
e += 2;
|
|
}
|
|
if (bits == 0) {
|
|
if ((e) && (out[0] == '0')) {
|
|
++out;
|
|
--e;
|
|
}
|
|
break;
|
|
}
|
|
while (out != o) {
|
|
*--out = '0';
|
|
++e;
|
|
}
|
|
}
|
|
|
|
*decimal_pos = tens;
|
|
*start = out;
|
|
*len = e;
|
|
return ng;
|
|
}
|
|
|
|
#undef stbsp__ddmulthi
|
|
#undef stbsp__ddrenorm
|
|
#undef stbsp__ddmultlo
|
|
#undef stbsp__ddmultlos
|
|
#undef STBSP__SPECIAL
|
|
#undef STBSP__COPYFP
|
|
|
|
#endif // STB_SPRINTF_NOFLOAT
|
|
|
|
// clean up
|
|
#undef stbsp__uint16
|
|
#undef stbsp__uint32
|
|
#undef stbsp__int32
|
|
#undef stbsp__uint64
|
|
#undef stbsp__int64
|
|
#undef STBSP__UNALIGNED
|
|
|
|
#endif // STB_SPRINTF_IMPLEMENTATION
|
|
|
|
/*
|
|
------------------------------------------------------------------------------
|
|
This software is available under 2 licenses -- choose whichever you prefer.
|
|
------------------------------------------------------------------------------
|
|
ALTERNATIVE A - MIT License
|
|
Copyright (c) 2017 Sean Barrett
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
this software and associated documentation files (the "Software"), to deal in
|
|
the Software without restriction, including without limitation the rights to
|
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
of the Software, and to permit persons to whom the Software is furnished to do
|
|
so, subject to the following conditions:
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
------------------------------------------------------------------------------
|
|
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
|
This is free and unencumbered software released into the public domain.
|
|
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
|
software, either in source code form or as a compiled binary, for any purpose,
|
|
commercial or non-commercial, and by any means.
|
|
In jurisdictions that recognize copyright laws, the author or authors of this
|
|
software dedicate any and all copyright interest in the software to the public
|
|
domain. We make this dedication for the benefit of the public at large and to
|
|
the detriment of our heirs and successors. We intend this dedication to be an
|
|
overt act of relinquishment in perpetuity of all present and future rights to
|
|
this software under copyright law.
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
------------------------------------------------------------------------------
|
|
*/
|
|
DN_GCC_WARNING_POP
|
|
DN_MSVC_WARNING_POP
|
|
|
|
#define DN_SPrintF(...) STB_SPRINTF_DECORATE(sprintf)(__VA_ARGS__)
|
|
#define DN_SNPrintF(...) STB_SPRINTF_DECORATE(snprintf)(__VA_ARGS__)
|
|
#define DN_VSPrintF(...) STB_SPRINTF_DECORATE(vsprintf)(__VA_ARGS__)
|
|
#define DN_VSNPrintF(...) STB_SPRINTF_DECORATE(vsnprintf)(__VA_ARGS__)
|
|
|
|
DN_API bool DN_MemStartsWith (void const *lhs, DN_USize lhs_size, void const *rhs, DN_USize rhs_size);
|
|
DN_API bool DN_MemEq (void const *lhs, DN_USize lhs_size, void const *rhs, DN_USize rhs_size);
|
|
DN_API bool DN_MemEqUnsafe (void const *lhs, void const *rhs, DN_USize size);
|
|
|
|
DN_API DN_U64 DN_AtomicSetValue64 (DN_U64 volatile *target, DN_U64 value);
|
|
DN_API DN_U32 DN_AtomicSetValue32 (DN_U32 volatile *target, DN_U32 value);
|
|
DN_API DN_USize DN_AlignUpPowerOfTwoUSize (DN_USize val);
|
|
DN_API DN_U64 DN_AlignUpPowerOfTwoU64 (DN_U64 val);
|
|
DN_API DN_U32 DN_AlignUpPowerOfTwoU32 (DN_U32 val);
|
|
|
|
DN_API void DN_ByteSwapU64Ptr (DN_U8* dest, DN_U64 src);
|
|
#define DN_ByteSwap64(val) ( \
|
|
(((((DN_U64)(val)) >> 56) & 0xFF) << 0) | \
|
|
(((((DN_U64)(val)) >> 48) & 0xFF) << 8) | \
|
|
(((((DN_U64)(val)) >> 40) & 0xFF) << 16) | \
|
|
(((((DN_U64)(val)) >> 32) & 0xFF) << 24) | \
|
|
(((((DN_U64)(val)) >> 24) & 0xFF) << 32) | \
|
|
(((((DN_U64)(val)) >> 16) & 0xFF) << 40) | \
|
|
(((((DN_U64)(val)) >> 8) & 0xFF) << 48) | \
|
|
(((((DN_U64)(val)) >> 0) & 0xFF) << 56) \
|
|
)
|
|
#define DN_ByteSwap32(val) ( \
|
|
(((((DN_U32)(val)) >> 24) & 0xFF) << 0) | \
|
|
(((((DN_U32)(val)) >> 16) & 0xFF) << 8) | \
|
|
(((((DN_U32)(val)) >> 8) & 0xFF) << 16) | \
|
|
(((((DN_U32)(val)) >> 0) & 0xFF) << 24) \
|
|
)
|
|
#define DN_ByteSwap24(val) ( \
|
|
(((((DN_U32)(val)) >> 16) & 0xFF) << 0) | \
|
|
(((((DN_U32)(val)) >> 8) & 0xFF) << 8) | \
|
|
(((((DN_U32)(val)) >> 0) & 0xFF) << 16) \
|
|
)
|
|
#define DN_ByteSwap16(val) ( \
|
|
(((((DN_U16)(val)) >> 8) & 0xFF) << 0) | \
|
|
(((((DN_U16)(val)) >> 0) & 0xFF) << 8) \
|
|
)
|
|
#if defined(DN_64_BIT)
|
|
#define DN_ByteSwapUSize(val) DN_ByteSwap64(val)
|
|
#else
|
|
#define DN_ByteSwapUSize(val) DN_ByteSwap32(val)
|
|
#endif
|
|
|
|
|
|
DN_API DN_CPUIDResult DN_CPUID (DN_CPUIDArgs args);
|
|
DN_API DN_USize DN_CPUHasFeatureArray (DN_CPUReport const *report, DN_CPUFeatureQuery *features, DN_USize features_size);
|
|
DN_API bool DN_CPUHasFeature (DN_CPUReport const *report, DN_CPUFeature feature);
|
|
DN_API bool DN_CPUHasAllFeatures (DN_CPUReport const *report, DN_CPUFeature const *features, DN_USize features_size);
|
|
DN_API void DN_CPUSetFeature (DN_CPUReport *report, DN_CPUFeature feature);
|
|
DN_API DN_CPUReport DN_CPUGetReport ();
|
|
|
|
DN_API void DN_TicketMutex_Begin (DN_TicketMutex *mutex);
|
|
DN_API void DN_TicketMutex_End (DN_TicketMutex *mutex);
|
|
DN_API DN_UInt DN_TicketMutex_MakeTicket (DN_TicketMutex *mutex);
|
|
DN_API void DN_TicketMutex_BeginTicket (DN_TicketMutex const *mutex, DN_UInt ticket);
|
|
DN_API bool DN_TicketMutex_CanLock (DN_TicketMutex const *mutex, DN_UInt ticket);
|
|
|
|
DN_API void DN_BitUnsetInplace (DN_USize *flags, DN_USize bitfield);
|
|
DN_API void DN_BitSetInplace (DN_USize *flags, DN_USize bitfield);
|
|
DN_API bool DN_BitIsSet (DN_USize bits, DN_USize bits_to_set);
|
|
DN_API bool DN_BitIsNotSet (DN_USize bits, DN_USize bits_to_check);
|
|
#define DN_BitClearNextLSB(value) (value) & ((value) - 1)
|
|
|
|
DN_API DN_I64 DN_SafeAddI64 (DN_I64 a, DN_I64 b);
|
|
DN_API DN_I64 DN_SafeMulI64 (DN_I64 a, DN_I64 b);
|
|
|
|
DN_API DN_U64 DN_SafeAddU64 (DN_U64 a, DN_U64 b);
|
|
DN_API DN_U64 DN_SafeMulU64 (DN_U64 a, DN_U64 b);
|
|
|
|
DN_API DN_U64 DN_SafeSubU64 (DN_U64 a, DN_U64 b);
|
|
DN_API DN_U32 DN_SafeSubU32 (DN_U32 a, DN_U32 b);
|
|
|
|
DN_API int DN_SaturateCastUSizeToInt (DN_USize val);
|
|
DN_API DN_I8 DN_SaturateCastUSizeToI8 (DN_USize val);
|
|
DN_API DN_I16 DN_SaturateCastUSizeToI16 (DN_USize val);
|
|
DN_API DN_I32 DN_SaturateCastUSizeToI32 (DN_USize val);
|
|
DN_API DN_I64 DN_SaturateCastUSizeToI64 (DN_USize val);
|
|
|
|
DN_API int DN_SaturateCastU64ToInt (DN_U64 val);
|
|
DN_API DN_I8 DN_SaturateCastU8ToI8 (DN_U64 val);
|
|
DN_API DN_I16 DN_SaturateCastU16ToI16 (DN_U64 val);
|
|
DN_API DN_I32 DN_SaturateCastU32ToI32 (DN_U64 val);
|
|
DN_API DN_I64 DN_SaturateCastU64ToI64 (DN_U64 val);
|
|
DN_API DN_UInt DN_SaturateCastU64ToUInt (DN_U64 val);
|
|
DN_API DN_U8 DN_SaturateCastU64ToU8 (DN_U64 val);
|
|
DN_API DN_U16 DN_SaturateCastU64ToU16 (DN_U64 val);
|
|
DN_API DN_U32 DN_SaturateCastU64ToU32 (DN_U64 val);
|
|
|
|
DN_API DN_U8 DN_SaturateCastUSizeToU8 (DN_USize val);
|
|
DN_API DN_U16 DN_SaturateCastUSizeToU16 (DN_USize val);
|
|
DN_API DN_U32 DN_SaturateCastUSizeToU32 (DN_USize val);
|
|
DN_API DN_U64 DN_SaturateCastUSizeToU64 (DN_USize val);
|
|
|
|
DN_API int DN_SaturateCastISizeToInt (DN_ISize val);
|
|
DN_API DN_I8 DN_SaturateCastISizeToI8 (DN_ISize val);
|
|
DN_API DN_I16 DN_SaturateCastISizeToI16 (DN_ISize val);
|
|
DN_API DN_I32 DN_SaturateCastISizeToI32 (DN_ISize val);
|
|
DN_API DN_I64 DN_SaturateCastISizeToI64 (DN_ISize val);
|
|
|
|
DN_API DN_UInt DN_SaturateCastISizeToUInt (DN_ISize val);
|
|
DN_API DN_U8 DN_SaturateCastISizeToU8 (DN_ISize val);
|
|
DN_API DN_U16 DN_SaturateCastISizeToU16 (DN_ISize val);
|
|
DN_API DN_U32 DN_SaturateCastISizeToU32 (DN_ISize val);
|
|
DN_API DN_U64 DN_SaturateCastISizeToU64 (DN_ISize val);
|
|
|
|
DN_API DN_ISize DN_SaturateCastI64ToISize (DN_I64 val);
|
|
DN_API DN_I8 DN_SaturateCastI64ToI8 (DN_I64 val);
|
|
DN_API DN_I16 DN_SaturateCastI64ToI16 (DN_I64 val);
|
|
DN_API DN_I32 DN_SaturateCastI64ToI32 (DN_I64 val);
|
|
|
|
DN_API DN_UInt DN_SaturateCastI64ToUInt (DN_I64 val);
|
|
DN_API DN_ISize DN_SaturateCastI64ToUSize (DN_I64 val);
|
|
DN_API DN_U8 DN_SaturateCastI64ToU8 (DN_I64 val);
|
|
DN_API DN_U16 DN_SaturateCastI64ToU16 (DN_I64 val);
|
|
DN_API DN_U32 DN_SaturateCastI64ToU32 (DN_I64 val);
|
|
DN_API DN_U64 DN_SaturateCastI64ToU64 (DN_I64 val);
|
|
|
|
DN_API DN_I8 DN_SaturateCastIntToI8 (int val);
|
|
DN_API DN_I16 DN_SaturateCastIntToI16 (int val);
|
|
DN_API DN_U8 DN_SaturateCastIntToU8 (int val);
|
|
DN_API DN_U16 DN_SaturateCastIntToU16 (int val);
|
|
DN_API DN_U32 DN_SaturateCastIntToU32 (int val);
|
|
DN_API DN_U64 DN_SaturateCastIntToU64 (int val);
|
|
|
|
DN_API void DN_ASanPoisonMemoryRegion (void const volatile *ptr, DN_USize size);
|
|
DN_API void DN_ASanUnpoisonMemoryRegion (void const volatile *ptr, DN_USize size);
|
|
|
|
DN_API DN_F32 DN_EpsilonClampF32 (DN_F32 value, DN_F32 target, DN_F32 epsilon);
|
|
|
|
DN_API DN_MemStats DN_MemStatsSum (DN_MemStats lhs, DN_MemStats rhs);
|
|
DN_API DN_MemStats DN_MemStatsSumArray (DN_MemStats const *array, DN_USize size);
|
|
|
|
DN_API DN_MemList DN_MemListFromBuffer (void *buffer, DN_USize size, DN_MemFlags flags);
|
|
DN_API DN_MemList DN_MemListFromMemFuncs (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags, DN_MemFuncs mem_funcs);
|
|
DN_API void DN_MemListDeinit (DN_MemList *mem);
|
|
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_MemListGrow (DN_MemList *mem, DN_U64 reserve, DN_U64 commit);
|
|
DN_API void * DN_MemListAlloc (DN_MemList *mem, DN_U64 size, uint8_t align, DN_ZMem zmem);
|
|
DN_API void * DN_MemListAllocContiguous (DN_MemList *mem, DN_U64 size, uint8_t align, DN_ZMem zmem);
|
|
DN_API void * DN_MemListCopy (DN_MemList *mem, void const *data, DN_U64 size, uint8_t align);
|
|
DN_API void DN_MemListPopTo (DN_MemList *mem, DN_U64 init_used);
|
|
DN_API void DN_MemListPop (DN_MemList *mem, DN_U64 amount);
|
|
DN_API DN_U64 DN_MemListPos (DN_MemList const *mem);
|
|
DN_API void DN_MemListClear (DN_MemList *mem);
|
|
DN_API bool DN_MemListOwnsPtr (DN_MemList const *mem, void *ptr);
|
|
DN_API DN_Str8x64 DN_MemListInfoStr8x64 (DN_MemListInfo info);
|
|
DN_API DN_MemListTemp DN_MemListTempBegin (DN_MemList *mem);
|
|
DN_API void DN_MemListTempEnd (DN_MemListTemp mem);
|
|
#define DN_MemListNew(arena, T, zmem) (T *)DN_MemListAlloc(arena, sizeof(T), alignof(T), zmem)
|
|
#define DN_MemListNewZ(arena, T) (T *)DN_MemListAlloc(arena, sizeof(T), alignof(T), DN_ZMem_Yes)
|
|
#define DN_MemListNewContiguous(arena, T, zmem) (T *)DN_MemListAllocContiguous(arena, sizeof(T), alignof(T), zmem)
|
|
#define DN_MemListNewContiguousZ(arena, T) (T *)DN_MemListAllocContiguous(arena, sizeof(T), alignof(T), DN_ZMem_Yes)
|
|
#define DN_MemListNewArray(arena, T, count, zmem) (T *)DN_MemListAlloc(arena, sizeof(T) * (count), alignof(T), zmem)
|
|
#define DN_MemListNewArrayZ(arena, T, count) (T *)DN_MemListAlloc(arena, sizeof(T) * (count), alignof(T), DN_ZMem_Yes)
|
|
#define DN_MemListNewArrayNoZ(arena, T, count) (T *)DN_MemListAlloc(arena, sizeof(T) * (count), alignof(T), DN_ZMem_No)
|
|
#define DN_MemListNewCopy(arena, T, src) (T *)DN_MemListCopy(arena, (src), sizeof(T), alignof(T))
|
|
#define DN_MemListNewArrayCopy(arena, T, src, count) (T *)DN_MemListCopy(arena, (src), sizeof(T) * (count), alignof(T))
|
|
|
|
DN_API void DN_ArenaUAFCheck (DN_Arena *arena);
|
|
#define DN_ArenaDeref(arena_view) (DN_ArenaUAFCheck(arena_view), (arena_view)->arena)
|
|
DN_API DN_Arena DN_ArenaFromMemList (DN_MemList *mem);
|
|
DN_API DN_Arena DN_ArenaTempBeginFromMemList (DN_MemList *mem);
|
|
DN_API DN_Arena DN_ArenaTempBeginFromArena (DN_Arena *arena);
|
|
DN_API void DN_ArenaTempEnd (DN_Arena *arena, DN_ArenaReset reset);
|
|
DN_API void* DN_ArenaAlloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZMem z_mem);
|
|
DN_API void* DN_ArenaAllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZMem z_arena);
|
|
DN_API void* DN_ArenaCopy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align);
|
|
|
|
#define DN_ArenaNew(arena, T, zmem) (T *)DN_ArenaAlloc(arena, sizeof(T), alignof(T), zmem)
|
|
#define DN_ArenaNewZ(arena, T) (T *)DN_ArenaAlloc(arena, sizeof(T), alignof(T), DN_ZMem_Yes)
|
|
#define DN_ArenaNewContiguous(arena, T, zmem) (T *)DN_ArenaAllocContiguous(arena, sizeof(T), alignof(T), zmem)
|
|
#define DN_ArenaNewContiguousZ(arena, T) (T *)DN_ArenaAllocContiguous(arena, sizeof(T), alignof(T), DN_ZMem_Yes)
|
|
#define DN_ArenaNewArray(arena, T, count, zmem) (T *)DN_ArenaAlloc(arena, sizeof(T) * (count), alignof(T), zmem)
|
|
#define DN_ArenaNewArrayZ(arena, T, count) (T *)DN_ArenaAlloc(arena, sizeof(T) * (count), alignof(T), DN_ZMem_Yes)
|
|
#define DN_ArenaNewArrayNoZ(arena, T, count) (T *)DN_ArenaAlloc(arena, sizeof(T) * (count), alignof(T), DN_ZMem_No)
|
|
#define DN_ArenaNewCopy(arena, T, src) (T *)DN_ArenaCopy(arena, (src), sizeof(T), alignof(T))
|
|
#define DN_ArenaNewArrayCopy(arena, T, src, count) (T *)DN_ArenaCopy(arena, (src), sizeof(T) * (count), alignof(T))
|
|
|
|
DN_API DN_Pool DN_PoolFromArena (DN_Arena *arena, DN_U8 align);
|
|
DN_API bool DN_PoolIsValid (DN_Pool const *pool);
|
|
DN_API void * DN_PoolAlloc (DN_Pool *pool, DN_USize size);
|
|
DN_API void DN_PoolDealloc (DN_Pool *pool, void *ptr);
|
|
DN_API void * DN_PoolCopy (DN_Pool *pool, void const *data, DN_U64 size, uint8_t align);
|
|
#define DN_PoolNew(pool, T) (T *)DN_PoolAlloc(pool, sizeof(T))
|
|
#define DN_PoolNewArray(pool, T, count) (T *)DN_PoolAlloc(pool, count * sizeof(T))
|
|
#define DN_PoolNewCopy(pool, T, src) (T *)DN_PoolCopy (pool, (src), sizeof(T), alignof(T))
|
|
#define DN_PoolNewArrayCopy(pool, T, src, count) (T *)DN_PoolCopy (pool, (src), sizeof(T) * (count), alignof(T))
|
|
|
|
DN_API DN_ErrSink* DN_ErrSinkBegin_ (DN_ErrSink *err, DN_ErrSinkMode mode, DN_CallSite call_site);
|
|
#define DN_ErrSinkBegin(err, mode) DN_ErrSinkBegin_(err, mode, DN_CALL_SITE)
|
|
#define DN_ErrSinkBeginDefault(err) DN_ErrSinkBegin(err, DN_ErrSinkMode_Nil)
|
|
DN_API bool DN_ErrSinkHasError (DN_ErrSink *err);
|
|
DN_API DN_ErrSinkMsg* DN_ErrSinkEnd (DN_Arena *arena, DN_ErrSink *err);
|
|
DN_API DN_Str8 DN_ErrSinkEndStr8 (DN_Arena *arena, DN_ErrSink *err);
|
|
DN_API void DN_ErrSinkEndIgnore (DN_ErrSink *err);
|
|
DN_API bool DN_ErrSinkEndLogError_ (DN_ErrSink *err, DN_CallSite call_site, DN_Str8 msg);
|
|
#define DN_ErrSinkEndLogError(err, err_msg) DN_ErrSinkEndLogError_(err, DN_CALL_SITE, err_msg)
|
|
DN_API bool DN_ErrSinkEndLogErrorFV_ (DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
#define DN_ErrSinkEndLogErrorFV(err, fmt, args) DN_ErrSinkEndLogErrorFV_(err, DN_CALL_SITE, fmt, args)
|
|
DN_API bool DN_ErrSinkEndLogErrorF_ (DN_ErrSink *err, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
|
|
#define DN_ErrSinkEndLogErrorF(err, fmt, ...) DN_ErrSinkEndLogErrorF_(err, DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
|
DN_API void DN_ErrSinkEndExitIfErrorF_ (DN_ErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, ...);
|
|
#define DN_ErrSinkEndExitIfErrorF(err, exit_val, fmt, ...) DN_ErrSinkEndExitIfErrorF_(err, DN_CALL_SITE, exit_val, fmt, ##__VA_ARGS__)
|
|
DN_API void DN_ErrSinkEndExitIfErrorFV_ (DN_ErrSink *err, DN_CallSite call_site, DN_U32 exit_val, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
#define DN_ErrSinkEndExitIfErrorFV(err, exit_val, fmt, args) DN_ErrSinkEndExitIfErrorFV_(err, DN_CALL_SITE, exit_val, fmt, args)
|
|
DN_API void DN_ErrSinkAppendFV_ (DN_ErrSink *err, DN_U32 error_code, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
#define DN_ErrSinkAppendFV(error, error_code, fmt, args) DN_ErrSinkAppendFV_(error, error_code, DN_CALL_SITE, fmt, args)
|
|
DN_API void DN_ErrSinkAppendF_ (DN_ErrSink *err, DN_U32 error_code, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, ...);
|
|
#define DN_ErrSinkAppendF(error, error_code, fmt, ...) DN_ErrSinkAppendF_(error, error_code, DN_CALL_SITE, fmt, ##__VA_ARGS__)
|
|
|
|
DN_API void DN_TCInit (DN_TCCore *tc, DN_U64 thread_id, DN_Arena *main_arena, DN_Arena *temp_a_arena, DN_Arena *temp_b_arena, DN_Arena *err_sink_arena);
|
|
DN_API void DN_TCInitFromMemFuncs (DN_TCCore *tc, DN_U64 thread_id, DN_TCInitArgs *args, DN_MemFuncs mem_funcs);
|
|
DN_API void DN_TCDeinit (DN_TCCore *tc, DN_TCDeinitArenas deinit_arenas);
|
|
DN_API void DN_TCEquip (DN_TCCore *tc);
|
|
DN_API DN_TCCore* DN_TCGet ();
|
|
DN_API DN_Arena* DN_TCMainArena ();
|
|
DN_API DN_Pool* DN_TCMainPool ();
|
|
DN_API DN_Arena DN_TCTempArena (DN_Arena **conflicts, DN_USize count);
|
|
DN_API DN_TCScratch DN_TCScratchBegin (DN_Arena **conflicts, DN_USize count);
|
|
DN_API void DN_TCScratchEnd (DN_TCScratch *scratch);
|
|
DN_API void DN_TCSetFrameArena (DN_Arena *arena);
|
|
DN_API DN_Arena* DN_TCFrameArena ();
|
|
DN_API DN_ErrSink* DN_TCErrSink ();
|
|
#define DN_TCErrSinkBegin(mode) DN_ErrSinkBegin(DN_TCErrSink(), mode)
|
|
#define DN_TCErrSinkBeginDefault() DN_ErrSinkBeginDefault(DN_TCErrSink())
|
|
|
|
DN_API bool DN_CharIsAlphabet (char ch);
|
|
DN_API bool DN_CharIsDigit (char ch);
|
|
DN_API bool DN_CharIsAlphaNum (char ch);
|
|
DN_API bool DN_CharIsWhitespace (char ch);
|
|
DN_API bool DN_CharIsHex (char ch);
|
|
DN_API char DN_CharToLower (char ch);
|
|
DN_API char DN_CharToUpper (char ch);
|
|
|
|
DN_API DN_U64FromResult DN_U64FromStr8 (DN_Str8 string, char separator);
|
|
DN_API DN_U64FromResult DN_U64FromPtr (void const *data, DN_USize size, char separator);
|
|
DN_API DN_U64 DN_U64FromPtrUnsafe (void const *data, DN_USize size, char separator);
|
|
DN_API DN_U64FromResult DN_U64FromHexPtr (void const *hex, DN_USize hex_count);
|
|
DN_API DN_U64 DN_U64FromHexPtrUnsafe (void const *hex, DN_USize hex_count);
|
|
DN_API DN_U64FromResult DN_U64FromHexStr8 (DN_Str8 hex);
|
|
DN_API DN_U64 DN_U64FromHexStr8Unsafe (DN_Str8 hex);
|
|
DN_API DN_U64 DN_U64FromU8x32HiBEUnsafe (DN_U8x32 const *val); // Get U64 stored in big-endian at the high bytes [24:32)
|
|
DN_API DN_U64FromResult DN_U64FromU8x32HiBE (DN_U8x32 const *val); // Checks [0:24) bytes aren't set before getting the U64
|
|
DN_API DN_USize DN_USizeFromU8x32HiBEUnsafe (DN_U8x32 const *val); // Get USize stored in big-endian at the high bytes [32 - sizeof USize:32)
|
|
DN_API DN_USizeFromResult DN_USizeFromU8x32HiBE (DN_U8x32 const *val); // Checks [0:sizeof USize) bytes aren't set before getting the U64
|
|
DN_API DN_I64FromResult DN_I64FromStr8 (DN_Str8 string, char separator);
|
|
DN_API DN_I64FromResult DN_I64FromPtr (void const *data, DN_USize size, char separator);
|
|
DN_API DN_I64 DN_I64FromPtrUnsafe (void const *data, DN_USize size, char separator);
|
|
|
|
DN_API bool DN_U8x32Eq (DN_U8x32 const *lhs, DN_U8x32 const *rhs);
|
|
DN_API DN_U8x32 DN_U8x32FromBytesLeftPadZ (DN_U8 const *ptr, DN_USize count);
|
|
DN_API DN_U8x32 DN_U8x32FromHexUnsafe (DN_Str8 hex_32b);
|
|
DN_API DN_U8x32FromResult DN_U8x32FromHex (DN_Str8 hex_32b);
|
|
DN_API DN_U8x32FromResult DN_U8x32FromDecimalStr8 (DN_Str8 decimal); // Write decimal string (e.g. "12345") as big-endian 256-bit value
|
|
|
|
DN_API DN_USize DN_FmtVSize (DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_USize DN_FmtSize (DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_FmtAppendResult DN_FmtVAppend (char *buf, DN_USize *buf_size, DN_USize buf_max, char const *fmt, va_list args);
|
|
DN_API DN_FmtAppendResult DN_FmtAppend (char *buf, DN_USize *buf_size, DN_USize buf_max, char const *fmt, ...);
|
|
DN_API DN_FmtAppendResult DN_FmtAppendTruncate (char *buf, DN_USize *buf_size, DN_USize buf_max, DN_Str8 truncator, char const *fmt, ...);
|
|
DN_API DN_USize DN_CStr8Size (char const *src);
|
|
DN_API DN_USize DN_CStr16Size (wchar_t const *src);
|
|
|
|
#define DN_Str16Lit(string) DN_Str16{(wchar_t *)(string), sizeof(string)/sizeof(string[0]) - 1}
|
|
#define DN_Str16FromPtr(data, size) DN_Literal(DN_Str16){(wchar_t *)(data), (DN_USize)(size)}
|
|
|
|
#define DN_Str8Lit(c_str) DN_Literal(DN_Str8){(char *)(c_str), sizeof(c_str) - 1}
|
|
#define DN_Str8PrintFmt(string) (int)((string).size), (string).data
|
|
#define DN_Str8FromPtr(data, size) DN_Literal(DN_Str8){(char *)(data), (DN_USize)(size)}
|
|
#define DN_Str8FromStruct(ptr) DN_Str8FromPtr((ptr)->data, (ptr)->size)
|
|
#define DN_Str8FromLitArray(c_array) DN_Str8FromPtr(c_array, DN_ArrayCountU(c_array))
|
|
DN_API DN_Str8 DN_Str8AllocArena (DN_USize size, DN_ZMem z_mem, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8AllocPool (DN_USize size, DN_Pool *pool);
|
|
DN_API DN_Str8 DN_Str8FromCStr8 (char const *src);
|
|
DN_API DN_Str8 DN_Str8FromCStr8Arena (char const *src, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8FromPtrArena (void const *data, DN_USize size, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8FromPtrPool (void const *data, DN_USize size, DN_Pool *pool);
|
|
DN_API DN_Str8 DN_Str8FromStr8Arena (DN_Str8 string, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8FromStr8Pool (DN_Str8 string, DN_Pool *pool);
|
|
DN_API DN_Str8 DN_Str8FromFmtVArena (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_Str8 DN_Str8FromFmtArena (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8 DN_Str8FromFmtVPool (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_Str8 DN_Str8FromFmtPool (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8 DN_Str8FromByteCountType (DN_ByteCountType type);
|
|
DN_API DN_Str8x16 DN_Str8x16FromFmt (DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8x16 DN_Str8x16FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_Str8x32 DN_Str8x32FromFmt (DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8x32 DN_Str8x32FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_Str8x64 DN_Str8x64FromFmt (DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8x64 DN_Str8x64FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_Str8x128 DN_Str8x128FromFmt (DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8x256 DN_Str8x256FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_Str8x256 DN_Str8x256FromFmt (DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8x256 DN_Str8x256FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_Str8x512 DN_Str8x512FromFmt (DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8x512 DN_Str8x512FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_Str8x1024 DN_Str8x1024FromFmt (DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8x1024 DN_Str8x1024FromFmtV (DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API void DN_Str8x16AppendFmt (DN_Str8x16 *str, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_Str8x16AppendFmtV (DN_Str8x16 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API void DN_Str8x32AppendFmt (DN_Str8x32 *str, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_Str8x32AppendFmtV (DN_Str8x32 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API void DN_Str8x64AppendFmt (DN_Str8x64 *str, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_Str8x64AppendFmtV (DN_Str8x64 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API void DN_Str8x128AppendFmt (DN_Str8x128 *str, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_Str8x128AppendFmtV (DN_Str8x128 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API void DN_Str8x256AppendFmt (DN_Str8x256 *str, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_Str8x256AppendFmtV (DN_Str8x256 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API void DN_Str8x512AppendFmt (DN_Str8x512 *str, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_Str8x512AppendFmtV (DN_Str8x512 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API void DN_Str8x1024AppendFmt (DN_Str8x1024 *str, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_Str8x1024AppendFmtV (DN_Str8x1024 *str, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_Str8x32 DN_Str8x32FromU64 (DN_U64 val, char separator);
|
|
DN_API bool DN_Str8IsAll (DN_Str8 string, DN_Str8IsAllType is_all);
|
|
DN_API char * DN_Str8End (DN_Str8 string);
|
|
DN_API DN_Str8 DN_Str8Subset (DN_Str8 string, DN_USize offset, DN_USize size);
|
|
DN_API DN_Str8 DN_Str8Advance (DN_Str8 string, DN_USize amount);
|
|
DN_API DN_Str8 DN_Str8NextLine (DN_Str8 string);
|
|
DN_API DN_Str8BSplitResult DN_Str8BSplitArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size);
|
|
DN_API DN_Str8BSplitResult DN_Str8BSplit (DN_Str8 string, DN_Str8 find);
|
|
DN_API DN_Str8BSplitResult DN_Str8BSplitLastArray (DN_Str8 string, DN_Str8 const *find, DN_USize find_size);
|
|
DN_API DN_Str8BSplitResult DN_Str8BSplitLast (DN_Str8 string, DN_Str8 find);
|
|
DN_API DN_USize DN_Str8Split (DN_Str8 string, DN_Str8 delimiter, DN_Str8 *splits, DN_USize splits_count, DN_Str8SplitFlags mode);
|
|
DN_API DN_Str8SplitResult DN_Str8SplitArena (DN_Str8 string, DN_Str8 delimiter, DN_Str8SplitFlags mode, DN_Arena *arena);
|
|
DN_API DN_Str8FindResult DN_Str8FindStr8Array (DN_Str8 string, DN_Str8 const *find, DN_USize find_size, DN_Str8EqCase eq_case);
|
|
DN_API DN_Str8FindResult DN_Str8FindStr8 (DN_Str8 string, DN_Str8 find, DN_Str8EqCase eq_case);
|
|
DN_API DN_Str8FindResult DN_Str8Find (DN_Str8 string, DN_Str8FindFlag flags);
|
|
DN_API DN_Str8 DN_Str8Segment (DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char);
|
|
DN_API DN_Str8 DN_Str8ReverseSegment (DN_Arena *arena, DN_Str8 src, DN_USize segment_size, char segment_char);
|
|
DN_API bool DN_Str8Eq (DN_Str8 lhs, DN_Str8 rhs, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
|
DN_API bool DN_Str8EqInsensitive (DN_Str8 lhs, DN_Str8 rhs);
|
|
DN_API bool DN_Str8StartsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
|
DN_API bool DN_Str8StartsWithInsensitive (DN_Str8 string, DN_Str8 prefix);
|
|
DN_API bool DN_Str8EndsWith (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
|
DN_API bool DN_Str8EndsWithInsensitive (DN_Str8 string, DN_Str8 prefix);
|
|
DN_API bool DN_Str8HasChar (DN_Str8 string, char ch);
|
|
DN_API DN_Str8 DN_Str8TrimPrefix (DN_Str8 string, DN_Str8 prefix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
|
DN_API DN_Str8 DN_Str8TrimHexPrefix (DN_Str8 string);
|
|
DN_API DN_Str8 DN_Str8TrimSuffix (DN_Str8 string, DN_Str8 suffix, DN_Str8EqCase eq_case = DN_Str8EqCase_Sensitive);
|
|
DN_API DN_Str8 DN_Str8TrimAround (DN_Str8 string, DN_Str8 trim_string);
|
|
DN_API DN_Str8 DN_Str8TrimHeadWhitespace (DN_Str8 string);
|
|
DN_API DN_Str8 DN_Str8TrimTailWhitespace (DN_Str8 string);
|
|
DN_API DN_Str8 DN_Str8TrimWhitespaceAround (DN_Str8 string);
|
|
DN_API DN_Str8 DN_Str8TrimByteOrderMark (DN_Str8 string);
|
|
DN_API DN_Str8 DN_Str8FileNameFromPath (DN_Str8 path);
|
|
DN_API DN_Str8 DN_Str8FileNameNoExtension (DN_Str8 path);
|
|
DN_API DN_Str8 DN_Str8FilePathNoExtension (DN_Str8 path);
|
|
DN_API DN_Str8 DN_Str8FileExtension (DN_Str8 path);
|
|
DN_API DN_Str8 DN_Str8FileDirectoryFromPath (DN_Str8 path);
|
|
DN_API DN_Str8 DN_Str8AppendF (DN_Arena *arena, DN_Str8 string, char const *fmt, ...);
|
|
DN_API DN_Str8 DN_Str8AppendFV (DN_Arena *arena, DN_Str8 string, char const *fmt, va_list args);
|
|
DN_API DN_Str8 DN_Str8FillF (DN_Arena *arena, DN_USize count, char const *fmt, ...);
|
|
DN_API DN_Str8 DN_Str8FillFV (DN_Arena *arena, DN_USize count, char const *fmt, va_list args);
|
|
DN_API void DN_Str8Remove (DN_Str8 *string, DN_USize offset, DN_USize size);
|
|
DN_API DN_Str8TruncResult DN_Str8TruncMiddlePtr (DN_Str8 str8, DN_USize side_size, DN_Str8 truncator, char *dest, DN_USize dest_max);
|
|
DN_API DN_Str8TruncResult DN_Str8TruncMiddle (DN_Str8 str8, DN_USize side_size, DN_Str8 truncator, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8Lower (DN_Str8 string, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8Upper (DN_Str8 string, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8Replace (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena, DN_Str8EqCase eq_case);
|
|
DN_API DN_Str8 DN_Str8ReplaceSensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8ReplaceInsensitive (DN_Str8 string, DN_Str8 find, DN_Str8 replace, DN_USize start_index, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8PadNewLines (DN_Str8 string, DN_Str8 pad_string, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8LineBreakStr8 (DN_Str8 src, DN_USize desired_width, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8Table (DN_Str8 const* rows, DN_USize num_rows, DN_USize num_cols, DN_Str8TableFlags flags, DN_Arena *arena);
|
|
|
|
DN_API DN_Str8 DN_Str8SliceRender (DN_Str8Slice array, DN_Str8 separator, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8RenderSpaceSep (DN_Str8Slice array, DN_Arena *arena);
|
|
|
|
DN_API bool DN_Str16Eq (DN_Str16 lhs, DN_Str16 rhs);
|
|
DN_API DN_Str16 DN_Str16SliceRender (DN_Str16Slice array, DN_Str16 separator, DN_Arena *arena);
|
|
DN_API DN_Str16 DN_Str16RenderSpaceSep (DN_Str16Slice array, DN_Arena *arena);
|
|
|
|
DN_API DN_Str8Builder DN_Str8BuilderFromArena (DN_Arena *arena);
|
|
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrRef (DN_Arena *arena, DN_Str8 const *strings, DN_USize size);
|
|
DN_API DN_Str8Builder DN_Str8BuilderFromStr8PtrCopy (DN_Arena *arena, DN_Str8 const *strings, DN_USize size);
|
|
DN_API DN_Str8Builder DN_Str8BuilderFromBuilder (DN_Arena *arena, DN_Str8Builder const *builder);
|
|
DN_API bool DN_Str8BuilderAddArrayRef (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add);
|
|
DN_API bool DN_Str8BuilderAddArrayCopy (DN_Str8Builder *builder, DN_Str8 const *strings, DN_USize size, DN_Str8BuilderAdd add);
|
|
DN_API bool DN_Str8BuilderAddFV (DN_Str8Builder *builder, DN_Str8BuilderAdd add, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
#define DN_Str8BuilderAppendArrayRef(builder, strings, size) DN_Str8BuilderAddArrayRef(builder, strings, size, DN_Str8BuilderAdd_Append)
|
|
#define DN_Str8BuilderAppendArrayCopy(builder, strings, size) DN_Str8BuilderAddArrayCopy(builder, strings, size, DN_Str8BuilderAdd_Append)
|
|
#define DN_Str8BuilderAppendSliceRef(builder, slice) DN_Str8BuilderAddArrayRef(builder, slice.data, slice.size, DN_Str8BuilderAdd_Append)
|
|
#define DN_Str8BuilderAppendSliceCopy(builder, slice) DN_Str8BuilderAddArrayCopy(builder, slice.data, slice.size, DN_Str8BuilderAdd_Append)
|
|
DN_API bool DN_Str8BuilderAppendRef (DN_Str8Builder *builder, DN_Str8 string);
|
|
DN_API bool DN_Str8BuilderAppendCopy (DN_Str8Builder *builder, DN_Str8 string);
|
|
#define DN_Str8BuilderAppendFV(builder, fmt, args) DN_Str8BuilderAddFV(builder, DN_Str8BuilderAdd_Append, fmt, args)
|
|
DN_API bool DN_Str8BuilderAppendF (DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API bool DN_Str8BuilderAppendBytesRef (DN_Str8Builder *builder, void const *ptr, DN_USize size);
|
|
DN_API bool DN_Str8BuilderAppendBytesCopy (DN_Str8Builder *builder, void const *ptr, DN_USize size);
|
|
DN_API bool DN_Str8BuilderAppendBuilderRef (DN_Str8Builder *dest, DN_Str8Builder const *src);
|
|
DN_API bool DN_Str8BuilderAppendBuilderCopy (DN_Str8Builder *dest, DN_Str8Builder const *src);
|
|
#define DN_Str8BuilderPrependArrayRef(builder, strings, size) DN_Str8BuilderAddArrayRef(builder, strings, size, DN_Str8BuilderAdd_Prepend)
|
|
#define DN_Str8BuilderPrependArrayCopy(builder, strings, size) DN_Str8BuilderAddArrayCopy(builder, strings, size, DN_Str8BuilderAdd_Prepend)
|
|
#define DN_Str8BuilderPrependSliceRef(builder, slice) DN_Str8BuilderAddArrayRef(builder, slice.data, slice.size, DN_Str8BuilderAdd_Prepend)
|
|
#define DN_Str8BuilderPrependSliceCopy(builder, slice) DN_Str8BuilderAddArrayCopy(builder, slice.data, slice.size, DN_Str8BuilderAdd_Prepend)
|
|
DN_API bool DN_Str8BuilderPrependRef (DN_Str8Builder *builder, DN_Str8 string);
|
|
DN_API bool DN_Str8BuilderPrependCopy (DN_Str8Builder *builder, DN_Str8 string);
|
|
#define DN_Str8BuilderPrependFV(builder, fmt, args) DN_Str8BuilderAddFV(builder, DN_Str8BuilderAdd_Prepend, fmt, args)
|
|
DN_API bool DN_Str8BuilderPrependF (DN_Str8Builder *builder, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API bool DN_Str8BuilderErase (DN_Str8Builder *builder, DN_Str8 string);
|
|
DN_API DN_Str8 DN_Str8BuilderBuild (DN_Str8Builder const *builder, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8BuilderBuildDelimited (DN_Str8Builder const *builder, DN_Str8 delimiter, DN_Arena *arena);
|
|
DN_API DN_Str8Slice DN_Str8BuilderBuildSlice (DN_Str8Builder const *builder, DN_Arena *arena);
|
|
|
|
DN_API int DN_UTF8Encode (DN_U8 utf8[4], DN_U32 codepoint);
|
|
DN_API int DN_UTF16Encode (DN_U16 utf16[2], DN_U32 codepoint);
|
|
DN_API DN_UTF8DecodeResult DN_UTF8Decode (DN_Str8 stream);
|
|
DN_API bool DN_UTF8DecodeIterate (DN_UTF8DecodeIterator *it, DN_Str8 utf8);
|
|
DN_API DN_USize DN_USizeCodepointCountFromUTF8 (DN_Str8 str, DN_CodepointCountFlags flags);
|
|
|
|
DN_API DN_U8 DN_U8FromHexNibble (char hex);
|
|
DN_API DN_NibbleFromU8Result DN_NibbleFromU8 (DN_U8 u8);
|
|
|
|
DN_API DN_USize DN_BytesFromHex (DN_Str8 hex, void *dest, DN_USize dest_count);
|
|
DN_API DN_Str8 DN_BytesFromHexArena (DN_Str8 hex, DN_Arena *arena);
|
|
DN_API DN_USize DN_BytesFromHexPtr (char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count);
|
|
DN_API DN_Str8 DN_BytesFromHexPtrArena (char const *hex, DN_USize hex_count, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_BytesFromHexPtrPool (char const *hex, DN_USize hex_count, DN_Pool *pool);
|
|
DN_API DN_U8x16 DN_BytesFromHex32Ptr (char const *hex, DN_USize hex_count);
|
|
DN_API DN_U8x32 DN_BytesFromHex64Ptr (char const *hex, DN_USize hex_count);
|
|
|
|
DN_API DN_HexU64Str8 DN_HexFromU64 (DN_U64 value, DN_HexFromU64Type type);
|
|
DN_API DN_USize DN_HexFromPtrBytes (void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
|
|
DN_API DN_Str8 DN_HexFromPtrBytesArena (void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
|
|
DN_API DN_USize DN_HexFromStr8Bytes (void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
|
|
DN_API DN_Hex32 DN_Hex32FromPtr16b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
|
DN_API DN_Hex64 DN_Hex64FromPtr32b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
|
DN_API DN_Hex128 DN_Hex128FromPtr64b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
|
|
|
DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_AgeUnit units);
|
|
DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units);
|
|
DN_API DN_Str8x128 DN_AgeStr8FromSecF64 (DN_F64 sec, DN_AgeUnit units);
|
|
|
|
DN_API int DN_IsLeapYear (int year);
|
|
DN_API bool DN_DateIsValid (DN_Date date);
|
|
DN_API DN_Date DN_DateFromUnixTimeMs (DN_USize unix_ts_ms);
|
|
DN_API DN_U64 DN_UnixTimeMsFromDate (DN_Date date);
|
|
|
|
DN_API DN_ByteCountResult DN_ByteCountFromType (DN_U64 bytes, DN_ByteCountType type);
|
|
#define DN_ByteCount(bytes) DN_ByteCountFromType(bytes, DN_ByteCountType_Auto)
|
|
DN_API DN_Str8x32 DN_ByteCountStr8x32FromType (DN_U64 bytes, DN_ByteCountType type);
|
|
#define DN_ByteCountStr8x32(bytes) DN_ByteCountStr8x32FromType(bytes, DN_ByteCountType_Auto)
|
|
|
|
#define DN_ProfilerZoneLoop(prof, name, index) \
|
|
DN_ProfilerZone DN_UniqueName(zone_) = DN_ProfilerBeginZone(prof, DN_Str8Lit(name), index), DN_UniqueName(dummy_) = {}; \
|
|
DN_UniqueName(dummy_).begin_tsc == 0; \
|
|
DN_ProfilerEndZone(prof, DN_UniqueName(zone_)), DN_UniqueName(dummy_).begin_tsc = 1
|
|
|
|
#define DN_ProfilerZoneLoopAuto(prof, name) DN_ProfilerZoneLoop(prof, name, __COUNTER__ + 1)
|
|
DN_API DN_Profiler DN_ProfilerInit (DN_ProfilerAnchor *anchors, DN_USize count, DN_USize anchors_per_frame, DN_ProfilerTSCNowFunc *tsc_now, DN_U64 tsc_frequency);
|
|
DN_API DN_ProfilerZone DN_ProfilerBeginZone (DN_Profiler *profiler, DN_Str8 name, DN_U16 anchor_index);
|
|
#define DN_ProfilerBeginZoneAuto(prof, name) DN_ProfilerBeginZone(prof, DN_Str8Lit(name), __COUNTER__ + 1)
|
|
DN_API void DN_ProfilerEndZone (DN_Profiler *profiler, DN_ProfilerZone zone);
|
|
DN_API DN_USize DN_ProfilerFrameCount (DN_Profiler const *profiler);
|
|
DN_API DN_ProfilerAnchorArray DN_ProfilerFrameAnchorsFromIndex (DN_Profiler *profiler, DN_USize frame_index);
|
|
DN_API DN_ProfilerAnchorArray DN_ProfilerFrameAnchors (DN_Profiler *profiler);
|
|
DN_API void DN_ProfilerNewFrame (DN_Profiler *profiler);
|
|
DN_API void DN_ProfilerDump (DN_Profiler *profiler);
|
|
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_PCG32 DN_PCG32Init (DN_U64 seed);
|
|
DN_API DN_U32 DN_PCG32Next (DN_PCG32 *rng);
|
|
DN_API DN_U64 DN_PCG32Next64 (DN_PCG32 *rng);
|
|
DN_API DN_U32 DN_PCG32Range (DN_PCG32 *rng, DN_U32 low, DN_U32 high);
|
|
DN_API DN_F32 DN_PCG32NextF32 (DN_PCG32 *rng);
|
|
DN_API DN_F64 DN_PCG32NextF64 (DN_PCG32 *rng);
|
|
DN_API void DN_PCG32Advance (DN_PCG32 *rng, DN_U64 delta);
|
|
|
|
#if !defined(DN_FNV1A32_SEED)
|
|
#define DN_FNV1A32_SEED 2166136261U
|
|
#endif
|
|
|
|
#if !defined(DN_FNV1A64_SEED)
|
|
#define DN_FNV1A64_SEED 14695981039346656037ULL
|
|
#endif
|
|
|
|
DN_API DN_U32 DN_FNV1AHashU32FromBytes (void const *bytes, DN_USize size, DN_U32 seed);
|
|
DN_API DN_U64 DN_FNV1AHashU64FromBytes (void const *bytes, DN_USize size, DN_U64 seed);
|
|
|
|
DN_API DN_U32 DN_MurmurHash3HashU32FromBytesX86 (void const *bytes, int len, DN_U32 seed);
|
|
DN_API DN_MurmurHash3 DN_MurmurHash3HashU128FromBytesX64 (void const *bytes, int len, DN_U32 seed);
|
|
DN_API DN_U64 DN_MurmurHash3HashU64FromBytesX64 (void const *bytes, int len, DN_U32 seed);
|
|
DN_API DN_U32 DN_MurmurHash3HashU32FromBytesX64 (void const *bytes, int len, DN_U32 seed);
|
|
|
|
#if defined(DN_64_BIT)
|
|
#define DN_MurmurHash3HashU32FromBytes(bytes, len, seed) DN_MurmurHash3HashU32FromBytesX64(bytes, len, seed)
|
|
#else
|
|
#define DN_MurmurHash3HashU32FromBytes(bytes, len, seed) DN_MurmurHash3HashU32FromBytesX86(bytes, len, seed)
|
|
#endif
|
|
|
|
#define DN_ANSICodeBoldLit "\x1b[1m"
|
|
#define DN_ANSICodeResetLit "\x1b[0m"
|
|
DN_API DN_Str8x32 DN_Str8x32FromANSIColourCodeU8RGB (DN_ANSIColourMode mode, DN_U8 r, DN_U8 g, DN_U8 b);
|
|
DN_API DN_Str8x32 DN_Str8x32FromANSIColourCodeV3F32RGB255 (DN_ANSIColourMode mode, DN_V3F32 rgb_255);
|
|
DN_API DN_Str8x32 DN_Str8x32FromANSIColourCodeU32RGB (DN_ANSIColourMode mode, DN_U32 value);
|
|
DN_API DN_Str8 DN_Str8FromStr8ANSIColourU8RGBArena (DN_ANSIColourMode mode, DN_Str8 str8, DN_U8 r, DN_U8 g, DN_U8 b, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8FromStr8ANSIColourV3F32RGB255Arena (DN_ANSIColourMode mode, DN_Str8 str8, DN_V3F32 rgb_255, DN_Arena *arena);
|
|
DN_API DN_Str8 DN_Str8FromFmtANSIColourU8RGBArena (DN_ANSIColourMode mode, DN_U8 r, DN_U8 g, DN_U8 b, DN_Arena *arena, char const *fmt, ...);
|
|
DN_API DN_Str8 DN_Str8FromFmtANSIColourV3F32RGB255Arena (DN_ANSIColourMode mode, DN_V3F32 rgb_255, DN_Arena *arena, char const *fmt, ...);
|
|
|
|
DN_API DN_LogPrefixSize DN_LogMakePrefix (DN_LogStyle style, DN_LogTypeParam type, DN_CallSite call_site, DN_LogDate date, char *dest, DN_USize dest_size);
|
|
DN_API void DN_LogSetPrintFunc (DN_LogPrintFunc *print_func, void *user_data);
|
|
DN_API void DN_LogPrint (DN_LogTypeParam type, DN_CallSite call_site, DN_LogFlags flags, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_LogTypeParam DN_LogTypeParamFromType (DN_LogType type);
|
|
#define DN_LogF(type, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(type), DN_CALL_SITE, DN_LogFlags_Nil, fmt, ##__VA_ARGS__)
|
|
|
|
#define DN_LogDebugF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Debug), DN_CALL_SITE, DN_LogFlags_Nil, fmt, ##__VA_ARGS__)
|
|
#define DN_LogInfoF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Info), DN_CALL_SITE, DN_LogFlags_Nil, fmt, ##__VA_ARGS__)
|
|
#define DN_LogWarningF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Warning), DN_CALL_SITE, DN_LogFlags_Nil, fmt, ##__VA_ARGS__)
|
|
#define DN_LogErrorF(fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Error), DN_CALL_SITE, DN_LogFlags_Nil, fmt, ##__VA_ARGS__)
|
|
|
|
#define DN_LogFlagF(type, flags, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(type), DN_CALL_SITE, flags, fmt, ##__VA_ARGS__)
|
|
#define DN_LogFlagDebugF(flags, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Debug), DN_CALL_SITE, flags, fmt, ##__VA_ARGS__)
|
|
#define DN_LogFlagInfoF(flags, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Info), DN_CALL_SITE, flags, fmt, ##__VA_ARGS__)
|
|
#define DN_LogFlagWarningF(flags, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Warning), DN_CALL_SITE, flags, fmt, ##__VA_ARGS__)
|
|
#define DN_LogFlagErrorF(flags, fmt, ...) DN_LogPrint(DN_LogTypeParamFromType(DN_LogType_Error), DN_CALL_SITE, flags, fmt, ##__VA_ARGS__)
|
|
|
|
|
|
// NOTE: OS primitives that the OS layer can provide for the base layer but is optional.
|
|
#if defined(DN_FREESTANDING)
|
|
#define DN_StackTraceWalk(...)
|
|
#define DN_StackTraceWalkResultIterate(...)
|
|
#define DN_StackTraceWalkResultToStr8(...) DN_Str8Lit("N/A")
|
|
#define DN_StackTraceWalkStr8(...) DN_Str8Lit("N/A")
|
|
#define DN_StackTraceWalkStr8FromHeap(...) DN_Str8Lit("N/A")
|
|
#define DN_StackTraceGetFrames(...)
|
|
#define DN_StackTraceRawFrameToFrame(...)
|
|
#define DN_StackTracePrint(...)
|
|
#define DN_StackTraceReloadSymbols(...)
|
|
#else
|
|
DN_API DN_StackTraceWalkResult DN_StackTraceWalk (DN_Arena *arena, DN_U16 limit);
|
|
DN_API bool DN_StackTraceWalkResultIterate (DN_StackTraceWalkResultIterator *it, DN_StackTraceWalkResult const *walk);
|
|
DN_API DN_Str8 DN_StackTraceWalkResultToStr8 (DN_Arena *arena, DN_StackTraceWalkResult const *walk, DN_U16 skip);
|
|
DN_API DN_Str8 DN_StackTraceWalkStr8 (DN_Arena *arena, DN_U16 limit, DN_U16 skip);
|
|
DN_API DN_Str8 DN_StackTraceWalkStr8FromHeap (DN_U16 limit, DN_U16 skip);
|
|
DN_API DN_StackTraceFrameSlice DN_StackTraceGetFrames (DN_Arena *arena, DN_U16 limit);
|
|
DN_API DN_StackTraceFrame DN_StackTraceRawFrameToFrame (DN_Arena *arena, DN_StackTraceRawFrame raw_frame);
|
|
DN_API void DN_StackTracePrint (DN_U16 limit);
|
|
DN_API void DN_StackTraceReloadSymbols ();
|
|
#endif
|
|
|
|
DN_API DN_F32 DN_F32Lerp (DN_F32 a, DN_F32 t, DN_F32 b);
|
|
DN_API DN_F32 DN_F32Floor (DN_F32 val);
|
|
DN_API DN_F32 DN_F32Ceil (DN_F32 val);
|
|
DN_API DN_F32 DN_F32RoundHalfUp (DN_F32 val);
|
|
|
|
#define DN_V2I32Zero DN_Literal(DN_V2I32){{(DN_I32)(0), (DN_I32)(0)}}
|
|
#define DN_V2I32One DN_Literal(DN_V2I32){{(DN_I32)(1), (DN_I32)(1)}}
|
|
#define DN_V2I32From1N(x) DN_Literal(DN_V2I32){{(DN_I32)(x), (DN_I32)(x)}}
|
|
#define DN_V2I32From2N(x, y) DN_Literal(DN_V2I32){{(DN_I32)(x), (DN_I32)(y)}}
|
|
#define DN_V2I32InitV2(xy) DN_Literal(DN_V2I32){{(DN_I32)(xy).x, (DN_I32)(xy).y}}
|
|
|
|
DN_API bool operator!= (DN_V2I32 lhs, DN_V2I32 rhs);
|
|
DN_API bool operator== (DN_V2I32 lhs, DN_V2I32 rhs);
|
|
DN_API bool operator>= (DN_V2I32 lhs, DN_V2I32 rhs);
|
|
DN_API bool operator<= (DN_V2I32 lhs, DN_V2I32 rhs);
|
|
DN_API bool operator< (DN_V2I32 lhs, DN_V2I32 rhs);
|
|
DN_API bool operator> (DN_V2I32 lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2I32 operator- (DN_V2I32 lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2I32 operator- (DN_V2I32 lhs);
|
|
DN_API DN_V2I32 operator+ (DN_V2I32 lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_F32 rhs);
|
|
DN_API DN_V2I32 operator* (DN_V2I32 lhs, DN_I32 rhs);
|
|
DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_F32 rhs);
|
|
DN_API DN_V2I32 operator/ (DN_V2I32 lhs, DN_I32 rhs);
|
|
DN_API DN_V2I32& operator*= (DN_V2I32& lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2I32& operator*= (DN_V2I32& lhs, DN_F32 rhs);
|
|
DN_API DN_V2I32& operator*= (DN_V2I32& lhs, DN_I32 rhs);
|
|
DN_API DN_V2I32& operator/= (DN_V2I32& lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2I32& operator/= (DN_V2I32& lhs, DN_F32 rhs);
|
|
DN_API DN_V2I32& operator/= (DN_V2I32& lhs, DN_I32 rhs);
|
|
DN_API DN_V2I32& operator-= (DN_V2I32& lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2I32& operator+= (DN_V2I32& lhs, DN_V2I32 rhs);
|
|
|
|
DN_API DN_V2I32 DN_V2I32Min (DN_V2I32 a, DN_V2I32 b);
|
|
DN_API DN_V2I32 DN_V2I32Max (DN_V2I32 a, DN_V2I32 b);
|
|
DN_API DN_V2I32 DN_V2I32Abs (DN_V2I32 a);
|
|
|
|
#define DN_V2U16Zero DN_Literal(DN_V2U16){{(DN_U16)(0), (DN_U16)(0)}}
|
|
#define DN_V2U16One DN_Literal(DN_V2U16){{(DN_U16)(1), (DN_U16)(1)}}
|
|
#define DN_V2U16From1N(x) DN_Literal(DN_V2U16){{(DN_U16)(x), (DN_U16)(x)}}
|
|
#define DN_V2U16From2N(x, y) DN_Literal(DN_V2U16){{(DN_U16)(x), (DN_U16)(y)}}
|
|
|
|
DN_API bool operator!= (DN_V2U16 lhs, DN_V2U16 rhs);
|
|
DN_API bool operator== (DN_V2U16 lhs, DN_V2U16 rhs);
|
|
DN_API bool operator>= (DN_V2U16 lhs, DN_V2U16 rhs);
|
|
DN_API bool operator<= (DN_V2U16 lhs, DN_V2U16 rhs);
|
|
DN_API bool operator< (DN_V2U16 lhs, DN_V2U16 rhs);
|
|
DN_API bool operator> (DN_V2U16 lhs, DN_V2U16 rhs);
|
|
DN_API DN_V2U16 operator- (DN_V2U16 lhs, DN_V2U16 rhs);
|
|
DN_API DN_V2U16 operator+ (DN_V2U16 lhs, DN_V2U16 rhs);
|
|
DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_V2U16 rhs);
|
|
DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_F32 rhs);
|
|
DN_API DN_V2U16 operator* (DN_V2U16 lhs, DN_I32 rhs);
|
|
DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_V2U16 rhs);
|
|
DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_F32 rhs);
|
|
DN_API DN_V2U16 operator/ (DN_V2U16 lhs, DN_I32 rhs);
|
|
DN_API DN_V2U16& operator*= (DN_V2U16& lhs, DN_V2U16 rhs);
|
|
DN_API DN_V2U16& operator*= (DN_V2U16& lhs, DN_F32 rhs);
|
|
DN_API DN_V2U16& operator*= (DN_V2U16& lhs, DN_I32 rhs);
|
|
DN_API DN_V2U16& operator/= (DN_V2U16& lhs, DN_V2U16 rhs);
|
|
DN_API DN_V2U16& operator/= (DN_V2U16& lhs, DN_F32 rhs);
|
|
DN_API DN_V2U16& operator/= (DN_V2U16& lhs, DN_I32 rhs);
|
|
DN_API DN_V2U16& operator-= (DN_V2U16& lhs, DN_V2U16 rhs);
|
|
DN_API DN_V2U16& operator+= (DN_V2U16& lhs, DN_V2U16 rhs);
|
|
|
|
#define DN_V2U32Zero DN_Literal(DN_V2U32){{(DN_U32)(0), (DN_U32)(0)}}
|
|
#define DN_V2U32One DN_Literal(DN_V2U32){{(DN_U32)(1), (DN_U32)(1)}}
|
|
#define DN_V2U32From1N(x) DN_Literal(DN_V2U32){{(DN_U32)(x), (DN_U32)(x)}}
|
|
#define DN_V2U32From2N(x, y) DN_Literal(DN_V2U32){{(DN_U32)(x), (DN_U32)(y)}}
|
|
|
|
#define DN_V2F32Zero DN_Literal(DN_V2F32){{(DN_F32)(0), (DN_F32)(0)}}
|
|
#define DN_V2F32One DN_Literal(DN_V2F32){{(DN_F32)(1), (DN_F32)(1)}}
|
|
#define DN_V2F32From1N(x) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(x)}}
|
|
#define DN_V2F32From2N(x, y) DN_Literal(DN_V2F32){{(DN_F32)(x), (DN_F32)(y)}}
|
|
#define DN_V2F32FromV2(xy) DN_Literal(DN_V2F32){{(DN_F32)(xy).x, (DN_F32)(xy).y}}
|
|
|
|
DN_API DN_V2F32 DN_V2F32Lerp (DN_V2F32 a, DN_F32 t, DN_V2F32 b);
|
|
|
|
DN_API bool operator!= (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API bool operator== (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API bool operator>= (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API bool operator<= (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API bool operator< (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API bool operator> (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
|
|
DN_API DN_V2F32 operator- (DN_V2F32 lhs);
|
|
DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_F32 rhs);
|
|
DN_API DN_V2F32 operator- (DN_V2F32 lhs, DN_I32 rhs);
|
|
|
|
DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_F32 rhs);
|
|
DN_API DN_V2F32 operator+ (DN_V2F32 lhs, DN_I32 rhs);
|
|
|
|
DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_F32 rhs);
|
|
DN_API DN_V2F32 operator* (DN_V2F32 lhs, DN_I32 rhs);
|
|
|
|
DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_F32 rhs);
|
|
DN_API DN_V2F32 operator/ (DN_V2F32 lhs, DN_I32 rhs);
|
|
|
|
DN_API DN_V2F32& operator*= (DN_V2F32& lhs, DN_V2F32 rhs);
|
|
DN_API DN_V2F32& operator*= (DN_V2F32& lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2F32& operator*= (DN_V2F32& lhs, DN_F32 rhs);
|
|
DN_API DN_V2F32& operator*= (DN_V2F32& lhs, DN_I32 rhs);
|
|
|
|
DN_API DN_V2F32& operator/= (DN_V2F32& lhs, DN_V2F32 rhs);
|
|
DN_API DN_V2F32& operator/= (DN_V2F32& lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2F32& operator/= (DN_V2F32& lhs, DN_F32 rhs);
|
|
DN_API DN_V2F32& operator/= (DN_V2F32& lhs, DN_I32 rhs);
|
|
|
|
DN_API DN_V2F32& operator-= (DN_V2F32& lhs, DN_V2F32 rhs);
|
|
DN_API DN_V2F32& operator-= (DN_V2F32& lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2F32& operator-= (DN_V2F32& lhs, DN_F32 rhs);
|
|
DN_API DN_V2F32& operator-= (DN_V2F32& lhs, DN_I32 rhs);
|
|
|
|
DN_API DN_V2F32& operator+= (DN_V2F32& lhs, DN_V2F32 rhs);
|
|
DN_API DN_V2F32& operator+= (DN_V2F32& lhs, DN_V2I32 rhs);
|
|
DN_API DN_V2F32& operator+= (DN_V2F32& lhs, DN_F32 rhs);
|
|
DN_API DN_V2F32& operator+= (DN_V2F32& lhs, DN_I32 rhs);
|
|
|
|
DN_API DN_V2F32 DN_V2F32Min (DN_V2F32 a, DN_V2F32 b);
|
|
DN_API DN_V2F32 DN_V2F32Max (DN_V2F32 a, DN_V2F32 b);
|
|
DN_API DN_V2F32 DN_V2F32Abs (DN_V2F32 a);
|
|
DN_API DN_F32 DN_V2F32Dot (DN_V2F32 a, DN_V2F32 b);
|
|
DN_API DN_F32 DN_V2F32LengthSq2V2 (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API bool DN_V2F32LengthSqIsWithin2V2 (DN_V2F32 lhs, DN_V2F32 rhs, DN_F32 within_amount_sq);
|
|
DN_API DN_F32 DN_V2F32Length2V2 (DN_V2F32 lhs, DN_V2F32 rhs);
|
|
DN_API DN_F32 DN_V2F32LengthSq (DN_V2F32 lhs);
|
|
DN_API DN_F32 DN_V2F32Length (DN_V2F32 lhs);
|
|
DN_API DN_V2F32 DN_V2F32Normalise (DN_V2F32 a);
|
|
DN_API DN_V2F32 DN_V2F32Perpendicular (DN_V2F32 a);
|
|
DN_API DN_V2F32 DN_V2F32Reflect (DN_V2F32 in, DN_V2F32 surface);
|
|
DN_API DN_F32 DN_V2F32Area (DN_V2F32 a);
|
|
|
|
#define DN_V3F32From1N(x) DN_Literal(DN_V3F32){{(DN_F32)(x), (DN_F32)(x), (DN_F32)(x)}}
|
|
#define DN_V3F32From3N(x, y, z) DN_Literal(DN_V3F32){{(DN_F32)(x), (DN_F32)(y), (DN_F32)(z)}}
|
|
#define DN_V3F32FromV2F32And1N(xy, z) DN_Literal(DN_V3F32){{(DN_F32)(xy.x), (DN_F32)(xy.y), (DN_F32)(z)}}
|
|
|
|
// NOTE: Grayscale co-efficients from:
|
|
// https://github.com/EpicGames/UnrealEngine/blob/260bb2e1c5610b31c63a36206eedd289409c5f11/Engine/Source/Runtime/Core/Private/Math/Color.cpp#L304
|
|
DN_V3F32 static const DN_V3F32_RGB_LUMINANCE = DN_V3F32From3N(0.3f, 0.59f, 0.11f);
|
|
|
|
DN_API bool operator== (DN_V3F32 lhs, DN_V3F32 rhs);
|
|
DN_API bool operator!= (DN_V3F32 lhs, DN_V3F32 rhs);
|
|
DN_API bool operator>= (DN_V3F32 lhs, DN_V3F32 rhs);
|
|
DN_API bool operator<= (DN_V3F32 lhs, DN_V3F32 rhs);
|
|
DN_API bool operator< (DN_V3F32 lhs, DN_V3F32 rhs);
|
|
DN_API bool operator> (DN_V3F32 lhs, DN_V3F32 rhs);
|
|
DN_API DN_V3F32 operator- (DN_V3F32 lhs, DN_V3F32 rhs);
|
|
DN_API DN_V3F32 operator- (DN_V3F32 lhs);
|
|
DN_API DN_V3F32 operator+ (DN_V3F32 lhs, DN_V3F32 rhs);
|
|
DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_V3F32 rhs);
|
|
DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_F32 rhs);
|
|
DN_API DN_V3F32 operator* (DN_V3F32 lhs, DN_I32 rhs);
|
|
DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_V3F32 rhs);
|
|
DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_F32 rhs);
|
|
DN_API DN_V3F32 operator/ (DN_V3F32 lhs, DN_I32 rhs);
|
|
DN_API DN_V3F32& operator*= (DN_V3F32 &lhs, DN_V3F32 rhs);
|
|
DN_API DN_V3F32& operator*= (DN_V3F32 &lhs, DN_F32 rhs);
|
|
DN_API DN_V3F32& operator*= (DN_V3F32 &lhs, DN_I32 rhs);
|
|
DN_API DN_V3F32& operator/= (DN_V3F32 &lhs, DN_V3F32 rhs);
|
|
DN_API DN_V3F32& operator/= (DN_V3F32 &lhs, DN_F32 rhs);
|
|
DN_API DN_V3F32& operator/= (DN_V3F32 &lhs, DN_I32 rhs);
|
|
DN_API DN_V3F32& operator-= (DN_V3F32 &lhs, DN_V3F32 rhs);
|
|
DN_API DN_V3F32& operator+= (DN_V3F32 &lhs, DN_V3F32 rhs);
|
|
DN_API DN_V3F32 DN_V3F32Lerp (DN_V3F32 lhs, DN_F32 t01, DN_V3F32 rhs);
|
|
DN_API DN_F32 DN_V3F32LengthSq (DN_V3F32 a);
|
|
DN_API DN_F32 DN_V3F32Length (DN_V3F32 a);
|
|
DN_API DN_V3F32 DN_V3F32Normalise (DN_V3F32 a);
|
|
|
|
#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_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_V4F32RGBA01FromRGBU8(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 bool DN_V4F32RGBA01IsValid (DN_V4F32 rgba01);
|
|
DN_API DN_V4F32 DN_V4F32RGBA01FromRGBU32 (DN_U32 u32);
|
|
DN_API DN_V4F32 DN_V4F32RGBA01FromRGBAU32 (DN_U32 u32);
|
|
DN_API DN_V4F32 DN_V4F32Linear01FromSRGB01 (DN_V4F32 rgb01);
|
|
DN_API DN_V4F32 DN_V4F32Linear01Desaturate (DN_V4F32 linear01, DN_F32 t01);
|
|
DN_API DN_V4F32 DN_V4F32SRGB01FromLinear01 (DN_V4F32 linear01);
|
|
|
|
#define DN_V4F32FromV4Alpha(v4, alpha) DN_V4F32FromV3And1N(v4.xyz, alpha)
|
|
|
|
DN_API bool operator== (DN_V4F32 lhs, DN_V4F32 rhs);
|
|
DN_API bool operator!= (DN_V4F32 lhs, DN_V4F32 rhs);
|
|
DN_API bool operator<= (DN_V4F32 lhs, DN_V4F32 rhs);
|
|
DN_API bool operator< (DN_V4F32 lhs, DN_V4F32 rhs);
|
|
DN_API bool operator> (DN_V4F32 lhs, DN_V4F32 rhs);
|
|
DN_API DN_V4F32 operator- (DN_V4F32 lhs, DN_V4F32 rhs);
|
|
DN_API DN_V4F32 operator- (DN_V4F32 lhs);
|
|
DN_API DN_V4F32 operator+ (DN_V4F32 lhs, DN_V4F32 rhs);
|
|
DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_V4F32 rhs);
|
|
DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_F32 rhs);
|
|
DN_API DN_V4F32 operator* (DN_V4F32 lhs, DN_I32 rhs);
|
|
DN_API DN_V4F32 operator/ (DN_V4F32 lhs, DN_F32 rhs);
|
|
DN_API DN_V4F32& operator*= (DN_V4F32 &lhs, DN_V4F32 rhs);
|
|
DN_API DN_V4F32& operator*= (DN_V4F32 &lhs, DN_F32 rhs);
|
|
DN_API DN_V4F32& operator*= (DN_V4F32 &lhs, DN_I32 rhs);
|
|
DN_API DN_V4F32& operator-= (DN_V4F32 &lhs, DN_V4F32 rhs);
|
|
DN_API DN_V4F32& operator+= (DN_V4F32 &lhs, DN_V4F32 rhs);
|
|
DN_API DN_F32 DN_V4F32Dot (DN_V4F32 a, DN_V4F32 b);
|
|
|
|
DN_API DN_M4 DN_M4Identity ();
|
|
DN_API DN_M4 DN_M4ScaleF (DN_F32 x, DN_F32 y, DN_F32 z);
|
|
DN_API DN_M4 DN_M4Scale (DN_V3F32 xyz);
|
|
DN_API DN_M4 DN_M4TranslateF (DN_F32 x, DN_F32 y, DN_F32 z);
|
|
DN_API DN_M4 DN_M4Translate (DN_V3F32 xyz);
|
|
DN_API DN_M4 DN_M4Transpose (DN_M4 mat);
|
|
DN_API DN_M4 DN_M4Rotate (DN_V3F32 axis, DN_F32 radians);
|
|
DN_API DN_M4 DN_M4Orthographic (DN_F32 left, DN_F32 right, DN_F32 bottom, DN_F32 top, DN_F32 z_near, DN_F32 z_far);
|
|
DN_API DN_M4 DN_M4Perspective (DN_F32 fov /*radians*/, DN_F32 aspect, DN_F32 z_near, DN_F32 z_far);
|
|
DN_API DN_M4 DN_M4Add (DN_M4 lhs, DN_M4 rhs);
|
|
DN_API DN_M4 DN_M4Sub (DN_M4 lhs, DN_M4 rhs);
|
|
DN_API DN_M4 DN_M4Mul (DN_M4 lhs, DN_M4 rhs);
|
|
DN_API DN_M4 DN_M4Div (DN_M4 lhs, DN_M4 rhs);
|
|
DN_API DN_M4 DN_M4AddF (DN_M4 lhs, DN_F32 rhs);
|
|
DN_API DN_M4 DN_M4SubF (DN_M4 lhs, DN_F32 rhs);
|
|
DN_API DN_M4 DN_M4MulF (DN_M4 lhs, DN_F32 rhs);
|
|
DN_API DN_M4 DN_M4DivF (DN_M4 lhs, DN_F32 rhs);
|
|
DN_API DN_Str8x256 DN_M4ColumnMajorString (DN_M4 mat);
|
|
|
|
DN_API bool operator== (DN_M2x3 const &lhs, DN_M2x3 const &rhs);
|
|
DN_API bool operator!= (DN_M2x3 const &lhs, DN_M2x3 const &rhs);
|
|
DN_API DN_M2x3 DN_M2x3Identity ();
|
|
DN_API DN_M2x3 DN_M2x3Translate (DN_V2F32 offset);
|
|
DN_API DN_V2F32 DN_M2x3ScaleGet (DN_M2x3 m2x3);
|
|
DN_API DN_M2x3 DN_M2x3Scale (DN_V2F32 scale);
|
|
DN_API DN_M2x3 DN_M2x3Rotate (DN_F32 radians);
|
|
DN_API DN_M2x3 DN_M2x3ProjFromV2F32 (DN_V2F32 size, DN_M2x3ProjOrigin origin);
|
|
DN_API DN_M2x3XForm DN_M2x3XFormFrom2M2x3 (DN_M2x3 forward, DN_M2x3 inverse);
|
|
DN_API DN_M2x3XForm DN_M2x3XFormFromTRS (DN_V2F32 pos, DN_V2F32 scale, DN_F32 rotate_rads, DN_V2F32 pivot_pos);
|
|
DN_API DN_M2x3XForm DN_M2x3XFormIdentity ();
|
|
DN_API DN_M2x3XForm DN_M2x3XFormMul (DN_M2x3XForm m1, DN_M2x3XForm m2);
|
|
DN_API DN_M2x3 DN_M2x3Mul (DN_M2x3 m1, DN_M2x3 m2);
|
|
DN_API DN_V2F32 DN_M2x3Mul2F32 (DN_M2x3 m1, DN_F32 x, DN_F32 y);
|
|
DN_API DN_V2F32 DN_M2x3MulV2F32 (DN_M2x3 m1, DN_V2F32 v2);
|
|
DN_API DN_Rect DN_M2x3MulRect (DN_M2x3 m1, DN_Rect rect);
|
|
|
|
#define DN_RectFrom2V2(pos, size) DN_Literal(DN_Rect){(pos), (size)}
|
|
#define DN_RectFrom4N(x, y, w, h) DN_Literal(DN_Rect){DN_Literal(DN_V2F32){{x, y}}, DN_Literal(DN_V2F32){{w, h}}}
|
|
#define DN_RectZero DN_RectFrom4N(0, 0, 0, 0)
|
|
|
|
DN_API bool operator== (const DN_Rect& lhs, const DN_Rect& rhs);
|
|
DN_API DN_V2F32 DN_RectCenter (DN_Rect rect);
|
|
DN_API bool DN_RectContainsPoint (DN_Rect rect, DN_V2F32 p);
|
|
DN_API bool DN_RectContainsRect (DN_Rect a, DN_Rect b);
|
|
DN_API DN_Rect DN_RectExpand (DN_Rect a, DN_F32 amount);
|
|
DN_API DN_Rect DN_RectExpandV2 (DN_Rect a, DN_V2F32 amount);
|
|
DN_API bool DN_RectIntersects (DN_Rect a, DN_Rect b);
|
|
DN_API DN_Rect DN_RectIntersection (DN_Rect a, DN_Rect b);
|
|
DN_API DN_Rect DN_RectUnion (DN_Rect a, DN_Rect b);
|
|
DN_API DN_2V2F32 DN_RectRange (DN_Rect a);
|
|
DN_API bool DN_RectEq (DN_Rect lhs, DN_Rect rhs);
|
|
DN_API DN_F32 DN_RectArea (DN_Rect a);
|
|
DN_API DN_V2F32 DN_RectInterpV2F32 (DN_Rect rect, DN_V2F32 t01);
|
|
DN_API DN_V2F32 DN_RectTopLeft (DN_Rect rect);
|
|
DN_API DN_V2F32 DN_RectTopRight (DN_Rect rect);
|
|
DN_API DN_V2F32 DN_RectBottomLeft (DN_Rect rect);
|
|
DN_API DN_V2F32 DN_RectBottomRight (DN_Rect rect);
|
|
|
|
DN_API DN_Rect DN_RectCutLeftClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
|
|
DN_API DN_Rect DN_RectCutRightClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
|
|
DN_API DN_Rect DN_RectCutTopClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
|
|
DN_API DN_Rect DN_RectCutBottomClip (DN_Rect *rect, DN_F32 amount, DN_RectCutClip clip);
|
|
|
|
#define DN_RectCutLeft(rect, amount) DN_RectCutLeftClip(rect, amount, DN_RectCutClip_Yes)
|
|
#define DN_RectCutRight(rect, amount) DN_RectCutRightClip(rect, amount, DN_RectCutClip_Yes)
|
|
#define DN_RectCutTop(rect, amount) DN_RectCutTopClip(rect, amount, DN_RectCutClip_Yes)
|
|
#define DN_RectCutBottom(rect, amount) DN_RectCutBottomClip(rect, amount, DN_RectCutClip_Yes)
|
|
|
|
#define DN_RectCutLeftNoClip(rect, amount) DN_RectCutLeftClip(rect, amount, DN_RectCutClip_No)
|
|
#define DN_RectCutRightNoClip(rect, amount) DN_RectCutRightClip(rect, amount, DN_RectCutClip_No)
|
|
#define DN_RectCutTopNoClip(rect, amount) DN_RectCutTopClip(rect, amount, DN_RectCutClip_No)
|
|
#define DN_RectCutBottomNoClip(rect, amount) DN_RectCutBottomClip(rect, amount, DN_RectCutClip_No)
|
|
|
|
DN_API DN_Rect DN_RectCutCut (DN_RectCut rect_cut, DN_V2F32 size, DN_RectCutClip clip);
|
|
#define DN_RectCutInit(rect, side) DN_Literal(DN_RectCut){rect, side}
|
|
|
|
DN_API DN_RaycastV2 DN_RaycastLineIntersectV2 (DN_V2F32 origin_a, DN_V2F32 dir_a, DN_V2F32 origin_b, DN_V2F32 dir_b);
|
|
#endif // !defined(DN_BASE_H)
|
|
// DN: Single header generator commented out => #include "Base/dn_base_assert.h"
|
|
#if !defined(DN_BASE_ASSERT_H)
|
|
#define DN_BASE_ASSERT_H
|
|
|
|
#define DN_HardAssertF(expr, fmt, ...) \
|
|
do { \
|
|
if (!(expr)) { \
|
|
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
|
DN_LogErrorF("Hard assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
|
DN_Str8PrintFmt(stack_trace_), \
|
|
##__VA_ARGS__); \
|
|
DN_DebugBreak; \
|
|
} \
|
|
} while (0)
|
|
#define DN_HardAssert(expr) DN_HardAssertF(expr, "")
|
|
|
|
// NOTE: Our default assert requires stack traces which has a bit of a chicken-and-egg problem if
|
|
// we're trying to detect some code related to the DN startup sequence. If we try to assert before
|
|
// the OS layer is initialised stack-traces will try to use temporary memory which requires TLS to
|
|
// be setup which belongs to the OS.
|
|
//
|
|
// This causes recursion errors as they call into each other. We use RawAsserts for these kind of
|
|
// checks.
|
|
#if defined(DN_NO_ASSERT)
|
|
#define DN_RawAssert(...)
|
|
#define DN_Assert(...)
|
|
#define DN_AssertOnce(...)
|
|
#define DN_AssertF(...)
|
|
#define DN_AssertFOnce(...)
|
|
#else
|
|
#define DN_RawAssert(expr) do { if (!(expr)) DN_DebugBreak; } while (0)
|
|
|
|
#define DN_AssertF(expr, fmt, ...) \
|
|
do { \
|
|
if (!(expr)) { \
|
|
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
|
DN_LogErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
|
DN_Str8PrintFmt(stack_trace_), \
|
|
##__VA_ARGS__); \
|
|
DN_DebugBreak; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define DN_AssertFOnce(expr, fmt, ...) \
|
|
do { \
|
|
static bool once = true; \
|
|
if (!(expr) && once) { \
|
|
once = false; \
|
|
DN_Str8 stack_trace_ = DN_StackTraceWalkStr8FromHeap(128 /*limit*/, 2 /*skip*/); \
|
|
DN_LogErrorF("Assertion [" #expr "], stack trace was:\n\n%.*s\n\n" fmt, \
|
|
DN_Str8PrintFmt(stack_trace_), \
|
|
##__VA_ARGS__); \
|
|
DN_DebugBreak; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define DN_Assert(expr) DN_AssertF((expr), "")
|
|
#define DN_AssertOnce(expr) DN_AssertFOnce((expr), "")
|
|
#endif
|
|
|
|
#define DN_InvalidCodePathF(fmt, ...) DN_HardAssertF(0, fmt, ##__VA_ARGS__)
|
|
#define DN_InvalidCodePath DN_InvalidCodePathF("Invalid code path triggered")
|
|
#define DN_StaticAssert(expr) \
|
|
DN_GCC_WARNING_PUSH \
|
|
DN_GCC_WARNING_DISABLE(-Wunused-local-typedefs) \
|
|
typedef char DN_TokenCombine(static_assert_dummy__, __LINE__)[(expr) ? 1 : -1]; \
|
|
DN_GCC_WARNING_POP
|
|
|
|
#define DN_Check(expr) DN_CheckF(expr, "")
|
|
#if defined(DN_NO_CHECK_BREAK)
|
|
#define DN_CheckF(expr, fmt, ...) \
|
|
((expr) ? true : (DN_LogWarningF(fmt, ##__VA_ARGS__), false))
|
|
#else
|
|
#define DN_CheckF(expr, fmt, ...) \
|
|
((expr) ? true : (DN_LogErrorF(fmt, ##__VA_ARGS__), DN_StackTracePrint(128 /*limit*/), DN_DebugBreak, false))
|
|
#endif
|
|
|
|
#endif
|
|
// DN: Single header generator commented out => #include "Base/dn_base_containers.h"
|
|
#if !defined(DN_CONTAINERS_H)
|
|
#define DN_CONTAINERS_H
|
|
// Containers that are imlpemented 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 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.
|
|
//
|
|
// Arrays
|
|
//
|
|
// Data structures that have a `T *data`, `DN_USize count` and `DN_USize max` capacity that can be
|
|
// dynamically shrunk or expanded.
|
|
//
|
|
// API
|
|
// ResizeFrom: Resizes the array to `new_max` erase elements if resizing to a smaller size
|
|
// GrowFrom: Expands the capacity of the array if `new_max > array.max` otherwise no-op
|
|
// GrowIfNeeded: Expands the capacity of the array if `array.size + add_count > array.max` otherwise no-op
|
|
//
|
|
// Variants
|
|
// PArray => Pointer (to) Array
|
|
// LArray => Literal Array
|
|
// Define a C array and size. (P) array macros take a pointer to the aray, its size and its max
|
|
// capacity. The (L) array macros take the literal array and derives the max capacity
|
|
// automatically using DN_ArrayCountU(l_array).
|
|
//
|
|
// MyStruct buffer[TB_ASType_Count] = {};
|
|
// DN_USize size = 0;
|
|
// MyStruct *item_0 = DN_PArrayMake(buffer, &size, DN_ArrayCountU(buffer), DN_ZMem_No);
|
|
// MyStruct *item_1 = DN_LArrayMake(buffer, &size, DN_ZMem_No);
|
|
//
|
|
// IArray => Intrusive Array
|
|
// Define a struct with the members `data`, `size` and `max`:
|
|
//
|
|
// struct MyArray {
|
|
// MyStruct *data;
|
|
// DN_USize size;
|
|
// DN_USize max;
|
|
// } my_array = {};
|
|
// DN_Arena arena = {};
|
|
// DN_IArrayResizeFromArena(&my_array, &arena, 256);
|
|
// MyStruct *item = DN_IArrayMake(&my_array, DN_ZMem_No);
|
|
//
|
|
// Slices
|
|
//
|
|
// Fixed size container allocated up front that have a `T *data` and `DN_USize count` elements.
|
|
//
|
|
// API
|
|
// AllocArena: Allocates the container with the requested `count` elements
|
|
//
|
|
// ISinglyLL => Intrusive Singly Linked List
|
|
// Define a struct with the members `next`:
|
|
//
|
|
// struct MyLinkItem {
|
|
// int data;
|
|
// MyLinkItem *next;
|
|
// } my_link = {};
|
|
//
|
|
// MyLinkItem *first_item = DN_ISinglyLLDetach(&my_link, MyLinkItem);
|
|
//
|
|
// DoublyLL => Doubly Linked List
|
|
// Define a struct with the members `next` and `prev`. This list has null pointers for head->prev
|
|
// and tail->next.
|
|
//
|
|
// struct MyLinkItem {
|
|
// int data;
|
|
// MyLinkItem *next;
|
|
// MyLinkItem *prev;
|
|
// } my_link = {};
|
|
//
|
|
// MyLinkItem first_item = {}, second_item = {};
|
|
// DN_DoublyLLAppend(&first_item, &second_item); // first_item -> second_item
|
|
//
|
|
// SentinelDoublyLL => Sentinel Doubly Linked List
|
|
// Uses a sentinel/dummy node as the list head. The sentinel points to itself when empty.
|
|
// Define a struct with the members `next` and `prev`:
|
|
//
|
|
// struct MyLinkItem {
|
|
// int data;
|
|
// MyLinkItem *next;
|
|
// MyLinkItem *prev;
|
|
// } my_list = {};
|
|
//
|
|
// DN_SentinelDoublyLLInit(&my_list);
|
|
// DN_SentinelDoublyLLAppend(&my_list, &new_item);
|
|
// DN_SentinelDoublyLLForEach(it, &my_list) { /* ... */ }
|
|
//
|
|
// SinglyHeadTailLL => Singly Linked List with Head and Tail pointer (or First and Last pointer)
|
|
/*
|
|
struct MyLinkItem {
|
|
int data;
|
|
MyLinkItem *next;
|
|
} my_list = {};
|
|
|
|
struct MyContainer {
|
|
MyLinkItem *head;
|
|
MyLinkItem *tail;
|
|
};
|
|
|
|
MyLinkItem item = {};
|
|
MyContainer container = {};
|
|
DN_ISinglyHeadTailLLAppend(container, item);
|
|
// ... or alternatively, DN_SinglyHeadTailLLAppend(container.head, container.tail, item);
|
|
|
|
for (MyLinkItem *it = container.head; it; it = it->next) { }
|
|
*/
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
struct DN_Ring
|
|
{
|
|
DN_U64 size;
|
|
char *base;
|
|
DN_U64 write_pos;
|
|
DN_U64 read_pos;
|
|
};
|
|
|
|
enum DN_ArrayErase
|
|
{
|
|
DN_ArrayErase_Unstable,
|
|
DN_ArrayErase_Stable,
|
|
};
|
|
|
|
enum DN_ArrayAdd
|
|
{
|
|
DN_ArrayAdd_Append,
|
|
DN_ArrayAdd_Prepend,
|
|
};
|
|
|
|
struct DN_ArrayEraseResult
|
|
{
|
|
// The next index your for-index should be set to such that you can continue
|
|
// to iterate the remainder of the array, e.g:
|
|
//
|
|
// for (DN_USize index = 0; index < array.size; index++) {
|
|
// if (erase)
|
|
// index = DN_FArray_EraseRange(&array, index, -3, DN_ArrayErase_Unstable);
|
|
// }
|
|
DN_USize it_index;
|
|
DN_USize items_erased; // The number of items erased
|
|
};
|
|
|
|
template <typename T> struct DN_ArrayFindResult
|
|
{
|
|
T *data; // Pointer to the value if a match is found, null pointer otherwise
|
|
DN_USize index; // Index to the value if a match is found, 0 otherwise
|
|
};
|
|
|
|
enum DN_DSMapKeyType
|
|
{
|
|
// Key | Key Hash | Map Index
|
|
DN_DSMapKeyType_Invalid,
|
|
DN_DSMapKeyType_U64, // U64 | Hash(U64) | Hash(U64) % map_size
|
|
DN_DSMapKeyType_U64NoHash, // U64 | U64 | U64 % map_size
|
|
DN_DSMapKeyType_Buffer, // Buffer | Hash(buffer) | Hash(buffer) % map_size
|
|
DN_DSMapKeyType_BufferAsU64NoHash, // Buffer | U64(buffer[0:4]) | U64(buffer[0:4]) % map_size
|
|
};
|
|
|
|
struct DN_DSMapKey
|
|
{
|
|
DN_DSMapKeyType type;
|
|
DN_U32 hash; // Hash to lookup in the map. If it equals, we check that the original key payload matches
|
|
void const *buffer_data;
|
|
DN_U32 buffer_size;
|
|
DN_U64 u64;
|
|
bool no_copy_buffer;
|
|
};
|
|
|
|
template <typename T>
|
|
struct DN_DSMapSlot
|
|
{
|
|
DN_DSMapKey key; // Hash table lookup key
|
|
T value; // Hash table value
|
|
};
|
|
|
|
typedef DN_U32 DN_DSMapFlags;
|
|
enum DN_DSMapFlags_
|
|
{
|
|
DN_DSMapFlags_Nil = 0,
|
|
DN_DSMapFlags_DontFreeArenaOnResize = 1 << 0,
|
|
};
|
|
|
|
using DN_DSMapHashFunction = DN_U32(DN_DSMapKey key, DN_U32 seed);
|
|
template <typename T> struct DN_DSMap
|
|
{
|
|
DN_U32 *hash_to_slot; // Mapping from hash to a index in the slots array
|
|
DN_DSMapSlot<T> *slots; // Values of the array stored contiguously, non-sorted order
|
|
DN_U32 size; // Total capacity of the map and is a power of two
|
|
DN_U32 occupied; // Number of slots used in the hash table
|
|
DN_Arena *arena; // Backing arena for the hash table
|
|
DN_Pool pool; // Allocator for keys that are variable-sized buffers
|
|
DN_U32 initial_size; // Initial map size, map cannot shrink on erase below this size
|
|
DN_DSMapHashFunction *hash_function; // Custom hashing function to use if field is set
|
|
DN_U32 hash_seed; // Seed for the hashing function, when 0, DN_DS_MAP_DEFAULT_HASH_SEED is used
|
|
DN_DSMapFlags flags;
|
|
};
|
|
|
|
template <typename T> struct DN_DSMapResult
|
|
{
|
|
bool found;
|
|
DN_DSMapSlot<T> *slot;
|
|
T *value;
|
|
};
|
|
|
|
#define DN_ISinglyLLDetach(list) (decltype(list))DN_SinglyLLDetach((void **)&(list), (void **)&(list)->next)
|
|
|
|
#define DN_SinglyHeadTailLLAppend(head, tail, to_append) \
|
|
do { \
|
|
if (!head) \
|
|
head = to_append; \
|
|
if (tail) \
|
|
tail->next = to_append; \
|
|
tail = to_append; \
|
|
} while (0)
|
|
#define DN_ISinglyHeadTailLLAppend(container_ptr, to_append) DN_SinglyHeadTailLLAppend((container_ptr)->head, (container_ptr)->tail, to_append)
|
|
|
|
#define DN_SentinelDoublyLLInit(list) (list)->next = (list)->prev = (list)
|
|
#define DN_SentinelDoublyLLIsSentinel(list, item) ((list) == (item))
|
|
#define DN_SentinelDoublyLLIsEmpty(list) (!(list) || ((list) == (list)->next))
|
|
#define DN_SentinelDoublyLLIsInit(list) ((list)->next && (list)->prev)
|
|
#define DN_SentinelDoublyLLHasItems(list) ((list) && ((list) != (list)->next))
|
|
#define DN_SentinelDoublyLLForEach(it, list) auto *it = (list)->next; (it) != (list); (it) = (it)->next
|
|
|
|
#define DN_SentinelDoublyLLInitArena(list, T, ptr_arena) \
|
|
do { \
|
|
(list) = DN_ArenaNew(ptr_arena, T, DN_ZMem_Yes); \
|
|
DN_SentinelDoublyLLInit(list); \
|
|
} while (0)
|
|
|
|
#define DN_SentinelDoublyLLInitPool(list, T, pool) \
|
|
do { \
|
|
(list) = DN_PoolNew(pool, T); \
|
|
DN_SentinelDoublyLLInit(list); \
|
|
} while (0)
|
|
|
|
#define DN_SentinelDoublyLLDetach(item) \
|
|
do { \
|
|
if (item) { \
|
|
(item)->prev->next = (item)->next; \
|
|
(item)->next->prev = (item)->prev; \
|
|
(item)->next = nullptr; \
|
|
(item)->prev = nullptr; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define DN_SentinelDoublyLLDequeue(list, dest_ptr) \
|
|
if (DN_SentinelDoublyLLHasItems(list)) { \
|
|
dest_ptr = (list)->next; \
|
|
DN_SentinelDoublyLLDetach(dest_ptr); \
|
|
}
|
|
|
|
#define DN_SentinelDoublyLLAppend(list, item) \
|
|
do { \
|
|
if (item) { \
|
|
if ((item)->next) \
|
|
DN_SentinelDoublyLLDetach(item); \
|
|
(item)->next = (list)->next; \
|
|
(item)->prev = (list); \
|
|
(item)->next->prev = (item); \
|
|
(item)->prev->next = (item); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define DN_SentinelDoublyLLPrepend(list, item) \
|
|
do { \
|
|
if (item) { \
|
|
if ((item)->next) \
|
|
DN_SentinelDoublyLLDetach(item); \
|
|
(item)->next = (list); \
|
|
(item)->prev = (list)->prev; \
|
|
(item)->next->prev = (item); \
|
|
(item)->prev->next = (item); \
|
|
} \
|
|
} while (0)
|
|
|
|
// DoublyLL => Non-intrusive Doubly Linked List
|
|
// A simple doubly linked list where each node has `next` and `prev` pointers.
|
|
// The head is passed as a pointer-to-pointer to allow head updates.
|
|
//
|
|
// struct MyLinkItem {
|
|
// int data;
|
|
// MyLinkItem *next;
|
|
// MyLinkItem *prev;
|
|
// } *head = nullptr;
|
|
// DN_DoublyLLAppend(&head, new_item);
|
|
// for (MyLinkItem *it = head; it; it = it->next) { /* ... */ }
|
|
|
|
#define DN_DoublyLLDetach(head, ptr) \
|
|
do { \
|
|
if ((head) && (head) == (ptr)) \
|
|
(head) = (head)->next; \
|
|
if ((ptr)) { \
|
|
if ((ptr)->next) \
|
|
(ptr)->next->prev = (ptr)->prev; \
|
|
if ((ptr)->prev) \
|
|
(ptr)->prev->next = (ptr)->next; \
|
|
(ptr)->prev = (ptr)->next = 0; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define DN_DoublyLLAppend(head, ptr) \
|
|
do { \
|
|
if ((ptr)) { \
|
|
DN_AssertF((ptr)->prev == 0 && (ptr)->next == 0, "Detach the pointer first"); \
|
|
(ptr)->prev = (head); \
|
|
(ptr)->next = 0; \
|
|
if ((head)) { \
|
|
(ptr)->next = (head)->next; \
|
|
(head)->next = (ptr); \
|
|
} else { \
|
|
(head) = (ptr); \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
#define DN_DoublyLLPrepend(head, ptr) \
|
|
do { \
|
|
if ((ptr)) { \
|
|
DN_AssertF((ptr)->prev == 0 && (ptr)->next == 0, "Detach the pointer first"); \
|
|
(ptr)->prev = nullptr; \
|
|
(ptr)->next = (head); \
|
|
if ((head)) { \
|
|
(ptr)->prev = (head)->prev; \
|
|
(head)->prev = (ptr); \
|
|
} else { \
|
|
(head) = (ptr); \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
// NOTE: For C++ we need to cast the void* returned in these functions to the concrete type. In C,
|
|
// no cast is needed.
|
|
#if defined(__cplusplus)
|
|
#define DN_CppDeclType(x) decltype(x)
|
|
#else
|
|
#define DN_CppDeclType
|
|
#endif
|
|
|
|
#define DN_PArrayResizeFromPool(ptr, ptr_size, ptr_max, pool, new_max) DN_CArrayResizeFromPool((void **)&(ptr), ptr_size, ptr_max, sizeof((ptr)[0]), pool, new_max)
|
|
#define DN_PArrayResizeFromArena(ptr, ptr_size, ptr_max, arena, new_max) DN_CArrayResizeFromArena((void **)&(ptr), ptr_size, ptr_max, sizeof((ptr)[0]), arena, new_max)
|
|
#define DN_PArrayGrowFromPool(ptr, size, ptr_max, pool, new_max) DN_CArrayGrowFromPool((void **)&(ptr), size, ptr_max, sizeof((ptr)[0]), pool, new_max)
|
|
#define DN_PArrayGrowFromArena(ptr, size, ptr_max, arena, new_max) DN_CArrayGrowFromArena((void **)&(ptr), size, ptr_max, sizeof((ptr)[0]), arena, new_max)
|
|
#define DN_PArrayGrowIfNeededFromPool(ptr, size, ptr_max, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(ptr), size, ptr_max, sizeof((*ptr)[0]), pool, add_count)
|
|
#define DN_PArrayGrowIfNeededFromArena(ptr, size, ptr_max, arena, add_count) DN_CArrayGrowIfNeededFromArena((void **)(ptr), size, ptr_max, sizeof((*ptr)[0]), arena, add_count)
|
|
#define DN_PArrayMakeArray(ptr, ptr_size, max, count, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), count, z_mem)
|
|
#define DN_PArrayMakeArrayZ(ptr, ptr_size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), count, DN_ZMem_Yes)
|
|
#define DN_PArrayMake(ptr, ptr_size, max, z_mem) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), 1, z_mem)
|
|
#define DN_PArrayMakeZ(ptr, ptr_size, max) (DN_CppDeclType(&(ptr)[0]))DN_CArrayMakeArray(ptr, ptr_size, max, sizeof((ptr)[0]), 1, DN_ZMem_Yes)
|
|
#define DN_PArrayAddArray(ptr, ptr_size, max, items, count, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), items, count, add)
|
|
#define DN_PArrayAdd(ptr, ptr_size, max, item, add) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), &item, 1, add)
|
|
#define DN_PArrayAppendArray(ptr, ptr_size, max, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), items, count, DN_ArrayAdd_Append)
|
|
#define DN_PArrayAppend(ptr, ptr_size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), &item, 1, DN_ArrayAdd_Append)
|
|
#define DN_PArrayPrependArray(ptr, ptr_size, max, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), items, count, DN_ArrayAdd_Prepend)
|
|
#define DN_PArrayPrepend(ptr, ptr_size, max, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayAddArray(ptr, ptr_size, max, sizeof((ptr)[0]), &item, 1, DN_ArrayAdd_Prepend)
|
|
#define DN_PArrayEraseRange(ptr, ptr_size, begin_index, count, erase) DN_CArrayEraseRange(ptr, ptr_size, sizeof((ptr)[0]), begin_index, count, erase)
|
|
#define DN_PArrayErase(ptr, ptr_size, index, erase) DN_CArrayEraseRange(ptr, ptr_size, sizeof((ptr)[0]), index, 1, erase)
|
|
#define DN_PArrayInsertArray(ptr, ptr_size, max, index, items, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, ptr_size, max, sizeof((ptr)[0]), index, items, count)
|
|
#define DN_PArrayInsert(ptr, ptr_size, max, index, item) (DN_CppDeclType(&(ptr)[0]))DN_CArrayInsertArray(ptr, ptr_size, max, sizeof((ptr)[0]), index, &item, 1)
|
|
#define DN_PArrayPopFront(ptr, ptr_size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopFront(ptr, ptr_size, sizeof((ptr)[0]), count)
|
|
#define DN_PArrayPopBack(ptr, ptr_size, max, count) (DN_CppDeclType(&(ptr)[0]))DN_CArrayPopBack(ptr, ptr_size, sizeof((ptr)[0]), count)
|
|
|
|
#define DN_LArrayResizeFromPool(c_array, size, pool, new_max) DN_PArrayResizeFromPool(c_array, size, DN_ArrayCountU(c_array), pool, new_max)
|
|
#define DN_LArrayResizeFromArena(c_array, size, arena, new_max) DN_PArrayResizeFromArena(c_array, size, DN_ArrayCountU(c_array), arena, new_max)
|
|
#define DN_LArrayGrowFromPool(c_array, size, pool, new_max) DN_PArrayGrowFromPool(c_array, size, DN_ArrayCountU(c_array), pool, new_max)
|
|
#define DN_LArrayGrowFromArena(c_array, size, arena, new_max) DN_PArrayGrowFromArena(c_array, size, DN_ArrayCountU(c_array), arena, new_max)
|
|
#define DN_LArrayGrowIfNeededFromPool(c_array, size, pool, add_count) DN_PArrayGrowIfNeededFromPool(c_array, size, DN_ArrayCountU(c_array), pool, add_count)
|
|
#define DN_LArrayGrowIfNeededFromArena(c_array, size, arena, add_count) DN_PArrayGrowIfNeededFromArena(c_array, size, DN_ArrayCountU(c_array), arena, add_count)
|
|
#define DN_LArrayMakeArray(c_array, ptr_size, count, z_mem) DN_PArrayMakeArray(c_array, ptr_size, DN_ArrayCountU(c_array), count, z_mem)
|
|
#define DN_LArrayMakeArrayZ(c_array, ptr_size, count) DN_PArrayMakeArrayZ(c_array, ptr_size, DN_ArrayCountU(c_array), count)
|
|
#define DN_LArrayMake(c_array, ptr_size, z_mem) DN_PArrayMake(c_array, ptr_size, DN_ArrayCountU(c_array), z_mem)
|
|
#define DN_LArrayMakeZ(c_array, ptr_size) DN_PArrayMakeZ(c_array, ptr_size, DN_ArrayCountU(c_array))
|
|
#define DN_LArrayAddArray(c_array, ptr_size, items, count, add) DN_PArrayAddArray(c_array, ptr_size, DN_ArrayCountU(c_array), items, count, add)
|
|
#define DN_LArrayAdd(c_array, ptr_size, item, add) DN_PArrayAdd(c_array, ptr_size, DN_ArrayCountU(c_array), item, add)
|
|
#define DN_LArrayAppendArray(c_array, ptr_size, items, count) DN_PArrayAppendArray(c_array, ptr_size, DN_ArrayCountU(c_array), items, count)
|
|
#define DN_LArrayAppend(c_array, ptr_size, item) DN_PArrayAppend(c_array, ptr_size, DN_ArrayCountU(c_array), item)
|
|
#define DN_LArrayPrependArray(c_array, ptr_size, items, count) DN_PArrayPrependArray(c_array, ptr_size, DN_ArrayCountU(c_array), items, count)
|
|
#define DN_LArrayPrepend(c_array, ptr_size, item) DN_PArrayPrepend(c_array, ptr_size, DN_ArrayCountU(c_array), item)
|
|
#define DN_LArrayEraseRange(c_array, ptr_size, begin_index, count, erase) DN_PArrayEraseRange(c_array, ptr_size, begin_index, count, erase)
|
|
#define DN_LArrayErase(c_array, ptr_size, index, erase) DN_PArrayErase(c_array, ptr_size, index, erase)
|
|
#define DN_LArrayInsertArray(c_array, ptr_size, index, items, count) DN_PArrayInsertArray(c_array, ptr_size, DN_ArrayCountU(c_array), index, items, count)
|
|
#define DN_LArrayInsert(c_array, ptr_size, index, item) DN_PArrayInsert(c_array, ptr_size, DN_ArrayCountU(c_array), index, item)
|
|
#define DN_LArrayPopFront(c_array, ptr_size, count) DN_PArrayPopFront(c_array, ptr_size, DN_ArrayCountU(c_array), count)
|
|
#define DN_LArrayPopBack(c_array, ptr_size, count) DN_PArrayPopBack(c_array, ptr_size, DN_ArrayCountU(c_array), count)
|
|
|
|
#define DN_IArrayResizeFromPool(ptr_array, pool, new_max) DN_CArrayResizeFromPool((void **)(&(ptr_array)->data), &(ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), pool, new_max)
|
|
#define DN_IArrayResizeFromArena(ptr_array, arena, new_max) DN_CArrayResizeFromArena((void **)(&(ptr_array)->data), &(ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), arena, new_max)
|
|
#define DN_IArrayGrowFromPool(ptr_array, pool, new_max) DN_CArrayGrowFromPool((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), pool, new_max)
|
|
#define DN_IArrayGrowFromArena(ptr_array, arena, new_max) DN_CArrayGrowFromArena((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), arena, new_max)
|
|
#define DN_IArrayGrowIfNeededFromPool(ptr_array, pool, add_count) DN_CArrayGrowIfNeededFromPool((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), pool, add_count)
|
|
#define DN_IArrayGrowIfNeededFromArena(ptr_array, arena, add_count) DN_CArrayGrowIfNeededFromArena((void **)(&(ptr_array)->data), (ptr_array)->size, &(ptr_array)->max, sizeof((ptr_array)->data[0]), arena, add_count)
|
|
#define DN_IArrayMakeArray(ptr_array, count, z_mem) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), count, z_mem)
|
|
#define DN_IArrayMakeArrayZ(ptr_array, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), count, DN_ZMem_Yes)
|
|
#define DN_IArrayMake(ptr_array, z_mem) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), 1, z_mem)
|
|
#define DN_IArrayMakeZ(ptr_array) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayMakeArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), 1, DN_ZMem_Yes)
|
|
#define DN_IArrayAddArray(ptr_array, items, count, add) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), items, count, add)
|
|
#define DN_IArrayAdd(ptr_array, item, add) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), &item, 1, add)
|
|
#define DN_IArrayAppendArray(ptr_array, items, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), items, count, DN_ArrayAdd_Append)
|
|
#define DN_IArrayAppend(ptr_array, item) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), &item, 1, DN_ArrayAdd_Append)
|
|
#define DN_IArrayPrependArray(ptr_array, items, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), items, count, DN_ArrayAdd_Prepend)
|
|
#define DN_IArrayPrepend(ptr_array, item) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayAddArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), &item, 1, DN_ArrayAdd_Prepend)
|
|
#define DN_IArrayEraseRange(ptr_array, begin_index, count, erase) DN_CArrayEraseRange((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_array)->data)[0]), begin_index, count, erase)
|
|
#define DN_IArrayErase(ptr_array, index, erase) DN_CArrayEraseRange((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_array)->data)[0]), index, 1, erase)
|
|
#define DN_IArrayInsertArray(ptr_array, index, items, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayInsertArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), index, items, count)
|
|
#define DN_IArrayInsert(ptr_array, index, item, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayInsertArray((ptr_array)->data, &(ptr_array)->size, (ptr_array)->max, sizeof(((ptr_array)->data)[0]), index, &item, 1)
|
|
#define DN_IArrayPopFront(ptr_array, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayPopFront((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_array)->data)[0]), count)
|
|
#define DN_IArrayPopBack(ptr_array, count) (DN_CppDeclType(&((ptr_array)->data)[0]))DN_CArrayPopBack((ptr_array)->data, &(ptr_array)->size, sizeof(((ptr_array)->data)[0]), count)
|
|
|
|
#define DN_ISliceAllocArena(slice_ptr, count_, zmem, arena) (DN_CppDeclType(&((slice_ptr)->data[0])))DN_SliceAllocArena((void **)&((slice_ptr)->data), &((slice_ptr)->count), count_, sizeof((slice_ptr)->data[0]), alignof(DN_CppDeclType((slice_ptr)->data[0])), zmem, arena)
|
|
|
|
DN_API void* DN_SliceAllocArena (void **data, DN_USize *slice_size_field, DN_USize size, DN_USize elem_size, DN_U8 align, DN_ZMem zmem, DN_Arena *arena);
|
|
|
|
DN_API void* DN_CArrayInsertArray (void *data, DN_USize *size, DN_USize max, DN_USize elem_size, DN_USize index, void const *items, DN_USize count);
|
|
DN_API void* DN_CArrayPopFront (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
|
|
DN_API void* DN_CArrayPopBack (void *data, DN_USize *size, DN_USize elem_size, DN_USize count);
|
|
DN_API DN_ArrayEraseResult DN_CArrayEraseRange (void *data, DN_USize *size, DN_USize elem_size, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
|
|
DN_API void* DN_CArrayMakeArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, DN_USize make_size, DN_ZMem z_mem);
|
|
DN_API void* DN_CArrayAddArray (void *data, DN_USize *size, DN_USize max, DN_USize data_size, void const *elems, DN_USize elems_count, DN_ArrayAdd add);
|
|
DN_API bool DN_CArrayResizeFromPool (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
|
|
DN_API bool DN_CArrayResizeFromArena (void **data, DN_USize *size, DN_USize *max, DN_USize data_size, DN_Arena *arena, DN_USize new_max);
|
|
DN_API bool DN_CArrayGrowFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
|
|
DN_API bool DN_CArrayGrowFromArena (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize new_max);
|
|
DN_API bool DN_CArrayGrowIfNeededFromPool (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Pool *pool, DN_USize add_count);
|
|
DN_API bool DN_CArrayGrowIfNeededFromArena (void **data, DN_USize size, DN_USize *max, DN_USize data_size, DN_Arena *pool, DN_USize add_count);
|
|
|
|
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_RingHasData (DN_Ring const *ring, DN_U64 size);
|
|
DN_API void DN_RingWrite (DN_Ring *ring, void const *src, DN_U64 src_size);
|
|
#define DN_RingWriteStruct(ring, item) DN_RingWrite((ring), (item), sizeof(*(item)))
|
|
DN_API void DN_RingRead (DN_Ring *ring, void *dest, DN_U64 dest_size);
|
|
#define DN_RingReadStruct(ring, dest) DN_RingRead((ring), (dest), sizeof(*(dest)))
|
|
|
|
DN_U32 const DN_DS_MAP_DEFAULT_HASH_SEED = 0x8a1ced49;
|
|
DN_U32 const DN_DS_MAP_SENTINEL_SLOT = 0;
|
|
|
|
template <typename T> DN_DSMap<T> DN_DSMapInit (DN_Arena *arena, DN_U32 size, DN_DSMapFlags flags);
|
|
template <typename T> void DN_DSMapDeinit (DN_DSMap<T> *map, DN_ZMem z_mem);
|
|
template <typename T> bool DN_DSMapIsValid (DN_DSMap<T> const *map);
|
|
template <typename T> DN_U32 DN_DSMapHash (DN_DSMap<T> const *map, DN_DSMapKey key);
|
|
template <typename T> DN_U32 DN_DSMapHashToSlotIndex (DN_DSMap<T> const *map, DN_DSMapKey key);
|
|
template <typename T> DN_DSMapResult<T> DN_DSMapFind (DN_DSMap<T> const *map, DN_DSMapKey key);
|
|
template <typename T> DN_DSMapResult<T> DN_DSMapMake (DN_DSMap<T> *map, DN_DSMapKey key);
|
|
template <typename T> DN_DSMapResult<T> DN_DSMapSet (DN_DSMap<T> *map, DN_DSMapKey key, T const &value);
|
|
template <typename T> DN_DSMapResult<T> DN_DSMapFindKeyU64 (DN_DSMap<T> const *map, DN_U64 key);
|
|
template <typename T> DN_DSMapResult<T> DN_DSMapMakeKeyU64 (DN_DSMap<T> *map, DN_U64 key);
|
|
template <typename T> DN_DSMapResult<T> DN_DSMapSetKeyU64 (DN_DSMap<T> *map, DN_U64 key, T const &value);
|
|
template <typename T> DN_DSMapResult<T> DN_DSMapFindKeyStr8 (DN_DSMap<T> const *map, DN_Str8 key);
|
|
template <typename T> DN_DSMapResult<T> DN_DSMapMakeKeyStr8 (DN_DSMap<T> *map, DN_Str8 key);
|
|
template <typename T> DN_DSMapResult<T> DN_DSMapSetKeyStr8 (DN_DSMap<T> *map, DN_Str8 key, T const &value);
|
|
template <typename T> bool DN_DSMapResize (DN_DSMap<T> *map, DN_U32 size);
|
|
template <typename T> bool DN_DSMapErase (DN_DSMap<T> *map, DN_DSMapKey key);
|
|
template <typename T> bool DN_DSMapEraseKeyU64 (DN_DSMap<T> *map, DN_U64 key);
|
|
template <typename T> bool DN_DSMapEraseKeyStr8 (DN_DSMap<T> *map, DN_Str8 key);
|
|
template <typename T> DN_DSMapKey DN_DSMapKeyBuffer (DN_DSMap<T> const *map, void const *data, DN_USize size);
|
|
template <typename T> DN_DSMapKey DN_DSMapKeyBufferAsU64NoHash (DN_DSMap<T> const *map, void const *data, DN_USize size);
|
|
template <typename T> DN_DSMapKey DN_DSMapKeyU64 (DN_DSMap<T> const *map, DN_U64 u64);
|
|
template <typename T> DN_DSMapKey DN_DSMapKeyStr8 (DN_DSMap<T> const *map, DN_Str8 string);
|
|
#define DN_DSMapKeyCStr8(map, string) DN_DSMapKeyBuffer(map, string, sizeof((string))/sizeof((string)[0]) - 1)
|
|
DN_API DN_DSMapKey DN_DSMapKeyU64NoHash (DN_U64 u64);
|
|
DN_API bool DN_DSMapKeyEquals (DN_DSMapKey lhs, DN_DSMapKey rhs);
|
|
DN_API bool operator== (DN_DSMapKey lhs, DN_DSMapKey rhs);
|
|
#endif // !defined(DN_CONTAINER_H)
|
|
// DN: Single header generator commented out => #include "Base/dn_base_leak.h"
|
|
#if !defined(DN_BASE_LEAK_H)
|
|
#define DN_BASE_LEAK_H
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
enum DN_LeakAllocFlag
|
|
{
|
|
DN_LeakAllocFlag_Freed = 1 << 0,
|
|
DN_LeakAllocFlag_LeakPermitted = 1 << 1,
|
|
};
|
|
|
|
struct DN_LeakAlloc
|
|
{
|
|
void *ptr; // 8 Pointer to the allocation being tracked
|
|
DN_USize size; // 16 Size of the allocation
|
|
DN_USize freed_size; // 24 Store the size of the allocation when it is freed
|
|
DN_Str8 stack_trace; // 40 Stack trace at the point of allocation
|
|
DN_Str8 freed_stack_trace; // 56 Stack trace of where the allocation was freed
|
|
DN_U16 flags; // 72 Bit flags from `DN_LeakAllocFlag`
|
|
};
|
|
|
|
// NOTE: We aim to keep the allocation record as light as possible as memory tracking can get
|
|
// expensive. Enforce that there is no unexpected padding.
|
|
DN_StaticAssert(sizeof(DN_LeakAlloc) == 64 || sizeof(DN_LeakAlloc) == 32); // NOTE: 64 bit vs 32 bit pointers respectively
|
|
|
|
struct DN_LeakTracker
|
|
{
|
|
DN_DSMap<DN_LeakAlloc> alloc_table;
|
|
DN_TicketMutex alloc_table_mutex;
|
|
DN_MemList alloc_table_mem;
|
|
DN_Arena alloc_table_arena;
|
|
DN_U64 alloc_table_bytes_allocated_for_stack_traces;
|
|
};
|
|
|
|
DN_API void DN_LeakTrackAlloc_ (DN_LeakTracker *leak, void *ptr, DN_USize size, bool alloc_can_leak);
|
|
DN_API void DN_LeakTrackDealloc_(DN_LeakTracker *leak, void *ptr);
|
|
DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
|
|
|
|
#if defined(DN_LEAK_TRACKING)
|
|
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) DN_LeakTrackAlloc_(leak, ptr, size, alloc_can_leak)
|
|
#define DN_LeakTrackDealloc(leak, ptr) DN_LeakTrackDealloc_(leak, ptr)
|
|
#define DN_LeakDump(leak) DN_LeakDump_(leak)
|
|
#else
|
|
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
|
#define DN_LeakTrackDealloc(leak, ptr) do { (void)ptr; } while (0)
|
|
#define DN_LeakDump(leak) do { } while (0)
|
|
#endif
|
|
#endif // DN_BASE_LEAK_H
|
|
|
|
#if DN_H_WITH_OS
|
|
#if defined(DN_PLATFORM_WIN32)
|
|
// DN: Single header generator commented out => #include "OS/dn_os_windows.h"
|
|
#if !defined(DN_OS_WINDOWS_H)
|
|
#define DN_OS_WINDOWS_H
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
#if defined(DN_COMPILER_MSVC) || defined(DN_COMPILER_CLANG_CL)
|
|
#pragma comment(lib, "bcrypt")
|
|
#pragma comment(lib, "winhttp")
|
|
#pragma comment(lib, "dbghelp")
|
|
#pragma comment(lib, "comdlg32")
|
|
#pragma comment(lib, "pathcch")
|
|
#pragma comment(lib, "Shell32") // ShellExecuteW
|
|
#pragma comment(lib, "shlwapi")
|
|
#endif
|
|
|
|
#if defined(DN_NO_WINDOWS_H_REPLACEMENT_HEADER) || defined(_INC_WINDOWS)
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <Windows.h> // LONG
|
|
#include <bcrypt.h> // DN_OS_SecureRNGBytes -> BCryptOpenAlgorithmProvider ... etc
|
|
#include <shellapi.h> // DN_Win_MakeProcessDPIAware -> SetProcessDpiAwareProc
|
|
#include <shlwapi.h> // PathRelativePathTO
|
|
#include <pathcch.h> // PathCchCanonicalizeEx
|
|
#include <winhttp.h> // WinHttp*
|
|
#include <psapi.h> // PROCESS_MEMORY_COUNTERS_EX2
|
|
#include <commdlg.h> // OPENFILENAMEW
|
|
#include <DbgHelp.h>
|
|
#else
|
|
DN_MSVC_WARNING_PUSH
|
|
DN_MSVC_WARNING_DISABLE(4201) // warning C4201: nonstandard extension used: nameless struct/union
|
|
|
|
// NOTE: basetsd.h /////////////////////////////////////////////////////////////////////////////
|
|
typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
|
|
typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
|
|
typedef ULONG_PTR SIZE_T, *PSIZE_T;
|
|
typedef __int64 LONG_PTR, *PLONG_PTR;
|
|
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
|
|
typedef unsigned __int64 ULONG64, *PULONG64;
|
|
typedef unsigned __int64 DWORD64, *PDWORD64;
|
|
|
|
// NOTE: shared/minwindef.h ////////////////////////////////////////////////////////////////////
|
|
struct HINSTANCE__ {
|
|
int unused;
|
|
};
|
|
typedef struct HINSTANCE__ *HINSTANCE;
|
|
|
|
typedef unsigned long DWORD;
|
|
typedef int BOOL;
|
|
typedef int INT;
|
|
typedef unsigned long ULONG;
|
|
typedef unsigned int UINT;
|
|
typedef unsigned short WORD;
|
|
typedef unsigned char BYTE;
|
|
typedef unsigned char UCHAR;
|
|
typedef HINSTANCE HMODULE; /* HMODULEs can be used in place of HINSTANCEs */
|
|
typedef void * HANDLE;
|
|
typedef HANDLE HLOCAL;
|
|
|
|
typedef unsigned __int64 WPARAM;
|
|
typedef LONG_PTR LPARAM;
|
|
typedef LONG_PTR LRESULT;
|
|
|
|
#define MAX_PATH 260
|
|
|
|
typedef struct _FILETIME {
|
|
DWORD dwLowDateTime;
|
|
DWORD dwHighDateTime;
|
|
} FILETIME, *PFILETIME, *LPFILETIME;
|
|
|
|
// NOTE: shared/winerror.h /////////////////////////////////////////////////////////////////////
|
|
// NOTE: GetModuleFileNameW
|
|
#define ERROR_INSUFFICIENT_BUFFER 122L // dderror
|
|
|
|
// NOTE: um/winnls.h ///////////////////////////////////////////////////////////////////////////
|
|
// NOTE: MultiByteToWideChar
|
|
#define CP_UTF8 65001 // UTF-8 translation
|
|
|
|
// NOTE: um/winnt.h ////////////////////////////////////////////////////////////////////////////
|
|
typedef void VOID;
|
|
typedef __int64 LONGLONG;
|
|
typedef unsigned __int64 ULONGLONG;
|
|
typedef void * HANDLE;
|
|
typedef char CHAR;
|
|
typedef short SHORT;
|
|
typedef long LONG;
|
|
typedef wchar_t WCHAR; // wc, 16-bit UNICODE character
|
|
typedef CHAR * NPSTR, *LPSTR, *PSTR;
|
|
typedef WCHAR * NWPSTR, *LPWSTR, *PWSTR;
|
|
typedef long HRESULT;
|
|
|
|
// NOTE: VirtualAlloc: Allocation Type
|
|
#define MEM_RESERVE 0x00002000
|
|
#define MEM_COMMIT 0x00001000
|
|
#define MEM_DECOMMIT 0x00004000
|
|
#define MEM_RELEASE 0x00008000
|
|
|
|
// NOTE: VirtualAlloc: Page Permissions
|
|
#define PAGE_NOACCESS 0x01
|
|
#define PAGE_READONLY 0x02
|
|
#define PAGE_READWRITE 0x04
|
|
#define PAGE_GUARD 0x100
|
|
|
|
// NOTE: HeapAlloc
|
|
#define HEAP_ZERO_MEMORY 0x00000008
|
|
#define HEAP_NO_SERIALIZE 0x00000001
|
|
#define HEAP_GROWABLE 0x00000002
|
|
#define HEAP_GENERATE_EXCEPTIONS 0x00000004
|
|
#define HEAP_ZERO_MEMORY 0x00000008
|
|
#define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010
|
|
#define HEAP_TAIL_CHECKING_ENABLED 0x00000020
|
|
#define HEAP_FREE_CHECKING_ENABLED 0x00000040
|
|
#define HEAP_DISABLE_COALESCE_ON_FREE 0x00000080
|
|
#define HEAP_CREATE_ALIGN_16 0x00010000
|
|
#define HEAP_CREATE_ENABLE_TRACING 0x00020000
|
|
#define HEAP_CREATE_ENABLE_EXECUTE 0x00040000
|
|
#define HEAP_MAXIMUM_TAG 0x0FFF
|
|
#define HEAP_PSEUDO_TAG_FLAG 0x8000
|
|
#define HEAP_TAG_SHIFT 18
|
|
#define HEAP_CREATE_SEGMENT_HEAP 0x00000100
|
|
#define HEAP_CREATE_HARDENED 0x00000200
|
|
|
|
// NOTE: FormatMessageA
|
|
#define MAKELANGID(p, s) ((((WORD )(s)) << 10) | (WORD )(p))
|
|
#define LANG_NEUTRAL 0x00
|
|
#define SUBLANG_DEFAULT 0x01 // user default
|
|
|
|
// NOTE: CreateFile
|
|
#define GENERIC_READ (0x80000000L)
|
|
#define GENERIC_WRITE (0x40000000L)
|
|
#define GENERIC_EXECUTE (0x20000000L)
|
|
#define GENERIC_ALL (0x10000000L)
|
|
|
|
#define FILE_APPEND_DATA (0x0004) // file
|
|
|
|
// NOTE: CreateFile/FindFirstFile
|
|
#define FILE_SHARE_READ 0x00000001
|
|
#define FILE_SHARE_WRITE 0x00000002
|
|
#define FILE_SHARE_DELETE 0x00000004
|
|
|
|
#define FILE_ATTRIBUTE_READONLY 0x00000001
|
|
#define FILE_ATTRIBUTE_HIDDEN 0x00000002
|
|
#define FILE_ATTRIBUTE_SYSTEM 0x00000004
|
|
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
|
|
#define FILE_ATTRIBUTE_NORMAL 0x00000080
|
|
|
|
// NOTE: STACKFRAME64
|
|
#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8)
|
|
|
|
// NOTE: WaitForSingleObject
|
|
#define WAIT_TIMEOUT 258L // dderror
|
|
#define STATUS_WAIT_0 ((DWORD )0x00000000L)
|
|
#define STATUS_ABANDONED_WAIT_0 ((DWORD )0x00000080L)
|
|
|
|
#define S_OK ((HRESULT)0L)
|
|
#define S_FALSE ((HRESULT)1L)
|
|
|
|
typedef union _ULARGE_INTEGER {
|
|
struct {
|
|
DWORD LowPart;
|
|
DWORD HighPart;
|
|
} DUMMYSTRUCTNAME;
|
|
struct {
|
|
DWORD LowPart;
|
|
DWORD HighPart;
|
|
} u;
|
|
ULONGLONG QuadPart;
|
|
} ULARGE_INTEGER;
|
|
|
|
typedef union _LARGE_INTEGER {
|
|
struct {
|
|
DWORD LowPart;
|
|
LONG HighPart;
|
|
} DUMMYSTRUCTNAME;
|
|
struct {
|
|
DWORD LowPart;
|
|
LONG HighPart;
|
|
} u;
|
|
LONGLONG QuadPart;
|
|
} LARGE_INTEGER;
|
|
|
|
typedef struct __declspec(align(16)) _M128A {
|
|
ULONGLONG Low;
|
|
LONGLONG High;
|
|
} M128A, *PM128A;
|
|
|
|
typedef struct __declspec(align(16)) _XSAVE_FORMAT {
|
|
WORD ControlWord;
|
|
WORD StatusWord;
|
|
BYTE TagWord;
|
|
BYTE Reserved1;
|
|
WORD ErrorOpcode;
|
|
DWORD ErrorOffset;
|
|
WORD ErrorSelector;
|
|
WORD Reserved2;
|
|
DWORD DataOffset;
|
|
WORD DataSelector;
|
|
WORD Reserved3;
|
|
DWORD MxCsr;
|
|
DWORD MxCsr_Mask;
|
|
M128A FloatRegisters[8];
|
|
#if defined(_WIN64)
|
|
M128A XmmRegisters[16];
|
|
BYTE Reserved4[96];
|
|
#else
|
|
M128A XmmRegisters[8];
|
|
BYTE Reserved4[224];
|
|
#endif
|
|
} XSAVE_FORMAT, *PXSAVE_FORMAT;
|
|
typedef XSAVE_FORMAT XMM_SAVE_AREA32, *PXMM_SAVE_AREA32;
|
|
|
|
typedef struct __declspec(align(16)) _CONTEXT {
|
|
DWORD64 P1Home;
|
|
DWORD64 P2Home;
|
|
DWORD64 P3Home;
|
|
DWORD64 P4Home;
|
|
DWORD64 P5Home;
|
|
DWORD64 P6Home;
|
|
DWORD ContextFlags;
|
|
DWORD MxCsr;
|
|
WORD SegCs;
|
|
WORD SegDs;
|
|
WORD SegEs;
|
|
WORD SegFs;
|
|
WORD SegGs;
|
|
WORD SegSs;
|
|
DWORD EFlags;
|
|
DWORD64 Dr0;
|
|
DWORD64 Dr1;
|
|
DWORD64 Dr2;
|
|
DWORD64 Dr3;
|
|
DWORD64 Dr6;
|
|
DWORD64 Dr7;
|
|
DWORD64 Rax;
|
|
DWORD64 Rcx;
|
|
DWORD64 Rdx;
|
|
DWORD64 Rbx;
|
|
DWORD64 Rsp;
|
|
DWORD64 Rbp;
|
|
DWORD64 Rsi;
|
|
DWORD64 Rdi;
|
|
DWORD64 R8;
|
|
DWORD64 R9;
|
|
DWORD64 R10;
|
|
DWORD64 R11;
|
|
DWORD64 R12;
|
|
DWORD64 R13;
|
|
DWORD64 R14;
|
|
DWORD64 R15;
|
|
DWORD64 Rip;
|
|
|
|
union {
|
|
XMM_SAVE_AREA32 FltSave;
|
|
|
|
struct {
|
|
M128A Header[2];
|
|
M128A Legacy[8];
|
|
M128A Xmm0;
|
|
M128A Xmm1;
|
|
M128A Xmm2;
|
|
M128A Xmm3;
|
|
M128A Xmm4;
|
|
M128A Xmm5;
|
|
M128A Xmm6;
|
|
M128A Xmm7;
|
|
M128A Xmm8;
|
|
M128A Xmm9;
|
|
M128A Xmm10;
|
|
M128A Xmm11;
|
|
M128A Xmm12;
|
|
M128A Xmm13;
|
|
M128A Xmm14;
|
|
M128A Xmm15;
|
|
} DUMMYSTRUCTNAME;
|
|
} DUMMYUNIONNAME;
|
|
|
|
M128A VectorRegister[26];
|
|
DWORD64 VectorControl;
|
|
DWORD64 DebugControl;
|
|
DWORD64 LastBranchToRip;
|
|
DWORD64 LastBranchFromRip;
|
|
DWORD64 LastExceptionToRip;
|
|
DWORD64 LastExceptionFromRip;
|
|
} CONTEXT;
|
|
|
|
typedef struct _LIST_ENTRY {
|
|
struct _LIST_ENTRY *Flink;
|
|
struct _LIST_ENTRY *Blink;
|
|
} LIST_ENTRY, *PLIST_ENTRY, PRLIST_ENTRY;
|
|
|
|
typedef struct _RTL_CRITICAL_SECTION_DEBUG {
|
|
WORD Type;
|
|
WORD CreatorBackTraceIndex;
|
|
struct _RTL_CRITICAL_SECTION *CriticalSection;
|
|
LIST_ENTRY ProcessLocksList;
|
|
DWORD EntryCount;
|
|
DWORD ContentionCount;
|
|
DWORD Flags;
|
|
WORD CreatorBackTraceIndexHigh;
|
|
WORD Identifier;
|
|
} RTL_CRITICAL_SECTION_DEBUG, *PRTL_CRITICAL_SECTION_DEBUG, RTL_RESOURCE_DEBUG, *PRTL_RESOURCE_DEBUG;
|
|
|
|
typedef struct _RTL_CONDITION_VARIABLE {
|
|
VOID *Ptr;
|
|
} RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
|
|
|
|
#pragma pack(push, 8)
|
|
typedef struct _RTL_CRITICAL_SECTION {
|
|
PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
|
|
|
|
//
|
|
// The following three fields control entering and exiting the critical
|
|
// section for the resource
|
|
//
|
|
|
|
LONG LockCount;
|
|
LONG RecursionCount;
|
|
HANDLE OwningThread; // from the thread's ClientId->UniqueThread
|
|
HANDLE LockSemaphore;
|
|
ULONG_PTR SpinCount; // force size on 64-bit systems when packed
|
|
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
|
|
#pragma pack(pop)
|
|
|
|
typedef struct _MODLOAD_DATA {
|
|
DWORD ssize; // size of this struct
|
|
DWORD ssig; // signature identifying the passed data
|
|
VOID *data; // pointer to passed data
|
|
DWORD size; // size of passed data
|
|
DWORD flags; // options
|
|
} MODLOAD_DATA, *PMODLOAD_DATA;
|
|
|
|
typedef struct _RTL_BARRIER {
|
|
DWORD Reserved1;
|
|
DWORD Reserved2;
|
|
ULONG_PTR Reserved3[2];
|
|
DWORD Reserved4;
|
|
DWORD Reserved5;
|
|
} RTL_BARRIER, *PRTL_BARRIER;
|
|
|
|
#define SLMFLAG_VIRTUAL 0x1
|
|
#define SLMFLAG_ALT_INDEX 0x2
|
|
#define SLMFLAG_NO_SYMBOLS 0x4
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) VOID __stdcall RtlCaptureContext(CONTEXT *ContextRecord);
|
|
__declspec(dllimport) HANDLE __stdcall GetCurrentProcess(void);
|
|
__declspec(dllimport) HANDLE __stdcall GetCurrentThread(void);
|
|
__declspec(dllimport) DWORD __stdcall SymSetOptions(DWORD SymOptions);
|
|
__declspec(dllimport) BOOL __stdcall SymInitialize(HANDLE hProcess, const CHAR* UserSearchPath, BOOL fInvadeProcess);
|
|
__declspec(dllimport) DWORD64 __stdcall SymLoadModuleEx(HANDLE hProcess, HANDLE hFile, CHAR const *ImageName, CHAR const *ModuleName, DWORD64 BaseOfDll, DWORD DllSize, MODLOAD_DATA *Data, DWORD Flags);
|
|
__declspec(dllimport) BOOL __stdcall SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll);
|
|
}
|
|
|
|
// NOTE: um/heapapi.h ////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) HANDLE __stdcall HeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize);
|
|
__declspec(dllimport) BOOL __stdcall HeapDestroy(HANDLE hHeap);
|
|
__declspec(dllimport) VOID * __stdcall HeapAlloc(HANDLE hHeap, DWORD dwFlags,SIZE_T dwBytes);
|
|
__declspec(dllimport) VOID * __stdcall HeapReAlloc(HANDLE hHeap, DWORD dwFlags, VOID *lpMem, SIZE_T dwBytes);
|
|
__declspec(dllimport) BOOL __stdcall HeapFree(HANDLE hHeap, DWORD dwFlags, VOID *lpMem);
|
|
__declspec(dllimport) SIZE_T __stdcall HeapSize(HANDLE hHeap, DWORD dwFlags, VOID const *lpMem);
|
|
__declspec(dllimport) HANDLE __stdcall GetProcessHeap(VOID);
|
|
__declspec(dllimport) SIZE_T __stdcall HeapCompact(HANDLE hHeap, DWORD dwFlags);
|
|
}
|
|
|
|
// NOTE: shared/windef.h ////////////////////////////////////////////////////////////////////
|
|
typedef struct tagPOINT
|
|
{
|
|
LONG x;
|
|
LONG y;
|
|
} POINT, *PPOINT, *NPPOINT, *LPPOINT;
|
|
|
|
// NOTE: handleapi.h ///////////////////////////////////////////////////////////////////////////
|
|
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall CloseHandle(HANDLE hObject);
|
|
}
|
|
|
|
// NOTE: consoleapi.h ///////////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall WriteConsoleA(HANDLE hConsoleOutput, const VOID* lpBuffer, DWORD nNumberOfCharsToWrite, DWORD *lpNumberOfCharsWritten, VOID *lpReserved);
|
|
__declspec(dllimport) BOOL __stdcall AllocConsole(VOID);
|
|
__declspec(dllimport) BOOL __stdcall FreeConsole(VOID);
|
|
__declspec(dllimport) BOOL __stdcall AttachConsole(DWORD dwProcessId);
|
|
__declspec(dllimport) BOOL __stdcall GetConsoleMode(HANDLE hConsoleHandle, DWORD *lpMode);
|
|
}
|
|
|
|
// NOTE: um/minwinbase.h ///////////////////////////////////////////////////////////////////////
|
|
// NOTE: FindFirstFile
|
|
#define FIND_FIRST_EX_CASE_SENSITIVE 0x00000001
|
|
#define FIND_FIRST_EX_LARGE_FETCH 0x00000002
|
|
|
|
// NOTE: WaitFor..
|
|
#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
|
|
#define WAIT_OBJECT_0 ((STATUS_WAIT_0 ) + 0 )
|
|
#define WAIT_ABANDONED ((STATUS_ABANDONED_WAIT_0 ) + 0 )
|
|
#define WAIT_ABANDONED_0 ((STATUS_ABANDONED_WAIT_0 ) + 0 )
|
|
|
|
// NOTE: CreateProcessW
|
|
#define CREATE_UNICODE_ENVIRONMENT 0x00000400
|
|
#define CREATE_NO_WINDOW 0x08000000
|
|
|
|
typedef enum _GET_FILEEX_INFO_LEVELS {
|
|
GetFileExInfoStandard,
|
|
GetFileExMaxInfoLevel
|
|
} GET_FILEEX_INFO_LEVELS;
|
|
|
|
typedef struct _SECURITY_ATTRIBUTES {
|
|
DWORD nLength;
|
|
VOID *lpSecurityDescriptor;
|
|
BOOL bInheritHandle;
|
|
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
|
|
|
|
typedef enum _FINDEX_INFO_LEVELS {
|
|
FindExInfoStandard,
|
|
FindExInfoBasic,
|
|
FindExInfoMaxInfoLevel
|
|
} FINDEX_INFO_LEVELS;
|
|
|
|
typedef enum _FINDEX_SEARCH_OPS {
|
|
FindExSearchNameMatch,
|
|
FindExSearchLimitToDirectories,
|
|
FindExSearchLimitToDevices,
|
|
FindExSearchMaxSearchOp
|
|
} FINDEX_SEARCH_OPS;
|
|
|
|
typedef struct _WIN32_FIND_DATAW {
|
|
DWORD dwFileAttributes;
|
|
FILETIME ftCreationTime;
|
|
FILETIME ftLastAccessTime;
|
|
FILETIME ftLastWriteTime;
|
|
DWORD nFileSizeHigh;
|
|
DWORD nFileSizeLow;
|
|
DWORD dwReserved0;
|
|
DWORD dwReserved1;
|
|
WCHAR cFileName[ MAX_PATH ];
|
|
WCHAR cAlternateFileName[ 14 ];
|
|
#ifdef _MAC
|
|
DWORD dwFileType;
|
|
DWORD dwCreatorType;
|
|
WORD wFinderFlags;
|
|
#endif
|
|
} WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW;
|
|
|
|
typedef struct _SYSTEMTIME {
|
|
WORD wYear;
|
|
WORD wMonth;
|
|
WORD wDayOfWeek;
|
|
WORD wDay;
|
|
WORD wHour;
|
|
WORD wMinute;
|
|
WORD wSecond;
|
|
WORD wMilliseconds;
|
|
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
|
|
|
|
typedef struct _OVERLAPPED {
|
|
ULONG_PTR Internal;
|
|
ULONG_PTR InternalHigh;
|
|
union {
|
|
struct {
|
|
DWORD Offset;
|
|
DWORD OffsetHigh;
|
|
} DUMMYSTRUCTNAME;
|
|
VOID *Pointer;
|
|
} DUMMYUNIONNAME;
|
|
|
|
HANDLE hEvent;
|
|
} OVERLAPPED, *LPOVERLAPPED;
|
|
|
|
typedef RTL_CRITICAL_SECTION CRITICAL_SECTION;
|
|
|
|
#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
|
|
#define WAIT_OBJECT_0 ((STATUS_WAIT_0 ) + 0 )
|
|
|
|
#define INFINITE 0xFFFFFFFF // Wait/Synchronisation: Infinite timeout
|
|
|
|
#define STD_INPUT_HANDLE ((DWORD)-10)
|
|
#define STD_OUTPUT_HANDLE ((DWORD)-11)
|
|
#define STD_ERROR_HANDLE ((DWORD)-12)
|
|
|
|
#define HANDLE_FLAG_INHERIT 0x00000001
|
|
#define HANDLE_FLAG_PROTECT_FROM_CLOSE 0x00000002
|
|
|
|
// NOTE: MoveFile
|
|
#define MOVEFILE_REPLACE_EXISTING 0x00000001
|
|
#define MOVEFILE_COPY_ALLOWED 0x00000002
|
|
|
|
// NOTE: FormatMessageA
|
|
#define FORMAT_MESSAGE_ALLOCATE_BUFFER 0x00000100
|
|
#define FORMAT_MESSAGE_IGNORE_INSERTS 0x00000200
|
|
#define FORMAT_MESSAGE_FROM_HMODULE 0x00000800
|
|
#define FORMAT_MESSAGE_FROM_SYSTEM 0x00001000
|
|
|
|
// NOTE: CreateProcessW
|
|
#define STARTF_USESTDHANDLES 0x00000100
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall MoveFileExW (const WCHAR *lpExistingFileName, const WCHAR *lpNewFileName, DWORD dwFlags);
|
|
__declspec(dllimport) BOOL __stdcall CopyFileW (const WCHAR *lpExistingFileName, const WCHAR *lpNewFileName, BOOL bFailIfExists);
|
|
__declspec(dllimport) HANDLE __stdcall CreateSemaphoreA(SECURITY_ATTRIBUTES *lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, const CHAR *lpName);
|
|
__declspec(dllimport) DWORD __stdcall FormatMessageW (DWORD dwFlags, VOID const *lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, va_list *Arguments);
|
|
__declspec(dllimport) HLOCAL __stdcall LocalFree (HLOCAL hMem);
|
|
}
|
|
|
|
// NOTE: um/stringapiset.h /////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) int __stdcall MultiByteToWideChar(UINT CodePage, DWORD dwFlags, const CHAR *lpMultiByteStr, int cbMultiByte, WCHAR *lpWideCharStr, int cchWideChar);
|
|
__declspec(dllimport) int __stdcall WideCharToMultiByte(UINT CodePage, DWORD dwFlags, const WCHAR *lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, const CHAR *lpDefaultChar, BOOL *lpUsedDefaultChar);
|
|
}
|
|
|
|
// NOTE: um/fileapi.h //////////////////////////////////////////////////////////////////////////
|
|
#define INVALID_FILE_SIZE ((DWORD)0xFFFFFFFF)
|
|
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
|
|
|
// NOTE: CreateFile
|
|
#define CREATE_NEW 1
|
|
#define CREATE_ALWAYS 2
|
|
#define OPEN_EXISTING 3
|
|
#define OPEN_ALWAYS 4
|
|
#define TRUNCATE_EXISTING 5
|
|
|
|
typedef struct _WIN32_FILE_ATTRIBUTE_DATA {
|
|
DWORD dwFileAttributes;
|
|
FILETIME ftCreationTime;
|
|
FILETIME ftLastAccessTime;
|
|
FILETIME ftLastWriteTime;
|
|
DWORD nFileSizeHigh;
|
|
DWORD nFileSizeLow;
|
|
} WIN32_FILE_ATTRIBUTE_DATA, *LPWIN32_FILE_ATTRIBUTE_DATA;
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall FlushFileBuffers (HANDLE hFile);
|
|
__declspec(dllimport) BOOL __stdcall CreateDirectoryW (const WCHAR *lpPathName, SECURITY_ATTRIBUTES *lpSecurityAttributes);
|
|
__declspec(dllimport) BOOL __stdcall RemoveDirectoryW (const WCHAR *lpPathName);
|
|
__declspec(dllimport) BOOL __stdcall FindNextFileW (HANDLE hFindFile, WIN32_FIND_DATAW *lpFindFileData);
|
|
__declspec(dllimport) BOOL __stdcall FindClose (HANDLE hFindFile);
|
|
__declspec(dllimport) BOOL __stdcall FileTimeToLocalFileTime(const FILETIME *lpFileTime, FILETIME *lpLocalFileTime);
|
|
|
|
__declspec(dllimport) HANDLE __stdcall FindFirstFileExW (const WCHAR *lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, VOID *lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, VOID *lpSearchFilter, DWORD dwAdditionalFlags);
|
|
__declspec(dllimport) BOOL __stdcall GetFileAttributesExW (const WCHAR *lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, VOID *lpFileInformation);
|
|
__declspec(dllimport) BOOL __stdcall GetFileSizeEx (HANDLE hFile, LARGE_INTEGER *lpFileSize);
|
|
__declspec(dllimport) BOOL __stdcall DeleteFileW (const WCHAR *lpFileName);
|
|
__declspec(dllimport) HANDLE __stdcall CreateFileW (const WCHAR *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
|
__declspec(dllimport) BOOL __stdcall ReadFile (HANDLE hFile, VOID *lpBuffer, DWORD nNumberOfBytesToRead, DWORD *lpNumberOfBytesRead, OVERLAPPED *lpOverlapped);
|
|
__declspec(dllimport) BOOL __stdcall WriteFile (HANDLE hFile, const VOID *lpBuffer, DWORD nNumberOfBytesToWrite, DWORD *lpNumberOfBytesWritten, OVERLAPPED *lpOverlapped);
|
|
__declspec(dllimport) BOOL __stdcall GetDiskFreeSpaceExW (WCHAR const *lpDirectoryName, ULARGE_INTEGER *lpFreeBytesAvailableToCaller, ULARGE_INTEGER *lpTotalNumberOfBytes, ULARGE_INTEGER *lpTotalNumberOfFreeBytes);
|
|
}
|
|
|
|
// NOTE: um/processenv.h ///////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) DWORD __stdcall GetCurrentDirectoryW (DWORD nBufferLength, WCHAR *lpBuffer);
|
|
__declspec(dllimport) HANDLE __stdcall GetStdHandle (DWORD nStdHandle);
|
|
__declspec(dllimport) WCHAR* __stdcall GetEnvironmentStringsW ();
|
|
__declspec(dllimport) BOOL __stdcall FreeEnvironmentStringsW(WCHAR *penv);
|
|
__declspec(dllimport) DWORD __stdcall GetEnvironmentVariableW(WCHAR const *lpName, WCHAR *lpBuffer, DWORD nSize);
|
|
__declspec(dllimport) BOOL __stdcall SetEnvironmentVariableW(WCHAR const *lpName, WCHAR const *lpValue);
|
|
}
|
|
|
|
// NOTE: um/psapi.h ////////////////////////////////////////////////////////////////////////////
|
|
typedef struct _PROCESS_MEMORY_COUNTERS {
|
|
DWORD cb;
|
|
DWORD PageFaultCount;
|
|
SIZE_T PeakWorkingSetSize;
|
|
SIZE_T WorkingSetSize;
|
|
SIZE_T QuotaPeakPagedPoolUsage;
|
|
SIZE_T QuotaPagedPoolUsage;
|
|
SIZE_T QuotaPeakNonPagedPoolUsage;
|
|
SIZE_T QuotaNonPagedPoolUsage;
|
|
SIZE_T PagefileUsage;
|
|
SIZE_T PeakPagefileUsage;
|
|
} PROCESS_MEMORY_COUNTERS;
|
|
typedef PROCESS_MEMORY_COUNTERS *PPROCESS_MEMORY_COUNTERS;
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall GetProcessMemoryInfo(HANDLE Process, PPROCESS_MEMORY_COUNTERS ppsmemCounters, DWORD cb);
|
|
}
|
|
|
|
// NOTE: um/sysinfoapi.h ///////////////////////////////////////////////////////////////////////
|
|
typedef struct _SYSTEM_INFO {
|
|
union {
|
|
DWORD dwOemId; // Obsolete field...do not use
|
|
struct {
|
|
WORD wProcessorArchitecture;
|
|
WORD wReserved;
|
|
} DUMMYSTRUCTNAME;
|
|
} DUMMYUNIONNAME;
|
|
DWORD dwPageSize;
|
|
VOID *lpMinimumApplicationAddress;
|
|
VOID *lpMaximumApplicationAddress;
|
|
DWORD_PTR dwActiveProcessorMask;
|
|
DWORD dwNumberOfProcessors;
|
|
DWORD dwProcessorType;
|
|
DWORD dwAllocationGranularity;
|
|
WORD wProcessorLevel;
|
|
WORD wProcessorRevision;
|
|
} SYSTEM_INFO, *LPSYSTEM_INFO;
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) VOID __stdcall GetSystemInfo(SYSTEM_INFO *lpSystemInfo);
|
|
__declspec(dllimport) VOID __stdcall GetSystemTime(SYSTEMTIME *lpSystemTime);
|
|
__declspec(dllimport) VOID __stdcall GetSystemTimeAsFileTime(FILETIME *lpSystemTimeAsFileTime);
|
|
__declspec(dllimport) VOID __stdcall GetLocalTime(SYSTEMTIME *lpSystemTime);
|
|
}
|
|
|
|
// NOTE: um/timezoneapi.h //////////////////////////////////////////////////////////////////////
|
|
typedef struct _TIME_ZONE_INFORMATION {
|
|
LONG Bias;
|
|
WCHAR StandardName[32];
|
|
SYSTEMTIME StandardDate;
|
|
LONG StandardBias;
|
|
WCHAR DaylightName[32];
|
|
SYSTEMTIME DaylightDate;
|
|
LONG DaylightBias;
|
|
} TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall FileTimeToSystemTime (const FILETIME* lpFileTime, SYSTEMTIME *lpSystemTime);
|
|
__declspec(dllimport) BOOL __stdcall SystemTimeToFileTime (const SYSTEMTIME* lpSystemTime, FILETIME *lpFileTime);
|
|
__declspec(dllimport) BOOL __stdcall TzSpecificLocalTimeToSystemTime(const TIME_ZONE_INFORMATION* lpTimeZoneInformation, const SYSTEMTIME* lpLocalTime, const LPSYSTEMTIME lpUniversalTime);
|
|
}
|
|
|
|
// NOTE: shared/windef.h ///////////////////////////////////////////////////////////////////////
|
|
typedef struct tagRECT {
|
|
LONG left;
|
|
LONG top;
|
|
LONG right;
|
|
LONG bottom;
|
|
} RECT;
|
|
|
|
struct HWND__ {
|
|
int unused;
|
|
};
|
|
typedef struct HWND__ *HWND;
|
|
|
|
struct DPI_AWARENESS_CONTEXT__ {
|
|
int unused;
|
|
};
|
|
typedef struct DPI_AWARENESS_CONTEXT__ *DPI_AWARENESS_CONTEXT;
|
|
|
|
typedef enum DPI_AWARENESS {
|
|
DPI_AWARENESS_INVALID = -1,
|
|
DPI_AWARENESS_UNAWARE = 0,
|
|
DPI_AWARENESS_SYSTEM_AWARE = 1,
|
|
DPI_AWARENESS_PER_MONITOR_AWARE = 2
|
|
} DPI_AWARENESS;
|
|
|
|
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)
|
|
|
|
// NOTE: um/winuser.h //////////////////////////////////////////////////////////////////////////
|
|
typedef struct tagWINDOWPLACEMENT {
|
|
UINT length;
|
|
UINT flags;
|
|
UINT showCmd;
|
|
POINT ptMinPosition;
|
|
POINT ptMaxPosition;
|
|
RECT rcNormalPosition;
|
|
#ifdef _MAC
|
|
RECT rcDevice;
|
|
#endif
|
|
} WINDOWPLACEMENT;
|
|
typedef WINDOWPLACEMENT *PWINDOWPLACEMENT, *LPWINDOWPLACEMENT;
|
|
|
|
#define SW_HIDE 0
|
|
#define SW_NORMAL 1
|
|
#define SW_MAXIMIZE 3
|
|
#define SW_SHOWNOACTIVATE 4
|
|
#define SW_SHOW 5
|
|
#define SW_FORCEMINIMIZE 11
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall GetWindowRect (HWND hWnd, RECT *lpRect);
|
|
__declspec(dllimport) BOOL __stdcall SetWindowPos (HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags);
|
|
__declspec(dllimport) UINT __stdcall GetWindowModuleFileNameA(HWND hwnd, LPSTR pszFileName, UINT cchFileNameMax);
|
|
__declspec(dllimport) BOOL __stdcall ShowWindow (HWND hWnd, int nCmdShow);
|
|
__declspec(dllimport) BOOL __stdcall GetWindowPlacement (HWND hWnd, WINDOWPLACEMENT *lpwndpl);
|
|
|
|
}
|
|
|
|
// NOTE: um/wininet.h //////////////////////////////////////////////////////////////////////////
|
|
typedef WORD INTERNET_PORT;
|
|
typedef VOID *HINTERNET;
|
|
|
|
// NOTE: um/winhttp.h //////////////////////////////////////////////////////////////////////////
|
|
#define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY 0
|
|
#define WINHTTP_ACCESS_TYPE_NO_PROXY 1
|
|
#define WINHTTP_ACCESS_TYPE_NAMED_PROXY 3
|
|
#define WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY 4
|
|
|
|
#define INTERNET_DEFAULT_PORT 0 // use the protocol-specific default
|
|
#define INTERNET_DEFAULT_HTTP_PORT 80 // " " HTTP "
|
|
#define INTERNET_DEFAULT_HTTPS_PORT 443 // " " HTTPS "
|
|
|
|
// NOTE: WinHttpOpen
|
|
#define WINHTTP_FLAG_ASYNC 0x10000000 // this session is asynchronous (where supported)
|
|
#define WINHTTP_FLAG_SECURE_DEFAULTS 0x30000000 // note that this flag also forces async
|
|
|
|
// NOTE: WinHttpOpenRequest
|
|
#define WINHTTP_FLAG_SECURE 0x00800000 // use SSL if applicable (HTTPS)
|
|
#define WINHTTP_FLAG_ESCAPE_PERCENT 0x00000004 // if escaping enabled, escape percent as well
|
|
#define WINHTTP_FLAG_NULL_CODEPAGE 0x00000008 // assume all symbols are ASCII, use fast convertion
|
|
#define WINHTTP_FLAG_ESCAPE_DISABLE 0x00000040 // disable escaping
|
|
#define WINHTTP_FLAG_ESCAPE_DISABLE_QUERY 0x00000080 // if escaping enabled escape path part, but do not escape query
|
|
#define WINHTTP_FLAG_BYPASS_PROXY_CACHE 0x00000100 // add "pragma: no-cache" request header
|
|
#define WINHTTP_FLAG_REFRESH WINHTTP_FLAG_BYPASS_PROXY_CACHE
|
|
#define WINHTTP_FLAG_AUTOMATIC_CHUNKING 0x00000200 // Send request without content-length header or chunked TE
|
|
|
|
#define WINHTTP_NO_PROXY_NAME NULL
|
|
#define WINHTTP_NO_PROXY_BYPASS NULL
|
|
|
|
//
|
|
// WINHTTP_QUERY_FLAG_NUMBER - if this bit is set in the dwInfoLevel parameter of
|
|
// HttpQueryHeader(), then the value of the header will be converted to a number
|
|
// before being returned to the caller, if applicable
|
|
//
|
|
#define WINHTTP_QUERY_FLAG_NUMBER 0x20000000
|
|
|
|
#define WINHTTP_QUERY_MIME_VERSION 0
|
|
#define WINHTTP_QUERY_CONTENT_TYPE 1
|
|
#define WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING 2
|
|
#define WINHTTP_QUERY_CONTENT_ID 3
|
|
#define WINHTTP_QUERY_CONTENT_DESCRIPTION 4
|
|
#define WINHTTP_QUERY_CONTENT_LENGTH 5
|
|
#define WINHTTP_QUERY_CONTENT_LANGUAGE 6
|
|
#define WINHTTP_QUERY_ALLOW 7
|
|
#define WINHTTP_QUERY_PUBLIC 8
|
|
#define WINHTTP_QUERY_DATE 9
|
|
#define WINHTTP_QUERY_EXPIRES 10
|
|
#define WINHTTP_QUERY_LAST_MODIFIED 11
|
|
#define WINHTTP_QUERY_MESSAGE_ID 12
|
|
#define WINHTTP_QUERY_URI 13
|
|
#define WINHTTP_QUERY_DERIVED_FROM 14
|
|
#define WINHTTP_QUERY_COST 15
|
|
#define WINHTTP_QUERY_LINK 16
|
|
#define WINHTTP_QUERY_PRAGMA 17
|
|
#define WINHTTP_QUERY_VERSION 18 // special: part of status line
|
|
#define WINHTTP_QUERY_STATUS_CODE 19 // special: part of status line
|
|
#define WINHTTP_QUERY_STATUS_TEXT 20 // special: part of status line
|
|
#define WINHTTP_QUERY_RAW_HEADERS 21 // special: all headers as ASCIIZ
|
|
#define WINHTTP_QUERY_RAW_HEADERS_CRLF 22 // special: all headers
|
|
#define WINHTTP_QUERY_CONNECTION 23
|
|
#define WINHTTP_QUERY_ACCEPT 24
|
|
#define WINHTTP_QUERY_ACCEPT_CHARSET 25
|
|
#define WINHTTP_QUERY_ACCEPT_ENCODING 26
|
|
#define WINHTTP_QUERY_ACCEPT_LANGUAGE 27
|
|
#define WINHTTP_QUERY_AUTHORIZATION 28
|
|
#define WINHTTP_QUERY_CONTENT_ENCODING 29
|
|
#define WINHTTP_QUERY_FORWARDED 30
|
|
#define WINHTTP_QUERY_FROM 31
|
|
#define WINHTTP_QUERY_IF_MODIFIED_SINCE 32
|
|
#define WINHTTP_QUERY_LOCATION 33
|
|
#define WINHTTP_QUERY_ORIG_URI 34
|
|
#define WINHTTP_QUERY_REFERER 35
|
|
#define WINHTTP_QUERY_RETRY_AFTER 36
|
|
#define WINHTTP_QUERY_SERVER 37
|
|
#define WINHTTP_QUERY_TITLE 38
|
|
#define WINHTTP_QUERY_USER_AGENT 39
|
|
#define WINHTTP_QUERY_WWW_AUTHENTICATE 40
|
|
#define WINHTTP_QUERY_PROXY_AUTHENTICATE 41
|
|
#define WINHTTP_QUERY_ACCEPT_RANGES 42
|
|
#define WINHTTP_QUERY_SET_COOKIE 43
|
|
#define WINHTTP_QUERY_COOKIE 44
|
|
#define WINHTTP_QUERY_REQUEST_METHOD 45 // special: GET/POST etc.
|
|
#define WINHTTP_QUERY_REFRESH 46
|
|
#define WINHTTP_QUERY_CONTENT_DISPOSITION 47
|
|
|
|
// NOTE: WinHttpQueryHeaders prettifiers for optional parameters.
|
|
#define WINHTTP_HEADER_NAME_BY_INDEX NULL
|
|
#define WINHTTP_NO_OUTPUT_BUFFER NULL
|
|
#define WINHTTP_NO_HEADER_INDEX NULL
|
|
|
|
// NOTE: Http Response Status Codes
|
|
#define HTTP_STATUS_CONTINUE 100 // OK to continue with request
|
|
#define HTTP_STATUS_SWITCH_PROTOCOLS 101 // server has switched protocols in upgrade header
|
|
|
|
#define HTTP_STATUS_OK 200 // request completed
|
|
#define HTTP_STATUS_CREATED 201 // object created, reason = new URI
|
|
#define HTTP_STATUS_ACCEPTED 202 // async completion (TBS)
|
|
#define HTTP_STATUS_PARTIAL 203 // partial completion
|
|
#define HTTP_STATUS_NO_CONTENT 204 // no info to return
|
|
#define HTTP_STATUS_RESET_CONTENT 205 // request completed, but clear form
|
|
#define HTTP_STATUS_PARTIAL_CONTENT 206 // partial GET fulfilled
|
|
#define HTTP_STATUS_WEBDAV_MULTI_STATUS 207 // WebDAV Multi-Status
|
|
|
|
#define HTTP_STATUS_AMBIGUOUS 300 // server couldn't decide what to return
|
|
#define HTTP_STATUS_MOVED 301 // object permanently moved
|
|
#define HTTP_STATUS_REDIRECT 302 // object temporarily moved
|
|
#define HTTP_STATUS_REDIRECT_METHOD 303 // redirection w/ new access method
|
|
#define HTTP_STATUS_NOT_MODIFIED 304 // if-modified-since was not modified
|
|
#define HTTP_STATUS_USE_PROXY 305 // redirection to proxy, location header specifies proxy to use
|
|
#define HTTP_STATUS_REDIRECT_KEEP_VERB 307 // HTTP/1.1: keep same verb
|
|
#define HTTP_STATUS_PERMANENT_REDIRECT 308 // Object permanently moved keep verb
|
|
|
|
#define HTTP_STATUS_BAD_REQUEST 400 // invalid syntax
|
|
#define HTTP_STATUS_DENIED 401 // access denied
|
|
#define HTTP_STATUS_PAYMENT_REQ 402 // payment required
|
|
#define HTTP_STATUS_FORBIDDEN 403 // request forbidden
|
|
#define HTTP_STATUS_NOT_FOUND 404 // object not found
|
|
#define HTTP_STATUS_BAD_METHOD 405 // method is not allowed
|
|
#define HTTP_STATUS_NONE_ACCEPTABLE 406 // no response acceptable to client found
|
|
#define HTTP_STATUS_PROXY_AUTH_REQ 407 // proxy authentication required
|
|
#define HTTP_STATUS_REQUEST_TIMEOUT 408 // server timed out waiting for request
|
|
#define HTTP_STATUS_CONFLICT 409 // user should resubmit with more info
|
|
#define HTTP_STATUS_GONE 410 // the resource is no longer available
|
|
#define HTTP_STATUS_LENGTH_REQUIRED 411 // the server refused to accept request w/o a length
|
|
#define HTTP_STATUS_PRECOND_FAILED 412 // precondition given in request failed
|
|
#define HTTP_STATUS_REQUEST_TOO_LARGE 413 // request entity was too large
|
|
#define HTTP_STATUS_URI_TOO_LONG 414 // request URI too long
|
|
#define HTTP_STATUS_UNSUPPORTED_MEDIA 415 // unsupported media type
|
|
#define HTTP_STATUS_RETRY_WITH 449 // retry after doing the appropriate action.
|
|
|
|
#define HTTP_STATUS_SERVER_ERROR 500 // internal server error
|
|
#define HTTP_STATUS_NOT_SUPPORTED 501 // required not supported
|
|
#define HTTP_STATUS_BAD_GATEWAY 502 // error response received from gateway
|
|
#define HTTP_STATUS_SERVICE_UNAVAIL 503 // temporarily overloaded
|
|
#define HTTP_STATUS_GATEWAY_TIMEOUT 504 // timed out waiting for gateway
|
|
#define HTTP_STATUS_VERSION_NOT_SUP 505 // HTTP version not supported
|
|
|
|
#define HTTP_STATUS_FIRST HTTP_STATUS_CONTINUE
|
|
#define HTTP_STATUS_LAST HTTP_STATUS_VERSION_NOT_SUP
|
|
|
|
#define WINHTTP_CALLBACK_STATUS_RESOLVING_NAME 0x00000001
|
|
#define WINHTTP_CALLBACK_STATUS_NAME_RESOLVED 0x00000002
|
|
#define WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER 0x00000004
|
|
#define WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER 0x00000008
|
|
#define WINHTTP_CALLBACK_STATUS_SENDING_REQUEST 0x00000010
|
|
#define WINHTTP_CALLBACK_STATUS_REQUEST_SENT 0x00000020
|
|
#define WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE 0x00000040
|
|
#define WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED 0x00000080
|
|
#define WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION 0x00000100
|
|
#define WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED 0x00000200
|
|
#define WINHTTP_CALLBACK_STATUS_HANDLE_CREATED 0x00000400
|
|
#define WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING 0x00000800
|
|
#define WINHTTP_CALLBACK_STATUS_DETECTING_PROXY 0x00001000
|
|
#define WINHTTP_CALLBACK_STATUS_REDIRECT 0x00004000
|
|
#define WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE 0x00008000
|
|
#define WINHTTP_CALLBACK_STATUS_SECURE_FAILURE 0x00010000
|
|
#define WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE 0x00020000
|
|
#define WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE 0x00040000
|
|
#define WINHTTP_CALLBACK_STATUS_READ_COMPLETE 0x00080000
|
|
#define WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE 0x00100000
|
|
#define WINHTTP_CALLBACK_STATUS_REQUEST_ERROR 0x00200000
|
|
#define WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE 0x00400000
|
|
|
|
#define WINHTTP_CALLBACK_STATUS_GETPROXYFORURL_COMPLETE 0x01000000
|
|
#define WINHTTP_CALLBACK_STATUS_CLOSE_COMPLETE 0x02000000
|
|
#define WINHTTP_CALLBACK_STATUS_SHUTDOWN_COMPLETE 0x04000000
|
|
#define WINHTTP_CALLBACK_STATUS_SETTINGS_WRITE_COMPLETE 0x10000000
|
|
#define WINHTTP_CALLBACK_STATUS_SETTINGS_READ_COMPLETE 0x20000000
|
|
|
|
#define WINHTTP_CALLBACK_FLAG_RESOLVE_NAME (WINHTTP_CALLBACK_STATUS_RESOLVING_NAME | WINHTTP_CALLBACK_STATUS_NAME_RESOLVED)
|
|
#define WINHTTP_CALLBACK_FLAG_CONNECT_TO_SERVER (WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER | WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER)
|
|
#define WINHTTP_CALLBACK_FLAG_SEND_REQUEST (WINHTTP_CALLBACK_STATUS_SENDING_REQUEST | WINHTTP_CALLBACK_STATUS_REQUEST_SENT)
|
|
#define WINHTTP_CALLBACK_FLAG_RECEIVE_RESPONSE (WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE | WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED)
|
|
#define WINHTTP_CALLBACK_FLAG_CLOSE_CONNECTION (WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION | WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED)
|
|
#define WINHTTP_CALLBACK_FLAG_HANDLES (WINHTTP_CALLBACK_STATUS_HANDLE_CREATED | WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING)
|
|
#define WINHTTP_CALLBACK_FLAG_DETECTING_PROXY WINHTTP_CALLBACK_STATUS_DETECTING_PROXY
|
|
#define WINHTTP_CALLBACK_FLAG_REDIRECT WINHTTP_CALLBACK_STATUS_REDIRECT
|
|
#define WINHTTP_CALLBACK_FLAG_INTERMEDIATE_RESPONSE WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE
|
|
#define WINHTTP_CALLBACK_FLAG_SECURE_FAILURE WINHTTP_CALLBACK_STATUS_SECURE_FAILURE
|
|
#define WINHTTP_CALLBACK_FLAG_SENDREQUEST_COMPLETE WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE
|
|
#define WINHTTP_CALLBACK_FLAG_HEADERS_AVAILABLE WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE
|
|
#define WINHTTP_CALLBACK_FLAG_DATA_AVAILABLE WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE
|
|
#define WINHTTP_CALLBACK_FLAG_READ_COMPLETE WINHTTP_CALLBACK_STATUS_READ_COMPLETE
|
|
#define WINHTTP_CALLBACK_FLAG_WRITE_COMPLETE WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE
|
|
#define WINHTTP_CALLBACK_FLAG_REQUEST_ERROR WINHTTP_CALLBACK_STATUS_REQUEST_ERROR
|
|
|
|
#define WINHTTP_CALLBACK_FLAG_GETPROXYFORURL_COMPLETE WINHTTP_CALLBACK_STATUS_GETPROXYFORURL_COMPLETE
|
|
|
|
#define WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS (WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE \
|
|
| WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE \
|
|
| WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE \
|
|
| WINHTTP_CALLBACK_STATUS_READ_COMPLETE \
|
|
| WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE \
|
|
| WINHTTP_CALLBACK_STATUS_REQUEST_ERROR \
|
|
| WINHTTP_CALLBACK_STATUS_GETPROXYFORURL_COMPLETE)
|
|
|
|
#define WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS 0xffffffff
|
|
#define WINHTTP_INVALID_STATUS_CALLBACK ((WINHTTP_STATUS_CALLBACK)(-1L))
|
|
|
|
typedef struct _WINHTTP_EXTENDED_HEADER
|
|
{
|
|
union
|
|
{
|
|
CHAR const *pwszName;
|
|
WCHAR const *pszName;
|
|
};
|
|
union
|
|
{
|
|
WCHAR const *pwszValue;
|
|
CHAR const *pszValue;
|
|
};
|
|
} WINHTTP_EXTENDED_HEADER, *PWINHTTP_EXTENDED_HEADER;
|
|
|
|
typedef struct _WINHTTP_ASYNC_RESULT
|
|
{
|
|
DWORD *dwResult; // indicates which async API has encountered an error
|
|
DWORD dwError; // the error code if the API failed
|
|
} WINHTTP_ASYNC_RESULT, *LPWINHTTP_ASYNC_RESULT, *PWINHTTP_ASYNC_RESULT;
|
|
|
|
typedef
|
|
VOID
|
|
(*WINHTTP_STATUS_CALLBACK)(
|
|
HINTERNET hInternet,
|
|
DWORD *dwContext,
|
|
DWORD dwInternetStatus,
|
|
VOID *lpvStatusInformation,
|
|
DWORD dwStatusInformationLength
|
|
);
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) HINTERNET __stdcall WinHttpOpen(WCHAR const *pszAgentW, DWORD dwAccessType, WCHAR const *pszProxyW, WCHAR const *pszProxyBypassW, DWORD dwFlags);
|
|
__declspec(dllimport) BOOL __stdcall WinHttpCloseHandle(HINTERNET hInternet);
|
|
__declspec(dllimport) HINTERNET __stdcall WinHttpConnect(HINTERNET hSession, WCHAR const *pswzServerName, INTERNET_PORT nServerPort, DWORD dwReserved);
|
|
__declspec(dllimport) BOOL __stdcall WinHttpReadData(HINTERNET hRequest, VOID *lpBuffer, DWORD dwNumberOfBytesToRead, DWORD *lpdwNumberOfBytesRead);
|
|
__declspec(dllimport) HINTERNET __stdcall WinHttpOpenRequest(HINTERNET hConnect, WCHAR const *pwszVerb, WCHAR const *pwszObjectName, WCHAR const *pwszVersion, WCHAR const *pwszReferrer, WCHAR const *ppwszAcceptTypes, DWORD dwFlags);
|
|
__declspec(dllimport) BOOL __stdcall WinHttpSendRequest(HINTERNET hRequest, WCHAR const *lpszHeaders, DWORD dwHeadersLength, VOID *lpOptional, DWORD dwOptionalLength, DWORD dwTotalLength, DWORD_PTR dwContext);
|
|
__declspec(dllimport) DWORD __stdcall WinHttpAddRequestHeadersEx(HINTERNET hRequest, DWORD dwModifiers, ULONGLONG ullFlags, ULONGLONG ullExtra, DWORD cHeaders, WINHTTP_EXTENDED_HEADER *pHeaders);
|
|
__declspec(dllimport) BOOL __stdcall WinHttpSetCredentials(HINTERNET hRequest, // HINTERNET handle returned by WinHttpOpenRequest.
|
|
DWORD AuthTargets, // Only WINHTTP_AUTH_TARGET_SERVER and WINHTTP_AUTH_TARGET_PROXY are supported in this version and they are mutually exclusive
|
|
DWORD AuthScheme, // must be one of the supported Auth Schemes returned from WinHttpQueryAuthSchemes()
|
|
WCHAR * pwszUserName, // 1) NULL if default creds is to be used, in which case pszPassword will be ignored
|
|
WCHAR * pwszPassword, // 1) "" == Blank Password; 2)Parameter ignored if pszUserName is NULL; 3) Invalid to pass in NULL if pszUserName is not NULL
|
|
VOID * pAuthParams);
|
|
__declspec(dllimport) BOOL __stdcall WinHttpQueryHeaders(HINTERNET hRequest, DWORD dwInfoLevel, WCHAR const *pwszName, VOID *lpBuffer, DWORD *lpdwBufferLength, DWORD *lpdwIndex);
|
|
__declspec(dllimport) BOOL __stdcall WinHttpReceiveResponse(HINTERNET hRequest, VOID *lpReserved);
|
|
__declspec(dllimport) WINHTTP_STATUS_CALLBACK __stdcall WinHttpSetStatusCallback(HINTERNET hInternet, WINHTTP_STATUS_CALLBACK lpfnInternetCallback, DWORD dwNotificationFlags, DWORD_PTR dwReserved);
|
|
}
|
|
|
|
// NOTE: um/DbgHelp.h //////////////////////////////////////////////////////////////////////////
|
|
#define SYMOPT_CASE_INSENSITIVE 0x00000001
|
|
#define SYMOPT_UNDNAME 0x00000002
|
|
#define SYMOPT_DEFERRED_LOADS 0x00000004
|
|
#define SYMOPT_NO_CPP 0x00000008
|
|
#define SYMOPT_LOAD_LINES 0x00000010
|
|
#define SYMOPT_OMAP_FIND_NEAREST 0x00000020
|
|
#define SYMOPT_LOAD_ANYTHING 0x00000040
|
|
#define SYMOPT_IGNORE_CVREC 0x00000080
|
|
#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100
|
|
#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200
|
|
#define SYMOPT_EXACT_SYMBOLS 0x00000400
|
|
#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800
|
|
#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000
|
|
#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000
|
|
#define SYMOPT_PUBLICS_ONLY 0x00004000
|
|
#define SYMOPT_NO_PUBLICS 0x00008000
|
|
#define SYMOPT_AUTO_PUBLICS 0x00010000
|
|
#define SYMOPT_NO_IMAGE_SEARCH 0x00020000
|
|
#define SYMOPT_SECURE 0x00040000
|
|
#define SYMOPT_NO_PROMPTS 0x00080000
|
|
#define SYMOPT_OVERWRITE 0x00100000
|
|
#define SYMOPT_IGNORE_IMAGEDIR 0x00200000
|
|
#define SYMOPT_FLAT_DIRECTORY 0x00400000
|
|
#define SYMOPT_FAVOR_COMPRESSED 0x00800000
|
|
#define SYMOPT_ALLOW_ZERO_ADDRESS 0x01000000
|
|
#define SYMOPT_DISABLE_SYMSRV_AUTODETECT 0x02000000
|
|
#define SYMOPT_READONLY_CACHE 0x04000000
|
|
#define SYMOPT_SYMPATH_LAST 0x08000000
|
|
#define SYMOPT_DISABLE_FAST_SYMBOLS 0x10000000
|
|
#define SYMOPT_DISABLE_SYMSRV_TIMEOUT 0x20000000
|
|
#define SYMOPT_DISABLE_SRVSTAR_ON_STARTUP 0x40000000
|
|
#define SYMOPT_DEBUG 0x80000000
|
|
|
|
#define MAX_SYM_NAME 2000
|
|
|
|
typedef enum {
|
|
AddrMode1616,
|
|
AddrMode1632,
|
|
AddrModeReal,
|
|
AddrModeFlat
|
|
} ADDRESS_MODE;
|
|
|
|
typedef struct _tagADDRESS64 {
|
|
DWORD64 Offset;
|
|
WORD Segment;
|
|
ADDRESS_MODE Mode;
|
|
} ADDRESS64, *LPADDRESS64;
|
|
|
|
|
|
typedef struct _KDHELP64 {
|
|
DWORD64 Thread;
|
|
DWORD ThCallbackStack;
|
|
DWORD ThCallbackBStore;
|
|
DWORD NextCallback;
|
|
DWORD FramePointer;
|
|
DWORD64 KiCallUserMode;
|
|
DWORD64 KeUserCallbackDispatcher;
|
|
DWORD64 SystemRangeStart;
|
|
DWORD64 KiUserExceptionDispatcher;
|
|
DWORD64 StackBase;
|
|
DWORD64 StackLimit;
|
|
DWORD BuildVersion;
|
|
DWORD RetpolineStubFunctionTableSize;
|
|
DWORD64 RetpolineStubFunctionTable;
|
|
DWORD RetpolineStubOffset;
|
|
DWORD RetpolineStubSize;
|
|
DWORD64 Reserved0[2];
|
|
} KDHELP64, *PKDHELP64;
|
|
|
|
typedef struct _tagSTACKFRAME64 {
|
|
ADDRESS64 AddrPC; // program counter
|
|
ADDRESS64 AddrReturn; // return address
|
|
ADDRESS64 AddrFrame; // frame pointer
|
|
ADDRESS64 AddrStack; // stack pointer
|
|
ADDRESS64 AddrBStore; // backing store pointer
|
|
VOID *FuncTableEntry; // pointer to pdata/fpo or NULL
|
|
DWORD64 Params[4]; // possible arguments to the function
|
|
BOOL Far; // WOW far call
|
|
BOOL Virtual; // is this a virtual frame?
|
|
DWORD64 Reserved[3];
|
|
KDHELP64 KdHelp;
|
|
} STACKFRAME64;
|
|
|
|
typedef struct _IMAGEHLP_LINEW64 {
|
|
DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64)
|
|
VOID *Key; // internal
|
|
DWORD LineNumber; // line number in file
|
|
WCHAR *FileName; // full filename
|
|
DWORD64 Address; // first instruction of line
|
|
} IMAGEHLP_LINEW64;
|
|
|
|
typedef struct _SYMBOL_INFOW {
|
|
ULONG SizeOfStruct;
|
|
ULONG TypeIndex; // Type Index of symbol
|
|
ULONG64 Reserved[2];
|
|
ULONG Index;
|
|
ULONG Size;
|
|
ULONG64 ModBase; // Base Address of module comtaining this symbol
|
|
ULONG Flags;
|
|
ULONG64 Value; // Value of symbol, ValuePresent should be 1
|
|
ULONG64 Address; // Address of symbol including base address of module
|
|
ULONG Register; // register holding value or pointer to value
|
|
ULONG Scope; // scope of the symbol
|
|
ULONG Tag; // pdb classification
|
|
ULONG NameLen; // Actual length of name
|
|
ULONG MaxNameLen;
|
|
WCHAR Name[1]; // Name of symbol
|
|
} SYMBOL_INFOW;
|
|
|
|
typedef BOOL (__stdcall READ_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess, DWORD64 qwBaseAddress, VOID *lpBuffer, DWORD nSize, DWORD *lpNumberOfBytesRead);
|
|
typedef VOID * (__stdcall FUNCTION_TABLE_ACCESS_ROUTINE64)(HANDLE ahProcess, DWORD64 AddrBase);
|
|
typedef DWORD64(__stdcall GET_MODULE_BASE_ROUTINE64)(HANDLE hProcess, DWORD64 Address);
|
|
typedef DWORD64(__stdcall TRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess, HANDLE hThread, ADDRESS64 *lpaddr);
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall StackWalk64 (DWORD MachineType, HANDLE hProcess, HANDLE hThread, STACKFRAME64 *StackFrame, VOID *ContextRecord, READ_PROCESS_MEMORY_ROUTINE64 *ReadMemoryRoutine, FUNCTION_TABLE_ACCESS_ROUTINE64 *FunctionTableAccessRoutine, GET_MODULE_BASE_ROUTINE64 *GetModuleBaseRoutine, TRANSLATE_ADDRESS_ROUTINE64 *TranslateAddress);
|
|
__declspec(dllimport) BOOL __stdcall SymFromAddrW (HANDLE hProcess, DWORD64 Address, DWORD64 *Displacement, SYMBOL_INFOW *Symbol);
|
|
__declspec(dllimport) VOID * __stdcall SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase);
|
|
__declspec(dllimport) BOOL __stdcall SymGetLineFromAddrW64 (HANDLE hProcess, DWORD64 dwAddr, DWORD *pdwDisplacement, IMAGEHLP_LINEW64 *Line);
|
|
__declspec(dllimport) DWORD64 __stdcall SymGetModuleBase64 (HANDLE hProcess, DWORD64 qwAddr);
|
|
__declspec(dllimport) BOOL __stdcall SymRefreshModuleList (HANDLE hProcess);
|
|
};
|
|
|
|
// NOTE: um/errhandlingapi.h ///////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) DWORD __stdcall GetLastError(VOID);
|
|
}
|
|
|
|
// NOTE: um/libloaderapi.h /////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) HMODULE __stdcall LoadLibraryA (const CHAR *lpLibFileName);
|
|
__declspec(dllimport) BOOL __stdcall FreeLibrary (HMODULE hLibModule);
|
|
__declspec(dllimport) void * __stdcall GetProcAddress (HMODULE hModule, const CHAR *lpProcName);
|
|
__declspec(dllimport) HMODULE __stdcall GetModuleHandleA (const CHAR *lpModuleName);
|
|
__declspec(dllimport) DWORD __stdcall GetModuleFileNameW(HMODULE hModule, WCHAR *lpFilename, DWORD nSize);
|
|
}
|
|
|
|
// NOTE: um/synchapi.h /////////////////////////////////////////////////////////////////////////
|
|
typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
|
|
|
|
typedef RTL_BARRIER SYNCHRONIZATION_BARRIER;
|
|
typedef PRTL_BARRIER PSYNCHRONIZATION_BARRIER;
|
|
typedef PRTL_BARRIER LPSYNCHRONIZATION_BARRIER;
|
|
|
|
#define SYNCHRONIZATION_BARRIER_FLAGS_SPIN_ONLY 0x01
|
|
#define SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY 0x02
|
|
#define SYNCHRONIZATION_BARRIER_FLAGS_NO_DELETE 0x04
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) VOID __stdcall InitializeConditionVariable (CONDITION_VARIABLE *ConditionVariable);
|
|
__declspec(dllimport) VOID __stdcall WakeConditionVariable (CONDITION_VARIABLE *ConditionVariable);
|
|
__declspec(dllimport) VOID __stdcall WakeAllConditionVariable (CONDITION_VARIABLE *ConditionVariable);
|
|
__declspec(dllimport) BOOL __stdcall SleepConditionVariableCS (CONDITION_VARIABLE *ConditionVariable, CRITICAL_SECTION *CriticalSection, DWORD dwMilliseconds);
|
|
|
|
__declspec(dllimport) VOID __stdcall InitializeCriticalSection (CRITICAL_SECTION *lpCriticalSection);
|
|
__declspec(dllimport) VOID __stdcall EnterCriticalSection (CRITICAL_SECTION *lpCriticalSection);
|
|
__declspec(dllimport) VOID __stdcall LeaveCriticalSection (CRITICAL_SECTION *lpCriticalSection);
|
|
__declspec(dllimport) BOOL __stdcall InitializeCriticalSectionAndSpinCount(CRITICAL_SECTION *lpCriticalSection, DWORD dwSpinCount);
|
|
__declspec(dllimport) BOOL __stdcall InitializeCriticalSectionEx (CRITICAL_SECTION *lpCriticalSection, DWORD dwSpinCount, DWORD Flags);
|
|
__declspec(dllimport) DWORD __stdcall SetCriticalSectionSpinCount (CRITICAL_SECTION *lpCriticalSection, DWORD dwSpinCount);
|
|
__declspec(dllimport) BOOL __stdcall TryEnterCriticalSection (CRITICAL_SECTION *lpCriticalSection);
|
|
__declspec(dllimport) VOID __stdcall DeleteCriticalSection (CRITICAL_SECTION *lpCriticalSection);
|
|
|
|
__declspec(dllimport) DWORD __stdcall WaitForSingleObject (HANDLE hHandle, DWORD dwMilliseconds);
|
|
__declspec(dllimport) BOOL __stdcall ReleaseSemaphore (HANDLE hSemaphore, LONG lReleaseCount, LONG *lpPreviousCount);
|
|
__declspec(dllimport) VOID __stdcall Sleep (DWORD dwMilliseconds);
|
|
|
|
__declspec(dllimport) BOOL __stdcall EnterSynchronizationBarrier (SYNCHRONIZATION_BARRIER *lpBarrier, DWORD dwFlags);
|
|
__declspec(dllimport) BOOL __stdcall InitializeSynchronizationBarrier (SYNCHRONIZATION_BARRIER *lpBarrier, LONG lTotalThreads, LONG lSpinCount);
|
|
__declspec(dllimport) BOOL __stdcall DeleteSynchronizationBarrier (SYNCHRONIZATION_BARRIER *lpBarrier);
|
|
}
|
|
|
|
// NOTE: um/profileapi.h ///////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall QueryPerformanceCounter (LARGE_INTEGER* lpPerformanceCount);
|
|
__declspec(dllimport) BOOL __stdcall QueryPerformanceFrequency(LARGE_INTEGER* lpFrequency);
|
|
}
|
|
|
|
// NOTE: um/processthreadsapi.h ////////////////////////////////////////////////////////////////
|
|
typedef struct _PROCESS_INFORMATION {
|
|
HANDLE hProcess;
|
|
HANDLE hThread;
|
|
DWORD dwProcessId;
|
|
DWORD dwThreadId;
|
|
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;
|
|
|
|
typedef struct _STARTUPINFOW {
|
|
DWORD cb;
|
|
WCHAR *lpReserved;
|
|
WCHAR *lpDesktop;
|
|
WCHAR *lpTitle;
|
|
DWORD dwX;
|
|
DWORD dwY;
|
|
DWORD dwXSize;
|
|
DWORD dwYSize;
|
|
DWORD dwXCountChars;
|
|
DWORD dwYCountChars;
|
|
DWORD dwFillAttribute;
|
|
DWORD dwFlags;
|
|
WORD wShowWindow;
|
|
WORD cbReserved2;
|
|
BYTE *lpReserved2;
|
|
HANDLE hStdInput;
|
|
HANDLE hStdOutput;
|
|
HANDLE hStdError;
|
|
} STARTUPINFOW, *LPSTARTUPINFOW;
|
|
|
|
typedef DWORD (__stdcall *PTHREAD_START_ROUTINE)(
|
|
VOID *lpThreadParameter
|
|
);
|
|
typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall CreateProcessW (WCHAR const *lpApplicationName, WCHAR *lpCommandLine, SECURITY_ATTRIBUTES *lpProcessAttributes, SECURITY_ATTRIBUTES *lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, VOID *lpEnvironment, WCHAR const *lpCurrentDirectory, STARTUPINFOW *lpStartupInfo, PROCESS_INFORMATION *lpProcessInformation);
|
|
__declspec(dllimport) HANDLE __stdcall CreateThread (SECURITY_ATTRIBUTES *lpThreadAttributes, SIZE_T dwStackSize, PTHREAD_START_ROUTINE lpStartAddress, VOID *lpParameter, DWORD dwCreationFlags, DWORD *lpThreadId);
|
|
__declspec(dllimport) DWORD __stdcall GetCurrentThreadId(VOID);
|
|
__declspec(dllimport) BOOL __stdcall GetExitCodeProcess(HANDLE hProcess, DWORD *lpExitCode);
|
|
__declspec(dllimport) void __stdcall ExitProcess (UINT uExitCode);
|
|
}
|
|
|
|
// NOTE: um/memoryapi.h ////////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) VOID * __stdcall VirtualAlloc (VOID *lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
|
|
__declspec(dllimport) BOOL __stdcall VirtualProtect(VOID *lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD *lpflOldProtect);
|
|
__declspec(dllimport) BOOL __stdcall VirtualFree (VOID *lpAddress, SIZE_T dwSize, DWORD dwFreeType);
|
|
}
|
|
|
|
// NOTE: shared/bcrypt.h ///////////////////////////////////////////////////////////////////////
|
|
typedef VOID *BCRYPT_ALG_HANDLE;
|
|
typedef LONG NTSTATUS;
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) NTSTATUS __stdcall BCryptOpenAlgorithmProvider(BCRYPT_ALG_HANDLE *phAlgorithm, const WCHAR *pszAlgId, const WCHAR *pszImplementation, ULONG dwFlags);
|
|
__declspec(dllimport) NTSTATUS __stdcall BCryptGenRandom (BCRYPT_ALG_HANDLE hAlgorithm, UCHAR *pbBuffer, ULONG cbBuffer, ULONG dwFlags);
|
|
}
|
|
|
|
// NOTE: um/shellapi.h /////////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) HINSTANCE __stdcall ShellExecuteA(HWND hwnd, CHAR const *lpOperation, CHAR const *lpFile, CHAR const *lpParameters, CHAR const *lpDirectory, INT nShowCmd);
|
|
__declspec(dllimport) HINSTANCE __stdcall ShellExecuteW(HWND hwnd, WCHAR const *lpOperation, WCHAR const *lpFile, WCHAR const *lpParameters, WCHAR const *lpDirectory, INT nShowCmd);
|
|
}
|
|
|
|
// NOTE: um/debugapi.h /////////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall IsDebuggerPresent();
|
|
}
|
|
|
|
// NOTE: um/namedpipeapi.h /////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall CreatePipe (HANDLE *hReadPipe, HANDLE *hWritePipe, LPSECURITY_ATTRIBUTES lpPipeAttributes, DWORD nSize);
|
|
__declspec(dllimport) BOOL __stdcall PeekNamedPipe(HANDLE hNamedPipe, VOID *lpBuffer, DWORD nBufferSize, DWORD *lpBytesRead, DWORD *lpTotalBytesAvail, DWORD *lpBytesLeftThisMessage);
|
|
}
|
|
|
|
// NOTE: um/handleapi.h ////////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall SetHandleInformation(HANDLE hObject, DWORD dwMask, DWORD dwFlags);
|
|
}
|
|
|
|
// NOTE: um/commdlg.h //////////////////////////////////////////////////////////////////////////
|
|
typedef UINT_PTR (__stdcall *LPOFNHOOKPROC)(HWND, UINT, WPARAM, LPARAM);
|
|
typedef struct tagOFNW {
|
|
DWORD lStructSize;
|
|
HWND hwndOwner;
|
|
HINSTANCE hInstance;
|
|
WCHAR const * lpstrFilter;
|
|
LPWSTR lpstrCustomFilter;
|
|
DWORD nMaxCustFilter;
|
|
DWORD nFilterIndex;
|
|
LPWSTR lpstrFile;
|
|
DWORD nMaxFile;
|
|
LPWSTR lpstrFileTitle;
|
|
DWORD nMaxFileTitle;
|
|
WCHAR const * lpstrInitialDir;
|
|
WCHAR const * lpstrTitle;
|
|
DWORD Flags;
|
|
WORD nFileOffset;
|
|
WORD nFileExtension;
|
|
WCHAR const * lpstrDefExt;
|
|
LPARAM lCustData;
|
|
LPOFNHOOKPROC lpfnHook;
|
|
WCHAR const * lpTemplateName;
|
|
#ifdef _MAC
|
|
LPEDITMENU lpEditInfo;
|
|
LPCSTR lpstrPrompt;
|
|
#endif
|
|
#if (_WIN32_WINNT >= 0x0500)
|
|
void * pvReserved;
|
|
DWORD dwReserved;
|
|
DWORD FlagsEx;
|
|
#endif // (_WIN32_WINNT >= 0x0500)
|
|
} OPENFILENAMEW, *LPOPENFILENAMEW;
|
|
|
|
|
|
#define OFN_READONLY 0x00000001
|
|
#define OFN_OVERWRITEPROMPT 0x00000002
|
|
#define OFN_HIDEREADONLY 0x00000004
|
|
#define OFN_NOCHANGEDIR 0x00000008
|
|
#define OFN_SHOWHELP 0x00000010
|
|
#define OFN_ENABLEHOOK 0x00000020
|
|
#define OFN_ENABLETEMPLATE 0x00000040
|
|
#define OFN_ENABLETEMPLATEHANDLE 0x00000080
|
|
#define OFN_NOVALIDATE 0x00000100
|
|
#define OFN_ALLOWMULTISELECT 0x00000200
|
|
#define OFN_EXTENSIONDIFFERENT 0x00000400
|
|
#define OFN_PATHMUSTEXIST 0x00000800
|
|
#define OFN_FILEMUSTEXIST 0x00001000
|
|
#define OFN_CREATEPROMPT 0x00002000
|
|
#define OFN_SHAREAWARE 0x00004000
|
|
#define OFN_NOREADONLYRETURN 0x00008000
|
|
#define OFN_NOTESTFILECREATE 0x00010000
|
|
#define OFN_NONETWORKBUTTON 0x00020000
|
|
#define OFN_NOLONGNAMES 0x00040000 // force no long names for 4.x modules
|
|
#if(WINVER >= 0x0400)
|
|
#define OFN_EXPLORER 0x00080000 // new look commdlg
|
|
#define OFN_NODEREFERENCELINKS 0x00100000
|
|
#define OFN_LONGNAMES 0x00200000 // force long names for 3.x modules
|
|
// OFN_ENABLEINCLUDENOTIFY and OFN_ENABLESIZING require
|
|
// Windows 2000 or higher to have any effect.
|
|
#define OFN_ENABLEINCLUDENOTIFY 0x00400000 // send include message to callback
|
|
#define OFN_ENABLESIZING 0x00800000
|
|
#endif /* WINVER >= 0x0400 */
|
|
#if (_WIN32_WINNT >= 0x0500)
|
|
#define OFN_DONTADDTORECENT 0x02000000
|
|
#define OFN_FORCESHOWHIDDEN 0x10000000 // Show All files including System and hidden files
|
|
#endif // (_WIN32_WINNT >= 0x0500)
|
|
|
|
//FlagsEx Values
|
|
#if (_WIN32_WINNT >= 0x0500)
|
|
#define OFN_EX_NOPLACESBAR 0x00000001
|
|
#endif // (_WIN32_WINNT >= 0x0500)
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall GetSaveFileNameW(LPOPENFILENAMEW);
|
|
__declspec(dllimport) BOOL __stdcall GetOpenFileNameW(LPOPENFILENAMEW);
|
|
}
|
|
|
|
// NOTE: um/shlwapi.h //////////////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) BOOL __stdcall PathRelativePathToW(WCHAR *pszPath, WCHAR const *pszFrom, DWORD dwAttrFrom, WCHAR const *pszTo, DWORD dwAttrTo);
|
|
__declspec(dllimport) BOOL __stdcall PathIsRelativeW(WCHAR *pszPath);
|
|
}
|
|
|
|
// NOTE: um/pathcch.h //////////////////////////////////////////////////////////////////////////
|
|
typedef enum PATHCCH_OPTIONS
|
|
{
|
|
PATHCCH_NONE = 0x0,
|
|
|
|
// This option allows applications to gain access to long paths. It has two
|
|
// different behaviors. For process configured to enable long paths it will allow
|
|
// the returned path to be longer than the max path limit that is normally imposed.
|
|
// For process that are not this option will convert long paths into the extended
|
|
// length DOS device form (with \\?\ prefix) when the path is longer than the limit.
|
|
// This form is not length limited by the Win32 file system API on all versions of Windows.
|
|
// This second behavior is the same behavior for OSes that don't have the long path feature.
|
|
// This can not be specified with PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH.
|
|
PATHCCH_ALLOW_LONG_PATHS = 0x01,
|
|
|
|
// Can only be used when PATHCCH_ALLOW_LONG_PATHS is specified. This
|
|
// Forces the API to treat the caller as long path enabled, independent of the
|
|
// process's long name enabled state. Cannot be used with PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS.
|
|
PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS = 0x02,
|
|
|
|
// Can only be used when PATHCCH_ALLOW_LONG_PATHS is specified. This
|
|
// Forces the API to treat the caller as long path disabled, independent of the
|
|
// process's long name enabled state. Cannot be used with PATHCCH_FORCE_ENABLE_LONG_NAME_PROCESS.
|
|
PATHCCH_FORCE_DISABLE_LONG_NAME_PROCESS = 0x04,
|
|
|
|
// Disable the normalization of path segments that includes removing trailing dots and spaces.
|
|
// This enables access to paths that win32 path normalization will block.
|
|
PATHCCH_DO_NOT_NORMALIZE_SEGMENTS = 0x08,
|
|
|
|
// Convert the input path into the extended length DOS device path form (with the \\?\ prefix)
|
|
// if not already in that form. This enables access to paths that are otherwise not addressable
|
|
// due to Win32 normalization rules (that can strip trailing dots and spaces) and path
|
|
// length limitations. This option implies the same behavior of PATHCCH_DO_NOT_NORMALIZE_SEGMENTS.
|
|
// This can not be specified with PATHCCH_ALLOW_LONG_PATHS.
|
|
PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH = 0x10,
|
|
|
|
// When combining or normalizing a path ensure there is a trailing backslash.
|
|
PATHCCH_ENSURE_TRAILING_SLASH = 0x020,
|
|
|
|
// Convert forward slashes to back slashes and collapse multiple slashes.
|
|
// This is needed to to support sub-path or identity comparisons.
|
|
PATHCCH_CANONICALIZE_SLASHES = 0x040,
|
|
} PATHCCH_OPTIONS;
|
|
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) HRESULT __stdcall PathCchCanonicalizeEx(PWSTR pszPathOut, size_t cchPathOut, WCHAR const *pszPathIn, ULONG dwFlags);
|
|
};
|
|
|
|
// NOTE: um/errhandlingapi.h ///////////////////////////////////////////////////////////////////
|
|
extern "C"
|
|
{
|
|
__declspec(dllimport) VOID __stdcall RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, const ULONG_PTR* lpArguments);
|
|
};
|
|
|
|
// NOTE: include/excpt.h ///////////////////////////////////////////////////////////////////
|
|
#define EXCEPTION_EXECUTE_HANDLER 1
|
|
#define EXCEPTION_CONTINUE_SEARCH 0
|
|
#define EXCEPTION_CONTINUE_EXECUTION (-1)
|
|
|
|
DN_MSVC_WARNING_POP
|
|
#endif // !defined(_INC_WINDOWS)
|
|
#endif // !defined(DN_OS_WINDOWS_H)
|
|
// DN: Single header generator commented out => #include "OS/dn_os_w32.h"
|
|
#if !defined(DN_OS_W32_H)
|
|
#define DN_OS_W32_H
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #define DN_H_WITH_OS 1
|
|
// #include "../dn.h"
|
|
// #include "dn_os_windows.h"
|
|
// #endif
|
|
|
|
struct DN_OSW32Error
|
|
{
|
|
unsigned long code;
|
|
DN_Str8 msg;
|
|
};
|
|
|
|
struct DN_OSW32FolderIteratorW
|
|
{
|
|
void *handle;
|
|
DN_Str16 file_name;
|
|
wchar_t file_name_buf[512];
|
|
};
|
|
|
|
enum DN_OSW32SyncPrimitiveType
|
|
{
|
|
DN_OSW32SyncPrimitiveType_Semaphore,
|
|
DN_OSW32SyncPrimitiveType_Mutex,
|
|
DN_OSW32SyncPrimitiveType_ConditionVariable,
|
|
DN_OSW32SyncPrimitiveType_Barrier,
|
|
};
|
|
|
|
struct DN_OSW32SyncPrimitive
|
|
{
|
|
union
|
|
{
|
|
void *sem;
|
|
CRITICAL_SECTION mutex;
|
|
CONDITION_VARIABLE cv;
|
|
SYNCHRONIZATION_BARRIER barrier;
|
|
};
|
|
|
|
DN_OSW32SyncPrimitive *next;
|
|
};
|
|
|
|
typedef HRESULT DN_OSW32SetThreadDescriptionFunc(HANDLE hThread, PWSTR const lpThreadDescription);
|
|
struct DN_OSW32Core
|
|
{
|
|
DN_OSW32SetThreadDescriptionFunc *set_thread_description;
|
|
LARGE_INTEGER qpc_frequency;
|
|
void *bcrypt_rng_handle;
|
|
bool bcrypt_init_success;
|
|
bool sym_initialised;
|
|
|
|
CRITICAL_SECTION sync_primitive_free_list_mutex;
|
|
DN_OSW32SyncPrimitive *sync_primitive_free_list;
|
|
};
|
|
|
|
DN_API DN_OSW32Core* DN_OS_W32GetCore ();
|
|
DN_API void DN_OS_W32ThreadSetName (DN_Str8 name);
|
|
|
|
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_W32ErrorCodeToMsgAlloc (DN_U32 error_code);
|
|
DN_API DN_OSW32Error DN_OS_W32LastError (DN_Arena *arena);
|
|
DN_API DN_OSW32Error DN_OS_W32LastErrorAlloc ();
|
|
DN_API void DN_OS_W32MakeProcessDPIAware ();
|
|
|
|
// NOTE: Windows Str8 <-> Str16
|
|
DN_API DN_Str16 DN_OS_W32Str8ToStr16 (DN_Arena *arena, DN_Str8 src);
|
|
DN_API int DN_OS_W32Str8ToStr16Buffer (DN_Str16 src, char *dest, int dest_size);
|
|
DN_API DN_Str8 DN_OS_W32Str16ToStr8 (DN_Arena *arena, DN_Str16 src);
|
|
DN_API int DN_OS_W32Str16ToStr8Buffer (DN_Str16 src, char *dest, int dest_size);
|
|
DN_API DN_Str8 DN_OS_W32Str16ToStr8FromHeap (DN_Str16 src);
|
|
|
|
// NOTE: Path navigation
|
|
DN_API DN_Str16 DN_OS_W32EXEPathW (DN_Arena *arena);
|
|
DN_API DN_Str16 DN_OS_W32EXEDirW (DN_Arena *arena);
|
|
DN_API DN_Str8 DN_OS_W32WorkingDir (DN_Arena *arena, DN_Str8 suffix);
|
|
DN_API DN_Str16 DN_OS_W32WorkingDirW (DN_Arena *arena, DN_Str16 suffix);
|
|
DN_API bool DN_OS_W32DirWIterate (DN_Str16 path, DN_OSW32FolderIteratorW *it);
|
|
#endif // !defined(DN_OS_W32_H)
|
|
#elif defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN)
|
|
// DN: Single header generator commented out => #include "OS/dn_os_posix.h"
|
|
#if !defined(DN_OS_POSIX_H)
|
|
#define DN_OS_POSIX_H
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
#include <pthread.h>
|
|
#include <semaphore.h>
|
|
|
|
struct DN_OSPosixProcSelfStatus
|
|
{
|
|
char name[64];
|
|
DN_U8 name_size;
|
|
DN_U32 pid;
|
|
DN_U64 vm_peak;
|
|
DN_U32 vm_size;
|
|
};
|
|
|
|
// NOTE: The POSIX implementation disallows copies of synchronisation objects in
|
|
// general hence we have to dynamically allocate these primitives to maintain a
|
|
// consistent address.
|
|
//
|
|
//
|
|
// Source: The Open Group Base Specifications Issue 7, 2018 edition
|
|
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_09
|
|
//
|
|
// 2.9.9 Synchronization Object Copies and Alternative Mappings
|
|
//
|
|
// For barriers, condition variables, mutexes, and read-write locks, [TSH]
|
|
// [Option Start] if the process-shared attribute is set to
|
|
// PTHREAD_PROCESS_PRIVATE, [Option End] only the synchronization object at the
|
|
// address used to initialize it can be used for performing synchronization. The
|
|
// effect of referring to another mapping of the same object when locking,
|
|
// unlocking, or destroying the object is undefined. [...] The effect of
|
|
// referring to a copy of the object when locking, unlocking, or destroying it
|
|
// is undefined.
|
|
enum DN_OSPosixSyncPrimitiveType
|
|
{
|
|
DN_OSPosixSyncPrimitiveType_Semaphore,
|
|
DN_OSPosixSyncPrimitiveType_Mutex,
|
|
DN_OSPosixSyncPrimitiveType_ConditionVariable,
|
|
};
|
|
|
|
struct DN_OSPosixSyncPrimitive
|
|
{
|
|
union
|
|
{
|
|
sem_t sem;
|
|
pthread_mutex_t mutex;
|
|
pthread_cond_t cv;
|
|
pthread_barrier_t barrier;
|
|
};
|
|
DN_OSPosixSyncPrimitive *next;
|
|
};
|
|
|
|
struct DN_OSPosixCore
|
|
{
|
|
DN_OSPosixSyncPrimitive *sync_primitive_free_list;
|
|
pthread_mutex_t sync_primitive_free_list_mutex;
|
|
bool clock_monotonic_raw;
|
|
};
|
|
|
|
DN_API void DN_OS_PosixInit (DN_OSPosixCore *posix);
|
|
DN_API void DN_OS_PosixThreadSetName (DN_Str8 name);
|
|
DN_API DN_OSPosixProcSelfStatus DN_OS_PosixProcSelfStatus();
|
|
#endif // !defined(DN_OS_POSIX_H)
|
|
#else
|
|
#error Please define a platform e.g. 'DN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
|
|
#endif
|
|
// DN: Single header generator commented out => #include "OS/dn_os.h"
|
|
#if !defined(DN_OS_H)
|
|
#define DN_OS_H
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #define DN_H_WITH_OS 1
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
#include <new> // operator new
|
|
|
|
#if !defined(DN_OS_WIN32) || defined(DN_OS_WIN32_USE_PTHREADS)
|
|
#include <pthread.h>
|
|
#include <semaphore.h>
|
|
#endif
|
|
|
|
#if defined(DN_PLATFORM_POSIX) || defined(DN_PLATFORM_EMSCRIPTEN)
|
|
#include <errno.h> // errno
|
|
#include <fcntl.h> // O_RDONLY ... etc
|
|
#include <sys/ioctl.h> // ioctl
|
|
#include <sys/mman.h> // mmap
|
|
#include <sys/random.h> // getrandom
|
|
#include <sys/stat.h> // stat
|
|
#include <sys/types.h> // pid_t
|
|
#include <sys/wait.h> // waitpid
|
|
#include <time.h> // clock_gettime, nanosleep
|
|
#include <unistd.h> // access, gettid, write
|
|
|
|
#if !defined(DN_PLATFORM_EMSCRIPTEN)
|
|
#include <linux/fs.h> // FICLONE
|
|
#include <sys/sendfile.h> // sendfile
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
|
#include <emscripten/fetch.h> // emscripten_fetch (for DN_OSHttpResponse)
|
|
#endif
|
|
|
|
extern DN_CPUFeatureDecl g_dn_cpu_feature_decl[DN_CPUFeature_Count];
|
|
|
|
struct DN_OSTimer /// Record time between two time-points using the OS's performance counter.
|
|
{
|
|
DN_U64 start;
|
|
DN_U64 end;
|
|
};
|
|
|
|
// NOTE: DN_OSFile
|
|
enum DN_OSPathInfoType
|
|
{
|
|
DN_OSPathInfoType_Unknown,
|
|
DN_OSPathInfoType_Directory,
|
|
DN_OSPathInfoType_File,
|
|
};
|
|
|
|
struct DN_OSPathInfo
|
|
{
|
|
bool exists;
|
|
DN_OSPathInfoType type;
|
|
DN_U64 create_time_in_s;
|
|
DN_U64 last_write_time_in_s;
|
|
DN_U64 last_access_time_in_s;
|
|
DN_U64 size;
|
|
};
|
|
|
|
struct DN_OSDirIterator
|
|
{
|
|
void *handle;
|
|
DN_Str8 file_name;
|
|
char buffer[512];
|
|
};
|
|
|
|
// NOTE: R/W Stream API
|
|
struct DN_OSFileRead
|
|
{
|
|
bool success;
|
|
DN_USize bytes_read;
|
|
};
|
|
|
|
struct DN_OSFile
|
|
{
|
|
bool error;
|
|
void *handle;
|
|
};
|
|
|
|
enum DN_OSFileOpen
|
|
{
|
|
DN_OSFileOpen_CreateAlways, // Create file if it does not exist, otherwise, zero out the file and open
|
|
DN_OSFileOpen_OpenIfExist, // Open file at path only if it exists
|
|
DN_OSFileOpen_OpenAlways, // Open file at path, create file if it does not exist
|
|
};
|
|
|
|
typedef DN_U32 DN_OSFileAccess;
|
|
|
|
enum DN_OSFileAccess_
|
|
{
|
|
DN_OSFileAccess_Read = 1 << 0,
|
|
DN_OSFileAccess_Write = 1 << 1,
|
|
DN_OSFileAccess_Execute = 1 << 2,
|
|
DN_OSFileAccess_AppendOnly = 1 << 3, // This flag cannot be combined with any other access mode
|
|
DN_OSFileAccess_ReadWrite = DN_OSFileAccess_Read | DN_OSFileAccess_Write,
|
|
DN_OSFileAccess_All = DN_OSFileAccess_ReadWrite | DN_OSFileAccess_Execute | DN_OSFileAccess_AppendOnly,
|
|
};
|
|
|
|
// NOTE: DN_OSPath
|
|
#if !defined(DN_OSPathSeperator)
|
|
#if defined(DN_OS_WIN32)
|
|
#define DN_OSPathSeperator "\\"
|
|
#else
|
|
#define DN_OSPathSeperator "/"
|
|
#endif
|
|
#define DN_OSPathSeperatorString DN_Str8Lit(DN_OSPathSeperator)
|
|
#endif
|
|
|
|
struct DN_OSPathLink
|
|
{
|
|
DN_Str8 string;
|
|
DN_OSPathLink *next;
|
|
DN_OSPathLink *prev;
|
|
};
|
|
|
|
struct DN_OSPath
|
|
{
|
|
bool has_prefix_path_separator;
|
|
DN_OSPathLink *head;
|
|
DN_OSPathLink *tail;
|
|
DN_USize string_size;
|
|
DN_U16 links_size;
|
|
};
|
|
|
|
// NOTE: DN_OSExec
|
|
typedef DN_U32 DN_OSExecFlags;
|
|
|
|
enum DN_OSExecFlags_
|
|
{
|
|
DN_OSExecFlags_Nil = 0,
|
|
DN_OSExecFlags_SaveStdout = 1 << 0,
|
|
DN_OSExecFlags_SaveStderr = 1 << 1,
|
|
DN_OSExecFlags_SaveOutput = DN_OSExecFlags_SaveStdout | DN_OSExecFlags_SaveStderr,
|
|
DN_OSExecFlags_MergeStderrToStdout = 1 << 2 | DN_OSExecFlags_SaveOutput,
|
|
};
|
|
|
|
struct DN_OSExecAsyncHandle
|
|
{
|
|
DN_OSExecFlags exec_flags;
|
|
DN_U32 os_error_code;
|
|
DN_U32 exit_code;
|
|
void *process;
|
|
void *stdout_read;
|
|
void *stdout_write;
|
|
void *stderr_read;
|
|
void *stderr_write;
|
|
};
|
|
|
|
struct DN_OSExecResult
|
|
{
|
|
bool finished;
|
|
DN_Str8 stdout_text;
|
|
DN_Str8 stderr_text;
|
|
DN_U32 os_error_code;
|
|
DN_U32 exit_code;
|
|
};
|
|
|
|
struct DN_OSExecArgs
|
|
{
|
|
DN_OSExecFlags flags;
|
|
DN_Str8 working_dir;
|
|
DN_Str8Slice environment;
|
|
};
|
|
|
|
// NOTE: DN_OSSemaphore
|
|
DN_U32 const DN_OS_SEMAPHORE_INFINITE_TIMEOUT = UINT32_MAX;
|
|
|
|
struct DN_OSSemaphore
|
|
{
|
|
DN_U64 handle;
|
|
};
|
|
|
|
struct DN_OSBarrier
|
|
{
|
|
DN_U64 handle;
|
|
};
|
|
|
|
enum DN_OSSemaphoreWaitResult
|
|
{
|
|
DN_OSSemaphoreWaitResult_Failed,
|
|
DN_OSSemaphoreWaitResult_Success,
|
|
DN_OSSemaphoreWaitResult_Timeout,
|
|
};
|
|
|
|
struct DN_OSMutex
|
|
{
|
|
DN_U64 handle;
|
|
};
|
|
|
|
struct DN_OSConditionVariable
|
|
{
|
|
DN_U64 handle;
|
|
};
|
|
|
|
// NOTE: DN_OSThread
|
|
typedef DN_I32(DN_OSThreadFunc)(struct DN_OSThread *);
|
|
|
|
struct DN_OSThreadLane
|
|
{
|
|
DN_USize index;
|
|
DN_USize count;
|
|
DN_OSBarrier barrier;
|
|
void* shared_mem;
|
|
};
|
|
|
|
struct DN_OSThread
|
|
{
|
|
DN_Str8x64 name;
|
|
DN_TCCore context;
|
|
DN_OSThreadLane lane;
|
|
bool is_lane_set;
|
|
void *handle;
|
|
DN_U64 thread_id;
|
|
void *user_context;
|
|
DN_OSThreadFunc *func;
|
|
DN_OSSemaphore init_semaphore;
|
|
};
|
|
|
|
// NOTE: DN_OSHttp
|
|
enum DN_OSHttpRequestSecure
|
|
{
|
|
DN_OSHttpRequestSecure_No,
|
|
DN_OSHttpRequestSecure_Yes,
|
|
};
|
|
|
|
struct DN_OSHttpResponse
|
|
{
|
|
// NOTE: Response data
|
|
DN_U32 error_code;
|
|
DN_Str8 error_msg;
|
|
DN_U16 http_status;
|
|
DN_Str8 body;
|
|
DN_B32 done;
|
|
|
|
// NOTE: Book-keeping
|
|
DN_Arena *arena; // Allocates memory for the response
|
|
|
|
// NOTE: Async book-keeping
|
|
// Synchronous HTTP response uses the TLS scratch arena whereas async
|
|
// calls use their own dedicated arena.
|
|
DN_Arena tmp_arena;
|
|
DN_Arena scratch_arena;
|
|
DN_Str8Builder builder;
|
|
DN_OSSemaphore on_complete_semaphore;
|
|
|
|
#if defined(DN_PLATFORM_EMSCRIPTEN)
|
|
emscripten_fetch_t *em_handle;
|
|
#elif defined(DN_PLATFORM_WIN32)
|
|
HINTERNET w32_request_session;
|
|
HINTERNET w32_request_connection;
|
|
HINTERNET w32_request_handle;
|
|
#endif
|
|
};
|
|
|
|
struct DN_OSCore
|
|
{
|
|
DN_CPUReport cpu_report;
|
|
|
|
// NOTE: Logging
|
|
bool log_to_file; // Output logs to file as well as standard out
|
|
DN_OSFile log_file; // TODO(dn): Hmmm, how should we do this... ?
|
|
DN_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
|
|
DN_TicketMutex log_mutex;
|
|
|
|
// NOTE: OS
|
|
DN_U32 logical_processor_count;
|
|
DN_U32 page_size;
|
|
DN_U32 alloc_granularity;
|
|
|
|
// NOTE: Memory
|
|
// Total OS mem allocs in lifetime of program (e.g. malloc, VirtualAlloc, HeapAlloc ...). This
|
|
// only includes allocations routed through the library such as the growing nature of arenas or
|
|
// using the memory allocation routines in the library like DN_OS_MemCommit and so forth.
|
|
DN_U64 vmem_allocs_total;
|
|
DN_U64 vmem_allocs_frame; // Total OS virtual memory allocs since the last 'DN_Core_FrameBegin' was invoked
|
|
DN_U64 mem_allocs_total;
|
|
DN_U64 mem_allocs_frame; // Total OS heap allocs since the last 'DN_Core_FrameBegin' was invoked
|
|
|
|
DN_MemList mem;
|
|
DN_Arena arena;
|
|
void *platform_context;
|
|
};
|
|
|
|
struct DN_OSDiskSpace
|
|
{
|
|
bool success;
|
|
DN_U64 avail;
|
|
DN_U64 size;
|
|
};
|
|
|
|
DN_API DN_MemFuncs DN_MemFuncsFromType (DN_MemFuncsType type);
|
|
DN_API DN_MemFuncs DN_MemFuncsDefault ();
|
|
DN_API DN_MemList DN_MemListFromHeap (DN_U64 size, DN_MemFlags flags);
|
|
DN_API DN_MemList DN_MemListFromVMem (DN_U64 reserve, DN_U64 commit, DN_MemFlags flags);
|
|
|
|
|
|
DN_API DN_Str8 DN_Str8FromHeapF (DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8 DN_Str8FromHeap (DN_USize size, DN_ZMem z_mem);
|
|
DN_API DN_Str8 DN_Str8BuilderBuildFromHeap (DN_Str8Builder const *builder);
|
|
|
|
DN_API void DN_OS_LogPrint (DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API void DN_OS_SetLogPrintFuncToOS ();
|
|
|
|
DN_API void * DN_OS_MemReserve (DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
|
|
DN_API bool DN_OS_MemCommit (void *ptr, DN_USize size, DN_U32 page_flags);
|
|
DN_API void DN_OS_MemDecommit (void *ptr, DN_USize size);
|
|
DN_API void DN_OS_MemRelease (void *ptr, DN_USize size);
|
|
DN_API int DN_OS_MemProtect (void *ptr, DN_USize size, DN_U32 page_flags);
|
|
|
|
DN_API void * DN_OS_MemAlloc (DN_USize size, DN_ZMem z_mem);
|
|
DN_API void DN_OS_MemDealloc (void *ptr);
|
|
|
|
DN_API DN_Date DN_OS_DateLocalTimeNow ();
|
|
DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8Now (char date_separator = '-', char hms_separator = ':');
|
|
DN_API DN_Str8x32 DN_OS_DateLocalTimeStr8 (DN_Date time, char date_separator = '-', char hms_separator = ':');
|
|
DN_API DN_U64 DN_OS_DateUnixTimeNs ();
|
|
#define DN_OS_DateUnixTimeUs() (DN_OS_DateUnixTimeNs() / 1000)
|
|
#define DN_OS_DateUnixTimeMs() (DN_OS_DateUnixTimeNs() / (1000 * 1000))
|
|
#define DN_OS_DateUnixTimeS() (DN_OS_DateUnixTimeNs() / (1000 * 1000 * 1000))
|
|
DN_API DN_U64 DN_OS_DateUnixTimeSFromLocalDate (DN_Date date);
|
|
DN_API DN_U64 DN_OS_DateLocalUnixTimeSFromUnixTimeS (DN_U64 unix_ts_s);
|
|
|
|
DN_API void DN_OS_GenBytesSecure (void *buffer, DN_U32 size);
|
|
DN_API bool DN_OS_SetEnvVar (DN_Str8 name, DN_Str8 value);
|
|
DN_API DN_OSDiskSpace DN_OS_DiskSpace (DN_Str8 path);
|
|
DN_API DN_Str8 DN_OS_EXEPath (DN_Arena *arena);
|
|
DN_API DN_Str8 DN_OS_EXEDir (DN_Arena *arena);
|
|
DN_API void DN_OS_SleepMs (DN_UInt milliseconds);
|
|
|
|
DN_API DN_U64 DN_OS_PerfCounterNow ();
|
|
DN_API DN_U64 DN_OS_PerfCounterFrequency ();
|
|
DN_API DN_F64 DN_OS_PerfCounterS (DN_U64 begin, uint64_t end);
|
|
DN_API DN_F64 DN_OS_PerfCounterMs (DN_U64 begin, uint64_t end);
|
|
DN_API DN_F64 DN_OS_PerfCounterUs (DN_U64 begin, uint64_t end);
|
|
DN_API DN_F64 DN_OS_PerfCounterNs (DN_U64 begin, uint64_t end);
|
|
DN_API DN_OSTimer DN_OS_TimerBegin ();
|
|
DN_API void DN_OS_TimerEnd (DN_OSTimer *timer);
|
|
DN_API DN_F64 DN_OS_TimerS (DN_OSTimer timer);
|
|
DN_API DN_F64 DN_OS_TimerMs (DN_OSTimer timer);
|
|
DN_API DN_F64 DN_OS_TimerUs (DN_OSTimer timer);
|
|
DN_API DN_F64 DN_OS_TimerNs (DN_OSTimer timer);
|
|
DN_API DN_U64 DN_OS_EstimateTSCPerSecond (uint64_t duration_ms_to_gauge_tsc_frequency);
|
|
|
|
DN_API bool DN_OS_FileCopy (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err);
|
|
DN_API bool DN_OS_FileMove (DN_Str8 src, DN_Str8 dest, bool overwrite, DN_ErrSink *err);
|
|
|
|
DN_API DN_OSFile DN_OS_FileOpen (DN_Str8 path, DN_OSFileOpen open_mode, DN_OSFileAccess access, DN_ErrSink *err);
|
|
DN_API DN_OSFileRead DN_OS_FileRead (DN_OSFile *file, void *buffer, DN_USize size, DN_ErrSink *err);
|
|
DN_API bool DN_OS_FileWritePtr (DN_OSFile *file, void const *data, DN_USize size, DN_ErrSink *err);
|
|
DN_API bool DN_OS_FileWrite (DN_OSFile *file, DN_Str8 buffer, DN_ErrSink *err);
|
|
DN_API bool DN_OS_FileWriteFV (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API bool DN_OS_FileWriteF (DN_OSFile *file, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API bool DN_OS_FileFlush (DN_OSFile *file, DN_ErrSink *err);
|
|
DN_API void DN_OS_FileClose (DN_OSFile *file);
|
|
|
|
DN_API DN_Str8 DN_OS_FileReadAll (DN_Allocator alloc_type, void *allocator, DN_Str8 path, DN_ErrSink *err);
|
|
DN_API DN_Str8 DN_OS_FileReadAllArena (DN_Arena *arena, DN_Str8 path, DN_ErrSink *err);
|
|
DN_API DN_Str8 DN_OS_FileReadAllPool (DN_Pool *pool, DN_Str8 path, DN_ErrSink *err);
|
|
|
|
DN_API bool DN_OS_FileWriteAll (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err);
|
|
DN_API bool DN_OS_FileWriteAllFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API bool DN_OS_FileWriteAllF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API bool DN_OS_FileWriteAllSafe (DN_Str8 path, DN_Str8 buffer, DN_ErrSink *err);
|
|
DN_API bool DN_OS_FileWriteAllSafeFV (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API bool DN_OS_FileWriteAllSafeF (DN_Str8 path, DN_ErrSink *err, DN_FMT_ATTRIB char const *fmt, ...);
|
|
|
|
DN_API DN_Str8 DN_OS_Str8FromPathInfoType (DN_OSPathInfoType type);
|
|
DN_API DN_OSPathInfo DN_OS_PathInfo (DN_Str8 path);
|
|
DN_API bool DN_OS_PathIsOlderThan (DN_Str8 file, DN_Str8 check_against);
|
|
DN_API bool DN_OS_PathDelete (DN_Str8 path);
|
|
DN_API bool DN_OS_PathIsFile (DN_Str8 path);
|
|
DN_API bool DN_OS_PathIsDir (DN_Str8 path);
|
|
DN_API bool DN_OS_PathMakeDir (DN_Str8 path);
|
|
DN_API bool DN_OS_PathIterateDir (DN_Str8 path, DN_OSDirIterator *it);
|
|
|
|
DN_API bool DN_OS_PathAddRef (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
|
|
DN_API bool DN_OS_PathAdd (DN_Arena *arena, DN_OSPath *fs_path, DN_Str8 path);
|
|
DN_API bool DN_OS_PathAddF (DN_Arena *arena, DN_OSPath *fs_path, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API bool DN_OS_PathPop (DN_OSPath *fs_path);
|
|
DN_API DN_Str8 DN_OS_PathBuildWithSeparator (DN_Arena *arena, DN_OSPath const *fs_path, DN_Str8 path_separator);
|
|
DN_API DN_Str8 DN_OS_PathTo (DN_Arena *arena, DN_Str8 path, DN_Str8 path_separtor);
|
|
DN_API DN_Str8 DN_OS_PathToF (DN_Arena *arena, DN_Str8 path_separator, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8 DN_OS_Path (DN_Arena *arena, DN_Str8 path);
|
|
DN_API DN_Str8 DN_OS_PathF (DN_Arena *arena, DN_FMT_ATTRIB char const *fmt, ...);
|
|
|
|
#define DN_OS_PathBuildFwdSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("/"))
|
|
#define DN_OS_PathBuildBackSlash(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_Str8Lit("\\"))
|
|
#define DN_OS_PathBuild(allocator, fs_path) DN_OS_PathBuildWithSeparator(allocator, fs_path, DN_OSPathSeparatorString)
|
|
|
|
DN_API void DN_OS_Exit (int32_t exit_code);
|
|
DN_API DN_OSExecResult DN_OS_ExecPump (DN_OSExecAsyncHandle handle, char *stdout_buffer, size_t *stdout_size, char *stderr_buffer, size_t *stderr_size, DN_U32 timeout_ms, DN_ErrSink *err);
|
|
DN_API DN_OSExecResult DN_OS_ExecWait (DN_OSExecAsyncHandle handle, DN_Arena *arena, DN_ErrSink *err);
|
|
DN_API DN_OSExecAsyncHandle DN_OS_ExecAsync (DN_Str8Slice cmd_line, DN_OSExecArgs *args, DN_ErrSink *err);
|
|
DN_API DN_OSExecResult DN_OS_Exec (DN_Str8Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena, DN_ErrSink *err);
|
|
DN_API DN_OSExecResult DN_OS_ExecOrAbort (DN_Str8Slice cmd_line, DN_OSExecArgs *args, DN_Arena *arena);
|
|
|
|
DN_API DN_OSSemaphore DN_OS_SemaphoreInit (DN_U32 initial_count);
|
|
DN_API void DN_OS_SemaphoreDeinit (DN_OSSemaphore *semaphore);
|
|
DN_API void DN_OS_SemaphoreIncrement (DN_OSSemaphore *semaphore, DN_U32 amount);
|
|
DN_API DN_OSSemaphoreWaitResult DN_OS_SemaphoreWait (DN_OSSemaphore *semaphore, DN_U32 timeout_ms);
|
|
|
|
DN_API DN_OSBarrier DN_OS_BarrierInit (DN_U32 thread_count);
|
|
DN_API void DN_OS_BarrierDeinit (DN_OSBarrier *barrier);
|
|
DN_API void DN_OS_BarrierWait (DN_OSBarrier *barrier);
|
|
|
|
DN_API DN_OSMutex DN_OS_MutexInit ();
|
|
DN_API void DN_OS_MutexDeinit (DN_OSMutex *mutex);
|
|
DN_API void DN_OS_MutexLock (DN_OSMutex *mutex);
|
|
DN_API void DN_OS_MutexUnlock (DN_OSMutex *mutex);
|
|
#define DN_OS_MutexScope(mutex) DN_DeferLoop(DN_OS_MutexLock(mutex), DN_OS_MutexUnlock(mutex))
|
|
|
|
DN_API DN_OSConditionVariable DN_OS_ConditionVariableInit ();
|
|
DN_API void DN_OS_ConditionVariableDeinit (DN_OSConditionVariable *cv);
|
|
DN_API bool DN_OS_ConditionVariableWait (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 sleep_ms);
|
|
DN_API bool DN_OS_ConditionVariableWaitUntil (DN_OSConditionVariable *cv, DN_OSMutex *mutex, DN_U64 end_ts_ms);
|
|
DN_API void DN_OS_ConditionVariableSignal (DN_OSConditionVariable *cv);
|
|
DN_API void DN_OS_ConditionVariableBroadcast (DN_OSConditionVariable *cv);
|
|
|
|
DN_API bool DN_OS_ThreadInit (DN_OSThread *thread, DN_OSThreadFunc *func, DN_OSThreadLane *lane, void *user_context);
|
|
DN_API bool DN_OS_ThreadJoin (DN_OSThread *thread, DN_TCDeinitArenas deinit_arenas);
|
|
DN_API DN_U32 DN_OS_ThreadID ();
|
|
DN_API void DN_OS_ThreadSetNameFmt (char const *fmt, ...);
|
|
|
|
DN_API DN_OSThreadLane DN_OS_ThreadLaneInit (DN_USize index, DN_USize thread_count, DN_OSBarrier barrier, DN_UPtr *share_mem);
|
|
DN_API void DN_OS_ThreadLaneSync (DN_OSThreadLane *lane, void **ptr_to_share);
|
|
DN_API DN_V2USize DN_OS_ThreadLaneRange (DN_OSThreadLane *lane, DN_USize values_count);
|
|
|
|
DN_API DN_OSThreadLane* DN_OS_TCThreadLane ();
|
|
DN_API void DN_OS_TCThreadLaneSync (void **ptr_to_share);
|
|
DN_API DN_OSThreadLane DN_OS_TCThreadLaneEquip (DN_OSThreadLane lane);
|
|
|
|
DN_API void DN_OS_HttpRequestAsync (DN_OSHttpResponse *response, DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
|
|
DN_API void DN_OS_HttpRequestWait (DN_OSHttpResponse *response);
|
|
DN_API void DN_OS_HttpRequestFree (DN_OSHttpResponse *response);
|
|
DN_API DN_OSHttpResponse DN_OS_HttpRequest (DN_Arena *arena, DN_Str8 host, DN_Str8 path, DN_OSHttpRequestSecure secure, DN_Str8 method, DN_Str8 body, DN_Str8 headers);
|
|
|
|
// NOTE: DN_OSPrint
|
|
enum DN_OSPrintDest
|
|
{
|
|
DN_OSPrintDest_Out,
|
|
DN_OSPrintDest_Err,
|
|
};
|
|
|
|
// NOTE: Print Macros
|
|
#define DN_OS_PrintOut(string) DN_OS_Print(DN_OSPrintDest_Out, string)
|
|
#define DN_OS_PrintOutF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
|
|
#define DN_OS_PrintOutFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Out, fmt, args)
|
|
|
|
#define DN_OS_PrintOutStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Out, style, string)
|
|
#define DN_OS_PrintOutFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
|
|
#define DN_OS_PrintOutFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Out, style, fmt, args)
|
|
|
|
#define DN_OS_PrintOutLn(string) DN_OS_PrintLn(DN_OSPrintDest_Out, string)
|
|
#define DN_OS_PrintOutLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Out, fmt, ##__VA_ARGS__)
|
|
#define DN_OS_PrintOutLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Out, fmt, args)
|
|
|
|
#define DN_OS_PrintOutLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Out, style, string);
|
|
#define DN_OS_PrintOutLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Out, style, fmt, ##__VA_ARGS__)
|
|
#define DN_OS_PrintOutLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Out, style, fmt, args);
|
|
|
|
#define DN_OS_PrintErr(string) DN_OS_Print(DN_OSPrintDest_Err, string)
|
|
#define DN_OS_PrintErrF(fmt, ...) DN_OS_PrintF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
|
|
#define DN_OS_PrintErrFV(fmt, args) DN_OS_PrintFV(DN_OSPrintDest_Err, fmt, args)
|
|
|
|
#define DN_OS_PrintErrStyle(style, string) DN_OS_PrintStyle(DN_OSPrintDest_Err, style, string)
|
|
#define DN_OS_PrintErrFStyle(style, fmt, ...) DN_OS_PrintFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
|
|
#define DN_OS_PrintErrFVStyle(style, fmt, args, ...) DN_OS_PrintFVStyle(DN_OSPrintDest_Err, style, fmt, args)
|
|
|
|
#define DN_OS_PrintErrLn(string) DN_OS_PrintLn(DN_OSPrintDest_Err, string)
|
|
#define DN_OS_PrintErrLnF(fmt, ...) DN_OS_PrintLnF(DN_OSPrintDest_Err, fmt, ##__VA_ARGS__)
|
|
#define DN_OS_PrintErrLnFV(fmt, args) DN_OS_PrintLnFV(DN_OSPrintDest_Err, fmt, args)
|
|
|
|
#define DN_OS_PrintErrLnStyle(style, string) DN_OS_PrintLnStyle(DN_OSPrintDest_Err, style, string);
|
|
#define DN_OS_PrintErrLnFStyle(style, fmt, ...) DN_OS_PrintLnFStyle(DN_OSPrintDest_Err, style, fmt, ##__VA_ARGS__)
|
|
#define DN_OS_PrintErrLnFVStyle(style, fmt, args) DN_OS_PrintLnFVStyle(DN_OSPrintDest_Err, style, fmt, args);
|
|
|
|
// NOTE: Print
|
|
DN_API void DN_OS_Print (DN_OSPrintDest dest, DN_Str8 string);
|
|
DN_API void DN_OS_PrintF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_OS_PrintFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
|
|
DN_API void DN_OS_PrintStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string);
|
|
DN_API void DN_OS_PrintFStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_OS_PrintFVStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
|
|
DN_API void DN_OS_PrintLn (DN_OSPrintDest dest, DN_Str8 string);
|
|
DN_API void DN_OS_PrintLnF (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_OS_PrintLnFV (DN_OSPrintDest dest, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
|
|
DN_API void DN_OS_PrintLnStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_Str8 string);
|
|
DN_API void DN_OS_PrintLnFStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API void DN_OS_PrintLnFVStyle (DN_OSPrintDest dest, DN_LogStyle style, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
|
|
// NOTE: DN_VArray
|
|
// TODO(doyle): Add an API for shrinking the array by decomitting pages back to the OS.
|
|
template <typename T> struct DN_VArray
|
|
{
|
|
T *data; // Pointer to the start of the array items in the block of memory
|
|
DN_USize size; // Number of items currently in the array
|
|
DN_USize max; // Maximum number of items this array can store
|
|
DN_USize commit; // Bytes committed
|
|
|
|
T *begin() { return data; }
|
|
T *end () { return data + size; }
|
|
T const *begin() const { return data; }
|
|
T const *end () const { return data + size; }
|
|
};
|
|
|
|
template <typename T> DN_VArray<T> DN_OS_VArrayInitByteSize (DN_USize byte_size);
|
|
template <typename T> DN_VArray<T> DN_OS_VArrayInit (DN_USize max);
|
|
template <typename T, DN_USize N> DN_VArray<T> DN_OS_VArrayInitCArray (T const (&items)[N], DN_USize max);
|
|
template <typename T> void DN_OS_VArrayDeinit (DN_VArray<T> *array);
|
|
template <typename T> bool DN_OS_VArrayIsValid (DN_VArray<T> const *array);
|
|
template <typename T> bool DN_OS_VArrayReserve (DN_VArray<T> *array, DN_USize count);
|
|
template <typename T> T * DN_OS_VArrayAddArray (DN_VArray<T> *array, T const *items, DN_USize count);
|
|
template <typename T, DN_USize N> T * DN_OS_VArrayAddCArray (DN_VArray<T> *array, T const (&items)[N]);
|
|
template <typename T> T * DN_OS_VArrayAdd (DN_VArray<T> *array, T const &item);
|
|
#define DN_OS_VArrayAddArrayAssert(...) DN_HardAssert(DN_OS_VArrayAddArray(__VA_ARGS__))
|
|
#define DN_OS_VArrayAddCArrayAssert(...) DN_HardAssert(DN_OS_VArrayAddCArray(__VA_ARGS__))
|
|
#define DN_OS_VArrayAddAssert(...) DN_HardAssert(DN_OS_VArrayAdd(__VA_ARGS__))
|
|
template <typename T> T * DN_OS_VArrayMakeArray (DN_VArray<T> *array, DN_USize count, DN_ZMem z_mem);
|
|
template <typename T> T * DN_OS_VArrayMake (DN_VArray<T> *array, DN_ZMem z_mem);
|
|
#define DN_OS_VArrayMakeArrayAssert(...) DN_HardAssert(DN_OS_VArrayMakeArray(__VA_ARGS__))
|
|
#define DN_OS_VArrayMakeAssert(...) DN_HardAssert(DN_OS_VArrayMake(__VA_ARGS__))
|
|
template <typename T> T * DN_OS_VArrayInsertArray (DN_VArray<T> *array, DN_USize index, T const *items, DN_USize count);
|
|
template <typename T, DN_USize N> T * DN_OS_VArrayInsertCArray (DN_VArray<T> *array, DN_USize index, T const (&items)[N]);
|
|
template <typename T> T * DN_OS_VArrayInsert (DN_VArray<T> *array, DN_USize index, T const &item);
|
|
#define DN_OS_VArrayInsertArrayAssert(...) DN_HardAssert(DN_OS_VArrayInsertArray(__VA_ARGS__))
|
|
#define DN_OS_VArrayInsertCArrayAssert(...) DN_HardAssert(DN_OS_VArrayInsertCArray(__VA_ARGS__))
|
|
#define DN_OS_VArrayInsertAssert(...) DN_HardAssert(DN_OS_VArrayInsert(__VA_ARGS__))
|
|
template <typename T> T DN_OS_VArrayPopFront (DN_VArray<T> *array, DN_USize count);
|
|
template <typename T> T DN_OS_VArrayPopBack (DN_VArray<T> *array, DN_USize count);
|
|
template <typename T> DN_ArrayEraseResult DN_OS_VArrayEraseRange (DN_VArray<T> *array, DN_USize begin_index, DN_ISize count, DN_ArrayErase erase);
|
|
template <typename T> void DN_OS_VArrayClear (DN_VArray<T> *array, DN_ZMem z_mem);
|
|
#endif // !defined(DN_OS_H)
|
|
#endif
|
|
|
|
struct DN_InitArgs
|
|
{
|
|
DN_TCInitArgs thread_context_init_args;
|
|
};
|
|
|
|
typedef DN_USize DN_InitFlags;
|
|
enum DN_InitFlags_
|
|
{
|
|
DN_InitFlags_Nil = 0,
|
|
DN_InitFlags_OS = (1 << 0),
|
|
DN_InitFlags_ThreadContext = (1 << 1) | DN_InitFlags_OS,
|
|
DN_InitFlags_LeakTracker = (1 << 2) | DN_InitFlags_OS,
|
|
DN_InitFlags_LogLibFeatures = (1 << 3),
|
|
DN_InitFlags_LogCPUFeatures = (1 << 4) | DN_InitFlags_OS,
|
|
DN_InitFlags_LogAllFeatures = DN_InitFlags_LogLibFeatures | DN_InitFlags_LogCPUFeatures,
|
|
};
|
|
|
|
struct DN_Core
|
|
{
|
|
DN_InitFlags init_flags;
|
|
DN_TCCore main_tc;
|
|
DN_USize mem_allocs_frame;
|
|
DN_LeakTracker leak;
|
|
|
|
DN_U32 log_level_to_show_from;
|
|
DN_LogPrintFunc* print_func;
|
|
void* print_func_context;
|
|
|
|
bool os_init;
|
|
#if defined(DN_OS_H)
|
|
DN_OSCore os;
|
|
#endif
|
|
};
|
|
|
|
DN_API void DN_Init (DN_Core *dn, DN_InitFlags flags, DN_InitArgs *args);
|
|
DN_API void DN_Set (DN_Core *dn);
|
|
DN_API DN_Core *DN_Get ();
|
|
DN_API void DN_BeginFrame();
|
|
|
|
#if DN_H_WITH_HELPERS
|
|
// DN: Single header generator commented out => #include "Extra/dn_helpers.h"
|
|
#if !defined(DN_HELPERS_H)
|
|
#define DN_HELPERS_H
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
/*
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// $$\ $$\ $$$$$$$$\ $$\ $$$$$$$\ $$$$$$$$\ $$$$$$$\ $$$$$$\
|
|
// $$ | $$ |$$ _____|$$ | $$ __$$\ $$ _____|$$ __$$\ $$ __$$\
|
|
// $$ | $$ |$$ | $$ | $$ | $$ |$$ | $$ | $$ |$$ / \__|
|
|
// $$$$$$$$ |$$$$$\ $$ | $$$$$$$ |$$$$$\ $$$$$$$ |\$$$$$$\
|
|
// $$ __$$ |$$ __| $$ | $$ ____/ $$ __| $$ __$$< \____$$\
|
|
// $$ | $$ |$$ | $$ | $$ | $$ | $$ | $$ |$$\ $$ |
|
|
// $$ | $$ |$$$$$$$$\ $$$$$$$$\ $$ | $$$$$$$$\ $$ | $$ |\$$$$$$ |
|
|
// \__| \__|\________|\________|\__| \________|\__| \__| \______/
|
|
//
|
|
// dn_helpers.h -- Helper functions/data structures
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
#if !defined(DN_NO_JSON_BUILDER)
|
|
enum DN_JSONBuilderItem
|
|
{
|
|
DN_JSONBuilderItem_Empty,
|
|
DN_JSONBuilderItem_OpenContainer,
|
|
DN_JSONBuilderItem_CloseContainer,
|
|
DN_JSONBuilderItem_KeyValue,
|
|
};
|
|
|
|
struct DN_JSONBuilder
|
|
{
|
|
bool use_stdout; // When set, ignore the string builder and dump immediately to stdout
|
|
DN_Str8Builder string_builder; // (Internal)
|
|
int indent_level; // (Internal)
|
|
int spaces_per_indent; // The number of spaces per indent level
|
|
DN_JSONBuilderItem last_item;
|
|
};
|
|
#endif // !defined(DN_NO_JSON_BUIDLER)
|
|
|
|
template <typename T>
|
|
using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs);
|
|
|
|
template <typename T>
|
|
bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs);
|
|
|
|
enum DN_BinarySearchType
|
|
{
|
|
// Index of the match. If no match is found, found is set to false and the
|
|
// index is set to the index where the match should be inserted/exist, if
|
|
// it were in the array
|
|
DN_BinarySearchType_Match,
|
|
|
|
// Index of the first element in the array that is `element >= find`. If no such
|
|
// item is found or the array is empty, then, the index is set to the array
|
|
// size and found is set to `false`.
|
|
//
|
|
// For example:
|
|
// int array[] = {0, 1, 2, 3, 4, 5};
|
|
// DN_BinarySearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BinarySearchType_LowerBound);
|
|
// printf("%zu\n", result.index); // Prints index '4'
|
|
|
|
DN_BinarySearchType_LowerBound,
|
|
|
|
// Index of the first element in the array that is `element > find`. If no such
|
|
// item is found or the array is empty, then, the index is set to the array
|
|
// size and found is set to `false`.
|
|
//
|
|
// For example:
|
|
// int array[] = {0, 1, 2, 3, 4, 5};
|
|
// DN_BinarySearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BinarySearchType_UpperBound);
|
|
// printf("%zu\n", result.index); // Prints index '5'
|
|
|
|
DN_BinarySearchType_UpperBound,
|
|
};
|
|
|
|
struct DN_BinarySearchResult
|
|
{
|
|
bool found;
|
|
DN_USize index;
|
|
};
|
|
|
|
template <typename T>
|
|
using DN_QSortLessThanProc = bool(T const &a, T const &b, void *user_context);
|
|
|
|
#if !defined(DN_NO_JSON_BUILDER)
|
|
// NOTE: DN_JSONBuilder ////////////////////////////////////////////////////////////////////////////
|
|
#define DN_JSONBuilder_Object(builder) \
|
|
DN_DeferLoop(DN_JSONBuilder_ObjectBegin(builder), \
|
|
DN_JSONBuilder_ObjectEnd(builder))
|
|
|
|
#define DN_JSONBuilder_ObjectNamed(builder, name) \
|
|
DN_DeferLoop(DN_JSONBuilder_ObjectBeginNamed(builder, name), \
|
|
DN_JSONBuilder_ObjectEnd(builder))
|
|
|
|
#define DN_JSONBuilder_Array(builder) \
|
|
DN_DeferLoop(DN_JSONBuilder_ArrayBegin(builder), \
|
|
DN_JSONBuilder_ArrayEnd(builder))
|
|
|
|
#define DN_JSONBuilder_ArrayNamed(builder, name) \
|
|
DN_DeferLoop(DN_JSONBuilder_ArrayBeginNamed(builder, name), \
|
|
DN_JSONBuilder_ArrayEnd(builder))
|
|
|
|
DN_API DN_JSONBuilder DN_JSONBuilder_Init (DN_Arena *arena, int spaces_per_indent);
|
|
DN_API DN_Str8 DN_JSONBuilder_Build (DN_JSONBuilder const *builder, DN_Arena *arena);
|
|
DN_API void DN_JSONBuilder_KeyValue (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value);
|
|
DN_API void DN_JSONBuilder_KeyValueF (DN_JSONBuilder *builder, DN_Str8 key, char const *value_fmt, ...);
|
|
DN_API void DN_JSONBuilder_ObjectBeginNamed (DN_JSONBuilder *builder, DN_Str8 name);
|
|
DN_API void DN_JSONBuilder_ObjectEnd (DN_JSONBuilder *builder);
|
|
DN_API void DN_JSONBuilder_ArrayBeginNamed (DN_JSONBuilder *builder, DN_Str8 name);
|
|
DN_API void DN_JSONBuilder_ArrayEnd (DN_JSONBuilder *builder);
|
|
DN_API void DN_JSONBuilder_Str8Named (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value);
|
|
DN_API void DN_JSONBuilder_LiteralNamed (DN_JSONBuilder *builder, DN_Str8 key, DN_Str8 value);
|
|
DN_API void DN_JSONBuilder_U64Named (DN_JSONBuilder *builder, DN_Str8 key, uint64_t value);
|
|
DN_API void DN_JSONBuilder_I64Named (DN_JSONBuilder *builder, DN_Str8 key, int64_t value);
|
|
DN_API void DN_JSONBuilder_F64Named (DN_JSONBuilder *builder, DN_Str8 key, double value, int decimal_places);
|
|
DN_API void DN_JSONBuilder_BoolNamed (DN_JSONBuilder *builder, DN_Str8 key, bool value);
|
|
|
|
#define DN_JSONBuilder_ObjectBegin(builder) DN_JSONBuilder_ObjectBeginNamed(builder, DN_Str8Lit(""))
|
|
#define DN_JSONBuilder_ArrayBegin(builder) DN_JSONBuilder_ArrayBeginNamed(builder, DN_Str8Lit(""))
|
|
#define DN_JSONBuilder_Str8(builder, value) DN_JSONBuilder_Str8Named(builder, DN_Str8Lit(""), value)
|
|
#define DN_JSONBuilder_Literal(builder, value) DN_JSONBuilder_LiteralNamed(builder, DN_Str8Lit(""), value)
|
|
#define DN_JSONBuilder_U64(builder, value) DN_JSONBuilder_U64Named(builder, DN_Str8Lit(""), value)
|
|
#define DN_JSONBuilder_I64(builder, value) DN_JSONBuilder_I64Named(builder, DN_Str8Lit(""), value)
|
|
#define DN_JSONBuilder_F64(builder, value) DN_JSONBuilder_F64Named(builder, DN_Str8Lit(""), value)
|
|
#define DN_JSONBuilder_Bool(builder, value) DN_JSONBuilder_BoolNamed(builder, DN_Str8Lit(""), value)
|
|
#endif // !defined(DN_NO_JSON_BUILDER)
|
|
|
|
// NOTE: DN_BinarySearch
|
|
template <typename T> bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs);
|
|
template <typename T> DN_BinarySearchResult DN_BinarySearch (T const *array, DN_USize array_size, T const &find, DN_BinarySearchType type = DN_BinarySearchType_Match, DN_BinarySearchLessThanProc<T> less_than = DN_BinarySearch_DefaultLessThan);
|
|
|
|
// NOTE: DN_QSort
|
|
template <typename T> bool DN_QSort_DefaultLessThan(T const &lhs, T const &rhs, void *user_context);
|
|
template <typename T> void DN_QSort (T *array, DN_USize array_size, void *user_context, DN_QSortLessThanProc<T> less_than = DN_QSort_DefaultLessThan);
|
|
|
|
// NOTE: DN_BinarySearch
|
|
template <typename T>
|
|
bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs)
|
|
{
|
|
bool result = lhs < rhs;
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
DN_BinarySearchResult DN_BinarySearch(T const *array,
|
|
DN_USize array_size,
|
|
T const &find,
|
|
DN_BinarySearchType type,
|
|
DN_BinarySearchLessThanProc<T> less_than)
|
|
{
|
|
DN_BinarySearchResult result = {};
|
|
if (!array || array_size <= 0 || !less_than)
|
|
return result;
|
|
|
|
T const *end = array + array_size;
|
|
T const *first = array;
|
|
T const *last = end;
|
|
while (first != last) {
|
|
DN_USize count = last - first;
|
|
T const *it = first + (count / 2);
|
|
|
|
bool advance_first = false;
|
|
if (type == DN_BinarySearchType_UpperBound)
|
|
advance_first = !less_than(find, it[0]);
|
|
else
|
|
advance_first = less_than(it[0], find);
|
|
|
|
if (advance_first)
|
|
first = it + 1;
|
|
else
|
|
last = it;
|
|
}
|
|
|
|
switch (type) {
|
|
case DN_BinarySearchType_Match: {
|
|
result.found = first != end && !less_than(find, *first);
|
|
} break;
|
|
|
|
case DN_BinarySearchType_LowerBound: /*FALLTHRU*/
|
|
case DN_BinarySearchType_UpperBound: {
|
|
result.found = first != end;
|
|
} break;
|
|
}
|
|
|
|
result.index = first - array;
|
|
return result;
|
|
}
|
|
|
|
// NOTE: DN_QSort //////////////////////////////////////////////////////////////////////////////////
|
|
template <typename T>
|
|
bool DN_QSort_DefaultLessThan(T const &lhs, T const &rhs, void *user_context)
|
|
{
|
|
(void)user_context;
|
|
bool result = lhs < rhs;
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
void DN_QSort(T *array, DN_USize array_size, void *user_context, DN_QSortLessThanProc<T> less_than)
|
|
{
|
|
if (!array || array_size <= 1 || !less_than)
|
|
return;
|
|
|
|
// NOTE: Insertion Sort, under 24->32 is an optimal amount /////////////////////////////////////
|
|
const DN_USize QSORT_THRESHOLD = 24;
|
|
if (array_size < QSORT_THRESHOLD) {
|
|
for (DN_USize item_to_insert_index = 1; item_to_insert_index < array_size; item_to_insert_index++) {
|
|
for (DN_USize index = 0; index < item_to_insert_index; index++) {
|
|
if (!less_than(array[index], array[item_to_insert_index], user_context)) {
|
|
T item_to_insert = array[item_to_insert_index];
|
|
for (DN_USize i = item_to_insert_index; i > index; i--)
|
|
array[i] = array[i - 1];
|
|
|
|
array[index] = item_to_insert;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// NOTE: Quick sort, under 24->32 is an optimal amount /////////////////////////////////////////
|
|
DN_USize last_index = array_size - 1;
|
|
DN_USize pivot_index = array_size / 2;
|
|
DN_USize partition_index = 0;
|
|
DN_USize start_index = 0;
|
|
|
|
// Swap pivot with last index, so pivot is always at the end of the array.
|
|
// This makes logic much simpler.
|
|
DN_Swap(array[last_index], array[pivot_index]);
|
|
pivot_index = last_index;
|
|
|
|
// 4^, 8, 7, 5, 2, 3, 6
|
|
if (less_than(array[start_index], array[pivot_index], user_context))
|
|
partition_index++;
|
|
start_index++;
|
|
|
|
// 4, |8, 7, 5^, 2, 3, 6*
|
|
// 4, 5, |7, 8, 2^, 3, 6*
|
|
// 4, 5, 2, |8, 7, ^3, 6*
|
|
// 4, 5, 2, 3, |7, 8, ^6*
|
|
for (DN_USize index = start_index; index < last_index; index++) {
|
|
if (less_than(array[index], array[pivot_index], user_context)) {
|
|
DN_Swap(array[partition_index], array[index]);
|
|
partition_index++;
|
|
}
|
|
}
|
|
|
|
// Move pivot to right of partition
|
|
// 4, 5, 2, 3, |6, 8, ^7*
|
|
DN_Swap(array[partition_index], array[pivot_index]);
|
|
DN_QSort(array, partition_index, user_context, less_than);
|
|
|
|
// Skip the value at partion index since that is guaranteed to be sorted.
|
|
// 4, 5, 2, 3, (x), 8, 7
|
|
DN_USize one_after_partition_index = partition_index + 1;
|
|
DN_QSort(array + one_after_partition_index, (array_size - one_after_partition_index), user_context, less_than);
|
|
}
|
|
|
|
#endif // !defined(DN_HELPERS_H)
|
|
#endif
|
|
|
|
#if DN_H_WITH_ASYNC
|
|
// DN: Single header generator commented out => #include "Extra/dn_async.h"
|
|
#if !defined(DN_ASYNC_H)
|
|
#define DN_ASYNC_H
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #define DN_H_WITH_OS 1
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
enum DN_ASYNCPriority
|
|
{
|
|
DN_ASYNCPriority_Low,
|
|
DN_ASYNCPriority_High,
|
|
DN_ASYNCPriority_Count,
|
|
};
|
|
|
|
struct DN_ASYNCCore
|
|
{
|
|
DN_OSMutex ring_mutex;
|
|
DN_OSConditionVariable ring_write_cv;
|
|
DN_OSSemaphore worker_sem;
|
|
DN_Ring ring;
|
|
DN_OSThread *threads;
|
|
DN_U32 thread_count;
|
|
DN_U32 busy_threads;
|
|
DN_U32 join_threads;
|
|
};
|
|
|
|
struct DN_ASYNCWorkArgs
|
|
{
|
|
DN_OSThread *thread;
|
|
void *input;
|
|
};
|
|
|
|
typedef void(DN_ASYNCWorkFunc)(DN_ASYNCWorkArgs work_args);
|
|
|
|
struct DN_ASYNCWork
|
|
{
|
|
DN_ASYNCWorkFunc *func;
|
|
void *input;
|
|
void *output;
|
|
};
|
|
|
|
struct DN_ASYNCTask
|
|
{
|
|
bool queued;
|
|
DN_ASYNCWork work;
|
|
DN_OSSemaphore completion_sem;
|
|
};
|
|
|
|
DN_API void DN_ASYNC_Init (DN_ASYNCCore *async, char *base, DN_USize base_size, DN_OSThread *threads, DN_U32 threads_size);
|
|
DN_API void DN_ASYNC_Deinit (DN_ASYNCCore *async);
|
|
DN_API bool DN_ASYNC_QueueWork(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms);
|
|
DN_API DN_ASYNCTask DN_ASYNC_QueueTask(DN_ASYNCCore *async, DN_ASYNCWorkFunc *func, void *input, DN_U64 wait_time_ms);
|
|
DN_API void DN_ASYNC_WaitTask (DN_OSSemaphore *sem, DN_U32 timeout_ms);
|
|
|
|
#endif // DN_ASYNC_H
|
|
#endif
|
|
|
|
#if DN_H_WITH_NET
|
|
// DN: Single header generator commented out => #include "Extra/dn_net.h"
|
|
#if !defined(DN_NET_H)
|
|
#define DN_NET_H
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #define DN_H_WITH_OS 1
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
enum DN_NETRequestType
|
|
{
|
|
DN_NETRequestType_Nil,
|
|
DN_NETRequestType_HTTP,
|
|
DN_NETRequestType_WS,
|
|
};
|
|
|
|
enum DN_NETResponseState
|
|
{
|
|
DN_NETResponseState_Nil,
|
|
DN_NETResponseState_Error,
|
|
DN_NETResponseState_HTTP,
|
|
DN_NETResponseState_WSOpen,
|
|
DN_NETResponseState_WSText,
|
|
DN_NETResponseState_WSBinary,
|
|
DN_NETResponseState_WSClose,
|
|
DN_NETResponseState_WSPing,
|
|
DN_NETResponseState_WSPong,
|
|
};
|
|
|
|
enum DN_NETWSSend
|
|
{
|
|
DN_NETWSSend_Text,
|
|
DN_NETWSSend_Binary,
|
|
DN_NETWSSend_Close,
|
|
DN_NETWSSend_Ping,
|
|
DN_NETWSSend_Pong,
|
|
};
|
|
|
|
enum DN_NETDoHTTPFlags
|
|
{
|
|
DN_NETDoHTTPFlags_Nil = 0,
|
|
DN_NETDoHTTPFlags_BasicAuth = 1 << 0,
|
|
};
|
|
|
|
struct DN_NETDoHTTPArgs
|
|
{
|
|
// NOTE: WS and HTTP args
|
|
DN_NETDoHTTPFlags flags;
|
|
DN_Str8 username;
|
|
DN_Str8 password;
|
|
DN_Str8 *headers;
|
|
DN_U16 headers_size;
|
|
|
|
// NOTE: HTTP args only
|
|
DN_Str8 payload;
|
|
};
|
|
|
|
struct DN_NETRequestHandle
|
|
{
|
|
DN_UPtr handle;
|
|
DN_U64 gen;
|
|
};
|
|
|
|
struct DN_NETResponse
|
|
{
|
|
// NOTE: Common to WS and HTTP responses
|
|
DN_NETResponseState state;
|
|
DN_NETRequestHandle request;
|
|
DN_Str8 error_str8;
|
|
DN_Str8 body;
|
|
|
|
// NOTE: HTTP responses only
|
|
DN_U32 http_status;
|
|
};
|
|
|
|
struct DN_NETRequest
|
|
{
|
|
DN_MemList mem;
|
|
DN_Arena arena;
|
|
DN_Arena start_response_arena;
|
|
DN_NETRequestType type;
|
|
DN_U64 gen;
|
|
DN_Str8 url;
|
|
DN_Str8 method;
|
|
DN_OSSemaphore completion_sem;
|
|
DN_NETDoHTTPArgs args;
|
|
DN_NETResponse response;
|
|
DN_NETRequest *next;
|
|
DN_NETRequest *prev;
|
|
DN_U64 context[2];
|
|
};
|
|
|
|
typedef void (DN_NETInitFunc) (struct DN_NETCore *net, char *base, DN_U64 base_size);
|
|
typedef void (DN_NETDeinitFunc) (struct DN_NETCore *net);
|
|
typedef DN_NETRequestHandle(DN_NETDoHTTPFunc) (struct DN_NETCore *net, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args);
|
|
typedef DN_NETRequestHandle(DN_NETDoWSFunc) (struct DN_NETCore *net, DN_Str8 url);
|
|
typedef void (DN_NETDoWSSendFunc) (DN_NETRequestHandle handle, DN_Str8 data, DN_NETWSSend send);
|
|
typedef DN_NETResponse (DN_NETWaitForResponseFunc) (DN_NETRequestHandle handle, DN_Arena *arena, DN_U32 timeout_ms);
|
|
typedef DN_NETResponse (DN_NETWaitForAnyResponseFunc)(struct DN_NETCore *net, DN_Arena *arena, DN_U32 timeout_ms);
|
|
|
|
struct DN_NETInterface
|
|
{
|
|
DN_NETInitFunc* init;
|
|
DN_NETDeinitFunc* deinit;
|
|
DN_NETDoHTTPFunc* do_http;
|
|
DN_NETDoWSFunc* do_ws;
|
|
DN_NETDoWSSendFunc* do_ws_send;
|
|
DN_NETWaitForResponseFunc* wait_for_response;
|
|
DN_NETWaitForAnyResponseFunc* wait_for_any_response;
|
|
};
|
|
|
|
struct DN_NETCore
|
|
{
|
|
char *base;
|
|
DN_U64 base_size;
|
|
DN_MemList mem;
|
|
DN_Arena arena;
|
|
DN_OSSemaphore completion_sem;
|
|
void *context;
|
|
DN_NETInterface api;
|
|
};
|
|
|
|
DN_Str8 DN_NET_Str8FromResponseState(DN_NETResponseState state);
|
|
DN_NETRequest * DN_NET_RequestFromHandle (DN_NETRequestHandle handle);
|
|
DN_NETRequestHandle DN_NET_HandleFromRequest (DN_NETRequest *request);
|
|
|
|
// NOTE: Internal functions for different networking implementations to use
|
|
void DN_NET_BaseInit_ (DN_NETCore *net, char *base, DN_U64 base_size);
|
|
DN_NETRequestHandle DN_NET_SetupRequest_ (DN_NETRequest *request, DN_Str8 url, DN_Str8 method, DN_NETDoHTTPArgs const *args, DN_NETRequestType type);
|
|
void DN_NET_EndFinishedRequest_ (DN_NETRequest *request);
|
|
|
|
#endif // DN_NET_H
|
|
#endif
|
|
#endif // !defined(DN_H)
|
|
#if !defined(DN_BIN_PACK_H)
|
|
#define DN_BIN_PACK_H
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
enum DN_BinPackMode
|
|
{
|
|
DN_BinPackMode_Serialise,
|
|
DN_BinPackMode_Deserialise,
|
|
};
|
|
|
|
struct DN_BinPack
|
|
{
|
|
DN_Str8Builder writer;
|
|
DN_Str8 read;
|
|
DN_USize read_index;
|
|
};
|
|
|
|
DN_API bool DN_BinPackIsEndOfReadStream(DN_BinPack const *pack);
|
|
DN_API void DN_BinPackUSize (DN_BinPack *pack, DN_BinPackMode mode, DN_USize *item);
|
|
DN_API void DN_BinPackU64 (DN_BinPack *pack, DN_BinPackMode mode, DN_U64 *item);
|
|
DN_API void DN_BinPackU32 (DN_BinPack *pack, DN_BinPackMode mode, DN_U32 *item);
|
|
DN_API void DN_BinPackU16 (DN_BinPack *pack, DN_BinPackMode mode, DN_U16 *item);
|
|
DN_API void DN_BinPackU8 (DN_BinPack *pack, DN_BinPackMode mode, DN_U8 *item);
|
|
DN_API void DN_BinPackI64 (DN_BinPack *pack, DN_BinPackMode mode, DN_I64 *item);
|
|
DN_API void DN_BinPackI32 (DN_BinPack *pack, DN_BinPackMode mode, DN_I32 *item);
|
|
DN_API void DN_BinPackI16 (DN_BinPack *pack, DN_BinPackMode mode, DN_I16 *item);
|
|
DN_API void DN_BinPackI8 (DN_BinPack *pack, DN_BinPackMode mode, DN_I8 *item);
|
|
DN_API void DN_BinPackF64 (DN_BinPack *pack, DN_BinPackMode mode, DN_F64 *item);
|
|
DN_API void DN_BinPackF32 (DN_BinPack *pack, DN_BinPackMode mode, DN_F32 *item);
|
|
#if defined (DN_MATH_H)
|
|
DN_API void DN_BinPackV2 (DN_BinPack *pack, DN_BinPackMode mode, DN_V2F32 *item);
|
|
DN_API void DN_BinPackV4 (DN_BinPack *pack, DN_BinPackMode mode, DN_V4F32 *item);
|
|
#endif
|
|
DN_API void DN_BinPackBool (DN_BinPack *pack, DN_BinPackMode mode, bool *item);
|
|
DN_API void DN_BinPackStr8FromArena (DN_BinPack *pack, DN_Arena *arena, DN_BinPackMode mode, DN_Str8 *string);
|
|
DN_API void DN_BinPackStr8FromPool (DN_BinPack *pack, DN_Pool *pool, DN_BinPackMode mode, DN_Str8 *string);
|
|
DN_API DN_Str8 DN_BinPackStr8FromBuffer (DN_BinPack *pack, DN_BinPackMode mode, char *ptr, DN_USize *size, DN_USize max);
|
|
DN_API void DN_BinPackBytesFromArena (DN_BinPack *pack, DN_Arena *arena, DN_BinPackMode mode, void **ptr, DN_USize *size);
|
|
DN_API void DN_BinPackBytesFromPool (DN_BinPack *pack, DN_Pool *pool, DN_BinPackMode mode, void **ptr, DN_USize *size);
|
|
DN_API void DN_BinPackCArray (DN_BinPack *pack, DN_BinPackMode mode, void *ptr, DN_USize size);
|
|
DN_API void DN_BinPackCBuffer (DN_BinPack *pack, DN_BinPackMode mode, char *ptr, DN_USize *size, DN_USize max);
|
|
DN_API DN_Str8 DN_BinPackBuild (DN_BinPack const *pack, DN_Arena *arena);
|
|
|
|
#endif // !defined(DN_BIN_PACK_H)
|
|
#if !defined(DN_CSV_H)
|
|
#define DN_CSV_H
|
|
|
|
// NOTE: Data structures to create and parse CSV files, supports Python style escaped quotes (e.g.
|
|
// Using "" to escape quotes inside a quoted string).
|
|
//
|
|
// API
|
|
// DN_CSV_TokeniserNextN: Reads the next N consecutive fields from the parser. If `column_iterator`
|
|
// is `false` then the read of the N consecutive fields does not proceed past the end of the
|
|
// current CSV row. If `true` then it reads the next N fields even if reading would progress onto
|
|
// the next row.
|
|
|
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
|
// #include "../dn.h"
|
|
// #endif
|
|
|
|
enum DN_CSVSerialise
|
|
{
|
|
DN_CSVSerialise_Read,
|
|
DN_CSVSerialise_Write,
|
|
};
|
|
|
|
struct DN_CSVTokeniser
|
|
{
|
|
bool bad;
|
|
DN_Str8 string;
|
|
char delimiter;
|
|
char const *it;
|
|
bool end_of_line;
|
|
};
|
|
|
|
struct DN_CSVPack
|
|
{
|
|
DN_Str8Builder write_builder;
|
|
DN_USize write_column;
|
|
DN_CSVTokeniser read_tokeniser;
|
|
};
|
|
|
|
DN_CSVTokeniser DN_CSV_TokeniserInit (DN_Str8 string, char delimiter);
|
|
bool DN_CSV_TokeniserValid (DN_CSVTokeniser *tokeniser);
|
|
bool DN_CSV_TokeniserNextRow (DN_CSVTokeniser *tokeniser);
|
|
DN_Str8 DN_CSV_TokeniserNextField (DN_CSVTokeniser *tokeniser);
|
|
DN_Str8 DN_CSV_TokeniserNextColumn (DN_CSVTokeniser *tokeniser);
|
|
void DN_CSV_TokeniserSkipLine (DN_CSVTokeniser *tokeniser);
|
|
int DN_CSV_TokeniserNextN (DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size, bool column_iterator);
|
|
int DN_CSV_TokeniserNextColumnN(DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size);
|
|
int DN_CSV_TokeniserNextFieldN (DN_CSVTokeniser *tokeniser, DN_Str8 *fields, int fields_size);
|
|
void DN_CSV_TokeniserSkipLineN (DN_CSVTokeniser *tokeniser, int count);
|
|
void DN_CSV_PackU64 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U64 *value);
|
|
void DN_CSV_PackI64 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I64 *value);
|
|
void DN_CSV_PackI32 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I32 *value);
|
|
void DN_CSV_PackI16 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I16 *value);
|
|
void DN_CSV_PackI8 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_I8 *value);
|
|
void DN_CSV_PackU32 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U32 *value);
|
|
void DN_CSV_PackU16 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_U16 *value);
|
|
void DN_CSV_PackBoolAsU64 (DN_CSVPack *pack, DN_CSVSerialise serialise, bool *value);
|
|
void DN_CSV_PackStr8 (DN_CSVPack *pack, DN_CSVSerialise serialise, DN_Str8 *str8, DN_Arena *arena);
|
|
void DN_CSV_PackBuffer (DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size);
|
|
void DN_CSV_PackBufferWithMax (DN_CSVPack *pack, DN_CSVSerialise serialise, void *dest, size_t *size, size_t max);
|
|
bool DN_CSV_PackNewLine (DN_CSVPack *pack, DN_CSVSerialise serialise);
|
|
|
|
#endif // !defined(DN_CSV_H)
|