dqn: Cleanup more documentation

This commit is contained in:
doyle 2023-07-06 00:14:13 +10:00
parent 580b8a6882
commit 55dbc25110
7 changed files with 563 additions and 654 deletions

46
dqn.h
View File

@ -1,3 +1,49 @@
// NOTE: [$CFGM] Config macros =====================================================================
//
// #define DQN_IMPLEMENTATION
// Define this in one and only one C++ file to enable the implementation
// code of the header file
//
// #define DQN_NO_ASSERT
// Turn all assertion macros to no-ops
//
// #define DQN_NO_CHECK_BREAK
// Disable debug break when a check macro's expression fails. Instead only
// the error will be logged.
//
// #define DQN_NO_WIN32_MIN_HEADER
// Define this to stop this library from defining a minimal subset of Win32
// prototypes and definitions in this file. Useful for stopping redefinition
// of symbols if another library includes "Windows.h"
//
// #define DQN_STATIC_API
// Apply static to all function definitions and disable external linkage to
// other translation units.
//
// #define DQN_STB_SPRINTF_HEADER_ONLY
// Define this to stop this library from defining
// STB_SPRINTF_IMPLEMENTATION. Useful if another library uses and includes
// "stb_sprintf.h"
//
// #define DQN_MEMSET_BYTE 0
// Change the byte that DQN_MEMSET will clear memory with. By default this
// is set to 0. Some of this library API accepts are clear memory parameter
// to scrub memory after certain operations.
//
// #define DQN_LEAK_TRACING
// When defined to some allocating calls in the library will automatically
// get passed in the file name, function name, line number and an optional
// leak_msg.
#if defined(DQN_LEAK_TRACING)
#error Leak tracing not supported because we enter an infinite leak tracing loop tracing our own allocations made to tracks leaks in the internal leak table.
#endif
//
// #define DQN_DEBUG_THREAD_CONTEXT
// Define this macro to record allocation stats for arenas used in the
// thread context. The thread context arena stats can be printed by using
// Dqn_Library_DumpThreadContextArenaStat.
#if !defined(DQN_H) #if !defined(DQN_H)
#define DQN_H #define DQN_H
#include <stdarg.h> // va_list #include <stdarg.h> // va_list

View File

