Re-organize bulk of library code

This commit is contained in:
doyle 2020-07-17 00:12:27 +10:00
parent 6cf6751013
commit 73f8a8bcb9
5 changed files with 1351 additions and 2208 deletions

2451
Code/Dqn.h

File diff suppressed because it is too large Load Diff

View File

@ -1,321 +0,0 @@
#ifndef DQN_HEADER_H
#define DQN_HEADER_H
// Compile & Run
/*
MSVC
cl /O2 /MT /W4 /EHsc /FC /wd4201 /D DQN_HEADER_IMPLEMENTATION /Tp DqnHeader.h /link /nologo
DqnHeader.exe Dqn.h > Dqn_Generated.h
*/
// NOTE: Copy the function prototype, all functions will be whitespaced aligned to the longest return type of the file
// NOTE: If you function contains a comma NOT in the argument list (i.e. multiple template parameters), this macro does NOT work.
// Please use the DQN_HEADER_COPY_BEGIN and DQN_HEADER_COPY_END unfortunately.
#define DQN_HEADER_COPY_PROTOTYPE(func_return, func_name_and_types) func_return func_name_and_types
// NOTE: Copy all contents from the file between the begin and end macro
#define DQN_HEADER_COPY_BEGIN
#define DQN_HEADER_COPY_END
// NOTE: Copy comments by writing comments with the prefix, "// @"
// @ Hello this comment will be copied to the output
// NOTE: Example Input
#if 0
#include "DqnHeader.h"
// @ ptr1: Pointer to the first block of memory
// @ ptr2: Pointer to the second block of memory
// @ num_bytes: The number of bytes to compare in both blocks of memory
DQN_HEADER_COPY_PROTOTYPE(int, Dqn_MemCmp(void const *ptr1, void const *ptr2, size_t num_bytes))
{
int result = memcmp(ptr1, ptr2, num_bytes);
return result;
}
DQN_HEADER_COPY_BEGIN
struct HelloWorld
{
int foo, bar;
};
DQN_HEADER_COPY_END
#endif
// NOTE: Example Output
#if 0
// @ ptr1: Pointer to the first block of memory
// @ ptr2: Pointer to the second block of memory
// @ num_bytes: The number of bytes to compare in both blocks of memory
int Dqn_MemCmp(void const *ptr1, void const *ptr2, size_t num_bytes);
struct HelloWorld
{
int foo, bar;
};
#endif
#endif /* DQN_HEADER_H */
#ifdef DQN_HEADER_IMPLEMENTATION
#define _CRT_SECURE_NO_WARNINGS // NOTE: Undefined at end of file
#include <stddef.h>
#define DQN_USE_PRIMITIVE_TYPEDEFS
#define DQN_IMPLEMENTATION
#include "Dqn.h"
char const *ParseFunctionReturnType(char const *ptr, Dqn_isize *len)
{
char const *result = Dqn_Str_SkipWhitespace(ptr);
Dqn_isize result_len = 0;
for (int scope = 0; ptr; ptr++) // NOTE: Parse the function return type
{
if (ptr[0] == '<' || ptr[0] == '>')
{
if (ptr[0] == '<') scope++;
else scope--;
continue;
}
else if (ptr[0] == ',')
{
if (scope != 0) continue;
result_len = static_cast<int>(ptr - result);
break;
}
}
if (len) *len = result_len;
return result;
}
char const *ParseFunctionNameAndParameters(char const *ptr, Dqn_isize *len)
{
char const *result = ptr;
int result_len = 0;
for (int scope = 0; ptr; ptr++) // NOTE: Parse the function name and parameters
{
if (ptr[0] == '(') scope++;
else if (ptr[0] == ')')
{
if (scope-- != 0) continue;
result_len = static_cast<int>(ptr - result);
break;
}
}
*len = result_len;
return result;
}
char const *ParseFunctionComment(char const *ptr, Dqn_isize *len)
{
while (ptr[0] != '"') ptr++;
ptr++;
char const *result = ptr;
Dqn_isize result_len = 0;
for (;;)
{
while (ptr[0] != '"')
ptr++;
if (ptr[-1] != '\\')
{
result_len = ptr - result;
break;
}
}
*len = result_len;
return result;
}
enum struct HeaderEntryType
{
Prototype,
Comment,
CopyBegin,
Count
};
struct HeaderEntry
{
HeaderEntryType type;
union
{
struct
{
Dqn_String return_val;
Dqn_String name_and_args;
} function_decl;
Dqn_String comment;
Dqn_String copy_range;
};
};
int main(int argc, char *argv[])
{
if (argc < 1)
{
fprintf(stdout, "Header Usage: %s [<source code filename>, ...]\n", argv[0]);
return 0;
}
Dqn_ArenaAllocator arena = {};
arena.allocator = Dqn_Allocator_InitWithXHeap();
Dqn_Allocator allocator = Dqn_Allocator_InitWithArena(&arena);
Dqn_ArenaAllocator_Reserve(&arena, DQN_MEGABYTES(16));
for (Dqn_isize arg_index = 1; arg_index < argc; ++arg_index)
{
char const *file = argv[arg_index];
Dqn_isize buf_size = 0;
char *buf = Dqn_File_ReadAll(&allocator, file, &buf_size);
if (!buf)
{
fprintf(stderr, "Failed to read file: %s\n", file);
continue;
}
char constexpr HEADER_COPY_PROTOTYPE[] = "DQN_HEADER_COPY_PROTOTYPE";
char constexpr HEADER_COMMENT[] = "// @";
char constexpr HEADER_COPY_BEGIN[] = "DQN_HEADER_COPY_BEGIN";
char constexpr HEADER_COPY_END[] = "DQN_HEADER_COPY_END";
char const *find_list[] = {HEADER_COPY_PROTOTYPE, HEADER_COMMENT, HEADER_COPY_BEGIN};
Dqn_isize constexpr find_string_lens[] = {
Dqn_CharCountI(HEADER_COPY_PROTOTYPE),
Dqn_CharCountI(HEADER_COMMENT),
Dqn_CharCountI(HEADER_COPY_BEGIN),
};
Dqn_isize num_header_entries = 0;
{
char const *ptr = buf;
char const *ptr_end = buf + buf_size;
Dqn_isize ptr_len = buf_size;
Dqn_isize matched_find_index = -1;
for (char const *token = Dqn_Str_FindMulti(ptr, find_list, find_string_lens, Dqn_ArrayCountI(find_list), &matched_find_index, ptr_len);
token;
token = Dqn_Str_FindMulti(ptr, find_list, find_string_lens, Dqn_ArrayCountI(find_list), &matched_find_index, ptr_len))
{
ptr = token + find_string_lens[matched_find_index];
num_header_entries++;
ptr_len = ptr_end - ptr;
}
}
auto *header_entries = Dqn_ArenaAllocator_AllocateType<HeaderEntry>(&arena, num_header_entries);
Dqn_isize header_entries_index = 0;
Dqn_isize max_prototype_return_val = 0;
char const *ptr = buf;
char const *ptr_end = buf + buf_size;
Dqn_isize ptr_len = buf_size;
Dqn_isize matched_find_index = -1;
for (char const *token = Dqn_Str_FindMulti(ptr, find_list, find_string_lens, Dqn_ArrayCountI(find_list), &matched_find_index, ptr_len);
token;
token = Dqn_Str_FindMulti(ptr, find_list, find_string_lens, Dqn_ArrayCountI(find_list), &matched_find_index, ptr_len))
{
HeaderEntry *entry = header_entries + header_entries_index++;
entry->type = static_cast<HeaderEntryType>(matched_find_index);
if (matched_find_index == (Dqn_isize)HeaderEntryType::Prototype)
{
ptr = token + find_string_lens[matched_find_index] + 1 /*macro start parenthesis*/;
Dqn_isize func_type_len = 0;
char const *func_type = ParseFunctionReturnType(ptr, &func_type_len);
ptr = func_type + func_type_len + 1; // Ptr is at macro comma, skip the comma
ptr = Dqn_Str_SkipWhitespace(ptr);
Dqn_isize func_name_len = 0;
char const *func_name = ParseFunctionNameAndParameters(ptr, &func_name_len);
entry->function_decl.return_val = Dqn_Asprintf(&allocator, "%.*s", func_type_len, func_type);
entry->function_decl.name_and_args = Dqn_Asprintf(&allocator, "%.*s", func_name_len, func_name);
ptr = func_name + func_name_len + 1; // Ptr is at macro closing paren, skip the paren
max_prototype_return_val = DQN_MAX(max_prototype_return_val, func_type_len);
}
else if (matched_find_index == (Dqn_isize)HeaderEntryType::Comment)
{
char const *comment_start = token;
ptr = token;
while (ptr[0] != '\n' && ptr[0] != '\r')
ptr++;
Dqn_isize comment_len = ptr - comment_start;
entry->comment.str = Dqn_ArenaAllocator_AllocateType<char>(&arena, comment_len);
DQN_FOR_EACH(comment_index, comment_len)
{
// NOTE: We capture "// @", and we want to skip the @ symbol, its ugly which is at the index 3
// Also if a space is given after the '@' symbol then skip that too.
char ch = comment_start[comment_index];
if (comment_index == 3 && ch == '@') continue;
if (comment_index == 4 && ch == ' ') continue;
entry->comment.str[entry->comment.len++] = ch;
}
while (entry->comment.len > 0 && Dqn_Char_IsWhitespace(entry->comment.str[entry->comment.len - 1]))
entry->comment.len--;
ptr = comment_start + comment_len;
}
else if (matched_find_index == (Dqn_isize)HeaderEntryType::CopyBegin)
{
ptr = token + find_string_lens[matched_find_index];
ptr = Dqn_Str_SkipWhitespace(ptr);
char const *copy_start = ptr;
char const *copy_end = Dqn_Str_Find(ptr, HEADER_COPY_END, ptr_len, Dqn_CharCountI(HEADER_COPY_END));
if (!copy_end)
{
fprintf(stderr, "Header copy begin macro: %s not matched with a copy end macro: %s", HEADER_COPY_BEGIN, HEADER_COPY_END);
return -1;
}
Dqn_isize copy_len = copy_end - copy_start;
entry->copy_range.str = Dqn_ArenaAllocator_AllocateType<char>(&arena, copy_len);
DQN_FOR_EACH(copy_index, copy_len)
{
char ch = copy_start[copy_index];
if (ch == '\r') continue;
entry->copy_range.str[entry->copy_range.len++] = ch;
}
ptr = copy_end;
}
ptr_len = ptr_end - ptr;
}
DQN_ASSERT(header_entries_index == num_header_entries);
DQN_FOR_EACH(entry_index, header_entries_index)
{
HeaderEntry const *entry = header_entries + entry_index;
switch(entry->type)
{
case HeaderEntryType::Prototype:
{
Dqn_isize remaining_space = max_prototype_return_val - entry->function_decl.return_val.len + 1;
fprintf(stdout, "%.*s", (int)entry->function_decl.return_val.len, entry->function_decl.return_val.str);
DQN_FOR_EACH(space, remaining_space) fputs(" ", stdout);
fprintf(stdout, " %.*s;\n", (int)entry->function_decl.name_and_args.len, entry->function_decl.name_and_args.str);
}
break;
case HeaderEntryType::Comment:
{
fprintf(stdout, "%.*s\n", (int)entry->comment.len, entry->comment.str);
}
break;
case HeaderEntryType::CopyBegin:
{
fprintf(stdout, "%.*s\n", (int)entry->copy_range.len, entry->copy_range.str);
}
break;
}
}
}
}
#undef _CRT_SECURE_NO_WARNINGS
#endif /* DQN_HEADER_IMPLEMENTATION */

