Minor fixes, add trim whitespace
This commit is contained in:
		
							parent
							
								
									7809185daa
								
							
						
					
					
						commit
						db25c5997f
					
				
							
								
								
									
										246
									
								
								dqn.h
									
									
									
									
									
								
							
							
						
						
									
										246
									
								
								dqn.h
									
									
									
									
									
								
							| @ -9,7 +9,7 @@ | |||||||
| 
 | 
 | ||||||
| 	// NOTE: For platform code, it's one or the other or you will get compilation problems.
 | 	// NOTE: For platform code, it's one or the other or you will get compilation problems.
 | ||||||
| 	// Define this in ONE and only ONE file to enable the implementation of platform code.
 | 	// Define this in ONE and only ONE file to enable the implementation of platform code.
 | ||||||
| 	// On Win32 you must link against user32.lib
 | 	// On Win32 you must link against user32.lib and kernel32.lib
 | ||||||
| 	#define DQN_WIN32_IMPLEMENTATION // Enable Win32 Code, but only if _WIN32 or _WIN64 is already defined. Also requires DQN_IMPLEMENTATION.
 | 	#define DQN_WIN32_IMPLEMENTATION // Enable Win32 Code, but only if _WIN32 or _WIN64 is already defined. Also requires DQN_IMPLEMENTATION.
 | ||||||
| 	#define DQN_UNIX_IMPLEMENTATION  // Enable Unix Code, but only if __linux__ is already defined. Also requires DQN_IMPLEMENTATION.
 | 	#define DQN_UNIX_IMPLEMENTATION  // Enable Unix Code, but only if __linux__ is already defined. Also requires DQN_IMPLEMENTATION.
 | ||||||
| 
 | 
 | ||||||
| @ -385,11 +385,13 @@ struct DqnMemStack | |||||||
| 	void  ClearCurrBlock(bool const zeroClear); | 	void  ClearCurrBlock(bool const zeroClear); | ||||||
| 
 | 
 | ||||||
| 	// -- Temporary Regions API
 | 	// -- Temporary Regions API
 | ||||||
| 	// region: Takes pointer to a zero-cleared DqnMemStackTempRegion struct.
 | 	// Revert all memory transactions between the Begin() and End() regions.
 | ||||||
| 	// return: FALSE if arguments are invalid.
 |  | ||||||
| 	struct DqnMemStackTempRegion TempRegionBegin(); | 	struct DqnMemStackTempRegion TempRegionBegin(); | ||||||
| 	void                         TempRegionEnd  (DqnMemStackTempRegion region); | 	void                         TempRegionEnd  (DqnMemStackTempRegion region); | ||||||
| 
 | 
 | ||||||
|  | 	// Keep the memory transactions that have occurred since Begin().
 | ||||||
|  | 	void  TempRegionKeepChanges(DqnMemStackTempRegion region); | ||||||
|  | 
 | ||||||
| 	// -- Scoped Temporary Regions API
 | 	// -- Scoped Temporary Regions API
 | ||||||
| 	struct DqnMemStackTempRegionGuard TempRegionGuard(); | 	struct DqnMemStackTempRegionGuard TempRegionGuard(); | ||||||
| 
 | 
 | ||||||
| @ -414,7 +416,7 @@ struct DqnMemStack | |||||||
| 
 | 
 | ||||||
| // TODO(doyle): Look into a way of "preventing/guarding" against anual calls to free/clear in temp
 | // TODO(doyle): Look into a way of "preventing/guarding" against anual calls to free/clear in temp
 | ||||||
| // regions
 | // regions
 | ||||||
| typedef struct DqnMemStackTempRegion | struct DqnMemStackTempRegion | ||||||
| { | { | ||||||
| 	// The stack associated with this TempRegion
 | 	// The stack associated with this TempRegion
 | ||||||
| 	DqnMemStack *stack; | 	DqnMemStack *stack; | ||||||
| @ -422,15 +424,17 @@ typedef struct DqnMemStackTempRegion | |||||||
| 	// Store memBlock state to revert back to on DqnMemStackTempRegion_End()
 | 	// Store memBlock state to revert back to on DqnMemStackTempRegion_End()
 | ||||||
| 	DqnMemStack::Block *startingBlock; | 	DqnMemStack::Block *startingBlock; | ||||||
| 	size_t used; | 	size_t used; | ||||||
| } DqnMemStackTempRegion; | }; | ||||||
| 
 | 
 | ||||||
| // Region guard automatically starts a region on construction and ends a region on destruction.
 | // Region guard automatically starts a region on construction and ends a region on destruction, except
 | ||||||
|  | // if keepChanges is set to true.
 | ||||||
