GCC Code Coverage Report


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