Add darray remove operations
This commit is contained in:
		
							parent
							
								
									15220a9646
								
							
						
					
					
						commit
						9106f185a3
					
				
							
								
								
									
										260
									
								
								dqn.h
									
									
									
									
									
								
							
							
						
						
									
										260
									
								
								dqn.h
									
									
									
									
									
								
							| @ -72,6 +72,23 @@ typedef float  f32; | |||||||
| 	dqn_darray_free(uintArray); | 	dqn_darray_free(uintArray); | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | // Typical operations should not require using the header directly, and it's
 | ||||||
|  | // recommended to use the API, but it can be used to have a faster way to track
 | ||||||
|  | // metadata.
 | ||||||
|  | typedef struct DqnDArrayHeader | ||||||
|  | { | ||||||
|  | 	u32  index; | ||||||
|  | 	u32  itemSize; | ||||||
|  | 	u32  capacity; | ||||||
|  | 	u32  signature; | ||||||
|  | 
 | ||||||
|  | 	void *data; | ||||||
|  | } DqnDArrayHeader; | ||||||
|  | 
 | ||||||
|  | // Returns the DArray header IF is a valid DArray
 | ||||||
|  | // Returns NULL              IF not a valid DArray
 | ||||||
|  | DQN_FILE_SCOPE DqnDArrayHeader *dqn_darray_get_header(void *array); | ||||||
|  | 
 | ||||||
| // The init macro RETURNS a pointer to your type, you can index this as normal
 | // The init macro RETURNS a pointer to your type, you can index this as normal
 | ||||||
| // with array notation [].
 | // with array notation [].
 | ||||||
| // u32 type             - The data type to initiate a dynamic array with
 | // u32 type             - The data type to initiate a dynamic array with
 | ||||||
| @ -84,11 +101,33 @@ typedef float  f32; | |||||||
| DQN_FILE_SCOPE u32  dqn_darray_get_capacity(void *array); | DQN_FILE_SCOPE u32  dqn_darray_get_capacity(void *array); | ||||||
| DQN_FILE_SCOPE u32  dqn_darray_get_num_items(void *array); | DQN_FILE_SCOPE u32  dqn_darray_get_num_items(void *array); | ||||||
| 
 | 
 | ||||||
|  | // Returns true and array modified in-place IF
 | ||||||
|  | //   - The capacity change was successful OR
 | ||||||
|  | //   - The newCapacity is equal to current capacity (no changes).
 | ||||||
|  | // Returns false and array is unmodified IF
 | ||||||
|  | //   - Invalid DArray passed in OR realloc failed OR
 | ||||||
|  | //   - More items in array than new capacity
 | ||||||
|  | DQN_FILE_SCOPE bool dqn_darray_capacity_change(void **array, i32 newCapacity); | ||||||
|  | 
 | ||||||
|  | // WARNING: This macro currently asserts if it's unable to push elements
 | ||||||
| // void **array - the address of the pointer returned by DQN_DARRAY_INIT
 | // void **array - the address of the pointer returned by DQN_DARRAY_INIT
 | ||||||
| // void *item   - a pointer to the object to insert
 | // void item    - the object to insert
 | ||||||
| // The push macro RETURNS true/false if the push was successful or not.
 |  | ||||||
| #define DQN_DARRAY_PUSH(array, item)                                           \ | #define DQN_DARRAY_PUSH(array, item)                                           \ | ||||||
| 	dqn_darray_push_internal((void **)array, (void *)item, sizeof(*item)) | 	{                                                                          \ | ||||||
|  | 		if (dqn_darray_capacity_grow_if_need_internal((void **)array))         \ | ||||||
|  | 		{                                                                      \ | ||||||
|  | 			DqnDArrayHeader *header = dqn_darray_get_header(*array);           \ | ||||||
|  | 			*array[header->index++] = item;                                    \ | ||||||
|  | 		}                                                                      \ | ||||||
|  | 		else                                                                   \ | ||||||
|  | 		{                                                                      \ | ||||||
|  | 			DQN_ASSERT(DQN_INVALID_CODE_PATH);                                 \ | ||||||
|  | 		}                                                                      \ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE bool dqn_darray_clear        (void *array); | ||||||
|  | DQN_FILE_SCOPE bool dqn_darray_remove       (void *array, u32 index); | ||||||
|  | DQN_FILE_SCOPE bool dqn_darray_remove_stable(void *array, u32 index); | ||||||
| 
 | 
 | ||||||
| // Pass in the pointer returned by DQN_DARRAY_INIT. Returns if the free was
 | // Pass in the pointer returned by DQN_DARRAY_INIT. Returns if the free was
 | ||||||
| // successful. This will return false if the array is not a valid DArray and
 | // successful. This will return false if the array is not a valid DArray and
 | ||||||
| @ -165,7 +204,7 @@ typedef union DqnV4 | |||||||
| } DqnV4; | } DqnV4; | ||||||
| 
 | 
 | ||||||
