Add strutil getlastbackslash

This commit is contained in:
Doyle Thai 2018-01-29 19:03:20 +11:00
parent 06b0f25f2a
commit f838cc79bf
2 changed files with 59 additions and 50 deletions

85
dqn.h
View File

@ -482,16 +482,17 @@ public:
bool Sprintf (char const *const fmt, ...); bool Sprintf (char const *const fmt, ...);
bool VSprintf(char const *const fmt, va_list argList); bool VSprintf(char const *const fmt, va_list argList);
bool Append (DqnString const string); bool Append (DqnString const string);
bool Append (DqnString const *string);
bool Append (char const *const cstr, i32 bytesToCopy = -1); bool Append (char const *const cstr, i32 bytesToCopy = -1);
void Clear (); void Clear ();
void Free (); void Free ();
// return: -1 if invalid, or if bufSize is 0 the required buffer length in wchar_t characters // return: -1 if invalid, or if bufSize is 0 the required buffer length in wchar_t characters
i32 ToWChar(wchar_t *const buf, i32 const bufSize); i32 ToWChar(wchar_t *const buf, i32 const bufSize) const;
// return: String allocated using api. // return: String allocated using api.
wchar_t *ToWChar(DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); wchar_t *ToWChar(DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR) const;
}; };
class DqnSmartString : public DqnString class DqnSmartString : public DqnString
@ -1671,6 +1672,10 @@ DQN_FILE_SCOPE char *DqnChar_GetNextLine (char *ptr, i32 *lineLength);
// return: 0 if equal. 0 < if a is before b, > 0 if a is after b // return: 0 if equal. 0 < if a is before b, > 0 if a is after b
DQN_FILE_SCOPE i32 DqnStr_Cmp (char const *const a, char const *const b, i32 numBytesToCompare = -1, bool ignoreCase = false); DQN_FILE_SCOPE i32 DqnStr_Cmp (char const *const a, char const *const b, i32 numBytesToCompare = -1, bool ignoreCase = false);
// strLen: Len of string, if -1, StrLen is used.
// return: Pointer in str to the last slash, if none then the original string.
DQN_FILE_SCOPE char *DqnStr_GetPtrToLastSlash (char const *str, i32 strLen = -1);
// return: String length not including the nullptr terminator. 0 if invalid args. // return: String length not including the nullptr terminator. 0 if invalid args.
DQN_FILE_SCOPE i32 DqnStr_Len (char const *const a); DQN_FILE_SCOPE i32 DqnStr_Len (char const *const a);
DQN_FILE_SCOPE i32 DqnStr_LenUTF8 (u32 const *const a, i32 *const lenInBytes = nullptr); DQN_FILE_SCOPE i32 DqnStr_LenUTF8 (u32 const *const a, i32 *const lenInBytes = nullptr);
@ -2050,14 +2055,6 @@ struct DqnFile
void *handle; void *handle;
size_t size; size_t size;
// Initialisation API
// ==============================================================================================
// If raiiCleanup is true, close() is called in the destructor on scope exit. Can be changed at
// any point by user.
bool raiiCleanup = false;
DqnFile (bool const raiiCleanup = false);
~DqnFile();
// API // API
// ============================================================================================== // ==============================================================================================
// NOTE: W(ide) versions of functions only work on Win32, since Unix is already UTF-8 compatible. // NOTE: W(ide) versions of functions only work on Win32, since Unix is already UTF-8 compatible.
@ -2065,7 +2062,7 @@ struct DqnFile
// Open a handle for file read and writing. Deleting files does not need a handle. Handles should be // Open a handle for file read and writing. Deleting files does not need a handle. Handles should be
// closed before deleting files otherwise the OS may not be able to delete the file. // closed before deleting files otherwise the OS may not be able to delete the file.
// return: FALSE if invalid args or failed to get handle (i.e. insufficient permissions) // return: FALSE if invalid args or failed to get handle (i.e. insufficient permissions)
bool Open (const char *const path, u32 const flags_, Action const action); bool Open(const char *const path, u32 const flags_, Action const action);
bool Open(const wchar_t *const path, u32 const flags_, Action const action); bool Open(const wchar_t *const path, u32 const flags_, Action const action);
// fileOffset: The byte offset to starting writing from. // fileOffset: The byte offset to starting writing from.
@ -2083,13 +2080,13 @@ struct DqnFile
// 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.
// 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, size_t const bufSize, size_t *const bytesRead); static bool ReadEntireFile(char const *const path, u8 *const buf, size_t const bufSize, size_t *const bytesRead);
static bool ReadEntireFile (wchar_t const *const path, u8 *const buf, size_t const bufSize, size_t *const bytesRead); static bool ReadEntireFile(wchar_t const *const path, u8 *const buf, size_t const bufSize, size_t *const bytesRead);
// Buffer should be freed when done with. // Buffer 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 *ReadEntireFileSimple(char const *const path, size_t *const bufSize, DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); static u8 *ReadEntireFile(char const *const path, size_t *const bufSize, DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR);
static u8 *ReadEntireFileSimple(wchar_t const *const path, size_t *const bufSize, DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); static u8 *ReadEntireFile(wchar_t const *const path, size_t *const bufSize, DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR);
// return: False if file access failure OR nullptr arguments. // return: False if file access failure OR nullptr arguments.
static bool GetFileSize (char const *const path, size_t *const size); static bool GetFileSize (char const *const path, size_t *const size);
@ -2114,6 +2111,12 @@ struct DqnFile
static void ListDirFree (char **fileList, i32 const numFiles); static void ListDirFree (char **fileList, i32 const numFiles);
}; };
class DqnSmartFile : public DqnFile
{
public:
~DqnSmartFile() { this->Close(); }
};
// XPlatform > #DqnTimer API // XPlatform > #DqnTimer API
// ================================================================================================= // =================================================================================================
DQN_FILE_SCOPE f64 DqnTimer_NowInMs(); DQN_FILE_SCOPE f64 DqnTimer_NowInMs();
@ -4553,7 +4556,7 @@ DQN_FILE_SCOPE char *DqnChar_TrimWhitespaceAround(char const *src, i32 srcLen, i
i32 charsSkipped = (i32)(start - src); i32 charsSkipped = (i32)(start - src);
i32 updatedLen = srcLen - charsSkipped; i32 updatedLen = srcLen - charsSkipped;
if (updatedLen == 0) if (updatedLen <= 0)
{ {
if (newLen) *newLen = 0; if (newLen) *newLen = 0;
return nullptr; return nullptr;
@ -4694,6 +4697,22 @@ DQN_FILE_SCOPE i32 DqnStr_Cmp(const char *const a, const char *const b, i32 numB
return (((*aPtr) < (*bPtr)) ? -1 : 1); return (((*aPtr) < (*bPtr)) ? -1 : 1);
} }
DQN_FILE_SCOPE char *DqnStr_GetPtrToLastSlash(char const *str, i32 strLen)
{
char const *result = str;
if (strLen == -1) strLen = DqnStr_Len(str);
for (auto i = strLen - 1; i >= 0; i--)
{
if (result[i] == '\\' || result[i] == '/')
{
result = result + i + 1;
break;
}
}
return (char *)result;
}
DQN_FILE_SCOPE i32 DqnStr_Len(const char *const a) DQN_FILE_SCOPE i32 DqnStr_Len(const char *const a)
{ {
i32 result = 0; i32 result = 0;
@ -5778,6 +5797,12 @@ bool DqnString::Append(DqnString const string)
return result; return result;
} }
bool DqnString::Append(DqnString const *string)
{
bool result = DqnStringInternal_Append(this, string->str, string->len);
return result;
}
void DqnString::Clear() void DqnString::Clear()
{ {
this->len = 0; this->len = 0;
@ -5810,7 +5835,7 @@ void DqnString::Free()
} }
} }
i32 DqnString::ToWChar(wchar_t *const buf, i32 const bufSize) i32 DqnString::ToWChar(wchar_t *const buf, i32 const bufSize) const
{ {
#if defined(DQN_IS_WIN32) && defined(DQN_WIN32_IMPLEMENTATION) #if defined(DQN_IS_WIN32) && defined(DQN_WIN32_IMPLEMENTATION)
i32 result = DqnWin32_UTF8ToWChar(this->str, buf, bufSize); i32 result = DqnWin32_UTF8ToWChar(this->str, buf, bufSize);
@ -5822,7 +5847,7 @@ i32 DqnString::ToWChar(wchar_t *const buf, i32 const bufSize)
#endif #endif
} }
wchar_t *DqnString::ToWChar(DqnMemAPI *const api) wchar_t *DqnString::ToWChar(DqnMemAPI *const api) const
{ {
// TODO(doyle): Should the "in" string allow specifyign len? probably // TODO(doyle): Should the "in" string allow specifyign len? probably
// Otherwise a c-string and a literal initiated string might have different lengths // Otherwise a c-string and a literal initiated string might have different lengths
@ -8029,22 +8054,6 @@ DQN_FILE_SCOPE char **DqnFileInternal_PlatformListDir(char const *const dir, u32
} }
#endif // DQN_UNIX_PLATFORM #endif // DQN_UNIX_PLATFORM
DqnFile::DqnFile(bool const raiiCleanup)
: flags(0)
, handle(nullptr)
, size(0)
, raiiCleanup(raiiCleanup)
{
}
DqnFile::~DqnFile()
{
if (raiiCleanup)
{
this->Close();
}
}
bool DqnFile::Open(char const *const path, u32 const flags_, Action const action) bool DqnFile::Open(char const *const path, u32 const flags_, Action const action)
{ {
if (!path) return false; if (!path) return false;
@ -8146,13 +8155,13 @@ size_t DqnFile::Read(u8 *const buf, size_t const numBytesToRead)
return numBytesRead; return numBytesRead;
} }
u8 *DqnFile::ReadEntireFileSimple(wchar_t const *const path, size_t *const bufSize, DqnMemAPI *const api) u8 *DqnFile::ReadEntireFile(wchar_t const *const path, size_t *const bufSize, DqnMemAPI *const api)
{ {
// TODO(doyle): Logging // TODO(doyle): Logging
if (!path || !bufSize) return false; if (!path || !bufSize) return false;
size_t requiredSize = 0; size_t requiredSize = 0;
if (!DqnFile::GetFileSize(path, &requiredSize)) return nullptr; if (!DqnFile::GetFileSize(path, &requiredSize) || requiredSize == 0) return nullptr;
auto *buf = (u8 *)api->Alloc(requiredSize, /*zeroClear*/ false); auto *buf = (u8 *)api->Alloc(requiredSize, /*zeroClear*/ false);
if (!buf) return nullptr; if (!buf) return nullptr;
@ -8169,12 +8178,12 @@ u8 *DqnFile::ReadEntireFileSimple(wchar_t const *const path, size_t *const bufSi
return nullptr; return nullptr;
} }
u8 *DqnFile::ReadEntireFileSimple(char const *const path, size_t *const bufSize, DqnMemAPI *const api) u8 *DqnFile::ReadEntireFile(char const *const path, size_t *const bufSize, DqnMemAPI *const api)
{ {
// TODO(doyle): Logging // TODO(doyle): Logging
size_t requiredSize = 0; size_t requiredSize = 0;
if (!DqnFile::GetFileSize(path, &requiredSize)) return nullptr; if (!DqnFile::GetFileSize(path, &requiredSize) || requiredSize == 0) return nullptr;
auto *buf = (u8 *)api->Alloc(requiredSize, /*zeroClear*/ false); auto *buf = (u8 *)api->Alloc(requiredSize, /*zeroClear*/ false);
if (!buf) return nullptr; if (!buf) return nullptr;

View File

@ -1462,7 +1462,7 @@ void DqnArray_TestRealDataInternal(DqnArray<char> *array)
{ {
#ifdef DQN_XPLATFORM_LAYER #ifdef DQN_XPLATFORM_LAYER
size_t bufSize = 0; size_t bufSize = 0;
u8 *buf = DqnFile::ReadEntireFileSimple("tests/google-10000-english.txt", &bufSize); u8 *buf = DqnFile::ReadEntireFile("tests/google-10000-english.txt", &bufSize);
DQN_ASSERT(buf); DQN_ASSERT(buf);
for (auto i = 0; i < bufSize; i++) for (auto i = 0; i < bufSize; i++)
@ -2007,7 +2007,7 @@ void DqnFile_Test()
if (1) if (1)
{ {
DqnFile raiiFile = DqnFile(true); DqnSmartFile raiiFile = {};
if (raiiFile.Open(FILE_TO_OPEN, if (raiiFile.Open(FILE_TO_OPEN,
DqnFile::PermissionFlag::FileWrite | DqnFile::PermissionFlag::FileRead, DqnFile::PermissionFlag::FileWrite | DqnFile::PermissionFlag::FileRead,
DqnFile::Action::OpenOnly)) DqnFile::Action::OpenOnly))