@ -1,7 +1,6 @@
// NOTE: Table Of Contents ========================================================================= // NOTE: Table Of Contents =========================================================================
// Index | Disable #define | Description // Index | Disable #define | Description
// ================================================================================================= // =================================================================================================
// [$CFGM] Config macros | | Compile time customisation of library
// [$CMAC] Compiler macros | | Macros for the compiler // [$CMAC] Compiler macros | | Macros for the compiler
// [$MACR] Macros | | Define macros used in the library // [$MACR] Macros | | Define macros used in the library
// [$TYPE] Typedefs | | Typedefs used in the library // [$TYPE] Typedefs | | Typedefs used in the library
@ -11,52 +10,6 @@
// [$CALL] Dqn_CallSite | | Source code location/tracing // [$CALL] Dqn_CallSite | | Source code location/tracing
// ===================+=================+=========================================================== // ===================+=================+===========================================================
// NOTE: [$CFGM] Config macros =====================================================================
// #define DQN_IMPLEMENTATION
// Define this in one and only one C++ file to enable the implementation
// code of the header file
//
// #define DQN_NO_ASSERT
// Turn all assertion macros to no-ops
//
// #define DQN_NO_CHECK_BREAK
// Disable debug break when a check macro's expression fails. Instead only
// the error will be logged.
//
// #define DQN_NO_WIN32_MINIMAL_HEADER
// Define this to stop this library from defining a minimal subset of Win32
// prototypes and definitions in this file. Useful for stopping redefinition
// of symbols if another library includes "Windows.h"
//
// #define DQN_STATIC_API
// Apply static to all function definitions and disable external linkage to
// other translation units.
//
// #define DQN_STB_SPRINTF_HEADER_ONLY
// Define this to stop this library from defining
// STB_SPRINTF_IMPLEMENTATION. Useful if another library uses and includes
// "stb_sprintf.h"
//
// #define DQN_MEMSET_BYTE 0
// Change the byte that DQN_MEMSET will clear memory with. By default this
// is set to 0. Some of this library API accepts are clear memory parameter
// to scrub memory after certain operations.
//
// #define DQN_LEAK_TRACING
// When defined to some allocating calls in the library will automatically
// get passed in the file name, function name, line number and an optional
// leak_msg.
#if defined(DQN_LEAK_TRACING)
#error Leak tracing not supported because we enter an infinite leak tracing loop tracing our own allocations made to tracks leaks in the internal leak table.
#endif
//
// #define DQN_DEBUG_THREAD_CONTEXT
// Define this macro to record allocation stats for arenas used in the
// thread context. The thread context arena stats can be printed by using
// Dqn_Library_DumpThreadContextArenaStat.
//
// NOTE: [$CMAC] Compiler macros =================================================================== // NOTE: [$CMAC] Compiler macros ===================================================================
// NOTE: Warning! Order is important here, clang-cl on Windows defines _MSC_VER // NOTE: Warning! Order is important here, clang-cl on Windows defines _MSC_VER
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -191,7 +144,7 @@
#define DQN_GIGABYTES(val) (1024ULL * DQN_MEGABYTES(val)) #define DQN_GIGABYTES(val) (1024ULL * DQN_MEGABYTES(val))
// NOTE: Time Macros =============================================================================== // NOTE: Time Macros ===============================================================================
#define DQN_SECONDS_TO_MS(val) ((val) * 1000.0f) #define DQN_SECONDS_TO_MS(val) ((val) * 1000)
#define DQN_MINS_TO_S(val) ((val) * 60ULL) #define DQN_MINS_TO_S(val) ((val) * 60ULL)
#define DQN_HOURS_TO_S(val) (DQN_MINS_TO_S(val) * 60ULL) #define DQN_HOURS_TO_S(val) (DQN_MINS_TO_S(val) * 60ULL)
#define DQN_DAYS_TO_S(val) (DQN_HOURS_TO_S(val) * 24ULL) #define DQN_DAYS_TO_S(val) (DQN_HOURS_TO_S(val) * 24ULL)
@ -237,7 +190,27 @@
} }
#endif #endif
#define DQN_INVALID_CODE_PATHF(fmt, ...) DQN_ASSERTF(0, fmt, ##__VA_ARGS__)
#define DQN_INVALID_CODE_PATH DQN_INVALID_CODE_PATHF("Invalid code path triggered")
// NOTE: Check macro ===============================================================================
// Assert the expression given in debug, whilst in release- assertion is
// removed and the expression is evaluated and returned.
//
// This function provides dual logic which allows handling of the condition
// gracefully in release mode, but asserting in debug mode. This is an internal
// function, prefer the @see DQN_CHECK macros.
//
// Returns true if the expression evaluated to true, false otherwise.
//
#if 0
bool flag = true;
if (!DQN_CHECKF(flag, "Flag was false!")) {
// This branch will execute!
}
#endif
#define DQN_CHECK(expr) DQN_CHECKF(expr, "") #define DQN_CHECK(expr) DQN_CHECKF(expr, "")
#if defined(DQN_NO_CHECK_BREAK) #if defined(DQN_NO_CHECK_BREAK)
#define DQN_CHECKF(expr, fmt, ...) \ #define DQN_CHECKF(expr, fmt, ...) \
((expr) ? true : (Dqn_Log_TypeFCallSite(Dqn_LogType_Warning, DQN_CALL_SITE, fmt, ## __VA_ARGS__), false)) ((expr) ? true : (Dqn_Log_TypeFCallSite(Dqn_LogType_Warning, DQN_CALL_SITE, fmt, ## __VA_ARGS__), false))
@ -246,30 +219,13 @@
((expr) ? true : (Dqn_Log_TypeFCallSite(Dqn_LogType_Error, DQN_CALL_SITE, fmt, ## __VA_ARGS__), DQN_DEBUG_BREAK, false)) ((expr) ? true : (Dqn_Log_TypeFCallSite(Dqn_LogType_Error, DQN_CALL_SITE, fmt, ## __VA_ARGS__), DQN_DEBUG_BREAK, false))
#endif #endif
#if 0 // NOTE: Zero initialisation macro =================================================================
DQN_API bool DQN_CHECKF_(bool assertion_expr, Dqn_CallSite call_site, char const *fmt, ...)
{
bool result = assertion_expr;
if (!result) {
va_list args;
va_start(args, fmt);
Dqn_Log_TypeFVCallSite(Dqn_LogType_Error, call_site, fmt, args);
va_end(args);
DQN_DEBUG_BREAK;
}
return result;
}
#endif
#if defined(__cplusplus) #if defined(__cplusplus)
#define DQN_ZERO_INIT {} #define DQN_ZERO_INIT {}
#else #else
#define DQN_ZERO_INIT {0} #define DQN_ZERO_INIT {0}
#endif #endif
#define DQN_INVALID_CODE_PATHF(fmt, ...) DQN_ASSERTF(0, fmt, ##__VA_ARGS__)
#define DQN_INVALID_CODE_PATH DQN_INVALID_CODE_PATHF("Invalid code path triggered")
// NOTE: Defer Macro =============================================================================== // NOTE: Defer Macro ===============================================================================
#if 0 #if 0
#include <stdio.h> #include <stdio.h>

View File

@ -78,264 +78,157 @@ DQN_API void Dqn_Library_LeakTraceMarkFree (Dqn_CallSite call_site, void
// NOTE: [$BITS] Dqn_Bit =========================================================================== // NOTE: [$BITS] Dqn_Bit ===========================================================================
DQN_API void Dqn_Bit_UnsetInplace(uint32_t *flags, uint32_t bitfield); DQN_API void Dqn_Bit_UnsetInplace(uint32_t *flags, uint32_t bitfield);
DQN_API void Dqn_Bit_SetInplace(uint32_t *flags, uint32_t bitfield); DQN_API void Dqn_Bit_SetInplace (uint32_t *flags, uint32_t bitfield);
DQN_API bool Dqn_Bit_IsSet(uint32_t bits, uint32_t bits_to_set); DQN_API bool Dqn_Bit_IsSet (uint32_t bits, uint32_t bits_to_set);
DQN_API bool Dqn_Bit_IsNotSet(uint32_t bits, uint32_t bits_to_check); DQN_API bool Dqn_Bit_IsNotSet (uint32_t bits, uint32_t bits_to_check);
// NOTE: [$SAFE] Dqn_Safe ========================================================================== // NOTE: [$SAFE] Dqn_Safe ==========================================================================
// Assert the expression given in debug, whilst in release- assertion is // @proc Dqn_Safe_AddI64, Dqn_Safe_MulI64
// removed and the expression is evaluated and returned. // @desc Add/multiply 2 I64's together, safe asserting that the operation does
// not overflow.
// @return The result of operation, INT64_MAX if it overflowed.
// @proc Dqn_Safe_AddU64, Dqn_Safe_MulU64
// @desc Add/multiply 2 U64's together, safe asserting that the operation does
// not overflow.
// @return The result of operation, UINT64_MAX if it overflowed.
// @proc Dqn_Safe_SubU64, Dqn_Safe_SubU32
// @desc Subtract 2xU64 or 2xU32's together, safe asserting that the operation
// does not overflow.
// @return The result of operation, 0 if it overflowed.
// @proc Dqn_Safe_SaturateCastUSizeToInt,
// Dqn_Safe_SaturateCastUSizeToI8,
// Dqn_Safe_SaturateCastUSizeToI16,
// Dqn_Safe_SaturateCastUSizeToI32,
// Dqn_Safe_SaturateCastUSizeToI64
// //
// This function provides dual logic which allows handling of the condition // Dqn_Safe_SaturateCastU64ToUInt,
// gracefully in release mode, but asserting in debug mode. This is an internal // Dqn_Safe_SaturateCastU64ToU8,
// function, prefer the @see DQN_CHECK macros. // Dqn_Safe_SaturateCastU64ToU16,
// Dqn_Safe_SaturateCastU64ToU32,
// //
// @param assertion_expr[in] Expressin to assert on // Dqn_Safe_SaturateCastUSizeToU8,
// @param fmt[in] Format string for providing a message on assertion // Dqn_Safe_SaturateCastUSizeToU16,
// @return True if the expression evaluated to true, false otherwise. // Dqn_Safe_SaturateCastUSizeToU32,
DQN_API bool DQN_CHECKF_(bool assertion_expr, Dqn_CallSite call_site, char const *fmt, ...); // Dqn_Safe_SaturateCastUSizeToU64
//
// Dqn_Safe_SaturateCastISizeToInt,
// Dqn_Safe_SaturateCastISizeToI8,
// Dqn_Safe_SaturateCastISizeToI16,
// Dqn_Safe_SaturateCastISizeToI32,
// Dqn_Safe_SaturateCastISizeToI64,
//
// int Dqn_Safe_SaturateCastISizeToUInt,
// Dqn_Safe_SaturateCastISizeToU8,
// Dqn_Safe_SaturateCastISizeToU16,
// Dqn_Safe_SaturateCastISizeToU32,
// Dqn_Safe_SaturateCastISizeToU64,
//
// Dqn_Safe_SaturateCastI64ToISize,
// Dqn_Safe_SaturateCastI64ToI8,
// Dqn_Safe_SaturateCastI64ToI16,
// Dqn_Safe_SaturateCastI64ToI32,
//
// Dqn_Safe_SaturateCastIntToI8,
// Dqn_Safe_SaturateCastIntToU8,
// Dqn_Safe_SaturateCastIntToU16,
// Dqn_Safe_SaturateCastIntToU32,
// Dqn_Safe_SaturateCastIntToU64,
//
// @desc Truncate the lhs operand to the right clamping the result to the max
// value of the desired data type. Safe asserts if clamping occurs.
//
// The following sentinel values are returned when saturated,
// USize -> Int: INT_MAX
// USize -> I8: INT8_MAX
// USize -> I16: INT16_MAX
// USize -> I32: INT32_MAX
// USize -> I64: INT64_MAX
//
// U64 -> UInt: UINT_MAX
// U64 -> U8: UINT8_MAX
// U64 -> U16: UINT16_MAX
// U64 -> U32: UINT32_MAX
//
// USize -> U8: UINT8_MAX
// USize -> U16: UINT16_MAX
// USize -> U32: UINT32_MAX
// USize -> U64: UINT64_MAX
//
// ISize -> Int: INT_MIN or INT_MAX
// ISize -> I8: INT8_MIN or INT8_MAX
// ISize -> I16: INT16_MIN or INT16_MAX
// ISize -> I32: INT32_MIN or INT32_MAX
// ISize -> I64: INT64_MIN or INT64_MAX
//
// ISize -> UInt: 0 or UINT_MAX
// ISize -> U8: 0 or UINT8_MAX
// ISize -> U16: 0 or UINT16_MAX
// ISize -> U32: 0 or UINT32_MAX
// ISize -> U64: 0 or UINT64_MAX
//
// I64 -> ISize: DQN_ISIZE_MIN or DQN_ISIZE_MAX
// I64 -> I8: INT8_MIN or INT8_MAX
// I64 -> I16: INT16_MIN or INT16_MAX
// I64 -> I32: INT32_MIN or INT32_MAX
//
// Int -> I8: INT8_MIN or INT8_MAX
// Int -> I16: INT16_MIN or INT16_MAX
// Int -> U8: 0 or UINT8_MAX
// Int -> U16: 0 or UINT16_MAX
// Int -> U32: 0 or UINT32_MAX
// Int -> U64: 0 or UINT64_MAX
// NOTE: Dqn_Safe Arithmetic DQN_API int64_t Dqn_Safe_AddI64 (int64_t a, int64_t b);
// ----------------------------------------------------------------------------- DQN_API int64_t Dqn_Safe_MulI64 (int64_t a, int64_t b);
/// Add 2 I64's together, safe asserting that the operation does not overflow.
/// @return The result of operation, INT64_MAX if it overflowed.
DQN_API int64_t Dqn_Safe_AddI64(int64_t a, int64_t b);
/// Multiply 2 I64's together, safe asserting that the operation does not DQN_API uint64_t Dqn_Safe_AddU64 (uint64_t a, uint64_t b);
/// overflow. DQN_API uint64_t Dqn_Safe_MulU64 (uint64_t a, uint64_t b);
/// @return The result of operation, IINT64_MAX if it overflowed.
DQN_API int64_t Dqn_Safe_MulI64(int64_t a, int64_t b);
/// Add 2 U64's together, safe asserting that the operation does not overflow. DQN_API uint64_t Dqn_Safe_SubU64 (uint64_t a, uint64_t b);
/// @return The result of operation, UINT64_MAX if it overflowed. DQN_API uint32_t Dqn_Safe_SubU32 (uint32_t a, uint32_t b);
DQN_API uint64_t Dqn_Safe_AddU64(uint64_t a, uint64_t b);
/// Subtract 2 U64's together, safe asserting that the operation does not DQN_API int Dqn_Safe_SaturateCastUSizeToInt (Dqn_usize val);
/// overflow. DQN_API int8_t Dqn_Safe_SaturateCastUSizeToI8 (Dqn_usize val);
/// @return The result of operation, 0 if it overflowed. DQN_API int16_t Dqn_Safe_SaturateCastUSizeToI16 (Dqn_usize val);
DQN_API uint64_t Dqn_Safe_SubU64(uint64_t a, uint64_t b); DQN_API int32_t Dqn_Safe_SaturateCastUSizeToI32 (Dqn_usize val);
DQN_API int64_t Dqn_Safe_SaturateCastUSizeToI64 (Dqn_usize val);
/// Multiple 2 U64's together, safe asserting that the operation does not DQN_API unsigned int Dqn_Safe_SaturateCastU64ToUInt (uint64_t val);
/// overflow. DQN_API uint8_t Dqn_Safe_SaturateCastU64ToU8 (uint64_t val);
/// @return The result of operation, UINT64_MAX if it overflowed. DQN_API uint16_t Dqn_Safe_SaturateCastU64ToU16 (uint64_t val);
DQN_API uint64_t Dqn_Safe_MulU64(uint64_t a, uint64_t b); DQN_API uint32_t Dqn_Safe_SaturateCastU64ToU32 (uint64_t val);
/// Subtract 2 U32's together, safe asserting that the operation does not DQN_API uint8_t Dqn_Safe_SaturateCastUSizeToU8 (Dqn_usize val);
/// overflow. DQN_API uint16_t Dqn_Safe_SaturateCastUSizeToU16 (Dqn_usize val);
/// @return The result of operation, 0 if it overflowed. DQN_API uint32_t Dqn_Safe_SaturateCastUSizeToU32 (Dqn_usize val);
DQN_API uint32_t Dqn_Safe_SubU32(uint32_t a, uint32_t b); DQN_API uint64_t Dqn_Safe_SaturateCastUSizeToU64 (Dqn_usize val);
// NOTE: Dqn_Safe_SaturateCastUSizeToI* DQN_API int Dqn_Safe_SaturateCastISizeToInt (Dqn_isize val);
// ----------------------------------------------------------------------------- DQN_API int8_t Dqn_Safe_SaturateCastISizeToI8 (Dqn_isize val);
/// Truncate a usize to int clamping the result to the max value of the desired DQN_API int16_t Dqn_Safe_SaturateCastISizeToI16 (Dqn_isize val);
/// data type. Safe asserts if clamping occurs. DQN_API int32_t Dqn_Safe_SaturateCastISizeToI32 (Dqn_isize val);
/// @return The truncated value or INT_MAX if the value would go out of the DQN_API int64_t Dqn_Safe_SaturateCastISizeToI64 (Dqn_isize val);
/// valid range when casted.
DQN_API int Dqn_Safe_SaturateCastUSizeToInt(Dqn_usize val);
/// Truncate a usize to I8 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT8_MAX if the value would go out of the
/// valid range when casted.
DQN_API int8_t Dqn_Safe_SaturateCastUSizeToI8(Dqn_usize val);
/// Truncate a usize to I16 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT16_MAX if the value would go out of the
/// valid range when casted.
DQN_API int16_t Dqn_Safe_SaturateCastUSizeToI16(Dqn_usize val);
/// Truncate a usize to I32 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT32_MAX if the value would go out of the
/// valid range when casted.
DQN_API int32_t Dqn_Safe_SaturateCastUSizeToI32(Dqn_usize val);
/// Truncate a usize to I64 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT64_MAX if the value would go out of the
/// valid range when casted.
DQN_API int64_t Dqn_Safe_SaturateCastUSizeToI64(Dqn_usize val);
// NOTE: Dqn_Safe_SaturateCastU64ToU*
// -----------------------------------------------------------------------------
/// Truncate a u64 to uint clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or UINT_MAX if the value would go out of the
/// valid range when casted.
DQN_API unsigned int Dqn_Safe_SaturateCastU64ToUInt(uint64_t val);
/// Truncate a u64 to u8 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or UINT8_MAX if the value would go out of the
/// valid range when casted.
DQN_API uint8_t Dqn_Safe_SaturateCastU64ToU8(uint64_t val);
/// Truncate a u64 to u16 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or UINT16_MAX if the value would go out of the
/// valid range when casted.
DQN_API uint16_t Dqn_Safe_SaturateCastU64ToU16(uint64_t val);
/// Truncate a u64 to u32 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or UINT32_MAX if the value would go out of the
/// valid range when casted.
DQN_API uint32_t Dqn_Safe_SaturateCastU64ToU32(uint64_t val);
// NOTE: Dqn_Safe_SaturateCastUSizeToU*
// -----------------------------------------------------------------------------
/// Truncate a usize to U8 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or UINT8_MAX if the value would go out of the
/// valid range when casted.
DQN_API uint8_t Dqn_Safe_SaturateCastUSizeToU8(Dqn_usize val);
/// Truncate a usize to U16 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or UINT16_MAX if the value would go out of the
/// valid range when casted.
DQN_API uint16_t Dqn_Safe_SaturateCastUSizeToU16(Dqn_usize val);
/// Truncate a usize to U32 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or UINT32_MAX if the value would go out of the
/// valid range when casted.
DQN_API uint32_t Dqn_Safe_SaturateCastUSizeToU32(Dqn_usize val);
/// Truncate a usize to U64 clamping the result to the max value of the desired
/// data type. Safe asserts if clamping occurs.
/// @return The truncated value or UINT64_MAX if the value would go out of the
/// valid range when casted.
DQN_API uint64_t Dqn_Safe_SaturateCastUSizeToU64(Dqn_usize val);
// NOTE: Dqn_Safe_SaturateCastISizeToI*
// -----------------------------------------------------------------------------
/// Truncate an isize to int clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT_MIN or INT_MAX if the value would go
/// out of the valid range when casted.
DQN_API int Dqn_Safe_SaturateCastISizeToInt(Dqn_isize val);
/// Truncate an isize to I8 clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT8_MIN or INT8_MAX if the value would go
/// out of the valid range when casted.
DQN_API int8_t Dqn_Safe_SaturateCastISizeToI8(Dqn_isize val);
/// Truncate an isize to I16 clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT16_MIN or INT16_MAX if the value would go
/// out of the valid range when casted.
DQN_API int16_t Dqn_Safe_SaturateCastISizeToI16(Dqn_isize val);
/// Truncate an isize to I32 clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT32_MIN or INT32_MAX if the value would go
/// out of the valid range when casted.
DQN_API int32_t Dqn_Safe_SaturateCastISizeToI32(Dqn_isize val);
/// Truncate an isize to I64 clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT64_MIN or INT64_MAX if the value would go
/// out of the valid range when casted.
DQN_API int64_t Dqn_Safe_SaturateCastISizeToI64(Dqn_isize val);
// NOTE: Dqn_Safe_SaturateCastISizeToU*
// -----------------------------------------------------------------------------
/// Truncate an isize to uint clamping the result to 0 and the max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or 0 or UINT_MAX if the value would go
/// out of the valid range when casted.
DQN_API unsigned int Dqn_Safe_SaturateCastISizeToUInt(Dqn_isize val); DQN_API unsigned int Dqn_Safe_SaturateCastISizeToUInt(Dqn_isize val);
DQN_API uint8_t Dqn_Safe_SaturateCastISizeToU8 (Dqn_isize val);
DQN_API uint16_t Dqn_Safe_SaturateCastISizeToU16 (Dqn_isize val);
DQN_API uint32_t Dqn_Safe_SaturateCastISizeToU32 (Dqn_isize val);
DQN_API uint64_t Dqn_Safe_SaturateCastISizeToU64 (Dqn_isize val);
/// Truncate an isize to U8 clamping the result to 0 and the max value of the DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToISize (int64_t val);
/// desired data type. Safe asserts if clamping occurs. DQN_API int8_t Dqn_Safe_SaturateCastI64ToI8 (int64_t val);
/// @return The truncated value or 0 or UINT8_MAX if the value would go DQN_API int16_t Dqn_Safe_SaturateCastI64ToI16 (int64_t val);
/// out of the valid range when casted. DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32 (int64_t val);
DQN_API uint8_t Dqn_Safe_SaturateCastISizeToU8(Dqn_isize val);
/// Truncate an isize to U16 clamping the result to 0 and the max value of the DQN_API int8_t Dqn_Safe_SaturateCastIntToI8 (int val);
/// desired data type. Safe asserts if clamping occurs. DQN_API int16_t Dqn_Safe_SaturateCastIntToI16 (int val);
/// @return The truncated value or 0 or UINT16_MAX if the value would go DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8 (int val);
/// out of the valid range when casted. DQN_API uint16_t Dqn_Safe_SaturateCastIntToU16 (int val);
DQN_API uint16_t Dqn_Safe_SaturateCastISizeToU16(Dqn_isize val); DQN_API uint32_t Dqn_Safe_SaturateCastIntToU32 (int val);
DQN_API uint64_t Dqn_Safe_SaturateCastIntToU64 (int val);
/// Truncate an isize to U32 clamping the result to 0 and the max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or 0 or UINT32_MAX if the value would go
/// out of the valid range when casted.
DQN_API uint32_t Dqn_Safe_SaturateCastISizeToU32(Dqn_isize val);
/// Truncate an isize to U64 clamping the result to 0 and the max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or 0 or UINT64_MAX if the value would go
/// out of the valid range when casted.
DQN_API uint64_t Dqn_Safe_SaturateCastISizeToU64(Dqn_isize val);
// NOTE: Dqn_Safe_SaturateCastI64To*
// -----------------------------------------------------------------------------
/// Truncate an I64 to isize clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or DQN_ISIZE_MIN or DQN_ISIZE_MAX if the value
/// would go out of the valid range when casted.
DQN_API Dqn_isize Dqn_Safe_SaturateCastI64ToISize(Dqn_isize val);
/// Truncate an I64 to I8 clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT8_MIN or INT8_MAX if the value would go
/// out of the valid range when casted.
DQN_API int8_t Dqn_Safe_SaturateCastI64ToI8(int64_t val);
/// Truncate an I64 to I16 clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT16_MIN or INT16_MAX if the value would go
/// out of the valid range when casted.
DQN_API int16_t Dqn_Safe_SaturateCastI64ToI16(int64_t val);
/// Truncate an I64 to I32 clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT32_MIN or INT32_MAX if the value would go
/// out of the valid range when casted.
DQN_API int32_t Dqn_Safe_SaturateCastI64ToI32(int64_t val);
// NOTE: Dqn_Safe_SaturateCastIntTo*
// -----------------------------------------------------------------------------
/// Truncate an int to I8 clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT8_MIN or INT8_MAX if the value
/// would go out of the valid range when casted.
DQN_API int8_t Dqn_Safe_SaturateCastIntToI8(int val);
/// Truncate an int to I16 clamping the result to the min and max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or INT16_MIN or INT16_MAX if the value
/// would go out of the valid range when casted.
DQN_API int16_t Dqn_Safe_SaturateCastIntToI16(int val);
/// Truncate an int to U8 clamping the result to 0 and the max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or 0 or UINT8_MAX if the value would go
/// out of the valid range when casted.
DQN_API uint8_t Dqn_Safe_SaturateCastIntToU8(int val);
/// Truncate an int to U16 clamping the result to 0 and the max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or 0 or UINT16_MAX if the value would go
/// out of the valid range when casted.
DQN_API uint16_t Dqn_Safe_SaturateCastIntToU16(int val);
/// Truncate an int to U32 clamping the result to 0 and the max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or 0 or UINT32_MAX if the value would go
/// out of the valid range when casted.
DQN_API uint32_t Dqn_Safe_SaturateCastIntToU32(int val);
/// Truncate an int to U64 clamping the result to 0 and the max value of the
/// desired data type. Safe asserts if clamping occurs.
/// @return The truncated value or 0 or UINT64_MAX if the value would go
/// out of the valid range when casted.
DQN_API uint64_t Dqn_Safe_SaturateCastIntToU64(int val);
// NOTE: [$TCTX] Dqn_ThreadContext ================================================================= // NOTE: [$TCTX] Dqn_ThreadContext =================================================================
// Each thread is assigned in their thread-local storage (TLS) scratch and // Each thread is assigned in their thread-local storage (TLS) scratch and

View File

@ -924,16 +924,16 @@ DQN_API Dqn_FsFile Dqn_Fs_OpenFile(Dqn_String8 path, Dqn_FsFileOpen open_mode, u
if (handle == INVALID_HANDLE_VALUE) { if (handle == INVALID_HANDLE_VALUE) {
Dqn_WinErrorMsg msg = Dqn_Win_LastError(); Dqn_WinErrorMsg msg = Dqn_Win_LastError();
result.error_size = result.error_size =
DQN_CAST(uint16_t) Dqn_SNPrintF2DotsOnOverflow(result.error, DQN_CAST(uint16_t) Dqn_SNPrintFDotTruncate(result.error,
DQN_ARRAY_UCOUNT(result.error), DQN_ARRAY_UCOUNT(result.error),
"Open file failed: %.*s for \"%.*s\"", "Open file failed: %.*s for \"%.*s\"",
DQN_STRING_FMT(msg), DQN_STRING_FMT(msg),
DQN_STRING_FMT(path)); DQN_STRING_FMT(path));
return result; return result;
} }
#else #else
if (access & Dqn_FsFileAccess_Execute) { if (access & Dqn_FsFileAccess_Execute) {
result.error_size = DQN_CAST(uint16_t) Dqn_SNPrintF2DotsOnOverflow( result.error_size = DQN_CAST(uint16_t) Dqn_SNPrintFDotTruncate(
result.error, result.error,
DQN_ARRAY_UCOUNT(result.error), DQN_ARRAY_UCOUNT(result.error),
"Open file failed: execute access not supported for \"%.*s\"", "Open file failed: execute access not supported for \"%.*s\"",
@ -1008,10 +1008,10 @@ DQN_API bool Dqn_Fs_WriteFile(Dqn_FsFile *file, char const *buffer, Dqn_usize si
if (!result) { if (!result) {
Dqn_WinErrorMsg msg = Dqn_Win_LastError(); Dqn_WinErrorMsg msg = Dqn_Win_LastError();
file->error_size = file->error_size =
DQN_CAST(uint16_t) Dqn_SNPrintF2DotsOnOverflow(file->error, DQN_CAST(uint16_t) Dqn_SNPrintFDotTruncate(file->error,
DQN_ARRAY_UCOUNT(file->error), DQN_ARRAY_UCOUNT(file->error),
"Write file failed: %.*s for %.*s", "Write file failed: %.*s for %.*s",
DQN_STRING_FMT(msg)); DQN_STRING_FMT(msg));
} }
#else #else
result = fwrite(buffer, DQN_CAST(Dqn_usize)size, 1 /*count*/, file->handle) == 1 /*count*/; result = fwrite(buffer, DQN_CAST(Dqn_usize)size, 1 /*count*/, file->handle) == 1 /*count*/;

View File

@ -10,6 +10,15 @@
// ================================================================================================= // =================================================================================================
// NOTE: [$FSYS] Dqn_Fs ============================================================================ // NOTE: [$FSYS] Dqn_Fs ============================================================================
// NOTE: FS Manipulation =======================================================
// TODO(dqn): We should have a Dqn_String8 interface and a CString interface
//
// NOTE: API ===================================================================
// @proc Dqn_FsDelete
// @desc Delete the item specified at the path. This function *CAN* not delete directories unless
// the directory is empty.
// @return True if deletion was successful, false otherwise
enum Dqn_FsInfoType enum Dqn_FsInfoType
{ {
Dqn_FsInfoType_Unknown, Dqn_FsInfoType_Unknown,
@ -27,45 +36,43 @@ struct Dqn_FsInfo
uint64_t size; uint64_t size;
}; };
// NOTE: File System API DQN_API bool Dqn_Fs_Exists (Dqn_String8 path);
// ============================================================================= DQN_API bool Dqn_Fs_DirExists(Dqn_String8 path);
// TODO(dqn): We should have a Dqn_String8 interface and a CString interface DQN_API Dqn_FsInfo Dqn_Fs_GetInfo (Dqn_String8 path);
DQN_API bool Dqn_Fs_Exists(Dqn_String8 path); DQN_API bool Dqn_Fs_Copy (Dqn_String8 src, Dqn_String8 dest, bool overwrite);
DQN_API bool Dqn_Fs_DirExists(Dqn_String8 path); DQN_API bool Dqn_Fs_MakeDir (Dqn_String8 path);
DQN_API Dqn_FsInfo Dqn_Fs_GetInfo(Dqn_String8 path); DQN_API bool Dqn_Fs_Move (Dqn_String8 src, Dqn_String8 dest, bool overwrite);
DQN_API bool Dqn_Fs_Copy(Dqn_String8 src, Dqn_String8 dest, bool overwrite); DQN_API bool Dqn_Fs_Delete (Dqn_String8 path);
DQN_API bool Dqn_Fs_MakeDir(Dqn_String8 path); // NOTE: R/W Entire File ===========================================================================
DQN_API bool Dqn_Fs_Move(Dqn_String8 src, Dqn_String8 dest, bool overwrite); // NOTE: API =======================================================================================
// @proc Dqn_Fs_WriteString8, Dqn_Fs_WriteCString8
// @desc Write the string to a file at the path overwriting if necessary.
// TODO(dqn): This doesn't work on directories unless you delete the files // @proc Dqn_Fs_ReadString8, Dqn_Fs_ReadCString8
// in that directory first. // @desc Read the file at the path to a string.
DQN_API bool Dqn_Fs_Delete(Dqn_String8 path);
// NOTE: Read/Write Entire File API
// =============================================================================
// file_size: (Optional) The size of the file in bytes, the allocated buffer is (file_size + 1 [null terminator]) in bytes.
DQN_API bool Dqn_Fs_WriteCString8(char const *file_path, Dqn_usize file_path_size, char const *buffer, Dqn_usize buffer_size);
DQN_API bool Dqn_Fs_WriteString8(Dqn_String8 file_path, Dqn_String8 buffer);
/// Read a file at the specified path into memory.
/// @param[in] path Path to the file to read
/// @param[in] path_size The string size of the file path
/// @param[out] file_size (Optional) Pass a pointer to receive the number of bytes read
/// @param[in] allocator Allocator used to read the file to memory with
/// @return A cstring with the read file, null pointer on failure.
#define Dqn_Fs_ReadCString8(path, path_size, file_size, allocator) Dqn_Fs_ReadCString8_(DQN_LEAK_TRACE path, path_size, file_size, allocator) #define Dqn_Fs_ReadCString8(path, path_size, file_size, allocator) Dqn_Fs_ReadCString8_(DQN_LEAK_TRACE path, path_size, file_size, allocator)
DQN_API char *Dqn_Fs_ReadCString8_(DQN_LEAK_TRACE_FUNCTION char const *path, Dqn_usize path_size, Dqn_usize *file_size, Dqn_Allocator allocator);
/// Read a file at the specified path into memory.
/// @param[in] file_path Path to the file to read
/// @param[in] allocator Allocator used to read the file to memory with
/// @return A string with the read file, invalid string on failure.
#define Dqn_Fs_ReadString8(path, allocator) Dqn_Fs_ReadString8_(DQN_LEAK_TRACE path, allocator) #define Dqn_Fs_ReadString8(path, allocator) Dqn_Fs_ReadString8_(DQN_LEAK_TRACE path, allocator)
DQN_API Dqn_String8 Dqn_Fs_ReadString8_(DQN_LEAK_TRACE_FUNCTION Dqn_String8 path, Dqn_Allocator allocator);
// NOTE: Read/Write File Stream API DQN_API bool Dqn_Fs_WriteCString8(char const *file_path, Dqn_usize file_path_size, char const *buffer, Dqn_usize buffer_size);
// ============================================================================= DQN_API bool Dqn_Fs_WriteString8 (Dqn_String8 file_path, Dqn_String8 buffer);
// NOTE: Internal ==================================================================================
DQN_API char *Dqn_Fs_ReadCString8_(DQN_LEAK_TRACE_FUNCTION char const *path, Dqn_usize path_size, Dqn_usize *file_size, Dqn_Allocator allocator);
DQN_API Dqn_String8 Dqn_Fs_ReadString8_ (DQN_LEAK_TRACE_FUNCTION Dqn_String8 path, Dqn_Allocator allocator);
// NOTE: R/W Stream API ============================================================================
// NOTE: API =======================================================================================
// @proc Dqn_Fs_OpenFile
// @desc Open a handle to the file
// @proc Dqn_Fs_WriteFile
// @desc Append to the file specified by the handle with the given buffer.
// @proc Dqn_Fs_CloseFile
// @desc Close the file at specified by the handle
struct Dqn_FsFile struct Dqn_FsFile
{ {
void *handle; void *handle;
@ -90,12 +97,35 @@ enum Dqn_FsFileAccess
Dqn_FsFileAccess_All = Dqn_FsFileAccess_ReadWrite | Dqn_FsFileAccess_Execute, Dqn_FsFileAccess_All = Dqn_FsFileAccess_ReadWrite | Dqn_FsFileAccess_Execute,
}; };
DQN_API Dqn_FsFile Dqn_Fs_OpenFile(Dqn_String8 path, Dqn_FsFileOpen open_mode, uint32_t access); DQN_API Dqn_FsFile Dqn_Fs_OpenFile (Dqn_String8 path, Dqn_FsFileOpen open_mode, uint32_t access);
DQN_API bool Dqn_Fs_WriteFile(Dqn_FsFile *file, char const *buffer, Dqn_usize size); DQN_API bool Dqn_Fs_WriteFile(Dqn_FsFile *file, char const *buffer, Dqn_usize size);
DQN_API void Dqn_Fs_CloseFile(Dqn_FsFile *file); DQN_API void Dqn_Fs_CloseFile(Dqn_FsFile *file);
// NOTE: File system paths =========================================================================
// Helper data structure for building paths suitable for OS consumption.
//
// NOTE: API =======================================================================================
// @proc Dqn_FsPath_AddRef, Dqn_FsPath_Add
// @desc Append a path to the file path. The passed in path can be specify
// both a single level or multiple directories with different path separators.
// The path will be decomposed into individual sections in the function.
//
// For example passing
// - "path/to/your/desired/folder" is valid
// - "path" is valid
// - "path/to\your/desired\folder" is valid
// @proc Dqn_FsPath_Pop
// @desc Remove the last appended path level from the current path stored in
// the FsPath.
//
// For example "path/to/your/desired/folder" popped produces
// "path/to/your/desired"
// @proc Dqn_FsPath_ConvertString8
// @desc Convert the path specified in the string to the OS native separated
// path.
// NOTE: Filesystem paths
// =============================================================================
#if !defined(Dqn_FsPathOSSeperator) #if !defined(Dqn_FsPathOSSeperator)
#if defined(DQN_OS_WIN32) #if defined(DQN_OS_WIN32)
#define Dqn_FsPathOSSeperator "\\" #define Dqn_FsPathOSSeperator "\\"
@ -125,7 +155,6 @@ DQN_API bool Dqn_FsPath_Add (Dqn_Arena *arena, Dqn_FsPath *
DQN_API bool Dqn_FsPath_Pop (Dqn_FsPath *fs_path); DQN_API bool Dqn_FsPath_Pop (Dqn_FsPath *fs_path);
DQN_API Dqn_String8 Dqn_FsPath_BuildWithSeparator(Dqn_Arena *arena, Dqn_FsPath const *fs_path, Dqn_String8 path_separator); DQN_API Dqn_String8 Dqn_FsPath_BuildWithSeparator(Dqn_Arena *arena, Dqn_FsPath const *fs_path, Dqn_String8 path_separator);
DQN_API Dqn_String8 Dqn_FsPath_ConvertString8 (Dqn_Arena *arena, Dqn_String8 path); DQN_API Dqn_String8 Dqn_FsPath_ConvertString8 (Dqn_Arena *arena, Dqn_String8 path);
#define Dqn_FsPath_BuildFwdSlash(arena, fs_path) Dqn_FsPath_BuildWithSeparator(arena, fs_path, DQN_STRING8("/")) #define Dqn_FsPath_BuildFwdSlash(arena, fs_path) Dqn_FsPath_BuildWithSeparator(arena, fs_path, DQN_STRING8("/"))
#define Dqn_FsPath_BuildBackSlash(arena, fs_path) Dqn_FsPath_BuildWithSeparator(arena, fs_path, DQN_STRING8("\\")) #define Dqn_FsPath_BuildBackSlash(arena, fs_path) Dqn_FsPath_BuildWithSeparator(arena, fs_path, DQN_STRING8("\\"))
@ -138,6 +167,11 @@ DQN_API Dqn_String8 Dqn_FsPath_ConvertString8 (Dqn_Arena *arena, Dqn_String8
#endif #endif
// NOTE: [$DATE] Dqn_Date ========================================================================== // NOTE: [$DATE] Dqn_Date ==========================================================================
// NOTE: API =======================================================================================
// @proc Dqn_Date_EpochTime
// @desc Produce the time elapsed since the Unix epoch
// (e.g. 1970-01-01T00:00:00Z) in seconds
struct Dqn_DateHMSTimeString struct Dqn_DateHMSTimeString
{ {
char date[DQN_ARRAY_UCOUNT("YYYY-MM-SS")]; char date[DQN_ARRAY_UCOUNT("YYYY-MM-SS")];
@ -158,13 +192,10 @@ struct Dqn_DateHMSTime
uint8_t seconds; uint8_t seconds;
}; };
// @return The current time at the point of invocation DQN_API Dqn_DateHMSTime Dqn_Date_HMSLocalTimeNow ();
DQN_API Dqn_DateHMSTime Dqn_Date_HMSLocalTimeNow();
DQN_API Dqn_DateHMSTimeString Dqn_Date_HMSLocalTimeStringNow(char date_separator = '-', char hms_separator = ':'); DQN_API Dqn_DateHMSTimeString Dqn_Date_HMSLocalTimeStringNow(char date_separator = '-', char hms_separator = ':');
DQN_API Dqn_DateHMSTimeString Dqn_Date_HMSLocalTimeString(Dqn_DateHMSTime time, char date_separator = '-', char hms_separator = ':'); DQN_API Dqn_DateHMSTimeString Dqn_Date_HMSLocalTimeString (Dqn_DateHMSTime time, char date_separator = '-', char hms_separator = ':');
DQN_API uint64_t Dqn_Date_EpochTime ();
// return: The time elapsed since Unix epoch (1970-01-01T00:00:00Z) in seconds
DQN_API uint64_t Dqn_Date_EpochTime();
// NOTE: [$W32H] Win32 Min Header ================================================================== // NOTE: [$W32H] Win32 Min Header ==================================================================
#if defined(DQN_OS_WIN32) #if defined(DQN_OS_WIN32)
@ -192,71 +223,70 @@ DQN_API uint64_t Dqn_Date_EpochTime();
#endif // !defined(DQN_NO_WIN32_MIN_HEADER) && !defined(_INC_WINDOWS) #endif // !defined(DQN_NO_WIN32_MIN_HEADER) && !defined(_INC_WINDOWS)
// NOTE: [$WIND] Dqn_Win =========================================================================== // NOTE: [$WIND] Dqn_Win ===========================================================================
// NOTE: API =======================================================================================
// @proc Dqn_Win_LastErrorToBuffer, Dqn_Win_LastError
// @desc Retrieve the latest error code and message Windows produced for the
// most recent Win32 API call.
// @proc Dqn_Win_MakeProcessDPIAware
// @desc Call once at application start-up to ensure that the application is
// DPI aware on Windows and ensure that application UI is scaled up
// appropriately for the monitor.
struct Dqn_WinErrorMsg struct Dqn_WinErrorMsg
{ {
unsigned long code; unsigned long code;
char data[DQN_KILOBYTES(64) - 1]; // Maximum error size char data[DQN_KILOBYTES(64) - 1]; // Maximum error size
unsigned long size; unsigned long size;
}; };
DQN_API void Dqn_Win_LastErrorToBuffer(Dqn_WinErrorMsg *msg); DQN_API void Dqn_Win_LastErrorToBuffer(Dqn_WinErrorMsg *msg);
DQN_API Dqn_WinErrorMsg Dqn_Win_LastError(); DQN_API Dqn_WinErrorMsg Dqn_Win_LastError();
DQN_API void Dqn_Win_MakeProcessDPIAware();
/// Call once at application start-up to ensure that the application is DPI // NOTE: Windows String8 <-> String16 ===========================================
/// aware on Windows and ensure that application UI is scaled up appropriately // Convert a UTF8 <-> UTF16 string.
/// for the monitor. //
DQN_API void Dqn_Win_MakeProcessDPIAware(); // The exact size buffer required for this function can be determined by
// calling this function with the 'dest' set to null and 'dest_size' set to 0,
// the return size is the size required for conversion not-including space for
// the null-terminator. This function *always* null-terminates the input
// buffer.
//
// Returns the number of u8's (for UTF16->8) OR u16's (for UTF8->16)
// written/required for conversion. 0 if there was a conversion error and can be
// queried using 'Dqn_Win_LastError'
// NOTE: Windows String8 To String16 DQN_API int Dqn_Win_CString8ToCString16 (char const *src, int src_size, wchar_t *dest, int dest_size);
// ----------------------------------------------------------------------------- DQN_API int Dqn_Win_String8ToCString16 (Dqn_String8 src, wchar_t *dest, int dest_size);
/// Convert a UTF8 to UTF16 string. DQN_API Dqn_String16 Dqn_Win_String8ToString16Allocator (Dqn_String8 src, Dqn_Allocator allocator);
///
/// The exact size buffer required for this function can be determined by
/// calling this function with the 'dest' set to null and 'dest_size' set to 0,
/// the return size is the size required for conversion not-including space for
/// the null-terminator. This function *always* null-terminates the input
/// buffer.
///
/// @return The number of u16's written/required for conversion. 0 if there was
/// a conversion error and can be queried using 'Dqn_Win_LastError'
DQN_API int Dqn_Win_CString8ToCString16(const char *src, int src_size, wchar_t *dest, int dest_size);
DQN_API int Dqn_Win_String8ToCString16(Dqn_String8 src, wchar_t *dest, int dest_size);
DQN_API Dqn_String16 Dqn_Win_String8ToString16Allocator(Dqn_String8 src, Dqn_Allocator allocator);
// NOTE: Windows String16 To String8 DQN_API int Dqn_Win_CString16ToCString8 (wchar_t const *src, int src_size, char *dest, int dest_size);
// ----------------------------------------------------------------------------- DQN_API Dqn_String8 Dqn_Win_CString16ToString8Allocator(wchar_t const *src, int src_size, Dqn_Allocator allocator);
/// Convert a UTF16 to UTF8 string. DQN_API int Dqn_Win_String16ToCString8 (Dqn_String16 src, char *dest, int dest_size);
/// DQN_API Dqn_String8 Dqn_Win_String16ToString8Allocator (Dqn_String16 src, Dqn_Allocator allocator);
/// The exact size buffer required for this function can be determined by
/// calling this function with the 'dest' set to null and 'dest_size' set to 0,
/// the return size is the size required for conversion not-including space for
/// the null-terminator. This function *always* null-terminates the input
/// buffer.
///
/// @return The number of u8's written/required for conversion. 0 if there was
/// a conversion error and can be queried using 'Dqn_Win_LastError'
DQN_API int Dqn_Win_CString16ToCString8(const wchar_t *src, int src_size, char *dest, int dest_size);
DQN_API Dqn_String8 Dqn_Win_CString16ToString8Allocator(const wchar_t *src, int src_size, Dqn_Allocator allocator);
DQN_API int Dqn_Win_String16ToCString8(Dqn_String16 src, char *dest, int dest_size);
DQN_API Dqn_String8 Dqn_Win_String16ToString8Allocator(Dqn_String16 src, Dqn_Allocator allocator);
// NOTE: Windows Executable Directory // NOTE: Path navigatoin ===========================================================================
// ----------------------------------------------------------------------------- // NOTE: API =======================================================================================
/// Evaluate the current executable's directory that is running when this // @proc Dqn_Win_EXEDirW, Dqn_Win_EXEDirWArena
/// function is called. // @desc Evaluate the current executable's directory that is running when this
/// @param[out] buffer The buffer to write the executable directory into. Set // function is called.
/// this to null to calculate the required buffer size for the directory. // @param[out] buffer The buffer to write the executable directory into. Set
/// @param[in] size The size of the buffer given. Set this to 0 to calculate the // this to null to calculate the required buffer size for the directory.
/// required buffer size for the directory. // @param[in] size The size of the buffer given. Set this to 0 to calculate the
/// @return The length of the executable directory string. If this return value // required buffer size for the directory.
/// exceeds the capacity of the 'buffer', the 'buffer' is untouched. // @return The length of the executable directory string. If this return value
DQN_API Dqn_usize Dqn_Win_EXEDirW(wchar_t *buffer, Dqn_usize size); // exceeds the capacity of the 'buffer', the 'buffer' is untouched.
DQN_API Dqn_String16 Dqn_Win_EXEDirWArena(Dqn_Arena *arena);
// @param[in] size (Optional) The size of the current directory string returned // @proc Dqn_Win_WorkingDir, Dqn_Win_WorkingDirW
// @param[in] suffix (Optional) A suffix to append to the current working directory // @param[in] suffix (Optional) A suffix to append to the current working directory
// @param[in] suffix_size (Optional) The size of the suffix to append
DQN_API Dqn_String8 Dqn_Win_WorkingDir(Dqn_Allocator allocator, Dqn_String8 suffix); // @proc Dqn_Win_FolderIterate, Dqn_Win_FolderWIterate
DQN_API Dqn_String16 Dqn_Win_WorkingDirW(Dqn_Allocator allocator, Dqn_String16 suffix); // @desc Iterate the files in the specified folder at the path
#if 0
for (Dqn_WinFolderIterator it = {}; Dqn_Win_FolderIterate("C:/your/path/", &it); ) {
printf("%.*s\n", DQN_STRING_FMT(it.file_name));
}
#endif
struct Dqn_Win_FolderIteratorW struct Dqn_Win_FolderIteratorW
{ {
@ -272,11 +302,36 @@ struct Dqn_Win_FolderIterator
char file_name_buf[512]; char file_name_buf[512];
}; };
DQN_API bool Dqn_Win_FolderIterate(Dqn_String8 path, Dqn_Win_FolderIterator *it); DQN_API Dqn_usize Dqn_Win_EXEDirW (wchar_t *buffer, Dqn_usize size);
DQN_API bool Dqn_Win_FolderWIterate(Dqn_String16 path, Dqn_Win_FolderIteratorW *it); DQN_API Dqn_String16 Dqn_Win_EXEDirWArena (Dqn_Arena *arena);
DQN_API Dqn_String8 Dqn_Win_WorkingDir (Dqn_Allocator allocator, Dqn_String8 suffix);
DQN_API Dqn_String16 Dqn_Win_WorkingDirW (Dqn_Allocator allocator, Dqn_String16 suffix);
DQN_API bool Dqn_Win_FolderIterate (Dqn_String8 path, Dqn_Win_FolderIterator *it);
DQN_API bool Dqn_Win_FolderWIterate(Dqn_String16 path, Dqn_Win_FolderIteratorW *it);
#if !defined(DQN_NO_WINNET) #if !defined(DQN_NO_WINNET)
// NOTE: [$WINN] Dqn_WinNet ======================================================================== // NOTE: [$WINN] Dqn_WinNet ========================================================================
// TODO(dqn): Useful options to expose in the handle
// https://docs.microsoft.com/en-us/windows/win32/wininet/option-flags
// INTERNET_OPTION_CONNECT_RETRIES -- default is 5 retries
// INTERNET_OPTION_CONNECT_TIMEOUT -- milliseconds
// INTERNET_OPTION_RECEIVE_TIMEOUT
// INTERNET_OPTION_SEND_TIMEOUT
//
// NOTE: API =======================================================================================
// @proc Dqn_Win_NetHandleInitHTTPMethod, Dqn_Win_NetHandleInitHTTPMethodCString
// @desc Setup a handle to the URL with the given HTTP verb.
//
// This function is the same as calling Dqn_Win_NetHandleInit() followed by
// Dqn_Win_NetHandleSetHTTPMethod().
//
// @param http_method The HTTP request type, e.g. "GET" or "POST" e.t.c
// @proc Dqn_Win_NetHandleSetHTTPMethod
// @desc Set the HTTP request method for the given handle. This function can
// be used on a pre-existing valid handle that has at the minimum been
// initialised.
enum Dqn_WinNetHandleState enum Dqn_WinNetHandleState
{ {
Dqn_WinNetHandleState_Invalid, Dqn_WinNetHandleState_Invalid,
@ -324,34 +379,6 @@ struct Dqn_WinNetHandle
Dqn_WinNetHandleState state; Dqn_WinNetHandleState state;
}; };
// TODO(dqn): Useful options to expose in the handle
// https://docs.microsoft.com/en-us/windows/win32/wininet/option-flags
// INTERNET_OPTION_CONNECT_RETRIES -- default is 5 retries
// INTERNET_OPTION_CONNECT_TIMEOUT -- milliseconds
// INTERNET_OPTION_RECEIVE_TIMEOUT
// INTERNET_OPTION_SEND_TIMEOUT
// Setup a handle to the URL with the given HTTP verb.
DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInitCString(char const *url, int url_size);
DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInit(Dqn_String8 url);
// Setup a handle to the URL with the given HTTP verb.
//
// This function is the same as calling Dqn_Win_NetHandleInit() followed by
// Dqn_Win_NetHandleSetHTTPMethod().
//
// @param http_method The HTTP request type, e.g. "GET" or "POST" e.t.c
DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInitHTTPMethodCString(char const *url, int url_size, char const *http_method);
DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInitHTTPMethod(Dqn_String8 url, Dqn_String8 http_method);
DQN_API void Dqn_Win_NetHandleClose(Dqn_WinNetHandle *handle);
DQN_API bool Dqn_Win_NetHandleIsValid(Dqn_WinNetHandle const *handle);
DQN_API void Dqn_Win_NetHandleSetUserAgentCString(Dqn_WinNetHandle *handle, char const *user_agent, int user_agent_size);
// Set the HTTP request method for the given handle. This function can be used
// on a pre-existing valid handle that has at the minimum been initialised.
DQN_API bool Dqn_Win_NetHandleSetHTTPMethod(Dqn_WinNetHandle *handle, char const *method);
enum Dqn_WinNetHandleRequestHeaderFlag enum Dqn_WinNetHandleRequestHeaderFlag
{ {
Dqn_WinNetHandleRequestHeaderFlag_Add, Dqn_WinNetHandleRequestHeaderFlag_Add,
@ -360,9 +387,6 @@ enum Dqn_WinNetHandleRequestHeaderFlag
Dqn_WinNetHandleRequestHeaderFlag_Count, Dqn_WinNetHandleRequestHeaderFlag_Count,
}; };
DQN_API bool Dqn_Win_NetHandleSetRequestHeaderCString8(Dqn_WinNetHandle *handle, char const *header, int header_size, uint32_t mode);
DQN_API bool Dqn_Win_NetHandleSetRequestHeaderString8(Dqn_WinNetHandle *handle, Dqn_String8 header, uint32_t mode);
struct Dqn_WinNetHandleResponse struct Dqn_WinNetHandleResponse
{ {
Dqn_String8 raw_headers; Dqn_String8 raw_headers;
@ -373,33 +397,35 @@ struct Dqn_WinNetHandleResponse
uint64_t content_length; uint64_t content_length;
Dqn_String8 content_type; Dqn_String8 content_type;
}; };
DQN_API Dqn_WinNetHandleResponse Dqn_Win_NetHandleSendRequest(Dqn_WinNetHandle *handle, Dqn_Allocator allocator, char const *post_data, unsigned long post_data_size);
DQN_API bool Dqn_Win_NetHandlePump(Dqn_WinNetHandle *handle, char *dest, int dest_size, size_t *download_size); DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInitCString (char const *url, int url_size);
DQN_API char * Dqn_Win_NetHandlePumpCString8(Dqn_WinNetHandle *handle, Dqn_Arena *arena, size_t *download_size); DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInit (Dqn_String8 url);
DQN_API Dqn_String8 Dqn_Win_NetHandlePumpString8(Dqn_WinNetHandle *handle, Dqn_Arena *arena); DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInitHTTPMethodCString (char const *url, int url_size, char const *http_method);
DQN_API Dqn_WinNetHandle Dqn_Win_NetHandleInitHTTPMethod (Dqn_String8 url, Dqn_String8 http_method);
DQN_API void Dqn_Win_NetHandlePumpToCRTFile(Dqn_WinNetHandle *handle, FILE *file); DQN_API void Dqn_Win_NetHandleClose (Dqn_WinNetHandle *handle);
DQN_API char *Dqn_Win_NetHandlePumpToAllocCString(Dqn_WinNetHandle *handle, size_t *download_size); DQN_API bool Dqn_Win_NetHandleIsValid (Dqn_WinNetHandle const *handle);
DQN_API Dqn_String8 Dqn_Win_NetHandlePumpToAllocString(Dqn_WinNetHandle *handle); DQN_API void Dqn_Win_NetHandleSetUserAgentCString (Dqn_WinNetHandle *handle, char const *user_agent, int user_agent_size);
DQN_API bool Dqn_Win_NetHandleSetHTTPMethod (Dqn_WinNetHandle *handle, char const *method);
DQN_API bool Dqn_Win_NetHandleSetRequestHeaderCString8(Dqn_WinNetHandle *handle, char const *header, int header_size, uint32_t mode);
DQN_API bool Dqn_Win_NetHandleSetRequestHeaderString8 (Dqn_WinNetHandle *handle, Dqn_String8 header, uint32_t mode);
DQN_API Dqn_WinNetHandleResponse Dqn_Win_NetHandleSendRequest (Dqn_WinNetHandle *handle, Dqn_Allocator allocator, char const *post_data, unsigned long post_data_size);
DQN_API bool Dqn_Win_NetHandlePump (Dqn_WinNetHandle *handle, char *dest, int dest_size, size_t *download_size);
DQN_API char * Dqn_Win_NetHandlePumpCString8 (Dqn_WinNetHandle *handle, Dqn_Arena *arena, size_t *download_size);
DQN_API Dqn_String8 Dqn_Win_NetHandlePumpString8 (Dqn_WinNetHandle *handle, Dqn_Arena *arena);
DQN_API void Dqn_Win_NetHandlePumpToCRTFile (Dqn_WinNetHandle *handle, FILE *file);
DQN_API char * Dqn_Win_NetHandlePumpToAllocCString (Dqn_WinNetHandle *handle, size_t *download_size);
DQN_API Dqn_String8 Dqn_Win_NetHandlePumpToAllocString (Dqn_WinNetHandle *handle);
#endif // !defined(DQN_NO_WINNET) #endif // !defined(DQN_NO_WINNET)
#endif // defined(DQN_OS_WIN32) #endif // defined(DQN_OS_WIN32)
// NOTE: [$OSYS] Dqn_OS ============================================================================ // NOTE: [$OSYS] Dqn_OS ============================================================================
/// Generate cryptographically secure bytes // NOTE: API =======================================================================================
DQN_API bool Dqn_OS_SecureRNGBytes(void *buffer, uint32_t size); // @proc Dqn_OS_SecureRNGBytes
// @desc Generate cryptographically secure bytes
// return: The directory without the trailing '/' or ('\' for windows). Empty // @proc Dqn_OS_EXEDir
// string with a nullptr if it fails. // @desc Retrieve the executable directory without the trailing '/' or
DQN_API Dqn_String8 Dqn_OS_EXEDir(Dqn_Allocator allocator); // ('\' for windows). If this fails an empty string is returned.
DQN_API void Dqn_OS_SleepMs(Dqn_uint milliseconds);
DQN_API uint64_t Dqn_OS_PerfCounterNow ();
DQN_API Dqn_f64 Dqn_OS_PerfCounterS (uint64_t begin, uint64_t end);
DQN_API Dqn_f64 Dqn_OS_PerfCounterMs (uint64_t begin, uint64_t end);
DQN_API Dqn_f64 Dqn_OS_PerfCounterMicroS(uint64_t begin, uint64_t end);
DQN_API Dqn_f64 Dqn_OS_PerfCounterNs (uint64_t begin, uint64_t end);
/// Record time between two time-points using the OS's performance counter. /// Record time between two time-points using the OS's performance counter.
struct Dqn_OSTimer struct Dqn_OSTimer
@ -408,12 +434,20 @@ struct Dqn_OSTimer
uint64_t end; uint64_t end;
}; };
DQN_API Dqn_OSTimer Dqn_OS_TimerBegin(); DQN_API bool Dqn_OS_SecureRNGBytes (void *buffer, uint32_t size);
DQN_API void Dqn_OS_TimerEnd (Dqn_OSTimer *timer); DQN_API Dqn_String8 Dqn_OS_EXEDir (Dqn_Allocator allocator);
DQN_API Dqn_f64 Dqn_OS_TimerS (Dqn_OSTimer timer); DQN_API void Dqn_OS_SleepMs (Dqn_uint milliseconds);
DQN_API Dqn_f64 Dqn_OS_TimerMs (Dqn_OSTimer timer); DQN_API uint64_t Dqn_OS_PerfCounterNow ();
DQN_API Dqn_f64 Dqn_OS_TimerMicroS (Dqn_OSTimer timer); DQN_API Dqn_f64 Dqn_OS_PerfCounterS (uint64_t begin, uint64_t end);
DQN_API Dqn_f64 Dqn_OS_TimerNs (Dqn_OSTimer timer); DQN_API Dqn_f64 Dqn_OS_PerfCounterMs (uint64_t begin, uint64_t end);
DQN_API Dqn_f64 Dqn_OS_PerfCounterMicroS(uint64_t begin, uint64_t end);
DQN_API Dqn_f64 Dqn_OS_PerfCounterNs (uint64_t begin, uint64_t end);
DQN_API Dqn_OSTimer Dqn_OS_TimerBegin ();
DQN_API void Dqn_OS_TimerEnd (Dqn_OSTimer *timer);
DQN_API Dqn_f64 Dqn_OS_TimerS (Dqn_OSTimer timer);
DQN_API Dqn_f64 Dqn_OS_TimerMs (Dqn_OSTimer timer);
DQN_API Dqn_f64 Dqn_OS_TimerMicroS (Dqn_OSTimer timer);
DQN_API Dqn_f64 Dqn_OS_TimerNs (Dqn_OSTimer timer);
// OS_TimedBlock provides a extremely primitive way of measuring the duration of // OS_TimedBlock provides a extremely primitive way of measuring the duration of
// code blocks, by sprinkling DQN_OS_TIMED_BLOCK_RECORD("record label"), you can // code blocks, by sprinkling DQN_OS_TIMED_BLOCK_RECORD("record label"), you can

View File

@ -589,7 +589,7 @@ DQN_API Dqn_String8 Dqn_String8_Copy_(DQN_LEAK_TRACE_FUNCTION Dqn_Allocator allo
} }
// NOTE: [$STRB] Dqn_String8Builder ================================================================ // NOTE: [$STRB] Dqn_String8Builder ================================================================
bool Dqn_String8Builder_AppendRef(Dqn_String8Builder *builder, Dqn_String8 string) DQN_API bool Dqn_String8Builder_AppendRef(Dqn_String8Builder *builder, Dqn_String8 string)
{ {
if (!builder || !string.data || string.size <= 0) if (!builder || !string.data || string.size <= 0)
return false; return false;
@ -612,14 +612,14 @@ bool Dqn_String8Builder_AppendRef(Dqn_String8Builder *builder, Dqn_String8 strin
return true; return true;
} }
bool Dqn_String8Builder_AppendCopy(Dqn_String8Builder *builder, Dqn_String8 string) DQN_API bool Dqn_String8Builder_AppendCopy(Dqn_String8Builder *builder, Dqn_String8 string)
{ {
Dqn_String8 copy = Dqn_String8_Copy(builder->allocator, string); Dqn_String8 copy = Dqn_String8_Copy(builder->allocator, string);
bool result = Dqn_String8Builder_AppendRef(builder, copy); bool result = Dqn_String8Builder_AppendRef(builder, copy);
return result; return result;
} }
bool Dqn_String8Builder_AppendFV_(DQN_LEAK_TRACE_FUNCTION Dqn_String8Builder *builder, char const *fmt, va_list args) DQN_API bool Dqn_String8Builder_AppendFV_(DQN_LEAK_TRACE_FUNCTION Dqn_String8Builder *builder, char const *fmt, va_list args)
{ {
Dqn_String8 string = Dqn_String8_InitFV(builder->allocator, fmt, args); Dqn_String8 string = Dqn_String8_InitFV(builder->allocator, fmt, args);
if (string.size == 0) if (string.size == 0)
@ -631,7 +631,7 @@ bool Dqn_String8Builder_AppendFV_(DQN_LEAK_TRACE_FUNCTION Dqn_String8Builder *bu
return result; return result;
} }
bool Dqn_String8Builder_AppendF(Dqn_String8Builder *builder, char const *fmt, ...) DQN_API bool Dqn_String8Builder_AppendF(Dqn_String8Builder *builder, char const *fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -640,7 +640,7 @@ bool Dqn_String8Builder_AppendF(Dqn_String8Builder *builder, char const *fmt, ..
return result; return result;
} }
Dqn_String8 Dqn_String8Builder_Build(Dqn_String8Builder const *builder, Dqn_Allocator allocator) DQN_API Dqn_String8 Dqn_String8Builder_Build(Dqn_String8Builder const *builder, Dqn_Allocator allocator)
{ {
Dqn_String8 result = DQN_ZERO_INIT; Dqn_String8 result = DQN_ZERO_INIT;
if (!builder || builder->string_size <= 0 || builder->count <= 0) if (!builder || builder->string_size <= 0 || builder->count <= 0)
@ -662,7 +662,7 @@ Dqn_String8 Dqn_String8Builder_Build(Dqn_String8Builder const *builder, Dqn_Allo
#if !defined(DQN_NO_JSON_BUILDER) #if !defined(DQN_NO_JSON_BUILDER)
// NOTE: [$JSON] Dqn_JSONBuilder =================================================================== // NOTE: [$JSON] Dqn_JSONBuilder ===================================================================
Dqn_JSONBuilder Dqn_JSONBuilder_Init(Dqn_Allocator allocator, int spaces_per_indent) DQN_API Dqn_JSONBuilder Dqn_JSONBuilder_Init(Dqn_Allocator allocator, int spaces_per_indent)
{ {
Dqn_JSONBuilder result = {}; Dqn_JSONBuilder result = {};
result.spaces_per_indent = spaces_per_indent; result.spaces_per_indent = spaces_per_indent;
@ -670,13 +670,13 @@ Dqn_JSONBuilder Dqn_JSONBuilder_Init(Dqn_Allocator allocator, int spaces_per_ind
return result; return result;
} }
Dqn_String8 Dqn_JSONBuilder_Build(Dqn_JSONBuilder const *builder, Dqn_Allocator allocator) DQN_API Dqn_String8 Dqn_JSONBuilder_Build(Dqn_JSONBuilder const *builder, Dqn_Allocator allocator)
{ {
Dqn_String8 result = Dqn_String8Builder_Build(&builder->string_builder, allocator); Dqn_String8 result = Dqn_String8Builder_Build(&builder->string_builder, allocator);
return result; return result;
} }
void Dqn_JSONBuilder_KeyValue(Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value) DQN_API void Dqn_JSONBuilder_KeyValue(Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value)
{ {
if (key.size == 0 && value.size == 0) if (key.size == 0 && value.size == 0)
return; return;
@ -729,14 +729,14 @@ void Dqn_JSONBuilder_KeyValue(Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_Str
builder->last_item = item; builder->last_item = item;
} }
void Dqn_JSONBuilder_KeyValueFV(Dqn_JSONBuilder *builder, Dqn_String8 key, char const *value_fmt, va_list args) DQN_API void Dqn_JSONBuilder_KeyValueFV(Dqn_JSONBuilder *builder, Dqn_String8 key, char const *value_fmt, va_list args)
{ {
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(builder->string_builder.allocator.user_context); Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(builder->string_builder.allocator.user_context);
Dqn_String8 value = Dqn_String8_InitFV(scratch.allocator, value_fmt, args); Dqn_String8 value = Dqn_String8_InitFV(scratch.allocator, value_fmt, args);
Dqn_JSONBuilder_KeyValue(builder, key, value); Dqn_JSONBuilder_KeyValue(builder, key, value);
} }
void Dqn_JSONBuilder_KeyValueF(Dqn_JSONBuilder *builder, Dqn_String8 key, char const *value_fmt, ...) DQN_API void Dqn_JSONBuilder_KeyValueF(Dqn_JSONBuilder *builder, Dqn_String8 key, char const *value_fmt, ...)
{ {
va_list args; va_list args;
va_start(args, value_fmt); va_start(args, value_fmt);
@ -744,47 +744,47 @@ void Dqn_JSONBuilder_KeyValueF(Dqn_JSONBuilder *builder, Dqn_String8 key, char c
va_end(args); va_end(args);
} }
void Dqn_JSONBuilder_ObjectBeginNamed(Dqn_JSONBuilder *builder, Dqn_String8 name) DQN_API void Dqn_JSONBuilder_ObjectBeginNamed(Dqn_JSONBuilder *builder, Dqn_String8 name)
{ {
Dqn_JSONBuilder_KeyValue(builder, name, DQN_STRING8("{")); Dqn_JSONBuilder_KeyValue(builder, name, DQN_STRING8("{"));
} }
void Dqn_JSONBuilder_ObjectEnd(Dqn_JSONBuilder *builder) DQN_API void Dqn_JSONBuilder_ObjectEnd(Dqn_JSONBuilder *builder)
{ {
Dqn_JSONBuilder_KeyValue(builder, DQN_STRING8(""), DQN_STRING8("}")); Dqn_JSONBuilder_KeyValue(builder, DQN_STRING8(""), DQN_STRING8("}"));
} }
void Dqn_JSONBuilder_ArrayBeginNamed(Dqn_JSONBuilder *builder, Dqn_String8 name) DQN_API void Dqn_JSONBuilder_ArrayBeginNamed(Dqn_JSONBuilder *builder, Dqn_String8 name)
{ {
Dqn_JSONBuilder_KeyValue(builder, name, DQN_STRING8("[")); Dqn_JSONBuilder_KeyValue(builder, name, DQN_STRING8("["));
} }
void Dqn_JSONBuilder_ArrayEnd(Dqn_JSONBuilder *builder) DQN_API void Dqn_JSONBuilder_ArrayEnd(Dqn_JSONBuilder *builder)
{ {
Dqn_JSONBuilder_KeyValue(builder, DQN_STRING8(""), DQN_STRING8("]")); Dqn_JSONBuilder_KeyValue(builder, DQN_STRING8(""), DQN_STRING8("]"));
} }
void Dqn_JSONBuilder_StringNamed(Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value) DQN_API void Dqn_JSONBuilder_StringNamed(Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value)
{ {
Dqn_JSONBuilder_KeyValueF(builder, key, "\"%.*s\"", value.size, value.data); Dqn_JSONBuilder_KeyValueF(builder, key, "\"%.*s\"", value.size, value.data);
} }
void Dqn_JSONBuilder_LiteralNamed(Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value) DQN_API void Dqn_JSONBuilder_LiteralNamed(Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value)
{ {
Dqn_JSONBuilder_KeyValueF(builder, key, "%.*s", value.size, value.data); Dqn_JSONBuilder_KeyValueF(builder, key, "%.*s", value.size, value.data);
} }
void Dqn_JSONBuilder_U64Named(Dqn_JSONBuilder *builder, Dqn_String8 key, uint64_t value) DQN_API void Dqn_JSONBuilder_U64Named(Dqn_JSONBuilder *builder, Dqn_String8 key, uint64_t value)
{ {
Dqn_JSONBuilder_KeyValueF(builder, key, "%I64u", value); Dqn_JSONBuilder_KeyValueF(builder, key, "%I64u", value);
} }
void Dqn_JSONBuilder_I64Named(Dqn_JSONBuilder *builder, Dqn_String8 key, int64_t value) DQN_API void Dqn_JSONBuilder_I64Named(Dqn_JSONBuilder *builder, Dqn_String8 key, int64_t value)
{ {
Dqn_JSONBuilder_KeyValueF(builder, key, "%I64d", value); Dqn_JSONBuilder_KeyValueF(builder, key, "%I64d", value);
} }
void Dqn_JSONBuilder_F64Named(Dqn_JSONBuilder *builder, Dqn_String8 key, double value, int decimal_places) DQN_API void Dqn_JSONBuilder_F64Named(Dqn_JSONBuilder *builder, Dqn_String8 key, double value, int decimal_places)
{ {
if (!builder) if (!builder)
return; return;
@ -797,22 +797,22 @@ void Dqn_JSONBuilder_F64Named(Dqn_JSONBuilder *builder, Dqn_String8 key, double
char float_fmt[16]; char float_fmt[16];
if (decimal_places > 0) { if (decimal_places > 0) {
// NOTE: Emit the format string "%.<decimal_places>f" i.e. %.1f // NOTE: Emit the format string "%.<decimal_places>f" i.e. %.1f
snprintf(float_fmt, sizeof(float_fmt), "%%.%df", decimal_places); STB_SPRINTF_DECORATE(snprintf)(float_fmt, sizeof(float_fmt), "%%.%df", decimal_places);
} else { } else {
// NOTE: Emit the format string "%f" // NOTE: Emit the format string "%f"
snprintf(float_fmt, sizeof(float_fmt), "%%f"); STB_SPRINTF_DECORATE(snprintf)(float_fmt, sizeof(float_fmt), "%%f");
} }
char fmt[32]; char fmt[32];
if (key.size) if (key.size)
snprintf(fmt, sizeof(fmt), "\"%%.*s\": %s", float_fmt); STB_SPRINTF_DECORATE(snprintf)(fmt, sizeof(fmt), "\"%%.*s\": %s", float_fmt);
else else
snprintf(fmt, sizeof(fmt), "%s", float_fmt); STB_SPRINTF_DECORATE(snprintf)(fmt, sizeof(fmt), "%s", float_fmt);
Dqn_JSONBuilder_KeyValueF(builder, key, fmt, value); Dqn_JSONBuilder_KeyValueF(builder, key, fmt, value);
} }
void Dqn_JSONBuilder_BoolNamed(Dqn_JSONBuilder *builder, Dqn_String8 key, bool value) DQN_API void Dqn_JSONBuilder_BoolNamed(Dqn_JSONBuilder *builder, Dqn_String8 key, bool value)
{ {
Dqn_String8 value_string = value ? DQN_STRING8("true") : DQN_STRING8("false"); Dqn_String8 value_string = value ? DQN_STRING8("true") : DQN_STRING8("false");
Dqn_JSONBuilder_KeyValueF(builder, key, "%.*s", value_string.size, value_string.data); Dqn_JSONBuilder_KeyValueF(builder, key, "%.*s", value_string.size, value_string.data);
@ -1193,7 +1193,8 @@ DQN_API Dqn_String8 Dqn_Bin_HexToBytesArena(Dqn_Arena *arena, Dqn_String8 hex)
} }
#endif // !defined(DQN_NO_HEX) #endif // !defined(DQN_NO_HEX)
DQN_API int Dqn_SNPrintF2DotsOnOverflow(char *buffer, int size, char const *fmt, ...) // NOTE: Other =====================================================================================
DQN_API int Dqn_SNPrintFDotTruncate(char *buffer, int size, char const *fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);

View File

@ -17,13 +17,13 @@
// @desc Calculate the size of a cstring literal/array at compile time // @desc Calculate the size of a cstring literal/array at compile time
// @param literal The cstring literal/array to calculate the size for // @param literal The cstring literal/array to calculate the size for
// @return The size of the cstring not including the null-terminating byte // @return The size of the cstring not including the null-terminating byte
//
// @proc Dqn_CString8_FSize, Dqn_CString8_FVSize // @proc Dqn_CString8_FSize, Dqn_CString8_FVSize
// Calculate the required size to format the given format cstring. // Calculate the required size to format the given format cstring.
// @param[in] fmt The format string to calculate the size for // @param[in] fmt The format string to calculate the size for
// @return The size required to format the string, not including the null // @return The size required to format the string, not including the null
// terminator. // terminator.
//
// @proc Dqn_CString8_Size // @proc Dqn_CString8_Size
// @desc Calculate the string length of the null-terminated string. // @desc Calculate the string length of the null-terminated string.
// @param[in] a The string whose length is to be determined // @param[in] a The string whose length is to be determined
@ -369,32 +369,31 @@ DQN_API Dqn_String8 Dqn_String8_Copy_ (DQN_LEAK_TRACE_FUNCTION Dq
#if !defined(DQN_NO_FSTRING8) #if !defined(DQN_NO_FSTRING8)
// NOTE: [$FSTR] Dqn_FString8 ====================================================================== // NOTE: [$FSTR] Dqn_FString8 ======================================================================
// NOTE: API // NOTE: API =======================================================================================
//
// @proc Dqn_FString8_InitF // @proc Dqn_FString8_InitF
// @desc Create a fixed string from the format string. The result string is // @desc Create a fixed string from the format string. The result string is
// null-terminated. // null-terminated.
// @param fmt[in] Format string specifier to create the fixed string from // @param fmt[in] Format string specifier to create the fixed string from
// @return The created string, truncated if there was insufficient space // @return The created string, truncated if there was insufficient space
//
// @proc Dqn_FString8_Max // @proc Dqn_FString8_Max
// @desc @param string[in] The string to query the maximum capacity of // @desc @param string[in] The string to query the maximum capacity of
// @return Maximum capacity of the fixed string // @return Maximum capacity of the fixed string
//
// @proc Dqn_FString8_Clear // @proc Dqn_FString8_Clear
// @desc Reset the characters in the string // @desc Reset the characters in the string
// @param string[in] The string to clear // @param string[in] The string to clear
//
// @proc Dqn_FString8_AppendFV // @proc Dqn_FString8_AppendFV
// @desc Append a format string to the fixed string. On failure the string is // @desc Append a format string to the fixed string. On failure the string is
// appended to but truncated ensuring null-termination. // appended to but truncated ensuring null-termination.
// @param string[in] The string to append to // @param string[in] The string to append to
// @param fmt[in] Format string to append to the fixed string // @param fmt[in] Format string to append to the fixed string
// @return True if append was successful, false otherwise. // @return True if append was successful, false otherwise.
//
// @proc Dqn_FString8_AppendF // @proc Dqn_FString8_AppendF
// @desc @copydocs Dqn_FString8_AppendF // @desc @copydocs Dqn_FString8_AppendF
//
// @proc Dqn_FString8_AppendCString8 // @proc Dqn_FString8_AppendCString8
// @desc Append a cstring to the fixed string. On failure the string is // @desc Append a cstring to the fixed string. On failure the string is
// appended to but truncated ensuring null-termination. // appended to but truncated ensuring null-termination.
@ -402,7 +401,7 @@ DQN_API Dqn_String8 Dqn_String8_Copy_ (DQN_LEAK_TRACE_FUNCTION Dq
// @param value[in] Cstring to append to the fixed string // @param value[in] Cstring to append to the fixed string
// @param size[in] Size of the cstring // @param size[in] Size of the cstring
// @return True if append was successful, false otherwise. // @return True if append was successful, false otherwise.
//
// @proc Dqn_FString8_Append // @proc Dqn_FString8_Append
// @desc Append a string to the fixed string. On failure the string is // @desc Append a string to the fixed string. On failure the string is
// appended to but truncated ensuring null-termination. // appended to but truncated ensuring null-termination.
@ -410,23 +409,23 @@ DQN_API Dqn_String8 Dqn_String8_Copy_ (DQN_LEAK_TRACE_FUNCTION Dq
// @param value[in] String to append to the fixed string // @param value[in] String to append to the fixed string
// determined before appending. // determined before appending.
// @return True if append was successful, false otherwise. // @return True if append was successful, false otherwise.
//
// @proc Dqn_FString8_ToString8 // @proc Dqn_FString8_ToString8
// @desc Convert a fixed string to a string. The string holds a reference to the // @desc Convert a fixed string to a string. The string holds a reference to the
// fixed string and is invalidated once fixed string is deleted. // fixed string and is invalidated once fixed string is deleted.
// @param string[in] The fixed string to create a string from // @param string[in] The fixed string to create a string from
// @return String referencing the contents of `string` // @return String referencing the contents of `string`
//
// @proc Dqn_FString8_Eq // @proc Dqn_FString8_Eq
// @desc @see Dqn_String8_Eq // @desc @see Dqn_String8_Eq
//
// @proc Dqn_FString8_EqString8 // @proc Dqn_FString8_EqString8
// @desc @see Dqn_String8_Eq // @desc @see Dqn_String8_Eq
//
// @proc Dqn_FString8_EqInsensitive // @proc Dqn_FString8_EqInsensitive
// @desc Compare a string for equality, case insensitive // @desc Compare a string for equality, case insensitive
// @see Dqn_String8_Eq // @see Dqn_String8_Eq
//
// @proc Dqn_FString8_EqString8Insensitive // @proc Dqn_FString8_EqString8Insensitive
// @desc Compare a string for equality, case insensitive // @desc Compare a string for equality, case insensitive
// @see Dqn_String8_Eq // @see Dqn_String8_Eq
@ -467,6 +466,31 @@ template <Dqn_usize A, Dqn_usize B> bool Dqn_FString8_EqFString8Insen
#endif // !defined(DQN_NO_FSTRING8) #endif // !defined(DQN_NO_FSTRING8)
// NOTE: [$STRB] Dqn_String8Builder ================================================================ // NOTE: [$STRB] Dqn_String8Builder ================================================================
// NOTE: API =======================================================================================
// @proc Dqn_String8Builder_AppendRef, Dqn_String8_AppendCopy,
// Dqn_String8_AppendFV, Dqn_String8_AppendF
// @desc Append a string to the list of strings in the builder.
//
// The string is appended to the builder as follows
// - AppendRef: By reference
// - AppendCopy: By copy using the builder's allocator to copy the string
// - AppendFV, AppendF: Using a format string, allocated using the builder's
// allocator
//
// The string's data must persist whilst the string builder is being used.
// @param builder The builder to append the string to
// @param string The string to append to the builder
// @return True if append was successful, false if parameters are invalid
// or memory allocation failure.
// @proc Dqn_String8Builder_Build
// @desc Build the list of strings into the final composite string from the
// string builder
// @param builder The string builder to build the string from
// @param allocator The allocator to use to build the string
// @return The string if build was successful, empty string if parameters are
// invalid or memory allocation failure.
struct Dqn_String8Builder struct Dqn_String8Builder
{ {
Dqn_Allocator allocator; ///< Allocator to use to back the string list Dqn_Allocator allocator; ///< Allocator to use to back the string list
@ -476,45 +500,50 @@ struct Dqn_String8Builder
Dqn_usize count; ///< The number of links in the linked list of strings Dqn_usize count; ///< The number of links in the linked list of strings
}; };
/// Append a string to the list of strings in the builder by reference. #define Dqn_String8Builder_AppendFV(builder, fmt, args) Dqn_String8Builder_AppendFV_(DQN_LEAK_TRACE builder, fmt, args)
/// The string's data must persist whilst the string builder is being used. DQN_API bool Dqn_String8Builder_AppendF (Dqn_String8Builder *builder, char const *fmt, ...);
/// @param builder The builder to append the string to DQN_API bool Dqn_String8Builder_AppendRef (Dqn_String8Builder *builder, Dqn_String8 string);
/// @param string The string to append to the builder DQN_API bool Dqn_String8Builder_AppendCopy(Dqn_String8Builder *builder, Dqn_String8 string);
/// @return True if append was successful, false if parameters are invalid DQN_API Dqn_String8 Dqn_String8Builder_Build (Dqn_String8Builder const *builder, Dqn_Allocator allocator);
/// or memory allocation failure.
bool Dqn_String8Builder_AppendRef(Dqn_String8Builder *builder, Dqn_String8 string);
/// Append a string to the list of strings in the builder by copy. // NOTE: Internal ==================================================================================
/// The string is copied using the builder's allocator before appending. DQN_API bool Dqn_String8Builder_AppendFV_ (DQN_LEAK_TRACE_FUNCTION Dqn_String8Builder *builder, char const *fmt, va_list args);
/// @param builder The builder to append the string to
/// @param string The string to append to the builder
/// @return True if append was successful, false if parameters are invalid
/// or memory allocation failure.
bool Dqn_String8Builder_AppendCopy(Dqn_String8Builder *builder, Dqn_String8 string);
/// @copydoc Dqn_String8Builder_AppendF
/// @param args The variable argument list to use in the format string
#define Dqn_String8Builder_AppendFV(builder, fmt, args) Dqn_String8Builder_AppendFV_(DQN_LEAK_TRACE builder, fmt, args)
bool Dqn_String8Builder_AppendFV_(DQN_LEAK_TRACE_FUNCTION Dqn_String8Builder *builder, char const *fmt, va_list args);
/// Append a printf-style format string to the list of strings in the builder.
/// @param builder The builder to append the string to
/// @param fmt The format string to use
/// @return True if append was successful, false if parameters are invalid
/// or memory allocation failure.
bool Dqn_String8Builder_AppendF(Dqn_String8Builder *builder, char const *fmt, ...);
/// Build the list of strings into the final composite string from the string
/// builder
/// @param builder The string builder to build the string from
/// @param allocator The allocator to use to build the string
/// @return The string if build was successful, empty string if parameters are
/// invalid or memory allocation failure.
Dqn_String8 Dqn_String8Builder_Build(Dqn_String8Builder const *builder, Dqn_Allocator allocator);
#if !defined(DQN_NO_JSON_BUILDER) #if !defined(DQN_NO_JSON_BUILDER)
// NOTE: [$JSON] Dqn_JSONBuilder =================================================================== // NOTE: [$JSON] Dqn_JSONBuilder ===================================================================
// Basic helper class to construct JSON output to a string
// TODO(dqn): We need to write tests for this // TODO(dqn): We need to write tests for this
//
// NOTE: API =======================================================================================
// @proc Dqn_JSONBuilder_Build
// @desc Convert the internal JSON buffer in the builder into a string.
// @param[in] arena The allocator to use to build the string
// @proc Dqn_JSONBuilder_KeyValue, Dqn_JSONBuilder_KeyValueF
// @desc Add a JSON key value pair untyped. The value is emitted directly
// without checking the contents of value.
//
// All other functions internally call into this function which is the main
// workhorse of the builder.
// @proc Dqn_JSON_Builder_ObjectEnd
// @desc End a JSON object in the builder, generates internally a '}' string
// @proc Dqn_JSON_Builder_ArrayEnd
// @desc End a JSON array in the builder, generates internally a ']' string
// @proc Dqn_JSONBuilder_LiteralNamed
// @desc Add a named JSON key-value object whose value is directly written to
// the following '"<key>": <value>' (e.g. useful for emitting the 'null'
// value)
// @proc Dqn_JSONBuilder_U64Named, Dqn_JSONBuilder_U64,
// Dqn_JSONBuilder_I64Named, Dqn_JSONBuilder_I64,
// Dqn_JSONBuilder_F64Named, Dqn_JSONBuilder_F64,
// Dqn_JSONBuilder_BoolNamed, Dqn_JSONBuilder_Bool,
// @desc Add the named JSON data type as a key-value object. Generates
// internally the string '"<key>": <value>'
enum Dqn_JSONBuilderItem { enum Dqn_JSONBuilderItem {
Dqn_JSONBuilderItem_Empty, Dqn_JSONBuilderItem_Empty,
Dqn_JSONBuilderItem_OpenContainer, Dqn_JSONBuilderItem_OpenContainer,
@ -522,7 +551,6 @@ enum Dqn_JSONBuilderItem {
Dqn_JSONBuilderItem_KeyValue, Dqn_JSONBuilderItem_KeyValue,
}; };
/// Basic helper class to construct JSON string output
struct Dqn_JSONBuilder { struct Dqn_JSONBuilder {
bool use_stdout; ///< When set, ignore the string builder and dump immediately to stdout bool use_stdout; ///< When set, ignore the string builder and dump immediately to stdout
Dqn_String8Builder string_builder; ///< (Internal) Dqn_String8Builder string_builder; ///< (Internal)
@ -548,82 +576,29 @@ struct Dqn_JSONBuilder {
Dqn_JSONBuilder_ArrayEnd(builder)) Dqn_JSONBuilder_ArrayEnd(builder))
/// Initialise a JSON builder DQN_API Dqn_JSONBuilder Dqn_JSONBuilder_Init (Dqn_Allocator allocator, int spaces_per_indent);
Dqn_JSONBuilder Dqn_JSONBuilder_Init(Dqn_Allocator allocator, int spaces_per_indent); DQN_API Dqn_String8 Dqn_JSONBuilder_Build (Dqn_JSONBuilder const *builder, Dqn_Allocator allocator);
DQN_API void Dqn_JSONBuilder_KeyValue (Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value);
DQN_API void Dqn_JSONBuilder_KeyValueF (Dqn_JSONBuilder *builder, Dqn_String8 key, char const *value_fmt, ...);
DQN_API void Dqn_JSONBuilder_ObjectBeginNamed(Dqn_JSONBuilder *builder, Dqn_String8 name);
DQN_API void Dqn_JSONBuilder_ObjectEnd (Dqn_JSONBuilder *builder);
DQN_API void Dqn_JSONBuilder_ArrayBeginNamed (Dqn_JSONBuilder *builder, Dqn_String8 name);
DQN_API void Dqn_JSONBuilder_ArrayEnd (Dqn_JSONBuilder *builder);
DQN_API void Dqn_JSONBuilder_StringNamed (Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value);
DQN_API void Dqn_JSONBuilder_LiteralNamed (Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value);
DQN_API void Dqn_JSONBuilder_U64Named (Dqn_JSONBuilder *builder, Dqn_String8 key, uint64_t value);
DQN_API void Dqn_JSONBuilder_I64Named (Dqn_JSONBuilder *builder, Dqn_String8 key, int64_t value);
DQN_API void Dqn_JSONBuilder_F64Named (Dqn_JSONBuilder *builder, Dqn_String8 key, double value, int decimal_places);
DQN_API void Dqn_JSONBuilder_BoolNamed (Dqn_JSONBuilder *builder, Dqn_String8 key, bool value);
/// Convert the internal JSON buffer in the builder into a string. #define Dqn_JSONBuilder_ObjectBegin(builder) Dqn_JSONBuilder_ObjectBeginNamed(builder, DQN_STRING8(""))
/// #define Dqn_JSONBuilder_ArrayBegin(builder) Dqn_JSONBuilder_ArrayBeginNamed(builder, DQN_STRING8(""))
/// @param[in] arena The allocator to use to build the string #define Dqn_JSONBuilder_String(builder, value) Dqn_JSONBuilder_StringNamed(builder, DQN_STRING8(""), value)
Dqn_String8 Dqn_JSONBuilder_Build(Dqn_JSONBuilder const *builder, Dqn_Allocator allocator); #define Dqn_JSONBuilder_Literal(builder, value) Dqn_JSONBuilder_LiteralNamed(builder, DQN_STRING8(""), value)
#define Dqn_JSONBuilder_U64(builder, value) Dqn_JSONBuilder_U64Named(builder, DQN_STRING8(""), value)
/// Add a JSON key value pair untyped. The value is emitted directly without #define Dqn_JSONBuilder_I64(builder, value) Dqn_JSONBuilder_I64Named(builder, DQN_STRING8(""), value)
/// checking the contents of value. #define Dqn_JSONBuilder_F64(builder, value) Dqn_JSONBuilder_F64Named(builder, DQN_STRING8(""), value)
/// #define Dqn_JSONBuilder_Bool(builder, value) Dqn_JSONBuilder_BoolNamed(builder, DQN_STRING8(""), value)
/// All other functions internally call into this function which is the main
/// workhorse of the builder.
void Dqn_JSONBuilder_KeyValue(Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value);
void Dqn_JSONBuilder_KeyValueF(Dqn_JSONBuilder *builder, Dqn_String8 key, char const *value_fmt, ...);
/// Begin a named JSON object for writing into in the builder
///
/// Generates internally a string like '"<name>": {'
void Dqn_JSONBuilder_ObjectBeginNamed(Dqn_JSONBuilder *builder, Dqn_String8 name);
#define Dqn_JSONBuilder_ObjectBegin(builder) Dqn_JSONBuilder_ObjectBeginNamed(builder, DQN_STRING8(""))
/// End a JSON object for writing into in the builder
///
/// Generates internally a string like '}'
void Dqn_JSONBuilder_ObjectEnd(Dqn_JSONBuilder *builder);
/// Begin a named JSON array for writing into in the builder
///
/// Generates internally a string like '"<name>": ['
void Dqn_JSONBuilder_ArrayBeginNamed(Dqn_JSONBuilder *builder, Dqn_String8 name);
#define Dqn_JSONBuilder_ArrayBegin(builder) Dqn_JSONBuilder_ArrayBeginNamed(builder, DQN_STRING8(""))
/// Begin a named JSON array for writing into in the builder
///
/// Generates internally a string like ']'
void Dqn_JSONBuilder_ArrayEnd(Dqn_JSONBuilder *builder);
/// Add a named JSON string key-value object
///
/// Generates internally a string like '"<key>": "<value>"'
void Dqn_JSONBuilder_StringNamed(Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value);
#define Dqn_JSONBuilder_String(builder, value) Dqn_JSONBuilder_StringNamed(builder, DQN_STRING8(""), value)
/// Add a named JSON key-value object whose value is directly written
///
/// Generates internally a string like '"<key>": <value>' (e.g. useful for
/// emitting the 'null' value)
void Dqn_JSONBuilder_LiteralNamed(Dqn_JSONBuilder *builder, Dqn_String8 key, Dqn_String8 value);
#define Dqn_JSONBuilder_Literal(builder, value) Dqn_JSONBuilder_LiteralNamed(builder, DQN_STRING8(""), value)
/// Add a named JSON u64 key-value object
///
/// Generates internally a string like '"<key>": <value>'
void Dqn_JSONBuilder_U64Named(Dqn_JSONBuilder *builder, Dqn_String8 key, uint64_t value);
#define Dqn_JSONBuilder_U64(builder, value) Dqn_JSONBuilder_U64Named(builder, DQN_STRING8(""), value)
/// Add a JSON i64 key-value object
///
/// Generates internally a string like '"<key>": <value>'
void Dqn_JSONBuilder_I64Named(Dqn_JSONBuilder *builder, Dqn_String8 key, int64_t value);
#define Dqn_JSONBuilder_I64(builder, value) Dqn_JSONBuilder_I64Named(builder, DQN_STRING8(""), value)
/// Add a JSON f64 key-value object
///
/// Generates internally a string like '"<key>": <value>'
/// @param[in] decimal_places The number of decimal places to preserve. Maximum 16
void Dqn_JSONBuilder_F64Named(Dqn_JSONBuilder *builder, Dqn_String8 key, double value, int decimal_places);
#define Dqn_JSONBuilder_F64(builder, value) Dqn_JSONBuilder_F64Named(builder, DQN_STRING8(""), value)
/// Add a JSON bool key-value object
///
/// Generates internally a string like '"<key>": <value>'
void Dqn_JSONBuilder_BoolNamed(Dqn_JSONBuilder *builder, Dqn_String8 key, bool value);
#define Dqn_JSONBuilder_Bool(builder, value) Dqn_JSONBuilder_BoolNamed(builder, DQN_STRING8(""), value)
#endif // !defined(DQN_NO_JSON_BUIDLER) #endif // !defined(DQN_NO_JSON_BUIDLER)
// NOTE: [$CHAR] Dqn_Char ========================================================================== // NOTE: [$CHAR] Dqn_Char ==========================================================================
@ -643,9 +618,7 @@ DQN_API int Dqn_UTF16_EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint);
#if !defined(DQN_NO_HEX) #if !defined(DQN_NO_HEX)
// NOTE: [$BHEX] Dqn_Bin =========================================================================== // NOTE: [$BHEX] Dqn_Bin ===========================================================================
// // NOTE: API =======================================================================================
// NOTE: API
//
// @proc Dqn_Bin_U64ToHexU64String // @proc Dqn_Bin_U64ToHexU64String
// @desc Convert a 64 bit number to a hex string // @desc Convert a 64 bit number to a hex string
// @param[in] number Number to convert to hexadecimal representation // @param[in] number Number to convert to hexadecimal representation
@ -653,21 +626,21 @@ DQN_API int Dqn_UTF16_EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint);
// output of the hexadecimal string. // output of the hexadecimal string.
// @return The hexadecimal representation of the number. This string is always // @return The hexadecimal representation of the number. This string is always
// null-terminated. // null-terminated.
//
// @proc Dqn_Bin_U64ToHex // @proc Dqn_Bin_U64ToHex
// @copybrief Dqn_Bin_U64ToHexU64String // @copybrief Dqn_Bin_U64ToHexU64String
//
// @param[in] allocator The memory allocator to use for the memory of the // @param[in] allocator The memory allocator to use for the memory of the
// hexadecimal string. // hexadecimal string.
// @copyparams Dqn_Bin_U64ToHexU64String // @copyparams Dqn_Bin_U64ToHexU64String
//
// @proc Dqn_Bin_HexBufferToU64 // @proc Dqn_Bin_HexBufferToU64
// @desc Convert a hexadecimal string a 64 bit value. // @desc Convert a hexadecimal string a 64 bit value.
// Asserts if the hex string is too big to be converted into a 64 bit number. // Asserts if the hex string is too big to be converted into a 64 bit number.
//
// @proc Dqn_Bin_HexToU64 // @proc Dqn_Bin_HexToU64
// @copydoc Dqn_Bin_HexToU64 // @copydoc Dqn_Bin_HexToU64
//
// @proc Dqn_Bin_BytesToHexBuffer // @proc Dqn_Bin_BytesToHexBuffer
// @desc Convert a binary buffer into its hex representation into dest. // @desc Convert a binary buffer into its hex representation into dest.
// //
@ -676,15 +649,15 @@ DQN_API int Dqn_UTF16_EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint);
// //
// @return True if the conversion into the dest buffer was successful, false // @return True if the conversion into the dest buffer was successful, false
// otherwise (e.g. invalid arguments). // otherwise (e.g. invalid arguments).
//
// @proc Dqn_Bin_BytesToHexBufferArena // @proc Dqn_Bin_BytesToHexBufferArena
// @desc Convert a series of bytes into a string // @desc Convert a series of bytes into a string
// @return A null-terminated hex string, null pointer if allocation failed // @return A null-terminated hex string, null pointer if allocation failed
//
// @proc Dqn_Bin_BytesToHexArena // @proc Dqn_Bin_BytesToHexArena
// @copydoc Dqn_Bin_BytesToHexBufferArena // @copydoc Dqn_Bin_BytesToHexBufferArena
// @return A hex string, the string is invalid if conversion failed. // @return A hex string, the string is invalid if conversion failed.
//
// @proc Dqn_Bin_HexBufferToBytes // @proc Dqn_Bin_HexBufferToBytes
// @desc Convert a hex string into binary at `dest`. // @desc Convert a hex string into binary at `dest`.
// //
@ -700,20 +673,20 @@ DQN_API int Dqn_UTF16_EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint);
// //
// @return The number of bytes written to `dest_size`, this value will *never* // @return The number of bytes written to `dest_size`, this value will *never*
// be greater than `dest_size`. // be greater than `dest_size`.
//
// @proc Dqn_Bin_HexToBytes // @proc Dqn_Bin_HexToBytes
// @desc String8 variant of @see Dqn_Bin_HexBufferToBytes // @desc String8 variant of @see Dqn_Bin_HexBufferToBytes
//
// @proc Dqn_Bin_StringHexBufferToBytesUnchecked // @proc Dqn_Bin_StringHexBufferToBytesUnchecked
// @desc Unchecked variant of @see Dqn_Bin_HexBufferToBytes // @desc Unchecked variant of @see Dqn_Bin_HexBufferToBytes
// //
// This function skips some string checks, it assumes the hex is a valid hex // This function skips some string checks, it assumes the hex is a valid hex
// stream and that the arguments are valid e.g. no trimming or 0x prefix // stream and that the arguments are valid e.g. no trimming or 0x prefix
// stripping is performed // stripping is performed
//
// @proc Dqn_Bin_String // @proc Dqn_Bin_String
// @desc String8 variant of @see Dqn_Bin_HexBufferToBytesUnchecked // @desc String8 variant of @see Dqn_Bin_HexBufferToBytesUnchecked
//
// @proc Dqn_Bin_HexBufferToBytesArena // @proc Dqn_Bin_HexBufferToBytesArena
// Dynamic allocating variant of @see Dqn_Bin_HexBufferToBytesUnchecked // Dynamic allocating variant of @see Dqn_Bin_HexBufferToBytesUnchecked
// //
@ -723,7 +696,7 @@ DQN_API int Dqn_UTF16_EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint);
// @param[out] real_size The size of the buffer returned by the function // @param[out] real_size The size of the buffer returned by the function
// //
// @return The byte representation of the hex string. // @return The byte representation of the hex string.
//
// @proc Dqn_Bin_HexToBytesArena // @proc Dqn_Bin_HexToBytesArena
// @copybrief Dqn_Bin_HexBufferToBytesArena // @copybrief Dqn_Bin_HexBufferToBytesArena
// //
@ -731,6 +704,7 @@ DQN_API int Dqn_UTF16_EncodeCodepoint(uint16_t utf16[2], uint32_t codepoint);
// @param[in] hex Hex string to convert into bytes // @param[in] hex Hex string to convert into bytes
// //
// @return The byte representation of the hex string. // @return The byte representation of the hex string.
struct Dqn_BinHexU64String struct Dqn_BinHexU64String
{ {
char data[2 /*0x*/ + 16 /*hex*/ + 1 /*null-terminator*/]; char data[2 /*0x*/ + 16 /*hex*/ + 1 /*null-terminator*/];
@ -765,12 +739,20 @@ DQN_API Dqn_usize Dqn_Bin_HexToBytes (Dqn_String8 hex,
DQN_API Dqn_String8 Dqn_Bin_HexToBytesArena (Dqn_Arena *arena, Dqn_String8 hex); DQN_API Dqn_String8 Dqn_Bin_HexToBytesArena (Dqn_Arena *arena, Dqn_String8 hex);
#endif // !defined(DQN_NO_HEX) #endif // !defined(DQN_NO_HEX)
/// Write the format string to the buffer truncating with a trailing ".." if // NOTE: Other =====================================================================================
/// there is insufficient space in the buffer followed by null-terminating the // NOTE: API =======================================================================================
/// buffer (uses stb_sprintf underneath). // @proc Dqn_SNPrintFDotTruncate
/// @return The size of the string written to the buffer *not* including the // @desc Write the format string to the buffer truncating with a trailing ".."
/// null-terminator. // if there is insufficient space in the buffer followed by null-terminating
DQN_API int Dqn_SNPrintF2DotsOnOverflow(char *buffer, int size, char const *fmt, ...); // the buffer (uses stb_sprintf underneath).
// @return The size of the string written to the buffer *not* including the
// null-terminator.
//
// @proc Dqn_U64ToString
// @desc Convert a 64 bit unsigned value to its string representation.
// @param[in] val Value to convert into a string
// @param[in] separator The separator to insert every 3 digits. Set this to
// 0 if no separator is desired.
struct Dqn_U64String struct Dqn_U64String
{ {
@ -778,11 +760,8 @@ struct Dqn_U64String
uint8_t size; uint8_t size;
}; };
/// Convert a 64 bit unsigned value to its string representation. DQN_API int Dqn_SNPrintFDotTruncate(char *buffer, int size, char const *fmt, ...);
/// @param[in] val Value to convert into a string DQN_API Dqn_U64String Dqn_U64ToString (uint64_t val, char separator);
/// @param[in] separator The separator to insert every 3 digits. Set this to
/// 0 if no separator is desired.
DQN_API Dqn_U64String Dqn_U64ToString(uint64_t val, char separator);
// NOTE: [$STBS] stb_sprintf ======================================================================= // NOTE: [$STBS] stb_sprintf =======================================================================
// stb_sprintf - v1.10 - public domain snprintf() implementation // stb_sprintf - v1.10 - public domain snprintf() implementation