View File

@ -1,690 +0,0 @@
// -------------------------------------------------------------------------------------------------
//
// NOTE: Typedefs, Macros, Utils
//
// -------------------------------------------------------------------------------------------------
constexpr Dqn_usize Dqn_ArrayCount(T const (&)[N]);
constexpr Dqn_isize Dqn_ArrayCountI(T const (&)[N]);
constexpr Dqn_usize Dqn_CharCount(char const (&)[N]);
constexpr Dqn_isize Dqn_CharCountI(char const (&)[N]);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Logging
//
// -------------------------------------------------------------------------------------------------
constexpr inline char const * Dqn_LogTypeTag(Dqn_LogType type);
// NOTE: Set the callback to get called whenever a log message has been printed
#define DQN_LOG_CALLBACK(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 *log_str)
typedef DQN_LOG_CALLBACK(Dqn_LogCallback);
Dqn_LogCallback *Dqn_log_callback;
#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__)
// -------------------------------------------------------------------------------------------------
//
// NOTE: Math
//
// -------------------------------------------------------------------------------------------------
union Dqn_V2I
{
struct { Dqn_i32 x, y; };
struct { Dqn_i32 w, h; };
struct { Dqn_i32 min, max; };
Dqn_i32 e[2];
Dqn_V2I() = default;
constexpr Dqn_V2I(Dqn_f32 x_, Dqn_f32 y_): x((Dqn_i32)x_), y((Dqn_i32)y_) {}
constexpr Dqn_V2I(Dqn_i32 x_, Dqn_i32 y_): x(x_), y(y_) {}
constexpr Dqn_V2I(Dqn_i32 xy): x(xy), y(xy) {}
constexpr bool operator!=(Dqn_V2I other) const { return !(*this == other); }
constexpr bool operator==(Dqn_V2I other) const { return (x == other.x) && (y == other.y); }
constexpr bool operator>=(Dqn_V2I other) const { return (x >= other.x) && (y >= other.y); }
constexpr bool operator<=(Dqn_V2I other) const { return (x <= other.x) && (y <= other.y); }
constexpr bool operator< (Dqn_V2I other) const { return (x < other.x) && (y < other.y); }
constexpr bool operator> (Dqn_V2I other) const { return (x > other.x) && (y > other.y); }
constexpr Dqn_V2I operator- (Dqn_V2I other) const { Dqn_V2I result(x - other.x, y - other.y); return result; }
constexpr Dqn_V2I operator+ (Dqn_V2I other) const { Dqn_V2I result(x + other.x, y + other.y); return result; }
constexpr Dqn_V2I operator* (Dqn_V2I other) const { Dqn_V2I result(x * other.x, y * other.y); return result; }
constexpr Dqn_V2I operator* (Dqn_f32 other) const { Dqn_V2I result(x * other, y * other); return result; }
constexpr Dqn_V2I operator* (Dqn_i32 other) const { Dqn_V2I result(x * other, y * other); return result; }
constexpr Dqn_V2I operator/ (Dqn_V2I other) const { Dqn_V2I result(x / other.x, y / other.y); return result; }
constexpr Dqn_V2I operator/ (Dqn_f32 other) const { Dqn_V2I result(x / other, y / other); return result; }
constexpr Dqn_V2I operator/ (Dqn_i32 other) const { Dqn_V2I result(x / other, y / other); return result; }
constexpr Dqn_V2I &operator*=(Dqn_V2I other) { *this = *this * other; return *this; }
constexpr Dqn_V2I &operator*=(Dqn_f32 other) { *this = *this * other; return *this; }
constexpr Dqn_V2I &operator*=(Dqn_i32 other) { *this = *this * other; return *this; }
constexpr Dqn_V2I &operator-=(Dqn_V2I other) { *this = *this - other; return *this; }
constexpr Dqn_V2I &operator+=(Dqn_V2I other) { *this = *this + other; return *this; }
};
union Dqn_V2
{
struct { Dqn_f32 x, y; };
struct { Dqn_f32 w, h; };
struct { Dqn_f32 min, max; };
Dqn_f32 e[2];
Dqn_V2() = default;
constexpr Dqn_V2(Dqn_f32 a) : x(a), y(a) {}
constexpr Dqn_V2(Dqn_i32 a) : x((Dqn_f32)a), y((Dqn_f32)a) {}
constexpr Dqn_V2(Dqn_f32 x_, Dqn_f32 y_): x(x_), y(y_) {}
constexpr Dqn_V2(Dqn_i32 x_, Dqn_i32 y_): x((Dqn_f32)x_), y((Dqn_f32)y_) {}
constexpr Dqn_V2(Dqn_V2I a) : x((Dqn_f32)a.x), y((Dqn_f32)a.y) {}
constexpr bool operator!=(Dqn_V2 other) const { return !(*this == other); }
constexpr bool operator==(Dqn_V2 other) const { return (x == other.x) && (y == other.y); }
constexpr bool operator>=(Dqn_V2 other) const { return (x >= other.x) && (y >= other.y); }
constexpr bool operator<=(Dqn_V2 other) const { return (x <= other.x) && (y <= other.y); }
constexpr bool operator< (Dqn_V2 other) const { return (x < other.x) && (y < other.y); }
constexpr bool operator> (Dqn_V2 other) const { return (x > other.x) && (y > other.y); }
constexpr Dqn_V2 operator- (Dqn_V2 other) const { Dqn_V2 result(x - other.x, y - other.y); return result; }
constexpr Dqn_V2 operator+ (Dqn_V2 other) const { Dqn_V2 result(x + other.x, y + other.y); return result; }
constexpr Dqn_V2 operator* (Dqn_V2 other) const { Dqn_V2 result(x * other.x, y * other.y); return result; }
constexpr Dqn_V2 operator* (Dqn_f32 other) const { Dqn_V2 result(x * other, y * other); return result; }
constexpr Dqn_V2 operator* (Dqn_i32 other) const { Dqn_V2 result(x * other, y * other); return result; }
constexpr Dqn_V2 operator/ (Dqn_V2 other) const { Dqn_V2 result(x / other.x, y / other.y); return result; }
constexpr Dqn_V2 operator/ (Dqn_f32 other) const { Dqn_V2 result(x / other, y / other); return result; }
constexpr Dqn_V2 operator/ (Dqn_i32 other) const { Dqn_V2 result(x / other, y / other); return result; }
constexpr Dqn_V2 &operator*=(Dqn_V2 other) { *this = *this * other; return *this; }
constexpr Dqn_V2 &operator*=(Dqn_f32 other) { *this = *this * other; return *this; }
constexpr Dqn_V2 &operator*=(Dqn_i32 other) { *this = *this * other; return *this; }
constexpr Dqn_V2 &operator/=(Dqn_V2 other) { *this = *this / other; return *this; }
constexpr Dqn_V2 &operator/=(Dqn_f32 other) { *this = *this / other; return *this; }
constexpr Dqn_V2 &operator/=(Dqn_i32 other) { *this = *this / other; return *this; }
constexpr Dqn_V2 &operator-=(Dqn_V2 other) { *this = *this - other; return *this; }
constexpr Dqn_V2 &operator+=(Dqn_V2 other) { *this = *this + other; return *this; }
};
union Dqn_V3
{
struct { Dqn_f32 x, y, z; };
struct { Dqn_f32 r, g, b; };
Dqn_V2 xy;
Dqn_f32 e[3];
Dqn_V3() = default;
constexpr Dqn_V3(Dqn_f32 a) : x(a), y(a), z(a) {}
constexpr Dqn_V3(Dqn_i32 a) : x((Dqn_f32)a), y((Dqn_f32)a), z((Dqn_f32)a) {}
constexpr Dqn_V3(Dqn_f32 x_, Dqn_f32 y_, Dqn_f32 z_): x(x_), y(y_), z(z_) {}
constexpr Dqn_V3(Dqn_i32 x_, Dqn_i32 y_, Dqn_f32 z_): x((Dqn_f32)x_), y((Dqn_f32)y_), z((Dqn_f32)z_) {}
constexpr Dqn_V3(Dqn_V2 xy, Dqn_f32 z_) : x(xy.x), y(xy.y), z(z_) {}
constexpr bool operator!= (Dqn_V3 other) const { return !(*this == other); }
constexpr bool operator== (Dqn_V3 other) const { return (x == other.x) && (y == other.y) && (z == other.z); }
constexpr bool operator>= (Dqn_V3 other) const { return (x >= other.x) && (y >= other.y) && (z >= other.z); }
constexpr bool operator<= (Dqn_V3 other) const { return (x <= other.x) && (y <= other.y) && (z <= other.z); }
constexpr bool operator< (Dqn_V3 other) const { return (x < other.x) && (y < other.y) && (z < other.z); }
constexpr bool operator> (Dqn_V3 other) const { return (x > other.x) && (y > other.y) && (z > other.z); }
constexpr Dqn_V3 operator- (Dqn_V3 other) const { Dqn_V3 result(x - other.x, y - other.y, z - other.z); return result; }
constexpr Dqn_V3 operator+ (Dqn_V3 other) const { Dqn_V3 result(x + other.x, y + other.y, z + other.z); return result; }
constexpr Dqn_V3 operator* (Dqn_V3 other) const { Dqn_V3 result(x * other.x, y * other.y, z * other.z); return result; }
constexpr Dqn_V3 operator* (Dqn_f32 other) const { Dqn_V3 result(x * other, y * other, z * other); return result; }
constexpr Dqn_V3 operator* (Dqn_i32 other) const { Dqn_V3 result(x * other, y * other, z * other); return result; }
constexpr Dqn_V3 operator/ (Dqn_V3 other) const { Dqn_V3 result(x / other.x, y / other.y, z / other.z); return result; }
constexpr Dqn_V3 operator/ (Dqn_f32 other) const { Dqn_V3 result(x / other, y / other, z / other); return result; }
constexpr Dqn_V3 operator/ (Dqn_i32 other) const { Dqn_V3 result(x / other, y / other, z / other); return result; }
constexpr Dqn_V3 &operator*=(Dqn_V3 other) { *this = *this * other; return *this; }
constexpr Dqn_V3 &operator*=(Dqn_f32 other) { *this = *this * other; return *this; }
constexpr Dqn_V3 &operator*=(Dqn_i32 other) { *this = *this * other; return *this; }
constexpr Dqn_V3 &operator/=(Dqn_V3 other) { *this = *this / other; return *this; }
constexpr Dqn_V3 &operator/=(Dqn_f32 other) { *this = *this / other; return *this; }
constexpr Dqn_V3 &operator/=(Dqn_i32 other) { *this = *this / other; return *this; }
constexpr Dqn_V3 &operator-=(Dqn_V3 other) { *this = *this - other; return *this; }
constexpr Dqn_V3 &operator+=(Dqn_V3 other) { *this = *this + other; return *this; }
};
union Dqn_V4
{
struct { Dqn_f32 x, y, z, w; };
struct { Dqn_f32 r, g, b, a; };
Dqn_V3 rgb;
Dqn_f32 e[4];
Dqn_V4() = default;
constexpr Dqn_V4(Dqn_f32 xyzw) : x(xyzw), y(xyzw), z(xyzw), w(xyzw) {}
constexpr Dqn_V4(Dqn_f32 x_, Dqn_f32 y_, Dqn_f32 z_, Dqn_f32 w_): x(x_), y(y_), z(z_), w(w_) {}
constexpr Dqn_V4(Dqn_i32 x_, Dqn_i32 y_, Dqn_i32 z_, Dqn_i32 w_): x((Dqn_f32)x_), y((Dqn_f32)y_), z((Dqn_f32)z_), w((Dqn_f32)w_) {}
constexpr Dqn_V4(Dqn_V3 xyz, Dqn_f32 w_) : x(xyz.x), y(xyz.y), z(xyz.z), w(w_) {}
constexpr bool operator!=(Dqn_V4 other) const { return !(*this == other); }
constexpr bool operator==(Dqn_V4 other) const { return (x == other.x) && (y == other.y) && (z == other.z) && (w == other.w); }
constexpr bool operator>=(Dqn_V4 other) const { return (x >= other.x) && (y >= other.y) && (z >= other.z) && (w >= other.w); }
constexpr bool operator<=(Dqn_V4 other) const { return (x <= other.x) && (y <= other.y) && (z <= other.z) && (w <= other.w); }
constexpr bool operator< (Dqn_V4 other) const { return (x < other.x) && (y < other.y) && (z < other.z) && (w < other.w); }
constexpr bool operator> (Dqn_V4 other) const { return (x > other.x) && (y > other.y) && (z > other.z) && (w > other.w); }
constexpr Dqn_V4 operator- (Dqn_V4 other) const { Dqn_V4 result(x - other.x, y - other.y, z - other.z, w - other.w); return result; }
constexpr Dqn_V4 operator+ (Dqn_V4 other) const { Dqn_V4 result(x + other.x, y + other.y, z + other.z, w + other.w); return result; }
constexpr Dqn_V4 operator* (Dqn_V4 other) const { Dqn_V4 result(x * other.x, y * other.y, z * other.z, w * other.w); return result; }
constexpr Dqn_V4 operator* (Dqn_f32 other) const { Dqn_V4 result(x * other, y * other, z * other, w * other); return result; }
constexpr Dqn_V4 operator* (Dqn_i32 other) const { Dqn_V4 result(x * other, y * other, z * other, w * other); return result; }
constexpr Dqn_V4 operator/ (Dqn_f32 other) const { Dqn_V4 result(x / other, y / other, z / other, w / other); return result; }
constexpr Dqn_V4 &operator*=(Dqn_V4 other) { *this = *this * other; return *this; }
constexpr Dqn_V4 &operator*=(Dqn_f32 other) { *this = *this * other; return *this; }
constexpr Dqn_V4 &operator*=(Dqn_i32 other) { *this = *this * other; return *this; }
constexpr Dqn_V4 &operator-=(Dqn_V4 other) { *this = *this - other; return *this; }
constexpr Dqn_V4 &operator+=(Dqn_V4 other) { *this = *this + other; return *this; }
};
struct Dqn_Rect
{
Dqn_V2 min, max;
Dqn_Rect() = default;
Dqn_Rect(Dqn_V2 min, Dqn_V2 max) : min(min), max(max) {}
Dqn_Rect(Dqn_V2I min, Dqn_V2I max) : min(min), max(max) {}
};
struct Dqn_RectI32
{
Dqn_V2I min, max;
Dqn_RectI32() = default;
Dqn_RectI32(Dqn_V2I min, Dqn_V2I max) : min(min), max(max) {}
};
union Dqn_Mat4
{
Dqn_f32 e[16];
Dqn_V4 row[4];
Dqn_f32 row_major[4][4];
Dqn_f32 operator[](Dqn_usize i) const { return e[i]; }
};
template <typename T> int Dqn_MemCmpType(T const *ptr1, T const *ptr2);
template <typename T> T * Dqn_MemZero(T *src);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_Allocator
//
// -------------------------------------------------------------------------------------------------
// Custom allocations must include Dqn_AllocateMetadata before the aligned_ptr, see Dqn_AllocateMetadata for more information
enum struct Dqn_Allocator_Type
{
#if defined(DQN_ALLOCATOR_DEFAULT_TO_NULL)
Null,
Heap, // Malloc, realloc, free
#else
Heap, // Malloc, realloc, free
Null,
#endif
XHeap, // Malloc realloc, free, crash on failure
Arena,
Custom,
};
#define DQN_ALLOCATOR_ALLOCATE_PROC(name) void *name(Dqn_isize size, Dqn_u8 alignment, void *user_context)
#define DQN_ALLOCATOR_REALLOC_PROC(name) void *name(void *old_ptr, Dqn_isize old_size, Dqn_isize new_size, void *user_context)
#define DQN_ALLOCATOR_FREE_PROC(name) void name(void *ptr, void *user_context)
typedef DQN_ALLOCATOR_ALLOCATE_PROC(Dqn_Allocator_AllocateProc);
typedef DQN_ALLOCATOR_REALLOC_PROC(Dqn_Allocator_ReallocProc);
typedef DQN_ALLOCATOR_FREE_PROC(Dqn_Allocator_FreeProc);
struct Dqn_Allocator
{
Dqn_Allocator_Type type;
union
{
void *user;
struct Dqn_ArenaAllocator *arena;
} context;
Dqn_isize bytes_allocated;
Dqn_isize total_bytes_allocated;
Dqn_isize allocations;
Dqn_isize total_allocations;
// NOTE: Only required if type == Dqn_Allocator_Type::Custom
Dqn_Allocator_AllocateProc *allocate;
Dqn_Allocator_ReallocProc *realloc;
Dqn_Allocator_FreeProc *free;
};
Dqn_Allocator inline Dqn_Allocator_InitWithNull();
Dqn_Allocator inline Dqn_Allocator_InitWithHeap();
Dqn_Allocator inline Dqn_Allocator_InitWithXHeap();
Dqn_Allocator inline Dqn_Allocator_InitWithArena(Dqn_ArenaAllocator *arena);
template <typename T> T * Dqn_Allocator_AllocateType(Dqn_Allocator *allocator, Dqn_isize num);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_AllocatorMetadata
//
// -------------------------------------------------------------------------------------------------
// Custom Dqn_Allocator implementations must include allocation metadata exactly (aligned_ptr - sizeof(Dqn_AllocatorMetadata)) bytes from the aligned ptr.
struct Dqn_AllocateMetadata
{
Dqn_u8 alignment;
Dqn_u8 offset; // Subtract offset from aligned ptr to return to the allocation ptr
};
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_ArenaAllocator
//
// -------------------------------------------------------------------------------------------------
struct Dqn_ArenaAllocatorBlock
{
void *memory;
Dqn_isize size;
Dqn_isize used;
Dqn_ArenaAllocatorBlock *prev;
Dqn_ArenaAllocatorBlock *next;
};
Dqn_usize const DQN_MEM_ARENA_DEFAULT_MIN_BLOCK_SIZE = DQN_KILOBYTES(4);
struct Dqn_ArenaAllocator
{
// NOTE: Configuration (fill once after "Zero Initialisation {}")
Dqn_isize min_block_size;
Dqn_Allocator allocator;
// NOTE: Read Only
Dqn_ArenaAllocatorBlock *curr_mem_block;
Dqn_ArenaAllocatorBlock *top_mem_block;
Dqn_isize highest_used_mark;
int total_allocated_mem_blocks;
};
struct Dqn_ArenaAllocatorRegion
{
Dqn_ArenaAllocator *arena;
Dqn_ArenaAllocatorBlock *curr_mem_block;
Dqn_isize curr_mem_block_used;
Dqn_ArenaAllocatorBlock *top_mem_block;
};
struct Dqn_ArenaAllocatorScopedRegion
{
Dqn_ArenaAllocatorScopedRegion(Dqn_ArenaAllocator *arena);
~Dqn_ArenaAllocatorScopedRegion();
Dqn_ArenaAllocatorRegion region;
};
void * Dqn_ArenaAllocator_Allocate(Dqn_ArenaAllocator *arena, Dqn_isize size, Dqn_u8 alignment);
Dqn_b32 Dqn_ArenaAllocator_Reserve(Dqn_ArenaAllocator *arena, Dqn_isize size);
DQN_HEADER_COPY_PROTOTYPE(template <typename T> T *, Dqn_ArenaAllocator_AllocateType(Dqn_ArenaAllocator *arena, Dqn_isize num))
{
auto *result = DQN_CAST(T *)Dqn_ArenaAllocator_Allocate(arena, sizeof(T) * num, alignof(T));
return result;
}
// -------------------------------------------------------------------------------------------------
//
// NOTE: String
//
// -------------------------------------------------------------------------------------------------
struct Dqn_String
{
union {
// NOTE: To appease GCC, Clang can't assign C string literal to char *
// Only UB if you try modify a string originally declared const
char const *str_;
char *str;
};
Dqn_isize len;
char const *begin() const { return str; }
char const *end () const { return str + len; }
char *begin() { return str; }
char *end () { return str + len; }
};
#define DQN_STRING_LITERAL(string) {string, Dqn_CharCountI(string)}
// -------------------------------------------------------------------------------------------------
//
// NOTE: String Builder
//
// -------------------------------------------------------------------------------------------------
struct Dqn_StringBuilderBlock
{
char *mem;
Dqn_isize size;
Dqn_isize used;
Dqn_StringBuilderBlock *next;
};
Dqn_isize constexpr DQN_STRING_BUILDER_MIN_BLOCK_SIZE = DQN_KILOBYTES(4);
template <Dqn_isize N = DQN_KILOBYTES(16)>
struct Dqn_StringBuilder
{
Dqn_Allocator allocator;
char fixed_mem[N];
Dqn_StringBuilderBlock fixed_mem_block;
Dqn_StringBuilderBlock *last_mem_block;
};
// size_required: The length of the string not including the null terminator.
// The necessary length to build the string, it returns the length not including the null-terminator
template <Dqn_isize N> Dqn_isize Dqn_StringBuilder_BuildLength(Dqn_StringBuilder<N> const *builder);
template <Dqn_isize N> void Dqn_StringBuilder_BuildToDest(Dqn_StringBuilder<N> const *builder, char *dest, Dqn_usize dest_size);
template <Dqn_isize N> char * Dqn_StringBuilder_Build(Dqn_StringBuilder<N> *builder, Dqn_Allocator *allocator, Dqn_isize *len = nullptr);
template <Dqn_isize N> Dqn_String Dqn_StringBuilder_BuildString(Dqn_StringBuilder<N> *builder, Dqn_Allocator *allocator);
template <Dqn_isize N> void Dqn_StringBuilder_VFmtAppend(Dqn_StringBuilder<N> *builder, char const *fmt, va_list va);
template <Dqn_isize N> void Dqn_StringBuilder_FmtAppend(Dqn_StringBuilder<N> *builder, char const *fmt, ...);
template <Dqn_isize N> void Dqn_StringBuilder_Append(Dqn_StringBuilder<N> *builder, char const *str, Dqn_isize len = -1);
template <Dqn_isize N> void Dqn_StringBuilder_AppendString(Dqn_StringBuilder<N> *builder, Dqn_String const string);
template <Dqn_isize N> void Dqn_StringBuilder_AppendChar(Dqn_StringBuilder<N> *builder, char ch);
template <Dqn_isize N> void Dqn_StringBuilder_Free(Dqn_StringBuilder<N> *builder);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_Slices
//
// -------------------------------------------------------------------------------------------------
inline Dqn_Slice<T> Dqn_Slice_InitWithArray(T (&array)[N]);
template <typename T> inline Dqn_Slice<T> Dqn_Slice_Allocate(Dqn_Allocator *allocator, Dqn_isize len);
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, Dqn_Slice<T> const src);
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, Dqn_Slice<T> const src);
template <typename T> inline bool Dqn_Slice_Equals(Dqn_Slice<T> const a, Dqn_Slice<T> const b);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_FixedArray
//
// -------------------------------------------------------------------------------------------------
#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 max = MAX_;
Dqn_isize len;
T &operator[] (Dqn_isize i) { DQN_ASSERT_MSG(i >= 0 && i <= len, "%jd >= 0 && %jd < %jd", i, len); 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 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 *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; }
};
int Dqn_FixedArray_Capacity(DQN_FIXED_ARRAY_TEMPLATE_DECL *);
DQN_FIXED_ARRAY_TEMPLATE_DECL Dqn_FixedArray_Init(T const *item, int num);
T * Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const *items, Dqn_isize num);
T * Dqn_FixedArray_Add(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const item);
T * Dqn_FixedArray_Make(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize num);
void Dqn_FixedArray_Clear(DQN_FIXED_ARRAY_TEMPLATE_DECL *a);
void Dqn_FixedArray_EraseStable(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize index);
void Dqn_FixedArray_EraseUnstable(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize index);
void Dqn_FixedArray_Pop(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, Dqn_isize num = 1);
T * Dqn_FixedArray_Peek(DQN_FIXED_ARRAY_TEMPLATE_DECL *a);
Dqn_isize Dqn_FixedArray_GetIndex(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T const *entry);
T * Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, EqualityProc IsEqual);
T * Dqn_FixedArray_Find(DQN_FIXED_ARRAY_TEMPLATE_DECL *a, T *find);
Dqn_Slice<T> Dqn_FixedArray_Slice(DQN_FIXED_ARRAY_TEMPLATE_DECL *a);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_Array
//
// -------------------------------------------------------------------------------------------------
template <typename T> struct Dqn_Array
{
Dqn_Allocator allocator;
T *data;
Dqn_isize len;
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 *begin () const { return data; }
T const *end () const { return data + len; }
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; }
};
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_InitWithAllocatorNoGrow(Dqn_Allocator *allocator, Dqn_isize max, Dqn_isize len = 0);
template <typename T> bool Dqn_Array_Reserve(Dqn_Array<T> *a, Dqn_isize size);
template <typename T> void Dqn_Array_Free(Dqn_Array<T> *a);
template <typename T> T * Dqn_Array_Add(Dqn_Array<T> *a, T const *items, Dqn_isize num);
template <typename T> T * Dqn_Array_Add(Dqn_Array<T> *a, T const item);
template <typename T> T * Dqn_Array_Make(Dqn_Array<T> *a, Dqn_isize num);
template <typename T> void Dqn_Array_Clear(Dqn_Array<T> *a, bool zero_mem = false);
template <typename T> void Dqn_Array_EraseStable(Dqn_Array<T> *a, Dqn_isize index);
template <typename T> void Dqn_Array_EraseUnstable(Dqn_Array<T> *a, Dqn_isize index);
template <typename T> void Dqn_Array_Pop(Dqn_Array<T> *a, Dqn_isize num);
template <typename T> T * Dqn_Array_Peek(Dqn_Array<T> *a);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_FixedString
//
// -------------------------------------------------------------------------------------------------
template <Dqn_isize MAX_>
struct Dqn_FixedString
{
union { char data[MAX_]; char str[MAX_]; char buf[MAX_]; };
Dqn_isize len;
Dqn_isize max = MAX_;
Dqn_FixedString() { data[0] = 0; len = 0; }
Dqn_FixedString(char const *fmt, ...)
{
*this = {};
va_list va;
va_start(va, fmt);
Dqn_FixedString_AppendVFmt(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);
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 *begin () const { return data; }
char const *end () const { return data + len; }
char *begin () { return data; }
char *end () { return data + len; }
};
template <Dqn_isize MAX_> int Dqn_FixedString_Capacity(Dqn_FixedString<MAX_> *);
template <Dqn_isize MAX_> void Dqn_FixedString_Clear(Dqn_FixedString<MAX_> *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_AppendFmt(Dqn_FixedString<MAX_> *str, char const *fmt, ...);
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_String Dqn_FixedString_ToString(Dqn_FixedString<MAX_> const *str);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_U64Str
//
// -------------------------------------------------------------------------------------------------
struct Dqn_U64Str
{
// Points to the start of the str in the buffer, not necessarily buf since
// we write into the buffer in reverse
char *str;
char buf[27]; // NOTE(doyle): 27 is the maximum size of Dqn_u64 including commas
int len;
};
char * Dqn_U64Str_ToStr(Dqn_u64 val, Dqn_U64Str *result, Dqn_b32 comma_sep);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Logging
//
// -------------------------------------------------------------------------------------------------
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);
// return: This returns a boolean as a hack so you can combine it in if expressions. I use it for my IF_ASSERT macro
Dqn_b32 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, ...);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_AllocateMetadata
//
// -------------------------------------------------------------------------------------------------
char * Dqn_AllocateMetadata_Init(void *ptr, Dqn_u8 alignment);
// TODO(doyle): Use bit masks and only support POT. That approach reflects how computers work better.
Dqn_AllocateMetadata Dqn_AllocateMetadata_Get(void *ptr);
char * Dqn_AllocateMetadata_GetRawPointer(void *ptr);
Dqn_isize Dqn_AllocateMetadata_SizeRequired(Dqn_isize size, Dqn_u8 alignment);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_Allocator
//
// -------------------------------------------------------------------------------------------------
void * Dqn_Allocator_Allocate(Dqn_Allocator *allocator, Dqn_isize size, Dqn_u8 alignment);
void * Dqn_Allocator_Realloc(Dqn_Allocator *allocator, void *old_ptr, Dqn_isize old_size, Dqn_isize new_size);
void Dqn_Allocator_Free(Dqn_Allocator *allocator, void *ptr);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_ArenaAllocator
//
// -------------------------------------------------------------------------------------------------
void * Dqn_ArenaAllocator_Allocate(Dqn_ArenaAllocator *arena, Dqn_isize size, Dqn_u8 alignment);
void Dqn_ArenaAllocator_Free(Dqn_ArenaAllocator *arena);
Dqn_b32 Dqn_ArenaAllocator_Reserve(Dqn_ArenaAllocator *arena, Dqn_isize size);
Dqn_ArenaAllocator Dqn_ArenaAllocator_InitWithAllocator(Dqn_Allocator allocator, Dqn_isize size);
Dqn_ArenaAllocator Dqn_ArenaAllocator_InitWithMemory(void *memory, Dqn_isize size);
void Dqn_ArenaAllocator_ResetUsage(Dqn_ArenaAllocator *arena, Dqn_ZeroMem zero_mem);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_Asprintf (Allocate Sprintf)
//
// -------------------------------------------------------------------------------------------------
// return: The allocated string. If allocation fails, the str ptr returned is nullptr and length is set o the size required, NOT INCLUDING the null terminator.
Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, va_list va);
Dqn_String Dqn_Asprintf(Dqn_Allocator *allocator, char const *fmt, ...);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Vectors
//
// -------------------------------------------------------------------------------------------------
Dqn_V2I Dqn_V2_ToV2I(Dqn_V2 a);
Dqn_V2 Dqn_V2_Max(Dqn_V2 a, Dqn_V2 b);
Dqn_V2 Dqn_V2_Abs(Dqn_V2 a);
Dqn_f32 Dqn_V2_Dot(Dqn_V2 a, Dqn_V2 b);
Dqn_f32 Dqn_V2_LengthSq(Dqn_V2 a, Dqn_V2 b);
Dqn_V2 Dqn_V2_Normalise(Dqn_V2 a);
Dqn_V2 Dqn_V2_Perpendicular(Dqn_V2 a);
Dqn_f32 Dqn_V4_Dot(Dqn_V4 const *a, Dqn_V4 const *b);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Rect
//
// -------------------------------------------------------------------------------------------------
Dqn_Rect Dqn_Rect_InitFromPosAndSize(Dqn_V2 pos, Dqn_V2 size);
Dqn_V2 Dqn_Rect_Center(Dqn_Rect rect);
Dqn_b32 Dqn_Rect_ContainsPoint(Dqn_Rect rect, Dqn_V2 p);
Dqn_b32 Dqn_Rect_ContainsRect(Dqn_Rect a, Dqn_Rect b);
Dqn_V2 Dqn_Rect_Size(Dqn_Rect rect);
Dqn_Rect Dqn_Rect_Move(Dqn_Rect src, Dqn_V2 move_amount);
Dqn_Rect Dqn_Rect_Intersection(Dqn_Rect a, Dqn_Rect b);
Dqn_Rect Dqn_Rect_Union(Dqn_Rect a, Dqn_Rect b);
Dqn_Rect Dqn_Rect_FromRectI32(Dqn_RectI32 a);
Dqn_V2I Dqn_RectI32_Size(Dqn_RectI32 rect);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Math Utils
//
// -------------------------------------------------------------------------------------------------
Dqn_V2 Dqn_LerpV2(Dqn_V2 a, Dqn_f32 t, Dqn_V2 b);
Dqn_f32 Dqn_LerpF32(Dqn_f32 a, Dqn_f32 t, Dqn_f32 b);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_Mat4
//
// -------------------------------------------------------------------------------------------------
Dqn_Mat4 Dqn_Mat4_Identity();
Dqn_Mat4 Dqn_Mat4_Scale3f(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z);
Dqn_Mat4 Dqn_Mat4_ScaleV3(Dqn_V3 vec);
Dqn_Mat4 Dqn_Mat4_Translate3f(Dqn_f32 x, Dqn_f32 y, Dqn_f32 z);
Dqn_Mat4 Dqn_Mat4_TranslateV3(Dqn_V3 vec);
Dqn_Mat4 operator*(Dqn_Mat4 const &a, Dqn_Mat4 const &b);
Dqn_V4 operator*(Dqn_Mat4 const &mat, Dqn_V4 const &vec);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Helper Functions
//
// -------------------------------------------------------------------------------------------------
void Dqn_Bit_UnsetInplace(Dqn_u32 *flags, Dqn_u32 bitfield);
void Dqn_Bit_SetInplace(Dqn_u32 *flags, Dqn_u32 bitfield);
Dqn_b32 Dqn_Bit_IsSet(Dqn_u32 bits, Dqn_u32 bits_to_set);
Dqn_b32 Dqn_Bit_IsNotSet(Dqn_u32 bits, Dqn_u32 bits_to_check);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Safe Arithmetic
//
// -------------------------------------------------------------------------------------------------
Dqn_i64 Dqn_Safe_AddI64(Dqn_i64 a, Dqn_i64 b);
Dqn_i64 Dqn_Safe_MulI64(Dqn_i64 a, Dqn_i64 b);
Dqn_u64 Dqn_Safe_AddU64(Dqn_u64 a, Dqn_u64 b);
Dqn_u64 Dqn_Safe_SubU64(Dqn_u64 a, Dqn_u64 b);
Dqn_u32 Dqn_Safe_SubU32(Dqn_u32 a, Dqn_u32 b);
Dqn_u64 Dqn_Safe_MulU64(Dqn_u64 a, Dqn_u64 b);
int Dqn_Safe_TruncateISizeToInt(Dqn_isize val);
Dqn_i32 Dqn_Safe_TruncateISizeToI32(Dqn_isize val);
Dqn_i8 Dqn_Safe_TruncateISizeToI8(Dqn_isize val);
Dqn_u32 Dqn_Safe_TruncateUSizeToU32(Dqn_u64 val);
int Dqn_Safe_TruncateUSizeToI32(Dqn_usize val);
int Dqn_Safe_TruncateUSizeToInt(Dqn_usize val);
Dqn_isize Dqn_Safe_TruncateUSizeToISize(Dqn_usize val);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Char Helpers
//
// -------------------------------------------------------------------------------------------------
Dqn_b32 Dqn_Char_IsAlpha(char ch);
Dqn_b32 Dqn_Char_IsDigit(char ch);
Dqn_b32 Dqn_Char_IsAlphaNum(char ch);
Dqn_b32 Dqn_Char_IsWhitespace(char ch);
char Dqn_Char_ToLower(char ch);
// -------------------------------------------------------------------------------------------------
//
// NOTE: String Helpers
//
// -------------------------------------------------------------------------------------------------
Dqn_b32 Dqn_Str_Equals(char const *a, char const *b, Dqn_isize a_len = -1, Dqn_isize b_len = -1);
char const * Dqn_Str_FindMulti(char const *buf, char const *find_list[], Dqn_isize const *find_string_lens, Dqn_isize find_len, Dqn_isize *match_index, Dqn_isize buf_len = -1);
char const * Dqn_Str_Find(char const *buf, char const *find, Dqn_isize buf_len = -1, Dqn_isize find_len = -1);
Dqn_b32 Dqn_Str_Match(char const *src, char const *find, int find_len);
char const * Dqn_Str_SkipToChar(char const *src, char ch);
char const * Dqn_Str_SkipToNextAlphaNum(char const *src);
char const * Dqn_Str_SkipToNextDigit(char const *src);
char const * Dqn_Str_SkipToNextChar(char const *src);
char const * Dqn_Str_SkipToNextWord(char const *src);
char const * Dqn_Str_SkipToNextWhitespace(char const *src);
char const * Dqn_Str_SkipWhitespace(char const *src);
char const * Dqn_Str_SkipToCharInPlace(char const **src, char ch);
char const * Dqn_Str_SkipToNextAlphaNumInPlace(char const **src);
char const * Dqn_Str_SkipToNextCharInPlace(char const **src);
char const * Dqn_Str_SkipToNextWhitespaceInPlace(char const **src);
char const * Dqn_Str_SkipToNextWordInPlace(char const **src);
char const * Dqn_Str_SkipWhitespaceInPlace(char const **src);
Dqn_u64 Dqn_Str_ToU64(char const *buf, int len = -1);
Dqn_i64 Dqn_Str_ToI64(char const *buf, int len = -1);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Dqn_String
//
// -------------------------------------------------------------------------------------------------
Dqn_b32 Dqn_String_Compare(Dqn_String const lhs, Dqn_String const rhs);
Dqn_b32 Dqn_String_CompareCaseInsensitive(Dqn_String const lhs, Dqn_String const rhs);
Dqn_String Dqn_String_Copy(Dqn_Allocator *allocator, Dqn_String const src);
Dqn_String Dqn_String_TrimWhitespaceAround(Dqn_String src);
// -------------------------------------------------------------------------------------------------
//
// NOTE: File
//
// -------------------------------------------------------------------------------------------------
char * Dqn_File_ReadAll(Dqn_Allocator *allocator, char const *file, Dqn_isize *file_size);
// -------------------------------------------------------------------------------------------------
//
// NOTE: Utils
//
// -------------------------------------------------------------------------------------------------
char * Dqn_EpochTimeToDate(Dqn_i64 timestamp, char *buf, Dqn_isize buf_len);

