dqn: Add improved binary split and find routines for strings

This commit is contained in:
doyle 2023-07-02 17:25:24 +10:00
parent eac4eaefe1
commit 807c65a253
2 changed files with 175 additions and 134 deletions

244
dqn.h
View File

@ -935,9 +935,6 @@ DQN_API Dqn_usize Dqn_CString16_Size (wcha
// @param[in] size The size of the slice // @param[in] size The size of the slice
// @return The sliced string // @return The sliced string
// @proc Dqn_String8_BinarySplitStringChars
// @desc TODO(doyle): Write description
// @proc Dqn_String8_BinarySplit // @proc Dqn_String8_BinarySplit
// @desc Split a string into the substring occuring prior and after the first // @desc Split a string into the substring occuring prior and after the first
// occurence of the `delimiter`. Neither strings include the `delimiter`. // occurence of the `delimiter`. Neither strings include the `delimiter`.
@ -1129,6 +1126,20 @@ struct Dqn_String16 /// A pointer and length style string that holds slices to U
#endif #endif
}; };
struct Dqn_String8BinarySplitResult
{
Dqn_String8 lhs;
Dqn_String8 rhs;
};
struct Dqn_String8FindResult
{
bool found;
Dqn_usize index;
Dqn_String8 match;
Dqn_String8 match_to_end_of_buffer;
};
// NOTE: Macros ==================================================================================== // NOTE: Macros ====================================================================================
#define DQN_STRING8(string) Dqn_String8{(char *)(string), sizeof(string) - 1} #define DQN_STRING8(string) Dqn_String8{(char *)(string), sizeof(string) - 1}
#define DQN_STRING16(string) Dqn_String16{(wchar_t *)(string), (sizeof(string)/sizeof(string[0])) - 1} #define DQN_STRING16(string) Dqn_String16{(wchar_t *)(string), (sizeof(string)/sizeof(string[0])) - 1}
@ -1159,51 +1170,56 @@ enum Dqn_String8EqCase
Dqn_String8EqCase_Insensitive, Dqn_String8EqCase_Insensitive,
}; };
DQN_API Dqn_String8 Dqn_String8_InitCString8 (char const *src); enum Dqn_String8FindFlag
DQN_API bool Dqn_String8_IsValid (Dqn_String8 string);
DQN_API bool Dqn_String8_IsAll (Dqn_String8 string, Dqn_String8IsAll is_all);
DQN_API Dqn_String8 Dqn_String8_Slice (Dqn_String8 string, Dqn_usize offset, Dqn_usize size);
DQN_API Dqn_String8 Dqn_String8_BinarySplitStringChars(Dqn_String8 string, Dqn_String8 delimiter_chars, Dqn_String8 *rhs);
DQN_API Dqn_String8 Dqn_String8_BinarySplit (Dqn_String8 string, char delimiter, Dqn_String8 *rhs);
DQN_API Dqn_usize Dqn_String8_Split (Dqn_String8 string, Dqn_String8 delimiter, Dqn_String8 *splits, Dqn_usize splits_count);
DQN_API Dqn_String8 Dqn_String8_Segment (Dqn_Allocator allocator, Dqn_String8 src, Dqn_usize segment_size, char segment_char);
DQN_API bool Dqn_String8_Eq (Dqn_String8 lhs, Dqn_String8 rhs, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API bool Dqn_String8_EqInsensitive (Dqn_String8 lhs, Dqn_String8 rhs);
DQN_API bool Dqn_String8_StartsWith (Dqn_String8 string, Dqn_String8 prefix, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API bool Dqn_String8_StartsWithInsensitive (Dqn_String8 string, Dqn_String8 prefix);
DQN_API bool Dqn_String8_EndsWith (Dqn_String8 string, Dqn_String8 prefix, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API bool Dqn_String8_EndsWithInsensitive (Dqn_String8 string, Dqn_String8 prefix);
DQN_API bool Dqn_String8_HasChar (Dqn_String8 string, char ch);
DQN_API Dqn_String8 Dqn_String8_TrimPrefix (Dqn_String8 string, Dqn_String8 prefix, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API Dqn_String8 Dqn_String8_TrimSuffix (Dqn_String8 string, Dqn_String8 suffix, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API Dqn_String8 Dqn_String8_TrimWhitespaceAround (Dqn_String8 string);
DQN_API Dqn_String8 Dqn_String8_TrimByteOrderMark (Dqn_String8 string);
DQN_API Dqn_String8 Dqn_String8_FileNameFromPath (Dqn_String8 path);
DQN_API bool Dqn_String8_ToU64Checked (Dqn_String8 string, char separator, uint64_t *output);
DQN_API uint64_t Dqn_String8_ToU64 (Dqn_String8 string, char separator);
DQN_API bool Dqn_String8_ToI64Checked (Dqn_String8 string, char separator, int64_t *output);
DQN_API int64_t Dqn_String8_ToI64 (Dqn_String8 string, char separator);
struct Dqn_String8FindResult
{ {
bool found; Dqn_String8FindFlag_Digit = 1 << 0, // 0-9
Dqn_usize offset; Dqn_String8FindFlag_Whitespace = 1 << 1, // '\r', '\t', '\n', ' '
Dqn_String8 string; Dqn_String8FindFlag_Alphabet = 1 << 2, // A-Z, a-z
Dqn_String8FindFlag_Plus = 1 << 3, // +
Dqn_String8FindFlag_Minus = 1 << 4, // -
Dqn_String8FindFlag_AlphaNum = Dqn_String8FindFlag_Alphabet | Dqn_String8FindFlag_Digit,
}; };
DQN_API Dqn_String8FindResult Dqn_String8_Find (Dqn_String8 string, Dqn_String8 find, Dqn_usize start_index, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive); DQN_API Dqn_String8 Dqn_String8_InitCString8 (char const *src);
DQN_API Dqn_String8 Dqn_String8_Replace (Dqn_String8 string, Dqn_String8 find, Dqn_String8 replace, Dqn_usize start_index, Dqn_Allocator allocator, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive); DQN_API bool Dqn_String8_IsValid (Dqn_String8 string);
DQN_API Dqn_String8 Dqn_String8_ReplaceInsensitive (Dqn_String8 string, Dqn_String8 find, Dqn_String8 replace, Dqn_usize start_index, Dqn_Allocator allocator); DQN_API bool Dqn_String8_IsAll (Dqn_String8 string, Dqn_String8IsAll is_all);
DQN_API void Dqn_String8_Remove (Dqn_String8 *string, Dqn_usize offset, Dqn_usize size);
DQN_API Dqn_String8 Dqn_String8_Slice (Dqn_String8 string, Dqn_usize offset, Dqn_usize size);
DQN_API Dqn_String8BinarySplitResult Dqn_String8_BinarySplitArray (Dqn_String8 string, Dqn_String8 const *find, Dqn_usize find_size);
DQN_API Dqn_String8BinarySplitResult Dqn_String8_BinarySplit (Dqn_String8 string, Dqn_String8 find);
DQN_API Dqn_usize Dqn_String8_Split (Dqn_String8 string, Dqn_String8 delimiter, Dqn_String8 *splits, Dqn_usize splits_count);
DQN_API Dqn_String8FindResult Dqn_String8_FindFirstStringArray (Dqn_String8 string, Dqn_String8 const *find, Dqn_usize find_size);
DQN_API Dqn_String8FindResult Dqn_String8_FindFirstString (Dqn_String8 string, Dqn_String8 find);
DQN_API Dqn_String8FindResult Dqn_String8_FindFirst (Dqn_String8 string, uint32_t flags);
DQN_API Dqn_String8 Dqn_String8_Segment (Dqn_Allocator allocator, Dqn_String8 src, Dqn_usize segment_size, char segment_char);
DQN_API bool Dqn_String8_Eq (Dqn_String8 lhs, Dqn_String8 rhs, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API bool Dqn_String8_EqInsensitive (Dqn_String8 lhs, Dqn_String8 rhs);
DQN_API bool Dqn_String8_StartsWith (Dqn_String8 string, Dqn_String8 prefix, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API bool Dqn_String8_StartsWithInsensitive (Dqn_String8 string, Dqn_String8 prefix);
DQN_API bool Dqn_String8_EndsWith (Dqn_String8 string, Dqn_String8 prefix, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API bool Dqn_String8_EndsWithInsensitive (Dqn_String8 string, Dqn_String8 prefix);
DQN_API bool Dqn_String8_HasChar (Dqn_String8 string, char ch);
DQN_API Dqn_String8 Dqn_String8_TrimPrefix (Dqn_String8 string, Dqn_String8 prefix, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API Dqn_String8 Dqn_String8_TrimSuffix (Dqn_String8 string, Dqn_String8 suffix, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API Dqn_String8 Dqn_String8_TrimWhitespaceAround (Dqn_String8 string);
DQN_API Dqn_String8 Dqn_String8_TrimByteOrderMark (Dqn_String8 string);
DQN_API Dqn_String8 Dqn_String8_FileNameFromPath (Dqn_String8 path);
DQN_API bool Dqn_String8_ToU64Checked (Dqn_String8 string, char separator, uint64_t *output);
DQN_API uint64_t Dqn_String8_ToU64 (Dqn_String8 string, char separator);
DQN_API bool Dqn_String8_ToI64Checked (Dqn_String8 string, char separator, int64_t *output);
DQN_API int64_t Dqn_String8_ToI64 (Dqn_String8 string, char separator);
DQN_API Dqn_String8 Dqn_String8_Replace (Dqn_String8 string, Dqn_String8 find, Dqn_String8 replace, Dqn_usize start_index, Dqn_Allocator allocator, Dqn_String8EqCase eq_case = Dqn_String8EqCase_Sensitive);
DQN_API Dqn_String8 Dqn_String8_ReplaceInsensitive (Dqn_String8 string, Dqn_String8 find, Dqn_String8 replace, Dqn_usize start_index, Dqn_Allocator allocator);
DQN_API void Dqn_String8_Remove (Dqn_String8 *string, Dqn_usize offset, Dqn_usize size);
#if defined(__cplusplus) #if defined(__cplusplus)
DQN_API bool operator== (Dqn_String8 const &lhs, Dqn_String8 const &rhs); DQN_API bool operator== (Dqn_String8 const &lhs, Dqn_String8 const &rhs);
DQN_API bool operator!= (Dqn_String8 const &lhs, Dqn_String8 const &rhs); DQN_API bool operator!= (Dqn_String8 const &lhs, Dqn_String8 const &rhs);
#endif #endif
// NOTE: Internal ================================================================================== // NOTE: Internal ==================================================================================
@ -2714,7 +2730,7 @@ DQN_API uint64_t Dqn_Safe_SaturateCastIntToU64(int val);
// ================================================================================================= // =================================================================================================
// [$CHAR] Dqn_Char | | Character ascii/digit.. helpers // [$CHAR] Dqn_Char | | Character ascii/digit.. helpers
// ================================================================================================= // =================================================================================================
DQN_API bool Dqn_Char_IsAlpha (char ch); DQN_API bool Dqn_Char_IsAlphabet (char ch);
DQN_API bool Dqn_Char_IsDigit (char ch); DQN_API bool Dqn_Char_IsDigit (char ch);
DQN_API bool Dqn_Char_IsAlphaNum (char ch); DQN_API bool Dqn_Char_IsAlphaNum (char ch);
DQN_API bool Dqn_Char_IsWhitespace (char ch); DQN_API bool Dqn_Char_IsWhitespace (char ch);
@ -5288,46 +5304,32 @@ DQN_API Dqn_String8 Dqn_String8_Slice(Dqn_String8 string, Dqn_usize offset, Dqn_
return result; return result;
} }
DQN_API Dqn_String8 Dqn_String8_BinarySplitStringChars(Dqn_String8 string, Dqn_String8 delimiter_chars, Dqn_String8 *rhs) DQN_API Dqn_String8BinarySplitResult Dqn_String8_BinarySplitArray(Dqn_String8 string, Dqn_String8 const *find, Dqn_usize find_size)
{ {
Dqn_String8 result = string; Dqn_String8BinarySplitResult result = {};
if (rhs) if (!Dqn_String8_IsValid(string) || !find || find_size == 0)
*rhs = {};
if (!Dqn_String8_IsValid(string))
return result; return result;
Dqn_usize offset = 0; result.lhs = string;
for (bool hit_delimiter = false; !hit_delimiter && offset < string.size; ) { for (size_t index = 0; index <= string.size; index++) {
for (Dqn_usize index = 0; !hit_delimiter && index < delimiter_chars.size; index++) { for (Dqn_usize find_index = 0; find_index < find_size; find_index++) {
char delimiter = delimiter_chars.data[index]; Dqn_String8 find_item = find[find_index];
hit_delimiter = string.data[offset] == delimiter; Dqn_String8 string_slice = Dqn_String8_Slice(string, index, find_item.size);
} if (Dqn_String8_Eq(string_slice, find_item)) {
result.lhs.size = index;
if (!hit_delimiter) result.rhs.data = string_slice.data + find_item.size;
offset++; result.rhs.size = string.size - (index + find_item.size);
} break;
}
// NOTE: LHS, the string before the delimiter
result = Dqn_String8_Init(string.data, offset);
// NOTE: RHS, the string after the delimiter
if (rhs) {
char *end = string.data + string.size;
char *next = DQN_MIN((string.data + offset + 1), end);
if (next != end) {
rhs->data = next;
rhs->size = end - rhs->data;
} }
} }
return result; return result;
} }
DQN_API Dqn_String8 Dqn_String8_BinarySplit(Dqn_String8 string, char delimiter, Dqn_String8 *rhs) DQN_API Dqn_String8BinarySplitResult Dqn_String8_BinarySplit(Dqn_String8 string, Dqn_String8 find)
{ {
Dqn_String8 delimiter_chars = Dqn_String8_Init(&delimiter, 1); Dqn_String8BinarySplitResult result = Dqn_String8_BinarySplitArray(string, &find, 1);
Dqn_String8 result = Dqn_String8_BinarySplitStringChars(string, delimiter_chars, rhs);
return result; return result;
} }
@ -5361,6 +5363,52 @@ DQN_API Dqn_usize Dqn_String8_Split(Dqn_String8 string, Dqn_String8 delimiter, D
return result; return result;
} }
DQN_API Dqn_String8FindResult Dqn_String8_FindFirstStringArray(Dqn_String8 string, Dqn_String8 const *find, Dqn_usize find_size)
{
Dqn_String8FindResult result = {};
if (!Dqn_String8_IsValid(string) || !find || find_size == 0)
return result;
for (Dqn_usize index = 0; !result.found && index < string.size; index++) {
for (Dqn_usize find_index = 0; find_index < find_size; find_index++) {
Dqn_String8 find_item = find[find_index];
Dqn_String8 string_slice = Dqn_String8_Slice(string, index, find_item.size);
if (Dqn_String8_Eq(string_slice, find_item)) {
result.found = true;
result.index = index;
result.match = Dqn_String8_Init(string.data + index, find_item.size);
result.match_to_end_of_buffer = Dqn_String8_Init(result.match.data, string.size - index);
break;
}
}
}
return result;
}
DQN_API Dqn_String8FindResult Dqn_String8_FindFirstString(Dqn_String8 string, Dqn_String8 find)
{
Dqn_String8FindResult result = Dqn_String8_FindFirstStringArray(string, &find, 1);
return result;
}
DQN_API Dqn_String8FindResult Dqn_String8_FindFirst(Dqn_String8 string, uint32_t flags)
{
Dqn_String8FindResult result = {};
for (size_t index = 0; !result.found && index < string.size; index++) {
result.found |= ((flags & Dqn_String8FindFlag_Digit) && Dqn_Char_IsDigit(string.data[index]));
result.found |= ((flags & Dqn_String8FindFlag_Alphabet) && Dqn_Char_IsAlphabet(string.data[index]));
result.found |= ((flags & Dqn_String8FindFlag_Whitespace) && Dqn_Char_IsWhitespace(string.data[index]));
result.found |= ((flags & Dqn_String8FindFlag_Plus) && string.data[index] == '+');
result.found |= ((flags & Dqn_String8FindFlag_Minus) && string.data[index] == '-');
if (result.found) {
result.index = index;
result.match = Dqn_String8_Init(string.data + index, 1);
result.match_to_end_of_buffer = Dqn_String8_Init(result.match.data, string.size - index);
}
}
return result;
}
DQN_API Dqn_String8 Dqn_String8_Segment(Dqn_Allocator allocator, Dqn_String8 src, Dqn_usize segment_size, char segment_char) DQN_API Dqn_String8 Dqn_String8_Segment(Dqn_Allocator allocator, Dqn_String8 src, Dqn_usize segment_size, char segment_char)
{ {
Dqn_usize result_size = src.size; Dqn_usize result_size = src.size;
@ -5380,6 +5428,7 @@ DQN_API Dqn_String8 Dqn_String8_Segment(Dqn_Allocator allocator, Dqn_String8 src
return result; return result;
} }
DQN_API bool Dqn_String8_Eq(Dqn_String8 lhs, Dqn_String8 rhs, Dqn_String8EqCase eq_case) DQN_API bool Dqn_String8_Eq(Dqn_String8 lhs, Dqn_String8 rhs, Dqn_String8EqCase eq_case)
{ {
if (lhs.size != rhs.size) if (lhs.size != rhs.size)
@ -5615,25 +5664,6 @@ DQN_API int64_t Dqn_String8_ToI64(Dqn_String8 string, char separator)
return result; return result;
} }
DQN_API Dqn_String8FindResult Dqn_String8_Find(Dqn_String8 string, Dqn_String8 find, Dqn_usize offset, Dqn_String8EqCase eq_case)
{
Dqn_String8FindResult result = {};
if (!Dqn_String8_IsValid(string) || !Dqn_String8_IsValid(find) || find.size > string.size)
return result;
Dqn_usize start_index = DQN_MIN(offset, string.size);
Dqn_usize end = string.size - find.size + 1;
for (Dqn_usize index = start_index; !result.found && index < end; index++) {
Dqn_String8 check = Dqn_String8_Slice(string, index, find.size);
if (Dqn_String8_Eq(check, find, eq_case)) {
result.found = true;
result.offset = index;
result.string = check;
}
}
return result;
}
DQN_API Dqn_String8 Dqn_String8_Replace(Dqn_String8 string, DQN_API Dqn_String8 Dqn_String8_Replace(Dqn_String8 string,
Dqn_String8 find, Dqn_String8 find,
Dqn_String8 replace, Dqn_String8 replace,
@ -7525,7 +7555,7 @@ DQN_API uint64_t Dqn_Safe_SaturateCastIntToU64(int val)
// ================================================================================================= // =================================================================================================
// [$CHAR] Dqn_Char | | Character ascii/digit.. helpers // [$CHAR] Dqn_Char | | Character ascii/digit.. helpers
// ================================================================================================= // =================================================================================================
DQN_API bool Dqn_Char_IsAlpha(char ch) DQN_API bool Dqn_Char_IsAlphabet(char ch)
{ {
bool result = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); bool result = (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
return result; return result;
@ -7539,7 +7569,7 @@ DQN_API bool Dqn_Char_IsDigit(char ch)
DQN_API bool Dqn_Char_IsAlphaNum(char ch) DQN_API bool Dqn_Char_IsAlphaNum(char ch)
{ {
bool result = Dqn_Char_IsAlpha(ch) || Dqn_Char_IsDigit(ch); bool result = Dqn_Char_IsAlphabet(ch) || Dqn_Char_IsDigit(ch);
return result; return result;
} }
@ -8551,8 +8581,10 @@ DQN_API Dqn_WinNetHandleResponse Dqn_Win_NetHandleSendRequest(Dqn_WinNetHandle *
bool found_content_length = false; bool found_content_length = false;
for (Dqn_usize header_index = 0; header_index < result.headers_size; header_index++) { for (Dqn_usize header_index = 0; header_index < result.headers_size; header_index++) {
Dqn_String8 header = result.headers[header_index]; Dqn_String8 header = result.headers[header_index];
Dqn_String8 value = {};
Dqn_String8 key = Dqn_String8_BinarySplit(header, ':', &value); Dqn_String8BinarySplitResult key_value_split = Dqn_String8_BinarySplit(header, DQN_STRING8(":"));
Dqn_String8 value = key_value_split.lhs;
Dqn_String8 key = key_value_split.rhs;
key = Dqn_String8_TrimWhitespaceAround(key); key = Dqn_String8_TrimWhitespaceAround(key);
value = Dqn_String8_TrimWhitespaceAround(value); value = Dqn_String8_TrimWhitespaceAround(value);
@ -9676,19 +9708,21 @@ DQN_API bool Dqn_FsPath_AddRef(Dqn_Arena *arena, Dqn_FsPath *fs_path, Dqn_String
if (path.size <= 0) if (path.size <= 0)
return true; return true;
Dqn_String8 delimiter_chars = DQN_STRING8("/\\"); Dqn_String8 const delimiter_array[] = {
DQN_STRING8("\\"),
DQN_STRING8("/")
};
for (;;) { for (;;) {
Dqn_String8 rhs = {}; Dqn_String8BinarySplitResult delimiter = Dqn_String8_BinarySplitArray(path, delimiter_array, DQN_ARRAY_UCOUNT(delimiter_array));
Dqn_String8 lhs = Dqn_String8_BinarySplitStringChars(path, delimiter_chars, &rhs); for (; delimiter.lhs.data; delimiter = Dqn_String8_BinarySplitArray(delimiter.rhs, delimiter_array, DQN_ARRAY_UCOUNT(delimiter_array))) {
for (; lhs.data; lhs = Dqn_String8_BinarySplitStringChars(rhs, delimiter_chars, &rhs)) { if (delimiter.lhs.size <= 0)
if (lhs.size <= 0)
continue; continue;
Dqn_FsPathLink *link = Dqn_Arena_New(arena, Dqn_FsPathLink, Dqn_ZeroMem_Yes); Dqn_FsPathLink *link = Dqn_Arena_New(arena, Dqn_FsPathLink, Dqn_ZeroMem_Yes);
if (!link) if (!link)
return false; return false;
link->string = lhs; link->string = delimiter.lhs;
link->prev = fs_path->tail; link->prev = fs_path->tail;
if (fs_path->tail) { if (fs_path->tail) {
fs_path->tail->next = link; fs_path->tail->next = link;
@ -9697,10 +9731,10 @@ DQN_API bool Dqn_FsPath_AddRef(Dqn_Arena *arena, Dqn_FsPath *fs_path, Dqn_String
} }
fs_path->tail = link; fs_path->tail = link;
fs_path->links_size += 1; fs_path->links_size += 1;
fs_path->string_size += lhs.size; fs_path->string_size += delimiter.lhs.size;
} }
if (!lhs.data) if (!delimiter.lhs.data)
break; break;
} }

View File

@ -1377,32 +1377,39 @@ Dqn_UTest TestString8()
// NOTE: Dqn_String8_BinarySplit // NOTE: Dqn_String8_BinarySplit
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
{ {
char const *TEST_FMT = "Dqn_String8_BinarySplit \"%s\" with 'c'"; {
char const *TEST_FMT = "Binary split \"%.*s\" with \"%.*s\"";
Dqn_String8 delimiter = DQN_STRING8("/");
Dqn_String8 input = DQN_STRING8("abcdef");
DQN_UTEST_TEST(TEST_FMT, DQN_STRING_FMT(input), DQN_STRING_FMT(delimiter)) {
Dqn_String8BinarySplitResult split = Dqn_String8_BinarySplit(input, delimiter);
DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(split.lhs, DQN_STRING8("abcdef")), "[lhs=%.*s]", DQN_STRING_FMT(split.lhs));
DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(split.rhs, DQN_STRING8("")), "[rhs=%.*s]", DQN_STRING_FMT(split.rhs));
}
char delimiter = '/'; input = DQN_STRING8("abc/def");
Dqn_String8 input = DQN_STRING8("abcdef"); DQN_UTEST_TEST(TEST_FMT, DQN_STRING_FMT(input), DQN_STRING_FMT(delimiter)) {
DQN_UTEST_TEST(TEST_FMT, input.data, delimiter) { Dqn_String8BinarySplitResult split = Dqn_String8_BinarySplit(input, delimiter);
Dqn_String8 rhs = {}; DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(split.lhs, DQN_STRING8("abc")), "[lhs=%.*s]", DQN_STRING_FMT(split.lhs));
Dqn_String8 lhs = Dqn_String8_BinarySplit(input, delimiter, &rhs); DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(split.rhs, DQN_STRING8("def")), "[rhs=%.*s]", DQN_STRING_FMT(split.rhs));
}
DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("abcdef")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); input = DQN_STRING8("/abcdef");
DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); DQN_UTEST_TEST(TEST_FMT, DQN_STRING_FMT(input), DQN_STRING_FMT(delimiter)) {
Dqn_String8BinarySplitResult split = Dqn_String8_BinarySplit(input, delimiter);
DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(split.lhs, DQN_STRING8("")), "[lhs=%.*s]", DQN_STRING_FMT(split.lhs));
DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(split.rhs, DQN_STRING8("abcdef")), "[rhs=%.*s]", DQN_STRING_FMT(split.rhs));
}
} }
input = DQN_STRING8("abc/def"); {
DQN_UTEST_TEST(TEST_FMT, input.data, delimiter) { Dqn_String8 delimiter = DQN_STRING8("-=-");
Dqn_String8 rhs = {}; Dqn_String8 input = DQN_STRING8("123-=-456");
Dqn_String8 lhs = Dqn_String8_BinarySplit(input, delimiter, &rhs); DQN_UTEST_TEST("Binary split \"%.*s\" with \"%.*s\"", DQN_STRING_FMT(input), DQN_STRING_FMT(delimiter)) {
DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("abc")), "[lhs=%.*s]", DQN_STRING_FMT(lhs)); Dqn_String8BinarySplitResult split = Dqn_String8_BinarySplit(input, delimiter);
DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("def")), "[rhs=%.*s]", DQN_STRING_FMT(rhs)); DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(split.lhs, DQN_STRING8("123")), "[lhs=%.*s]", DQN_STRING_FMT(split.lhs));
} DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(split.rhs, DQN_STRING8("456")), "[rhs=%.*s]", DQN_STRING_FMT(split.rhs));
}
input = DQN_STRING8("/abcdef");
DQN_UTEST_TEST(TEST_FMT, input.data, delimiter) {
Dqn_String8 rhs = {};
Dqn_String8 lhs = Dqn_String8_BinarySplit(input, delimiter, &rhs);
DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(lhs, DQN_STRING8("")), "[lhs=%.*s]", DQN_STRING_FMT(lhs));
DQN_UTEST_ASSERTF(&test, Dqn_String8_Eq(rhs, DQN_STRING8("abcdef")), "[rhs=%.*s]", DQN_STRING_FMT(rhs));
} }
} }
@ -1505,20 +1512,20 @@ Dqn_UTest TestString8()
DQN_UTEST_TEST("Find: String (char) is not in buffer") { DQN_UTEST_TEST("Find: String (char) is not in buffer") {
Dqn_String8 buf = DQN_STRING8("836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"); Dqn_String8 buf = DQN_STRING8("836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55");
Dqn_String8 find = DQN_STRING8("2"); Dqn_String8 find = DQN_STRING8("2");
Dqn_String8FindResult result = Dqn_String8_Find(buf, find, 0); Dqn_String8FindResult result = Dqn_String8_FindFirstString(buf, find);
DQN_UTEST_ASSERT(&test, !result.found); DQN_UTEST_ASSERT(&test, !result.found);
DQN_UTEST_ASSERT(&test, result.offset == 0); DQN_UTEST_ASSERT(&test, result.index == 0);
DQN_UTEST_ASSERT(&test, result.string.data == nullptr); DQN_UTEST_ASSERT(&test, result.match.data == nullptr);
DQN_UTEST_ASSERT(&test, result.string.size == 0); DQN_UTEST_ASSERT(&test, result.match.size == 0);
} }
DQN_UTEST_TEST("Find: String (char) is in buffer") { DQN_UTEST_TEST("Find: String (char) is in buffer") {
Dqn_String8 buf = DQN_STRING8("836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55"); Dqn_String8 buf = DQN_STRING8("836a35becd4e74b66a0d6844d51f1a63018c7ebc44cf7e109e8e4bba57eefb55");
Dqn_String8 find = DQN_STRING8("6"); Dqn_String8 find = DQN_STRING8("6");
Dqn_String8FindResult result = Dqn_String8_Find(buf, find, 0); Dqn_String8FindResult result = Dqn_String8_FindFirstString(buf, find);
DQN_UTEST_ASSERT(&test, result.found); DQN_UTEST_ASSERT(&test, result.found);
DQN_UTEST_ASSERT(&test, result.offset == 2); DQN_UTEST_ASSERT(&test, result.index == 2);
DQN_UTEST_ASSERT(&test, result.string.data[0] == '6'); DQN_UTEST_ASSERT(&test, result.match.data[0] == '6');
} }
// NOTE: Dqn_String8_FileNameFromPath // NOTE: Dqn_String8_FileNameFromPath