| // Create a vector using ints and typecast to floats
 | // Create a vector using ints and typecast to floats
 | ||||||
| DQN_FILE_SCOPE DqnV4 dqn_v4i(i32 x, i32 y, i32 z); | DQN_FILE_SCOPE DqnV4 dqn_v4i(i32 x, i32 y, i32 z, f32 w); | ||||||
| DQN_FILE_SCOPE DqnV4 dqn_v4 (f32 x, f32 y, f32 z, f32 w); | DQN_FILE_SCOPE DqnV4 dqn_v4 (f32 x, f32 y, f32 z, f32 w); | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE DqnV4 dqn_v4_add     (DqnV4 a, DqnV4 b); | DQN_FILE_SCOPE DqnV4 dqn_v4_add     (DqnV4 a, DqnV4 b); | ||||||
| @ -230,6 +269,12 @@ DQN_FILE_SCOPE void  dqn_i32_to_str (i32 value, char *buf, i32 bufSize); | |||||||
| DQN_FILE_SCOPE u32 dqn_ucs_to_utf8(u32 *dest, u32 character); | DQN_FILE_SCOPE u32 dqn_ucs_to_utf8(u32 *dest, u32 character); | ||||||
| DQN_FILE_SCOPE u32 dqn_utf8_to_ucs(u32 *dest, u32 character); | DQN_FILE_SCOPE u32 dqn_utf8_to_ucs(u32 *dest, u32 character); | ||||||
| 
 | 
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | // Win32 Specific
 | ||||||
|  | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
|  | DQN_FILE_SCOPE bool dqn_win32_utf8_to_wchar(char *in, wchar_t *out, i32 outLen); | ||||||
|  | DQN_FILE_SCOPE bool dqn_win32_wchar_to_utf8(wchar_t *in, char *out, i32 outLen); | ||||||
|  | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // File Operations
 | // File Operations
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| @ -301,27 +346,17 @@ DQN_FILE_SCOPE i32  dqn_rnd_pcg_range(DqnRandPCGState *pcg, i32 min, i32 max); | |||||||
| // DArray - Dynamic Array
 | // DArray - Dynamic Array
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| #define DQN_DARRAY_SIGNATURE_INTERNAL 0xAC83DB81 | #define DQN_DARRAY_SIGNATURE_INTERNAL 0xAC83DB81 | ||||||
| typedef struct DqnDArrayInternal |  | ||||||
| { |  | ||||||
| 	u32  index; |  | ||||||
| 	u32  itemSize; |  | ||||||
| 	u32  capacity; |  | ||||||
| 	u32  signature; |  | ||||||
| 
 |  | ||||||
| 	void *data; |  | ||||||
| } DqnDArrayInternal; |  | ||||||
| 
 |  | ||||||
