aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Ridgers <[email protected]>2021-12-02 16:02:13 +0100
committerMartin Ridgers <[email protected]>2021-12-02 16:02:41 +0100
commitde286a8a79c5b3219e2cd5438bb015e01606ba6c (patch)
treeb8eb4abd7857934a8529d4969c0fe4361903f105
parentFake concrt for non-Windows platforms (diff)
downloadzen-de286a8a79c5b3219e2cd5438bb015e01606ba6c.tar.xz
zen-de286a8a79c5b3219e2cd5438bb015e01606ba6c.zip
Implement zen/internalfile for POSIX platforms
-rw-r--r--zen/internalfile.cpp99
-rw-r--r--zen/internalfile.h4
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;