aboutsummaryrefslogtreecommitdiff
path: root/zenstore/basicfile.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-09-19 18:35:56 +0200
committerStefan Boberg <[email protected]>2021-09-19 18:35:56 +0200
commit8b5213bd050634e17b6215cbe25228b4cc6128ef (patch)
tree9356fcb1dbbf4c6e53ac010fb96ddf2ae0ef3323 /zenstore/basicfile.cpp
parentExclude build outputs from vs-chromium (diff)
downloadzen-8b5213bd050634e17b6215cbe25228b4cc6128ef.tar.xz
zen-8b5213bd050634e17b6215cbe25228b4cc6128ef.zip
Changed BasicFile implementation
* No longer uses ATL on Windows (we just use raw Win32 API) * Added non-throwing Open() implementation * Added beginnings of a test suite, for verifying cross-platform implementation
Diffstat (limited to 'zenstore/basicfile.cpp')
-rw-r--r--zenstore/basicfile.cpp90
1 files changed, 73 insertions, 17 deletions
diff --git a/zenstore/basicfile.cpp b/zenstore/basicfile.cpp
index 35ccdd042..75de638cf 100644
--- a/zenstore/basicfile.cpp
+++ b/zenstore/basicfile.cpp
@@ -5,7 +5,9 @@
#include <zencore/except.h>
#include <zencore/filesystem.h>
#include <zencore/fmtutils.h>
+#include <zencore/testutils.h>
+#include <doctest/doctest.h>
#include <fmt/format.h>
#include <gsl/gsl-lite.hpp>
@@ -13,16 +15,54 @@ namespace zen {
using namespace fmt::literals;
+BasicFile::~BasicFile()
+{
+ Close();
+}
+
void
-BasicFile::Open(std::filesystem::path FileName, bool isCreate)
+BasicFile::Open(std::filesystem::path FileName, bool IsCreate)
{
- const DWORD dwCreationDisposition = isCreate ? CREATE_ALWAYS : OPEN_EXISTING;
+ std::error_code Ec;
+ Open(FileName, IsCreate, Ec);
- HRESULT hRes = m_File.Create(FileName.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, dwCreationDisposition);
+ if (Ec)
+ {
+ throw std::system_error(Ec, "failed to open file '{}'"_format(FileName));
+ }
+}
- if (FAILED(hRes))
+void
+BasicFile::Open(std::filesystem::path FileName, bool IsCreate, std::error_code& Ec)
+{
+ const DWORD dwCreationDisposition = IsCreate ? CREATE_ALWAYS : OPEN_EXISTING;
+ const DWORD dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
+ const DWORD dwShareMode = FILE_SHARE_READ;
+ const DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
+ HANDLE hTemplateFile = nullptr;
+
+ HANDLE FileHandle = CreateFile(FileName.c_str(),
+ dwDesiredAccess,
+ dwShareMode,
+ /* lpSecurityAttributes */ nullptr,
+ dwCreationDisposition,
+ dwFlagsAndAttributes,
+ hTemplateFile);
+
+ if (FileHandle == INVALID_HANDLE_VALUE)
{
- ThrowSystemException(hRes, "Failed to open bucket sobs file '{}'"_format(FileName));
+ Ec = zen::MakeErrorCodeFromLastError();
+ }
+
+ m_FileHandle = FileHandle;
+}
+
+void
+BasicFile::Close()
+{
+ if (m_FileHandle)
+ {
+ ::CloseHandle(m_FileHandle);
}
}
@@ -34,11 +74,14 @@ BasicFile::Read(void* Data, uint64_t Size, uint64_t Offset)
Ovl.Offset = DWORD(Offset & 0xffff'ffffu);
Ovl.OffsetHigh = DWORD(Offset >> 32);
- HRESULT hRes = m_File.Read(Data, gsl::narrow<DWORD>(Size), &Ovl);
+ DWORD dwNumberOfBytesToRead = gsl::narrow<DWORD>(Size);
+ DWORD dwNumberOfBytesRead = 0;
+
+ BOOL Success = ::ReadFile(m_FileHandle, Data, dwNumberOfBytesToRead, &dwNumberOfBytesRead, &Ovl);
- if (FAILED(hRes))
+ if (!Success)
{
- ThrowSystemException(hRes, "Failed to read from file '{}'"_format(zen::PathFromHandle(m_File)));
+ ThrowLastError("Failed to read from file '{}'"_format(zen::PathFromHandle(m_FileHandle)));
}
}
@@ -60,33 +103,46 @@ BasicFile::Write(const void* Data, uint64_t Size, uint64_t Offset)
Ovl.Offset = DWORD(Offset & 0xffff'ffffu);
Ovl.OffsetHigh = DWORD(Offset >> 32);
- HRESULT hRes = m_File.Write(Data, gsl::narrow<DWORD>(Size), &Ovl);
+ DWORD dwNumberOfBytesToWrite = gsl::narrow<DWORD>(Size);
+ DWORD dwNumberOfBytesWritten = 0;
+
+ BOOL Success = ::WriteFile(m_FileHandle, Data, dwNumberOfBytesToWrite, &dwNumberOfBytesWritten, &Ovl);
- if (FAILED(hRes))
+ if (!Success)
{
- ThrowSystemException(hRes, "Failed to write to file '{}'"_format(zen::PathFromHandle(m_File)));
+ ThrowLastError("Failed to write to file '{}'"_format(zen::PathFromHandle(m_FileHandle)));
}
}
void
BasicFile::Flush()
{
- m_File.Flush();
+ FlushFileBuffers(m_FileHandle);
}
uint64_t
BasicFile::FileSize()
{
- ULONGLONG Sz;
- m_File.GetSize(Sz);
+ ULARGE_INTEGER liFileSize;
+ liFileSize.LowPart = ::GetFileSize(m_FileHandle, &liFileSize.HighPart);
- return uint64_t(Sz);
+ return uint64_t(liFileSize.QuadPart);
+}
+
+TEST_CASE("BasicFile")
+{
+ ScopedCurrentDirectoryChange _;
+
+ BasicFile File1;
+ CHECK_THROWS(File1.Open("zonk", false));
+ CHECK_NOTHROW(File1.Open("zonk", true));
+ CHECK_NOTHROW(File1.Write("abcd", 4, 0));
+ CHECK(File1.FileSize() == 4);
}
void
-BasicFile::Close()
+basicfile_forcelink()
{
- m_File.Close();
}
} // namespace zen