Implement dir read/free and file write in Unix
This commit is contained in:
		
							parent
							
								
									245e6b11f1
								
							
						
					
					
						commit
						a067fed81f
					
				
							
								
								
									
										283
									
								
								dqn.h
									
									
									
									
									
								
							
							
						
						
									
										283
									
								
								dqn.h
									
									
									
									
									
								
							| @ -817,6 +817,8 @@ DQN_FILE_SCOPE i32  DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max); | |||||||
| 
 | 
 | ||||||
| #ifdef DQN_UNIX_PLATFORM | #ifdef DQN_UNIX_PLATFORM | ||||||
| 	#include <sys/stat.h> | 	#include <sys/stat.h> | ||||||
|  | 	#include <stdio.h>    // Basic File I/O | ||||||
|  | 	#include <dirent.h>   // readdir()/opendir()/closedir() | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| @ -856,7 +858,7 @@ typedef struct DqnFile | |||||||
| DQN_FILE_SCOPE bool   DqnFile_Open (const char *const path, DqnFile *const file, const u32 permissionFlags, const enum DqnFileAction action); | DQN_FILE_SCOPE bool   DqnFile_Open (const char *const path, DqnFile *const file, const u32 permissionFlags, const enum DqnFileAction action); | ||||||
| DQN_FILE_SCOPE bool   DqnFile_OpenW(const wchar_t *const path, DqnFile *const file, const u32 permissionFlags, const enum DqnFileAction action); | DQN_FILE_SCOPE bool   DqnFile_OpenW(const wchar_t *const path, DqnFile *const file, const u32 permissionFlags, const enum DqnFileAction action); | ||||||
| // File offset is the byte offset to starting writing from
 | // File offset is the byte offset to starting writing from
 | ||||||
| DQN_FILE_SCOPE size_t DqnFile_Write(const DqnFile *const file, const u8 *const buffer, const size_t numBytesToWrite, const size_t fileOffset); | DQN_FILE_SCOPE size_t DqnFile_Write(const DqnFile *const file, u8 *const buffer, const size_t numBytesToWrite, const size_t fileOffset); | ||||||
| 
 | 
 | ||||||
| // Return the number of bytes read
 | // Return the number of bytes read
 | ||||||
