Line data Source code
1 : //
2 : // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2025 Mohammad Nejati
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/cppalliance/http_proto
9 : //
10 :
11 : #ifndef BOOST_HTTP_PROTO_FILE_HPP
12 : #define BOOST_HTTP_PROTO_FILE_HPP
13 :
14 : #include <boost/http_proto/detail/config.hpp>
15 : #include <boost/http_proto/detail/except.hpp>
16 : #include <boost/http_proto/detail/file_posix.hpp>
17 : #include <boost/http_proto/detail/file_stdio.hpp>
18 : #include <boost/http_proto/detail/file_win32.hpp>
19 : #include <boost/http_proto/file_mode.hpp>
20 : namespace boost {
21 : namespace http_proto {
22 :
23 : /** A platform-independent file stream.
24 :
25 : This class provides a portable interface for
26 : reading from and writing to files. It is
27 : intended for use with @ref file_sink and @ref
28 : file_source to enable streaming HTTP message
29 : bodies to and from files.
30 :
31 : @par Example 1
32 : @code
33 : file f("example.zip", file_mode::scan);
34 : response.set_payload_size(f.size());
35 : serializer.start<file_source>(response, std::move(f));
36 : @endcode
37 :
38 : @par Example 2
39 : @code
40 : parser.set_body<file_sink>("example.zip", file_mode::write_new);
41 : @endcode
42 :
43 : @see
44 : @ref file_mode,
45 : @ref file_sink,
46 : @ref file_source.
47 : */
48 : class file
49 : {
50 : #if BOOST_HTTP_PROTO_USE_WIN32_FILE
51 : using impl_type = detail::file_win32;
52 : #elif BOOST_HTTP_PROTO_USE_POSIX_FILE
53 : using impl_type = detail::file_posix;
54 : #else
55 : using impl_type = detail::file_stdio;
56 : #endif
57 :
58 : impl_type impl_;
59 :
60 : public:
61 : /** The type of the underlying native file handle.
62 :
63 : This type is platform-specific.
64 : */
65 : using native_handle_type = impl_type::native_handle_type;
66 :
67 : /** Constructor.
68 :
69 : There is no open file initially.
70 : */
71 : file() = default;
72 :
73 : /** Constructor.
74 :
75 : Open a file at the given path with the specified mode.
76 :
77 : @par Exception Safety
78 : Exception thrown if operation fails.
79 :
80 : @throw system_error
81 : Operation fails.
82 :
83 : @param path The UTF-8 encoded path to the file.
84 :
85 : @param mode The file mode to use.
86 :
87 : @see
88 : @ref file_mode,
89 : @ref open.
90 : */
91 1 : file(char const* path, file_mode mode)
92 1 : {
93 1 : open(path, mode);
94 1 : }
95 :
96 : /** Constructor.
97 :
98 : The moved-from object behaves as if default-constructed.
99 : */
100 6 : file(file&& other) noexcept = default;
101 :
102 : /** Assignment
103 :
104 : The moved-from object behaves as if default-constructed.
105 : */
106 : file&
107 3 : operator=(
108 : file&& other) noexcept = default;
109 :
110 : /** Destructor
111 :
112 : If the file is open it is first closed.
113 : */
114 34 : ~file() = default;
115 :
116 : /** Returns the native handle associated with the file.
117 : */
118 : native_handle_type
119 2 : native_handle()
120 : {
121 2 : return impl_.native_handle();
122 : }
123 :
124 : /** Set the native file handle.
125 :
126 : If the file is open it is first closed.
127 :
128 : @param h The native handle to assign.
129 : */
130 : void
131 1 : native_handle(native_handle_type h)
132 : {
133 1 : impl_.native_handle(h);
134 1 : }
135 :
136 : /** Return true if the file is open.
137 : */
138 : bool
139 12 : is_open() const
140 : {
141 12 : return impl_.is_open();
142 : }
143 :
144 : /** Close the file if open.
145 :
146 : Note that, The descriptor is closed even if the function
147 : reports an error.
148 :
149 : @param ec Set to the error, if any occurred.
150 : */
151 : void
152 5 : close(system::error_code& ec)
153 : {
154 5 : impl_.close(ec);
155 5 : }
156 :
157 : /** Close the file if open.
158 :
159 : Note that, The descriptor is closed even if the function
160 : reports an error.
161 :
162 : @par Exception Safety
163 : Exception thrown if operation fails.
164 :
165 : @throw system_error
166 : Operation fails.
167 : */
168 : void
169 : close()
170 : {
171 : system::error_code ec;
172 : impl_.close(ec);
173 : if(ec.failed())
174 : detail::throw_system_error(ec);
175 : }
176 :
177 : /** Open a file at the given path with the specified mode.
178 :
179 : @param path The UTF-8 encoded path to the file.
180 :
181 : @param mode The file mode to use.
182 :
183 : @param ec Set to the error, if any occurred.
184 :
185 : @see
186 : @ref file_mode.
187 : */
188 : void
189 24 : open(char const* path, file_mode mode, system::error_code& ec)
190 : {
191 24 : impl_.open(path, mode, ec);
192 24 : }
193 :
194 : /** Open a file at the given path with the specified mode.
195 :
196 : @param path The UTF-8 encoded path to the file.
197 :
198 : @param mode The file mode to use.
199 :
200 : @par Exception Safety
201 : Exception thrown if operation fails.
202 :
203 : @throw system_error
204 : Operation fails.
205 :
206 : @see
207 : @ref file_mode.
208 : */
209 : void
210 2 : open(char const* path, file_mode mode)
211 : {
212 2 : system::error_code ec;
213 2 : impl_.open(path, mode, ec);
214 2 : if(ec.failed())
215 2 : detail::throw_system_error(ec);
216 0 : }
217 :
218 : /** Return the size of the open file in bytes.
219 :
220 : @param ec Set to the error, if any occurred.
221 : */
222 : std::uint64_t
223 2 : size(system::error_code& ec) const
224 : {
225 2 : return impl_.size(ec);
226 : }
227 :
228 : /** Return the size of the open file in bytes.
229 :
230 : @par Exception Safety
231 : Exception thrown if operation fails.
232 :
233 : @throw system_error
234 : Operation fails.
235 : */
236 : std::uint64_t
237 1 : size() const
238 : {
239 1 : system::error_code ec;
240 1 : auto r = impl_.size(ec);
241 1 : if(ec.failed())
242 1 : detail::throw_system_error(ec);
243 0 : return r;
244 : }
245 :
246 : /** Return the current position in the file, in bytes from the beginning.
247 :
248 : @param ec Set to the error, if any occurred.
249 : */
250 : std::uint64_t
251 3 : pos(system::error_code& ec) const
252 : {
253 3 : return impl_.pos(ec);
254 : }
255 :
256 : /** Return the current position in the file, in bytes from the beginning.
257 :
258 : @par Exception Safety
259 : Exception thrown if operation fails.
260 :
261 : @throw system_error
262 : Operation fails.
263 : */
264 : std::uint64_t
265 1 : pos() const
266 : {
267 1 : system::error_code ec;
268 1 : auto r = impl_.pos(ec);
269 1 : if(ec.failed())
270 1 : detail::throw_system_error(ec);
271 0 : return r;
272 : }
273 :
274 : /** Set the current position in the file.
275 :
276 : @param offset The byte offset from the beginning of the file.
277 :
278 : @param ec Set to the error, if any occurred.
279 : */
280 : void
281 2 : seek(std::uint64_t offset, system::error_code& ec)
282 : {
283 2 : impl_.seek(offset, ec);
284 2 : }
285 :
286 : /** Set the current position in the file.
287 :
288 : @par Exception Safety
289 : Exception thrown if operation fails.
290 :
291 : @throw system_error
292 : Operation fails.
293 :
294 : @param offset The byte offset from the beginning of the file.
295 : */
296 : void
297 1 : seek(std::uint64_t offset)
298 : {
299 1 : system::error_code ec;
300 1 : impl_.seek(offset, ec);
301 1 : if(ec.failed())
302 1 : detail::throw_system_error(ec);
303 0 : }
304 :
305 : /** Read data from the file.
306 :
307 : @return The number of bytes read. Returns
308 : 0 on end-of-file or if an error occurs (in
309 : which case @p ec is set).
310 :
311 : @param buffer The buffer to store the read data.
312 :
313 : @param n The number of bytes to read.
314 :
315 : @param ec Set to the error, if any occurred.
316 : */
317 : std::size_t
318 10 : read(void* buffer, std::size_t n, system::error_code& ec)
319 : {
320 10 : return impl_.read(buffer, n, ec);
321 : }
322 :
323 : /** Read data from the file.
324 :
325 : @par Exception Safety
326 : Exception thrown if operation fails.
327 :
328 : @throw system_error
329 : Operation fails.
330 :
331 : @return The number of bytes read. Returns
332 : 0 on end-of-file.
333 :
334 : @param buffer The buffer to store the read data.
335 :
336 : @param n The number of bytes to read.
337 : */
338 : std::size_t
339 1 : read(void* buffer, std::size_t n)
340 : {
341 1 : system::error_code ec;
342 1 : auto r = impl_.read(buffer, n, ec);
343 1 : if(ec.failed())
344 1 : detail::throw_system_error(ec);
345 0 : return r;
346 : }
347 :
348 : /** Write data to the file.
349 :
350 : @return The number of bytes written.
351 : Returns 0 on error (in which case @p ec is
352 : set).
353 :
354 : @param buffer The buffer containing the data to write.
355 :
356 : @param n The number of bytes to write.
357 :
358 : @param ec Set to the error, if any occurred.
359 : */
360 : std::size_t
361 10 : write(void const* buffer, std::size_t n, system::error_code& ec)
362 : {
363 10 : return impl_.write(buffer, n, ec);
364 : }
365 :
366 : /** Write data to the file.
367 :
368 : @par Exception Safety
369 : Exception thrown if operation fails.
370 :
371 : @throw system_error
372 : Operation fails.
373 :
374 : @return The number of bytes written.
375 :
376 : @param buffer The buffer containing the data to write.
377 :
378 : @param n The number of bytes to write.
379 : */
380 : std::size_t
381 1 : write(void const* buffer, std::size_t n)
382 : {
383 1 : system::error_code ec;
384 1 : auto r = impl_.write(buffer, n, ec);
385 1 : if(ec.failed())
386 1 : detail::throw_system_error(ec);
387 0 : return r;
388 : }
389 : };
390 :
391 : } // http_proto
392 : } // boost
393 :
394 : #endif
|