Add file write tests and delete functionality
This commit is contained in:
parent
93bbc25b11
commit
84149d0ad1
31
dqn.h
31
dqn.h
@ -801,7 +801,6 @@ DQN_FILE_SCOPE u32 DqnRnd_PCGNext (DqnRandPCGState *pcg);
|
|||||||
DQN_FILE_SCOPE f32 DqnRnd_PCGNextf(DqnRandPCGState *pcg);
|
DQN_FILE_SCOPE f32 DqnRnd_PCGNextf(DqnRandPCGState *pcg);
|
||||||
// Returns a random integer N between [min, max]
|
// Returns a random integer N between [min, max]
|
||||||
DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max);
|
DQN_FILE_SCOPE i32 DqnRnd_PCGRange(DqnRandPCGState *pcg, i32 min, i32 max);
|
||||||
|
|
||||||
#endif /* DQN_H */
|
#endif /* DQN_H */
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -817,6 +816,7 @@ 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 <unistd.h> // unlink()
|
||||||
#include <stdio.h> // Basic File I/O
|
#include <stdio.h> // Basic File I/O
|
||||||
#include <dirent.h> // readdir()/opendir()/closedir()
|
#include <dirent.h> // readdir()/opendir()/closedir()
|
||||||
#endif
|
#endif
|
||||||
@ -854,6 +854,7 @@ typedef struct DqnFile
|
|||||||
u32 permissionFlags;
|
u32 permissionFlags;
|
||||||
} DqnFile;
|
} DqnFile;
|
||||||
|
|
||||||
|
// NOTE: W(ide) versions of functions only work on Win32, since Unix is UTF-8 compatible.
|
||||||
// Open a handle to the file
|
// Open a handle to the file
|
||||||
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);
|
||||||
@ -864,6 +865,10 @@ DQN_FILE_SCOPE size_t DqnFile_Write(const DqnFile *const file, u8 *const buffer,
|
|||||||
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);
|
||||||
DQN_FILE_SCOPE void DqnFile_Close(DqnFile *const file);
|
DQN_FILE_SCOPE void DqnFile_Close(DqnFile *const file);
|
||||||
|
|
||||||
|
// NOTE: You can't delete a file unless the handle has been closed to it on Win32.
|
||||||
|
DQN_FILE_SCOPE bool DqnFile_Delete (const char *const path);
|
||||||
|
DQN_FILE_SCOPE bool DqnFile_DeleteW(const wchar_t *const path);
|
||||||
|
|
||||||
// Return an array of strings of the files in the directory in UTF-8. numFiles
|
// Return an array of strings of the files in the directory in UTF-8. numFiles
|
||||||
// returns the number of strings read.
|
// returns the number of strings read.
|
||||||
// This is allocated using malloc and MUST BE FREED! Can be done manually or
|
// This is allocated using malloc and MUST BE FREED! Can be done manually or
|
||||||
@ -1704,9 +1709,10 @@ DQN_FILE_SCOPE bool DqnMemStack_Pop(DqnMemStack *const stack, void *ptr, size_t
|
|||||||
"'ptr' to pop does not belong to current memStack attached block"))
|
"'ptr' to pop does not belong to current memStack attached block"))
|
||||||
{
|
{
|
||||||
size_t calcSize = (size_t)currPtr - (size_t)ptr;
|
size_t calcSize = (size_t)currPtr - (size_t)ptr;
|
||||||
if (DQN_ASSERT_MSG(calcSize == size, "'ptr' was not the last item allocated to memStack"))
|
size_t sizeAligned = DQN_ALIGN_POW_N(size, stack->byteAlign);
|
||||||
|
if (DQN_ASSERT_MSG(calcSize == sizeAligned, "'ptr' was not the last item allocated to memStack"))
|
||||||
{
|
{
|
||||||
stack->block->used -= size;
|
stack->block->used -= sizeAligned;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3878,7 +3884,7 @@ DQN_FILE_SCOPE size_t DqnFile_Write(const DqnFile *const file,
|
|||||||
{
|
{
|
||||||
size_t numBytesWritten = 0;
|
size_t numBytesWritten = 0;
|
||||||
// TODO(doyle): Implement when it's needed
|
// TODO(doyle): Implement when it's needed
|
||||||
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;
|
||||||
|
|
||||||
#if defined(DQN_WIN32_PLATFORM)
|
#if defined(DQN_WIN32_PLATFORM)
|
||||||
@ -3963,6 +3969,23 @@ DQN_FILE_SCOPE void DqnFile_Close(DqnFile *const file)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DQN_FILE_SCOPE bool DqnFile_Delete(const char *const path)
|
||||||
|
{
|
||||||
|
if (!path) return false;
|
||||||
|
|
||||||
|
// TODO(doyle): Logging
|
||||||
|
#if defined(DQN_WIN32_PLATFORM)
|
||||||
|
return DeleteFile(path);
|
||||||
|
|
||||||
|
#elif defined(DQN_UNIX_PLATFORM)
|
||||||
|
i32 result = unlink(path);
|
||||||
|
|
||||||
|
if (result == 0) return true;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
char **result = DqnDirInternal_PlatformRead(dir, numFiles);
|
char **result = DqnDirInternal_PlatformRead(dir, numFiles);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#if (defined(_WIN32) || defined(_WIN64))
|
#if (defined(_WIN32) || defined(_WIN64))
|
||||||
#define DQN_WIN32_IMPLEMENTATION
|
#define DQN_WIN32_IMPLEMENTATION
|
||||||
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
@ -1445,21 +1446,46 @@ void FileTest()
|
|||||||
{
|
{
|
||||||
// File i/o
|
// File i/o
|
||||||
{
|
{
|
||||||
{
|
|
||||||
DqnFile file = {};
|
|
||||||
DQN_ASSERT(DqnFile_Open(
|
|
||||||
".clang-format", &file,
|
|
||||||
(DqnFilePermissionFlag_Write | DqnFilePermissionFlag_Read),
|
|
||||||
DqnFileAction_OpenOnly));
|
|
||||||
|
|
||||||
|
// Test file open
|
||||||
|
{
|
||||||
|
const char *const FILE_TO_OPEN = ".clang-format";
|
||||||
|
u32 expectedSize = 0;
|
||||||
#if defined(DQN_UNIX_IMPLEMENTATION)
|
#if defined(DQN_UNIX_IMPLEMENTATION)
|
||||||
const u32 EXPECTED_SIZE = 1274;
|
{
|
||||||
|
struct stat fileStat = {0};
|
||||||
|
DQN_ASSERT(stat(FILE_TO_OPEN, &fileStat) == 0);
|
||||||
|
expectedSize = fileStat.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined(DQN_WIN32_IMPLEMENTATION)
|
#elif defined(DQN_WIN32_IMPLEMENTATION)
|
||||||
const u32 EXPECTED_SIZE = 1320;
|
{
|
||||||
|
HANDLE handle =
|
||||||
|
CreateFile(FILE_TO_OPEN, GENERIC_READ, 0, NULL,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
DqnWin32_DisplayLastError("CreateFile() failed");
|
||||||
|
}
|
||||||
|
DQN_ASSERT(handle != INVALID_HANDLE_VALUE);
|
||||||
|
|
||||||
|
LARGE_INTEGER size;
|
||||||
|
DQN_ASSERT(GetFileSizeEx(handle, &size));
|
||||||
|
|
||||||
|
CloseHandle(handle);
|
||||||
|
expectedSize = size.LowPart;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
DQN_ASSERT_MSG(file.size == EXPECTED_SIZE,
|
|
||||||
|
DqnFile file = {};
|
||||||
|
DQN_ASSERT(DqnFile_Open(
|
||||||
|
".clang-format", &file,
|
||||||
|
(DqnFilePermissionFlag_Write | DqnFilePermissionFlag_Read),
|
||||||
|
DqnFileAction_OpenOnly));
|
||||||
|
|
||||||
|
DQN_ASSERT_MSG(file.size == expectedSize,
|
||||||
"DqnFileOpen() failed: file.size: %d, expected:%d\n",
|
"DqnFileOpen() failed: file.size: %d, expected:%d\n",
|
||||||
file.size, EXPECTED_SIZE);
|
file.size, expectedSize);
|
||||||
|
|
||||||
u8 *buffer = (u8 *)calloc(1, (size_t)file.size * sizeof(u8));
|
u8 *buffer = (u8 *)calloc(1, (size_t)file.size * sizeof(u8));
|
||||||
DQN_ASSERT(DqnFile_Read(file, buffer, (u32)file.size) == file.size);
|
DQN_ASSERT(DqnFile_Read(file, buffer, (u32)file.size) == file.size);
|
||||||
@ -1470,6 +1496,7 @@ void FileTest()
|
|||||||
file.permissionFlags == 0);
|
file.permissionFlags == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test invalid file
|
||||||
{
|
{
|
||||||
DqnFile file = {};
|
DqnFile file = {};
|
||||||
DQN_ASSERT(!DqnFile_Open(
|
DQN_ASSERT(!DqnFile_Open(
|
||||||
@ -1482,10 +1509,77 @@ void FileTest()
|
|||||||
printf("FileTest(): FileIO: Completed successfully\n");
|
printf("FileTest(): FileIO: Completed successfully\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(doyle): Write tests for writing out to file
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Write Test
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
{
|
{
|
||||||
|
const char *fileNames[] = {"dqn_1", "dqn_2", "dqn_3", "dqn_4", "dqn_5"};
|
||||||
|
const char *writeData[] = {"1234", "2468", "36912", "481216",
|
||||||
|
"5101520"};
|
||||||
|
DqnFile files[DQN_ARRAY_COUNT(fileNames)] = {};
|
||||||
|
|
||||||
|
// Write data out to some files
|
||||||
|
for (u32 i = 0; i < DQN_ARRAY_COUNT(fileNames); i++)
|
||||||
|
{
|
||||||
|
u32 permissions =
|
||||||
|
DqnFilePermissionFlag_Read | DqnFilePermissionFlag_Write;
|
||||||
|
if (!DqnFile_Open(fileNames[i], files + i, permissions,
|
||||||
|
DqnFileAction_ClearIfExist))
|
||||||
|
{
|
||||||
|
bool result = DqnFile_Open(fileNames[i], files + i, permissions,
|
||||||
|
DqnFileAction_CreateIfNotExist);
|
||||||
|
DQN_ASSERT(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t bytesToWrite = DqnStr_Len(writeData[i]);
|
||||||
|
u8 *dataToWrite = (u8 *)(writeData[i]);
|
||||||
|
size_t bytesWritten = DqnFile_Write(files + i, dataToWrite, bytesToWrite, 0);
|
||||||
|
DQN_ASSERT(bytesWritten == bytesToWrite);
|
||||||
|
DqnFile_Close(&files[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
DqnMemStack memStack = {};
|
||||||
|
DQN_ASSERT(DqnMemStack_Init(&memStack, DQN_MEGABYTE(1), true));
|
||||||
|
// Read data back in
|
||||||
|
for (u32 i = 0; i < DQN_ARRAY_COUNT(fileNames); i++)
|
||||||
|
{
|
||||||
|
u32 permissions = DqnFilePermissionFlag_Read;
|
||||||
|
DqnFile *file = files + i;
|
||||||
|
bool result = DqnFile_Open(fileNames[i], file, permissions,
|
||||||
|
DqnFileAction_OpenOnly);
|
||||||
|
DQN_ASSERT(result);
|
||||||
|
|
||||||
|
u8 *buffer = (u8 *)DqnMemStack_Push(&memStack, file->size);
|
||||||
|
DQN_ASSERT(buffer);
|
||||||
|
|
||||||
|
size_t bytesRead = DqnFile_Read(files[i], buffer, file->size);
|
||||||
|
DQN_ASSERT(bytesRead == file->size);
|
||||||
|
|
||||||
|
// Verify the data is the same as we wrote out
|
||||||
|
DQN_ASSERT(DqnStr_Cmp((char *)buffer, (writeData[i])) == 0);
|
||||||
|
|
||||||
|
// Delete when we're done with it
|
||||||
|
DQN_ASSERT(DqnMemStack_Pop(&memStack, buffer, file->size));
|
||||||
|
DqnFile_Close(file);
|
||||||
|
|
||||||
|
DQN_ASSERT(DqnFile_Delete(fileNames[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then check delete actually worked, files should not exist.
|
||||||
|
for (u32 i = 0; i < DQN_ARRAY_COUNT(fileNames); i++)
|
||||||
|
{
|
||||||
|
DqnFile dummy = {};
|
||||||
|
u32 permissions = DqnFilePermissionFlag_Read;
|
||||||
|
bool fileExists = DqnFile_Open(fileNames[i], &dummy, permissions,
|
||||||
|
DqnFileAction_OpenOnly);
|
||||||
|
DQN_ASSERT(!fileExists);
|
||||||
|
}
|
||||||
|
DqnMemStack_Free(&memStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
u32 numFiles;
|
u32 numFiles;
|
||||||
#if defined(DQN_UNIX_IMPLEMENTATION)
|
#if defined(DQN_UNIX_IMPLEMENTATION)
|
||||||
char **filelist = DqnDir_Read(".", &numFiles);
|
char **filelist = DqnDir_Read(".", &numFiles);
|
||||||
@ -1559,6 +1653,10 @@ FILE_SCOPE void JobQueueTest()
|
|||||||
for (i32 i = 0; i < DQN_ARRAY_COUNT(globalDebugCounterMemoize); i++)
|
for (i32 i = 0; i < DQN_ARRAY_COUNT(globalDebugCounterMemoize); i++)
|
||||||
DQN_ASSERT(globalDebugCounterMemoize[i]);
|
DQN_ASSERT(globalDebugCounterMemoize[i]);
|
||||||
|
|
||||||
|
while (DqnJobQueue_TryExecuteNextJob(jobQueue) &&
|
||||||
|
!DqnJobQueue_AllJobsComplete(jobQueue))
|
||||||
|
;
|
||||||
|
|
||||||
printf("\nJobQueueTest(): Final incremented value: %d\n", globalDebugCounter);
|
printf("\nJobQueueTest(): Final incremented value: %d\n", globalDebugCounter);
|
||||||
DQN_ASSERT(globalDebugCounter == DQN_ARRAY_COUNT(globalDebugCounterMemoize));
|
DQN_ASSERT(globalDebugCounter == DQN_ARRAY_COUNT(globalDebugCounterMemoize));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user