View File

@ -1,4 +1,5 @@
#define DQN_USE_PRIMITIVE_TYPEDEFS
#define DQN_NO_ASSERT
#define DQN_IMPLEMENTATION
#include "Dqn.h"
@ -13,11 +14,11 @@ struct TestState
struct TestingState
{
int num_tests_in_group;
int num_tests_ok_in_group;
TestState test;
Dqn_ArenaAllocator arena_;
Dqn_Allocator allocator;
int num_tests_in_group;
int num_tests_ok_in_group;
TestState test;
Dqn_ArenaAllocator arena_;
Dqn_Allocator allocator;
};
#define ANSI_COLOR_RED "\x1b[31m"
@ -106,7 +107,7 @@ void TestState_PrintResult(TestState const *result)
}
}
DQN_FILE_SCOPE void UnitTests()
static void UnitTests()
{
TestingState testing_state = {};
// ---------------------------------------------------------------------------------------------
@ -141,7 +142,7 @@ DQN_FILE_SCOPE void UnitTests()
{
TEST_START_SCOPE(testing_state, "ArenaAllocator - Allocate Small");
Dqn_ArenaAllocator arena = {};
Dqn_ArenaAllocator arena = {};
arena.allocator = Dqn_Allocator_InitWithHeap();
Dqn_Allocator allocator = Dqn_Allocator_InitWithArena(&arena);
char constexpr EXPECT[] = "hello_world";
@ -154,10 +155,10 @@ DQN_FILE_SCOPE void UnitTests()
// NOTE: Alignment Test
{
Dqn_u8 const ALIGNMENT3 = 3;
Dqn_u8 const ALIGNMENT3 = 4;
Dqn_u8 const NUM_BYTES = sizeof(Dqn_u32);
{
TEST_START_SCOPE(testing_state, "HeapAllocator - Align to 3 bytes");
TEST_START_SCOPE(testing_state, "HeapAllocator - Align to 32 bytes");
Dqn_Allocator allocator = Dqn_Allocator_InitWithHeap();
auto *buf = DQN_CAST(Dqn_u32 *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3);
DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); };
@ -166,7 +167,7 @@ DQN_FILE_SCOPE void UnitTests()
}
{
TEST_START_SCOPE(testing_state, "XHeapAllocator - Align to 3 bytes");
TEST_START_SCOPE(testing_state, "XHeapAllocator - Align to 32 bytes");
Dqn_Allocator allocator = Dqn_Allocator_InitWithXHeap();
auto *buf = DQN_CAST(Dqn_u32 *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3);
DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); };
@ -175,7 +176,7 @@ DQN_FILE_SCOPE void UnitTests()
}
{
TEST_START_SCOPE(testing_state, "ArenaAllocator - Align to 3 bytes");
TEST_START_SCOPE(testing_state, "ArenaAllocator - Align to 32 bytes");
Dqn_ArenaAllocator arena = {};
Dqn_Allocator allocator = Dqn_Allocator_InitWithArena(&arena);
auto *buf = DQN_CAST(Dqn_u32 *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3);
@ -184,17 +185,17 @@ DQN_FILE_SCOPE void UnitTests()
}
}
// NOTE: Dqn_AllocateMetadata tests
// NOTE: Dqn_PointerMetadata tests
{
Dqn_u8 const ALIGNMENT3 = 3;
Dqn_u8 const ALIGNMENT3 = 4;
Dqn_u8 const NUM_BYTES = 4;
Dqn_u8 const MAX_OFFSET = (ALIGNMENT3 - 1) + sizeof(Dqn_AllocateMetadata);
Dqn_u8 const MAX_OFFSET = (ALIGNMENT3 - 1) + sizeof(Dqn_PointerMetadata);
{
TEST_START_SCOPE(testing_state, "HeapAllocator - Allocation metadata initialised");
Dqn_Allocator allocator = Dqn_Allocator_InitWithHeap();
char *buf = DQN_CAST(char *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3);
DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); };
Dqn_AllocateMetadata metadata = Dqn_AllocateMetadata_Get(buf);
Dqn_PointerMetadata metadata = Dqn_PointerMetadata_Get(buf);
TEST_EXPECT_MSG(testing_state, metadata.alignment == ALIGNMENT3, "metadata.alignment: %u, ALIGNMENT3: %u", metadata.alignment, ALIGNMENT3);
TEST_EXPECT_MSG(testing_state, metadata.offset <= MAX_OFFSET, "metadata.offset: %u, MAX_OFFSET: %u", metadata.offset, MAX_OFFSET);
}
@ -204,18 +205,7 @@ DQN_FILE_SCOPE void UnitTests()
Dqn_Allocator allocator = Dqn_Allocator_InitWithXHeap();
char *buf = DQN_CAST(char *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3);
DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); };
Dqn_AllocateMetadata metadata = Dqn_AllocateMetadata_Get(buf);
TEST_EXPECT_MSG(testing_state, metadata.alignment == ALIGNMENT3, "metadata.alignment: %u, ALIGNMENT3: %u", metadata.alignment, ALIGNMENT3);
TEST_EXPECT_MSG(testing_state, metadata.offset <= MAX_OFFSET, "metadata.offset: %u, MAX_OFFSET: %u", metadata.offset, MAX_OFFSET);
}
{
TEST_START_SCOPE(testing_state, "ArenaAllocator - Allocation metadata initialised");
Dqn_ArenaAllocator arena = {};
Dqn_Allocator allocator = Dqn_Allocator_InitWithArena(&arena);
char *buf = DQN_CAST(char *)Dqn_Allocator_Allocate(&allocator, NUM_BYTES, ALIGNMENT3);
DQN_DEFER { Dqn_Allocator_Free(&allocator, buf); };
Dqn_AllocateMetadata metadata = Dqn_AllocateMetadata_Get(buf);
Dqn_PointerMetadata metadata = Dqn_PointerMetadata_Get(buf);
TEST_EXPECT_MSG(testing_state, metadata.alignment == ALIGNMENT3, "metadata.alignment: %u, ALIGNMENT3: %u", metadata.alignment, ALIGNMENT3);
TEST_EXPECT_MSG(testing_state, metadata.offset <= MAX_OFFSET, "metadata.offset: %u, MAX_OFFSET: %u", metadata.offset, MAX_OFFSET);
}

