Convert binary search to a C style impl
This commit is contained in:
+273
-204
@@ -1,4 +1,4 @@
|
|||||||
// Generated by the DN single header generator 2026-07-05 12:47:32
|
// Generated by the DN single header generator 2026-07-05 23:26:32
|
||||||
|
|
||||||
// DN: Single header generator commented out => #if defined(_CLANGD)
|
// DN: Single header generator commented out => #if defined(_CLANGD)
|
||||||
// #define DN_WITH_TESTS 1
|
// #define DN_WITH_TESTS 1
|
||||||
@@ -2679,14 +2679,14 @@ DN_API DN_U8x32 DN_U8x32FromHexUnsafe(DN_Str8 hex_32b)
|
|||||||
DN_U8x32 result = {};
|
DN_U8x32 result = {};
|
||||||
hex_32b = DN_Str8TrimHexPrefix(hex_32b);
|
hex_32b = DN_Str8TrimHexPrefix(hex_32b);
|
||||||
DN_Assert(hex_32b.count <= sizeof(result.data) * 2);
|
DN_Assert(hex_32b.count <= sizeof(result.data) * 2);
|
||||||
DN_BytesFromHexPtr(hex_32b.data, hex_32b.count, result.data, sizeof(result.data));
|
DN_PtrBytesFromPtrHex(hex_32b.data, hex_32b.count, result.data, sizeof(result.data));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_U8x32FromResult DN_U8x32FromHex(DN_Str8 hex_32b)
|
DN_API DN_U8x32FromResult DN_U8x32FromHex(DN_Str8 hex_32b)
|
||||||
{
|
{
|
||||||
DN_U8x32FromResult result = {};
|
DN_U8x32FromResult result = {};
|
||||||
DN_USize bytes_written = DN_BytesFromHexPtr(hex_32b.data, hex_32b.count, result.value.data, sizeof(result.value.data));
|
DN_USize bytes_written = DN_PtrBytesFromPtrHex(hex_32b.data, hex_32b.count, result.value.data, sizeof(result.value.data));
|
||||||
if (bytes_written == sizeof(result.value.data))
|
if (bytes_written == sizeof(result.value.data))
|
||||||
result.success = true;
|
result.success = true;
|
||||||
return result;
|
return result;
|
||||||
@@ -4986,7 +4986,7 @@ DN_API DN_NibbleFromU8Result DN_NibbleFromU8(DN_U8 u8)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_USize DN_BytesFromHex(DN_Str8 hex, void *dest, DN_USize dest_count)
|
DN_API DN_USize DN_PtrBytesFromStr8Hex(DN_Str8 hex, void *dest, DN_USize dest_count)
|
||||||
{
|
{
|
||||||
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(hex);
|
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(hex);
|
||||||
DN_USize result = 0;
|
DN_USize result = 0;
|
||||||
@@ -5019,65 +5019,65 @@ DN_API DN_USize DN_BytesFromHex(DN_Str8 hex, void *dest, DN_USize dest_count)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_BytesFromHexArena(DN_Str8 hex, DN_Arena *arena)
|
DN_API DN_USize DN_PtrBytesFromPtrHex(char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count)
|
||||||
{
|
{
|
||||||
DN_Str8 result = DN_BytesFromHexPtrArena(hex.data, hex.count, arena);
|
DN_USize result = DN_PtrBytesFromStr8Hex(DN_Str8FromPtr(hex, hex_count), dest, dest_count);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_USize DN_BytesFromHexPtr(char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count)
|
DN_API DN_Str8 DN_Str8BytesFromStr8HexArena(DN_Str8 hex, DN_Arena *arena)
|
||||||
{
|
{
|
||||||
DN_USize result = DN_BytesFromHex(DN_Str8FromPtr(hex, hex_count), dest, dest_count);
|
DN_Str8 result = DN_Str8BytesFromPtrHexArena(hex.data, hex.count, arena);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_BytesFromHexPtrArena(char const *hex, DN_USize hex_count, DN_Arena *arena)
|
DN_API DN_Str8 DN_Str8BytesFromPtrHexArena(char const *hex, DN_USize hex_count, DN_Arena *arena)
|
||||||
{
|
{
|
||||||
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
||||||
DN_Assert(hex_trimmed.count % 2 == 0);
|
DN_Assert(hex_trimmed.count % 2 == 0);
|
||||||
DN_Str8 result = {};
|
DN_Str8 result = {};
|
||||||
result.data = DN_ArenaNewArray(arena, char, hex_trimmed.count / 2, DN_ZMem_No);
|
result.data = DN_ArenaNewArray(arena, char, hex_trimmed.count / 2, DN_ZMem_No);
|
||||||
if (result.data)
|
if (result.data)
|
||||||
result.count = DN_BytesFromHex(hex_trimmed, result.data, hex_trimmed.count / 2);
|
result.count = DN_PtrBytesFromStr8Hex(hex_trimmed, result.data, hex_trimmed.count / 2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_BytesFromHexPtrPool(char const *hex, DN_USize hex_count, DN_Pool *pool)
|
DN_API DN_Str8 DN_Str8BytesFromPtrHexPool(char const *hex, DN_USize hex_count, DN_Pool *pool)
|
||||||
{
|
{
|
||||||
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
||||||
DN_Assert(hex_trimmed.count % 2 == 0);
|
DN_Assert(hex_trimmed.count % 2 == 0);
|
||||||
DN_Str8 result = {};
|
DN_Str8 result = {};
|
||||||
result.data = DN_PoolNewArray(pool, char, hex_trimmed.count / 2);
|
result.data = DN_PoolNewArray(pool, char, hex_trimmed.count / 2);
|
||||||
if (result.data)
|
if (result.data)
|
||||||
result.count = DN_BytesFromHex(hex_trimmed, result.data, hex_trimmed.count / 2);
|
result.count = DN_PtrBytesFromStr8Hex(hex_trimmed, result.data, hex_trimmed.count / 2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DN_API DN_U8x16 DN_BytesFromHex32Ptr(char const *hex, DN_USize hex_count)
|
DN_API DN_U8x16 DN_U8x16FromPtrHex32(char const *hex, DN_USize hex_count)
|
||||||
{
|
{
|
||||||
DN_U8x16 result = {};
|
DN_U8x16 result = {};
|
||||||
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
||||||
DN_Assert(hex_trimmed.count / 2 == sizeof result.data);
|
DN_Assert(hex_trimmed.count / 2 == sizeof result.data);
|
||||||
DN_USize bytes_written = DN_BytesFromHex(hex_trimmed, result.data, sizeof result.data);
|
DN_USize bytes_written = DN_PtrBytesFromStr8Hex(hex_trimmed, result.data, sizeof result.data);
|
||||||
DN_Assert(bytes_written == sizeof result.data);
|
DN_Assert(bytes_written == sizeof result.data);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_U8x32 DN_BytesFromHex64Ptr(char const *hex, DN_USize hex_count)
|
DN_API DN_U8x32 DN_U8x32FromPtrHex64(char const *hex, DN_USize hex_count)
|
||||||
{
|
{
|
||||||
DN_U8x32 result = {};
|
DN_U8x32 result = {};
|
||||||
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
||||||
DN_Assert(hex_trimmed.count / 2 == sizeof result.data);
|
DN_Assert(hex_trimmed.count / 2 == sizeof result.data);
|
||||||
DN_USize bytes_written = DN_BytesFromHex(hex_trimmed, result.data, sizeof result.data);
|
DN_USize bytes_written = DN_PtrBytesFromStr8Hex(hex_trimmed, result.data, sizeof result.data);
|
||||||
DN_Assert(bytes_written == sizeof result.data);
|
DN_Assert(bytes_written == sizeof result.data);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_HexU64 DN_HexFromU64(DN_U64 value, DN_HexFromU64Type type)
|
DN_API DN_HexU64 DN_HexU64FromU64(DN_U64 value, DN_HexFromU64Type type)
|
||||||
{
|
{
|
||||||
DN_HexU64 result = {};
|
DN_HexU64 result = {};
|
||||||
DN_USize count = DN_HexFromPtrBytes(&value, sizeof(value), result.data, sizeof(result.data), DN_TrimLeadingZero_No);
|
DN_USize count = DN_PtrHexFromPtrBytes(&value, sizeof(value), result.data, sizeof(result.data), DN_TrimLeadingZero_No);
|
||||||
result.count = DN_SaturateCastUSizeToU8(count);
|
result.count = DN_SaturateCastUSizeToU8(count);
|
||||||
if (type == DN_HexFromU64Type_Uppercase) {
|
if (type == DN_HexFromU64Type_Uppercase) {
|
||||||
for (DN_USize index = 0; index < result.count; index++)
|
for (DN_USize index = 0; index < result.count; index++)
|
||||||
@@ -5086,7 +5086,7 @@ DN_API DN_HexU64 DN_HexFromU64(DN_U64 value, DN_HexFromU64Type type)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_USize DN_HexFromPtrBytes(void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_USize DN_PtrHexFromPtrBytes(void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_USize result = 0;
|
DN_USize result = 0;
|
||||||
if ((bytes_count * 2) > hex_count)
|
if ((bytes_count * 2) > hex_count)
|
||||||
@@ -5118,57 +5118,57 @@ DN_API DN_USize DN_HexFromPtrBytes(void const *bytes, DN_USize bytes_count, void
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_HexFromPtrBytesArena(void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_Str8 DN_Str8HexFromPtrBytesArena(void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_Str8 result = {};
|
DN_Str8 result = {};
|
||||||
if (bytes_count) {
|
if (bytes_count) {
|
||||||
result.data = DN_ArenaNewArray(arena, char, bytes_count * 2, DN_ZMem_No);
|
result.data = DN_ArenaNewArray(arena, char, bytes_count * 2, DN_ZMem_No);
|
||||||
if (result.data)
|
if (result.data)
|
||||||
result.count = DN_HexFromPtrBytes(bytes, bytes_count, result.data, bytes_count * 2, trim_leading_z);
|
result.count = DN_PtrHexFromPtrBytes(bytes, bytes_count, result.data, bytes_count * 2, trim_leading_z);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_USize DN_HexFromStr8Bytes(DN_Str8 bytes, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_USize DN_PtrHexFromStr8Bytes(DN_Str8 bytes, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_USize result = DN_HexFromPtrBytes(bytes.data, bytes.count, hex, hex_count, trim_leading_z);
|
DN_USize result = DN_PtrHexFromPtrBytes(bytes.data, bytes.count, hex, hex_count, trim_leading_z);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_HexFromStr8BytesArena(DN_Str8 bytes, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_Str8 DN_Str8HexFromStr8BytesArena(DN_Str8 bytes, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_Str8 result = {};
|
DN_Str8 result = {};
|
||||||
if (bytes.count) {
|
if (bytes.count) {
|
||||||
result.data = DN_ArenaNewArray(arena, char, bytes.count * 2, DN_ZMem_No);
|
result.data = DN_ArenaNewArray(arena, char, bytes.count * 2, DN_ZMem_No);
|
||||||
if (result.data)
|
if (result.data)
|
||||||
result.count = DN_HexFromStr8Bytes(bytes, result.data, bytes.count * 2, trim_leading_z);
|
result.count = DN_PtrHexFromStr8Bytes(bytes, result.data, bytes.count * 2, trim_leading_z);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Hex32 DN_Hex32FromPtr16b(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_Hex32 DN_Hex32FromPtrBytes16(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_Hex32 result = {};
|
DN_Hex32 result = {};
|
||||||
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
||||||
result.count = DN_HexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
result.count = DN_PtrHexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
||||||
DN_Assert(result.count <= sizeof result.data - 1);
|
DN_Assert(result.count <= sizeof result.data - 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Hex64 DN_Hex64FromPtr32b(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_Hex64 DN_Hex64FromPtrBytes32(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_Hex64 result = {};
|
DN_Hex64 result = {};
|
||||||
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
||||||
result.count = DN_HexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
result.count = DN_PtrHexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
||||||
DN_Assert(result.count <= sizeof result.data - 1);
|
DN_Assert(result.count <= sizeof result.data - 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Hex128 DN_Hex128FromPtr64b(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_Hex128 DN_Hex128FromPtrBytes64(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_Hex128 result = {};
|
DN_Hex128 result = {};
|
||||||
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
||||||
result.count = DN_HexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
result.count = DN_PtrHexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
||||||
DN_Assert(result.count <= sizeof result.data - 1);
|
DN_Assert(result.count <= sizeof result.data - 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -5748,7 +5748,7 @@ DN_API bool DN_QSortCompareStr8LexicographicDesc(void const* lhs, void const *rh
|
|||||||
DN_API bool DN_QSortCompareBytesLT(void const* lhs, void const *rhs, void *user_context)
|
DN_API bool DN_QSortCompareBytesLT(void const* lhs, void const *rhs, void *user_context)
|
||||||
{
|
{
|
||||||
DN_USize elem_size = *DN_Cast(DN_USize *)user_context;
|
DN_USize elem_size = *DN_Cast(DN_USize *)user_context;
|
||||||
bool result = DN_Memcmp(lhs, rhs, elem_size) < 0;
|
bool result = DN_Memcmp(lhs, rhs, elem_size) < 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5789,6 +5789,75 @@ DN_API void DN_QSortStr8LexicographicDesc(DN_Str8 *array, DN_USize array_size, D
|
|||||||
DN_QSort(array, array_size, sizeof(*array), /*user_context=*/ &eq_case, DN_QSortCompareStr8LexicographicDesc);
|
DN_QSort(array, array_size, sizeof(*array), /*user_context=*/ &eq_case, DN_QSortCompareStr8LexicographicDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DN_API bool DN_BSearchLessThanBytes(void const *lhs, void const *rhs, void *user_context)
|
||||||
|
{
|
||||||
|
DN_USize elem_size = *DN_Cast(DN_USize *)user_context;
|
||||||
|
bool result = DN_Memcmp(lhs, rhs, elem_size) < 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_BSearchResult DN_BSearch(void const *array, DN_USize count, DN_USize elem_size, void const *find, DN_BSearchType type, void *user_context, DN_BSearchLessThanFunc *less_than)
|
||||||
|
{
|
||||||
|
DN_BSearchResult result = {};
|
||||||
|
if (!array || count <= 0 || !less_than || !find)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
void const *end = DN_Cast(char *)array + (count * elem_size);
|
||||||
|
void const *first = array;
|
||||||
|
void const *last = end;
|
||||||
|
while (first != last) {
|
||||||
|
DN_USize dist = (DN_Cast(char *)last - DN_Cast(char *)first) / elem_size;
|
||||||
|
void const *it = DN_Cast(char *)first + ((dist / 2) * elem_size);
|
||||||
|
bool advance_first = false;
|
||||||
|
if (type == DN_BSearchType_UpperBound)
|
||||||
|
advance_first = !less_than(find, it, user_context);
|
||||||
|
else
|
||||||
|
advance_first = less_than(it, find, user_context);
|
||||||
|
|
||||||
|
if (advance_first)
|
||||||
|
first = DN_Cast(char *)it + (1 * elem_size);
|
||||||
|
else
|
||||||
|
last = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DN_BSearchType_Match: {
|
||||||
|
result.found = first != end && !less_than(find, first, user_context);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DN_BSearchType_LowerBound: /*FALLTHRU*/
|
||||||
|
case DN_BSearchType_UpperBound: {
|
||||||
|
result.found = first != end;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.index = (DN_Cast(char *)first - DN_Cast(char *)array) / elem_size;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_BSearchResult DN_BSearchBytes(void const *array, DN_USize count, DN_USize elem_size, void const *find, DN_BSearchType type)
|
||||||
|
{
|
||||||
|
DN_BSearchResult result = DN_BSearch(array, count, elem_size, find, type, &elem_size, DN_BSearchLessThanBytes);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_BSearchResult DN_BSearchUSize(DN_USize const *array, DN_USize count, DN_USize find, DN_BSearchType type)
|
||||||
|
{
|
||||||
|
DN_BSearchResult result = DN_BSearchBytes(array, count, sizeof(*array), &find, type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_BSearchResult DN_BSearchU64(DN_U64 const *array, DN_USize count, DN_U64 find, DN_BSearchType type)
|
||||||
|
{
|
||||||
|
DN_BSearchResult result = DN_BSearchBytes(array, count, sizeof(*array), &find, type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_BSearchResult DN_BSearchU32(DN_U32 const *array, DN_USize count, DN_U32 find, DN_BSearchType type)
|
||||||
|
{
|
||||||
|
DN_BSearchResult result = DN_BSearchBytes(array, count, sizeof(*array), &find, type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#define DN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL
|
#define DN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL
|
||||||
#define DN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL
|
#define DN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL
|
||||||
@@ -9303,6 +9372,109 @@ DN_API void DN_TestEnd(DN_TestCore *test)
|
|||||||
group->curr_entry = nullptr;
|
group->curr_entry = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DN_API DN_Str8 DN_Str8FromTestCore(DN_TestCore const *test, DN_Arena *arena, DN_Str8FromTestCoreFlags flags)
|
||||||
|
{
|
||||||
|
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
|
||||||
|
DN_USize padding_count = 100;
|
||||||
|
DN_Str8 padding_line = DN_Str8FillF(&scratch.arena, padding_count, ".");
|
||||||
|
if (flags & DN_Str8FromTestCoreFlags_Colour)
|
||||||
|
padding_line = DN_Str8FromFmtANSIColourU8RGBArena(DN_ANSIColourMode_Fg, 64, 64, 64, &scratch.arena, "%.*s", DN_Str8PrintFmt(padding_line));
|
||||||
|
|
||||||
|
DN_V3F32 const good_colour = DN_V3F32From3N(0, 255, 0);
|
||||||
|
DN_V3F32 const bad_colour = DN_V3F32From3N(255, 0, 0);
|
||||||
|
DN_Str8Builder builder = DN_Str8BuilderFromArena(arena);
|
||||||
|
for (DN_ForItSize(group_it, DN_TestGroup const, test->groups, test->groups_count)) {
|
||||||
|
DN_TestGroup const* group = group_it.data;
|
||||||
|
DN_USize group_successes = 0;
|
||||||
|
DN_USize group_failures = 0;
|
||||||
|
DN_MSVC_WARNING_PUSH
|
||||||
|
DN_MSVC_WARNING_DISABLE(6067) // _Param_(5) in call to 'DN_Str8BuilderAppendF' must be the address of a string. Actual type: 'const unsigned __int64'.
|
||||||
|
DN_MSVC_WARNING_DISABLE(6271) // Extra argument passed to 'DN_Str8BuilderAppendF'.
|
||||||
|
DN_Str8BuilderAppendF(&builder, "[%.*s] (%'zu test%s)\n", DN_Str8PrintFmt(group->name), group->entries_count, (group->entries_count > 1) ? "s" : "");
|
||||||
|
DN_MSVC_WARNING_POP
|
||||||
|
for (DN_ForItSize(entry_it, DN_TestEntry const, group->entries, group->entries_count)) {
|
||||||
|
DN_TestEntry const* entry = entry_it.data;
|
||||||
|
if (entry->failed)
|
||||||
|
group_failures++;
|
||||||
|
else
|
||||||
|
group_successes++;
|
||||||
|
|
||||||
|
// NOTE: Extract the test name and pad the line with dots (.)
|
||||||
|
DN_Str8 test_prefix = DN_Str8FromFmtArena(&scratch.arena, " [%zu/%zu] %.*s ", entry_it.index + 1, group->entries_count, DN_Str8PrintFmt(entry->name));
|
||||||
|
if (test_prefix.count < padding_line.count) {
|
||||||
|
DN_USize remaining = padding_line.count - test_prefix.count;
|
||||||
|
DN_Str8 padder = DN_Str8Subset(padding_line, 0, remaining);
|
||||||
|
test_prefix = DN_Str8AppendF(&scratch.arena, test_prefix, "%.*s", DN_Str8PrintFmt(padder));
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Construct the test line
|
||||||
|
DN_Str8 outcome_str8 = entry->failed ? DN_Str8Lit("FAILED") : DN_Str8Lit("OK");
|
||||||
|
if (flags & DN_Str8FromTestCoreFlags_Colour) {
|
||||||
|
if (entry->failed)
|
||||||
|
outcome_str8 = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, bad_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(outcome_str8));
|
||||||
|
else
|
||||||
|
outcome_str8 = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, good_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(outcome_str8));
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_F64 elapsed_ms = DN_OS_PerfCounterMs(entry->ts_begin, entry->ts_end);
|
||||||
|
DN_Str8BuilderAppendF(&builder, "%.*s %.*s (%.3fms)\n", DN_Str8PrintFmt(test_prefix), DN_Str8PrintFmt(outcome_str8), elapsed_ms);
|
||||||
|
|
||||||
|
// NOTE: Output the test diagnostics, populated on failure
|
||||||
|
if (entry->failed) {
|
||||||
|
for (DN_ForItSize(row_it, DN_TestDiagnosticRow, entry->diagnostics, entry->diagnostics_count)) {
|
||||||
|
DN_USize row_count = 1;
|
||||||
|
DN_Str8TableFlags table_flags = DN_Str8TableFlags_None;
|
||||||
|
if (row_it.index == 0) {
|
||||||
|
row_count++; // Header
|
||||||
|
table_flags |= DN_Str8TableFlags_HasHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_USize col_count = 3; // Expression, Eval, Call site
|
||||||
|
DN_USize row_index = 0;
|
||||||
|
DN_Str8 *rows_str8 = DN_ArenaNewArrayZ(&scratch.arena, DN_Str8, row_count * col_count);
|
||||||
|
if (row_it.index == 0) {
|
||||||
|
rows_str8[row_index++] = DN_Str8Lit("Expr.");
|
||||||
|
rows_str8[row_index++] = DN_Str8Lit("Eval.");
|
||||||
|
rows_str8[row_index++] = DN_Str8Lit("Location");
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_TestDiagnosticRow *row = row_it.data;
|
||||||
|
DN_Str8 file_name = DN_Str8FileNameFromPath(row->call_site.file);
|
||||||
|
rows_str8[row_index++] = row->expr;
|
||||||
|
rows_str8[row_index++] = row->invariant;
|
||||||
|
rows_str8[row_index++] = DN_Str8FromFmtArena(&scratch.arena, "%.*s:%u", DN_Str8PrintFmt(file_name), row->call_site.line);
|
||||||
|
|
||||||
|
DN_Str8 table = DN_Str8Table(rows_str8, row_count, col_count, table_flags, &scratch.arena);
|
||||||
|
table = DN_Str8PadNewLinesArena(table, DN_Str8Lit(" "), &scratch.arena);
|
||||||
|
DN_Str8BuilderAppendF(&builder, " %.*s\n", DN_Str8PrintFmt(table));
|
||||||
|
if (row->message.count) {
|
||||||
|
DN_Str8 line_break = DN_Str8LineBreakArena(row->message, 100, DN_Str8Lit("\n "), DN_Str8LineBreakMode_AtWord, &scratch.arena);
|
||||||
|
DN_Str8BuilderAppendF(&builder, " User Message: %.*s\n", DN_Str8PrintFmt(line_break));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DN_Str8BuilderAppendF(&builder, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_F64 elapsed_ms = DN_OS_PerfCounterMs(group->ts_begin, group->ts_end);
|
||||||
|
DN_MSVC_WARNING_PUSH
|
||||||
|
DN_MSVC_WARNING_DISABLE(6067) // _Param_(3) in call to 'DN_Str8BuilderAppendF' must be the address of a string. Actual type: 'const unsigned __int64'.
|
||||||
|
DN_MSVC_WARNING_DISABLE(6271) // Extra argument passed to 'DN_Str8BuilderAppendF'.
|
||||||
|
DN_Str8 group_prefix = DN_Str8FromFmtArena(&scratch.arena, "%'zu/%'zu test%s", group_successes, group->entries_count, group_successes > 1 ? "s" :"");
|
||||||
|
DN_MSVC_WARNING_POP
|
||||||
|
if (flags & DN_Str8FromTestCoreFlags_Colour) {
|
||||||
|
if (group_failures == 0)
|
||||||
|
group_prefix = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, good_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(group_prefix));
|
||||||
|
else
|
||||||
|
group_prefix = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, bad_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(group_prefix));
|
||||||
|
}
|
||||||
|
DN_Str8BuilderAppendF(&builder, "\n %.*s passed in [%.*s] %.3fms (%zu failed)\n", DN_Str8PrintFmt(group_prefix), DN_Str8PrintFmt(group->name), elapsed_ms, group_failures);
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_Str8 result = DN_Str8FromStr8BuilderArena(&builder, arena);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
DN_API DN_TestDiagnosticRow *DN_TestVerifySetupFmtV(DN_TestCore *test, DN_CallSite call_site, DN_Str8 expr, bool verify_failed, char const *fmt, va_list args)
|
DN_API DN_TestDiagnosticRow *DN_TestVerifySetupFmtV(DN_TestCore *test, DN_CallSite call_site, DN_Str8 expr, bool verify_failed, char const *fmt, va_list args)
|
||||||
{
|
{
|
||||||
DN_AssertF(test->curr_group, "Test group must be started before attempting to verify a test invariant");
|
DN_AssertF(test->curr_group, "Test group must be started before attempting to verify a test invariant");
|
||||||
@@ -9444,8 +9616,8 @@ DN_API void DN_TestVerifyBytesF(DN_TestCore *test, DN_CallSite call_site, DN_Str
|
|||||||
DN_TestDiagnosticRow *row = DN_TestVerifySetupFmtV(test, call_site, expr, verify_failed, fmt, args);
|
DN_TestDiagnosticRow *row = DN_TestVerifySetupFmtV(test, call_site, expr, verify_failed, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if (row) {
|
if (row) {
|
||||||
DN_Str8 bytes_hex = DN_HexFromStr8BytesArena(bytes, test->arena, DN_TrimLeadingZero_No);
|
DN_Str8 bytes_hex = DN_Str8HexFromStr8BytesArena(bytes, test->arena, DN_TrimLeadingZero_No);
|
||||||
DN_Str8 expect_hex = DN_HexFromStr8BytesArena(expect, test->arena, DN_TrimLeadingZero_No);
|
DN_Str8 expect_hex = DN_Str8HexFromStr8BytesArena(expect, test->arena, DN_TrimLeadingZero_No);
|
||||||
if (expect_eq)
|
if (expect_eq)
|
||||||
row->invariant = DN_Str8FromFmtArena(test->arena, "\"%.*s\" != \"%.*s\"", DN_Str8PrintFmt(bytes_hex), DN_Str8PrintFmt(expect_hex));
|
row->invariant = DN_Str8FromFmtArena(test->arena, "\"%.*s\" != \"%.*s\"", DN_Str8PrintFmt(bytes_hex), DN_Str8PrintFmt(expect_hex));
|
||||||
else
|
else
|
||||||
@@ -9453,109 +9625,6 @@ DN_API void DN_TestVerifyBytesF(DN_TestCore *test, DN_CallSite call_site, DN_Str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_Str8FromTestCore(DN_TestCore const *test, DN_Arena *arena, DN_Str8FromTestCoreFlags flags)
|
|
||||||
{
|
|
||||||
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
|
|
||||||
DN_USize padding_count = 100;
|
|
||||||
DN_Str8 padding_line = DN_Str8FillF(&scratch.arena, padding_count, ".");
|
|
||||||
if (flags & DN_Str8FromTestCoreFlags_Colour)
|
|
||||||
padding_line = DN_Str8FromFmtANSIColourU8RGBArena(DN_ANSIColourMode_Fg, 64, 64, 64, &scratch.arena, "%.*s", DN_Str8PrintFmt(padding_line));
|
|
||||||
|
|
||||||
DN_V3F32 const good_colour = DN_V3F32From3N(0, 255, 0);
|
|
||||||
DN_V3F32 const bad_colour = DN_V3F32From3N(255, 0, 0);
|
|
||||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(arena);
|
|
||||||
for (DN_ForItSize(group_it, DN_TestGroup const, test->groups, test->groups_count)) {
|
|
||||||
DN_TestGroup const* group = group_it.data;
|
|
||||||
DN_USize group_successes = 0;
|
|
||||||
DN_USize group_failures = 0;
|
|
||||||
DN_MSVC_WARNING_PUSH
|
|
||||||
DN_MSVC_WARNING_DISABLE(6067) // _Param_(5) in call to 'DN_Str8BuilderAppendF' must be the address of a string. Actual type: 'const unsigned __int64'.
|
|
||||||
DN_MSVC_WARNING_DISABLE(6271) // Extra argument passed to 'DN_Str8BuilderAppendF'.
|
|
||||||
DN_Str8BuilderAppendF(&builder, "[%.*s] (%'zu test%s)\n", DN_Str8PrintFmt(group->name), group->entries_count, (group->entries_count > 1) ? "s" : "");
|
|
||||||
DN_MSVC_WARNING_POP
|
|
||||||
for (DN_ForItSize(entry_it, DN_TestEntry const, group->entries, group->entries_count)) {
|
|
||||||
DN_TestEntry const* entry = entry_it.data;
|
|
||||||
if (entry->failed)
|
|
||||||
group_failures++;
|
|
||||||
else
|
|
||||||
group_successes++;
|
|
||||||
|
|
||||||
// NOTE: Extract the test name and pad the line with dots (.)
|
|
||||||
DN_Str8 test_prefix = DN_Str8FromFmtArena(&scratch.arena, " [%zu/%zu] %.*s ", entry_it.index + 1, group->entries_count, DN_Str8PrintFmt(entry->name));
|
|
||||||
if (test_prefix.count < padding_line.count) {
|
|
||||||
DN_USize remaining = padding_line.count - test_prefix.count;
|
|
||||||
DN_Str8 padder = DN_Str8Subset(padding_line, 0, remaining);
|
|
||||||
test_prefix = DN_Str8AppendF(&scratch.arena, test_prefix, "%.*s", DN_Str8PrintFmt(padder));
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Construct the test line
|
|
||||||
DN_Str8 outcome_str8 = entry->failed ? DN_Str8Lit("FAILED") : DN_Str8Lit("OK");
|
|
||||||
if (flags & DN_Str8FromTestCoreFlags_Colour) {
|
|
||||||
if (entry->failed)
|
|
||||||
outcome_str8 = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, bad_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(outcome_str8));
|
|
||||||
else
|
|
||||||
outcome_str8 = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, good_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(outcome_str8));
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_F64 elapsed_ms = DN_OS_PerfCounterMs(entry->ts_begin, entry->ts_end);
|
|
||||||
DN_Str8BuilderAppendF(&builder, "%.*s %.*s (%.3fms)\n", DN_Str8PrintFmt(test_prefix), DN_Str8PrintFmt(outcome_str8), elapsed_ms);
|
|
||||||
|
|
||||||
// NOTE: Output the test diagnostics, populated on failure
|
|
||||||
if (entry->failed) {
|
|
||||||
for (DN_ForItSize(row_it, DN_TestDiagnosticRow, entry->diagnostics, entry->diagnostics_count)) {
|
|
||||||
DN_USize row_count = 1;
|
|
||||||
DN_Str8TableFlags table_flags = DN_Str8TableFlags_None;
|
|
||||||
if (row_it.index == 0) {
|
|
||||||
row_count++; // Header
|
|
||||||
table_flags |= DN_Str8TableFlags_HasHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_USize col_count = 3; // Expression, Eval, Call site
|
|
||||||
DN_USize row_index = 0;
|
|
||||||
DN_Str8 *rows_str8 = DN_ArenaNewArrayZ(&scratch.arena, DN_Str8, row_count * col_count);
|
|
||||||
if (row_it.index == 0) {
|
|
||||||
rows_str8[row_index++] = DN_Str8Lit("Expr.");
|
|
||||||
rows_str8[row_index++] = DN_Str8Lit("Eval.");
|
|
||||||
rows_str8[row_index++] = DN_Str8Lit("Location");
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_TestDiagnosticRow *row = row_it.data;
|
|
||||||
DN_Str8 file_name = DN_Str8FileNameFromPath(row->call_site.file);
|
|
||||||
rows_str8[row_index++] = row->expr;
|
|
||||||
rows_str8[row_index++] = row->invariant;
|
|
||||||
rows_str8[row_index++] = DN_Str8FromFmtArena(&scratch.arena, "%.*s:%u", DN_Str8PrintFmt(file_name), row->call_site.line);
|
|
||||||
|
|
||||||
DN_Str8 table = DN_Str8Table(rows_str8, row_count, col_count, table_flags, &scratch.arena);
|
|
||||||
table = DN_Str8PadNewLinesArena(table, DN_Str8Lit(" "), &scratch.arena);
|
|
||||||
DN_Str8BuilderAppendF(&builder, " %.*s\n", DN_Str8PrintFmt(table));
|
|
||||||
if (row->message.count) {
|
|
||||||
DN_Str8 line_break = DN_Str8LineBreakArena(row->message, 100, DN_Str8Lit("\n "), DN_Str8LineBreakMode_AtWord, &scratch.arena);
|
|
||||||
DN_Str8BuilderAppendF(&builder, " User Message: %.*s\n", DN_Str8PrintFmt(line_break));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DN_Str8BuilderAppendF(&builder, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_F64 elapsed_ms = DN_OS_PerfCounterMs(group->ts_begin, group->ts_end);
|
|
||||||
DN_MSVC_WARNING_PUSH
|
|
||||||
DN_MSVC_WARNING_DISABLE(6067) // _Param_(3) in call to 'DN_Str8BuilderAppendF' must be the address of a string. Actual type: 'const unsigned __int64'.
|
|
||||||
DN_MSVC_WARNING_DISABLE(6271) // Extra argument passed to 'DN_Str8BuilderAppendF'.
|
|
||||||
DN_Str8 group_prefix = DN_Str8FromFmtArena(&scratch.arena, "%'zu/%'zu test%s", group_successes, group->entries_count, group_successes > 1 ? "s" :"");
|
|
||||||
DN_MSVC_WARNING_POP
|
|
||||||
if (flags & DN_Str8FromTestCoreFlags_Colour) {
|
|
||||||
if (group_failures == 0)
|
|
||||||
group_prefix = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, good_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(group_prefix));
|
|
||||||
else
|
|
||||||
group_prefix = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, bad_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(group_prefix));
|
|
||||||
}
|
|
||||||
DN_Str8BuilderAppendF(&builder, "\n %.*s passed in [%.*s] %.3fms (%zu failed)\n", DN_Str8PrintFmt(group_prefix), DN_Str8PrintFmt(group->name), elapsed_ms, group_failures);
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_Str8 result = DN_Str8FromStr8BuilderArena(&builder, arena);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DN_WITH_TESTS
|
#if DN_WITH_TESTS
|
||||||
#if defined(DN_PLATFORM_WIN32) && defined(DN_COMPILER_MSVC)
|
#if defined(DN_PLATFORM_WIN32) && defined(DN_COMPILER_MSVC)
|
||||||
// NOTE: Taken from MSDN __cpuid example implementation
|
// NOTE: Taken from MSDN __cpuid example implementation
|
||||||
@@ -10001,261 +10070,261 @@ DN_API DN_TestCore DN_TestSuite(DN_Arena *arena_)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: BytesHex
|
// NOTE: Hex/Bytes
|
||||||
{
|
{
|
||||||
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena_, 1);
|
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena_, 1);
|
||||||
DN_DEFER { DN_TCScratchEnd(&scratch); };
|
DN_DEFER { DN_TCScratchEnd(&scratch); };
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 0x123")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 0x123")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0x123"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0x123"));
|
||||||
DN_TestVerifyExprF(&result, val == 0x123, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0x123, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 0xFFFF")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 0xFFFF")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0xFFFF"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0xFFFF"));
|
||||||
DN_TestVerifyExprF(&result, val == 0xFFFF, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0xFFFF, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert FFFF")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert FFFF")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("FFFF"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("FFFF"));
|
||||||
DN_TestVerifyExprF(&result, val == 0xFFFF, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0xFFFF, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert abCD")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert abCD")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("abCD"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("abCD"));
|
||||||
DN_TestVerifyExprF(&result, val == 0xabCD, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0xabCD, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 0xabCD")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 0xabCD")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0xabCD"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0xabCD"));
|
||||||
DN_TestVerifyExprF(&result, val == 0xabCD, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0xabCD, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 0x")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 0x")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0x"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0x"));
|
||||||
DN_TestVerifyExprF(&result, val == 0x0, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0x0, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 0X")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 0X")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0X"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0X"));
|
||||||
DN_TestVerifyExprF(&result, val == 0x0, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0x0, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 3")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 3")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("3"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("3"));
|
||||||
DN_TestVerifyExprF(&result, val == 3, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 3, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert f")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert f")) {
|
||||||
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("f"));
|
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("f"));
|
||||||
DN_TestVerifyExpr(&result, res.success);
|
DN_TestVerifyExpr(&result, res.success);
|
||||||
DN_TestVerifyExpr(&result, res.value == 0xf);
|
DN_TestVerifyExpr(&result, res.value == 0xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert g")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert g")) {
|
||||||
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("g"));
|
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("g"));
|
||||||
DN_TestVerifyExpr(&result, !res.success);
|
DN_TestVerifyExpr(&result, !res.success);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert -0x3")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert -0x3")) {
|
||||||
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("-0x3"));
|
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("-0x3"));
|
||||||
DN_TestVerifyExpr(&result, !res.success);
|
DN_TestVerifyExpr(&result, !res.success);
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_U32 number = 0xd095f6;
|
DN_U32 number = 0xd095f6;
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert %x to string", number)) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert %x to string", number)) {
|
||||||
DN_Str8 number_hex = DN_HexFromPtrBytesArena(&number, sizeof(number), &scratch.arena, DN_TrimLeadingZero_No);
|
DN_Str8 number_hex = DN_Str8HexFromPtrBytesArena(&number, sizeof(number), &scratch.arena, DN_TrimLeadingZero_No);
|
||||||
DN_TestVerifyStr8EqF(&result, number_hex, DN_Str8Lit("f695d000"), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
|
DN_TestVerifyStr8EqF(&result, number_hex, DN_Str8Lit("f695d000"), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
|
||||||
}
|
}
|
||||||
|
|
||||||
number = 0xf6ed00;
|
number = 0xf6ed00;
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert %x to string", number)) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert %x to string", number)) {
|
||||||
DN_Str8 number_hex = DN_HexFromPtrBytesArena(&number, sizeof(number), &scratch.arena, DN_TrimLeadingZero_No);
|
DN_Str8 number_hex = DN_Str8HexFromPtrBytesArena(&number, sizeof(number), &scratch.arena, DN_TrimLeadingZero_No);
|
||||||
DN_TestVerifyStr8EqF(&result, number_hex, DN_Str8Lit("00edf600"), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
|
DN_TestVerifyStr8EqF(&result, number_hex, DN_Str8Lit("00edf600"), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_Str8 hex = DN_Str8Lit("0xf6ed00");
|
DN_Str8 hex = DN_Str8Lit("0xf6ed00");
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert %.*s to bytes", DN_Str8PrintFmt(hex))) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert %.*s to bytes", DN_Str8PrintFmt(hex))) {
|
||||||
DN_Str8 bytes = DN_BytesFromHexArena(hex, &scratch.arena);
|
DN_Str8 bytes = DN_Str8BytesFromStr8HexArena(hex, &scratch.arena);
|
||||||
DN_TestVerifyStr8EqF(&result,
|
DN_TestVerifyStr8EqF(&result,
|
||||||
bytes,
|
bytes,
|
||||||
DN_Str8Lit("\xf6\xed\x00"),
|
DN_Str8Lit("\xf6\xed\x00"),
|
||||||
"number_hex=%.*s",
|
"number_hex=%.*s",
|
||||||
DN_Str8PrintFmt(DN_HexFromPtrBytesArena(bytes.data, bytes.count, &scratch.arena, DN_TrimLeadingZero_No)));
|
DN_Str8PrintFmt(DN_Str8HexFromPtrBytesArena(bytes.data, bytes.count, &scratch.arena, DN_TrimLeadingZero_No)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert empty bytes to string")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert empty bytes to string")) {
|
||||||
DN_Str8 bytes = DN_Str8Lit("");
|
DN_Str8 bytes = DN_Str8Lit("");
|
||||||
DN_Str8 as_hex = DN_HexFromPtrBytesArena(bytes.data, bytes.count, &scratch.arena, DN_TrimLeadingZero_No);
|
DN_Str8 as_hex = DN_Str8HexFromPtrBytesArena(bytes.data, bytes.count, &scratch.arena, DN_TrimLeadingZero_No);
|
||||||
DN_TestVerifyStr8EqF(&result, as_hex, DN_Str8Lit(""), "as_hex=%.*s", DN_Str8PrintFmt(as_hex));
|
DN_TestVerifyStr8EqF(&result, as_hex, DN_Str8Lit(""), "as_hex=%.*s", DN_Str8PrintFmt(as_hex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: BinarySearch
|
// NOTE: BSearch
|
||||||
{
|
{
|
||||||
for (DN_TestScopeF(&result, "[BinarySearch] Search array of 1 item")) {
|
for (DN_TestScopeF(&result, "[BSearch] Search array of 1 item")) {
|
||||||
DN_U32 array[] = {1};
|
DN_U32 array[] = {1};
|
||||||
DN_BinarySearchResult search = {};
|
DN_BSearchResult search = {};
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BinarySearch] Search array of 3 items")) {
|
for (DN_TestScopeF(&result, "[BSearch] Search array of 3 items")) {
|
||||||
DN_U32 array[] = {1, 2, 3};
|
DN_U32 array[] = {1, 2, 3};
|
||||||
DN_BinarySearchResult search = {};
|
DN_BSearchResult search = {};
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 4U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 4U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 4U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 4U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 4U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 4U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BinarySearch] Search array with duplicate items")) {
|
for (DN_TestScopeF(&result, "[BSearch] Search array with duplicate items")) {
|
||||||
DN_U32 array[] = {1, 1, 2, 2, 3};
|
DN_U32 array[] = {1, 1, 2, 2, 3};
|
||||||
DN_BinarySearchResult search = {};
|
DN_BSearchResult search = {};
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 4U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 4U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 4U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 4U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Generated by the DN single header generator 2026-07-05 12:47:31
|
// Generated by the DN single header generator 2026-07-05 23:26:32
|
||||||
|
|
||||||
#if !defined(DN_H)
|
#if !defined(DN_H)
|
||||||
#define DN_H
|
#define DN_H
|
||||||
@@ -1542,7 +1542,42 @@ struct DN_Profiler
|
|||||||
DN_F64 frame_avg_tsc;
|
DN_F64 frame_avg_tsc;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef bool (DN_QSortCompareFunc)(void const *a, void const *b, void *user_context);
|
typedef bool (DN_QSortCompareFunc) (void const *lhs, void const *rhs, void *user_context);
|
||||||
|
typedef bool (DN_BSearchLessThanFunc)(void const *lhs, void const *rhs, void *user_context);
|
||||||
|
enum DN_BSearchType
|
||||||
|
{
|
||||||
|
// NOTE: Index of the match. If no match is found, found is set to false and the
|
||||||
|
// index is set to the index where the match should be inserted/exist, if
|
||||||
|
// it were in the array
|
||||||
|
DN_BSearchType_Match,
|
||||||
|
|
||||||
|
// NOTE: Index of the first element in the array that is `element >= find`. If no such
|
||||||
|
// item is found or the array is empty, then, the index is set to the array
|
||||||
|
// size and found is set to `false`.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// int array[] = {0, 1, 2, 3, 4, 5};
|
||||||
|
// DN_BSearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BSearchType_LowerBound);
|
||||||
|
// printf("%zu\n", result.index); // Prints index '4'
|
||||||
|
DN_BSearchType_LowerBound,
|
||||||
|
|
||||||
|
// NOTE: Index of the first element in the array that is `element > find`. If no such
|
||||||
|
// item is found or the array is empty, then, the index is set to the array
|
||||||
|
// size and found is set to `false`.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// int array[] = {0, 1, 2, 3, 4, 5};
|
||||||
|
// DN_BSearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BSearchType_UpperBound);
|
||||||
|
// printf("%zu\n", result.index); // Prints index '5'
|
||||||
|
DN_BSearchType_UpperBound,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DN_BSearchResult
|
||||||
|
{
|
||||||
|
bool found;
|
||||||
|
DN_USize index;
|
||||||
|
};
|
||||||
|
|
||||||
enum DN_ErrSinkMode
|
enum DN_ErrSinkMode
|
||||||
{
|
{
|
||||||
DN_ErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink
|
DN_ErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink
|
||||||
@@ -4953,22 +4988,22 @@ DN_API DN_USize DN_USizeCodepointCountFromUTF8
|
|||||||
DN_API DN_U8 DN_U8FromHexNibble (char hex);
|
DN_API DN_U8 DN_U8FromHexNibble (char hex);
|
||||||
DN_API DN_NibbleFromU8Result DN_NibbleFromU8 (DN_U8 u8);
|
DN_API DN_NibbleFromU8Result DN_NibbleFromU8 (DN_U8 u8);
|
||||||
|
|
||||||
DN_API DN_USize DN_BytesFromHex (DN_Str8 hex, void *dest, DN_USize dest_count);
|
DN_API DN_USize DN_PtrBytesFromStr8Hex (DN_Str8 hex, void *dest, DN_USize dest_count);
|
||||||
DN_API DN_Str8 DN_BytesFromHexArena (DN_Str8 hex, DN_Arena *arena);
|
DN_API DN_USize DN_PtrBytesFromPtrHex (char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count);
|
||||||
DN_API DN_USize DN_BytesFromHexPtr (char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count);
|
DN_API DN_Str8 DN_Str8BytesFromStr8HexArena (DN_Str8 hex, DN_Arena *arena);
|
||||||
DN_API DN_Str8 DN_BytesFromHexPtrArena (char const *hex, DN_USize hex_count, DN_Arena *arena);
|
DN_API DN_Str8 DN_Str8BytesFromPtrHexArena (char const *hex, DN_USize hex_count, DN_Arena *arena);
|
||||||
DN_API DN_Str8 DN_BytesFromHexPtrPool (char const *hex, DN_USize hex_count, DN_Pool *pool);
|
DN_API DN_Str8 DN_Str8BytesFromPtrHexPool (char const *hex, DN_USize hex_count, DN_Pool *pool);
|
||||||
DN_API DN_U8x16 DN_BytesFromHex32Ptr (char const *hex, DN_USize hex_count);
|
DN_API DN_U8x16 DN_U8x16FromPtrHex32 (char const *hex, DN_USize hex_count);
|
||||||
DN_API DN_U8x32 DN_BytesFromHex64Ptr (char const *hex, DN_USize hex_count);
|
DN_API DN_U8x32 DN_U8x32FromPtrHex64 (char const *hex, DN_USize hex_count);
|
||||||
|
|
||||||
DN_API DN_HexU64 DN_HexFromU64 (DN_U64 value, DN_HexFromU64Type type);
|
DN_API DN_HexU64 DN_HexU64FromU64 (DN_U64 value, DN_HexFromU64Type type);
|
||||||
DN_API DN_USize DN_HexFromPtrBytes (void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_USize DN_PtrHexFromPtrBytes (void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_Str8 DN_HexFromPtrBytesArena (void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_USize DN_PtrHexFromStr8Bytes (DN_Str8 bytes, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_USize DN_HexFromStr8Bytes (DN_Str8 bytes, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_Str8 DN_Str8HexFromPtrBytesArena (void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_Str8 DN_HexFromStr8BytesArena (DN_Str8 bytes, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_Str8 DN_Str8HexFromStr8BytesArena (DN_Str8 bytes, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_Hex32 DN_Hex32FromPtr16b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_Hex32 DN_Hex32FromPtrBytes16 (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_Hex64 DN_Hex64FromPtr32b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_Hex64 DN_Hex64FromPtrBytes32 (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_Hex128 DN_Hex128FromPtr64b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_Hex128 DN_Hex128FromPtrBytes64 (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
||||||
|
|
||||||
DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_AgeUnit units);
|
DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_AgeUnit units);
|
||||||
DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units);
|
DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units);
|
||||||
@@ -5060,6 +5095,13 @@ DN_API void DN_QSortStr8NaturalDesc
|
|||||||
DN_API void DN_QSortStr8LexicographicAsc (DN_Str8 *array, DN_USize array_size, DN_Str8EqCase eq_case);
|
DN_API void DN_QSortStr8LexicographicAsc (DN_Str8 *array, DN_USize array_size, DN_Str8EqCase eq_case);
|
||||||
DN_API void DN_QSortStr8LexicographicDesc (DN_Str8 *array, DN_USize array_size, DN_Str8EqCase eq_case);
|
DN_API void DN_QSortStr8LexicographicDesc (DN_Str8 *array, DN_USize array_size, DN_Str8EqCase eq_case);
|
||||||
|
|
||||||
|
DN_API bool DN_BSearchLessThanBytes (void const *lhs, void const *rhs, void *user_context);
|
||||||
|
DN_API DN_BSearchResult DN_BSearch (void const *array, DN_USize count, DN_USize elem_size, void const *find, DN_BSearchType type, void *user_context, DN_BSearchLessThanFunc *less_than);
|
||||||
|
DN_API DN_BSearchResult DN_BSearchBytes (void const *array, DN_USize count, DN_USize elem_size, void const *find, DN_BSearchType type);
|
||||||
|
DN_API DN_BSearchResult DN_BSearchUSize (DN_USize const *array, DN_USize count, DN_USize find, DN_BSearchType type);
|
||||||
|
DN_API DN_BSearchResult DN_BSearchU64 (DN_U64 const *array, DN_USize count, DN_U64 find, DN_BSearchType type);
|
||||||
|
DN_API DN_BSearchResult DN_BSearchU32 (DN_U32 const *array, DN_USize count, DN_U32 find, DN_BSearchType type);
|
||||||
|
|
||||||
DN_API DN_PCG32 DN_PCG32Init (DN_U64 seed);
|
DN_API DN_PCG32 DN_PCG32Init (DN_U64 seed);
|
||||||
DN_API DN_U32 DN_PCG32Next (DN_PCG32 *rng);
|
DN_API DN_U32 DN_PCG32Next (DN_PCG32 *rng);
|
||||||
DN_API DN_U64 DN_PCG32Next64 (DN_PCG32 *rng);
|
DN_API DN_U64 DN_PCG32Next64 (DN_PCG32 *rng);
|
||||||
@@ -6073,6 +6115,7 @@ DN_API void DN_TestGroupEnd
|
|||||||
DN_API void DN_TestBeginF (DN_TestCore *test, char const *fmt, ...);
|
DN_API void DN_TestBeginF (DN_TestCore *test, char const *fmt, ...);
|
||||||
DN_API void DN_TestEnd (DN_TestCore *test);
|
DN_API void DN_TestEnd (DN_TestCore *test);
|
||||||
#define DN_TestScopeF(test_ptr, fmt, ...) bool test_once_ = (DN_TestBeginF(test_ptr, fmt, ##__VA_ARGS__), false); !test_once_; DN_TestEnd(test_ptr), test_once_ = true
|
#define DN_TestScopeF(test_ptr, fmt, ...) bool test_once_ = (DN_TestBeginF(test_ptr, fmt, ##__VA_ARGS__), false); !test_once_; DN_TestEnd(test_ptr), test_once_ = true
|
||||||
|
DN_API DN_Str8 DN_Str8FromTestCore (DN_TestCore const *test, DN_Arena *arena, DN_Str8FromTestCoreFlags flags);
|
||||||
|
|
||||||
DN_API void DN_TestVerifyExprF_ (DN_TestCore *test, DN_CallSite call_site, DN_Str8 expr, bool expr_result, char const *fmt, ...);
|
DN_API void DN_TestVerifyExprF_ (DN_TestCore *test, DN_CallSite call_site, DN_Str8 expr, bool expr_result, char const *fmt, ...);
|
||||||
#define DN_TestVerifyExprF(test_ptr, expr, fmt, ...) DN_TestVerifyExprF_(test_ptr, DN_CallSiteNow, DN_Str8Lit(#expr), (expr), fmt, ##__VA_ARGS__)
|
#define DN_TestVerifyExprF(test_ptr, expr, fmt, ...) DN_TestVerifyExprF_(test_ptr, DN_CallSiteNow, DN_Str8Lit(#expr), (expr), fmt, ##__VA_ARGS__)
|
||||||
@@ -6132,128 +6175,28 @@ DN_API void DN_TestVerifyBytesF
|
|||||||
#define DN_TestVerifyBytesNotEqF(test_ptr, bytes, expect, fmt, ...) DN_TestVerifyBytesF(test_ptr, DN_CallSiteNow, DN_Str8Lit(#bytes " != " #expect), (bytes), (expect), /*expect_eq=*/ false, fmt, ##__VA_ARGS__)
|
#define DN_TestVerifyBytesNotEqF(test_ptr, bytes, expect, fmt, ...) DN_TestVerifyBytesF(test_ptr, DN_CallSiteNow, DN_Str8Lit(#bytes " != " #expect), (bytes), (expect), /*expect_eq=*/ false, fmt, ##__VA_ARGS__)
|
||||||
#define DN_TestVerifyBytesNotEq(test_ptr, bytes, expect) DN_TestVerifyBytesF(test_ptr, DN_CallSiteNow, DN_Str8Lit(#bytes " != " #expect), (bytes), (expect), /*expect_eq=*/ false, "")
|
#define DN_TestVerifyBytesNotEq(test_ptr, bytes, expect) DN_TestVerifyBytesF(test_ptr, DN_CallSiteNow, DN_Str8Lit(#bytes " != " #expect), (bytes), (expect), /*expect_eq=*/ false, "")
|
||||||
|
|
||||||
DN_API DN_Str8 DN_Str8FromTestCore (DN_TestCore const *test, DN_Arena *arena, DN_Str8FromTestCoreFlags flags);
|
|
||||||
|
|
||||||
#if DN_WITH_TESTS
|
#if DN_WITH_TESTS
|
||||||
DN_API DN_TestCore DN_TestSuite (DN_Arena *arena_);
|
DN_API DN_TestCore DN_TestSuite (DN_Arena *arena_);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: Replace with a C implementation
|
DN_API void DN_LeakTrackAlloc_ (DN_LeakTracker *leak, void *ptr, DN_USize size, bool alloc_can_leak);
|
||||||
template <typename T>
|
DN_API void DN_LeakTrackDealloc_ (DN_LeakTracker *leak, void *ptr);
|
||||||
using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs);
|
DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs);
|
|
||||||
|
|
||||||
enum DN_BinarySearchType
|
|
||||||
{
|
|
||||||
// Index of the match. If no match is found, found is set to false and the
|
|
||||||
// index is set to the index where the match should be inserted/exist, if
|
|
||||||
// it were in the array
|
|
||||||
DN_BinarySearchType_Match,
|
|
||||||
|
|
||||||
// Index of the first element in the array that is `element >= find`. If no such
|
|
||||||
// item is found or the array is empty, then, the index is set to the array
|
|
||||||
// size and found is set to `false`.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// int array[] = {0, 1, 2, 3, 4, 5};
|
|
||||||
// DN_BinarySearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BinarySearchType_LowerBound);
|
|
||||||
// printf("%zu\n", result.index); // Prints index '4'
|
|
||||||
|
|
||||||
DN_BinarySearchType_LowerBound,
|
|
||||||
|
|
||||||
// Index of the first element in the array that is `element > find`. If no such
|
|
||||||
// item is found or the array is empty, then, the index is set to the array
|
|
||||||
// size and found is set to `false`.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// int array[] = {0, 1, 2, 3, 4, 5};
|
|
||||||
// DN_BinarySearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BinarySearchType_UpperBound);
|
|
||||||
// printf("%zu\n", result.index); // Prints index '5'
|
|
||||||
|
|
||||||
DN_BinarySearchType_UpperBound,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DN_BinarySearchResult
|
|
||||||
{
|
|
||||||
bool found;
|
|
||||||
DN_USize index;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs);
|
|
||||||
template <typename T> DN_BinarySearchResult DN_BinarySearch (T const *array, DN_USize array_size, T const &find, DN_BinarySearchType type = DN_BinarySearchType_Match, DN_BinarySearchLessThanProc<T> less_than = DN_BinarySearch_DefaultLessThan);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs)
|
|
||||||
{
|
|
||||||
bool result = lhs < rhs;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
DN_BinarySearchResult DN_BinarySearch(T const *array,
|
|
||||||
DN_USize array_size,
|
|
||||||
T const &find,
|
|
||||||
DN_BinarySearchType type,
|
|
||||||
DN_BinarySearchLessThanProc<T> less_than)
|
|
||||||
{
|
|
||||||
DN_BinarySearchResult result = {};
|
|
||||||
if (!array || array_size <= 0 || !less_than)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
T const *end = array + array_size;
|
|
||||||
T const *first = array;
|
|
||||||
T const *last = end;
|
|
||||||
while (first != last) {
|
|
||||||
DN_USize count = last - first;
|
|
||||||
T const *it = first + (count / 2);
|
|
||||||
|
|
||||||
bool advance_first = false;
|
|
||||||
if (type == DN_BinarySearchType_UpperBound)
|
|
||||||
advance_first = !less_than(find, it[0]);
|
|
||||||
else
|
|
||||||
advance_first = less_than(it[0], find);
|
|
||||||
|
|
||||||
if (advance_first)
|
|
||||||
first = it + 1;
|
|
||||||
else
|
|
||||||
last = it;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case DN_BinarySearchType_Match: {
|
|
||||||
result.found = first != end && !less_than(find, *first);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case DN_BinarySearchType_LowerBound: /*FALLTHRU*/
|
|
||||||
case DN_BinarySearchType_UpperBound: {
|
|
||||||
result.found = first != end;
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.index = first - array;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_API void DN_LeakTrackAlloc_ (DN_LeakTracker *leak, void *ptr, DN_USize size, bool alloc_can_leak);
|
|
||||||
DN_API void DN_LeakTrackDealloc_(DN_LeakTracker *leak, void *ptr);
|
|
||||||
DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
|
|
||||||
|
|
||||||
#if defined(DN_LEAK_TRACKING)
|
#if defined(DN_LEAK_TRACKING)
|
||||||
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) DN_LeakTrackAlloc_(leak, ptr, size, alloc_can_leak)
|
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) DN_LeakTrackAlloc_(leak, ptr, size, alloc_can_leak)
|
||||||
#define DN_LeakTrackDealloc(leak, ptr) DN_LeakTrackDealloc_(leak, ptr)
|
#define DN_LeakTrackDealloc(leak, ptr) DN_LeakTrackDealloc_(leak, ptr)
|
||||||
#define DN_LeakDump(leak) DN_LeakDump_(leak)
|
#define DN_LeakDump(leak) DN_LeakDump_(leak)
|
||||||
#else
|
#else
|
||||||
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
||||||
#define DN_LeakTrackDealloc(leak, ptr) do { (void)ptr; } while (0)
|
#define DN_LeakTrackDealloc(leak, ptr) do { (void)ptr; } while (0)
|
||||||
#define DN_LeakDump(leak) do { } while (0)
|
#define DN_LeakDump(leak) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DN_WITH_OS
|
#if DN_WITH_OS
|
||||||
DN_API DN_Str8 DN_OS_Str8FromStr8BuilderHeap (DN_Str8Builder const *builder);
|
DN_API DN_Str8 DN_OS_Str8FromStr8BuilderHeap (DN_Str8Builder const *builder);
|
||||||
DN_API void DN_OS_LogPrint (DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
|
DN_API void DN_OS_LogPrint (DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||||
DN_API void DN_OS_SetLogPrintFuncToOS ();
|
DN_API void DN_OS_SetLogPrintFuncToOS ();
|
||||||
|
|
||||||
// NOTE: Heap
|
// NOTE: Heap
|
||||||
// Overview
|
// Overview
|
||||||
|
|||||||
@@ -679,10 +679,10 @@ enum DN_SHA3TestHash
|
|||||||
DN_SHA3TestHash_Count,
|
DN_SHA3TestHash_Count,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void DN_SHA3TestHashDispatch_(DN_TestCore *test, DN_SHA3TestHash hash_type, DN_Str8 input)
|
static void DN_SHA3_TestHashDispatch_(DN_TestCore *test, DN_SHA3TestHash hash_type, DN_Str8 input)
|
||||||
{
|
{
|
||||||
DN_TCScratch scratch = DN_TCScratchBeginArena(&test->arena, 1);
|
DN_TCScratch scratch = DN_TCScratchBeginArena(&test->arena, 1);
|
||||||
DN_Str8 input_hex = DN_HexFromPtrBytesArena(input.data, input.count, &scratch.arena, DN_TrimLeadingZero_No);
|
DN_Str8 input_hex = DN_Str8HexFromPtrBytesArena(input.data, input.count, &scratch.arena, DN_TrimLeadingZero_No);
|
||||||
switch (hash_type) {
|
switch (hash_type) {
|
||||||
case DN_SHA3TestHash_Count: DN_AssertInvalidCodePath; break;
|
case DN_SHA3TestHash_Count: DN_AssertInvalidCodePath; break;
|
||||||
case DN_SHA3TestHash_224: {
|
case DN_SHA3TestHash_224: {
|
||||||
@@ -774,7 +774,7 @@ DN_TestCore DN_SHA3_TestSuite(DN_Arena *arena)
|
|||||||
|
|
||||||
for (DN_ForItCArray(it, DN_Str8 const, INPUTS)) {
|
for (DN_ForItCArray(it, DN_Str8 const, INPUTS)) {
|
||||||
for (DN_TestScopeF(&result, "[%.*s] %.*s", DN_Str8PrintFmt(hash_name), DN_Str8PrintFmt(*it.data)))
|
for (DN_TestScopeF(&result, "[%.*s] %.*s", DN_Str8PrintFmt(hash_name), DN_Str8PrintFmt(*it.data)))
|
||||||
DN_SHA3TestHashDispatch_(&result, DN_Cast(DN_SHA3TestHash)hash_type, *it.data);
|
DN_SHA3_TestHashDispatch_(&result, DN_Cast(DN_SHA3TestHash)hash_type, *it.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,7 +790,7 @@ DN_TestCore DN_SHA3_TestSuite(DN_Arena *arena)
|
|||||||
|
|
||||||
// NOTE: Do the hashing
|
// NOTE: Do the hashing
|
||||||
DN_Str8 input = DN_Str8FromPtr(src, src_size);
|
DN_Str8 input = DN_Str8FromPtr(src, src_size);
|
||||||
DN_SHA3TestHashDispatch_(&result, DN_Cast(DN_SHA3TestHash)hash_type, input);
|
DN_SHA3_TestHashDispatch_(&result, DN_Cast(DN_SHA3TestHash)hash_type, input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+272
-203
@@ -2677,14 +2677,14 @@ DN_API DN_U8x32 DN_U8x32FromHexUnsafe(DN_Str8 hex_32b)
|
|||||||
DN_U8x32 result = {};
|
DN_U8x32 result = {};
|
||||||
hex_32b = DN_Str8TrimHexPrefix(hex_32b);
|
hex_32b = DN_Str8TrimHexPrefix(hex_32b);
|
||||||
DN_Assert(hex_32b.count <= sizeof(result.data) * 2);
|
DN_Assert(hex_32b.count <= sizeof(result.data) * 2);
|
||||||
DN_BytesFromHexPtr(hex_32b.data, hex_32b.count, result.data, sizeof(result.data));
|
DN_PtrBytesFromPtrHex(hex_32b.data, hex_32b.count, result.data, sizeof(result.data));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_U8x32FromResult DN_U8x32FromHex(DN_Str8 hex_32b)
|
DN_API DN_U8x32FromResult DN_U8x32FromHex(DN_Str8 hex_32b)
|
||||||
{
|
{
|
||||||
DN_U8x32FromResult result = {};
|
DN_U8x32FromResult result = {};
|
||||||
DN_USize bytes_written = DN_BytesFromHexPtr(hex_32b.data, hex_32b.count, result.value.data, sizeof(result.value.data));
|
DN_USize bytes_written = DN_PtrBytesFromPtrHex(hex_32b.data, hex_32b.count, result.value.data, sizeof(result.value.data));
|
||||||
if (bytes_written == sizeof(result.value.data))
|
if (bytes_written == sizeof(result.value.data))
|
||||||
result.success = true;
|
result.success = true;
|
||||||
return result;
|
return result;
|
||||||
@@ -4984,7 +4984,7 @@ DN_API DN_NibbleFromU8Result DN_NibbleFromU8(DN_U8 u8)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_USize DN_BytesFromHex(DN_Str8 hex, void *dest, DN_USize dest_count)
|
DN_API DN_USize DN_PtrBytesFromStr8Hex(DN_Str8 hex, void *dest, DN_USize dest_count)
|
||||||
{
|
{
|
||||||
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(hex);
|
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(hex);
|
||||||
DN_USize result = 0;
|
DN_USize result = 0;
|
||||||
@@ -5017,65 +5017,65 @@ DN_API DN_USize DN_BytesFromHex(DN_Str8 hex, void *dest, DN_USize dest_count)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_BytesFromHexArena(DN_Str8 hex, DN_Arena *arena)
|
DN_API DN_USize DN_PtrBytesFromPtrHex(char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count)
|
||||||
{
|
{
|
||||||
DN_Str8 result = DN_BytesFromHexPtrArena(hex.data, hex.count, arena);
|
DN_USize result = DN_PtrBytesFromStr8Hex(DN_Str8FromPtr(hex, hex_count), dest, dest_count);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_USize DN_BytesFromHexPtr(char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count)
|
DN_API DN_Str8 DN_Str8BytesFromStr8HexArena(DN_Str8 hex, DN_Arena *arena)
|
||||||
{
|
{
|
||||||
DN_USize result = DN_BytesFromHex(DN_Str8FromPtr(hex, hex_count), dest, dest_count);
|
DN_Str8 result = DN_Str8BytesFromPtrHexArena(hex.data, hex.count, arena);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_BytesFromHexPtrArena(char const *hex, DN_USize hex_count, DN_Arena *arena)
|
DN_API DN_Str8 DN_Str8BytesFromPtrHexArena(char const *hex, DN_USize hex_count, DN_Arena *arena)
|
||||||
{
|
{
|
||||||
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
||||||
DN_Assert(hex_trimmed.count % 2 == 0);
|
DN_Assert(hex_trimmed.count % 2 == 0);
|
||||||
DN_Str8 result = {};
|
DN_Str8 result = {};
|
||||||
result.data = DN_ArenaNewArray(arena, char, hex_trimmed.count / 2, DN_ZMem_No);
|
result.data = DN_ArenaNewArray(arena, char, hex_trimmed.count / 2, DN_ZMem_No);
|
||||||
if (result.data)
|
if (result.data)
|
||||||
result.count = DN_BytesFromHex(hex_trimmed, result.data, hex_trimmed.count / 2);
|
result.count = DN_PtrBytesFromStr8Hex(hex_trimmed, result.data, hex_trimmed.count / 2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_BytesFromHexPtrPool(char const *hex, DN_USize hex_count, DN_Pool *pool)
|
DN_API DN_Str8 DN_Str8BytesFromPtrHexPool(char const *hex, DN_USize hex_count, DN_Pool *pool)
|
||||||
{
|
{
|
||||||
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
||||||
DN_Assert(hex_trimmed.count % 2 == 0);
|
DN_Assert(hex_trimmed.count % 2 == 0);
|
||||||
DN_Str8 result = {};
|
DN_Str8 result = {};
|
||||||
result.data = DN_PoolNewArray(pool, char, hex_trimmed.count / 2);
|
result.data = DN_PoolNewArray(pool, char, hex_trimmed.count / 2);
|
||||||
if (result.data)
|
if (result.data)
|
||||||
result.count = DN_BytesFromHex(hex_trimmed, result.data, hex_trimmed.count / 2);
|
result.count = DN_PtrBytesFromStr8Hex(hex_trimmed, result.data, hex_trimmed.count / 2);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DN_API DN_U8x16 DN_BytesFromHex32Ptr(char const *hex, DN_USize hex_count)
|
DN_API DN_U8x16 DN_U8x16FromPtrHex32(char const *hex, DN_USize hex_count)
|
||||||
{
|
{
|
||||||
DN_U8x16 result = {};
|
DN_U8x16 result = {};
|
||||||
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
||||||
DN_Assert(hex_trimmed.count / 2 == sizeof result.data);
|
DN_Assert(hex_trimmed.count / 2 == sizeof result.data);
|
||||||
DN_USize bytes_written = DN_BytesFromHex(hex_trimmed, result.data, sizeof result.data);
|
DN_USize bytes_written = DN_PtrBytesFromStr8Hex(hex_trimmed, result.data, sizeof result.data);
|
||||||
DN_Assert(bytes_written == sizeof result.data);
|
DN_Assert(bytes_written == sizeof result.data);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_U8x32 DN_BytesFromHex64Ptr(char const *hex, DN_USize hex_count)
|
DN_API DN_U8x32 DN_U8x32FromPtrHex64(char const *hex, DN_USize hex_count)
|
||||||
{
|
{
|
||||||
DN_U8x32 result = {};
|
DN_U8x32 result = {};
|
||||||
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
DN_Str8 hex_trimmed = DN_Str8TrimHexPrefix(DN_Str8FromPtr(hex, hex_count));
|
||||||
DN_Assert(hex_trimmed.count / 2 == sizeof result.data);
|
DN_Assert(hex_trimmed.count / 2 == sizeof result.data);
|
||||||
DN_USize bytes_written = DN_BytesFromHex(hex_trimmed, result.data, sizeof result.data);
|
DN_USize bytes_written = DN_PtrBytesFromStr8Hex(hex_trimmed, result.data, sizeof result.data);
|
||||||
DN_Assert(bytes_written == sizeof result.data);
|
DN_Assert(bytes_written == sizeof result.data);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_HexU64 DN_HexFromU64(DN_U64 value, DN_HexFromU64Type type)
|
DN_API DN_HexU64 DN_HexU64FromU64(DN_U64 value, DN_HexFromU64Type type)
|
||||||
{
|
{
|
||||||
DN_HexU64 result = {};
|
DN_HexU64 result = {};
|
||||||
DN_USize count = DN_HexFromPtrBytes(&value, sizeof(value), result.data, sizeof(result.data), DN_TrimLeadingZero_No);
|
DN_USize count = DN_PtrHexFromPtrBytes(&value, sizeof(value), result.data, sizeof(result.data), DN_TrimLeadingZero_No);
|
||||||
result.count = DN_SaturateCastUSizeToU8(count);
|
result.count = DN_SaturateCastUSizeToU8(count);
|
||||||
if (type == DN_HexFromU64Type_Uppercase) {
|
if (type == DN_HexFromU64Type_Uppercase) {
|
||||||
for (DN_USize index = 0; index < result.count; index++)
|
for (DN_USize index = 0; index < result.count; index++)
|
||||||
@@ -5084,7 +5084,7 @@ DN_API DN_HexU64 DN_HexFromU64(DN_U64 value, DN_HexFromU64Type type)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_USize DN_HexFromPtrBytes(void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_USize DN_PtrHexFromPtrBytes(void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_USize result = 0;
|
DN_USize result = 0;
|
||||||
if ((bytes_count * 2) > hex_count)
|
if ((bytes_count * 2) > hex_count)
|
||||||
@@ -5116,57 +5116,57 @@ DN_API DN_USize DN_HexFromPtrBytes(void const *bytes, DN_USize bytes_count, void
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_HexFromPtrBytesArena(void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_Str8 DN_Str8HexFromPtrBytesArena(void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_Str8 result = {};
|
DN_Str8 result = {};
|
||||||
if (bytes_count) {
|
if (bytes_count) {
|
||||||
result.data = DN_ArenaNewArray(arena, char, bytes_count * 2, DN_ZMem_No);
|
result.data = DN_ArenaNewArray(arena, char, bytes_count * 2, DN_ZMem_No);
|
||||||
if (result.data)
|
if (result.data)
|
||||||
result.count = DN_HexFromPtrBytes(bytes, bytes_count, result.data, bytes_count * 2, trim_leading_z);
|
result.count = DN_PtrHexFromPtrBytes(bytes, bytes_count, result.data, bytes_count * 2, trim_leading_z);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_USize DN_HexFromStr8Bytes(DN_Str8 bytes, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_USize DN_PtrHexFromStr8Bytes(DN_Str8 bytes, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_USize result = DN_HexFromPtrBytes(bytes.data, bytes.count, hex, hex_count, trim_leading_z);
|
DN_USize result = DN_PtrHexFromPtrBytes(bytes.data, bytes.count, hex, hex_count, trim_leading_z);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_HexFromStr8BytesArena(DN_Str8 bytes, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_Str8 DN_Str8HexFromStr8BytesArena(DN_Str8 bytes, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_Str8 result = {};
|
DN_Str8 result = {};
|
||||||
if (bytes.count) {
|
if (bytes.count) {
|
||||||
result.data = DN_ArenaNewArray(arena, char, bytes.count * 2, DN_ZMem_No);
|
result.data = DN_ArenaNewArray(arena, char, bytes.count * 2, DN_ZMem_No);
|
||||||
if (result.data)
|
if (result.data)
|
||||||
result.count = DN_HexFromStr8Bytes(bytes, result.data, bytes.count * 2, trim_leading_z);
|
result.count = DN_PtrHexFromStr8Bytes(bytes, result.data, bytes.count * 2, trim_leading_z);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Hex32 DN_Hex32FromPtr16b(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_Hex32 DN_Hex32FromPtrBytes16(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_Hex32 result = {};
|
DN_Hex32 result = {};
|
||||||
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
||||||
result.count = DN_HexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
result.count = DN_PtrHexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
||||||
DN_Assert(result.count <= sizeof result.data - 1);
|
DN_Assert(result.count <= sizeof result.data - 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Hex64 DN_Hex64FromPtr32b(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_Hex64 DN_Hex64FromPtrBytes32(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_Hex64 result = {};
|
DN_Hex64 result = {};
|
||||||
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
||||||
result.count = DN_HexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
result.count = DN_PtrHexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
||||||
DN_Assert(result.count <= sizeof result.data - 1);
|
DN_Assert(result.count <= sizeof result.data - 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Hex128 DN_Hex128FromPtr64b(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
DN_API DN_Hex128 DN_Hex128FromPtrBytes64(void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z)
|
||||||
{
|
{
|
||||||
DN_Hex128 result = {};
|
DN_Hex128 result = {};
|
||||||
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
DN_Assert(bytes_count * 2 == sizeof result.data - 1);
|
||||||
result.count = DN_HexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
result.count = DN_PtrHexFromPtrBytes(bytes, bytes_count, result.data, sizeof result.data, trim_leading_z);
|
||||||
DN_Assert(result.count <= sizeof result.data - 1);
|
DN_Assert(result.count <= sizeof result.data - 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -5746,7 +5746,7 @@ DN_API bool DN_QSortCompareStr8LexicographicDesc(void const* lhs, void const *rh
|
|||||||
DN_API bool DN_QSortCompareBytesLT(void const* lhs, void const *rhs, void *user_context)
|
DN_API bool DN_QSortCompareBytesLT(void const* lhs, void const *rhs, void *user_context)
|
||||||
{
|
{
|
||||||
DN_USize elem_size = *DN_Cast(DN_USize *)user_context;
|
DN_USize elem_size = *DN_Cast(DN_USize *)user_context;
|
||||||
bool result = DN_Memcmp(lhs, rhs, elem_size) < 0;
|
bool result = DN_Memcmp(lhs, rhs, elem_size) < 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5787,6 +5787,75 @@ DN_API void DN_QSortStr8LexicographicDesc(DN_Str8 *array, DN_USize array_size, D
|
|||||||
DN_QSort(array, array_size, sizeof(*array), /*user_context=*/ &eq_case, DN_QSortCompareStr8LexicographicDesc);
|
DN_QSort(array, array_size, sizeof(*array), /*user_context=*/ &eq_case, DN_QSortCompareStr8LexicographicDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DN_API bool DN_BSearchLessThanBytes(void const *lhs, void const *rhs, void *user_context)
|
||||||
|
{
|
||||||
|
DN_USize elem_size = *DN_Cast(DN_USize *)user_context;
|
||||||
|
bool result = DN_Memcmp(lhs, rhs, elem_size) < 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_BSearchResult DN_BSearch(void const *array, DN_USize count, DN_USize elem_size, void const *find, DN_BSearchType type, void *user_context, DN_BSearchLessThanFunc *less_than)
|
||||||
|
{
|
||||||
|
DN_BSearchResult result = {};
|
||||||
|
if (!array || count <= 0 || !less_than || !find)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
void const *end = DN_Cast(char *)array + (count * elem_size);
|
||||||
|
void const *first = array;
|
||||||
|
void const *last = end;
|
||||||
|
while (first != last) {
|
||||||
|
DN_USize dist = (DN_Cast(char *)last - DN_Cast(char *)first) / elem_size;
|
||||||
|
void const *it = DN_Cast(char *)first + ((dist / 2) * elem_size);
|
||||||
|
bool advance_first = false;
|
||||||
|
if (type == DN_BSearchType_UpperBound)
|
||||||
|
advance_first = !less_than(find, it, user_context);
|
||||||
|
else
|
||||||
|
advance_first = less_than(it, find, user_context);
|
||||||
|
|
||||||
|
if (advance_first)
|
||||||
|
first = DN_Cast(char *)it + (1 * elem_size);
|
||||||
|
else
|
||||||
|
last = it;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DN_BSearchType_Match: {
|
||||||
|
result.found = first != end && !less_than(find, first, user_context);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DN_BSearchType_LowerBound: /*FALLTHRU*/
|
||||||
|
case DN_BSearchType_UpperBound: {
|
||||||
|
result.found = first != end;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.index = (DN_Cast(char *)first - DN_Cast(char *)array) / elem_size;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_BSearchResult DN_BSearchBytes(void const *array, DN_USize count, DN_USize elem_size, void const *find, DN_BSearchType type)
|
||||||
|
{
|
||||||
|
DN_BSearchResult result = DN_BSearch(array, count, elem_size, find, type, &elem_size, DN_BSearchLessThanBytes);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_BSearchResult DN_BSearchUSize(DN_USize const *array, DN_USize count, DN_USize find, DN_BSearchType type)
|
||||||
|
{
|
||||||
|
DN_BSearchResult result = DN_BSearchBytes(array, count, sizeof(*array), &find, type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_BSearchResult DN_BSearchU64(DN_U64 const *array, DN_USize count, DN_U64 find, DN_BSearchType type)
|
||||||
|
{
|
||||||
|
DN_BSearchResult result = DN_BSearchBytes(array, count, sizeof(*array), &find, type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_API DN_BSearchResult DN_BSearchU32(DN_U32 const *array, DN_USize count, DN_U32 find, DN_BSearchType type)
|
||||||
|
{
|
||||||
|
DN_BSearchResult result = DN_BSearchBytes(array, count, sizeof(*array), &find, type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#define DN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL
|
#define DN_PCG_DEFAULT_MULTIPLIER_64 6364136223846793005ULL
|
||||||
#define DN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL
|
#define DN_PCG_DEFAULT_INCREMENT_64 1442695040888963407ULL
|
||||||
@@ -9301,6 +9370,109 @@ DN_API void DN_TestEnd(DN_TestCore *test)
|
|||||||
group->curr_entry = nullptr;
|
group->curr_entry = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DN_API DN_Str8 DN_Str8FromTestCore(DN_TestCore const *test, DN_Arena *arena, DN_Str8FromTestCoreFlags flags)
|
||||||
|
{
|
||||||
|
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
|
||||||
|
DN_USize padding_count = 100;
|
||||||
|
DN_Str8 padding_line = DN_Str8FillF(&scratch.arena, padding_count, ".");
|
||||||
|
if (flags & DN_Str8FromTestCoreFlags_Colour)
|
||||||
|
padding_line = DN_Str8FromFmtANSIColourU8RGBArena(DN_ANSIColourMode_Fg, 64, 64, 64, &scratch.arena, "%.*s", DN_Str8PrintFmt(padding_line));
|
||||||
|
|
||||||
|
DN_V3F32 const good_colour = DN_V3F32From3N(0, 255, 0);
|
||||||
|
DN_V3F32 const bad_colour = DN_V3F32From3N(255, 0, 0);
|
||||||
|
DN_Str8Builder builder = DN_Str8BuilderFromArena(arena);
|
||||||
|
for (DN_ForItSize(group_it, DN_TestGroup const, test->groups, test->groups_count)) {
|
||||||
|
DN_TestGroup const* group = group_it.data;
|
||||||
|
DN_USize group_successes = 0;
|
||||||
|
DN_USize group_failures = 0;
|
||||||
|
DN_MSVC_WARNING_PUSH
|
||||||
|
DN_MSVC_WARNING_DISABLE(6067) // _Param_(5) in call to 'DN_Str8BuilderAppendF' must be the address of a string. Actual type: 'const unsigned __int64'.
|
||||||
|
DN_MSVC_WARNING_DISABLE(6271) // Extra argument passed to 'DN_Str8BuilderAppendF'.
|
||||||
|
DN_Str8BuilderAppendF(&builder, "[%.*s] (%'zu test%s)\n", DN_Str8PrintFmt(group->name), group->entries_count, (group->entries_count > 1) ? "s" : "");
|
||||||
|
DN_MSVC_WARNING_POP
|
||||||
|
for (DN_ForItSize(entry_it, DN_TestEntry const, group->entries, group->entries_count)) {
|
||||||
|
DN_TestEntry const* entry = entry_it.data;
|
||||||
|
if (entry->failed)
|
||||||
|
group_failures++;
|
||||||
|
else
|
||||||
|
group_successes++;
|
||||||
|
|
||||||
|
// NOTE: Extract the test name and pad the line with dots (.)
|
||||||
|
DN_Str8 test_prefix = DN_Str8FromFmtArena(&scratch.arena, " [%zu/%zu] %.*s ", entry_it.index + 1, group->entries_count, DN_Str8PrintFmt(entry->name));
|
||||||
|
if (test_prefix.count < padding_line.count) {
|
||||||
|
DN_USize remaining = padding_line.count - test_prefix.count;
|
||||||
|
DN_Str8 padder = DN_Str8Subset(padding_line, 0, remaining);
|
||||||
|
test_prefix = DN_Str8AppendF(&scratch.arena, test_prefix, "%.*s", DN_Str8PrintFmt(padder));
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Construct the test line
|
||||||
|
DN_Str8 outcome_str8 = entry->failed ? DN_Str8Lit("FAILED") : DN_Str8Lit("OK");
|
||||||
|
if (flags & DN_Str8FromTestCoreFlags_Colour) {
|
||||||
|
if (entry->failed)
|
||||||
|
outcome_str8 = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, bad_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(outcome_str8));
|
||||||
|
else
|
||||||
|
outcome_str8 = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, good_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(outcome_str8));
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_F64 elapsed_ms = DN_OS_PerfCounterMs(entry->ts_begin, entry->ts_end);
|
||||||
|
DN_Str8BuilderAppendF(&builder, "%.*s %.*s (%.3fms)\n", DN_Str8PrintFmt(test_prefix), DN_Str8PrintFmt(outcome_str8), elapsed_ms);
|
||||||
|
|
||||||
|
// NOTE: Output the test diagnostics, populated on failure
|
||||||
|
if (entry->failed) {
|
||||||
|
for (DN_ForItSize(row_it, DN_TestDiagnosticRow, entry->diagnostics, entry->diagnostics_count)) {
|
||||||
|
DN_USize row_count = 1;
|
||||||
|
DN_Str8TableFlags table_flags = DN_Str8TableFlags_None;
|
||||||
|
if (row_it.index == 0) {
|
||||||
|
row_count++; // Header
|
||||||
|
table_flags |= DN_Str8TableFlags_HasHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_USize col_count = 3; // Expression, Eval, Call site
|
||||||
|
DN_USize row_index = 0;
|
||||||
|
DN_Str8 *rows_str8 = DN_ArenaNewArrayZ(&scratch.arena, DN_Str8, row_count * col_count);
|
||||||
|
if (row_it.index == 0) {
|
||||||
|
rows_str8[row_index++] = DN_Str8Lit("Expr.");
|
||||||
|
rows_str8[row_index++] = DN_Str8Lit("Eval.");
|
||||||
|
rows_str8[row_index++] = DN_Str8Lit("Location");
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_TestDiagnosticRow *row = row_it.data;
|
||||||
|
DN_Str8 file_name = DN_Str8FileNameFromPath(row->call_site.file);
|
||||||
|
rows_str8[row_index++] = row->expr;
|
||||||
|
rows_str8[row_index++] = row->invariant;
|
||||||
|
rows_str8[row_index++] = DN_Str8FromFmtArena(&scratch.arena, "%.*s:%u", DN_Str8PrintFmt(file_name), row->call_site.line);
|
||||||
|
|
||||||
|
DN_Str8 table = DN_Str8Table(rows_str8, row_count, col_count, table_flags, &scratch.arena);
|
||||||
|
table = DN_Str8PadNewLinesArena(table, DN_Str8Lit(" "), &scratch.arena);
|
||||||
|
DN_Str8BuilderAppendF(&builder, " %.*s\n", DN_Str8PrintFmt(table));
|
||||||
|
if (row->message.count) {
|
||||||
|
DN_Str8 line_break = DN_Str8LineBreakArena(row->message, 100, DN_Str8Lit("\n "), DN_Str8LineBreakMode_AtWord, &scratch.arena);
|
||||||
|
DN_Str8BuilderAppendF(&builder, " User Message: %.*s\n", DN_Str8PrintFmt(line_break));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DN_Str8BuilderAppendF(&builder, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_F64 elapsed_ms = DN_OS_PerfCounterMs(group->ts_begin, group->ts_end);
|
||||||
|
DN_MSVC_WARNING_PUSH
|
||||||
|
DN_MSVC_WARNING_DISABLE(6067) // _Param_(3) in call to 'DN_Str8BuilderAppendF' must be the address of a string. Actual type: 'const unsigned __int64'.
|
||||||
|
DN_MSVC_WARNING_DISABLE(6271) // Extra argument passed to 'DN_Str8BuilderAppendF'.
|
||||||
|
DN_Str8 group_prefix = DN_Str8FromFmtArena(&scratch.arena, "%'zu/%'zu test%s", group_successes, group->entries_count, group_successes > 1 ? "s" :"");
|
||||||
|
DN_MSVC_WARNING_POP
|
||||||
|
if (flags & DN_Str8FromTestCoreFlags_Colour) {
|
||||||
|
if (group_failures == 0)
|
||||||
|
group_prefix = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, good_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(group_prefix));
|
||||||
|
else
|
||||||
|
group_prefix = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, bad_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(group_prefix));
|
||||||
|
}
|
||||||
|
DN_Str8BuilderAppendF(&builder, "\n %.*s passed in [%.*s] %.3fms (%zu failed)\n", DN_Str8PrintFmt(group_prefix), DN_Str8PrintFmt(group->name), elapsed_ms, group_failures);
|
||||||
|
}
|
||||||
|
|
||||||
|
DN_Str8 result = DN_Str8FromStr8BuilderArena(&builder, arena);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
DN_API DN_TestDiagnosticRow *DN_TestVerifySetupFmtV(DN_TestCore *test, DN_CallSite call_site, DN_Str8 expr, bool verify_failed, char const *fmt, va_list args)
|
DN_API DN_TestDiagnosticRow *DN_TestVerifySetupFmtV(DN_TestCore *test, DN_CallSite call_site, DN_Str8 expr, bool verify_failed, char const *fmt, va_list args)
|
||||||
{
|
{
|
||||||
DN_AssertF(test->curr_group, "Test group must be started before attempting to verify a test invariant");
|
DN_AssertF(test->curr_group, "Test group must be started before attempting to verify a test invariant");
|
||||||
@@ -9442,8 +9614,8 @@ DN_API void DN_TestVerifyBytesF(DN_TestCore *test, DN_CallSite call_site, DN_Str
|
|||||||
DN_TestDiagnosticRow *row = DN_TestVerifySetupFmtV(test, call_site, expr, verify_failed, fmt, args);
|
DN_TestDiagnosticRow *row = DN_TestVerifySetupFmtV(test, call_site, expr, verify_failed, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if (row) {
|
if (row) {
|
||||||
DN_Str8 bytes_hex = DN_HexFromStr8BytesArena(bytes, test->arena, DN_TrimLeadingZero_No);
|
DN_Str8 bytes_hex = DN_Str8HexFromStr8BytesArena(bytes, test->arena, DN_TrimLeadingZero_No);
|
||||||
DN_Str8 expect_hex = DN_HexFromStr8BytesArena(expect, test->arena, DN_TrimLeadingZero_No);
|
DN_Str8 expect_hex = DN_Str8HexFromStr8BytesArena(expect, test->arena, DN_TrimLeadingZero_No);
|
||||||
if (expect_eq)
|
if (expect_eq)
|
||||||
row->invariant = DN_Str8FromFmtArena(test->arena, "\"%.*s\" != \"%.*s\"", DN_Str8PrintFmt(bytes_hex), DN_Str8PrintFmt(expect_hex));
|
row->invariant = DN_Str8FromFmtArena(test->arena, "\"%.*s\" != \"%.*s\"", DN_Str8PrintFmt(bytes_hex), DN_Str8PrintFmt(expect_hex));
|
||||||
else
|
else
|
||||||
@@ -9451,109 +9623,6 @@ DN_API void DN_TestVerifyBytesF(DN_TestCore *test, DN_CallSite call_site, DN_Str
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_API DN_Str8 DN_Str8FromTestCore(DN_TestCore const *test, DN_Arena *arena, DN_Str8FromTestCoreFlags flags)
|
|
||||||
{
|
|
||||||
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena, 1);
|
|
||||||
DN_USize padding_count = 100;
|
|
||||||
DN_Str8 padding_line = DN_Str8FillF(&scratch.arena, padding_count, ".");
|
|
||||||
if (flags & DN_Str8FromTestCoreFlags_Colour)
|
|
||||||
padding_line = DN_Str8FromFmtANSIColourU8RGBArena(DN_ANSIColourMode_Fg, 64, 64, 64, &scratch.arena, "%.*s", DN_Str8PrintFmt(padding_line));
|
|
||||||
|
|
||||||
DN_V3F32 const good_colour = DN_V3F32From3N(0, 255, 0);
|
|
||||||
DN_V3F32 const bad_colour = DN_V3F32From3N(255, 0, 0);
|
|
||||||
DN_Str8Builder builder = DN_Str8BuilderFromArena(arena);
|
|
||||||
for (DN_ForItSize(group_it, DN_TestGroup const, test->groups, test->groups_count)) {
|
|
||||||
DN_TestGroup const* group = group_it.data;
|
|
||||||
DN_USize group_successes = 0;
|
|
||||||
DN_USize group_failures = 0;
|
|
||||||
DN_MSVC_WARNING_PUSH
|
|
||||||
DN_MSVC_WARNING_DISABLE(6067) // _Param_(5) in call to 'DN_Str8BuilderAppendF' must be the address of a string. Actual type: 'const unsigned __int64'.
|
|
||||||
DN_MSVC_WARNING_DISABLE(6271) // Extra argument passed to 'DN_Str8BuilderAppendF'.
|
|
||||||
DN_Str8BuilderAppendF(&builder, "[%.*s] (%'zu test%s)\n", DN_Str8PrintFmt(group->name), group->entries_count, (group->entries_count > 1) ? "s" : "");
|
|
||||||
DN_MSVC_WARNING_POP
|
|
||||||
for (DN_ForItSize(entry_it, DN_TestEntry const, group->entries, group->entries_count)) {
|
|
||||||
DN_TestEntry const* entry = entry_it.data;
|
|
||||||
if (entry->failed)
|
|
||||||
group_failures++;
|
|
||||||
else
|
|
||||||
group_successes++;
|
|
||||||
|
|
||||||
// NOTE: Extract the test name and pad the line with dots (.)
|
|
||||||
DN_Str8 test_prefix = DN_Str8FromFmtArena(&scratch.arena, " [%zu/%zu] %.*s ", entry_it.index + 1, group->entries_count, DN_Str8PrintFmt(entry->name));
|
|
||||||
if (test_prefix.count < padding_line.count) {
|
|
||||||
DN_USize remaining = padding_line.count - test_prefix.count;
|
|
||||||
DN_Str8 padder = DN_Str8Subset(padding_line, 0, remaining);
|
|
||||||
test_prefix = DN_Str8AppendF(&scratch.arena, test_prefix, "%.*s", DN_Str8PrintFmt(padder));
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Construct the test line
|
|
||||||
DN_Str8 outcome_str8 = entry->failed ? DN_Str8Lit("FAILED") : DN_Str8Lit("OK");
|
|
||||||
if (flags & DN_Str8FromTestCoreFlags_Colour) {
|
|
||||||
if (entry->failed)
|
|
||||||
outcome_str8 = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, bad_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(outcome_str8));
|
|
||||||
else
|
|
||||||
outcome_str8 = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, good_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(outcome_str8));
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_F64 elapsed_ms = DN_OS_PerfCounterMs(entry->ts_begin, entry->ts_end);
|
|
||||||
DN_Str8BuilderAppendF(&builder, "%.*s %.*s (%.3fms)\n", DN_Str8PrintFmt(test_prefix), DN_Str8PrintFmt(outcome_str8), elapsed_ms);
|
|
||||||
|
|
||||||
// NOTE: Output the test diagnostics, populated on failure
|
|
||||||
if (entry->failed) {
|
|
||||||
for (DN_ForItSize(row_it, DN_TestDiagnosticRow, entry->diagnostics, entry->diagnostics_count)) {
|
|
||||||
DN_USize row_count = 1;
|
|
||||||
DN_Str8TableFlags table_flags = DN_Str8TableFlags_None;
|
|
||||||
if (row_it.index == 0) {
|
|
||||||
row_count++; // Header
|
|
||||||
table_flags |= DN_Str8TableFlags_HasHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_USize col_count = 3; // Expression, Eval, Call site
|
|
||||||
DN_USize row_index = 0;
|
|
||||||
DN_Str8 *rows_str8 = DN_ArenaNewArrayZ(&scratch.arena, DN_Str8, row_count * col_count);
|
|
||||||
if (row_it.index == 0) {
|
|
||||||
rows_str8[row_index++] = DN_Str8Lit("Expr.");
|
|
||||||
rows_str8[row_index++] = DN_Str8Lit("Eval.");
|
|
||||||
rows_str8[row_index++] = DN_Str8Lit("Location");
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_TestDiagnosticRow *row = row_it.data;
|
|
||||||
DN_Str8 file_name = DN_Str8FileNameFromPath(row->call_site.file);
|
|
||||||
rows_str8[row_index++] = row->expr;
|
|
||||||
rows_str8[row_index++] = row->invariant;
|
|
||||||
rows_str8[row_index++] = DN_Str8FromFmtArena(&scratch.arena, "%.*s:%u", DN_Str8PrintFmt(file_name), row->call_site.line);
|
|
||||||
|
|
||||||
DN_Str8 table = DN_Str8Table(rows_str8, row_count, col_count, table_flags, &scratch.arena);
|
|
||||||
table = DN_Str8PadNewLinesArena(table, DN_Str8Lit(" "), &scratch.arena);
|
|
||||||
DN_Str8BuilderAppendF(&builder, " %.*s\n", DN_Str8PrintFmt(table));
|
|
||||||
if (row->message.count) {
|
|
||||||
DN_Str8 line_break = DN_Str8LineBreakArena(row->message, 100, DN_Str8Lit("\n "), DN_Str8LineBreakMode_AtWord, &scratch.arena);
|
|
||||||
DN_Str8BuilderAppendF(&builder, " User Message: %.*s\n", DN_Str8PrintFmt(line_break));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DN_Str8BuilderAppendF(&builder, "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_F64 elapsed_ms = DN_OS_PerfCounterMs(group->ts_begin, group->ts_end);
|
|
||||||
DN_MSVC_WARNING_PUSH
|
|
||||||
DN_MSVC_WARNING_DISABLE(6067) // _Param_(3) in call to 'DN_Str8BuilderAppendF' must be the address of a string. Actual type: 'const unsigned __int64'.
|
|
||||||
DN_MSVC_WARNING_DISABLE(6271) // Extra argument passed to 'DN_Str8BuilderAppendF'.
|
|
||||||
DN_Str8 group_prefix = DN_Str8FromFmtArena(&scratch.arena, "%'zu/%'zu test%s", group_successes, group->entries_count, group_successes > 1 ? "s" :"");
|
|
||||||
DN_MSVC_WARNING_POP
|
|
||||||
if (flags & DN_Str8FromTestCoreFlags_Colour) {
|
|
||||||
if (group_failures == 0)
|
|
||||||
group_prefix = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, good_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(group_prefix));
|
|
||||||
else
|
|
||||||
group_prefix = DN_Str8FromFmtANSIColourV3F32RGB255Arena(DN_ANSIColourMode_Fg, bad_colour, &scratch.arena, "%.*s", DN_Str8PrintFmt(group_prefix));
|
|
||||||
}
|
|
||||||
DN_Str8BuilderAppendF(&builder, "\n %.*s passed in [%.*s] %.3fms (%zu failed)\n", DN_Str8PrintFmt(group_prefix), DN_Str8PrintFmt(group->name), elapsed_ms, group_failures);
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_Str8 result = DN_Str8FromStr8BuilderArena(&builder, arena);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DN_WITH_TESTS
|
#if DN_WITH_TESTS
|
||||||
#if defined(DN_PLATFORM_WIN32) && defined(DN_COMPILER_MSVC)
|
#if defined(DN_PLATFORM_WIN32) && defined(DN_COMPILER_MSVC)
|
||||||
// NOTE: Taken from MSDN __cpuid example implementation
|
// NOTE: Taken from MSDN __cpuid example implementation
|
||||||
@@ -9999,261 +10068,261 @@ DN_API DN_TestCore DN_TestSuite(DN_Arena *arena_)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: BytesHex
|
// NOTE: Hex/Bytes
|
||||||
{
|
{
|
||||||
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena_, 1);
|
DN_TCScratch scratch = DN_TCScratchBeginArena(&arena_, 1);
|
||||||
DN_DEFER { DN_TCScratchEnd(&scratch); };
|
DN_DEFER { DN_TCScratchEnd(&scratch); };
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 0x123")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 0x123")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0x123"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0x123"));
|
||||||
DN_TestVerifyExprF(&result, val == 0x123, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0x123, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 0xFFFF")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 0xFFFF")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0xFFFF"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0xFFFF"));
|
||||||
DN_TestVerifyExprF(&result, val == 0xFFFF, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0xFFFF, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert FFFF")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert FFFF")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("FFFF"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("FFFF"));
|
||||||
DN_TestVerifyExprF(&result, val == 0xFFFF, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0xFFFF, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert abCD")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert abCD")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("abCD"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("abCD"));
|
||||||
DN_TestVerifyExprF(&result, val == 0xabCD, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0xabCD, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 0xabCD")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 0xabCD")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0xabCD"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0xabCD"));
|
||||||
DN_TestVerifyExprF(&result, val == 0xabCD, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0xabCD, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 0x")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 0x")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0x"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0x"));
|
||||||
DN_TestVerifyExprF(&result, val == 0x0, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0x0, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 0X")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 0X")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0X"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("0X"));
|
||||||
DN_TestVerifyExprF(&result, val == 0x0, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 0x0, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert 3")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert 3")) {
|
||||||
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("3"));
|
uint64_t val = DN_U64FromHexStr8Unsafe(DN_Str8Lit("3"));
|
||||||
DN_TestVerifyExprF(&result, val == 3, "val: %" PRIu64, val);
|
DN_TestVerifyExprF(&result, val == 3, "val: %" PRIu64, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert f")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert f")) {
|
||||||
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("f"));
|
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("f"));
|
||||||
DN_TestVerifyExpr(&result, res.success);
|
DN_TestVerifyExpr(&result, res.success);
|
||||||
DN_TestVerifyExpr(&result, res.value == 0xf);
|
DN_TestVerifyExpr(&result, res.value == 0xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert g")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert g")) {
|
||||||
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("g"));
|
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("g"));
|
||||||
DN_TestVerifyExpr(&result, !res.success);
|
DN_TestVerifyExpr(&result, !res.success);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert -0x3")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert -0x3")) {
|
||||||
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("-0x3"));
|
DN_U64FromResult res = DN_U64FromHexStr8(DN_Str8Lit("-0x3"));
|
||||||
DN_TestVerifyExpr(&result, !res.success);
|
DN_TestVerifyExpr(&result, !res.success);
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_U32 number = 0xd095f6;
|
DN_U32 number = 0xd095f6;
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert %x to string", number)) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert %x to string", number)) {
|
||||||
DN_Str8 number_hex = DN_HexFromPtrBytesArena(&number, sizeof(number), &scratch.arena, DN_TrimLeadingZero_No);
|
DN_Str8 number_hex = DN_Str8HexFromPtrBytesArena(&number, sizeof(number), &scratch.arena, DN_TrimLeadingZero_No);
|
||||||
DN_TestVerifyStr8EqF(&result, number_hex, DN_Str8Lit("f695d000"), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
|
DN_TestVerifyStr8EqF(&result, number_hex, DN_Str8Lit("f695d000"), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
|
||||||
}
|
}
|
||||||
|
|
||||||
number = 0xf6ed00;
|
number = 0xf6ed00;
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert %x to string", number)) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert %x to string", number)) {
|
||||||
DN_Str8 number_hex = DN_HexFromPtrBytesArena(&number, sizeof(number), &scratch.arena, DN_TrimLeadingZero_No);
|
DN_Str8 number_hex = DN_Str8HexFromPtrBytesArena(&number, sizeof(number), &scratch.arena, DN_TrimLeadingZero_No);
|
||||||
DN_TestVerifyStr8EqF(&result, number_hex, DN_Str8Lit("00edf600"), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
|
DN_TestVerifyStr8EqF(&result, number_hex, DN_Str8Lit("00edf600"), "number_hex=%.*s", DN_Str8PrintFmt(number_hex));
|
||||||
}
|
}
|
||||||
|
|
||||||
DN_Str8 hex = DN_Str8Lit("0xf6ed00");
|
DN_Str8 hex = DN_Str8Lit("0xf6ed00");
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert %.*s to bytes", DN_Str8PrintFmt(hex))) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert %.*s to bytes", DN_Str8PrintFmt(hex))) {
|
||||||
DN_Str8 bytes = DN_BytesFromHexArena(hex, &scratch.arena);
|
DN_Str8 bytes = DN_Str8BytesFromStr8HexArena(hex, &scratch.arena);
|
||||||
DN_TestVerifyStr8EqF(&result,
|
DN_TestVerifyStr8EqF(&result,
|
||||||
bytes,
|
bytes,
|
||||||
DN_Str8Lit("\xf6\xed\x00"),
|
DN_Str8Lit("\xf6\xed\x00"),
|
||||||
"number_hex=%.*s",
|
"number_hex=%.*s",
|
||||||
DN_Str8PrintFmt(DN_HexFromPtrBytesArena(bytes.data, bytes.count, &scratch.arena, DN_TrimLeadingZero_No)));
|
DN_Str8PrintFmt(DN_Str8HexFromPtrBytesArena(bytes.data, bytes.count, &scratch.arena, DN_TrimLeadingZero_No)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BytesHex] Convert empty bytes to string")) {
|
for (DN_TestScopeF(&result, "[Hex/Bytes] Convert empty bytes to string")) {
|
||||||
DN_Str8 bytes = DN_Str8Lit("");
|
DN_Str8 bytes = DN_Str8Lit("");
|
||||||
DN_Str8 as_hex = DN_HexFromPtrBytesArena(bytes.data, bytes.count, &scratch.arena, DN_TrimLeadingZero_No);
|
DN_Str8 as_hex = DN_Str8HexFromPtrBytesArena(bytes.data, bytes.count, &scratch.arena, DN_TrimLeadingZero_No);
|
||||||
DN_TestVerifyStr8EqF(&result, as_hex, DN_Str8Lit(""), "as_hex=%.*s", DN_Str8PrintFmt(as_hex));
|
DN_TestVerifyStr8EqF(&result, as_hex, DN_Str8Lit(""), "as_hex=%.*s", DN_Str8PrintFmt(as_hex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: BinarySearch
|
// NOTE: BSearch
|
||||||
{
|
{
|
||||||
for (DN_TestScopeF(&result, "[BinarySearch] Search array of 1 item")) {
|
for (DN_TestScopeF(&result, "[BSearch] Search array of 1 item")) {
|
||||||
DN_U32 array[] = {1};
|
DN_U32 array[] = {1};
|
||||||
DN_BinarySearchResult search = {};
|
DN_BSearchResult search = {};
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BinarySearch] Search array of 3 items")) {
|
for (DN_TestScopeF(&result, "[BSearch] Search array of 3 items")) {
|
||||||
DN_U32 array[] = {1, 2, 3};
|
DN_U32 array[] = {1, 2, 3};
|
||||||
DN_BinarySearchResult search = {};
|
DN_BSearchResult search = {};
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 4U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 4U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 4U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 4U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
DN_TestVerifyUSizeEq(&result, search.index, 1);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 4U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 4U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
DN_TestVerifyUSizeEq(&result, search.index, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (DN_TestScopeF(&result, "[BinarySearch] Search array with duplicate items")) {
|
for (DN_TestScopeF(&result, "[BSearch] Search array with duplicate items")) {
|
||||||
DN_U32 array[] = {1, 1, 2, 2, 3};
|
DN_U32 array[] = {1, 1, 2, 2, 3};
|
||||||
DN_BinarySearchResult search = {};
|
DN_BSearchResult search = {};
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 4U, DN_BinarySearchType_Match);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 4U, DN_BSearchType_Match);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 4U, DN_BinarySearchType_LowerBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 4U, DN_BSearchType_LowerBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 0U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 0U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
DN_TestVerifyUSizeEq(&result, search.index, 0);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 1U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 1U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
DN_TestVerifyUSizeEq(&result, search.index, 2);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 2U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 2U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, search.found);
|
DN_TestVerifyExpr(&result, search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
DN_TestVerifyUSizeEq(&result, search.index, 4);
|
||||||
|
|
||||||
search = DN_BinarySearch<DN_U32>(array, DN_ArrayCountU(array), 3U, DN_BinarySearchType_UpperBound);
|
search = DN_BSearchU32(array, DN_ArrayCountU(array), 3U, DN_BSearchType_UpperBound);
|
||||||
DN_TestVerifyExpr(&result, !search.found);
|
DN_TestVerifyExpr(&result, !search.found);
|
||||||
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
DN_TestVerifyUSizeEq(&result, search.index, 5);
|
||||||
}
|
}
|
||||||
|
|||||||
+71
-128
@@ -1540,7 +1540,42 @@ struct DN_Profiler
|
|||||||
DN_F64 frame_avg_tsc;
|
DN_F64 frame_avg_tsc;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef bool (DN_QSortCompareFunc)(void const *a, void const *b, void *user_context);
|
typedef bool (DN_QSortCompareFunc) (void const *lhs, void const *rhs, void *user_context);
|
||||||
|
typedef bool (DN_BSearchLessThanFunc)(void const *lhs, void const *rhs, void *user_context);
|
||||||
|
enum DN_BSearchType
|
||||||
|
{
|
||||||
|
// NOTE: Index of the match. If no match is found, found is set to false and the
|
||||||
|
// index is set to the index where the match should be inserted/exist, if
|
||||||
|
// it were in the array
|
||||||
|
DN_BSearchType_Match,
|
||||||
|
|
||||||
|
// NOTE: Index of the first element in the array that is `element >= find`. If no such
|
||||||
|
// item is found or the array is empty, then, the index is set to the array
|
||||||
|
// size and found is set to `false`.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// int array[] = {0, 1, 2, 3, 4, 5};
|
||||||
|
// DN_BSearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BSearchType_LowerBound);
|
||||||
|
// printf("%zu\n", result.index); // Prints index '4'
|
||||||
|
DN_BSearchType_LowerBound,
|
||||||
|
|
||||||
|
// NOTE: Index of the first element in the array that is `element > find`. If no such
|
||||||
|
// item is found or the array is empty, then, the index is set to the array
|
||||||
|
// size and found is set to `false`.
|
||||||
|
//
|
||||||
|
// For example:
|
||||||
|
// int array[] = {0, 1, 2, 3, 4, 5};
|
||||||
|
// DN_BSearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BSearchType_UpperBound);
|
||||||
|
// printf("%zu\n", result.index); // Prints index '5'
|
||||||
|
DN_BSearchType_UpperBound,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DN_BSearchResult
|
||||||
|
{
|
||||||
|
bool found;
|
||||||
|
DN_USize index;
|
||||||
|
};
|
||||||
|
|
||||||
enum DN_ErrSinkMode
|
enum DN_ErrSinkMode
|
||||||
{
|
{
|
||||||
DN_ErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink
|
DN_ErrSinkMode_Nil, // Default behaviour to accumulate errors into the sink
|
||||||
@@ -3023,22 +3058,22 @@ DN_API DN_USize DN_USizeCodepointCountFromUTF8
|
|||||||
DN_API DN_U8 DN_U8FromHexNibble (char hex);
|
DN_API DN_U8 DN_U8FromHexNibble (char hex);
|
||||||
DN_API DN_NibbleFromU8Result DN_NibbleFromU8 (DN_U8 u8);
|
DN_API DN_NibbleFromU8Result DN_NibbleFromU8 (DN_U8 u8);
|
||||||
|
|
||||||
DN_API DN_USize DN_BytesFromHex (DN_Str8 hex, void *dest, DN_USize dest_count);
|
DN_API DN_USize DN_PtrBytesFromStr8Hex (DN_Str8 hex, void *dest, DN_USize dest_count);
|
||||||
DN_API DN_Str8 DN_BytesFromHexArena (DN_Str8 hex, DN_Arena *arena);
|
DN_API DN_USize DN_PtrBytesFromPtrHex (char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count);
|
||||||
DN_API DN_USize DN_BytesFromHexPtr (char const *hex, DN_USize hex_count, void *dest, DN_USize dest_count);
|
DN_API DN_Str8 DN_Str8BytesFromStr8HexArena (DN_Str8 hex, DN_Arena *arena);
|
||||||
DN_API DN_Str8 DN_BytesFromHexPtrArena (char const *hex, DN_USize hex_count, DN_Arena *arena);
|
DN_API DN_Str8 DN_Str8BytesFromPtrHexArena (char const *hex, DN_USize hex_count, DN_Arena *arena);
|
||||||
DN_API DN_Str8 DN_BytesFromHexPtrPool (char const *hex, DN_USize hex_count, DN_Pool *pool);
|
DN_API DN_Str8 DN_Str8BytesFromPtrHexPool (char const *hex, DN_USize hex_count, DN_Pool *pool);
|
||||||
DN_API DN_U8x16 DN_BytesFromHex32Ptr (char const *hex, DN_USize hex_count);
|
DN_API DN_U8x16 DN_U8x16FromPtrHex32 (char const *hex, DN_USize hex_count);
|
||||||
DN_API DN_U8x32 DN_BytesFromHex64Ptr (char const *hex, DN_USize hex_count);
|
DN_API DN_U8x32 DN_U8x32FromPtrHex64 (char const *hex, DN_USize hex_count);
|
||||||
|
|
||||||
DN_API DN_HexU64 DN_HexFromU64 (DN_U64 value, DN_HexFromU64Type type);
|
DN_API DN_HexU64 DN_HexU64FromU64 (DN_U64 value, DN_HexFromU64Type type);
|
||||||
DN_API DN_USize DN_HexFromPtrBytes (void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_USize DN_PtrHexFromPtrBytes (void const *bytes, DN_USize bytes_count, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_Str8 DN_HexFromPtrBytesArena (void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_USize DN_PtrHexFromStr8Bytes (DN_Str8 bytes, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_USize DN_HexFromStr8Bytes (DN_Str8 bytes, void *hex, DN_USize hex_count, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_Str8 DN_Str8HexFromPtrBytesArena (void const *bytes, DN_USize bytes_count, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_Str8 DN_HexFromStr8BytesArena (DN_Str8 bytes, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_Str8 DN_Str8HexFromStr8BytesArena (DN_Str8 bytes, DN_Arena *arena, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_Hex32 DN_Hex32FromPtr16b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_Hex32 DN_Hex32FromPtrBytes16 (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_Hex64 DN_Hex64FromPtr32b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_Hex64 DN_Hex64FromPtrBytes32 (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
||||||
DN_API DN_Hex128 DN_Hex128FromPtr64b (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
DN_API DN_Hex128 DN_Hex128FromPtrBytes64 (void const *bytes, DN_USize bytes_count, DN_TrimLeadingZero trim_leading_z);
|
||||||
|
|
||||||
DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_AgeUnit units);
|
DN_API DN_Str8x128 DN_AgeStr8FromMsU64 (DN_U64 duration_ms, DN_AgeUnit units);
|
||||||
DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units);
|
DN_API DN_Str8x128 DN_AgeStr8FromSecU64 (DN_U64 duration_ms, DN_AgeUnit units);
|
||||||
@@ -3130,6 +3165,13 @@ DN_API void DN_QSortStr8NaturalDesc
|
|||||||
DN_API void DN_QSortStr8LexicographicAsc (DN_Str8 *array, DN_USize array_size, DN_Str8EqCase eq_case);
|
DN_API void DN_QSortStr8LexicographicAsc (DN_Str8 *array, DN_USize array_size, DN_Str8EqCase eq_case);
|
||||||
DN_API void DN_QSortStr8LexicographicDesc (DN_Str8 *array, DN_USize array_size, DN_Str8EqCase eq_case);
|
DN_API void DN_QSortStr8LexicographicDesc (DN_Str8 *array, DN_USize array_size, DN_Str8EqCase eq_case);
|
||||||
|
|
||||||
|
DN_API bool DN_BSearchLessThanBytes (void const *lhs, void const *rhs, void *user_context);
|
||||||
|
DN_API DN_BSearchResult DN_BSearch (void const *array, DN_USize count, DN_USize elem_size, void const *find, DN_BSearchType type, void *user_context, DN_BSearchLessThanFunc *less_than);
|
||||||
|
DN_API DN_BSearchResult DN_BSearchBytes (void const *array, DN_USize count, DN_USize elem_size, void const *find, DN_BSearchType type);
|
||||||
|
DN_API DN_BSearchResult DN_BSearchUSize (DN_USize const *array, DN_USize count, DN_USize find, DN_BSearchType type);
|
||||||
|
DN_API DN_BSearchResult DN_BSearchU64 (DN_U64 const *array, DN_USize count, DN_U64 find, DN_BSearchType type);
|
||||||
|
DN_API DN_BSearchResult DN_BSearchU32 (DN_U32 const *array, DN_USize count, DN_U32 find, DN_BSearchType type);
|
||||||
|
|
||||||
DN_API DN_PCG32 DN_PCG32Init (DN_U64 seed);
|
DN_API DN_PCG32 DN_PCG32Init (DN_U64 seed);
|
||||||
DN_API DN_U32 DN_PCG32Next (DN_PCG32 *rng);
|
DN_API DN_U32 DN_PCG32Next (DN_PCG32 *rng);
|
||||||
DN_API DN_U64 DN_PCG32Next64 (DN_PCG32 *rng);
|
DN_API DN_U64 DN_PCG32Next64 (DN_PCG32 *rng);
|
||||||
@@ -4143,6 +4185,7 @@ DN_API void DN_TestGroupEnd
|
|||||||
DN_API void DN_TestBeginF (DN_TestCore *test, char const *fmt, ...);
|
DN_API void DN_TestBeginF (DN_TestCore *test, char const *fmt, ...);
|
||||||
DN_API void DN_TestEnd (DN_TestCore *test);
|
DN_API void DN_TestEnd (DN_TestCore *test);
|
||||||
#define DN_TestScopeF(test_ptr, fmt, ...) bool test_once_ = (DN_TestBeginF(test_ptr, fmt, ##__VA_ARGS__), false); !test_once_; DN_TestEnd(test_ptr), test_once_ = true
|
#define DN_TestScopeF(test_ptr, fmt, ...) bool test_once_ = (DN_TestBeginF(test_ptr, fmt, ##__VA_ARGS__), false); !test_once_; DN_TestEnd(test_ptr), test_once_ = true
|
||||||
|
DN_API DN_Str8 DN_Str8FromTestCore (DN_TestCore const *test, DN_Arena *arena, DN_Str8FromTestCoreFlags flags);
|
||||||
|
|
||||||
DN_API void DN_TestVerifyExprF_ (DN_TestCore *test, DN_CallSite call_site, DN_Str8 expr, bool expr_result, char const *fmt, ...);
|
DN_API void DN_TestVerifyExprF_ (DN_TestCore *test, DN_CallSite call_site, DN_Str8 expr, bool expr_result, char const *fmt, ...);
|
||||||
#define DN_TestVerifyExprF(test_ptr, expr, fmt, ...) DN_TestVerifyExprF_(test_ptr, DN_CallSiteNow, DN_Str8Lit(#expr), (expr), fmt, ##__VA_ARGS__)
|
#define DN_TestVerifyExprF(test_ptr, expr, fmt, ...) DN_TestVerifyExprF_(test_ptr, DN_CallSiteNow, DN_Str8Lit(#expr), (expr), fmt, ##__VA_ARGS__)
|
||||||
@@ -4202,128 +4245,28 @@ DN_API void DN_TestVerifyBytesF
|
|||||||
#define DN_TestVerifyBytesNotEqF(test_ptr, bytes, expect, fmt, ...) DN_TestVerifyBytesF(test_ptr, DN_CallSiteNow, DN_Str8Lit(#bytes " != " #expect), (bytes), (expect), /*expect_eq=*/ false, fmt, ##__VA_ARGS__)
|
#define DN_TestVerifyBytesNotEqF(test_ptr, bytes, expect, fmt, ...) DN_TestVerifyBytesF(test_ptr, DN_CallSiteNow, DN_Str8Lit(#bytes " != " #expect), (bytes), (expect), /*expect_eq=*/ false, fmt, ##__VA_ARGS__)
|
||||||
#define DN_TestVerifyBytesNotEq(test_ptr, bytes, expect) DN_TestVerifyBytesF(test_ptr, DN_CallSiteNow, DN_Str8Lit(#bytes " != " #expect), (bytes), (expect), /*expect_eq=*/ false, "")
|
#define DN_TestVerifyBytesNotEq(test_ptr, bytes, expect) DN_TestVerifyBytesF(test_ptr, DN_CallSiteNow, DN_Str8Lit(#bytes " != " #expect), (bytes), (expect), /*expect_eq=*/ false, "")
|
||||||
|
|
||||||
DN_API DN_Str8 DN_Str8FromTestCore (DN_TestCore const *test, DN_Arena *arena, DN_Str8FromTestCoreFlags flags);
|
|
||||||
|
|
||||||
#if DN_WITH_TESTS
|
#if DN_WITH_TESTS
|
||||||
DN_API DN_TestCore DN_TestSuite (DN_Arena *arena_);
|
DN_API DN_TestCore DN_TestSuite (DN_Arena *arena_);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: Replace with a C implementation
|
DN_API void DN_LeakTrackAlloc_ (DN_LeakTracker *leak, void *ptr, DN_USize size, bool alloc_can_leak);
|
||||||
template <typename T>
|
DN_API void DN_LeakTrackDealloc_ (DN_LeakTracker *leak, void *ptr);
|
||||||
using DN_BinarySearchLessThanProc = bool(T const &lhs, T const &rhs);
|
DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs);
|
|
||||||
|
|
||||||
enum DN_BinarySearchType
|
|
||||||
{
|
|
||||||
// Index of the match. If no match is found, found is set to false and the
|
|
||||||
// index is set to the index where the match should be inserted/exist, if
|
|
||||||
// it were in the array
|
|
||||||
DN_BinarySearchType_Match,
|
|
||||||
|
|
||||||
// Index of the first element in the array that is `element >= find`. If no such
|
|
||||||
// item is found or the array is empty, then, the index is set to the array
|
|
||||||
// size and found is set to `false`.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// int array[] = {0, 1, 2, 3, 4, 5};
|
|
||||||
// DN_BinarySearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BinarySearchType_LowerBound);
|
|
||||||
// printf("%zu\n", result.index); // Prints index '4'
|
|
||||||
|
|
||||||
DN_BinarySearchType_LowerBound,
|
|
||||||
|
|
||||||
// Index of the first element in the array that is `element > find`. If no such
|
|
||||||
// item is found or the array is empty, then, the index is set to the array
|
|
||||||
// size and found is set to `false`.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// int array[] = {0, 1, 2, 3, 4, 5};
|
|
||||||
// DN_BinarySearchResult result = DN_BinarySearch(array, DN_ArrayCountU(array), 4, DN_BinarySearchType_UpperBound);
|
|
||||||
// printf("%zu\n", result.index); // Prints index '5'
|
|
||||||
|
|
||||||
DN_BinarySearchType_UpperBound,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DN_BinarySearchResult
|
|
||||||
{
|
|
||||||
bool found;
|
|
||||||
DN_USize index;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs);
|
|
||||||
template <typename T> DN_BinarySearchResult DN_BinarySearch (T const *array, DN_USize array_size, T const &find, DN_BinarySearchType type = DN_BinarySearchType_Match, DN_BinarySearchLessThanProc<T> less_than = DN_BinarySearch_DefaultLessThan);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool DN_BinarySearch_DefaultLessThan(T const &lhs, T const &rhs)
|
|
||||||
{
|
|
||||||
bool result = lhs < rhs;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
DN_BinarySearchResult DN_BinarySearch(T const *array,
|
|
||||||
DN_USize array_size,
|
|
||||||
T const &find,
|
|
||||||
DN_BinarySearchType type,
|
|
||||||
DN_BinarySearchLessThanProc<T> less_than)
|
|
||||||
{
|
|
||||||
DN_BinarySearchResult result = {};
|
|
||||||
if (!array || array_size <= 0 || !less_than)
|
|
||||||
return result;
|
|
||||||
|
|
||||||
T const *end = array + array_size;
|
|
||||||
T const *first = array;
|
|
||||||
T const *last = end;
|
|
||||||
while (first != last) {
|
|
||||||
DN_USize count = last - first;
|
|
||||||
T const *it = first + (count / 2);
|
|
||||||
|
|
||||||
bool advance_first = false;
|
|
||||||
if (type == DN_BinarySearchType_UpperBound)
|
|
||||||
advance_first = !less_than(find, it[0]);
|
|
||||||
else
|
|
||||||
advance_first = less_than(it[0], find);
|
|
||||||
|
|
||||||
if (advance_first)
|
|
||||||
first = it + 1;
|
|
||||||
else
|
|
||||||
last = it;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case DN_BinarySearchType_Match: {
|
|
||||||
result.found = first != end && !less_than(find, *first);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case DN_BinarySearchType_LowerBound: /*FALLTHRU*/
|
|
||||||
case DN_BinarySearchType_UpperBound: {
|
|
||||||
result.found = first != end;
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.index = first - array;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DN_API void DN_LeakTrackAlloc_ (DN_LeakTracker *leak, void *ptr, DN_USize size, bool alloc_can_leak);
|
|
||||||
DN_API void DN_LeakTrackDealloc_(DN_LeakTracker *leak, void *ptr);
|
|
||||||
DN_API void DN_LeakDump_ (DN_LeakTracker *leak);
|
|
||||||
|
|
||||||
#if defined(DN_LEAK_TRACKING)
|
#if defined(DN_LEAK_TRACKING)
|
||||||
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) DN_LeakTrackAlloc_(leak, ptr, size, alloc_can_leak)
|
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) DN_LeakTrackAlloc_(leak, ptr, size, alloc_can_leak)
|
||||||
#define DN_LeakTrackDealloc(leak, ptr) DN_LeakTrackDealloc_(leak, ptr)
|
#define DN_LeakTrackDealloc(leak, ptr) DN_LeakTrackDealloc_(leak, ptr)
|
||||||
#define DN_LeakDump(leak) DN_LeakDump_(leak)
|
#define DN_LeakDump(leak) DN_LeakDump_(leak)
|
||||||
#else
|
#else
|
||||||
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
#define DN_LeakTrackAlloc(leak, ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
||||||
#define DN_LeakTrackDealloc(leak, ptr) do { (void)ptr; } while (0)
|
#define DN_LeakTrackDealloc(leak, ptr) do { (void)ptr; } while (0)
|
||||||
#define DN_LeakDump(leak) do { } while (0)
|
#define DN_LeakDump(leak) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DN_WITH_OS
|
#if DN_WITH_OS
|
||||||
DN_API DN_Str8 DN_OS_Str8FromStr8BuilderHeap (DN_Str8Builder const *builder);
|
DN_API DN_Str8 DN_OS_Str8FromStr8BuilderHeap (DN_Str8Builder const *builder);
|
||||||
DN_API void DN_OS_LogPrint (DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
|
DN_API void DN_OS_LogPrint (DN_LogTypeParam type, void *user_data, DN_CallSite call_site, DN_FMT_ATTRIB char const *fmt, va_list args);
|
||||||
DN_API void DN_OS_SetLogPrintFuncToOS ();
|
DN_API void DN_OS_SetLogPrintFuncToOS ();
|
||||||
|
|
||||||
// NOTE: Heap
|
// NOTE: Heap
|
||||||
// Overview
|
// Overview
|
||||||
|
|||||||
Reference in New Issue
Block a user