| FILE_SCOPE void *dqn_darray_init_internal(u32 itemSize, u32 startingCapacity) | FILE_SCOPE void *dqn_darray_init_internal(u32 itemSize, u32 startingCapacity) | ||||||
| { | { | ||||||
| 	if (startingCapacity <= 0 || itemSize == 0) return NULL; | 	if (startingCapacity <= 0 || itemSize == 0) return NULL; | ||||||
| 
 | 
 | ||||||
| 	u32 metadataSize = sizeof(DqnDArrayInternal); | 	u32 metadataSize = sizeof(DqnDArrayHeader); | ||||||
| 	u32 storageSize  = itemSize * startingCapacity; | 	u32 storageSize  = itemSize * startingCapacity; | ||||||
| 
 | 
 | ||||||
| 	void *memory = calloc(1, metadataSize + storageSize); | 	void *memory = calloc(1, metadataSize + storageSize); | ||||||
| 	if (!memory) return NULL; | 	if (!memory) return NULL; | ||||||
| 
 | 
 | ||||||
| 	DqnDArrayInternal *array = (DqnDArrayInternal *)memory; | 	DqnDArrayHeader *array = (DqnDArrayHeader *)memory; | ||||||
| 	array->signature  = DQN_DARRAY_SIGNATURE_INTERNAL; | 	array->signature  = DQN_DARRAY_SIGNATURE_INTERNAL; | ||||||
| 	array->itemSize   = itemSize; | 	array->itemSize   = itemSize; | ||||||
| 	array->capacity   = startingCapacity; | 	array->capacity   = startingCapacity; | ||||||
| @ -330,36 +365,65 @@ FILE_SCOPE void *dqn_darray_init_internal(u32 itemSize, u32 startingCapacity) | |||||||
| 	return array->data; | 	return array->data; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| FILE_SCOPE DqnDArrayInternal *dqn_darray_get_header_internal(void *array) | DQN_FILE_SCOPE DqnDArrayHeader *dqn_darray_get_header(void *array) | ||||||
| { | { | ||||||
| 	if (!array) return NULL; | 	if (!array) return NULL; | ||||||
| 
 | 
 | ||||||
| 	DqnDArrayInternal *result = (DqnDArrayInternal *)((u8 *)array - sizeof(DqnDArrayInternal)); | 	DqnDArrayHeader *result = (DqnDArrayHeader *)((u8 *)array - sizeof(DqnDArrayHeader)); | ||||||
| 	if (result->signature != DQN_DARRAY_SIGNATURE_INTERNAL) return 0; | 	if (result->signature != DQN_DARRAY_SIGNATURE_INTERNAL) return NULL; | ||||||
| 
 | 
 | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE u32 dqn_darray_get_capacity(void *array) | DQN_FILE_SCOPE u32 dqn_darray_get_capacity(void *array) | ||||||
| { | { | ||||||
| 	DqnDArrayInternal *header = dqn_darray_get_header_internal(array); | 	DqnDArrayHeader *header = dqn_darray_get_header(array); | ||||||
| 	if (!header) return 0; | 	if (!header) return 0; | ||||||
| 	return header->capacity; | 	return header->capacity; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE u32 dqn_darray_get_num_items(void *array) | DQN_FILE_SCOPE u32 dqn_darray_get_num_items(void *array) | ||||||
| { | { | ||||||
| 	DqnDArrayInternal *header = dqn_darray_get_header_internal(array); | 	DqnDArrayHeader *header = dqn_darray_get_header(array); | ||||||
| 	if (!header) return 0; | 	if (!header) return 0; | ||||||
| 	return header->index; | 	return header->index; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool dqn_darray_push_internal(void **array, void *element, u32 itemSize) | DQN_FILE_SCOPE bool dqn_darray_capacity_change(void **array, u32 newCapacity) | ||||||
| { | { | ||||||
| 	if (!element || !array) return false; | 	DqnDArrayHeader *header = dqn_darray_get_header(*array); | ||||||
|  | 	if (!header) return false; | ||||||
|  | 	if (header->capacity == newCapacity) return true; | ||||||
| 
 | 
 | ||||||
| 	DqnDArrayInternal *header = dqn_darray_get_header_internal(*array); | 	if (newCapacity > header->index) | ||||||
| 	if (!header || header->itemSize != itemSize) return false; | 	{ | ||||||
|  | 		u32 metadataSize = sizeof(DqnDArrayHeader); | ||||||
|  | 		u32 storageSize  = header->itemSize * newCapacity; | ||||||
|  | 		void *newMem     = realloc(header, metadataSize + storageSize); | ||||||
|  | 		if (newMem) | ||||||
|  | 		{ | ||||||
|  | 			header           = (DqnDArrayHeader *)newMem; | ||||||
|  | 			header->capacity = newCapacity; | ||||||
|  | 			header->data     = (u8 *)newMem + metadataSize; | ||||||
|  | 			*array           = header->data; | ||||||
|  | 
 | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | FILE_SCOPE bool dqn_darray_capacity_grow_if_need_internal(void **array) | ||||||
|  | { | ||||||
|  | 	DqnDArrayHeader *header = dqn_darray_get_header(*array); | ||||||
|  | 	if (!header) return false; | ||||||
| 
 | 
 | ||||||
| 	if (header->index >= header->capacity) | 	if (header->index >= header->capacity) | ||||||
| 	{ | 	{ | ||||||
| @ -367,21 +431,23 @@ bool dqn_darray_push_internal(void **array, void *element, u32 itemSize) | |||||||
| 		u32 newCapacity         = (i32)(header->capacity * GROWTH_FACTOR); | 		u32 newCapacity         = (i32)(header->capacity * GROWTH_FACTOR); | ||||||
| 		if (newCapacity == header->capacity) newCapacity++; | 		if (newCapacity == header->capacity) newCapacity++; | ||||||
| 
 | 
 | ||||||
| 		u32 metadataSize = sizeof(DqnDArrayInternal); | 		return dqn_darray_capacity_change(array, newCapacity); | ||||||
| 		u32 storageSize  = header->itemSize * newCapacity; |  | ||||||
| 		void *newMem     = realloc(header, metadataSize + storageSize); |  | ||||||
| 		if (newMem) |  | ||||||
| 		{ |  | ||||||
| 			header           = (DqnDArrayInternal *)newMem; |  | ||||||
| 			header->capacity = newCapacity; |  | ||||||
| 			header->data     = (u8 *)newMem + metadataSize; |  | ||||||
| 			*array           = header->data; |  | ||||||
| 	} | 	} | ||||||
| 		else | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool dqn_darray_push_internal(void **array, void *element, u32 itemSize) | ||||||
| { | { | ||||||
|  | 	if (!element || !array) return false; | ||||||
|  | 
 | ||||||
|  | 	DqnDArrayHeader *header = dqn_darray_get_header(*array); | ||||||
|  | 	if (!header || header->itemSize != itemSize) return false; | ||||||
|  | 
 | ||||||
|  | 	// NOTE: Array is grown before this step happens. If at this point it still
 | ||||||
|  | 	// doesn't fit then we've had a mem alloc problem.
 | ||||||
|  | 	if (header->index >= header->capacity) | ||||||
| 		return false; | 		return false; | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	u32 arrayOffset = header->itemSize * header->index++; | 	u32 arrayOffset = header->itemSize * header->index++; | ||||||
| 	DQN_ASSERT(header->index <= header->capacity); | 	DQN_ASSERT(header->index <= header->capacity); | ||||||
| @ -394,9 +460,108 @@ bool dqn_darray_push_internal(void **array, void *element, u32 itemSize) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | DQN_FILE_SCOPE bool dqn_darray_clear(void *array) | ||||||
|  | { | ||||||
|  | 	DqnDArrayHeader *header = dqn_darray_get_header(array); | ||||||
|  | 	if (header) | ||||||
|  | 	{ | ||||||
|  | 		header->index = 0; | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE bool dqn_darray_remove(void *array, u32 index) | ||||||
|  | { | ||||||
|  | 	DqnDArrayHeader *header = dqn_darray_get_header(array); | ||||||
|  | 	if (header) | ||||||
|  | 	{ | ||||||
|  | 		// NOTE: header->index is the index where the next entry will be push to
 | ||||||
|  | 		// Array is empty, or index is out of bounds
 | ||||||
|  | 		if (header->index == 0 || index >= header->index) return false; | ||||||
|  | 
 | ||||||
|  | 		// If it's the first entry we just need to decrement index
 | ||||||
|  | 		if (index == 0 && header->index == 1) | ||||||
|  | 		{ | ||||||
|  | 			header->index--; | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// If it's the last entry we just need to decrement index
 | ||||||
|  | 		if (index == (header->index - 1)) | ||||||
|  | 		{ | ||||||
|  | 			header->index--; | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		u32 lastEntryIndex        = header->index - 1; | ||||||
|  | 		u32 lastEntryByteOffset   = lastEntryIndex * header->itemSize; | ||||||
|  | 		u32 removeEntryIndex      = index; | ||||||
|  | 		u32 removeEntryByteOffset = removeEntryIndex * header->itemSize; | ||||||
|  | 
 | ||||||
|  | 		u8 *dataPtr = (u8 *)header->data; | ||||||
|  | 		void *dest  = (void *)&dataPtr[removeEntryByteOffset]; | ||||||
|  | 		void *src   = (void *)&dataPtr[lastEntryByteOffset]; | ||||||
|  | 		memcpy(dest, src, header->itemSize); | ||||||
|  | 
 | ||||||
|  | 		header->index--; | ||||||
|  | 
 | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE bool dqn_darray_remove_stable(void *array, u32 index) | ||||||
|  | { | ||||||
|  | 	DqnDArrayHeader *header = dqn_darray_get_header(array); | ||||||
|  | 	if (header) | ||||||
|  | 	{ | ||||||
|  | 		// NOTE: header->index is the index where the next entry will be push to
 | ||||||
|  | 		// Array is empty, or index is out of bounds
 | ||||||
|  | 		if (header->index == 0 || index >= header->index) return false; | ||||||
|  | 
 | ||||||
|  | 		// If it's the last entry we just need to decrement index
 | ||||||
|  | 		if (index == (header->index - 1)) | ||||||
|  | 		{ | ||||||
|  | 			header->index--; | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// If it's the first entry we just need to decrement index
 | ||||||
|  | 		if (index == 0 && header->index == 1) | ||||||
|  | 		{ | ||||||
|  | 			header->index--; | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		u32 removeEntryIndex         = index; | ||||||
|  | 		u32 removeEntryByteOffset    = removeEntryIndex * header->itemSize; | ||||||
|  | 
 | ||||||
|  | 		u32 oneAfterRemove           = index + 1; | ||||||
|  | 		u32 oneAfterRemoveByteOffset = oneAfterRemove * header->itemSize; | ||||||
|  | 		u32 endOfListIndex           = header->index - 1; | ||||||
|  | 		u32 endOfListByteOffset      = endOfListIndex * header->itemSize; | ||||||
|  | 
 | ||||||
|  | 		u32 numBytesToShift = endOfListByteOffset - oneAfterRemoveByteOffset; | ||||||
|  | 		DQN_ASSERT(numBytesToShift <= (header->itemSize * header->capacity)); | ||||||
|  | 
 | ||||||
|  | 		u8 *dataPtr = (u8 *)header->data; | ||||||
|  | 		void *dest  = (void *)&dataPtr[removeEntryByteOffset]; | ||||||
|  | 		void *src   = (void *)&dataPtr[oneAfterRemoveByteOffset]; | ||||||
|  | 		memmove(dest, src, endOfListByteOffset); | ||||||
|  | 
 | ||||||
|  | 		header->index--; | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| DQN_FILE_SCOPE inline bool dqn_darray_free(void *array) | DQN_FILE_SCOPE inline bool dqn_darray_free(void *array) | ||||||
| { | { | ||||||
| 	DqnDArrayInternal *header = dqn_darray_get_header_internal(array); | 	DqnDArrayHeader *header = dqn_darray_get_header(array); | ||||||
| 	if (header) | 	if (header) | ||||||
| 	{ | 	{ | ||||||
| 		header->index     = 0; | 		header->index     = 0; | ||||||
| @ -1224,8 +1389,7 @@ DQN_FILE_SCOPE u32 dqn_utf8_to_ucs(u32 *dest, u32 character) | |||||||
| #ifdef DQN_WIN32 | #ifdef DQN_WIN32 | ||||||
| 	#define DQN_WIN32_ERROR_BOX(text, title) MessageBoxA(NULL, text, title, MB_OK); | 	#define DQN_WIN32_ERROR_BOX(text, title) MessageBoxA(NULL, text, title, MB_OK); | ||||||
| 
 | 
 | ||||||
| FILE_SCOPE bool dqn_win32_utf8_to_wchar_internal(char *in, wchar_t *out, | DQN_FILE_SCOPE bool dqn_win32_utf8_to_wchar(char *in, wchar_t *out, i32 outLen) | ||||||
|                                                   i32 outLen) |  | ||||||
| { | { | ||||||
| 	u32 result = MultiByteToWideChar(CP_UTF8, 0, in, -1, out, outLen-1); | 	u32 result = MultiByteToWideChar(CP_UTF8, 0, in, -1, out, outLen-1); | ||||||
| 
 | 
 | ||||||
| @ -1238,8 +1402,7 @@ FILE_SCOPE bool dqn_win32_utf8_to_wchar_internal(char *in, wchar_t *out, | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| FILE_SCOPE bool dqn_win32_wchar_to_utf8_internal(wchar_t *in, char *out, | DQN_FILE_SCOPE bool dqn_win32_wchar_to_utf8(wchar_t *in, char *out, i32 outLen) | ||||||
|                                                   i32 outLen) |  | ||||||
| { | { | ||||||
| 	u32 result = | 	u32 result = | ||||||
| 	    WideCharToMultiByte(CP_UTF8, 0, in, -1, out, outLen, NULL, NULL); | 	    WideCharToMultiByte(CP_UTF8, 0, in, -1, out, outLen, NULL, NULL); | ||||||
| @ -1260,8 +1423,7 @@ DQN_FILE_SCOPE bool dqn_file_open(char *const path, DqnFile *file) | |||||||
| 
 | 
 | ||||||
| #ifdef DQN_WIN32 | #ifdef DQN_WIN32 | ||||||
| 	wchar_t widePath[MAX_PATH] = {}; | 	wchar_t widePath[MAX_PATH] = {}; | ||||||
| 	dqn_win32_utf8_to_wchar_internal(path, widePath, | 	dqn_win32_utf8_to_wchar(path, widePath, DQN_ARRAY_COUNT(widePath)); | ||||||
| 	                                  DQN_ARRAY_COUNT(widePath)); |  | ||||||
| 
 | 
 | ||||||
| 	HANDLE handle = CreateFileW(widePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, | 	HANDLE handle = CreateFileW(widePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, | ||||||
| 	                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | 	                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | ||||||
| @ -1333,7 +1495,7 @@ DQN_FILE_SCOPE char **dqn_dir_read(char *dir, u32 *numFiles) | |||||||
| 
 | 
 | ||||||
| 	u32 currNumFiles = 0; | 	u32 currNumFiles = 0; | ||||||
| 	wchar_t wideDir[MAX_PATH] = {}; | 	wchar_t wideDir[MAX_PATH] = {}; | ||||||
| 	dqn_win32_utf8_to_wchar_internal(dir, wideDir, DQN_ARRAY_COUNT(wideDir)); | 	dqn_win32_utf8_to_wchar(dir, wideDir, DQN_ARRAY_COUNT(wideDir)); | ||||||
| 
 | 
 | ||||||
| 	// Enumerate number of files first
 | 	// Enumerate number of files first
 | ||||||
| 	{ | 	{ | ||||||
| @ -1388,8 +1550,8 @@ DQN_FILE_SCOPE char **dqn_dir_read(char *dir, u32 *numFiles) | |||||||
| 		WIN32_FIND_DATAW findData = {}; | 		WIN32_FIND_DATAW findData = {}; | ||||||
| 		while (FindNextFileW(findHandle, &findData) != 0) | 		while (FindNextFileW(findHandle, &findData) != 0) | ||||||
| 		{ | 		{ | ||||||
| 			dqn_win32_wchar_to_utf8_internal( | 			dqn_win32_wchar_to_utf8(findData.cFileName, list[listIndex++], | ||||||
| 			    findData.cFileName, list[listIndex++], MAX_PATH); | 			                        MAX_PATH); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		*numFiles = currNumFiles; | 		*numFiles = currNumFiles; | ||||||
| @ -1430,9 +1592,9 @@ inline FILE_SCOPE f64 dqn_win32_query_perf_counter_time_in_s_internal() | |||||||
| 	LARGE_INTEGER qpcResult; | 	LARGE_INTEGER qpcResult; | ||||||
| 	QueryPerformanceCounter(&qpcResult); | 	QueryPerformanceCounter(&qpcResult); | ||||||
| 
 | 
 | ||||||
| 	// Convert to seconds
 | 	// Convert to ms
 | ||||||
| 	f64 timestamp = | 	f64 timestamp = | ||||||
| 	    (f64)(qpcResult.QuadPart / queryPerformanceFrequency.QuadPart); | 	    qpcResult.QuadPart / (f64)queryPerformanceFrequency.QuadPart; | ||||||
| 	return timestamp; | 	return timestamp; | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -561,24 +561,19 @@ void dqn_darray_test() | |||||||
| 		// Test basic insert
 | 		// Test basic insert
 | ||||||
| 		{ | 		{ | ||||||
| 			DqnV2 va = dqn_v2(5, 10); | 			DqnV2 va = dqn_v2(5, 10); | ||||||
| 			DQN_ASSERT(DQN_DARRAY_PUSH(&vecDArray, &va)); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 
 | 
 | ||||||
| 			DqnV2 vb = vecDArray[0]; | 			DqnV2 vb = vecDArray[0]; | ||||||
| 			DQN_ASSERT(dqn_v2_equals(va, vb)); | 			DQN_ASSERT(dqn_v2_equals(va, vb)); | ||||||
| 
 | 
 | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 1); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 1); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 1); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 1); | ||||||
| 
 |  | ||||||
| 			DqnV2 *empty = NULL; |  | ||||||
| 			DQN_ASSERT(DQN_DARRAY_PUSH(NULL, empty) == false); |  | ||||||
| 			DQN_ASSERT(DQN_DARRAY_PUSH(NULL, &va) == false); |  | ||||||
| 			DQN_ASSERT(DQN_DARRAY_PUSH(&vecDArray, empty) == false); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// Test array resizing and freeing
 | 		// Test array resizing and freeing
 | ||||||
| 		{ | 		{ | ||||||
| 			DqnV2 va = dqn_v2(10, 15); | 			DqnV2 va = dqn_v2(10, 15); | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &va); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 
 | 
 | ||||||
| 			DqnV2 vb = vecDArray[0]; | 			DqnV2 vb = vecDArray[0]; | ||||||
| 			DQN_ASSERT(dqn_v2_equals(va, vb) == false); | 			DQN_ASSERT(dqn_v2_equals(va, vb) == false); | ||||||
| @ -589,44 +584,44 @@ void dqn_darray_test() | |||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 2); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 2); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 2); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 2); | ||||||
| 
 | 
 | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &va); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 3); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 3); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 3); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 3); | ||||||
| 
 | 
 | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &va); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 4); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 4); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 4); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 4); | ||||||
| 
 | 
 | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &va); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 5); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 5); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 5); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 5); | ||||||
| 
 | 
 | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &va); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 6); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 6); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 6); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 6); | ||||||
| 
 | 
 | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &va); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 7); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 7); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 7); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 7); | ||||||
| 
 | 
 | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &va); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 8); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 8); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 8); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 8); | ||||||
| 
 | 
 | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &va); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 9); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 9); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 9); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 9); | ||||||
| 
 | 
 | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &va); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 10); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 10); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 10); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 10); | ||||||