| DQN_FILE_SCOPE size_t DqnFile_Read (const DqnFile file, u8 *const buffer, const size_t numBytesToRead); | DQN_FILE_SCOPE size_t DqnFile_Read (const DqnFile file, u8 *const buffer, const size_t numBytesToRead); | ||||||
| @ -1477,7 +1479,7 @@ STBSP__PUBLICDEF void STB_SPRINTF_DECORATE(set_separators)(char comma, char peri | |||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| #include <math.h>    // TODO(doyle): For trigonometry functions (for now) | #include <math.h>    // TODO(doyle): For trigonometry functions (for now) | ||||||
| #include <stdlib.h>    // For calloc, malloc, free | #include <stdlib.h>    // For calloc, malloc, free | ||||||
| #include <stdio.h>     // For printf, portable file io | #include <stdio.h>     // For printf | ||||||
| #include <x86intrin.h> // __rdtsc | #include <x86intrin.h> // __rdtsc | ||||||
| 
 | 
 | ||||||
| // NOTE: STB_SPRINTF is included when DQN_IMPLEMENTATION defined
 | // NOTE: STB_SPRINTF is included when DQN_IMPLEMENTATION defined
 | ||||||
| @ -3593,6 +3595,102 @@ FILE_SCOPE bool DqnFileInternal_Win32OpenW(const wchar_t *const path, | |||||||
| 	file->permissionFlags = permissionFlags; | 	file->permissionFlags = permissionFlags; | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE char **DqnDirInternal_PlatformRead(const char *const dir, | ||||||
|  |                                                   u32 *const numFiles) | ||||||
|  | { | ||||||
|  | 	if (!dir || !numFiles) return NULL; | ||||||
|  | 
 | ||||||
|  | 	u32 currNumFiles = 0; | ||||||
|  | 	wchar_t wideDir[MAX_PATH] = {0}; | ||||||
|  | 	DqnWin32_UTF8ToWChar(dir, wideDir, DQN_ARRAY_COUNT(wideDir)); | ||||||
|  | 
 | ||||||
|  | 	// Enumerate number of files first
 | ||||||
|  | 	{ | ||||||
|  | 		WIN32_FIND_DATAW findData = {0}; | ||||||
|  | 		HANDLE findHandle = FindFirstFileW(wideDir, &findData); | ||||||
|  | 		if (findHandle == INVALID_HANDLE_VALUE) | ||||||
|  | 		{ | ||||||
|  | 			DQN_WIN32_ERROR_BOX("FindFirstFile() failed.", NULL); | ||||||
|  | 			return NULL; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		bool stayInLoop = true; | ||||||
|  | 		while (stayInLoop) | ||||||
|  | 		{ | ||||||
|  | 			BOOL result = FindNextFileW(findHandle, &findData); | ||||||
|  | 			if (result == 0) | ||||||
|  | 			{ | ||||||
|  | 				DWORD error = GetLastError(); | ||||||
|  | 				if (error != ERROR_NO_MORE_FILES) | ||||||
|  | 				{ | ||||||
|  | 					DqnWin32_DisplayErrorCode(error, | ||||||
|  | 					                             "FindNextFileW() failed"); | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				stayInLoop = false; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 				currNumFiles++; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		FindClose(findHandle); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (currNumFiles == 0) | ||||||
|  | 	{ | ||||||
|  | 		*numFiles = 0; | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	{ | ||||||
|  | 		WIN32_FIND_DATAW initFind = {0}; | ||||||
|  | 		HANDLE findHandle = FindFirstFileW(wideDir, &initFind); | ||||||
|  | 		if (findHandle == INVALID_HANDLE_VALUE) | ||||||
|  | 		{ | ||||||
|  | 			DQN_WIN32_ERROR_BOX("FindFirstFile() failed.", NULL); | ||||||
|  | 			*numFiles = 0; | ||||||
|  | 			return NULL; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		char **list = (char **)DqnMem_Calloc( | ||||||
|  | 		    sizeof(*list) * (currNumFiles)); | ||||||
|  | 		if (!list) | ||||||
|  | 		{ | ||||||
|  | 			DQN_WIN32_ERROR_BOX("DqnMem_Alloc() failed.", NULL); | ||||||
|  | 			*numFiles = 0; | ||||||
|  | 			return NULL; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for (u32 i = 0; i < currNumFiles; i++) | ||||||
|  | 		{ | ||||||
|  | 			list[i] = (char *)DqnMem_Calloc(sizeof(**list) * MAX_PATH); | ||||||
|  | 			if (!list[i]) | ||||||
|  | 			{ | ||||||
|  | 				for (u32 j = 0; j < i; j++) | ||||||
|  | 					DqnMem_Free(list[j]); | ||||||
|  | 
 | ||||||
|  | 				DQN_WIN32_ERROR_BOX("DqnMem_Alloc() failed.", NULL); | ||||||
|  | 				*numFiles = 0; | ||||||
|  | 				return NULL; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		i32 listIndex = 0; | ||||||
|  | 		WIN32_FIND_DATAW findData = {0}; | ||||||
|  | 		while (FindNextFileW(findHandle, &findData) != 0) | ||||||
|  | 		{ | ||||||
|  | 			DqnWin32_WCharToUTF8(findData.cFileName, list[listIndex++], | ||||||
|  | 			                        MAX_PATH); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		*numFiles = currNumFiles; | ||||||
|  | 		FindClose(findHandle); | ||||||
|  | 
 | ||||||
|  | 		return list; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| #endif // DQN_WIN32_PLATFORM
 | #endif // DQN_WIN32_PLATFORM
 | ||||||
| 
 | 
 | ||||||
| #ifdef DQN_UNIX_PLATFORM | #ifdef DQN_UNIX_PLATFORM | ||||||
| @ -3662,7 +3760,75 @@ FILE_SCOPE bool DqnFileInternal_UnixOpen(const char *const path, | |||||||
| 
 | 
 | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| #endif | 
 | ||||||
|  | DQN_FILE_SCOPE char **DqnDirInternal_PlatformRead(const char *const dir, | ||||||
|  |                                                   u32 *const numFiles) | ||||||
|  | { | ||||||
|  | 	if (!dir || !numFiles) return NULL; | ||||||
|  | 
 | ||||||
|  | 	// Enumerate num files
 | ||||||
|  | 	u32 currNumFiles = 0; | ||||||
|  | 	{ | ||||||
|  | 		DIR *const dirHandle = opendir(dir); | ||||||
|  | 		if (!dirHandle) return NULL; | ||||||
|  | 
 | ||||||
|  | 		struct dirent *dirFile = readdir(dirHandle); | ||||||
|  | 		while (dirFile) | ||||||
|  | 		{ | ||||||
|  | 			currNumFiles++; | ||||||
|  | 			dirFile = readdir(dirHandle); | ||||||
|  | 		} | ||||||
|  | 		closedir(dirHandle); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (currNumFiles == 0) | ||||||
|  | 	{ | ||||||
|  | 		*numFiles = 0; | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Create file list
 | ||||||
|  | 	{ | ||||||
|  | 		DIR *const dirHandle = opendir(dir); | ||||||
|  | 		if (!dirHandle) return NULL; | ||||||
|  | 
 | ||||||
|  | 		char **list = (char **)DqnMem_Calloc(sizeof(*list) * currNumFiles); | ||||||
|  | 		if (!list) | ||||||
|  | 		{ | ||||||
|  | 			// TODO(doyle): Logging
 | ||||||
|  | 			DQN_ASSERT(DQN_INVALID_CODE_PATH); | ||||||
|  | 			*numFiles = 0; | ||||||
|  | 			return NULL; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		struct dirent *dirFile = readdir(dirHandle); | ||||||
|  | 		for (u32 i = 0; i < currNumFiles; i++) | ||||||
|  | 		{ | ||||||
|  | 			list[i] = (char *)DqnMem_Calloc(sizeof(**list) * | ||||||
|  | 			                                DQN_ARRAY_COUNT(dirFile->d_name)); | ||||||
|  | 			if (!list[i]) | ||||||
|  | 			{ | ||||||
|  | 				for (u32 j = 0; j < i; j++) DqnMem_Free(list[j]); | ||||||
|  | 
 | ||||||
|  | 				// TODO(doyle): Logging
 | ||||||
|  | 				*numFiles = 0; | ||||||
|  | 				return NULL; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		u32 listIndex = 0; | ||||||
|  | 		*numFiles     = currNumFiles; | ||||||
|  | 		while (dirFile) | ||||||
|  | 		{ | ||||||
|  | 			DqnStr_Copy(list[listIndex++], dirFile->d_name, DQN_ARRAY_COUNT(dirFile->d_name)); | ||||||
|  | 			dirFile = readdir(dirHandle); | ||||||
|  | 		} | ||||||
|  | 		closedir(dirHandle); | ||||||
|  | 
 | ||||||
|  | 		return list; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | #endif // DQN_UNIX_PLATFORM
 | ||||||
| 
 | 
 | ||||||
| ////////////////////////////////////////////////////////////////////////////////
 | ////////////////////////////////////////////////////////////////////////////////
 | ||||||
| // DqnFile Implementation
 | // DqnFile Implementation
 | ||||||
| @ -3703,7 +3869,7 @@ bool DqnFile_OpenW(const wchar_t *const path, DqnFile *const file, const u32 per | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE size_t DqnFile_Write(const DqnFile *const file, | DQN_FILE_SCOPE size_t DqnFile_Write(const DqnFile *const file, | ||||||
|                                     const u8 *const buffer, |                                     u8 *const buffer, | ||||||
|                                     const size_t numBytesToWrite, |                                     const size_t numBytesToWrite, | ||||||
|                                     const size_t fileOffset) |                                     const size_t fileOffset) | ||||||
| { | { | ||||||
| @ -3712,7 +3878,7 @@ DQN_FILE_SCOPE size_t DqnFile_Write(const DqnFile *const file, | |||||||
| 	if (DQN_ASSERT_MSG(fileOffset != 0, "'fileOffset' not implemented yet")) return 0; | 	if (DQN_ASSERT_MSG(fileOffset != 0, "'fileOffset' not implemented yet")) return 0; | ||||||
| 	if (!file || !buffer) return numBytesToWrite; | 	if (!file || !buffer) return numBytesToWrite; | ||||||
| 
 | 
 | ||||||
| #ifdef DQN_WIN32_PLATFORM | #if defined(DQN_WIN32_PLATFORM) | ||||||
| 	DWORD bytesToWrite = (DWORD)numBytesToWrite; | 	DWORD bytesToWrite = (DWORD)numBytesToWrite; | ||||||
| 	DWORD bytesWritten; | 	DWORD bytesWritten; | ||||||
| 	BOOL result = | 	BOOL result = | ||||||
| @ -3725,8 +3891,14 @@ DQN_FILE_SCOPE size_t DqnFile_Write(const DqnFile *const file, | |||||||
| 		DQN_WIN32_ERROR_BOX("ReadFile() failed.", NULL); | 		DQN_WIN32_ERROR_BOX("ReadFile() failed.", NULL); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| #else | #elif defined(DQN_UNIX_PLATFORM) | ||||||
| 	DQN_ASSERT_MSG(DQN_INVALID_CODE_PATH, "Non Win32 path not implemented"); | 	const size_t ITEMS_TO_WRITE = 1; | ||||||
|  | 	if (fwrite(buffer, numBytesToWrite, ITEMS_TO_WRITE, (FILE *)file->handle) == | ||||||
|  | 	    ITEMS_TO_WRITE) | ||||||
|  | 	{ | ||||||
|  | 		rewind((FILE *)file->handle); | ||||||
|  | 		numBytesWritten = ITEMS_TO_WRITE * numBytesToWrite; | ||||||
|  | 	} | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	return numBytesWritten; | 	return numBytesWritten; | ||||||
| @ -3790,101 +3962,8 @@ DQN_FILE_SCOPE void DqnFile_Close(DqnFile *const file) | |||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE char **DqnDir_Read(const char *const dir, u32 *const numFiles) | DQN_FILE_SCOPE char **DqnDir_Read(const char *const dir, u32 *const numFiles) | ||||||
| { | { | ||||||
| 	if (!dir) return NULL; | 	char **result = DqnDirInternal_PlatformRead(dir, numFiles); | ||||||
| #ifdef DQN_WIN32_PLATFORM | 	return result; | ||||||
| 
 |  | ||||||
| 	u32 currNumFiles = 0; |  | ||||||
| 	wchar_t wideDir[MAX_PATH] = {0}; |  | ||||||
| 	DqnWin32_UTF8ToWChar(dir, wideDir, DQN_ARRAY_COUNT(wideDir)); |  | ||||||
| 
 |  | ||||||
| 	// Enumerate number of files first
 |  | ||||||
| 	{ |  | ||||||
| 		WIN32_FIND_DATAW findData = {0}; |  | ||||||
| 		HANDLE findHandle = FindFirstFileW(wideDir, &findData); |  | ||||||
| 		if (findHandle == INVALID_HANDLE_VALUE) |  | ||||||
| 		{ |  | ||||||
| 			DQN_WIN32_ERROR_BOX("FindFirstFile() failed.", NULL); |  | ||||||
| 			return NULL; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		bool stayInLoop = true; |  | ||||||
| 		while (stayInLoop) |  | ||||||
| 		{ |  | ||||||
| 			BOOL result = FindNextFileW(findHandle, &findData); |  | ||||||
| 			if (result == 0) |  | ||||||
| 			{ |  | ||||||
| 				DWORD error = GetLastError(); |  | ||||||
| 				if (error != ERROR_NO_MORE_FILES) |  | ||||||
| 				{ |  | ||||||
| 					DqnWin32_DisplayErrorCode(error, |  | ||||||
| 					                             "FindNextFileW() failed"); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				stayInLoop = false; |  | ||||||
| 			} |  | ||||||
| 			else |  | ||||||
| 			{ |  | ||||||
| 				currNumFiles++; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		FindClose(findHandle); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (currNumFiles == 0) |  | ||||||
| 	{ |  | ||||||
| 		*numFiles = 0; |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	{ |  | ||||||
| 		WIN32_FIND_DATAW initFind = {0}; |  | ||||||
| 		HANDLE findHandle = FindFirstFileW(wideDir, &initFind); |  | ||||||
| 		if (findHandle == INVALID_HANDLE_VALUE) |  | ||||||
| 		{ |  | ||||||
| 			DQN_WIN32_ERROR_BOX("FindFirstFile() failed.", NULL); |  | ||||||
| 			return NULL; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		char **list = (char **)DqnMem_Calloc( |  | ||||||
| 		    sizeof(*list) * (currNumFiles)); |  | ||||||
| 		if (!list) |  | ||||||
| 		{ |  | ||||||
| 			DQN_WIN32_ERROR_BOX("DqnMem_Alloc() failed.", NULL); |  | ||||||
| 			return NULL; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		for (u32 i = 0; i < currNumFiles; i++) |  | ||||||
| 		{ |  | ||||||
| 			list[i] = |  | ||||||
| 			    (char *)DqnMem_Calloc(sizeof(**list) * MAX_PATH); |  | ||||||
| 			if (!list[i]) |  | ||||||
| 			{ |  | ||||||
| 				for (u32 j = 0; j < i; j++) |  | ||||||
| 				{ |  | ||||||
| 					DqnMem_Free(list[j]); |  | ||||||
| 				} |  | ||||||
| 
 |  | ||||||
| 				DQN_WIN32_ERROR_BOX("DqnMem_Alloc() failed.", NULL); |  | ||||||
| 				return NULL; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		i32 listIndex = 0; |  | ||||||
| 		WIN32_FIND_DATAW findData = {0}; |  | ||||||
| 		while (FindNextFileW(findHandle, &findData) != 0) |  | ||||||
| 		{ |  | ||||||
| 			DqnWin32_WCharToUTF8(findData.cFileName, list[listIndex++], |  | ||||||
| 			                        MAX_PATH); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		*numFiles = currNumFiles; |  | ||||||
| 		FindClose(findHandle); |  | ||||||
| 
 |  | ||||||
| 		return list; |  | ||||||
| 	} |  | ||||||
| #else |  | ||||||
| 	return NULL; |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE void DqnDir_ReadFree(char **fileList, u32 numFiles) | DQN_FILE_SCOPE void DqnDir_ReadFree(char **fileList, u32 numFiles) | ||||||
|  | |||||||
| @ -1481,13 +1481,18 @@ void FileTest() | |||||||
| 			DQN_ASSERT(!file.handle); | 			DQN_ASSERT(!file.handle); | ||||||
| 			printf("FileTest(): FileIO: Completed successfully\n"); | 			printf("FileTest(): FileIO: Completed successfully\n"); | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		// TODO(doyle): Write tests for writing out to file
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	{ | 	{ | ||||||
| 		u32 numFiles; | 		u32 numFiles; | ||||||
| 		char **filelist = DqnDir_Read("*", &numFiles); | #if defined(DQN_UNIX_IMPLEMENTATION) | ||||||
|  | 	    char **filelist = DqnDir_Read(".", &numFiles); | ||||||
|  | #elif defined(DQN_WIN32_IMPLEMENTATION) | ||||||
|  | 	    char **filelist = DqnDir_Read("*", &numFiles); | ||||||
|  | #endif | ||||||
| 		printf("FileTest(): DirRead: Display read files\n"); | 		printf("FileTest(): DirRead: Display read files\n"); | ||||||
| 
 |  | ||||||
| 		for (u32 i = 0; i < numFiles; i++) | 		for (u32 i = 0; i < numFiles; i++) | ||||||
| 			printf("FileTest(): DirRead: %s\n", filelist[i]); | 			printf("FileTest(): DirRead: %s\n", filelist[i]); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user