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