src/win_file_stream.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "DetourModKit/win_file_stream.hpp" | ||
| 2 | |||
| 3 | #include <windows.h> | ||
| 4 | #include <algorithm> | ||
| 5 | #include <cassert> | ||
| 6 | #include <climits> | ||
| 7 | #include <cstring> | ||
| 8 | |||
| 9 | namespace DetourModKit | ||
| 10 | { | ||
| 11 | // --- WinFileStreamBuf --- | ||
| 12 | |||
| 13 | 40 | WinFileStreamBuf::WinFileStreamBuf() noexcept | |
| 14 | 40 | : handle_(INVALID_HANDLE_VALUE) | |
| 15 | { | ||
| 16 | 120 | setp(buffer_.data(), buffer_.data() + BUFFER_SIZE); | |
| 17 | 40 | } | |
| 18 | |||
| 19 | 40 | WinFileStreamBuf::~WinFileStreamBuf() noexcept | |
| 20 | { | ||
| 21 | 40 | close(); | |
| 22 | 40 | } | |
| 23 | |||
| 24 | 238 | bool WinFileStreamBuf::open(const std::string &path, std::ios_base::openmode mode) | |
| 25 | { | ||
| 26 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 238 times.
|
238 | if (is_open()) |
| 27 | { | ||
| 28 | ✗ | close(); | |
| 29 | } | ||
| 30 | |||
| 31 | 238 | DWORD creation = CREATE_ALWAYS; | |
| 32 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 238 times.
|
238 | if (mode & std::ios_base::app) |
| 33 | { | ||
| 34 | ✗ | creation = OPEN_ALWAYS; | |
| 35 | } | ||
| 36 | |||
| 37 | 238 | handle_ = CreateFileA( | |
| 38 | path.c_str(), | ||
| 39 | GENERIC_WRITE, | ||
| 40 | FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||
| 41 | nullptr, | ||
| 42 | creation, | ||
| 43 | FILE_ATTRIBUTE_NORMAL, | ||
| 44 | nullptr); | ||
| 45 | |||
| 46 |
2/2✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 237 times.
|
238 | if (handle_ == INVALID_HANDLE_VALUE) |
| 47 | { | ||
| 48 | 1 | return false; | |
| 49 | } | ||
| 50 | |||
| 51 |
1/2✗ Branch 13 → 14 not taken.
✓ Branch 13 → 23 taken 237 times.
|
237 | if (mode & std::ios_base::app) |
| 52 | { | ||
| 53 | ✗ | if (SetFilePointer(static_cast<HANDLE>(handle_), 0, nullptr, FILE_END) == | |
| 54 | ✗ | INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) | |
| 55 | { | ||
| 56 | ✗ | CloseHandle(static_cast<HANDLE>(handle_)); | |
| 57 | ✗ | handle_ = INVALID_HANDLE_VALUE; | |
| 58 | ✗ | return false; | |
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | 711 | setp(buffer_.data(), buffer_.data() + BUFFER_SIZE); | |
| 63 | 237 | return true; | |
| 64 | } | ||
| 65 | |||
| 66 | 46413 | bool WinFileStreamBuf::is_open() const noexcept | |
| 67 | { | ||
| 68 | 46413 | return handle_ != INVALID_HANDLE_VALUE; | |
| 69 | } | ||
| 70 | |||
| 71 | 248 | void WinFileStreamBuf::close() | |
| 72 | { | ||
| 73 |
2/2✓ Branch 3 → 4 taken 11 times.
✓ Branch 3 → 5 taken 237 times.
|
248 | if (!is_open()) |
| 74 | { | ||
| 75 | 11 | return; | |
| 76 | } | ||
| 77 | |||
| 78 | 237 | flush_buffer(); | |
| 79 | 237 | CloseHandle(static_cast<HANDLE>(handle_)); | |
| 80 | 237 | handle_ = INVALID_HANDLE_VALUE; | |
| 81 | 237 | setp(nullptr, nullptr); | |
| 82 | } | ||
| 83 | |||
| 84 | ✗ | WinFileStreamBuf::int_type WinFileStreamBuf::overflow(int_type ch) | |
| 85 | { | ||
| 86 | ✗ | if (!is_open()) | |
| 87 | { | ||
| 88 | ✗ | return traits_type::eof(); | |
| 89 | } | ||
| 90 | |||
| 91 | ✗ | if (!flush_buffer()) | |
| 92 | { | ||
| 93 | ✗ | return traits_type::eof(); | |
| 94 | } | ||
| 95 | |||
| 96 | ✗ | if (!traits_type::eq_int_type(ch, traits_type::eof())) | |
| 97 | { | ||
| 98 | ✗ | *pptr() = traits_type::to_char_type(ch); | |
| 99 | ✗ | pbump(1); | |
| 100 | } | ||
| 101 | |||
| 102 | ✗ | return traits_type::not_eof(ch); | |
| 103 | } | ||
| 104 | |||
| 105 | 709 | int WinFileStreamBuf::sync() | |
| 106 | { | ||
| 107 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 709 times.
|
709 | if (!is_open()) |
| 108 | { | ||
| 109 | ✗ | return -1; | |
| 110 | } | ||
| 111 | |||
| 112 |
1/2✓ Branch 6 → 7 taken 709 times.
✗ Branch 6 → 8 not taken.
|
709 | return flush_buffer() ? 0 : -1; |
| 113 | } | ||
| 114 | |||
| 115 | 43428 | std::streamsize WinFileStreamBuf::xsputn(const char *s, std::streamsize count) | |
| 116 | { | ||
| 117 |
5/6✓ Branch 3 → 4 taken 43428 times.
✗ Branch 3 → 5 not taken.
✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 6 taken 43424 times.
✓ Branch 7 → 8 taken 4 times.
✓ Branch 7 → 9 taken 43424 times.
|
43428 | if (!is_open() || count <= 0) |
| 118 | { | ||
| 119 | 4 | return 0; | |
| 120 | } | ||
| 121 | |||
| 122 | 43424 | std::streamsize written = 0; | |
| 123 | |||
| 124 |
2/2✓ Branch 27 → 10 taken 43426 times.
✓ Branch 27 → 28 taken 43424 times.
|
86850 | while (written < count) |
| 125 | { | ||
| 126 | 43426 | const auto available = static_cast<std::streamsize>(epptr() - pptr()); | |
| 127 | 43426 | const auto to_copy = std::min(count - written, available); | |
| 128 | |||
| 129 |
1/2✓ Branch 13 → 14 taken 43426 times.
✗ Branch 13 → 20 not taken.
|
43426 | if (to_copy > 0) |
| 130 | { | ||
| 131 | 43426 | std::memcpy(pptr(), s + written, static_cast<size_t>(to_copy)); | |
| 132 |
1/2✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 43426 times.
|
43426 | assert(to_copy <= INT_MAX); |
| 133 | 43426 | pbump(static_cast<int>(to_copy)); | |
| 134 | 43426 | written += to_copy; | |
| 135 | } | ||
| 136 | |||
| 137 |
2/2✓ Branch 22 → 23 taken 2 times.
✓ Branch 22 → 26 taken 43424 times.
|
43426 | if (pptr() == epptr()) |
| 138 | { | ||
| 139 |
2/4✓ Branch 23 → 24 taken 2 times.
✗ Branch 23 → 30 not taken.
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 26 taken 2 times.
|
2 | if (!flush_buffer()) |
| 140 | { | ||
| 141 | ✗ | break; | |
| 142 | } | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | 43424 | return written; | |
| 147 | } | ||
| 148 | |||
| 149 | 948 | bool WinFileStreamBuf::flush_buffer() | |
| 150 | { | ||
| 151 | 948 | const auto count = static_cast<DWORD>(pptr() - pbase()); | |
| 152 |
2/2✓ Branch 4 → 5 taken 304 times.
✓ Branch 4 → 6 taken 644 times.
|
948 | if (count == 0) |
| 153 | { | ||
| 154 | 304 | return true; | |
| 155 | } | ||
| 156 | |||
| 157 | 644 | DWORD bytes_written = 0; | |
| 158 | 1288 | const BOOL result = WriteFile( | |
| 159 |
1/2✓ Branch 7 → 8 taken 644 times.
✗ Branch 7 → 20 not taken.
|
644 | static_cast<HANDLE>(handle_), pbase(), count, &bytes_written, nullptr); |
| 160 | 1932 | setp(buffer_.data(), buffer_.data() + BUFFER_SIZE); | |
| 161 | |||
| 162 |
2/4✓ Branch 13 → 14 taken 644 times.
✗ Branch 13 → 16 not taken.
✓ Branch 14 → 15 taken 644 times.
✗ Branch 14 → 16 not taken.
|
644 | return result != 0 && bytes_written == count; |
| 163 | } | ||
| 164 | |||
| 165 | // --- WinFileStream --- | ||
| 166 | |||
| 167 | 3 | WinFileStream::WinFileStream() | |
| 168 |
1/2✓ Branch 3 → 4 taken 3 times.
✗ Branch 3 → 6 not taken.
|
3 | : std::ostream(&buf_) |
| 169 | { | ||
| 170 | 3 | } | |
| 171 | |||
| 172 | 37 | WinFileStream::WinFileStream(const std::string &path, std::ios_base::openmode mode) | |
| 173 |
1/2✓ Branch 3 → 4 taken 37 times.
✗ Branch 3 → 11 not taken.
|
37 | : std::ostream(&buf_) |
| 174 | { | ||
| 175 |
1/4DetourModKit::WinFileStream::WinFileStream(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::_Ios_Openmode):
✓ Branch 5 → 6 taken 37 times.
✗ Branch 5 → 7 not taken.
DetourModKit::WinFileStream::WinFileStream(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::_Ios_Openmode):
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
|
37 | open(path, mode); |
| 176 | 37 | } | |
| 177 | |||
| 178 | 40 | WinFileStream::~WinFileStream() noexcept = default; | |
| 179 | |||
| 180 | 238 | void WinFileStream::open(const std::string &path, std::ios_base::openmode mode) | |
| 181 | { | ||
| 182 | 238 | clear(); | |
| 183 |
2/2✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 237 times.
|
238 | if (!buf_.open(path, mode)) |
| 184 | { | ||
| 185 | 1 | setstate(std::ios_base::failbit); | |
| 186 | } | ||
| 187 | 238 | } | |
| 188 | |||
| 189 | 1790 | bool WinFileStream::is_open() const noexcept | |
| 190 | { | ||
| 191 | 1790 | return buf_.is_open(); | |
| 192 | } | ||
| 193 | |||
| 194 | 208 | void WinFileStream::close() | |
| 195 | { | ||
| 196 | 208 | buf_.close(); | |
| 197 | 208 | } | |
| 198 | |||
| 199 | } // namespace DetourModKit | ||
| 200 |