| 
 | 
 | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &va); | 			DQN_DARRAY_PUSH(&vecDArray, va); | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 12); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 12); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 11); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 11); | ||||||
| 
 | 
 | ||||||
| 			DqnV2 vc = dqn_v2(90, 100); | 			DqnV2 vc = dqn_v2(90, 100); | ||||||
| 			DQN_DARRAY_PUSH(&vecDArray, &vc); | 			DQN_DARRAY_PUSH(&vecDArray, vc); | ||||||
| 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 12); | 			DQN_ASSERT(dqn_darray_get_capacity(vecDArray) == 12); | ||||||
| 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 12); | 			DQN_ASSERT(dqn_darray_get_num_items(vecDArray) == 12); | ||||||
| 			DQN_ASSERT(dqn_v2_equals(vc, vecDArray[11])); | 			DQN_ASSERT(dqn_v2_equals(vc, vecDArray[11])); | ||||||
| @ -641,11 +636,101 @@ void dqn_darray_test() | |||||||
| 		DQN_ASSERT(dqn_darray_get_capacity(array) == 1); | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 1); | ||||||
| 		DQN_ASSERT(dqn_darray_get_num_items(array) == 0); | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 0); | ||||||
| 
 | 
 | ||||||
| 		f32 *empty = NULL; | 		dqn_darray_free(array); | ||||||
| 		DQN_ASSERT(DQN_DARRAY_PUSH(NULL, empty) == false); |  | ||||||
| 		DQN_ASSERT(DQN_DARRAY_PUSH(&array, empty) == false); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	{ | ||||||
|  | 		DqnV2 a = dqn_v2(1, 2); | ||||||
|  | 		DqnV2 b = dqn_v2(3, 4); | ||||||
|  | 		DqnV2 c = dqn_v2(5, 6); | ||||||
|  | 		DqnV2 d = dqn_v2(7, 8); | ||||||
|  | 
 | ||||||
|  | 		DqnV2 *array = DQN_DARRAY_INIT(DqnV2, 16); | ||||||
|  | 		DQN_ASSERT(array); | ||||||
|  | 		DQN_ASSERT(dqn_darray_remove(array, 0) == false); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 0); | ||||||
|  | 
 | ||||||
