aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt6
-rw-r--r--src/common/io/Win32FileStream.cpp127
2 files changed, 133 insertions, 0 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 40c85ef0..d8462abf 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -21,6 +21,12 @@ if (UNIX)
endif()
if (WIN32)
+ target_sources(cru_base PRIVATE
+ io/Win32FileStream.cpp
+ )
+endif()
+
+if (WIN32)
target_compile_definitions(cru_base PUBLIC CRU_PLATFORM_WINDOWS)
elseif(APPLE)
target_compile_definitions(cru_base PUBLIC CRU_PLATFORM_OSX)
diff --git a/src/common/io/Win32FileStream.cpp b/src/common/io/Win32FileStream.cpp
new file mode 100644
index 00000000..e7ee0e6a
--- /dev/null
+++ b/src/common/io/Win32FileStream.cpp
@@ -0,0 +1,127 @@
+#include "cru/common/io/Win32FileStream.hpp"
+
+#include "cru/common/Exception.hpp"
+#include "cru/common/io/OpenFileFlag.hpp"
+
+#include <Windows.h>
+
+namespace cru::io {
+namespace details {
+struct Win32FileStreamPrivate {
+ HANDLE handle;
+};
+} // namespace details
+
+Win32FileStream::Win32FileStream(String path, OpenFileFlag flags)
+ : path_(std::move(path)), flags_(flags) {
+ p_ = new details::Win32FileStreamPrivate();
+
+ DWORD dwDesiredAccess = 0;
+ if (flags & OpenFileFlags::Read) {
+ dwDesiredAccess |= GENERIC_READ;
+ }
+ if (flags & OpenFileFlags::Write) {
+ dwDesiredAccess |= GENERIC_WRITE;
+ }
+
+ DWORD dwCreationDisposition = 0;
+ if (flags & OpenFileFlags::Create) {
+ if (flags & OpenFileFlags::ThrowOnExist) {
+ dwCreationDisposition = CREATE_NEW;
+ } else {
+ dwCreationDisposition = OPEN_ALWAYS;
+ }
+ } else {
+ dwCreationDisposition = OPEN_EXISTING;
+ }
+
+ p_->handle =
+ ::CreateFileW(path_.WinCStr(), dwDesiredAccess, 0, nullptr,
+ dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
+
+ if (p_->handle == INVALID_HANDLE_VALUE) {
+ throw Exception(u"Failed to call CreateFileW.");
+ }
+}
+
+Win32FileStream::~Win32FileStream() {
+ Close();
+ delete p_;
+}
+
+bool Win32FileStream::CanSeek() { return true; }
+
+Index Win32FileStream::Tell() {
+ CheckClosed();
+
+ LARGE_INTEGER offset;
+ offset.QuadPart = 0;
+ LARGE_INTEGER file_pointer;
+ if (::SetFilePointerEx(p_->handle, offset, &file_pointer, FILE_CURRENT) ==
+ 0) {
+ throw Exception(u"Failed to call SetFilePointerEx.");
+ }
+
+ return file_pointer.QuadPart;
+}
+
+void Win32FileStream::Seek(Index offset, SeekOrigin origin) {
+ CheckClosed();
+
+ DWORD dwMoveMethod = 0;
+
+ if (origin == SeekOrigin::Current) {
+ dwMoveMethod = FILE_CURRENT;
+ } else if (origin == SeekOrigin::End) {
+ dwMoveMethod = FILE_END;
+ } else {
+ dwMoveMethod = FILE_BEGIN;
+ }
+
+ LARGE_INTEGER n_offset;
+ n_offset.QuadPart = offset;
+ if (::SetFilePointerEx(p_->handle, n_offset, nullptr, dwMoveMethod) == 0) {
+ throw Exception(u"Failed to call SetFilePointerEx.");
+ }
+}
+
+bool Win32FileStream::CanRead() { return true; }
+
+Index Win32FileStream::Read(std::byte* buffer, Index offset, Index size) {
+ CheckClosed();
+
+ DWORD dwRead;
+ if (::ReadFile(p_->handle, buffer + offset, size, &dwRead, nullptr) == 0) {
+ throw Exception(u"Failed to call ReadFile.");
+ }
+ return dwRead;
+}
+
+bool Win32FileStream::CanWrite() { return true; }
+
+Index Win32FileStream::Write(const std::byte* buffer, Index offset,
+ Index size) {
+ CheckClosed();
+
+ DWORD dwWritten;
+ if (::WriteFile(p_->handle, buffer + offset, size, &dwWritten, nullptr) ==
+ 0) {
+ throw Exception(u"Failed to call WriteFile.");
+ }
+
+ return dwWritten;
+}
+
+void Win32FileStream::Close() {
+ if (closed_) return;
+
+ ::CloseHandle(p_->handle);
+
+ closed_ = true;
+}
+
+void Win32FileStream::CheckClosed() {
+ if (closed_) throw Exception(u"Stream is closed.");
+}
+
+} // namespace cru::io