EtrediaEmpires/engine/src/FileSystem.cpp

158 lines
3.4 KiB
C++

module;
#include <ee_utils/platform.hpp>
module FileSystem;
import utils;
//TOO: REWORK WITH IOCP
IFileSystem::~IFileSystem()
{
for (FileHandle* handle : activeFiles)
Deallocate(handle);
for (FileHandle* handle : failedFiles)
Deallocate(handle);
}
#ifdef _WIN32
FileHandle& NativeFileSystem::Open(const std::filesystem::path &path, const std::uint32_t flags)
{
FileHandle* result = Allocate<FileHandle>();
#ifndef NDEBUG
result->debugPath = path;
#endif
DWORD createFileMode = 0;
if (flags & FILE_OPEN_READ)
createFileMode |= GENERIC_READ;
if (flags & FILE_OPEN_WRITE)
createFileMode |= GENERIC_WRITE;
HANDLE file = CreateFileW(
path.c_str(),
createFileMode,
NULL,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
if (file == INVALID_HANDLE_VALUE)
{
LOG(ERROR, "Failed to open file %s. Error: %d", path.c_str(), GetLastError());
failedFiles.push_back(result);
return *result;
}
result->win32Handle = file;
result->size = GetFileSize(file, NULL);
if (result->size == INVALID_FILE_SIZE)
LOG(ERROR, "Failed to get size of file %s. Error: %d", path.c_str(), GetLastError());
if (freeFileSlots.size() > 0)
{
std::size_t pos = freeFileSlots.back();
result->id = pos;
activeFiles[pos] = result;
freeFileSlots.pop_back();
}
else
{
result->id = activeFiles.size();
activeFiles.push_back(result);
}
return *result;
}
void NativeFileSystem::ReadAsync(FileHandle &file, const std::uint32_t bufferSize, const std::uint32_t flags)
{
file.overlapped = {
.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)
};
file.buffer = AllocateArray<std::uint8_t>(bufferSize);
file.bufferSize = bufferSize;
BOOL isSync = ReadFile(
file.win32Handle,
file.buffer,
bufferSize,
NULL,
&file.overlapped
);
if (isSync || GetLastError() != ERROR_IO_PENDING)
LOG(ERROR, "File reading is synchronious while asynchronious is awaited");
}
bool NativeFileSystem::PollReady(FileHandle &file)
{
DWORD status = WaitForSingleObject(file.overlapped.hEvent, 0);
switch (status)
{
case WAIT_OBJECT_0:
{
if (file.size == file.bufferSize)
{
file.data = file.buffer;
file.buffer = nullptr;
}
else
{
/* TODO: reserve size for data, shift and move */
}
break;
}
case WAIT_ABANDONED:
case WAIT_TIMEOUT:
return false;
default:
{
LOG(CRITICAL, "Failed to get file status. Error: %d", GetLastError());
return false;
}
}
return true;
}
void NativeFileSystem::Close(FileHandle &file)
{
if (file.overlapped.hEvent)
CloseHandle(file.overlapped.hEvent);
if (file.buffer != nullptr)
{
DeallocateArray(file.buffer);
file.buffer = nullptr;
}
if (file.data != nullptr)
{
DeallocateArray(file.data);
file.data = nullptr;
}
if (file.win32Handle != INVALID_HANDLE_VALUE)
{
CloseHandle(file.win32Handle);
file.win32Handle = INVALID_HANDLE_VALUE;
}
freeFileSlots.push_back(file.id);
}
#endif
#ifdef __linux__
#endif