GCC Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 85.5% 100 / 0 / 117
Functions: 100.0% 17 / 0 / 17
Branches: 67.9% 53 / 0 / 78

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 #include <memory>
9
10 namespace DetourModKit
11 {
12 // --- WinFileStreamBuf ---
13
14 76 WinFileStreamBuf::WinFileStreamBuf() noexcept
15 76 : handle_(INVALID_HANDLE_VALUE)
16 {
17 228 setp(buffer_.data(), buffer_.data() + BUFFER_SIZE);
18 76 }
19
20 76 WinFileStreamBuf::~WinFileStreamBuf() noexcept
21 {
22 76 close();
23 76 }
24
25 338 bool WinFileStreamBuf::open(const std::wstring &path, std::ios_base::openmode mode)
26 {
27
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 337 times.
338 if (is_open())
28 {
29 1 close();
30 }
31
32 338 DWORD creation = CREATE_ALWAYS;
33
2/2
✓ Branch 6 → 7 taken 3 times.
✓ Branch 6 → 8 taken 335 times.
338 if (mode & std::ios_base::app)
34 {
35 3 creation = OPEN_ALWAYS;
36 }
37
38 338 handle_ = CreateFileW(
39 path.c_str(),
40 GENERIC_WRITE,
41 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
42 nullptr,
43 creation,
44 FILE_ATTRIBUTE_NORMAL,
45 nullptr);
46
47
2/2
✓ Branch 10 → 11 taken 8 times.
✓ Branch 10 → 12 taken 330 times.
338 if (handle_ == INVALID_HANDLE_VALUE)
48 {
49 8 return false;
50 }
51
52
2/2
✓ Branch 13 → 14 taken 3 times.
✓ Branch 13 → 23 taken 327 times.
330 if (mode & std::ios_base::app)
53 {
54 3 if (SetFilePointer(static_cast<HANDLE>(handle_), 0, nullptr, FILE_END) ==
55
2/6
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 19 taken 3 times.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 23 taken 3 times.
3 INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
56 {
57 CloseHandle(static_cast<HANDLE>(handle_));
58 handle_ = INVALID_HANDLE_VALUE;
59 return false;
60 }
61 }
62
63 990 setp(buffer_.data(), buffer_.data() + BUFFER_SIZE);
64 330 return true;
65 }
66
67 66 bool WinFileStreamBuf::open(const std::string &path, std::ios_base::openmode mode)
68 {
69 // Convert narrow string to wide. Try UTF-8 first, fall back to ACP.
70
1/2
✓ Branch 3 → 4 taken 66 times.
✗ Branch 3 → 27 not taken.
66 int wide_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, path.c_str(), -1, nullptr, 0);
71 66 UINT code_page = CP_UTF8;
72
2/2
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 8 taken 65 times.
66 if (wide_len <= 0)
73 {
74 1 code_page = CP_ACP;
75
1/2
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 27 not taken.
1 wide_len = MultiByteToWideChar(CP_ACP, 0, path.c_str(), -1, nullptr, 0);
76 }
77
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 66 times.
66 if (wide_len <= 0)
78 {
79 return false;
80 }
81
82
1/2
✓ Branch 12 → 13 taken 66 times.
✗ Branch 12 → 22 not taken.
66 std::wstring wide_path(static_cast<size_t>(wide_len - 1), L'\0');
83
1/2
✓ Branch 16 → 17 taken 66 times.
✗ Branch 16 → 25 not taken.
66 MultiByteToWideChar(code_page, 0, path.c_str(), -1, wide_path.data(), wide_len);
84
85
1/2
✓ Branch 17 → 18 taken 66 times.
✗ Branch 17 → 25 not taken.
66 return open(wide_path, mode);
86 66 }
87
88 62583 bool WinFileStreamBuf::is_open() const noexcept
89 {
90 62583 return handle_ != INVALID_HANDLE_VALUE;
91 }
92
93 368 void WinFileStreamBuf::close()
94 {
95
2/2
✓ Branch 3 → 4 taken 38 times.
✓ Branch 3 → 5 taken 330 times.
368 if (!is_open())
96 {
97 38 return;
98 }
99
100 330 flush_buffer();
101 330 CloseHandle(static_cast<HANDLE>(handle_));
102 330 handle_ = INVALID_HANDLE_VALUE;
103 330 setp(nullptr, nullptr);
104 }
105
106 2 WinFileStreamBuf::int_type WinFileStreamBuf::overflow(int_type ch)
107 {
108
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1 time.
2 if (!is_open())
109 {
110 1 return traits_type::eof();
111 }
112
113
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 1 time.
1 if (!flush_buffer())
114 {
115 return traits_type::eof();
116 }
117
118
1/2
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 14 not taken.
1 if (!traits_type::eq_int_type(ch, traits_type::eof()))
119 {
120 1 *pptr() = traits_type::to_char_type(ch);
121 1 pbump(1);
122 }
123
124 1 return traits_type::not_eof(ch);
125 }
126
127 1539 int WinFileStreamBuf::sync()
128 {
129
2/2
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1538 times.
1539 if (!is_open())
130 {
131 1 return -1;
132 }
133
134
1/2
✓ Branch 6 → 7 taken 1538 times.
✗ Branch 6 → 8 not taken.
1538 return flush_buffer() ? 0 : -1;
135 }
136
137 56457 std::streamsize WinFileStreamBuf::xsputn(const char *s, std::streamsize count)
138 {
139
6/6
✓ Branch 3 → 4 taken 56456 times.
✓ Branch 3 → 5 taken 1 time.
✓ Branch 4 → 5 taken 5 times.
✓ Branch 4 → 6 taken 56451 times.
✓ Branch 7 → 8 taken 6 times.
✓ Branch 7 → 9 taken 56451 times.
56457 if (!is_open() || count <= 0)
140 {
141 6 return 0;
142 }
143
144 56451 std::streamsize written = 0;
145
146
2/2
✓ Branch 27 → 10 taken 56456 times.
✓ Branch 27 → 28 taken 56451 times.
112907 while (written < count)
147 {
148 56456 const auto available = static_cast<std::streamsize>(epptr() - pptr());
149 56456 const auto to_copy = std::min(count - written, available);
150
151
1/2
✓ Branch 13 → 14 taken 56456 times.
✗ Branch 13 → 20 not taken.
56456 if (to_copy > 0)
152 {
153 56456 std::memcpy(pptr(), s + written, static_cast<size_t>(to_copy));
154
1/2
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 56456 times.
56456 assert(to_copy <= INT_MAX);
155 56456 pbump(static_cast<int>(to_copy));
156 56456 written += to_copy;
157 }
158
159
2/2
✓ Branch 22 → 23 taken 6 times.
✓ Branch 22 → 26 taken 56450 times.
56456 if (pptr() == epptr())
160 {
161
2/4
✓ Branch 23 → 24 taken 6 times.
✗ Branch 23 → 30 not taken.
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 26 taken 6 times.
6 if (!flush_buffer())
162 {
163 break;
164 }
165 }
166 }
167
168 56451 return written;
169 }
170
171 1875 bool WinFileStreamBuf::flush_buffer()
172 {
173 1875 const auto count = static_cast<DWORD>(pptr() - pbase());
174
2/2
✓ Branch 4 → 5 taken 426 times.
✓ Branch 4 → 6 taken 1449 times.
1875 if (count == 0)
175 {
176 426 return true;
177 }
178
179 1449 DWORD bytes_written = 0;
180 2898 const BOOL result = WriteFile(
181
1/2
✓ Branch 7 → 8 taken 1449 times.
✗ Branch 7 → 20 not taken.
1449 static_cast<HANDLE>(handle_), pbase(), count, &bytes_written, nullptr);
182 4347 setp(buffer_.data(), buffer_.data() + BUFFER_SIZE);
183
184
2/4
✓ Branch 13 → 14 taken 1449 times.
✗ Branch 13 → 16 not taken.
✓ Branch 14 → 15 taken 1449 times.
✗ Branch 14 → 16 not taken.
1449 return result != 0 && bytes_written == count;
185 }
186
187 // --- WinFileStream ---
188
189 10 WinFileStream::WinFileStream()
190
1/2
✓ Branch 3 → 4 taken 10 times.
✗ Branch 3 → 6 not taken.
10 : std::ostream(&buf_)
191 {
192 10 }
193
194 48 WinFileStream::WinFileStream(const std::string &path, std::ios_base::openmode mode)
195
1/2
✓ Branch 3 → 4 taken 48 times.
✗ Branch 3 → 11 not taken.
48 : std::ostream(&buf_)
196 {
197
1/4
DetourModKit::WinFileStream::WinFileStream(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::_Ios_Openmode):
✓ Branch 5 → 6 taken 48 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.
48 open(path, mode);
198 48 }
199
200 58 WinFileStream::~WinFileStream() noexcept = default;
201
202 52 void WinFileStream::open(const std::string &path, std::ios_base::openmode mode)
203 {
204 52 clear();
205
2/2
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 6 taken 50 times.
52 if (!buf_.open(path, mode))
206 {
207 2 setstate(std::ios_base::failbit);
208 }
209 52 }
210
211 271 void WinFileStream::open(const std::wstring &path, std::ios_base::openmode mode)
212 {
213 271 clear();
214
2/2
✓ Branch 4 → 5 taken 5 times.
✓ Branch 4 → 6 taken 266 times.
271 if (!buf_.open(path, mode))
215 {
216 5 setstate(std::ios_base::failbit);
217 }
218 271 }
219
220 3872 bool WinFileStream::is_open() const noexcept
221 {
222 3872 return buf_.is_open();
223 }
224
225 277 void WinFileStream::close()
226 {
227 277 buf_.close();
228 277 }
229
230 } // namespace DetourModKit
231