len->size, make some functions null allocator aware
This commit is contained in:
parent
73f8a8bcb9
commit
76bd54d9b0
475
Code/Dqn.h
475
Code/Dqn.h
@ -10,8 +10,8 @@
|
||||
// #define DQN_ALLOCATOR_DEFAULT_TO_NULL
|
||||
//
|
||||
// If defined, 0 initialising an allocator uses the null allocator (i.e. crashes
|
||||
// when allocating). It forces the user to specify explicitly which allocator
|
||||
// to use, for example.
|
||||
// when allocating). It forces the user to specify explicitly which allocator to
|
||||
// use, for example.
|
||||
//
|
||||
// Dqn_Allocator allocator = {};
|
||||
// allocator.type = Dqn_AllocatorType::Heap;
|
||||
@ -20,13 +20,40 @@
|
||||
//
|
||||
// Dqn_Allocator allocator = Dqn_AllocatorHeap()
|
||||
//
|
||||
// Otherwise if not defined, Dqn_Allocator allocator = {}; will by default use malloc, realloc, free
|
||||
// Otherwise if not defined, Dqn_Allocator allocator = {}; will by default use
|
||||
// malloc, realloc, free
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Library Config
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// Dqn library logs errors and outputs through Dqn_Log(...). This is
|
||||
// customisable by updating the function ptr the logging routine is called
|
||||
// through. Currently it is set in the global variable `dqn_log`, i.e.
|
||||
//
|
||||
// Dqn_LogProc *dqn_log = Dqn_Log;
|
||||
//
|
||||
// Set dqn_log to your own routine to override the default library logging
|
||||
// routine.
|
||||
|
||||
#if !defined(DQN_H)
|
||||
#define DQN_H
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Compiler
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
#if defined(_MSC_VER)
|
||||
#define DQN_COMPILER_MSVC
|
||||
#elif defined(__clang__)
|
||||
#define DQN_COMPILER_CLANG
|
||||
#elif defined(__GNUC__)
|
||||
#define DQN_COMPILER_GCC
|
||||
#endif
|
||||
|
||||
#if defined(DQN_COMPILER_MSVC)
|
||||
#if defined(_CRT_SECURE_NO_WARNINGS)
|
||||
#define DQN_CRT_SECURE_NO_WARNINGS_PREVIOUSLY_DEFINED
|
||||
#else
|
||||
@ -80,18 +107,9 @@
|
||||
#define DQN_SQRTF(val) sqrtf(val)
|
||||
#endif
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Compiler
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
#if defined(_MSC_VER)
|
||||
#define DQN_COMPILER_MSVC
|
||||
#elif defined(__clang__)
|
||||
#define DQN_COMPILER_CLANG
|
||||
#elif defined(__GNUC__)
|
||||
#define DQN_COMPILER_GCC
|
||||
#if !defined(DQN_STRLEN)
|
||||
#include <string.h>
|
||||
#define DQN_STRLEN(str) strlen(str)
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
@ -474,31 +492,20 @@ enum struct Dqn_LogType { X_MACRO };
|
||||
|
||||
#define X_ENTRY(enum_val, string) string,
|
||||
char const *Dqn_LogTypeString[] = { X_MACRO };
|
||||
#undef X_ENTRY
|
||||
#undef X_MACRO
|
||||
|
||||
#define DQN_LOG_E(fmt, ...) dqn_core.Log(Dqn_LogType::Error, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG_D(fmt, ...) dqn_core.Log(Dqn_LogType::Debug, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG_W(fmt, ...) dqn_core.Log(Dqn_LogType::Warning, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG_I(fmt, ...) dqn_core.Log(Dqn_LogType::Info, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG_M(fmt, ...) dqn_core.Log(Dqn_LogType::Memory, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG(log_type, fmt, ...) dqn_core.Log(log_type, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG_E(fmt, ...) dqn_log(Dqn_LogType::Error, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG_D(fmt, ...) dqn_log(Dqn_LogType::Debug, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG_W(fmt, ...) dqn_log(Dqn_LogType::Warning, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG_I(fmt, ...) dqn_log(Dqn_LogType::Info, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG_M(fmt, ...) dqn_log(Dqn_LogType::Memory, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
#define DQN_LOG(log_type, fmt, ...) dqn_log(log_type, DQN_STR_AND_LEN(__FILE__), DQN_STR_AND_LEN(__func__), __LINE__, fmt, ## __VA_ARGS__)
|
||||
|
||||
#define DQN_LOG_PROC(name) void name(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, ...)
|
||||
typedef DQN_LOG_PROC(Dqn_LogProc);
|
||||
|
||||
DQN_API void Dqn_LogV(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, va_list va);
|
||||
DQN_API DQN_LOG_PROC(Dqn_Log);
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Core Config
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
struct Dqn_Core
|
||||
{
|
||||
Dqn_LogProc *Log;
|
||||
};
|
||||
extern Dqn_Core dqn_core;
|
||||
DQN_API void Dqn_LogV (Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, va_list va);
|
||||
DQN_API void Dqn_Log (Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, ...);
|
||||
typedef void Dqn_LogProc(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, ...);
|
||||
extern Dqn_LogProc *dqn_log;
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
@ -904,6 +911,7 @@ DQN_API char Dqn_Char_ToLower (char ch);
|
||||
// NOTE: String
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
#define DQN_STRING_LITERAL(string) {string, Dqn_CharCountI(string)}
|
||||
struct Dqn_String
|
||||
{
|
||||
union {
|
||||
@ -913,28 +921,29 @@ struct Dqn_String
|
||||
char *str;
|
||||
};
|
||||
|
||||
Dqn_isize len;
|
||||
Dqn_isize size;
|
||||
char const *begin() const { return str; }
|
||||
char const *end () const { return str + len; }
|
||||
char const *end () const { return str + size; }
|
||||
char *begin() { return str; }
|
||||
char *end () { return str + len; }
|
||||
char *end () { return str + size; }
|
||||
};
|
||||
|
||||
DQN_API Dqn_b32 Dqn_String_Compare (Dqn_String const lhs, Dqn_String const rhs);
|
||||
DQN_API Dqn_b32 Dqn_String_CompareCaseInsensitive(Dqn_String const lhs, Dqn_String const rhs);
|
||||
DQN_API Dqn_String Dqn_String_Copy (Dqn_Allocator *allocator, Dqn_String const src);
|
||||
|
||||
// allocator: (Optional) When null, the string is allocated with DQN_MALLOC, result should be freed with DQN_FREE.
|
||||
DQN_API Dqn_String Dqn_String_Copy (Dqn_String const src, Dqn_Allocator *allocator);
|
||||
DQN_API Dqn_String Dqn_String_TrimWhitespaceAround (Dqn_String src);
|
||||
DQN_API Dqn_b32 operator== (Dqn_String const &lhs, Dqn_String const &rhs);
|
||||
#define DQN_STRING_LITERAL(string) {string, Dqn_CharCountI(string)}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// NOTE: Dqn_Asprintf (Allocate Sprintf)
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
// return: The allocated string. If allocation fails, the str returned is nullptr and length is set o the size required, NOT INCLUDING the null terminator.
|
||||
DQN_API Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, va_list va);
|
||||
DQN_API Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, ...);
|
||||
// return: The allocated string. When allocation fails, str returned is nullptr, size is set to the length required NOT INCLUDING the null terminator.
|
||||
// i.e. the required buffer length for generating the string is (result.size + 1).
|
||||
DQN_API Dqn_String Dqn_String_FmtV (Dqn_Allocator *allocator, char const *fmt, va_list va);
|
||||
DQN_API Dqn_String Dqn_String_FmtF (Dqn_Allocator *allocator, char const *fmt, ...);
|
||||
|
||||
// Free a string allocated with `Dqn_String_Copy`, `Dqn_String_FmtV` `Dqn_String_FmtF`
|
||||
// allocator: The same allocator specified when `Dqn_String_Copy` was called.
|
||||
DQN_API void Dqn_String_Free (Dqn_String *string, Dqn_Allocator *allocator);
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
@ -966,7 +975,11 @@ DQN_API Dqn_i64 Dqn_Str_ToI64 (char const *buf, int len
|
||||
// NOTE: Dqn_File
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
DQN_API char *Dqn_File_ReadAll(Dqn_Allocator *allocator, char const *file, Dqn_isize *file_size);
|
||||
// file_size: (Optional) The size of the file in bytes, the allocated buffer is (file_size + 1 [null terminator]) in bytes.
|
||||
// allocator: (Optional) When null, the buffer is allocated with DQN_MALLOC, result should be freed with DQN_FREE.
|
||||
// return: nullptr if allocation failed.
|
||||
DQN_API char *Dqn_File_ReadEntireFile (char const *file, Dqn_isize *file_size, Dqn_Allocator *allocator);
|
||||
DQN_API Dqn_b32 Dqn_File_WriteEntireFile(char const *file, char const *buffer, Dqn_isize buffer_size);
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
@ -1100,12 +1113,12 @@ template <Dqn_isize N>
|
||||
Dqn_String Dqn_StringBuilder_BuildString(Dqn_StringBuilder<N> *builder, Dqn_Allocator *allocator)
|
||||
{
|
||||
Dqn_String result = {};
|
||||
result.str = Dqn_StringBuilder_Build(builder, allocator, &result.len);
|
||||
result.str = Dqn_StringBuilder_Build(builder, allocator, &result.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <Dqn_isize N>
|
||||
void Dqn_StringBuilder_VFmtAppend(Dqn_StringBuilder<N> *builder, char const *fmt, va_list va)
|
||||
void Dqn_StringBuilder_AppendFmtV(Dqn_StringBuilder<N> *builder, char const *fmt, va_list va)
|
||||
{
|
||||
if (!fmt) return;
|
||||
va_list va2;
|
||||
@ -1120,11 +1133,11 @@ void Dqn_StringBuilder_VFmtAppend(Dqn_StringBuilder<N> *builder, char const *fmt
|
||||
}
|
||||
|
||||
template <Dqn_isize N>
|
||||
void Dqn_StringBuilder_FmtAppend(Dqn_StringBuilder<N> *builder, char const *fmt, ...)
|
||||
void Dqn_StringBuilder_AppendFmtF(Dqn_StringBuilder<N> *builder, char const *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
Dqn_StringBuilder_VFmtAppend(builder, fmt, va);
|
||||
Dqn_StringBuilder_AppendFmtV(builder, fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
@ -1176,22 +1189,22 @@ template <typename T>
|
||||
struct Dqn_Slice
|
||||
{
|
||||
T *data;
|
||||
Dqn_isize len;
|
||||
Dqn_isize size;
|
||||
|
||||
T const &operator[] (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
||||
T &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
||||
T const &operator[] (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < size, "%d >= 0 && %d < %d", i, size); return data[i]; }
|
||||
T &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < size, "%d >= 0 && %d < %d", i, size); return data[i]; }
|
||||
T const *begin () const { return data; }
|
||||
T const *end () const { return data + len; }
|
||||
T const *end () const { return data + size; }
|
||||
T *begin () { return data; }
|
||||
T *end () { return data + len; }
|
||||
T const *operator+ (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; }
|
||||
T *operator+ (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; }
|
||||
T *end () { return data + size; }
|
||||
T const *operator+ (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < size, "%d >= 0 && %d < %d", i, size); return data + i; }
|
||||
T *operator+ (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < size, "%d >= 0 && %d < %d", i, size); return data + i; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
Dqn_b32 operator==(Dqn_Slice<T> const &lhs, Dqn_Slice<T> const &rhs)
|
||||
{
|
||||
Dqn_b32 result = lhs.len == rhs.len && lhs.data == rhs.data;
|
||||
Dqn_b32 result = lhs.size == rhs.size && lhs.data == rhs.data;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1199,56 +1212,55 @@ template <typename T, Dqn_isize N>
|
||||
inline Dqn_Slice<T> Dqn_Slice_InitWithArray(T (&array)[N])
|
||||
{
|
||||
Dqn_Slice<T> result = {};
|
||||
result.len = N;
|
||||
result.size = N;
|
||||
result.data = array;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <typename T> inline Dqn_Slice<T> Dqn_Slice_Allocate(Dqn_Allocator *allocator, Dqn_isize len, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes)
|
||||
template <typename T> inline Dqn_Slice<T> Dqn_Slice_Allocate(Dqn_Allocator *allocator, Dqn_isize size, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes)
|
||||
{
|
||||
Dqn_Slice<T> result = {};
|
||||
result.len = len;
|
||||
result.data = DQN_CAST(T *) Dqn_Allocator_Allocate(allocator, (sizeof(T) * len), alignof(T), zero_mem);
|
||||
result.size = size;
|
||||
result.data = DQN_CAST(T *) Dqn_Allocator_Allocate(allocator, (sizeof(T) * size), alignof(T), zero_mem);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T> inline Dqn_Slice<T> Dqn_Slice_CopyNullTerminated(Dqn_Allocator *allocator, T const *src, Dqn_isize len)
|
||||
template <typename T> inline Dqn_Slice<T> Dqn_Slice_CopyNullTerminated(Dqn_Allocator *allocator, T const *src, Dqn_isize size)
|
||||
{
|
||||
Dqn_Slice<T> result = {};
|
||||
result.len = len;
|
||||
result.data = DQN_CAST(T *) Dqn_Allocator_Allocate(allocator, (sizeof(T) * len) + 1, alignof(T), Dqn_ZeroMem::No);
|
||||
DQN_MEMCOPY(result.data, src, len * sizeof(T));
|
||||
result.buf[len] = 0;
|
||||
result.size = size;
|
||||
result.data = DQN_CAST(T *) Dqn_Allocator_Allocate(allocator, (sizeof(T) * size) + 1, alignof(T), Dqn_ZeroMem::No);
|
||||
DQN_MEMCOPY(result.data, src, size * sizeof(T));
|
||||
result.buf[size] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T> inline Dqn_Slice<T> Dqn_Slice_CopyNullTerminated(Dqn_Allocator *allocator, Dqn_Slice<T> const src)
|
||||
{
|
||||
Dqn_Slice<T> result = Dqn_Slice_CopyNullTerminated(allocator, src.data, src.len);
|
||||
Dqn_Slice<T> result = Dqn_Slice_CopyNullTerminated(allocator, src.data, src.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T> inline Dqn_Slice<T> Dqn_Slice_Copy(Dqn_Allocator *allocator, T const *src, Dqn_isize len)
|
||||
template <typename T> inline Dqn_Slice<T> Dqn_Slice_Copy(Dqn_Allocator *allocator, T const *src, Dqn_isize size)
|
||||
{
|
||||
Dqn_Slice<T> result = {};
|
||||
result.len = len;
|
||||
result.data = DQN_CAST(T *) Dqn_Allocator_Allocate(allocator, sizeof(T) * len, alignof(T), Dqn_ZeroMem::No);
|
||||
DQN_MEMCOPY(result.dat, src, len * sizeof(T));
|
||||
result.size = size;
|
||||
result.data = DQN_CAST(T *) Dqn_Allocator_Allocate(allocator, sizeof(T) * size, alignof(T), Dqn_ZeroMem::No);
|
||||
DQN_MEMCOPY(result.dat, src, size * sizeof(T));
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T> inline Dqn_Slice<T> Dqn_Slice_Copy(Dqn_Allocator *allocator, Dqn_Slice<T> const src)
|
||||
{
|
||||
Dqn_Slice<T> result = Dqn_Slice_Copy(allocator, src.data, src.len);
|
||||
Dqn_Slice<T> result = Dqn_Slice_Copy(allocator, src.data, src.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T> inline bool Dqn_Slice_Equals(Dqn_Slice<T> const a, Dqn_Slice<T> const b)
|
||||
{
|
||||
bool result = false;
|
||||
if (a.len != b.len) return result;
|
||||
result = (memcmp(a.data, b.data, a.len) == 0);
|
||||
if (a.size != b.size) return result;
|
||||
result = (memcmp(a.data, b.data, a.size) == 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1258,32 +1270,31 @@ template <typename T> inline bool Dqn_Slice_Equals(Dqn_Slice<T> const a, Dqn_Sli
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T> void Dqn__EraseStableFromCArray(T *array, Dqn_isize len, Dqn_isize max, Dqn_isize index)
|
||||
template <typename T> void Dqn__EraseStableFromCArray(T *array, Dqn_isize size, Dqn_isize max, Dqn_isize index)
|
||||
{
|
||||
DQN_ASSERT(index >= 0 && index < len);
|
||||
DQN_ASSERT(len <= max); (void)max;
|
||||
Dqn_isize next_index = DQN_MIN(index + 1, len);
|
||||
Dqn_usize bytes_to_copy = (len - next_index) * sizeof(T);
|
||||
DQN_ASSERT(index >= 0 && index < size);
|
||||
DQN_ASSERT(size <= max); (void)max;
|
||||
Dqn_isize next_index = DQN_MIN(index + 1, size);
|
||||
Dqn_usize bytes_to_copy = (size - next_index) * sizeof(T);
|
||||
memmove(array + index, array + next_index, bytes_to_copy);
|
||||
}
|
||||
|
||||
|
||||
#define DQN_FIXED_ARRAY_TEMPLATE template <typename T, int MAX_>
|
||||
#define DQN_FIXED_ARRAY_TEMPLATE_DECL Dqn_FixedArray<T, MAX_>
|
||||
DQN_FIXED_ARRAY_TEMPLATE struct Dqn_FixedArray
|
||||
{
|
||||
T data[MAX_];
|
||||
Dqn_isize len;
|
||||
Dqn_isize size;
|
||||
|
||||
T &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i <= len, "%jd >= 0 && %jd < %jd", i, len); return data[i]; }
|
||||
T &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i <= size, "%jd >= 0 && %jd < %jd", i, size); return data[i]; }
|
||||
T *begin () { return data; }
|
||||
T *end () { return data + len; }
|
||||
T *operator+ (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i <= len, "%jd >= 0 && %jd < %jd", i, len); return data + i; }
|
||||
T *end () { return data + size; }
|
||||
T *operator+ (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i <= size, "%jd >= 0 && %jd < %jd", i, size); return data + i; }
|
||||
|
||||
T const &operator[] (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i <= len, "%jd >= 0 && %jd < %jd", i, i, len); return data[i]; }
|
||||
T const &operator[] (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i <= size, "%jd >= 0 && %jd < %jd", i, i, size); return data[i]; }
|
||||
T const *begin () const { return data; }
|
||||
T const *end () const { return data + len; }
|
||||
T const *operator+ (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i <= len, "%jd >= 0 && %jd < %jd", i, len); return data + i; }
|
||||
T const *end () const { return data + size; }
|
||||
T const *operator+ (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i <= size, "%jd >= 0 && %jd < %jd", i, size); return data + i; }
|
||||
};
|
||||
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
@ -1304,69 +1315,69 @@ DQN_FIXED_ARRAY_TEMPLATE_DECL Dqn_FixedArray_Init(T const *item, int num)
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
T * Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const *items, Dqn_isize num)
|
||||
{
|
||||
DQN_ASSERT(a->len + num <= MAX_);
|
||||
T *result = static_cast<T *>(DQN_MEMCOPY(a->data + a->len, items, sizeof(T) * num));
|
||||
a->len += num;
|
||||
DQN_ASSERT(a->size + num <= MAX_);
|
||||
T *result = static_cast<T *>(DQN_MEMCOPY(a->data + a->size, items, sizeof(T) * num));
|
||||
a->size += num;
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
T * Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const item)
|
||||
{
|
||||
DQN_ASSERT(a->len < MAX_);
|
||||
a->data[a->len++] = item;
|
||||
return &a->data[a->len - 1];
|
||||
DQN_ASSERT(a->size < MAX_);
|
||||
a->data[a->size++] = item;
|
||||
return &a->data[a->size - 1];
|
||||
}
|
||||
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
T * Dqn_FixedArray_Make(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize num)
|
||||
{
|
||||
DQN_ASSERT(a->len + num <= MAX_);
|
||||
T *result = a->data + a->len;
|
||||
a->len += num;
|
||||
DQN_ASSERT(a->size + num <= MAX_);
|
||||
T *result = a->data + a->size;
|
||||
a->size += num;
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
void Dqn_FixedArray_Clear(DQN_FIXED_ARRAY_TEMPLATE_DECL *a)
|
||||
{
|
||||
a->len = 0;
|
||||
a->size = 0;
|
||||
}
|
||||
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
void Dqn_FixedArray_EraseStable(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize index)
|
||||
{
|
||||
Dqn__EraseStableFromCArray<T>(a->data, a->len--, MAX_, index);
|
||||
Dqn__EraseStableFromCArray<T>(a->data, a->size--, MAX_, index);
|
||||
}
|
||||
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
void Dqn_FixedArray_EraseUnstable(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize index)
|
||||
{
|
||||
DQN_ASSERT(index >= 0 && index < a->len);
|
||||
if (--a->len == 0) return;
|
||||
a->data[index] = a->data[a->len];
|
||||
DQN_ASSERT(index >= 0 && index < a->size);
|
||||
if (--a->size == 0) return;
|
||||
a->data[index] = a->data[a->size];
|
||||
}
|
||||
|
||||
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
void Dqn_FixedArray_Pop(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize num = 1)
|
||||
{
|
||||
DQN_ASSERT(a->len - num >= 0);
|
||||
a->len -= num;
|
||||
DQN_ASSERT(a->size - num >= 0);
|
||||
a->size -= num;
|
||||
}
|
||||
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
T * Dqn_FixedArray_Peek(DQN_FIXED_ARRAY_TEMPLATE_DECL *a)
|
||||
{
|
||||
T *result = (a->len == 0) ? nullptr : a->data + (a->len - 1);
|
||||
T *result = (a->size == 0) ? nullptr : a->data + (a->size - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
T Dqn_FixedArray_PeekCopy(DQN_FIXED_ARRAY_TEMPLATE_DECL const *a)
|
||||
{
|
||||
DQN_ASSERT(a->len > 0);
|
||||
T const *result = a->data + (a->len - 1);
|
||||
DQN_ASSERT(a->size > 0);
|
||||
T const *result = a->data + (a->size - 1);
|
||||
return *result;
|
||||
}
|
||||
|
||||
@ -1418,7 +1429,7 @@ T *Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T *find)
|
||||
DQN_FIXED_ARRAY_TEMPLATE
|
||||
Dqn_Slice<T> Dqn_FixedArray_Slice(DQN_FIXED_ARRAY_TEMPLATE_DECL *a)
|
||||
{
|
||||
Dqn_Slice<T> result = {a->data, a->len};
|
||||
Dqn_Slice<T> result = {a->data, a->size};
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1431,47 +1442,47 @@ template <typename T> struct Dqn_Array
|
||||
{
|
||||
Dqn_Allocator allocator;
|
||||
T *data;
|
||||
Dqn_isize len;
|
||||
Dqn_isize size;
|
||||
Dqn_isize max;
|
||||
|
||||
T const operator[](Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
||||
T operator[](Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
||||
T const operator[](Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < size, "%d >= 0 && %d < %d", i, size); return data[i]; }
|
||||
T operator[](Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < size, "%d >= 0 && %d < %d", i, size); return data[i]; }
|
||||
T const *begin () const { return data; }
|
||||
T const *end () const { return data + len; }
|
||||
T const *end () const { return data + size; }
|
||||
T *begin () { return data; }
|
||||
T *end () { return data + len; }
|
||||
T const *operator+(Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; }
|
||||
T *operator+(Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data + i; }
|
||||
T *end () { return data + size; }
|
||||
T const *operator+(Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < size, "%d >= 0 && %d < %d", i, size); return data + i; }
|
||||
T *operator+(Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < size, "%d >= 0 && %d < %d", i, size); return data + i; }
|
||||
};
|
||||
|
||||
template <typename T> Dqn_Array<T> Dqn_Array_InitWithMemory(T *memory, Dqn_isize max, Dqn_isize len = 0)
|
||||
template <typename T> Dqn_Array<T> Dqn_Array_InitWithMemory(T *memory, Dqn_isize max, Dqn_isize size = 0)
|
||||
{
|
||||
Dqn_Array<T> result = {};
|
||||
result.allocator = Dqn_Allocator_InitWithNull();
|
||||
result.data = memory;
|
||||
result.len = len;
|
||||
result.size = size;
|
||||
result.max = max;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T> Dqn_Array<T> Dqn_Array_InitWithAllocatorNoGrow(Dqn_Allocator *allocator, Dqn_isize max, Dqn_isize len = 0, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes)
|
||||
template <typename T> Dqn_Array<T> Dqn_Array_InitWithAllocatorNoGrow(Dqn_Allocator *allocator, Dqn_isize max, Dqn_isize size = 0, Dqn_ZeroMem zero_mem = Dqn_ZeroMem::Yes)
|
||||
{
|
||||
T *memory = DQN_CAST(T *)Dqn_Allocator_Allocate(allocator, sizeof(T) * max, alignof(T), zero_mem);
|
||||
Dqn_Array<T> result = Dqn_Array_InitWithMemory(memory, max, len);
|
||||
Dqn_Array<T> result = Dqn_Array_InitWithMemory(memory, max, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
template <typename T> bool Dqn_Array_Reserve(Dqn_Array<T> *a, Dqn_isize size)
|
||||
{
|
||||
if (size <= a->len) return true;
|
||||
if (size <= a->size) return true;
|
||||
T *new_ptr = DQN_CAST(T *)Dqn_Allocator_Allocate(&a->allocator, sizeof(T) * size, alignof(T));
|
||||
if (!new_ptr) return false;
|
||||
|
||||
if (a->data)
|
||||
{
|
||||
// NOTE(doyle): Realloc, I don't like and don't support. Use virtual arrays
|
||||
DQN_MEMCOPY(new_ptr, a->data, a->len * sizeof(T));
|
||||
DQN_MEMCOPY(new_ptr, a->data, a->size * sizeof(T));
|
||||
Dqn_Allocator_Free(&a->allocator, a->data);
|
||||
}
|
||||
|
||||
@ -1487,11 +1498,11 @@ template <typename T> void Dqn_Array_Free(Dqn_Array<T> *a)
|
||||
|
||||
template <typename T> bool Dqn_Array__GrowIfNeeded(Dqn_Array<T> *a, Dqn_isize num_to_add)
|
||||
{
|
||||
Dqn_isize new_len = a->len + num_to_add;
|
||||
bool result = true;
|
||||
if (new_len > a->max)
|
||||
Dqn_isize new_size = a->size + num_to_add;
|
||||
bool result = true;
|
||||
if (new_size > a->max)
|
||||
{
|
||||
Dqn_isize num_items = DQN_MAX(4, DQN_MAX(new_len, (a->max * 2)));
|
||||
Dqn_isize num_items = DQN_MAX(4, DQN_MAX(new_size, (a->max * 2)));
|
||||
result = Dqn_Array_Reserve(a, num_items);
|
||||
}
|
||||
|
||||
@ -1502,8 +1513,8 @@ template <typename T> T * Dqn_Array_Add(Dqn_Array<T> *a, T const *items, Dqn_isi
|
||||
{
|
||||
if (!Dqn_Array__GrowIfNeeded(a, num))
|
||||
return nullptr;
|
||||
T *result = static_cast<T *>(DQN_MEMCOPY(a->data + a->len, items, sizeof(T) * num));
|
||||
a->len += num;
|
||||
T *result = static_cast<T *>(DQN_MEMCOPY(a->data + a->size, items, sizeof(T) * num));
|
||||
a->size += num;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1511,45 +1522,45 @@ template <typename T> T * Dqn_Array_Add(Dqn_Array<T> *a, T const item)
|
||||
{
|
||||
if (!Dqn_Array__GrowIfNeeded(a, 1))
|
||||
return nullptr;
|
||||
a->data[a->len++] = item;
|
||||
return &a->data[a->len - 1];
|
||||
a->data[a->size++] = item;
|
||||
return &a->data[a->size - 1];
|
||||
}
|
||||
template <typename T> T * Dqn_Array_Make(Dqn_Array<T> *a, Dqn_isize num)
|
||||
{
|
||||
if (!Dqn_Array__GrowIfNeeded(a, num))
|
||||
return nullptr;
|
||||
T *result = a->data + a->len;
|
||||
a->len += num;
|
||||
T *result = a->data + a->size;
|
||||
a->size += num;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T> void Dqn_Array_Clear(Dqn_Array<T> *a, bool zero_mem = false)
|
||||
{
|
||||
a->len = 0;
|
||||
a->size = 0;
|
||||
if (zero_mem) DQN_MEMSET(a->data, 0, sizeof(T) * a->max);
|
||||
}
|
||||
|
||||
template <typename T> void Dqn_Array_EraseStable(Dqn_Array<T> *a, Dqn_isize index)
|
||||
{
|
||||
Dqn__EraseStableFromCArray<T>(a->data, a->len--, a->max, index);
|
||||
Dqn__EraseStableFromCArray<T>(a->data, a->size--, a->max, index);
|
||||
}
|
||||
|
||||
template <typename T> void Dqn_Array_EraseUnstable(Dqn_Array<T> *a, Dqn_isize index)
|
||||
{
|
||||
DQN_ASSERT(index >= 0 && index < a->len);
|
||||
if (--a->len == 0) return;
|
||||
a->data[index] = a->data[a->len];
|
||||
DQN_ASSERT(index >= 0 && index < a->size);
|
||||
if (--a->size == 0) return;
|
||||
a->data[index] = a->data[a->size];
|
||||
}
|
||||
|
||||
template <typename T> void Dqn_Array_Pop(Dqn_Array<T> *a, Dqn_isize num)
|
||||
{
|
||||
DQN_ASSERT(a->len - num >= 0);
|
||||
a->len -= num;
|
||||
DQN_ASSERT(a->size - num >= 0);
|
||||
a->size -= num;
|
||||
}
|
||||
|
||||
template <typename T> T * Dqn_Array_Peek(Dqn_Array<T> *a)
|
||||
{
|
||||
T *result = (a->len == 0) ? nullptr : a->data + (a->len - 1);
|
||||
T *result = (a->size == 0) ? nullptr : a->data + (a->size - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1562,34 +1573,34 @@ template <Dqn_isize MAX_>
|
||||
struct Dqn_FixedString
|
||||
{
|
||||
union { char data[MAX_]; char str[MAX_]; char buf[MAX_]; };
|
||||
Dqn_isize len;
|
||||
Dqn_isize size;
|
||||
Dqn_isize max = MAX_;
|
||||
|
||||
Dqn_FixedString() { data[0] = 0; len = 0; }
|
||||
Dqn_FixedString() { data[0] = 0; size = 0; }
|
||||
Dqn_FixedString(char const *fmt, ...)
|
||||
{
|
||||
*this = {};
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
Dqn_FixedString_AppendVFmt(this, fmt, va);
|
||||
Dqn_FixedString_AppendFmtV(this, fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
Dqn_b32 operator==(Dqn_FixedString const &other) const
|
||||
{
|
||||
if (len != other.len) return false;
|
||||
bool result = memcmp(data, other.data, len);
|
||||
if (size != other.size) return false;
|
||||
bool result = memcmp(data, other.data, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
Dqn_b32 operator!=(Dqn_FixedString const &other) const { return !(*this == other); }
|
||||
|
||||
char const &operator[] (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
||||
char &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < len, "%d >= 0 && %d < %d", i, len); return data[i]; }
|
||||
char const &operator[] (Dqn_isize i) const { DQN_ASSERT_MSG(i >= 0 && i < size, "%d >= 0 && %d < %d", i, size); return data[i]; }
|
||||
char &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i < size, "%d >= 0 && %d < %d", i, size); return data[i]; }
|
||||
char const *begin () const { return data; }
|
||||
char const *end () const { return data + len; }
|
||||
char const *end () const { return data + size; }
|
||||
char *begin () { return data; }
|
||||
char *end () { return data + len; }
|
||||
char *end () { return data + size; }
|
||||
};
|
||||
|
||||
template <Dqn_isize MAX_> int Dqn_FixedString_Capacity(Dqn_FixedString<MAX_> *)
|
||||
@ -1599,46 +1610,46 @@ template <Dqn_isize MAX_> int Dqn_FixedString_Capacity(Dqn_FixedString<MAX_> *)
|
||||
}
|
||||
|
||||
template <Dqn_isize MAX_> void Dqn_FixedString_Clear(Dqn_FixedString<MAX_> *str) { *str = {}; }
|
||||
template <Dqn_isize MAX_> Dqn_b32 Dqn_FixedString_AppendVFmt(Dqn_FixedString<MAX_> *str, char const *fmt, va_list va)
|
||||
template <Dqn_isize MAX_> Dqn_b32 Dqn_FixedString_AppendFmtV(Dqn_FixedString<MAX_> *str, char const *fmt, va_list va)
|
||||
{
|
||||
va_list va2;
|
||||
va_copy(va2, va);
|
||||
Dqn_isize require = stbsp_vsnprintf(nullptr, 0, fmt, va) + 1;
|
||||
Dqn_isize space = MAX_ - str->len;
|
||||
Dqn_isize space = MAX_ - str->size;
|
||||
Dqn_b32 result = require <= space;
|
||||
DQN_ASSERT(require <= space);
|
||||
str->len += stbsp_vsnprintf(str->data + str->len, static_cast<int>(space), fmt, va2);
|
||||
str->size += stbsp_vsnprintf(str->data + str->size, static_cast<int>(space), fmt, va2);
|
||||
va_end(va2);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <Dqn_isize MAX_> Dqn_b32 Dqn_FixedString_AppendFmt(Dqn_FixedString<MAX_> *str, char const *fmt, ...)
|
||||
template <Dqn_isize MAX_> Dqn_b32 Dqn_FixedString_AppendFmtF(Dqn_FixedString<MAX_> *str, char const *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
Dqn_b32 result = Dqn_FixedString_AppendVFmt(str, fmt, va);
|
||||
Dqn_b32 result = Dqn_FixedString_AppendFmtV(str, fmt, va);
|
||||
va_end(va);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <Dqn_isize MAX_> Dqn_b32 Dqn_FixedString_Append(Dqn_FixedString<MAX_> *str, char const *src, Dqn_isize len = -1)
|
||||
template <Dqn_isize MAX_> Dqn_b32 Dqn_FixedString_Append(Dqn_FixedString<MAX_> *str, char const *src, Dqn_isize size = -1)
|
||||
{
|
||||
if (len == -1) len = DQN_CAST(Dqn_isize)strlen(src);
|
||||
Dqn_isize space = MAX_ - str->len;
|
||||
if (size == -1) size = DQN_CAST(Dqn_isize)DQN_STRLEN(src);
|
||||
Dqn_isize space = MAX_ - str->size;
|
||||
|
||||
Dqn_b32 result = true;
|
||||
DQN_ASSERT_MSG_IF(len >= space, "len: %jd, space: %jd", len, space)
|
||||
DQN_ASSERT_MSG_IF(size >= space, "size: %jd, space: %jd", size, space)
|
||||
return false;
|
||||
|
||||
DQN_MEMCOPY(str->data + str->len, src, len);
|
||||
str->len += len;
|
||||
str->str[str->len] = 0;
|
||||
DQN_MEMCOPY(str->data + str->size, src, size);
|
||||
str->size += size;
|
||||
str->str[str->size] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <Dqn_isize MAX_> Dqn_String Dqn_FixedString_ToString(Dqn_FixedString<MAX_> const *str)
|
||||
{
|
||||
Dqn_String result = { str->str, str->len };
|
||||
Dqn_String result = { str->str, str->size };
|
||||
return result;
|
||||
}
|
||||
#endif // DQN_H
|
||||
@ -1655,7 +1666,7 @@ template <Dqn_isize MAX_> Dqn_String Dqn_FixedString_ToString(Dqn_FixedString<MA
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Logging
|
||||
// NOTE: Dqn_Log
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
DQN_API void Dqn_LogV(Dqn_LogType type, char const *file, Dqn_usize file_len, char const *func, Dqn_usize func_len, Dqn_usize line, char const *fmt, va_list va)
|
||||
@ -1675,13 +1686,14 @@ DQN_API void Dqn_LogV(Dqn_LogType type, char const *file, Dqn_usize file_len, ch
|
||||
|
||||
FILE *handle = (type == Dqn_LogType::Error) ? stderr : stdout;
|
||||
fprintf(handle,
|
||||
"%.*s %05zu %.*s %s ",
|
||||
"%s %.*s %05zu %.*s ",
|
||||
Dqn_LogTypeString[DQN_CAST(int) type],
|
||||
(int)file_ptr_len,
|
||||
file_ptr,
|
||||
line,
|
||||
(int)func_len,
|
||||
func,
|
||||
Dqn_LogTypeString[DQN_CAST(int)type]);
|
||||
func
|
||||
);
|
||||
|
||||
vfprintf(handle, fmt, va);
|
||||
fputc('\n', handle);
|
||||
@ -1695,18 +1707,7 @@ DQN_API void Dqn_Log(Dqn_LogType type, char const *file, Dqn_usize file_len, cha
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Core Config
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
DQN_API Dqn_Core Dqn__CoreDefault()
|
||||
{
|
||||
Dqn_Core result = {};
|
||||
result.Log = Dqn_Log;
|
||||
return result;
|
||||
}
|
||||
Dqn_Core dqn_core = Dqn__CoreDefault();
|
||||
Dqn_LogProc *dqn_log = Dqn_Log;
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
@ -2076,7 +2077,7 @@ DQN_API Dqn_f32 Dqn_LerpF32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b)
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Dqn_Allocator
|
||||
// NOTE: Dqn_Allocator
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
DQN_API Dqn_Allocator Dqn_Allocator_InitWithNull()
|
||||
@ -2108,11 +2109,6 @@ DQN_API Dqn_Allocator Dqn_Allocator_InitWithArena(Dqn_ArenaAllocator *arena)
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// NOTE: Dqn_Allocator
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
DQN_API void *Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_isize size, Dqn_u8 alignment, Dqn_ZeroMem zero_mem)
|
||||
{
|
||||
char *result = nullptr;
|
||||
@ -2151,6 +2147,7 @@ DQN_API void *Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_isize size, D
|
||||
if (result)
|
||||
{
|
||||
allocator->allocations++;
|
||||
allocator->total_allocations++;
|
||||
allocator->total_bytes_allocated += size;
|
||||
}
|
||||
return result;
|
||||
@ -2183,7 +2180,6 @@ void Dqn_Allocator_Free(Dqn_Allocator *allocator, void *ptr)
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
allocator->total_allocations++;
|
||||
allocator->allocations--;
|
||||
DQN_ASSERT(allocator->allocations >= 0);
|
||||
}
|
||||
@ -2563,81 +2559,82 @@ DQN_API char Dqn_Char_ToLower(char ch)
|
||||
DQN_API Dqn_b32 Dqn_String_Compare(Dqn_String const lhs, Dqn_String const rhs)
|
||||
{
|
||||
Dqn_b32 result = false;
|
||||
if (lhs.len == rhs.len)
|
||||
result = (memcmp(lhs.str, rhs.str, DQN_CAST(size_t)lhs.len) == 0);
|
||||
if (lhs.size == rhs.size)
|
||||
result = (memcmp(lhs.str, rhs.str, DQN_CAST(size_t)lhs.size) == 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_b32 Dqn_String_CompareCaseInsensitive(Dqn_String const lhs, Dqn_String const rhs)
|
||||
{
|
||||
Dqn_b32 result = (lhs.len == rhs.len);
|
||||
if (result)
|
||||
{
|
||||
for (Dqn_isize index = 0; index < lhs.len && result; index++)
|
||||
result = (Dqn_Char_ToLower(lhs.str[index]) == Dqn_Char_ToLower(rhs.str[index]));
|
||||
}
|
||||
Dqn_b32 result = (lhs.size == rhs.size);
|
||||
for (Dqn_isize index = 0; index < lhs.size && result; index++)
|
||||
result = (Dqn_Char_ToLower(lhs.str[index]) == Dqn_Char_ToLower(rhs.str[index]));
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_String Dqn_String_Copy(Dqn_Allocator *allocator, Dqn_String const src)
|
||||
DQN_API Dqn_String Dqn_String_Copy(Dqn_String const src, Dqn_Allocator *allocator)
|
||||
{
|
||||
Dqn_String result = src;
|
||||
result.str = DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, result.len, alignof(char));
|
||||
DQN_MEMCOPY(result.str, src.str, DQN_CAST(size_t)result.len);
|
||||
result.str = allocator ? DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, result.size, alignof(char)) :
|
||||
DQN_CAST(char *)DQN_MALLOC(result.size);
|
||||
DQN_MEMCOPY(result.str, src.str, DQN_CAST(size_t)result.size);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_String Dqn_String_TrimWhitespaceAround(Dqn_String src)
|
||||
{
|
||||
Dqn_String result = src;
|
||||
if (src.len <= 0) return result;
|
||||
if (src.size <= 0) return result;
|
||||
|
||||
char *start = src.str;
|
||||
char *end = start + (src.len - 1);
|
||||
char *end = start + (src.size - 1);
|
||||
while (Dqn_Char_IsWhitespace(start[0])) start++;
|
||||
while (end != start && Dqn_Char_IsWhitespace(end[0])) end--;
|
||||
|
||||
result.str = start;
|
||||
result.len = (end - start) + 1;
|
||||
result.str = start;
|
||||
result.size = (end - start) + 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_b32 operator==(Dqn_String const &lhs, Dqn_String const &rhs)
|
||||
{
|
||||
Dqn_b32 result = lhs.len == rhs.len && (DQN_MEMCMP(lhs.str, rhs.str, lhs.len) == 0);
|
||||
Dqn_b32 result = lhs.size == rhs.size && (DQN_MEMCMP(lhs.str, rhs.str, lhs.size) == 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// NOTE: Dqn_Asprintf (Allocate Sprintf)
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
DQN_API Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, va_list va)
|
||||
DQN_API Dqn_String Dqn_String_FmtV(Dqn_Allocator *allocator, char const *fmt, va_list va)
|
||||
{
|
||||
Dqn_String result = {};
|
||||
va_list va2;
|
||||
va_copy(va2, va);
|
||||
result.len = stbsp_vsnprintf(nullptr, 0, fmt, va);
|
||||
result.str = DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, result.len + 1, alignof(char));
|
||||
result.size = stbsp_vsnprintf(nullptr, 0, fmt, va);
|
||||
result.str = allocator ? DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, result.size + 1, alignof(char))
|
||||
: DQN_CAST(char *)DQN_MALLOC(result.size + 1);
|
||||
if (result.str)
|
||||
{
|
||||
stbsp_vsnprintf(result.str, Dqn_Safe_TruncateISizeToInt(result.len + 1), fmt, va2);
|
||||
result.str[result.len] = 0;
|
||||
stbsp_vsnprintf(result.str, Dqn_Safe_TruncateISizeToInt(result.size + 1), fmt, va2);
|
||||
result.str[result.size] = 0;
|
||||
}
|
||||
va_end(va2);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, ...)
|
||||
DQN_API Dqn_String Dqn_String_FmtF(Dqn_Allocator *allocator, char const *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
Dqn_String result = Dqn_Asprintf(allocator, fmt, va);
|
||||
Dqn_String result = Dqn_String_FmtV(allocator, fmt, va);
|
||||
va_end(va);
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API void Dqn_String_Free(Dqn_String *string, Dqn_Allocator *allocator)
|
||||
{
|
||||
if (allocator) Dqn_Allocator_Free(allocator, string->str);
|
||||
else DQN_FREE(string->str);
|
||||
*string = {};
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// NOTE: Dqn_Str
|
||||
@ -2856,17 +2853,23 @@ DQN_API Dqn_i64 Dqn_Str_ToI64(char const *buf, int len)
|
||||
// NOTE: Dqn_File
|
||||
//
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
DQN_API char *Dqn_File_ReadAll(Dqn_Allocator *allocator, char const *file, Dqn_isize *file_size)
|
||||
DQN_API char *Dqn_File_ReadEntireFile(char const *file, Dqn_isize *file_size, Dqn_Allocator *allocator)
|
||||
{
|
||||
Dqn_isize file_size_ = 0;
|
||||
if (!file_size) file_size = &file_size_;
|
||||
if (!file_size)
|
||||
file_size = &file_size_;
|
||||
|
||||
FILE *file_handle = fopen(file, "rb");
|
||||
if (!file_handle) return nullptr;
|
||||
DQN_DEFER { fclose(file_handle); };
|
||||
if (!file_handle)
|
||||
{
|
||||
DQN_LOG_E("Failed to open file '%s' using fopen\n", file);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DQN_DEFER { fclose(file_handle); };
|
||||
fseek(file_handle, 0, SEEK_END);
|
||||
*file_size = ftell(file_handle);
|
||||
|
||||
if (DQN_CAST(long)(*file_size) == -1L)
|
||||
{
|
||||
DQN_LOG_E("Failed to determine '%s' file size using ftell\n", file);
|
||||
@ -2874,16 +2877,20 @@ DQN_API char *Dqn_File_ReadAll(Dqn_Allocator *allocator, char const *file, Dqn_i
|
||||
}
|
||||
|
||||
rewind(file_handle);
|
||||
auto *result = DQN_CAST(char *)Dqn_Allocator_Allocate(allocator, *file_size + 1, alignof(char));
|
||||
auto *result = allocator ? DQN_CAST(char *) Dqn_Allocator_Allocate(allocator, *file_size + 1, alignof(char))
|
||||
: DQN_CAST(char *) DQN_MALLOC(*file_size + 1);
|
||||
if (!result)
|
||||
{
|
||||
DQN_LOG_M("Failed to allocate %td bytes to read file '%s'\n", file_size + 1, file);
|
||||
DQN_LOG_M("Failed to allocate %td bytes to read file '%s'\n", *file_size + 1, file);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
result[*file_size] = 0;
|
||||
if (fread(result, DQN_CAST(size_t)(*file_size), 1, file_handle) != 1)
|
||||
{
|
||||
if (allocator) Dqn_Allocator_Free(allocator, result);
|
||||
else DQN_FREE(result);
|
||||
|
||||
DQN_LOG_E("Failed to read %td bytes into buffer from '%s'\n", *file_size, file);
|
||||
return nullptr;
|
||||
}
|
||||
@ -2891,6 +2898,26 @@ DQN_API char *Dqn_File_ReadAll(Dqn_Allocator *allocator, char const *file, Dqn_i
|
||||
return result;
|
||||
}
|
||||
|
||||
DQN_API Dqn_b32 Dqn_File_WriteEntireFile(char const *file, char const *buffer, Dqn_isize buffer_size)
|
||||
{
|
||||
FILE *file_handle = fopen(file, "w+b");
|
||||
if (!file_handle)
|
||||
{
|
||||
DQN_LOG_E("Failed to open file '%s' using fopen\n", file);
|
||||
return false;
|
||||
}
|
||||
|
||||
DQN_DEFER { fclose(file_handle); };
|
||||
Dqn_usize write_count = fwrite(buffer, buffer_size, 1 /*count*/, file_handle);
|
||||
|
||||
if (write_count != 1)
|
||||
{
|
||||
DQN_LOG_E("Failed to write to file '%s' using fwrite\n", file);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// NOTE: Utilities
|
||||
|
@ -32,13 +32,13 @@ struct TestingState
|
||||
#define TEST_START_SCOPE(testing_state, test_name) \
|
||||
DQN_DEFER \
|
||||
{ \
|
||||
if (testing_state.test.fail_expr.len == 0) testing_state.num_tests_ok_in_group++; \
|
||||
if (testing_state.test.fail_expr.size == 0) testing_state.num_tests_ok_in_group++; \
|
||||
TestState_PrintResult(&testing_state.test); \
|
||||
Dqn_ArenaAllocator_ResetUsage(&testing_state.arena_, Dqn_ZeroMem::No); \
|
||||
testing_state.allocator = Dqn_Allocator_InitWithArena(&testing_state.arena_); \
|
||||
Dqn_ArenaAllocator_ResetUsage(&testing_state.arena_, Dqn_ZeroMem::No); \
|
||||
testing_state.allocator = Dqn_Allocator_InitWithArena(&testing_state.arena_); \
|
||||
testing_state.test = {}; \
|
||||
}; \
|
||||
testing_state.test.name = Dqn_Asprintf(&testing_state.allocator, test_name); \
|
||||
testing_state.test.name = Dqn_String_FmtF(&testing_state.allocator, test_name); \
|
||||
testing_state.test.scope_started = true; \
|
||||
testing_state.num_tests_in_group++
|
||||
|
||||
@ -54,8 +54,8 @@ struct TestingState
|
||||
DQN_ASSERT(testing_state.test.scope_started); \
|
||||
if (!(expr)) \
|
||||
{ \
|
||||
testing_state.test.fail_expr = Dqn_Asprintf(&testing_state.allocator, #expr); \
|
||||
testing_state.test.fail_msg = Dqn_Asprintf(&testing_state.allocator, msg, ##__VA_ARGS__); \
|
||||
testing_state.test.fail_expr = Dqn_String_FmtF(&testing_state.allocator, #expr); \
|
||||
testing_state.test.fail_msg = Dqn_String_FmtF(&testing_state.allocator, msg, ##__VA_ARGS__); \
|
||||
}
|
||||
|
||||
#define TEST_EXPECT(testing_state, expr) TEST_EXPECT_MSG(testing_state, expr, "")
|
||||
@ -69,11 +69,11 @@ void TestingState_PrintGroupResult(TestingState const *result)
|
||||
|
||||
bool all_tests_passed = (result->num_tests_ok_in_group == result->num_tests_in_group);
|
||||
char buf[256] = {};
|
||||
int len = snprintf(buf, Dqn_ArrayCount(buf), "%02d/%02d Tests Passed ", result->num_tests_ok_in_group, result->num_tests_in_group);
|
||||
Dqn_isize remaining_len = DESIRED_LEN - len - 1;
|
||||
remaining_len = (all_tests_passed) ? remaining_len - Dqn_CharCount(STATUS_OK) : remaining_len - Dqn_CharCount(STATUS_FAIL);
|
||||
remaining_len = DQN_MAX(remaining_len, 0);
|
||||
DQN_FOR_EACH(i, remaining_len) fprintf(stdout, " ");
|
||||
int size = snprintf(buf, Dqn_ArrayCount(buf), "%02d/%02d Tests Passed ", result->num_tests_ok_in_group, result->num_tests_in_group);
|
||||
Dqn_isize remaining_size = DESIRED_LEN - size - 1;
|
||||
remaining_size = (all_tests_passed) ? remaining_size - Dqn_CharCount(STATUS_OK) : remaining_size - Dqn_CharCount(STATUS_FAIL);
|
||||
remaining_size = DQN_MAX(remaining_size, 0);
|
||||
DQN_FOR_EACH(i, remaining_size) fprintf(stdout, " ");
|
||||
|
||||
fprintf(stdout, "%s", buf);
|
||||
if (result->num_tests_ok_in_group == result->num_tests_in_group)
|
||||
@ -91,11 +91,11 @@ void TestState_PrintResult(TestState const *result)
|
||||
char const STATUS_OK[] = "OK";
|
||||
char const STATUS_FAIL[] = "FAIL";
|
||||
|
||||
Dqn_isize remaining_len = DESIRED_LEN - result->name.len - Dqn_CharCount(INDENT);
|
||||
remaining_len = (result->fail_expr.str) ? remaining_len - Dqn_CharCount(STATUS_FAIL) : remaining_len - Dqn_CharCount(STATUS_OK);
|
||||
remaining_len = DQN_MAX(remaining_len, 0);
|
||||
Dqn_isize remaining_size = DESIRED_LEN - result->name.size - Dqn_CharCount(INDENT);
|
||||
remaining_size = (result->fail_expr.str) ? remaining_size - Dqn_CharCount(STATUS_FAIL) : remaining_size - Dqn_CharCount(STATUS_OK);
|
||||
remaining_size = DQN_MAX(remaining_size, 0);
|
||||
|
||||
DQN_FOR_EACH(i, remaining_len) fprintf(stdout, ".");
|
||||
DQN_FOR_EACH(i, remaining_size) fprintf(stdout, ".");
|
||||
if (result->fail_expr.str)
|
||||
{
|
||||
fprintf(stdout, ANSI_COLOR_RED "%s" ANSI_COLOR_RESET "\n", STATUS_FAIL);
|
||||
@ -224,7 +224,7 @@ static void UnitTests()
|
||||
{
|
||||
TEST_START_SCOPE(testing_state, "Fixed Memory: Test add single item and can't allocate more");
|
||||
int memory[4] = {};
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*size*/);
|
||||
Dqn_Array_Add(&array, 1);
|
||||
Dqn_Array_Add(&array, 2);
|
||||
Dqn_Array_Add(&array, 3);
|
||||
@ -233,11 +233,11 @@ static void UnitTests()
|
||||
TEST_EXPECT_MSG(testing_state, array.data[1] == 2, "array.data %d", array.data[1]);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[2] == 3, "array.data %d", array.data[2]);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[3] == 4, "array.data %d", array.data[3]);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 4, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 4, "array.size: %d", array.size);
|
||||
|
||||
int *added_item = Dqn_Array_Add(&array, 5);
|
||||
TEST_EXPECT(testing_state, added_item == nullptr);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 4, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 4, "array.size: %d", array.size);
|
||||
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||
}
|
||||
|
||||
@ -245,12 +245,12 @@ static void UnitTests()
|
||||
TEST_START_SCOPE(testing_state, "Fixed Memory: Test add array of items");
|
||||
int memory[4] = {};
|
||||
int DATA[] = {1, 2, 3};
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*size*/);
|
||||
Dqn_Array_Add(&array, DATA, Dqn_ArrayCount(DATA));
|
||||
TEST_EXPECT_MSG(testing_state, array.data[0] == 1, "array.data %d", array.data[0]);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[1] == 2, "array.data %d", array.data[1]);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[2] == 3, "array.data %d", array.data[2]);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 3, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 3, "array.size: %d", array.size);
|
||||
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||
}
|
||||
|
||||
@ -258,10 +258,10 @@ static void UnitTests()
|
||||
TEST_START_SCOPE(testing_state, "Fixed Memory: Test clear and clear with memory zeroed");
|
||||
int memory[4] = {};
|
||||
int DATA[] = {1, 2, 3};
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*size*/);
|
||||
Dqn_Array_Add(&array, DATA, Dqn_ArrayCount(DATA));
|
||||
Dqn_Array_Clear(&array, false /*zero_mem*/);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 0, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 0, "array.size: %d", array.size);
|
||||
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[0] == 1, "array.data %d. Clear but don't zero memory so old values should still remain", array.data[0]);
|
||||
|
||||
@ -273,41 +273,41 @@ static void UnitTests()
|
||||
TEST_START_SCOPE(testing_state, "Fixed Memory: Test erase stable and erase unstable");
|
||||
int memory[4] = {};
|
||||
int DATA[] = {1, 2, 3, 4};
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*size*/);
|
||||
Dqn_Array_Add(&array, DATA, Dqn_ArrayCount(DATA));
|
||||
Dqn_Array_EraseUnstable(&array, 1);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[0] == 1, "array.data %d", array.data[0]);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[1] == 4, "array.data %d", array.data[1]);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[2] == 3, "array.data %d", array.data[2]);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 3, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 3, "array.size: %d", array.size);
|
||||
|
||||
Dqn_Array_EraseStable(&array, 0);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[0] == 4, "array.data: %d", array.data[0]);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[1] == 3, "array.data: %d", array.data[1]);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 2, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 2, "array.size: %d", array.size);
|
||||
}
|
||||
|
||||
{
|
||||
TEST_START_SCOPE(testing_state, "Fixed Memory: Test array pop and peek");
|
||||
int memory[4] = {};
|
||||
int DATA[] = {1, 2, 3};
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*size*/);
|
||||
Dqn_Array_Add(&array, DATA, Dqn_ArrayCount(DATA));
|
||||
Dqn_Array_Pop(&array, 2);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[0] == 1, "array.data: %d", array.data[0]);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 1, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 1, "array.size: %d", array.size);
|
||||
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||
|
||||
int *peek_item = Dqn_Array_Peek(&array);
|
||||
TEST_EXPECT_MSG(testing_state, *peek_item == 1, "peek: %d", *peek_item);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 1, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 1, "array.size: %d", array.size);
|
||||
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||
}
|
||||
|
||||
{
|
||||
TEST_START_SCOPE(testing_state, "Fixed Memory: Test free on fixed memory array does nothing");
|
||||
int memory[4] = {};
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*len*/);
|
||||
Dqn_Array<int> array = Dqn_Array_InitWithMemory(memory, Dqn_ArrayCount(memory), 0 /*size*/);
|
||||
DQN_DEFER { Dqn_Array_Free(&array); };
|
||||
}
|
||||
}
|
||||
@ -320,7 +320,7 @@ static void UnitTests()
|
||||
DQN_DEFER { Dqn_Array_Free(&array); };
|
||||
|
||||
Dqn_Array_Reserve(&array, 4);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 0, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 0, "array.size: %d", array.size);
|
||||
TEST_EXPECT_MSG(testing_state, array.max == 4, "array.max: %d", array.max);
|
||||
|
||||
int DATA[] = {1, 2, 3, 4};
|
||||
@ -329,12 +329,12 @@ static void UnitTests()
|
||||
TEST_EXPECT_MSG(testing_state, array.data[1] == 2, "array.data: %d", array.data[1]);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[2] == 3, "array.data: %d", array.data[2]);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[3] == 4, "array.data: %d", array.data[3]);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 4, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 4, "array.size: %d", array.size);
|
||||
|
||||
int *added_item = Dqn_Array_Add(&array, 5);
|
||||
TEST_EXPECT_MSG(testing_state, *added_item == 5, "added_item: %d", *added_item);
|
||||
TEST_EXPECT_MSG(testing_state, array.data[4] == 5, "array.data: %d", array.data[4]);
|
||||
TEST_EXPECT_MSG(testing_state, array.len == 5, "array.len: %d", array.len);
|
||||
TEST_EXPECT_MSG(testing_state, array.size == 5, "array.size: %d", array.size);
|
||||
TEST_EXPECT_MSG(testing_state, array.max >= 5, "array.max: %d", array.max);
|
||||
}
|
||||
}
|
||||
@ -483,17 +483,17 @@ static void UnitTests()
|
||||
// NOTE: Dqn_StringBuilder_Append
|
||||
{
|
||||
{
|
||||
TEST_START_SCOPE(testing_state, "Append variable length strings and build using heap allocator");
|
||||
TEST_START_SCOPE(testing_state, "Append variable size strings and build using heap allocator");
|
||||
Dqn_StringBuilder<> builder = {};
|
||||
Dqn_StringBuilder_Append(&builder, "Abc", 1);
|
||||
Dqn_StringBuilder_Append(&builder, "cd");
|
||||
Dqn_isize len = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &len);
|
||||
Dqn_isize size = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &size);
|
||||
DQN_DEFER { Dqn_Allocator_Free(&allocator, result); };
|
||||
|
||||
char constexpr EXPECT_STR[] = "Acd";
|
||||
TEST_EXPECT_MSG(testing_state, len == Dqn_CharCountI(EXPECT_STR), "len: %zd", len);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, len) == 0, "result: %s", result);
|
||||
TEST_EXPECT_MSG(testing_state, size == Dqn_CharCountI(EXPECT_STR), "size: %zd", size);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, size) == 0, "result: %s", result);
|
||||
}
|
||||
|
||||
{
|
||||
@ -501,13 +501,13 @@ static void UnitTests()
|
||||
Dqn_StringBuilder<> builder = {};
|
||||
Dqn_StringBuilder_Append(&builder, "");
|
||||
Dqn_StringBuilder_Append(&builder, "");
|
||||
Dqn_isize len = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &len);
|
||||
Dqn_isize size = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &size);
|
||||
DQN_DEFER { Dqn_Allocator_Free(&allocator, result); };
|
||||
|
||||
char constexpr EXPECT_STR[] = "";
|
||||
TEST_EXPECT_MSG(testing_state, len == Dqn_CharCountI(EXPECT_STR), "len: %zd", len);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, len) == 0, "result: %s", result);
|
||||
TEST_EXPECT_MSG(testing_state, size == Dqn_CharCountI(EXPECT_STR), "size: %zd", size);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, size) == 0, "result: %s", result);
|
||||
}
|
||||
|
||||
{
|
||||
@ -515,26 +515,26 @@ static void UnitTests()
|
||||
Dqn_StringBuilder<> builder = {};
|
||||
Dqn_StringBuilder_Append(&builder, "Acd");
|
||||
Dqn_StringBuilder_Append(&builder, "");
|
||||
Dqn_isize len = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &len);
|
||||
Dqn_isize size = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &size);
|
||||
DQN_DEFER { Dqn_Allocator_Free(&allocator, result); };
|
||||
|
||||
char constexpr EXPECT_STR[] = "Acd";
|
||||
TEST_EXPECT_MSG(testing_state, len == Dqn_CharCountI(EXPECT_STR), "len: %zd", len);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, len) == 0, "result: %s", result);
|
||||
TEST_EXPECT_MSG(testing_state, size == Dqn_CharCountI(EXPECT_STR), "size: %zd", size);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, size) == 0, "result: %s", result);
|
||||
}
|
||||
|
||||
{
|
||||
TEST_START_SCOPE(testing_state, "Append nullptr and build using heap allocator");
|
||||
Dqn_StringBuilder<> builder = {};
|
||||
Dqn_StringBuilder_Append(&builder, nullptr, 5);
|
||||
Dqn_isize len = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &len);
|
||||
Dqn_isize size = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &size);
|
||||
DQN_DEFER { Dqn_Allocator_Free(&allocator, result); };
|
||||
|
||||
char constexpr EXPECT_STR[] = "";
|
||||
TEST_EXPECT_MSG(testing_state, len == Dqn_CharCountI(EXPECT_STR), "len: %zd", len);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, len) == 0, "result: %s", result);
|
||||
TEST_EXPECT_MSG(testing_state, size == Dqn_CharCountI(EXPECT_STR), "size: %zd", size);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, size) == 0, "result: %s", result);
|
||||
}
|
||||
|
||||
{
|
||||
@ -543,13 +543,13 @@ static void UnitTests()
|
||||
Dqn_StringBuilder_Append(&builder, "A");
|
||||
Dqn_StringBuilder_Append(&builder, "z"); // Should force a new memory block
|
||||
Dqn_StringBuilder_Append(&builder, "tec");
|
||||
Dqn_isize len = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &len);
|
||||
Dqn_isize size = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &size);
|
||||
DQN_DEFER { Dqn_Allocator_Free(&allocator, result); };
|
||||
|
||||
char constexpr EXPECT_STR[] = "Aztec";
|
||||
TEST_EXPECT_MSG(testing_state, len == Dqn_CharCountI(EXPECT_STR), "len: %zd", len);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, len) == 0, "result: %s", result);
|
||||
TEST_EXPECT_MSG(testing_state, size == Dqn_CharCountI(EXPECT_STR), "size: %zd", size);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, size) == 0, "result: %s", result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -559,42 +559,42 @@ static void UnitTests()
|
||||
Dqn_StringBuilder<> builder = {};
|
||||
Dqn_StringBuilder_AppendChar(&builder, 'a');
|
||||
Dqn_StringBuilder_AppendChar(&builder, 'b');
|
||||
Dqn_isize len = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &len);
|
||||
Dqn_isize size = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &size);
|
||||
DQN_DEFER { Dqn_Allocator_Free(&allocator, result); };
|
||||
|
||||
char constexpr EXPECT_STR[] = "ab";
|
||||
TEST_EXPECT_MSG(testing_state, len == Dqn_CharCountI(EXPECT_STR), "len: %zd", len);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, len) == 0, "result: %s", result);
|
||||
TEST_EXPECT_MSG(testing_state, size == Dqn_CharCountI(EXPECT_STR), "size: %zd", size);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, size) == 0, "result: %s", result);
|
||||
}
|
||||
|
||||
// NOTE: Dqn_StringBuilder_FmtAppend
|
||||
// NOTE: Dqn_StringBuilder_AppendFmtF
|
||||
{
|
||||
{
|
||||
TEST_START_SCOPE(testing_state, "Append format string and build using heap allocator");
|
||||
Dqn_StringBuilder<> builder = {};
|
||||
Dqn_StringBuilder_FmtAppend(&builder, "Number: %d, String: %s, ", 4, "Hello Sailor");
|
||||
Dqn_StringBuilder_FmtAppend(&builder, "Extra Stuff");
|
||||
Dqn_isize len = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &len);
|
||||
Dqn_StringBuilder_AppendFmtF(&builder, "Number: %d, String: %s, ", 4, "Hello Sailor");
|
||||
Dqn_StringBuilder_AppendFmtF(&builder, "Extra Stuff");
|
||||
Dqn_isize size = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &size);
|
||||
DQN_DEFER { Dqn_Allocator_Free(&allocator, result); };
|
||||
|
||||
char constexpr EXPECT_STR[] = "Number: 4, String: Hello Sailor, Extra Stuff";
|
||||
TEST_EXPECT_MSG(testing_state, len == Dqn_CharCountI(EXPECT_STR), "len: %zd", len);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, len) == 0, "result: %s", result);
|
||||
TEST_EXPECT_MSG(testing_state, size == Dqn_CharCountI(EXPECT_STR), "size: %zd", size);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, size) == 0, "result: %s", result);
|
||||
}
|
||||
|
||||
{
|
||||
TEST_START_SCOPE(testing_state, "Append nullptr format string and build using heap allocator");
|
||||
Dqn_StringBuilder<> builder = {};
|
||||
Dqn_StringBuilder_FmtAppend(&builder, nullptr);
|
||||
Dqn_isize len = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &len);
|
||||
Dqn_StringBuilder_AppendFmtF(&builder, nullptr);
|
||||
Dqn_isize size = 0;
|
||||
char *result = Dqn_StringBuilder_Build(&builder, &allocator, &size);
|
||||
DQN_DEFER { Dqn_Allocator_Free(&allocator, result); };
|
||||
|
||||
char constexpr EXPECT_STR[] = "";
|
||||
TEST_EXPECT_MSG(testing_state, len == Dqn_CharCountI(EXPECT_STR), "len: %zd", len);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, len) == 0, "result: %s", result);
|
||||
TEST_EXPECT_MSG(testing_state, size == Dqn_CharCountI(EXPECT_STR), "size: %zd", size);
|
||||
TEST_EXPECT_MSG(testing_state, strncmp(result, EXPECT_STR, size) == 0, "result: %s", result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -611,7 +611,7 @@ static void UnitTests()
|
||||
TEST_START_SCOPE(testing_state, "Initialise from raw array");
|
||||
int raw_array[] = {1, 2};
|
||||
auto array = Dqn_FixedArray_Init<int, 4>(raw_array, (int)Dqn_ArrayCount(raw_array));
|
||||
TEST_EXPECT(testing_state, array.len == 2);
|
||||
TEST_EXPECT(testing_state, array.size == 2);
|
||||
TEST_EXPECT(testing_state, array[0] == 1);
|
||||
TEST_EXPECT(testing_state, array[1] == 2);
|
||||
}
|
||||
@ -622,7 +622,7 @@ static void UnitTests()
|
||||
int raw_array[] = {1, 2, 3};
|
||||
auto array = Dqn_FixedArray_Init<int, 4>(raw_array, (int)Dqn_ArrayCount(raw_array));
|
||||
Dqn_FixedArray_EraseStable(&array, 1);
|
||||
TEST_EXPECT(testing_state, array.len == 2);
|
||||
TEST_EXPECT(testing_state, array.size == 2);
|
||||
TEST_EXPECT(testing_state, array[0] == 1);
|
||||
TEST_EXPECT(testing_state, array[1] == 3);
|
||||
}
|
||||
@ -633,7 +633,7 @@ static void UnitTests()
|
||||
int raw_array[] = {1, 2, 3};
|
||||
auto array = Dqn_FixedArray_Init<int, 4>(raw_array, (int)Dqn_ArrayCount(raw_array));
|
||||
Dqn_FixedArray_EraseUnstable(&array, 0);
|
||||
TEST_EXPECT(testing_state, array.len == 2);
|
||||
TEST_EXPECT(testing_state, array.size == 2);
|
||||
TEST_EXPECT(testing_state, array[0] == 3);
|
||||
TEST_EXPECT(testing_state, array[1] == 2);
|
||||
}
|
||||
@ -645,7 +645,7 @@ static void UnitTests()
|
||||
int raw_array[] = {1};
|
||||
auto array = Dqn_FixedArray_Init<int, 4>(raw_array, (int)Dqn_ArrayCount(raw_array));
|
||||
Dqn_FixedArray_Add(&array, ITEM);
|
||||
TEST_EXPECT(testing_state, array.len == 2);
|
||||
TEST_EXPECT(testing_state, array.size == 2);
|
||||
TEST_EXPECT(testing_state, array[0] == 1);
|
||||
TEST_EXPECT(testing_state, array[1] == ITEM);
|
||||
}
|
||||
@ -656,7 +656,7 @@ static void UnitTests()
|
||||
int raw_array[] = {1};
|
||||
auto array = Dqn_FixedArray_Init<int, 4>(raw_array, (int)Dqn_ArrayCount(raw_array));
|
||||
Dqn_FixedArray_Clear(&array);
|
||||
TEST_EXPECT(testing_state, array.len == 0);
|
||||
TEST_EXPECT(testing_state, array.size == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -675,11 +675,11 @@ static void UnitTests()
|
||||
TEST_EXPECT_MSG(testing_state, Dqn_FixedString_Append(&str, "abcd") == false, "We need space for the null-terminator");
|
||||
}
|
||||
|
||||
// NOTE: Dqn_FixedString_AppendFmt
|
||||
// NOTE: Dqn_FixedString_AppendFmtF
|
||||
{
|
||||
TEST_START_SCOPE(testing_state, "Append format string too much fails");
|
||||
Dqn_FixedString<4> str = {};
|
||||
TEST_EXPECT_MSG(testing_state, Dqn_FixedString_AppendFmt(&str, "abcd") == false, "We need space for the null-terminator");
|
||||
TEST_EXPECT_MSG(testing_state, Dqn_FixedString_AppendFmtF(&str, "abcd") == false, "We need space for the null-terminator");
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user