diff options
| author | Martin Ridgers <[email protected]> | 2021-12-02 16:02:13 +0100 |
|---|---|---|
| committer | Martin Ridgers <[email protected]> | 2021-12-02 16:02:41 +0100 |
| commit | de286a8a79c5b3219e2cd5438bb015e01606ba6c (patch) | |
| tree | b8eb4abd7857934a8529d4969c0fe4361903f105 | |
| parent | Fake concrt for non-Windows platforms (diff) | |
| download | zen-de286a8a79c5b3219e2cd5438bb015e01606ba6c.tar.xz zen-de286a8a79c5b3219e2cd5438bb015e01606ba6c.zip | |
Implement zen/internalfile for POSIX platforms
| -rw-r--r-- | zen/internalfile.cpp | 99 | ||||
| -rw-r--r-- | zen/internalfile.h | 4 |
2 files changed, 90 insertions, 13 deletions
diff --git a/zen/internalfile.cpp b/zen/internalfile.cpp index ef88b9e04..44a2eb98d 100644 --- a/zen/internalfile.cpp +++ b/zen/internalfile.cpp @@ -8,6 +8,13 @@ #include <zencore/logging.h> #include <zencore/memory.h> +#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC +# include <fcntl.h> +# include <sys/file.h> +# include <sys/mman.h> +# include <sys/stat.h> +#endif + #include <gsl/gsl-lite.hpp> #define ZEN_USE_SLIST ZEN_PLATFORM_WINDOWS @@ -125,6 +132,10 @@ FileBufferManager::ReturnBuffer(zen::IoBuffer Buffer) ////////////////////////////////////////////////////////////////////////// InternalFile::InternalFile() +#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC +: m_File(nullptr) +, m_Mmap(nullptr) +#endif { } @@ -132,25 +143,52 @@ InternalFile::~InternalFile() { if (m_Memory) zen::Memory::Free(m_Memory); + +#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC + if (m_Mmap) munmap(m_Mmap, GetFileSize()); + if (m_File) close(int(intptr_t(m_File))); +#endif } size_t InternalFile::GetFileSize() { +#if ZEN_PLATFORM_WINDOWS ULONGLONG sz; m_File.GetSize(sz); - return size_t(sz); +#else + int Fd = int(intptr_t(m_File)); + static_assert(sizeof(decltype(stat::st_size)) == sizeof(uint64_t), "fstat() doesn't support large files"); + struct stat Stat; + fstat(Fd, &Stat); + return size_t(Stat.st_size); +#endif } void InternalFile::OpenWrite(std::filesystem::path FileName, bool IsCreate) { + bool Success = false; + +#if ZEN_PLATFORM_WINDOWS const DWORD dwCreationDisposition = IsCreate ? CREATE_ALWAYS : OPEN_EXISTING; HRESULT hRes = m_File.Create(FileName.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, dwCreationDisposition); + Success = SUCCEEDED(hRes); +#else + int OpenFlags = O_RDWR; + OpenFlags |= IsCreate ? O_CREAT|O_TRUNC : 0; - if (FAILED(hRes)) + int Fd = open(FileName.c_str(), OpenFlags, 0666); + if (Fd >= 0) + { + Success = true; + m_File = (void*)(intptr_t(Fd)); + } +#endif // ZEN_PLATFORM_WINDOWS + + if (Success) { using namespace fmt::literals; zen::ThrowLastError("Failed to open file for writing: '{}'"_format(FileName)); @@ -160,11 +198,23 @@ InternalFile::OpenWrite(std::filesystem::path FileName, bool IsCreate) void InternalFile::OpenRead(std::filesystem::path FileName) { + bool Success = false; + +#if ZEN_PLATFORM_WINDOWS const DWORD dwCreationDisposition = OPEN_EXISTING; HRESULT hRes = m_File.Create(FileName.c_str(), GENERIC_READ, FILE_SHARE_READ, dwCreationDisposition); + Success = SUCCEEDED(hRes); +#else + int Fd = open(FileName.c_str(), O_RDONLY); + if (Fd >= 0) + { + Success = true; + m_File = (void*)(intptr_t(Fd)); + } +#endif - if (FAILED(hRes)) + if (Success) { using namespace fmt::literals; zen::ThrowLastError("Failed to open file for reading: '{}'"_format(FileName)); @@ -176,30 +226,44 @@ InternalFile::MemoryMapFile() { auto FileSize = GetFileSize(); - if (FileSize > 100 * 1024 * 1024) + if (FileSize <= 100 * 1024 * 1024) { - m_Mmap.MapFile(m_File); + m_Memory = zen::Memory::Alloc(FileSize, 64); + Read(m_Memory, FileSize, 0); - return m_Mmap.GetData(); + return m_Memory; } - m_Memory = zen::Memory::Alloc(FileSize, 64); - Read(m_Memory, FileSize, 0); - - return m_Memory; +#if ZEN_PLATFORM_WINDOWS + m_Mmap.MapFile(m_File); + return m_Mmap.GetData(); +#else + int Fd = int(intptr_t(m_File)); + m_Mmap = mmap(nullptr, FileSize, PROT_READ, MAP_PRIVATE, Fd, 0); + return m_Mmap; +#endif } void InternalFile::Read(void* Data, uint64_t Size, uint64_t Offset) { + bool Success; + +#if ZEN_PLATFORM_WINDOWS OVERLAPPED ovl{}; ovl.Offset = DWORD(Offset & 0xffff'ffffu); ovl.OffsetHigh = DWORD(Offset >> 32); HRESULT hRes = m_File.Read(Data, gsl::narrow<DWORD>(Size), &ovl); + Success = SUCCEEDED(hRes); +#else + int Fd = int(intptr_t(m_File)); + int BytesRead = pread(Fd, Data, Size, Offset); + Success = (BytesRead > 0); +#endif - if (FAILED(hRes)) + if (Success) { using namespace fmt::literals; zen::ThrowLastError("Failed to read from file '{}'"_format(""));//zen::PathFromHandle(m_File))); @@ -209,16 +273,25 @@ InternalFile::Read(void* Data, uint64_t Size, uint64_t Offset) void InternalFile::Write(const void* Data, uint64_t Size, uint64_t Offset) { + bool Success; + +#if ZEN_PLATFORM_WINDOWS OVERLAPPED Ovl{}; Ovl.Offset = DWORD(Offset & 0xffff'ffffu); Ovl.OffsetHigh = DWORD(Offset >> 32); HRESULT hRes = m_File.Write(Data, gsl::narrow<DWORD>(Size), &Ovl); + Success = SUCCEEDED(hRes); +#else + int Fd = int(intptr_t(m_File)); + int BytesWritten = pwrite(Fd, Data, Size, Offset); + Success = (BytesWritten > 0); +#endif - if (FAILED(hRes)) + if (Success) { using namespace fmt::literals; - zen::ThrowLastError("Failed to write to file '{}'"_format(""));//zen::PathFromHandle(m_File))); + zen::ThrowLastError("Failed to write to file '{}'"_format(zen::PathFromHandle(m_File))); } } diff --git a/zen/internalfile.h b/zen/internalfile.h index 4eca48443..aaead2dd1 100644 --- a/zen/internalfile.h +++ b/zen/internalfile.h @@ -55,6 +55,10 @@ public: size_t GetFileSize(); private: +#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC + using CAtlFile = void*; + using CAtlFileMappingBase = void*; +#endif CAtlFile m_File; CAtlFileMappingBase m_Mmap; void* m_Memory = nullptr; |