diff options
author | crupest <crupest@outlook.com> | 2022-01-25 17:42:19 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2022-01-25 17:42:19 +0800 |
commit | 839292efaaf8d997b2cbca7abae8c6e575f6c01a (patch) | |
tree | 0f0354fca793e75b90f9d02e86351b2a86601f34 /src/common/platform/win/Win32FileStream.cpp | |
parent | 2ed65999ef6f3e1156427dd3efe04353ae657882 (diff) | |
download | cru-839292efaaf8d997b2cbca7abae8c6e575f6c01a.tar.gz cru-839292efaaf8d997b2cbca7abae8c6e575f6c01a.tar.bz2 cru-839292efaaf8d997b2cbca7abae8c6e575f6c01a.zip |
...
Diffstat (limited to 'src/common/platform/win/Win32FileStream.cpp')
-rw-r--r-- | src/common/platform/win/Win32FileStream.cpp | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/common/platform/win/Win32FileStream.cpp b/src/common/platform/win/Win32FileStream.cpp new file mode 100644 index 00000000..5997c570 --- /dev/null +++ b/src/common/platform/win/Win32FileStream.cpp @@ -0,0 +1,129 @@ +#include "cru/common/platform/win/Win32FileStream.hpp" + +#include "cru/common/io/OpenFileFlag.hpp" +#include "cru/common/platform/win/Exception.hpp" + +#include <Windows.h> + +namespace cru::platform::win { +using 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 Win32Error(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 Win32Error(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 Win32Error(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 Win32Error(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 Win32Error(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::platform::win |