View File

@ -1,53 +1,2 @@
# Dqn
Personal utility library.
## DqnHeader
A simple C++ introspection metaprogram designed as a prebuild step and generates a summary of function prototypes and comments in a header file based on annotations. It is not designed to be used as a header file for compilation and will most likely fail syntax rules if tried.
The generated file is written to stdout.
### Build
Build DqnHeader by defining `DQN_HEADER_IMPLEMENTATION` before compiling and execute it as follows
`DqnHeader.exe SourceCode.h > GeneratedFile.h`
### Usage
Include `DqnHeader.h` in a file and use the macros, annotations as described.
* Extract function prototypes using the `DQN_HEADER_COPY_PROTOTYPE` macro
* Copy comments by writing comments with `// @` as the prefix
* Copy many lines of code by enclosing it in `DQN_HEADER_COPY_BEGIN` and `DQN_HEADER_COPY_END` macros
```
#include "DqnHeader.h"
// @ ptr1: Pointer to the first block of memory
// @ ptr2: Pointer to the second block of memory
// @ num_bytes: The number of bytes to compare in both blocks of memory
DQN_HEADER_COPY_PROTOTYPE(int, Dqn_MemCmp(void const *ptr1, void const *ptr2, size_t num_bytes))
{
int result = memcmp(ptr1, ptr2, num_bytes);
return result;
}
DQN_HEADER_COPY_BEGIN
struct HelloWorld
{
int foo, bar;
};
DQN_HEADER_COPY_END
```
Which generates the following output
```
// ptr1: Pointer to the first block of memory
// ptr2: Pointer to the second block of memory
// num_bytes: The number of bytes to compare in both blocks of memory
int Dqn_MemCmp(void const *ptr1, void const *ptr2, size_t num_bytes);
struct HelloWorld
{
int foo, bar;
};
```
Personal utility library that provides allocator aware data structures, custom memory allocators and various miscellaneous helpers.