GCC Code Coverage Report


Directory: libs/http_proto/
File: src/detail/file_stdio.cpp
Date: 2025-09-21 18:08:15
Exec Total Coverage
Lines: 107 126 84.9%
Functions: 11 11 100.0%
Branches: 41 53 77.4%

Line Branch Exec Source
1 //
2 // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/http_proto
8 //
9
10 #include "src/detail/win32_unicode_path.hpp"
11 #include <boost/http_proto/detail/file_stdio.hpp>
12 #include <boost/http_proto/error.hpp>
13 #include <boost/system/errc.hpp>
14 #include <boost/config/workaround.hpp>
15 #include <boost/core/exchange.hpp>
16 #include <limits>
17
18 namespace boost {
19 namespace http_proto {
20 namespace detail {
21
22 23 file_stdio::
23 ~file_stdio()
24 {
25
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 12 times.
23 if(f_)
26 11 fclose(f_);
27 23 }
28
29 1 file_stdio::
30 file_stdio(
31 1 file_stdio&& other) noexcept
32 1 : f_(boost::exchange(other.f_, nullptr))
33 {
34 1 }
35
36 file_stdio&
37 3 file_stdio::
38 operator=(
39 file_stdio&& other) noexcept
40 {
41
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if(&other == this)
42 1 return *this;
43
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(f_)
44 1 fclose(f_);
45 2 f_ = other.f_;
46 2 other.f_ = nullptr;
47 2 return *this;
48 }
49
50 void
51 1 file_stdio::
52 native_handle(std::FILE* f)
53 {
54
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if(f_)
55 1 fclose(f_);
56 1 f_ = f;
57 1 }
58
59 void
60 4 file_stdio::
61 close(
62 system::error_code& ec)
63 {
64
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if(f_)
65 {
66 4 int failed = fclose(f_);
67 4 f_ = nullptr;
68
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if(failed)
69 {
70 ec.assign(errno,
71 system::generic_category());
72 return;
73 }
74 }
75 4 ec = {};
76 }
77
78 void
79 21 file_stdio::
80 open(char const* path, file_mode mode,
81 system::error_code& ec)
82 {
83
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 20 times.
21 if(f_)
84 {
85 1 fclose(f_);
86 1 f_ = nullptr;
87 }
88 21 ec = {};
89 #ifdef _WIN32
90 boost::winapi::WCHAR_ const* s;
91 detail::win32_unicode_path unicode_path(path, ec);
92 if (ec)
93 return;
94 #else
95 char const* s;
96 #endif
97
7/7
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
21 switch(mode)
98 {
99 2 default:
100 case file_mode::read:
101 #ifdef _WIN32
102 s = L"rb";
103 #else
104 2 s = "rb";
105 #endif
106 2 break;
107
108 1 case file_mode::scan:
109 #ifdef _WIN32
110 s = L"rbS";
111 #else
112 1 s = "rb";
113 #endif
114 1 break;
115
116 10 case file_mode::write:
117 #ifdef _WIN32
118 s = L"wb+";
119 #else
120 10 s = "wb+";
121 #endif
122 10 break;
123
124 2 case file_mode::write_new:
125 {
126 #ifdef _WIN32
127 # if (defined(BOOST_MSVC) && BOOST_MSVC >= 1910) || (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION >= 141)
128 s = L"wbx";
129 # else
130 std::FILE* f0;
131 auto const ev = ::_wfopen_s(&f0, unicode_path.c_str(), L"rb");
132 if(! ev)
133 {
134 std::fclose(f0);
135 ec = make_error_code(
136 system::errc::file_exists);
137 return;
138 }
139 else if(ev !=
140 system::errc::no_such_file_or_directory)
141 {
142 ec.assign(ev,
143 system::generic_category());
144 return;
145 }
146 s = L"wb";
147 # endif
148 #else
149 2 s = "wbx";
150 #endif
151 2 break;
152 }
153
154 2 case file_mode::write_existing:
155 #ifdef _WIN32
156 s = L"rb+";
157 #else
158 2 s = "rb+";
159 #endif
160 2 break;
161
162 2 case file_mode::append:
163 #ifdef _WIN32
164 s = L"ab";
165 #else
166 2 s = "ab";
167 #endif
168 2 break;
169
170 2 case file_mode::append_existing:
171 {
172 #ifdef _WIN32
173 std::FILE* f0;
174 auto const ev =
175 ::_wfopen_s(&f0, unicode_path.c_str(), L"rb+");
176 if(ev)
177 {
178 ec.assign(ev,
179 system::generic_category());
180 return;
181 }
182 #else
183 auto const f0 =
184 2 std::fopen(path, "rb+");
185
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(! f0)
186 {
187 1 ec.assign(errno,
188 system::generic_category());
189 1 return;
190 }
191 #endif
192 1 std::fclose(f0);
193 #ifdef _WIN32
194 s = L"ab";
195 #else
196 1 s = "ab";
197 #endif
198 1 break;
199 }
200 }
201
202 #ifdef _WIN32
203 auto const ev = ::_wfopen_s(
204 &f_, unicode_path.c_str(), s);
205 if(ev)
206 {
207 f_ = nullptr;
208 ec.assign(ev,
209 system::generic_category());
210 return;
211 }
212 #else
213 20 f_ = std::fopen(path, s);
214
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if(! f_)
215 {
216 2 ec.assign(errno,
217 system::generic_category());
218 2 return;
219 }
220 #endif
221 }
222
223 std::uint64_t
224 2 file_stdio::
225 size(
226 system::error_code& ec) const
227 {
228
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(! f_)
229 {
230 1 ec = make_error_code(
231 system::errc::bad_file_descriptor);
232 1 return 0;
233 }
234 1 long pos = std::ftell(f_);
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(pos == -1L)
236 {
237 ec.assign(errno,
238 system::generic_category());
239 return 0;
240 }
241 1 int result = std::fseek(f_, 0, SEEK_END);
242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(result != 0)
243 {
244 ec.assign(errno,
245 system::generic_category());
246 return 0;
247 }
248 1 long size = std::ftell(f_);
249
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(size == -1L)
250 {
251 ec.assign(errno,
252 system::generic_category());
253 std::fseek(f_, pos, SEEK_SET);
254 return 0;
255 }
256 1 result = std::fseek(f_, pos, SEEK_SET);
257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(result != 0)
258 ec.assign(errno,
259 system::generic_category());
260 else
261 1 ec = {};
262 1 return size;
263 }
264
265 std::uint64_t
266 3 file_stdio::
267 pos(
268 system::error_code& ec) const
269 {
270
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if(! f_)
271 {
272 1 ec = make_error_code(
273 system::errc::bad_file_descriptor);
274 1 return 0;
275 }
276 2 long pos = std::ftell(f_);
277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if(pos == -1L)
278 {
279 ec.assign(errno,
280 system::generic_category());
281 return 0;
282 }
283 2 ec = {};
284 2 return pos;
285 }
286
287 void
288 2 file_stdio::
289 seek(std::uint64_t offset,
290 system::error_code& ec)
291 {
292
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if(! f_)
293 {
294 1 ec = make_error_code(
295 system::errc::bad_file_descriptor);
296 1 return;
297 }
298
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if(offset > static_cast<std::uint64_t>((std::numeric_limits<long>::max)()))
299 {
300 ec = make_error_code(
301 system::errc::invalid_seek);
302 return;
303 }
304 1 int result = std::fseek(f_,
305 static_cast<long>(offset), SEEK_SET);
306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if(result != 0)
307 ec.assign(errno,
308 system::generic_category());
309 else
310 1 ec = {};
311 }
312
313 std::size_t
314 3 file_stdio::
315 read(void* buffer, std::size_t n,
316 system::error_code& ec)
317 {
318
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if(! f_)
319 {
320 1 ec = make_error_code(
321 system::errc::bad_file_descriptor);
322 1 return 0;
323 }
324 2 auto nread = std::fread(buffer, 1, n, f_);
325
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if(std::ferror(f_))
326 {
327 ec.assign(errno,
328 system::generic_category());
329 return 0;
330 }
331 2 return nread;
332 }
333
334 std::size_t
335 5 file_stdio::
336 write(void const* buffer, std::size_t n,
337 system::error_code& ec)
338 {
339
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
5 if(! f_)
340 {
341 1 ec = make_error_code(
342 system::errc::bad_file_descriptor);
343 1 return 0;
344 }
345 4 auto nwritten = std::fwrite(buffer, 1, n, f_);
346
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if(std::ferror(f_))
347 {
348 ec.assign(errno,
349 system::generic_category());
350 return 0;
351 }
352 4 return nwritten;
353 }
354
355 } // detail
356 } // http_proto
357 } // boost
358