low_io.hpp (4244B)
1 #ifndef GUARD_UNREVEALINGLY_SLATY_MICROSCHIZONT_AUTOIONIZES_2256 2 #define GUARD_UNREVEALINGLY_SLATY_MICROSCHIZONT_AUTOIONIZES_2256 3 #pragma once 4 5 #include "libshit/platform.hpp" 6 7 #include <cstddef> 8 #include <cstdint> 9 #include <type_traits> 10 #include <utility> 11 12 namespace Libshit 13 { 14 15 class LowIo 16 { 17 public: 18 using FdType = std::conditional_t<LIBSHIT_OS_IS_WINDOWS, void*, int>; 19 static inline const FdType INVALID_FD = reinterpret_cast<FdType>(-1); 20 using FilePosition = std::uint64_t; 21 22 LowIo() noexcept {}; // can't be default due to a clang8 bug 23 explicit LowIo(FdType fd) noexcept : fd{fd} {} 24 LowIo(FdType fd, bool owning) noexcept : fd{fd}, owning{owning} {} 25 26 enum class Permission { READ_ONLY, WRITE_ONLY, READ_WRITE }; 27 enum class Mode { OPEN_ONLY, CREATE_ONLY, OPEN_OR_CREATE, TRUNC_OR_CREATE }; 28 29 LowIo(const char* fname, Permission perm, Mode mode); 30 ~LowIo() noexcept { Reset(); } 31 void Reset() noexcept; 32 33 static LowIo OpenStdOut(); 34 35 enum class OpenError 36 { 37 OK, 38 ACCESS, // (maybe) perm related errors 39 EXISTS, NOT_EXISTS, // (maybe) mode related errors 40 UNKNOWN // not mapped error 41 }; 42 using ErrorCode = std::conditional_t< 43 LIBSHIT_OS_IS_WINDOWS, unsigned int, int>; 44 std::pair<OpenError, ErrorCode> TryOpen( 45 const char* fname, Permission perm, Mode mode); 46 47 #if LIBSHIT_OS_IS_WINDOWS 48 LowIo(const wchar_t* fname, Permission perm, Mode mode); 49 std::pair<OpenError, ErrorCode> TryOpen( 50 const wchar_t* fname, Permission perm, Mode mode); 51 52 # define LIBSHIT_LOWIO_RETHROW_OPEN_ERROR(code, fname) \ 53 LIBSHIT_THROW(::Libshit::WindowsError, code, "API function", "CreateFile", \ 54 "File name", fname) 55 #else 56 # define LIBSHIT_LOWIO_RETHROW_OPEN_ERROR(code, fname) \ 57 LIBSHIT_THROW(::Libshit::ErrnoError, code, "API function", "open", \ 58 "File name", fname) 59 #endif 60 61 LowIo(LowIo&& o) noexcept 62 : fd{o.fd}, LIBSHIT_OS_WINDOWS(mmap_fd{o.mmap_fd},) owning{o.owning} 63 { 64 o.fd = INVALID_FD; 65 LIBSHIT_OS_WINDOWS(o.mmap_fd = INVALID_FD); 66 } 67 LowIo& operator=(LowIo o) noexcept 68 { 69 swap(*this, o); 70 return *this; 71 } 72 73 friend void swap(LowIo& a, LowIo& b) noexcept 74 { 75 std::swap(a.fd, b.fd); 76 LIBSHIT_OS_WINDOWS(std::swap(a.mmap_fd, b.mmap_fd)); 77 std::swap(a.owning, b.owning); 78 } 79 80 class MmapPtr 81 { 82 public: 83 MmapPtr() noexcept = default; 84 MmapPtr(MmapPtr&& o) noexcept 85 : ptr{o.ptr} LIBSHIT_OS_NOT_WINDOWS(, size{o.size}) 86 { 87 o.ptr = nullptr; 88 LIBSHIT_OS_NOT_WINDOWS(o.size = 0); 89 } 90 MmapPtr& operator=(MmapPtr o) noexcept 91 { 92 swap(*this, o); 93 return *this; 94 } 95 ~MmapPtr() noexcept { Reset(); } 96 97 friend void swap(MmapPtr& a, MmapPtr& b) noexcept 98 { 99 std::swap(a.ptr, b.ptr); 100 LIBSHIT_OS_NOT_WINDOWS(std::swap(a.size, b.size)); 101 } 102 103 explicit operator bool() const noexcept { return ptr; } 104 void* Get() const noexcept { return ptr; } 105 106 void Reset() noexcept; 107 void* Release() 108 { 109 auto res = ptr; 110 ptr = nullptr; 111 return res; 112 } 113 114 private: 115 #if LIBSHIT_OS_IS_WINDOWS 116 MmapPtr(void* ptr) : ptr{ptr} {} 117 #else 118 MmapPtr(void* ptr, std::size_t size) : ptr{ptr}, size{size} {} 119 #endif 120 friend class LowIo; 121 122 void* ptr = nullptr; 123 LIBSHIT_OS_NOT_WINDOWS(std::size_t size = 0); 124 }; 125 126 static constexpr const bool MMAP_SUPPORTED = !LIBSHIT_OS_IS_VITA; 127 128 FilePosition GetSize() const; 129 void Truncate(FilePosition size) const; 130 void PrepareMmap(bool write); 131 MmapPtr Mmap(FilePosition offs, std::size_t size, bool write) const; 132 static void Munmap(void* ptr, std::size_t size); 133 134 void Pread(void* buf, std::size_t len, FilePosition offs) const; 135 void Read(void* buf, std::size_t len) const; 136 137 void Pwrite(const void* buf, std::size_t len, FilePosition offs) const; 138 void Write(const void* buf, std::size_t len) const; 139 140 FdType GetFd() noexcept { return fd; } 141 142 private: 143 FdType fd = INVALID_FD; 144 LIBSHIT_OS_WINDOWS(FdType mmap_fd = INVALID_FD); 145 bool owning = true; 146 }; 147 148 } 149 #endif