From c92f450ff8159239fe8bf740cd56c10f65f3ea88 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Fri, 4 Jan 2019 17:11:41 +1100 Subject: [PATCH] win32/file: add basic file wrapper --- CMakeLists.txt | 2 + win32/file.cpp | 116 +++++++++++++++++++++++++++++++++++++++++++++++++ win32/file.hpp | 45 +++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 win32/file.cpp create mode 100644 win32/file.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f7ef1e3..fcfb1c4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,6 +142,8 @@ if (WIN32) win32/windows.hpp win32/except.cpp win32/except.hpp + win32/file.cpp + win32/file.hpp win32/handle.cpp win32/handle.hpp win32/registry.cpp diff --git a/win32/file.cpp b/win32/file.cpp new file mode 100644 index 00000000..412a7f6e --- /dev/null +++ b/win32/file.cpp @@ -0,0 +1,116 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2019 Danny Robson + */ + +#include "file.hpp" + +#include "except.hpp" +#include "../cast.hpp" + +using cruft::win32::file; + + +/////////////////////////////////////////////////////////////////////////////// +file::file (std::filesystem::path const &src, DWORD access, DWORD share, DWORD create, DWORD flags) + : m_handle ( + error::try_call ( + CreateFileW, + src.c_str (), + access, + share, + nullptr, // security + create, + flags, + nullptr // template + ) + ) +{ ; } + + +//----------------------------------------------------------------------------- +file::file (file &&src) noexcept + : m_handle (std::move (src.m_handle)) +{ ; } + + +//----------------------------------------------------------------------------- +file::file (handle &&src) noexcept + : m_handle (std::move (src)) +{ ; } + + +//----------------------------------------------------------------------------- +file::file (posix::fd &&src) + : file (handle (std::move (src))) +{ ; } + + + +/////////////////////////////////////////////////////////////////////////////// +DWORD +file::read(void *buf, size_t available) +{ + DWORD total_read; + error::try_call (ReadFile, m_handle, buf, available, &total_read, nullptr); + return total_read; +} + + +//----------------------------------------------------------------------------- +DWORD +file::write (void *buf, size_t available) +{ + DWORD total_written; + error::try_call (WriteFile, m_handle, buf, available, &total_written, nullptr); + return total_written; +} + + +/////////////////////////////////////////////////////////////////////////////// +DWORD +file::read(void *buf, size_t available, OVERLAPPED &overlapped) +{ + DWORD total_read; + auto const res = ReadFile (m_handle, buf, available, &total_read, &overlapped); + + // If we're performing async IO then a value of FALSE is always returned. + if (!overlapped.hEvent && res == FALSE) + error::throw_code(); + + return total_read; +} + + +//----------------------------------------------------------------------------- +DWORD +file::write (void *buf, size_t available, OVERLAPPED &overlapped) +{ + DWORD total_written; + auto const res = WriteFile (m_handle, buf, available, &total_written, &overlapped); + + // If we're performing async IO then a value of FALSE is always returned. + if (!overlapped.hEvent && res == FALSE) + error::throw_code(); + + return total_written; +} + + +/////////////////////////////////////////////////////////////////////////////// +u64 +file::set_pointer(u64 request, DWORD method) +{ + LONG const lo = request & 0xffffffff; + LONG hi = request >> 32u; + + auto result = SetFilePointer (m_handle, lo, &hi, method); + if (result == INVALID_SET_FILE_POINTER) + error::throw_code(); + + u64 offset = cruft::cast::lossless (result) | cruft::cast::lossless (hi) << 32; + return offset; +} diff --git a/win32/file.hpp b/win32/file.hpp new file mode 100644 index 00000000..4f4ddbb2 --- /dev/null +++ b/win32/file.hpp @@ -0,0 +1,45 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 2019 Danny Robson + */ + +#pragma once + +#include "handle.hpp" +#include "../std.hpp" + +#include + + +/////////////////////////////////////////////////////////////////////////////// +namespace cruft::win32 { + class file { + public: + file (std::filesystem::path const &, DWORD access, DWORD share, DWORD create, DWORD flags); + explicit file (handle&&) noexcept; + explicit file (posix::fd&&); + file (file&&) noexcept; + file& operator= (file&&) noexcept; + + file (file const&) = delete; + file& operator= (file const&) = delete; + + [[nodiscard]] DWORD read (void* buf, size_t count); + [[nodiscard]] DWORD write (void* buf, size_t count); + + [[nodiscard]] DWORD read (void* buf, size_t count, OVERLAPPED&); + [[nodiscard]] DWORD write (void* buf, size_t count, OVERLAPPED&); + + [[nodiscard]] u64 set_pointer (u64 offset, DWORD method); + + decltype(auto) native (void) { return m_handle.native (); } + + operator auto () { return m_handle.native (); } + + private: + handle m_handle; + }; +}