| struct DqnMemStackTempRegionGuard | struct DqnMemStackTempRegionGuard | ||||||
| { | { | ||||||
| 	// stack: Takes a pointer to a pre-existing and already initialised stack
 | 	// stack: Takes a pointer to a pre-existing and already initialised stack
 | ||||||
| 	DqnMemStackTempRegionGuard(DqnMemStack *const stack); | 	DqnMemStackTempRegionGuard(DqnMemStack *const stack); | ||||||
| 	~DqnMemStackTempRegionGuard(); | 	~DqnMemStackTempRegionGuard(); | ||||||
| 
 | 
 | ||||||
|  | 	bool keepChanges = false; | ||||||
| private: | private: | ||||||
| 	DqnMemStackTempRegion memRegion; | 	DqnMemStackTempRegion memRegion; | ||||||
| }; | }; | ||||||
| @ -911,6 +915,7 @@ struct DqnHashTable | |||||||
| 	i64 usedEntriesIndex; | 	i64 usedEntriesIndex; | ||||||
| 
 | 
 | ||||||
| 	bool Init(i64 const numTableEntries = 1024, DqnMemAPI const api = DqnMemAPI_HeapAllocator()); | 	bool Init(i64 const numTableEntries = 1024, DqnMemAPI const api = DqnMemAPI_HeapAllocator()); | ||||||
|  | 	bool Init(i64 const numTableEntries, DqnMemStack *const stack); | ||||||
| 
 | 
 | ||||||
| 	// keyLen: Len of string not including null-terminator, if -1, utf8 strlen will be used to determine length.
 | 	// keyLen: Len of string not including null-terminator, if -1, utf8 strlen will be used to determine length.
 | ||||||
| 	// return: Pre-existing entry if it exists, otherwise a nullptr.
 | 	// return: Pre-existing entry if it exists, otherwise a nullptr.
 | ||||||
