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