|  | 		DQN_ASSERT(dqn_darray_clear(array)); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 0); | ||||||
|  | 
 | ||||||
|  | 		DQN_DARRAY_PUSH(&array, a); | ||||||
|  | 		DQN_DARRAY_PUSH(&array, b); | ||||||
|  | 		DQN_DARRAY_PUSH(&array, c); | ||||||
|  | 		DQN_DARRAY_PUSH(&array, d); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 4); | ||||||
|  | 
 | ||||||
|  | 		DQN_ASSERT(dqn_darray_remove(array, 0)); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[0], d)); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[1], b)); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[2], c)); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 3); | ||||||
|  | 
 | ||||||
|  | 		DQN_ASSERT(dqn_darray_remove(array, 2)); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[0], d)); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[1], b)); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 2); | ||||||
|  | 
 | ||||||
|  | 		DQN_ASSERT(dqn_darray_remove(array, 100) == false); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[0], d)); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[1], b)); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 2); | ||||||
|  | 
 | ||||||
|  | 		DQN_ASSERT(dqn_darray_clear(array)); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 0); | ||||||
|  | 
 | ||||||
|  | 		dqn_darray_free(array); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	{ | ||||||
|  | 		DqnV2 a = dqn_v2(1, 2); | ||||||
|  | 		DqnV2 b = dqn_v2(3, 4); | ||||||
|  | 		DqnV2 c = dqn_v2(5, 6); | ||||||
|  | 		DqnV2 d = dqn_v2(7, 8); | ||||||
|  | 
 | ||||||
|  | 		DqnV2 *array = DQN_DARRAY_INIT(DqnV2, 16); | ||||||
|  | 		DQN_ASSERT(array); | ||||||
|  | 
 | ||||||
|  | 		DQN_DARRAY_PUSH(&array, a); | ||||||
|  | 		DQN_DARRAY_PUSH(&array, b); | ||||||
|  | 		DQN_DARRAY_PUSH(&array, c); | ||||||
|  | 		DQN_DARRAY_PUSH(&array, d); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 4); | ||||||
|  | 
 | ||||||
