Add slices, make returned bufs are null terminated

This commit is contained in:
Doyle Thai 2018-02-07 16:39:40 +11:00
parent b0217483db
commit 7f2950b3dd

112
dqn.h
View File

@ -34,6 +34,7 @@
// #DqnMemAPI Custom memory API for Dqn Data Structures // #DqnMemAPI Custom memory API for Dqn Data Structures
// #DqnArray Dynamic Array using Templates // #DqnArray Dynamic Array using Templates
// #DqnMemStack Memory Allocator, Push, Pop Style // #DqnMemStack Memory Allocator, Push, Pop Style
// #DqnSlice Slices
// #DqnHash Hashing using Murmur // #DqnHash Hashing using Murmur
// #DqnMath Simple Math Helpers (Lerp etc.) // #DqnMath Simple Math Helpers (Lerp etc.)
// #DqnV2 2D Math Vectors // #DqnV2 2D Math Vectors
@ -138,6 +139,8 @@ using f32 = float;
#define DQN_MEGABYTE(val) (DQN_KILOBYTE(val) * 1024LL) #define DQN_MEGABYTE(val) (DQN_KILOBYTE(val) * 1024LL)
#define DQN_KILOBYTE(val) ((val) * 1024LL) #define DQN_KILOBYTE(val) ((val) * 1024LL)
#define DQN_MINUTE(val) ((val) * 60LL)
#define DQN_ALIGN_POW_N(val, align) ((((usize)val) + ((usize)align-1)) & (~(usize)(align-1))) #define DQN_ALIGN_POW_N(val, align) ((((usize)val) + ((usize)align-1)) & (~(usize)(align-1)))
#define DQN_ALIGN_POW_4(val) DQN_ALIGN_POW_N(val, 4) #define DQN_ALIGN_POW_4(val) DQN_ALIGN_POW_N(val, 4)
@ -857,6 +860,15 @@ void DqnArray<T>::RemoveStable(isize *indexList, isize numIndexes)
} }
} }
// #DqnSlice API
// =================================================================================================
template <typename T>
struct DqnSlice
{
T *data;
i32 len;
};
// #DqnHash API // #DqnHash API
// ================================================================================================= // =================================================================================================
DQN_FILE_SCOPE u32 DqnHash_Murmur32Seed(void const *data, usize len, u32 seed); DQN_FILE_SCOPE u32 DqnHash_Murmur32Seed(void const *data, usize len, u32 seed);
@ -1796,6 +1808,13 @@ DQN_FILE_SCOPE DqnRndPCG DqnRndPCG_(u32 seed);
// #Dqn_ API // #Dqn_ API
// ================================================================================================= // =================================================================================================
// return: The number of splits in the array. If array is null this returns the required size of the array.
i32 Dqn_SplitString(char const *src, i32 srcLen, char splitChar, DqnSlice<char> *array = nullptr, i32 size = 0);
// Util function that uses Dqn_SplitString
// return: The number of splits, splitting by "splitChar" would generate.
i32 Dqn_GetNumSplits(char const *src, i32 srcLen, char splitChar);
inline bool Dqn_BitIsSet(u32 const bits, u32 const flag) inline bool Dqn_BitIsSet(u32 const bits, u32 const flag)
{ {
bool result = ((bits & flag) == flag); bool result = ((bits & flag) == flag);
@ -2123,12 +2142,13 @@ struct DqnFile
// Static API // Static API
// ============================================================================================== // ==============================================================================================
// Read entire file into the given buffer. To determine required bufSize size, use GetFileSize. // Read entire file into the given buffer. To determine required bufSize size, use GetFileSize.
// NOTE: You want size + 1 and add the null-terminator yourself if you want a null terminated buffer.
// bytesRead: Pass in to get how many bytes of the buf was used. Basically the return value of Read // bytesRead: Pass in to get how many bytes of the buf was used. Basically the return value of Read
// return: False if insufficient bufSize OR file access failure OR nullptr arguments. // return: False if insufficient bufSize OR file access failure OR nullptr arguments.
static bool ReadEntireFile(char const *const path, u8 *const buf, usize const bufSize, usize *const bytesRead); static bool ReadEntireFile(char const *const path, u8 *const buf, usize const bufSize, usize *const bytesRead);
static bool ReadEntireFile(wchar_t const *const path, u8 *const buf, usize const bufSize, usize *const bytesRead); static bool ReadEntireFile(wchar_t const *const path, u8 *const buf, usize const bufSize, usize *const bytesRead);
// Buffer should be freed when done with. // Buffer is null-terminated and should be freed when done with.
// return: False if file access failure OR nullptr arguments. // return: False if file access failure OR nullptr arguments.
static u8 *ReadEntireFile(char const *const path, usize *const bufSize, DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); static u8 *ReadEntireFile(char const *const path, usize *const bufSize, DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR);
static u8 *ReadEntireFile(wchar_t const *const path, usize *const bufSize, DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); static u8 *ReadEntireFile(wchar_t const *const path, usize *const bufSize, DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR);
@ -3010,6 +3030,7 @@ DQN_FILE_SCOPE void *DqnMem_Set64(void *const dest, u8 const value, i64 const nu
usize const numU8ToCopy = numBytesToCopy & (remainingMask); usize const numU8ToCopy = numBytesToCopy & (remainingMask);
__stosb(destU8, valueU8, numU8ToCopy); __stosb(destU8, valueU8, numU8ToCopy);
#else #else
(void)dest; (void)value; (void)numBytesToCopy;
DQN_ASSERT(DQN_INVALID_CODE_PATH) DQN_ASSERT(DQN_INVALID_CODE_PATH)
#endif #endif
return dest; return dest;
@ -5087,7 +5108,7 @@ DQN_FILE_SCOPE char *DqnChar_GetNextLine (char *ptr, i32 *lineLength)
// #DqnStr Implementation // #DqnStr Implementation
// ================================================================================================= // =================================================================================================
DQN_FILE_SCOPE i32 DqnStr_Cmp(const char *const a, const char *const b, i32 numBytesToCompare, bool ignoreCase) DQN_FILE_SCOPE i32 DqnStr_Cmp(char const *a, char const *b, i32 numBytesToCompare, bool ignoreCase)
{ {
if (!a && !b) return -1; if (!a && !b) return -1;
if (!a) return -1; if (!a) return -1;
@ -5095,35 +5116,22 @@ DQN_FILE_SCOPE i32 DqnStr_Cmp(const char *const a, const char *const b, i32 numB
if (numBytesToCompare == 0) return -1; if (numBytesToCompare == 0) return -1;
i32 bytesCompared = 0; i32 bytesCompared = 0;
char const *aPtr = a;
char const *bPtr = b;
if (ignoreCase) if (ignoreCase)
{ {
while (DqnChar_ToLower((*aPtr)) == DqnChar_ToLower((*bPtr))) while (a[0] && DqnChar_ToLower((*a++)) == DqnChar_ToLower((*b++)))
{ {
if (!(*aPtr)) return 0; if (++bytesCompared == numBytesToCompare) return 0;
bytesCompared++;
aPtr++;
bPtr++;
if (bytesCompared == numBytesToCompare) return 0;
} }
} }
else else
{ {
while ((*aPtr) == (*bPtr)) while (a[0] && (*a++) == (*b++))
{ {
if (!(*aPtr)) return 0; if (++bytesCompared == numBytesToCompare) return 0;
bytesCompared++;
aPtr++;
bPtr++;
if (bytesCompared == numBytesToCompare) return 0;
} }
} }
return (((*aPtr) < (*bPtr)) ? -1 : 1); return (*a - *b);
} }
DQN_FILE_SCOPE char *DqnStr_GetPtrToLastSlash(char const *str, i32 strLen) DQN_FILE_SCOPE char *DqnStr_GetPtrToLastSlash(char const *str, i32 strLen)
@ -5318,7 +5326,12 @@ DQN_FILE_SCOPE i32 Dqn_I64ToStr(i64 const value, char *const buf, i32 const bufS
if (value == 0) if (value == 0)
{ {
if (validBuffer) buf[0] = '0'; if (validBuffer)
{
buf[0] = '0';
buf[1] = 0;
}
return 1; return 1;
} }
@ -5381,6 +5394,7 @@ DQN_FILE_SCOPE i32 Dqn_I64ToStr(i64 const value, char *const buf, i32 const bufS
} }
} }
buf[charIndex] = 0;
return charIndex; return charIndex;
} }
@ -6069,6 +6083,7 @@ bool DqnString::InitLiteral(wchar_t const *const cstr, DqnMemAPI *const api)
return true; return true;
#else #else
(void)cstr; (void)api;
DQN_ASSERT(DQN_INVALID_CODE_PATH); DQN_ASSERT(DQN_INVALID_CODE_PATH);
return false; return false;
@ -6286,6 +6301,7 @@ i32 DqnString::ToWChar(wchar_t *const buf, i32 const bufSize) const
return result; return result;
#else #else
(void)buf; (void)bufSize;
DQN_ASSERT(DQN_INVALID_CODE_PATH); DQN_ASSERT(DQN_INVALID_CODE_PATH);
return -1; return -1;
#endif #endif
@ -6308,6 +6324,7 @@ wchar_t *DqnString::ToWChar(DqnMemAPI *const api) const
return result; return result;
#else #else
(void)api;
DQN_ASSERT(DQN_INVALID_CODE_PATH); DQN_ASSERT(DQN_INVALID_CODE_PATH);
return nullptr; return nullptr;
@ -6425,6 +6442,56 @@ i32 DqnRndPCG::Range(i32 min, i32 max)
// #Dqn // #Dqn
// ================================================================================================= // =================================================================================================
i32 Dqn_GetNumSplits(char const *src, i32 srcLen, char splitChar)
{
auto result = Dqn_SplitString(src, srcLen, splitChar, nullptr, 0);
return result;
}
i32 Dqn_SplitString(char const *src, i32 srcLen, char splitChar, DqnSlice<char> *array, i32 size)
{
// TODO(doyle): Const correctness
i32 sliceLen = 0;
i32 arrayIndex = 0;
for (auto i = 0; i < srcLen; i++)
{
char *c = (char *)(src + i);
if (*c == splitChar)
{
DqnSlice<char> slice = {c - sliceLen, sliceLen};
if (array)
{
if (arrayIndex < size)
{
array[arrayIndex] = slice;
}
}
arrayIndex++;
sliceLen = 0;
}
else
{
sliceLen++;
}
}
DqnSlice<char> lastSlice = {(char *)src + srcLen - sliceLen, sliceLen};
if (lastSlice.len > 0)
{
if (array)
{
if (arrayIndex < size)
{
array[arrayIndex] = lastSlice;
}
}
arrayIndex++;
}
return arrayIndex;
}
DQN_FILE_SCOPE i64 Dqn_BSearch(i64 *const array, i64 const size, i64 const find, DQN_FILE_SCOPE i64 Dqn_BSearch(i64 *const array, i64 const size, i64 const find,
Dqn_BSearchBound const bound) Dqn_BSearchBound const bound)
{ {
@ -8669,8 +8736,7 @@ cleanup:
return result; return result;
} }
bool DqnFile::ReadEntireFile(const char *const path, u8 *const buf, usize const bufSize, bool DqnFile::ReadEntireFile(const char *const path, u8 *const buf, usize const bufSize, usize *const bytesRead)
usize *const bytesRead)
{ {
if (!path || !buf || !bytesRead) return false; if (!path || !buf || !bytesRead) return false;