| @ -969,6 +974,16 @@ bool DqnHashTable<T>::Init(i64 const numTableEntries, DqnMemAPI const api) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template <typename T> | ||||||
|  | bool DqnHashTable<T>::Init(i64 const numTableEntries, DqnMemStack *const stack) | ||||||
|  | { | ||||||
|  | 	if (!stack) return false; | ||||||
|  | 
 | ||||||
|  | 	DqnMemAPI memAPI_ = DqnMemAPI_StackAllocator(stack); | ||||||
|  | 	bool result = Init(numTableEntries, memAPI_); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| typename DqnHashTable<T>::Entry *DqnHashTableInternal_AllocateEntry(DqnHashTable<T> *table) | typename DqnHashTable<T>::Entry *DqnHashTableInternal_AllocateEntry(DqnHashTable<T> *table) | ||||||
| { | { | ||||||
| @ -1615,9 +1630,12 @@ DQN_FILE_SCOPE char DqnChar_ToLower   (char c); | |||||||
| DQN_FILE_SCOPE char DqnChar_ToUpper     (char c); | DQN_FILE_SCOPE char DqnChar_ToUpper     (char c); | ||||||
| DQN_FILE_SCOPE bool DqnChar_IsDigit     (char c); | DQN_FILE_SCOPE bool DqnChar_IsDigit     (char c); | ||||||
| DQN_FILE_SCOPE bool DqnChar_IsAlpha     (char c); | DQN_FILE_SCOPE bool DqnChar_IsAlpha     (char c); | ||||||
| DQN_FILE_SCOPE bool DqnChar_IsAlphanum(char c); | DQN_FILE_SCOPE bool DqnChar_IsAlphaNum  (char c); | ||||||
|  | DQN_FILE_SCOPE bool DqnChar_IsEndOfLine (char c); | ||||||
|  | DQN_FILE_SCOPE bool DqnChar_IsWhitespace(char c); | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE char *DqnChar_SkipWhitespace(char *ptr); | DQN_FILE_SCOPE char *DqnChar_TrimWhitespaceAround(char const *src, i32 srcLen, i32 *newLen); | ||||||
|  | DQN_FILE_SCOPE char *DqnChar_SkipWhitespace      (char const *ptr); | ||||||
| 
 | 
 | ||||||
| // TODO(doyle): this is NOT UTF8 safe
 | // TODO(doyle): this is NOT UTF8 safe
 | ||||||
| // ch:        Char to find
 | // ch:        Char to find
 | ||||||
| @ -1626,9 +1644,11 @@ DQN_FILE_SCOPE char *DqnChar_SkipWhitespace(char *ptr); | |||||||
| // return:    The ptr to the last char, null if it could not find.
 | // return:    The ptr to the last char, null if it could not find.
 | ||||||
| DQN_FILE_SCOPE char *DqnChar_FindLastChar  (char *ptr, char const ch, i32 len, u32 *const lenToChar); | DQN_FILE_SCOPE char *DqnChar_FindLastChar  (char *ptr, char const ch, i32 len, u32 *const lenToChar); | ||||||
| 
 | 
 | ||||||
|  | // Finds up to the first [\r]\n and destroy the line, giving you a null terminated line at the newline.
 | ||||||
| // returns: The value to advance the ptr by, this can be different from the line
 | // returns: The value to advance the ptr by, this can be different from the line
 | ||||||
| //          length if there are new lines or leading whitespaces in the next line
 | //          length if there are new lines or leading whitespaces in the next line
 | ||||||
| DQN_FILE_SCOPE i32   DqnChar_GetNextLine (char const *ptr, i32 *lineLength); | DQN_FILE_SCOPE i32   DqnChar_FindNextLine(char *ptr, i32 *lineLength); | ||||||
|  | DQN_FILE_SCOPE char *DqnChar_GetNextLine (char *ptr, i32 *lineLength); | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // #DqnStr Public API - Str Operations
 | // #DqnStr Public API - Str Operations
 | ||||||
| @ -1653,10 +1673,10 @@ DQN_FILE_SCOPE void DqnStr_Reverse(char *const buf, u32 const bufSize); | |||||||
| DQN_FILE_SCOPE i32 DqnStr_ReadUTF8Codepoint(u32 const *const a, u32 *outCodepoint); | DQN_FILE_SCOPE i32 DqnStr_ReadUTF8Codepoint(u32 const *const a, u32 *outCodepoint); | ||||||
| 
 | 
 | ||||||
| // return: The offset into the src to first char of the found string. Returns -1 if not found
 | // return: The offset into the src to first char of the found string. Returns -1 if not found
 | ||||||
| DQN_FILE_SCOPE i32   DqnStr_FindFirstOccurence(char const *const src, i32 const srcLen, char const *const find, i32 const findLen, bool ignoreCase = false); | DQN_FILE_SCOPE i32   DqnStr_FindFirstOccurence(char const *src, i32 const srcLen, char const *find, i32 const findLen, bool ignoreCase = false); | ||||||
| // return: Helper function that returns the pointer to the first occurence, nullptr if not found.
 | // return: Helper function that returns the pointer to the first occurence, nullptr if not found.
 | ||||||
| DQN_FILE_SCOPE char *DqnStr_GetFirstOccurence(char *const src, i32 const srcLen, char *const find, i32 const findLen, bool ignoreCase = false); | DQN_FILE_SCOPE char *DqnStr_GetFirstOccurence(char const *src, i32 const srcLen, char const *find, i32 const findLen, bool ignoreCase = false); | ||||||
| DQN_FILE_SCOPE bool  DqnStr_HasSubstring     (char const *const src, i32 const srcLen, char const *const find, i32 const findLen, bool ignoreCase = false); | DQN_FILE_SCOPE bool  DqnStr_HasSubstring     (char const *src, i32 const srcLen, char const *find, i32 const findLen, bool ignoreCase = false); | ||||||
| 
 | 
 | ||||||
| #define DQN_32BIT_NUM_MAX_STR_SIZE 11 | #define DQN_32BIT_NUM_MAX_STR_SIZE 11 | ||||||
| #define DQN_64BIT_NUM_MAX_STR_SIZE 21 | #define DQN_64BIT_NUM_MAX_STR_SIZE 21 | ||||||
| @ -1987,6 +2007,14 @@ struct DqnFile | |||||||
| 		ForceCreate,      // Always create, even if it exists
 | 		ForceCreate,      // Always create, even if it exists
 | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | 	struct Info | ||||||
|  | 	{ | ||||||
|  | 		size_t size; | ||||||
|  | 		u64 createTimeInS; | ||||||
|  | 		u64 lastWriteTimeInS; | ||||||
|  | 		u64 lastAccessTimeInS; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| 	u32     flags; | 	u32     flags; | ||||||
| 	void   *handle; | 	void   *handle; | ||||||
| 	size_t  size; | 	size_t  size; | ||||||
| @ -2029,14 +2057,19 @@ struct DqnFile | |||||||
| 	//          if the returned ptr is null.
 | 	//          if the returned ptr is null.
 | ||||||
| 	// returns: nullptr if file could not be read, malloc failed or string.
 | 	// returns: nullptr if file could not be read, malloc failed or string.
 | ||||||
| 	//          Free the buffer using the memAPI, if default heap allocator, this is just free().
 | 	//          Free the buffer using the memAPI, if default heap allocator, this is just free().
 | ||||||
| 	static u8 *ReadEntireFileSimple (char    const *const path, size_t &bufSize, DqnMemAPI const memAPI = DqnMemAPI_HeapAllocator()); | 	static u8 *ReadEntireFileSimple (char    const *const path, size_t *bufSize, DqnMemAPI const memAPI = DqnMemAPI_HeapAllocator()); | ||||||
| 	static u8 *ReadEntireFileSimpleW(wchar_t const *const path, size_t &bufSize, DqnMemAPI const memAPI = DqnMemAPI_HeapAllocator()); | 	static u8 *ReadEntireFileSimpleW(wchar_t const *const path, size_t *bufSize, DqnMemAPI const memAPI = DqnMemAPI_HeapAllocator()); | ||||||
| 
 | 
 | ||||||
| 	// size: Pass in a pointer to a size_t where the file size gets put into. It holds invalid data if
 | 	// size: Pass in a pointer to a size_t where the file size gets put into. It holds invalid data if
 | ||||||
| 	// function returns false.
 | 	// function returns false.
 | ||||||
| 	static bool GetFileSize (char    const *const path, size_t &size); | 	static bool GetFileSize (char    const *const path, size_t &size); | ||||||
| 	static bool GetFileSizeW(wchar_t const *const path, size_t &size); | 	static bool GetFileSizeW(wchar_t const *const path, size_t &size); | ||||||
| 
 | 
 | ||||||
|  | 	// info: Pass in a pointer to a info where file attributes gets put into
 | ||||||
|  | 	// function returns false.
 | ||||||
|  | 	static bool GetInfo (char    const *const path, Info *info); | ||||||
|  | 	static bool GetInfoW(wchar_t const *const path, Info *info); | ||||||
|  | 
 | ||||||
| 	// NOTE: You can't delete a file unless the handle has been closed to it on Win32.
 | 	// NOTE: You can't delete a file unless the handle has been closed to it on Win32.
 | ||||||
| 	static bool Delete (char    const *const path); | 	static bool Delete (char    const *const path); | ||||||
| 	static bool DeleteW(wchar_t const *const path); | 	static bool DeleteW(wchar_t const *const path); | ||||||
| @ -2797,6 +2830,10 @@ DQN_FILE_SCOPE bool DqnAssertInternal(const bool result, const char *const file, | |||||||
| 			va_end(argList); | 			va_end(argList); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | #if defined(DQN_WIN32_PLATFORM) | ||||||
|  | 		DqnWin32_OutputDebugString(formatStr, file, lineNum, expr, userMsg); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| 		printf(formatStr, file, lineNum, expr, userMsg); | 		printf(formatStr, file, lineNum, expr, userMsg); | ||||||
| 		(*((i32 *)0)) = 0; | 		(*((i32 *)0)) = 0; | ||||||
| 	} | 	} | ||||||
| @ -3353,7 +3390,7 @@ DQN_FILE_SCOPE void DqnMemStack::ClearCurrBlock(bool const zeroClear) | |||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // #DqnMemStackTempRegion Implementation
 | // #DqnMemStackTempRegion Implementation
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| DQN_FILE_SCOPE DqnMemStackTempRegion DqnMemStack::TempRegionBegin() | DqnMemStackTempRegion DqnMemStack::TempRegionBegin() | ||||||
| { | { | ||||||
| 	DqnMemStackTempRegion result; | 	DqnMemStackTempRegion result; | ||||||
| 	result.stack         = this; | 	result.stack         = this; | ||||||
| @ -3364,7 +3401,7 @@ DQN_FILE_SCOPE DqnMemStackTempRegion DqnMemStack::TempRegionBegin() | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE void DqnMemStack::TempRegionEnd(DqnMemStackTempRegion region) | void DqnMemStack::TempRegionEnd(DqnMemStackTempRegion region) | ||||||
| { | { | ||||||
| 	DqnMemStack *stack = region.stack; | 	DqnMemStack *stack = region.stack; | ||||||
| 	DQN_ASSERT(stack == this); | 	DQN_ASSERT(stack == this); | ||||||
| @ -3382,6 +3419,15 @@ DQN_FILE_SCOPE void DqnMemStack::TempRegionEnd(DqnMemStackTempRegion region) | |||||||
| 	DQN_ASSERT_HARD(this->tempRegionCount >= 0); | 	DQN_ASSERT_HARD(this->tempRegionCount >= 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void DqnMemStack::TempRegionKeepChanges(DqnMemStackTempRegion region) | ||||||
|  | { | ||||||
|  | 	DqnMemStack *stack = region.stack; | ||||||
|  | 	DQN_ASSERT(stack == this); | ||||||
|  | 
 | ||||||
|  | 	this->tempRegionCount--; | ||||||
|  | 	DQN_ASSERT_HARD(this->tempRegionCount >= 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| DqnMemStackTempRegionGuard DqnMemStack::TempRegionGuard() | DqnMemStackTempRegionGuard DqnMemStack::TempRegionGuard() | ||||||
| { | { | ||||||
| 	return DqnMemStackTempRegionGuard(this); | 	return DqnMemStackTempRegionGuard(this); | ||||||
| @ -3396,7 +3442,15 @@ DqnMemStackTempRegionGuard::~DqnMemStackTempRegionGuard() | |||||||
| { | { | ||||||
| 	const DqnMemStackTempRegion ®ion = this->memRegion; | 	const DqnMemStackTempRegion ®ion = this->memRegion; | ||||||
| 	DqnMemStack *const stack            = region.stack; | 	DqnMemStack *const stack            = region.stack; | ||||||
|  | 
 | ||||||
|  | 	if (this->keepChanges) | ||||||
|  | 	{ | ||||||
|  | 		stack->TempRegionKeepChanges(region); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
| 		stack->TempRegionEnd(region); | 		stack->TempRegionEnd(region); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| @ -4369,6 +4423,49 @@ DQN_FILE_SCOPE char DqnChar_ToUpper(char c) | |||||||
| 	return c; | 	return c; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | DQN_FILE_SCOPE bool DqnChar_IsEndOfLine(char c) | ||||||
|  | { | ||||||
|  | 	bool result = (c == '\n'); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE bool DqnChar_IsWhitespace(char c) | ||||||
|  | { | ||||||
|  | 	bool result = (c == ' ' || c == '\r' || c == '\n' || c == '\t'); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE char *DqnChar_TrimWhitespaceAround(char const *src, i32 srcLen, i32 *newLen) | ||||||
|  | { | ||||||
|  | 	if (!src)       return nullptr; | ||||||
|  | 	if (srcLen < 0) return (char *)src; | ||||||
|  | 
 | ||||||
|  | 	char const *start = src; | ||||||
|  | 	char const *end   = start + (srcLen - 1); | ||||||
|  | 	while(start[0] && DqnChar_IsWhitespace(start[0])) | ||||||
|  | 	{ | ||||||
|  | 		start++; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	i32 charsSkipped = (i32)(start - src); | ||||||
|  | 	i32 updatedLen   = srcLen - charsSkipped; | ||||||
|  | 	if (updatedLen == 0) | ||||||
|  | 	{ | ||||||
|  | 		if (newLen) *newLen = 0; | ||||||
|  | 		return nullptr; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	while(end[0] && DqnChar_IsWhitespace(end[0])) | ||||||
|  | 	{ | ||||||
|  | 		end--; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	charsSkipped = (i32)((src + srcLen - 1) - end); | ||||||
|  | 	updatedLen   = updatedLen - charsSkipped; | ||||||
|  | 
 | ||||||
|  | 	if (newLen) *newLen = updatedLen; | ||||||
|  | 	return (char *)start; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE bool DqnChar_IsDigit(char c) | DQN_FILE_SCOPE bool DqnChar_IsDigit(char c) | ||||||
| { | { | ||||||
| @ -4388,10 +4485,10 @@ DQN_FILE_SCOPE bool DqnChar_IsAlphaNum(char c) | |||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE char *DqnChar_SkipWhitespace(char *ptr) | DQN_FILE_SCOPE char *DqnChar_SkipWhitespace(char const *ptr) | ||||||
| { | { | ||||||
| 	while (ptr && (*ptr == ' ' || *ptr == '\r' || *ptr == '\n')) ptr++; | 	while (ptr && (*ptr == ' ' || *ptr == '\r' || *ptr == '\n' || *ptr == '\t')) ptr++; | ||||||
| 	return ptr; | 	return (char *)ptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE char *DqnChar_FindLastChar(char *ptr, const char ch, i32 len, u32 *const lenToChar) | DQN_FILE_SCOPE char *DqnChar_FindLastChar(char *ptr, const char ch, i32 len, u32 *const lenToChar) | ||||||
| @ -4408,7 +4505,7 @@ DQN_FILE_SCOPE char *DqnChar_FindLastChar(char *ptr, const char ch, i32 len, u32 | |||||||
| 	return nullptr; | 	return nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE i32 DqnChar_GetNextLine(char *ptr, i32 *lineLength) | DQN_FILE_SCOPE i32 DqnChar_FindNextLine(char *ptr, i32 *lineLength) | ||||||
| { | { | ||||||
| 	i32 len = 0; | 	i32 len = 0; | ||||||
| 	ptr     = DqnChar_SkipWhitespace(ptr); | 	ptr     = DqnChar_SkipWhitespace(ptr); | ||||||
| @ -4439,6 +4536,20 @@ DQN_FILE_SCOPE i32 DqnChar_GetNextLine(char *ptr, i32 *lineLength) | |||||||
| 	return len + extraChars; | 	return len + extraChars; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | DQN_FILE_SCOPE char *DqnChar_GetNextLine (char *ptr, i32 *lineLength) | ||||||
|  | { | ||||||
|  | 	i32 offsetToNextLine = DqnChar_FindNextLine(ptr, lineLength); | ||||||
|  | 
 | ||||||
|  | 	char *result = nullptr; | ||||||
|  | 	if (offsetToNextLine != -1) | ||||||
|  | 	{ | ||||||
|  | 		result = ptr + offsetToNextLine; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // #DqnStr Implementation
 | // #DqnStr Implementation
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| @ -4590,8 +4701,8 @@ DQN_FILE_SCOPE void DqnStr_Reverse(char *const buf, const u32 bufSize) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE i32 DqnStr_FindFirstOccurence(const char *const src, const i32 srcLen, | DQN_FILE_SCOPE i32 DqnStr_FindFirstOccurence(char const *src, i32 const srcLen, | ||||||
|                                              const char *const find, const i32 findLen, bool ignoreCase) |                                              char const *find, i32 const findLen, bool ignoreCase) | ||||||
| { | { | ||||||
| 	if (!src || !find)               return -1; | 	if (!src || !find)               return -1; | ||||||
| 	if (srcLen == 0 || findLen == 0) return -1; | 	if (srcLen == 0 || findLen == 0) return -1; | ||||||
| @ -4617,18 +4728,18 @@ DQN_FILE_SCOPE i32 DqnStr_FindFirstOccurence(const char *const src, const i32 sr | |||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE char *DqnStr_GetFirstOccurence(char *const src, i32 const srcLen, char *const find, | DQN_FILE_SCOPE char *DqnStr_GetFirstOccurence(char const *src, i32 const srcLen, char const *find, | ||||||
|                                               i32 const findLen, bool ignoreCase) |                                               i32 const findLen, bool ignoreCase) | ||||||
| { | { | ||||||
| 	i32 offset = DqnStr_FindFirstOccurence(src, srcLen, find, findLen, ignoreCase); | 	i32 offset = DqnStr_FindFirstOccurence(src, srcLen, find, findLen, ignoreCase); | ||||||
| 	if (offset == -1) return nullptr; | 	if (offset == -1) return nullptr; | ||||||
| 
 | 
 | ||||||
| 	char *result = src + offset; | 	char *result = (char *)(src + offset); | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE bool DqnStr_HasSubstring(char const *const src, i32 const srcLen, | DQN_FILE_SCOPE bool DqnStr_HasSubstring(char const *src, i32 const srcLen, | ||||||
|                                         char const *const find, i32 const findLen, bool ignoreCase) |                                         char const *find, i32 const findLen, bool ignoreCase) | ||||||
| { | { | ||||||
| 	if (DqnStr_FindFirstOccurence(src, srcLen, find, findLen, ignoreCase) == -1) | 	if (DqnStr_FindFirstOccurence(src, srcLen, find, findLen, ignoreCase) == -1) | ||||||
| 		return false; | 		return false; | ||||||
| @ -5538,7 +5649,6 @@ bool DqnString::Append(DqnString const strToAppend, i32 bytesToCopy) | |||||||
| void DqnString::Clear() | void DqnString::Clear() | ||||||
| { | { | ||||||
| 	this->len = 0; | 	this->len = 0; | ||||||
| 
 |  | ||||||
| 	if (this->str) | 	if (this->str) | ||||||
| 	{ | 	{ | ||||||
| 		this->str[0] = 0; | 		this->str[0] = 0; | ||||||
| @ -7918,7 +8028,7 @@ size_t DqnFile::Read(u8 *const buf, size_t const numBytesToRead) | |||||||
| 	return numBytesRead; | 	return numBytesRead; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| u8 *DqnFile::ReadEntireFileSimpleW(wchar_t const *const path, size_t &bufSize, DqnMemAPI const memAPI) | u8 *DqnFile::ReadEntireFileSimpleW(wchar_t const *const path, size_t *bufSize, DqnMemAPI const memAPI) | ||||||
| { | { | ||||||
| 	// TODO(doyle): Logging
 | 	// TODO(doyle): Logging
 | ||||||
| 
 | 
 | ||||||
| @ -7932,7 +8042,7 @@ u8 *DqnFile::ReadEntireFileSimpleW(wchar_t const *const path, size_t &bufSize, D | |||||||
| 	size_t bytesRead = 0; | 	size_t bytesRead = 0; | ||||||
| 	if (DqnFile::ReadEntireFileW(path, buf, requiredSize, bytesRead)) | 	if (DqnFile::ReadEntireFileW(path, buf, requiredSize, bytesRead)) | ||||||
| 	{ | 	{ | ||||||
| 		bufSize = requiredSize; | 		*bufSize = requiredSize; | ||||||
| 		DQN_ASSERT(bytesRead == requiredSize); | 		DQN_ASSERT(bytesRead == requiredSize); | ||||||
| 		return buf; | 		return buf; | ||||||
| 	} | 	} | ||||||
| @ -7941,7 +8051,7 @@ u8 *DqnFile::ReadEntireFileSimpleW(wchar_t const *const path, size_t &bufSize, D | |||||||
| 	return nullptr; | 	return nullptr; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| u8 *DqnFile::ReadEntireFileSimple(char const *const path, size_t &bufSize, DqnMemAPI const memAPI) | u8 *DqnFile::ReadEntireFileSimple(char const *const path, size_t *bufSize, DqnMemAPI const memAPI) | ||||||
| { | { | ||||||
| 	// TODO(doyle): Logging
 | 	// TODO(doyle): Logging
 | ||||||
| 
 | 
 | ||||||
| @ -7955,7 +8065,7 @@ u8 *DqnFile::ReadEntireFileSimple(char const *const path, size_t &bufSize, DqnMe | |||||||
| 	size_t bytesRead = 0; | 	size_t bytesRead = 0; | ||||||
| 	if (DqnFile::ReadEntireFile(path, buf, requiredSize, bytesRead)) | 	if (DqnFile::ReadEntireFile(path, buf, requiredSize, bytesRead)) | ||||||
| 	{ | 	{ | ||||||
| 		bufSize = requiredSize; | 		*bufSize = requiredSize; | ||||||
| 		DQN_ASSERT(bytesRead == requiredSize); | 		DQN_ASSERT(bytesRead == requiredSize); | ||||||
| 		return buf; | 		return buf; | ||||||
| 	} | 	} | ||||||
| @ -8036,25 +8146,13 @@ void DqnFile::Close() | |||||||
| 
 | 
 | ||||||
| bool DqnFile::GetFileSizeW(wchar_t const *const path, size_t &size) | bool DqnFile::GetFileSizeW(wchar_t const *const path, size_t &size) | ||||||
| { | { | ||||||
| #if defined(DQN_WIN32_PLATFORM) | 	Info info = {}; | ||||||
| 	WIN32_FILE_ATTRIBUTE_DATA attribData = {}; | 	if (GetInfoW(path, &info)) | ||||||
| 	if (GetFileAttributesExW(path, GetFileExInfoStandard, &attribData)) |  | ||||||
| 	{ | 	{ | ||||||
| 		// TODO(doyle): What if size_t is < Quad.part?
 | 		size = info.size; | ||||||
| 		LARGE_INTEGER largeInt = {}; |  | ||||||
| 		largeInt.HighPart      = attribData.nFileSizeHigh; |  | ||||||
| 		largeInt.LowPart       = attribData.nFileSizeLow; |  | ||||||
| 
 |  | ||||||
| 		size = (size_t)largeInt.QuadPart; |  | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| #elif defined(DQN_UNIX_PLATFORM) |  | ||||||
| 	// NOTE: Not supported on unix
 |  | ||||||
| 	DQN_ASSERT_HARD(DQN_INVALID_CODE_PATH); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -8087,6 +8185,62 @@ bool DqnFile::GetFileSize(char const *const path, size_t &size) | |||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool DqnFile::GetInfoW(wchar_t const *const path, Info *info) | ||||||
|  | { | ||||||
|  | 	if (!path || !info) return false; | ||||||
|  | 
 | ||||||
|  | #if defined(DQN_WIN32_PLATFORM) | ||||||
|  | 	auto FileTimeToSeconds = [](FILETIME const *time) -> i64 { | ||||||
|  | 		ULARGE_INTEGER timeLargeInt = {}; | ||||||
|  | 		timeLargeInt.LowPart        = time->dwLowDateTime; | ||||||
|  | 		timeLargeInt.HighPart       = time->dwHighDateTime; | ||||||
|  | 
 | ||||||
|  | 		u64 result = (timeLargeInt.QuadPart / 10000000ULL) - 11644473600ULL; | ||||||
|  | 		return result; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	WIN32_FILE_ATTRIBUTE_DATA attribData = {}; | ||||||
|  | 	if (GetFileAttributesExW(path, GetFileExInfoStandard, &attribData)) | ||||||
|  | 	{ | ||||||
|  | 		info->createTimeInS     = FileTimeToSeconds(&attribData.ftCreationTime); | ||||||
|  | 		info->lastAccessTimeInS = FileTimeToSeconds(&attribData.ftLastAccessTime); | ||||||
|  | 		info->lastWriteTimeInS  = FileTimeToSeconds(&attribData.ftLastWriteTime); | ||||||
|  | 
 | ||||||
|  | 		// TODO(doyle): What if size_t is < Quad.part?
 | ||||||
|  | 		LARGE_INTEGER largeInt = {}; | ||||||
|  | 		largeInt.HighPart      = attribData.nFileSizeHigh; | ||||||
|  | 		largeInt.LowPart       = attribData.nFileSizeLow; | ||||||
|  | 		info->size            = (size_t)largeInt.QuadPart; | ||||||
|  | 
 | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | #elif defined(DQN_UNIX_PLATFORM) | ||||||
|  | 	// NOTE: Not supported on unix
 | ||||||
|  | 	DQN_ASSERT_HARD(DQN_INVALID_CODE_PATH); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool DqnFile::GetInfo(char const *const path, Info *info) | ||||||
|  | { | ||||||
|  | 	if (!path) return false; | ||||||
|  | 
 | ||||||
|  | 	// TODO(doyle): Logging
 | ||||||
|  | #if defined(DQN_WIN32_PLATFORM) | ||||||
|  | 	// TODO(doyle): MAX PATH is baad
 | ||||||
|  | 	wchar_t widePath[MAX_PATH] = {0}; | ||||||
|  | 	DqnWin32_UTF8ToWChar(path, widePath, DQN_ARRAY_COUNT(widePath)); | ||||||
|  | 	return DqnFile::GetInfoW(widePath, info); | ||||||
|  | 
 | ||||||
|  | #elif defined(DQN_UNIX_PLATFORM) | ||||||
|  | #error UNIX implementation not completed. | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| bool DqnFile::Delete(char const *const path) | bool DqnFile::Delete(char const *const path) | ||||||
| { | { | ||||||
| 	if (!path) return false; | 	if (!path) return false; | ||||||
|  | |||||||
| @ -517,6 +517,7 @@ void DqnStr_Test() | |||||||
| 			DQN_ASSERT(DqnStr_HasSubstring(b, lenB, a, lenA) == false); | 			DQN_ASSERT(DqnStr_HasSubstring(b, lenB, a, lenA) == false); | ||||||
| 			LogSuccess("DqnStr_HasSubstring(): Check string with non-matching substring"); | 			LogSuccess("DqnStr_HasSubstring(): Check string with non-matching substring"); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -561,6 +562,72 @@ void DqnChar_Test() | |||||||
| 		DQN_ASSERT(DqnChar_ToUpper(L' ') == L' '); | 		DQN_ASSERT(DqnChar_ToUpper(L' ') == L' '); | ||||||
| 		LogSuccess("DqnChar_ToUpper()"); | 		LogSuccess("DqnChar_ToUpper()"); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	// Trim white space test
 | ||||||
|  | 	if (1) | ||||||
|  | 	{ | ||||||
|  | 		if (1) | ||||||
|  | 		{ | ||||||
|  | 			char a[]     = ""; | ||||||
|  | 			i32 newLen   = 0; | ||||||
|  | 			auto *result = DqnChar_TrimWhitespaceAround(a, DQN_CHAR_COUNT(a), &newLen); | ||||||
|  | 
 | ||||||
|  | 			DQN_ASSERT(newLen == 0); | ||||||
|  | 			DQN_ASSERT(result == nullptr); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (1) | ||||||
|  | 		{ | ||||||
|  | 			char a[]     = "a"; | ||||||
|  | 			i32 newLen   = 0; | ||||||
|  | 			auto *result = DqnChar_TrimWhitespaceAround(a, DQN_CHAR_COUNT(a), &newLen); | ||||||
|  | 
 | ||||||
|  | 			DQN_ASSERT(newLen == 1); | ||||||
|  | 			DQN_ASSERT(result == a); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (1) | ||||||
|  | 		{ | ||||||
|  | 			char a[]     = " abc"; | ||||||
|  | 			i32 newLen   = 0; | ||||||
|  | 			auto *result = DqnChar_TrimWhitespaceAround(a, DQN_CHAR_COUNT(a), &newLen); | ||||||
|  | 
 | ||||||
|  | 			DQN_ASSERT(newLen == 3); | ||||||
|  | 			DQN_ASSERT(result == (a + 1)); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (1) | ||||||
|  | 		{ | ||||||
|  | 			char a[]     = "abc "; | ||||||
|  | 			i32 newLen   = 0; | ||||||
|  | 			auto *result = DqnChar_TrimWhitespaceAround(a, DQN_CHAR_COUNT(a), &newLen); | ||||||
|  | 
 | ||||||
|  | 			DQN_ASSERT(newLen == 3); | ||||||
|  | 			DQN_ASSERT(result == a); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (1) | ||||||
|  | 		{ | ||||||
|  | 			char a[]     = "   abc "; | ||||||
|  | 			i32 newLen   = 0; | ||||||
|  | 			auto *result = DqnChar_TrimWhitespaceAround(a, DQN_CHAR_COUNT(a), &newLen); | ||||||
|  | 
 | ||||||
|  | 			DQN_ASSERT(newLen == 3); | ||||||
|  | 			DQN_ASSERT(result == a + 3); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (1) | ||||||
|  | 		{ | ||||||
|  | 			char a[]     = "         "; | ||||||
|  | 			i32 newLen   = 0; | ||||||
|  | 			auto *result = DqnChar_TrimWhitespaceAround(a, DQN_CHAR_COUNT(a), &newLen); | ||||||
|  | 
 | ||||||
|  | 			DQN_ASSERT(newLen == 0); | ||||||
|  | 			DQN_ASSERT(result == nullptr); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		LogSuccess("DqnChar_TrimAroundWhitespace()"); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DqnString_Test() | void DqnString_Test() | ||||||
| @ -1395,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::ReadEntireFileSimple("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++) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user