|  | 		dqn_darray_remove_stable(array, 0); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[0], b)); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[1], c)); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[2], d)); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 3); | ||||||
|  | 
 | ||||||
|  | 		dqn_darray_remove_stable(array, 1); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[0], b)); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[1], d)); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 2); | ||||||
|  | 
 | ||||||
|  | 		dqn_darray_remove_stable(array, 1); | ||||||
|  | 		DQN_ASSERT(dqn_v2_equals(array[0], b)); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_capacity(array) == 16); | ||||||
|  | 		DQN_ASSERT(dqn_darray_get_num_items(array) == 1); | ||||||
|  | 		dqn_darray_free(array); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	{ | ||||||
|  | 		DQN_ASSERT(dqn_darray_clear(NULL) == false); | ||||||
|  | 		DQN_ASSERT(dqn_darray_clear(NULL) == false); | ||||||
|  | 		DQN_ASSERT(dqn_darray_free(NULL) == false); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 	printf("dqn_darray_test(): Completed successfully\n"); | 	printf("dqn_darray_test(): Completed successfully\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -21,7 +21,7 @@ Global | |||||||
| 		Release|x86 = Release|x86 | 		Release|x86 = Release|x86 | ||||||
| 	EndGlobalSection | 	EndGlobalSection | ||||||
| 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||||
| 		{87785192-6F49-4F85-AA0D-F0AFA5CCCDDA}.Release|x86.ActiveCfg = Release | 		{87785192-6F49-4F85-AA0D-F0AFA5CCCDDA}.Release|x86.ActiveCfg = Release|x86 | ||||||
| 	EndGlobalSection | 	EndGlobalSection | ||||||
| 	GlobalSection(SolutionProperties) = preSolution | 	GlobalSection(SolutionProperties) = preSolution | ||||||
| 		HideSolutionNode = FALSE | 		HideSolutionNode = FALSE | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user