1 | // File based streams -*- C++ -*- |
2 | |
3 | // Copyright (C) 1997-2018 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file include/fstream |
26 | * This is a Standard C++ Library header. |
27 | */ |
28 | |
29 | // |
30 | // ISO C++ 14882: 27.8 File-based streams |
31 | // |
32 | |
33 | #ifndef _GLIBCXX_FSTREAM |
34 | #define _GLIBCXX_FSTREAM 1 |
35 | |
36 | #pragma GCC system_header |
37 | |
38 | #include <istream> |
39 | #include <ostream> |
40 | #include <bits/codecvt.h> |
41 | #include <cstdio> // For BUFSIZ |
42 | #include <bits/basic_file.h> // For __basic_file, __c_lock |
43 | #if __cplusplus >= 201103L |
44 | #include <string> // For std::string overloads. |
45 | #endif |
46 | |
47 | namespace std _GLIBCXX_VISIBILITY(default) |
48 | { |
49 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
50 | |
51 | #if __cplusplus >= 201703L |
52 | // Enable if _Path is a filesystem::path or experimental::filesystem::path |
53 | template<typename _Path, typename _Result = _Path, typename _Path2 |
54 | = decltype(std::declval<_Path&>().make_preferred().filename())> |
55 | using _If_fs_path = enable_if_t<is_same_v<_Path, _Path2>, _Result>; |
56 | #endif // C++17 |
57 | |
58 | |
59 | // [27.8.1.1] template class basic_filebuf |
60 | /** |
61 | * @brief The actual work of input and output (for files). |
62 | * @ingroup io |
63 | * |
64 | * @tparam _CharT Type of character stream. |
65 | * @tparam _Traits Traits for character type, defaults to |
66 | * char_traits<_CharT>. |
67 | * |
68 | * This class associates both its input and output sequence with an |
69 | * external disk file, and maintains a joint file position for both |
70 | * sequences. Many of its semantics are described in terms of similar |
71 | * behavior in the Standard C Library's @c FILE streams. |
72 | * |
73 | * Requirements on traits_type, specific to this class: |
74 | * - traits_type::pos_type must be fpos<traits_type::state_type> |
75 | * - traits_type::off_type must be streamoff |
76 | * - traits_type::state_type must be Assignable and DefaultConstructible, |
77 | * - traits_type::state_type() must be the initial state for codecvt. |
78 | */ |
79 | template<typename _CharT, typename _Traits> |
80 | class basic_filebuf : public basic_streambuf<_CharT, _Traits> |
81 | { |
82 | #if __cplusplus >= 201103L |
83 | template<typename _Tp> |
84 | using __chk_state = __and_<is_copy_assignable<_Tp>, |
85 | is_copy_constructible<_Tp>, |
86 | is_default_constructible<_Tp>>; |
87 | |
88 | static_assert(__chk_state<typename _Traits::state_type>::value, |
89 | "state_type must be CopyAssignable, CopyConstructible" |
90 | " and DefaultConstructible" ); |
91 | |
92 | static_assert(is_same<typename _Traits::pos_type, |
93 | fpos<typename _Traits::state_type>>::value, |
94 | "pos_type must be fpos<state_type>" ); |
95 | #endif |
96 | public: |
97 | // Types: |
98 | typedef _CharT char_type; |
99 | typedef _Traits traits_type; |
100 | typedef typename traits_type::int_type int_type; |
101 | typedef typename traits_type::pos_type pos_type; |
102 | typedef typename traits_type::off_type off_type; |
103 | |
104 | typedef basic_streambuf<char_type, traits_type> __streambuf_type; |
105 | typedef basic_filebuf<char_type, traits_type> __filebuf_type; |
106 | typedef __basic_file<char> __file_type; |
107 | typedef typename traits_type::state_type __state_type; |
108 | typedef codecvt<char_type, char, __state_type> __codecvt_type; |
109 | |
110 | friend class ios_base; // For sync_with_stdio. |
111 | |
112 | protected: |
113 | // Data Members: |
114 | // MT lock inherited from libio or other low-level io library. |
115 | __c_lock _M_lock; |
116 | |
117 | // External buffer. |
118 | __file_type _M_file; |
119 | |
120 | /// Place to stash in || out || in | out settings for current filebuf. |
121 | ios_base::openmode _M_mode; |
122 | |
123 | // Beginning state type for codecvt. |
124 | __state_type _M_state_beg; |
125 | |
126 | // During output, the state that corresponds to pptr(), |
127 | // during input, the state that corresponds to egptr() and |
128 | // _M_ext_next. |
129 | __state_type _M_state_cur; |
130 | |
131 | // Not used for output. During input, the state that corresponds |
132 | // to eback() and _M_ext_buf. |
133 | __state_type _M_state_last; |
134 | |
135 | /// Pointer to the beginning of internal buffer. |
136 | char_type* _M_buf; |
137 | |
138 | /** |
139 | * Actual size of internal buffer. This number is equal to the size |
140 | * of the put area + 1 position, reserved for the overflow char of |
141 | * a full area. |
142 | */ |
143 | size_t _M_buf_size; |
144 | |
145 | // Set iff _M_buf is allocated memory from _M_allocate_internal_buffer. |
146 | bool _M_buf_allocated; |
147 | |
148 | /** |
149 | * _M_reading == false && _M_writing == false for @b uncommitted mode; |
150 | * _M_reading == true for @b read mode; |
151 | * _M_writing == true for @b write mode; |
152 | * |
153 | * NB: _M_reading == true && _M_writing == true is unused. |
154 | */ |
155 | bool _M_reading; |
156 | bool _M_writing; |
157 | |
158 | //@{ |
159 | /** |
160 | * Necessary bits for putback buffer management. |
161 | * |
162 | * @note pbacks of over one character are not currently supported. |
163 | */ |
164 | char_type _M_pback; |
165 | char_type* _M_pback_cur_save; |
166 | char_type* _M_pback_end_save; |
167 | bool _M_pback_init; |
168 | //@} |
169 | |
170 | // Cached codecvt facet. |
171 | const __codecvt_type* _M_codecvt; |
172 | |
173 | /** |
174 | * Buffer for external characters. Used for input when |
175 | * codecvt::always_noconv() == false. When valid, this corresponds |
176 | * to eback(). |
177 | */ |
178 | char* _M_ext_buf; |
179 | |
180 | /** |
181 | * Size of buffer held by _M_ext_buf. |
182 | */ |
183 | streamsize _M_ext_buf_size; |
184 | |
185 | /** |
186 | * Pointers into the buffer held by _M_ext_buf that delimit a |
187 | * subsequence of bytes that have been read but not yet converted. |
188 | * When valid, _M_ext_next corresponds to egptr(). |
189 | */ |
190 | const char* _M_ext_next; |
191 | char* _M_ext_end; |
192 | |
193 | /** |
194 | * Initializes pback buffers, and moves normal buffers to safety. |
195 | * Assumptions: |
196 | * _M_in_cur has already been moved back |
197 | */ |
198 | void |
199 | _M_create_pback() |
200 | { |
201 | if (!_M_pback_init) |
202 | { |
203 | _M_pback_cur_save = this->gptr(); |
204 | _M_pback_end_save = this->egptr(); |
205 | this->setg(&_M_pback, &_M_pback, &_M_pback + 1); |
206 | _M_pback_init = true; |
207 | } |
208 | } |
209 | |
210 | /** |
211 | * Deactivates pback buffer contents, and restores normal buffer. |
212 | * Assumptions: |
213 | * The pback buffer has only moved forward. |
214 | */ |
215 | void |
216 | _M_destroy_pback() throw() |
217 | { |
218 | if (_M_pback_init) |
219 | { |
220 | // Length _M_in_cur moved in the pback buffer. |
221 | _M_pback_cur_save += this->gptr() != this->eback(); |
222 | this->setg(_M_buf, _M_pback_cur_save, _M_pback_end_save); |
223 | _M_pback_init = false; |
224 | } |
225 | } |
226 | |
227 | public: |
228 | // Constructors/destructor: |
229 | /** |
230 | * @brief Does not open any files. |
231 | * |
232 | * The default constructor initializes the parent class using its |
233 | * own default ctor. |
234 | */ |
235 | basic_filebuf(); |
236 | |
237 | #if __cplusplus >= 201103L |
238 | basic_filebuf(const basic_filebuf&) = delete; |
239 | basic_filebuf(basic_filebuf&&); |
240 | #endif |
241 | |
242 | /** |
243 | * @brief The destructor closes the file first. |
244 | */ |
245 | virtual |
246 | ~basic_filebuf() |
247 | { this->close(); } |
248 | |
249 | #if __cplusplus >= 201103L |
250 | basic_filebuf& operator=(const basic_filebuf&) = delete; |
251 | basic_filebuf& operator=(basic_filebuf&&); |
252 | void swap(basic_filebuf&); |
253 | #endif |
254 | |
255 | // Members: |
256 | /** |
257 | * @brief Returns true if the external file is open. |
258 | */ |
259 | bool |
260 | is_open() const throw() |
261 | { return _M_file.is_open(); } |
262 | |
263 | /** |
264 | * @brief Opens an external file. |
265 | * @param __s The name of the file. |
266 | * @param __mode The open mode flags. |
267 | * @return @c this on success, NULL on failure |
268 | * |
269 | * If a file is already open, this function immediately fails. |
270 | * Otherwise it tries to open the file named @a __s using the flags |
271 | * given in @a __mode. |
272 | * |
273 | * Table 92, adapted here, gives the relation between openmode |
274 | * combinations and the equivalent @c fopen() flags. |
275 | * (NB: lines app, in|out|app, in|app, binary|app, binary|in|out|app, |
276 | * and binary|in|app per DR 596) |
277 | * <pre> |
278 | * +---------------------------------------------------------+ |
279 | * | ios_base Flag combination stdio equivalent | |
280 | * |binary in out trunc app | |
281 | * +---------------------------------------------------------+ |
282 | * | + w | |
283 | * | + + a | |
284 | * | + a | |
285 | * | + + w | |
286 | * | + r | |
287 | * | + + r+ | |
288 | * | + + + w+ | |
289 | * | + + + a+ | |
290 | * | + + a+ | |
291 | * +---------------------------------------------------------+ |
292 | * | + + wb | |
293 | * | + + + ab | |
294 | * | + + ab | |
295 | * | + + + wb | |
296 | * | + + rb | |
297 | * | + + + r+b | |
298 | * | + + + + w+b | |
299 | * | + + + + a+b | |
300 | * | + + + a+b | |
301 | * +---------------------------------------------------------+ |
302 | * </pre> |
303 | */ |
304 | __filebuf_type* |
305 | open(const char* __s, ios_base::openmode __mode); |
306 | |
307 | #if __cplusplus >= 201103L |
308 | /** |
309 | * @brief Opens an external file. |
310 | * @param __s The name of the file. |
311 | * @param __mode The open mode flags. |
312 | * @return @c this on success, NULL on failure |
313 | */ |
314 | __filebuf_type* |
315 | open(const std::string& __s, ios_base::openmode __mode) |
316 | { return open(__s.c_str(), __mode); } |
317 | |
318 | #if __cplusplus >= 201703L |
319 | /** |
320 | * @brief Opens an external file. |
321 | * @param __s The name of the file, as a filesystem::path. |
322 | * @param __mode The open mode flags. |
323 | * @return @c this on success, NULL on failure |
324 | */ |
325 | template<typename _Path> |
326 | _If_fs_path<_Path, __filebuf_type*> |
327 | open(const _Path& __s, ios_base::openmode __mode) |
328 | { return open(__s.c_str(), __mode); } |
329 | #endif // C++17 |
330 | #endif // C++11 |
331 | |
332 | /** |
333 | * @brief Closes the currently associated file. |
334 | * @return @c this on success, NULL on failure |
335 | * |
336 | * If no file is currently open, this function immediately fails. |
337 | * |
338 | * If a <em>put buffer area</em> exists, @c overflow(eof) is |
339 | * called to flush all the characters. The file is then |
340 | * closed. |
341 | * |
342 | * If any operations fail, this function also fails. |
343 | */ |
344 | __filebuf_type* |
345 | close(); |
346 | |
347 | protected: |
348 | void |
349 | _M_allocate_internal_buffer(); |
350 | |
351 | void |
352 | _M_destroy_internal_buffer() throw(); |
353 | |
354 | // [27.8.1.4] overridden virtual functions |
355 | virtual streamsize |
356 | showmanyc(); |
357 | |
358 | // Stroustrup, 1998, p. 628 |
359 | // underflow() and uflow() functions are called to get the next |
360 | // character from the real input source when the buffer is empty. |
361 | // Buffered input uses underflow() |
362 | |
363 | virtual int_type |
364 | underflow(); |
365 | |
366 | virtual int_type |
367 | pbackfail(int_type __c = _Traits::eof()); |
368 | |
369 | // Stroustrup, 1998, p 648 |
370 | // The overflow() function is called to transfer characters to the |
371 | // real output destination when the buffer is full. A call to |
372 | // overflow(c) outputs the contents of the buffer plus the |
373 | // character c. |
374 | // 27.5.2.4.5 |
375 | // Consume some sequence of the characters in the pending sequence. |
376 | virtual int_type |
377 | overflow(int_type __c = _Traits::eof()); |
378 | |
379 | // Convert internal byte sequence to external, char-based |
380 | // sequence via codecvt. |
381 | bool |
382 | _M_convert_to_external(char_type*, streamsize); |
383 | |
384 | /** |
385 | * @brief Manipulates the buffer. |
386 | * @param __s Pointer to a buffer area. |
387 | * @param __n Size of @a __s. |
388 | * @return @c this |
389 | * |
390 | * If no file has been opened, and both @a __s and @a __n are zero, then |
391 | * the stream becomes unbuffered. Otherwise, @c __s is used as a |
392 | * buffer; see |
393 | * https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html#io.streambuf.buffering |
394 | * for more. |
395 | */ |
396 | virtual __streambuf_type* |
397 | setbuf(char_type* __s, streamsize __n); |
398 | |
399 | virtual pos_type |
400 | seekoff(off_type __off, ios_base::seekdir __way, |
401 | ios_base::openmode __mode = ios_base::in | ios_base::out); |
402 | |
403 | virtual pos_type |
404 | seekpos(pos_type __pos, |
405 | ios_base::openmode __mode = ios_base::in | ios_base::out); |
406 | |
407 | // Common code for seekoff, seekpos, and overflow |
408 | pos_type |
409 | _M_seek(off_type __off, ios_base::seekdir __way, __state_type __state); |
410 | |
411 | int |
412 | _M_get_ext_pos(__state_type &__state); |
413 | |
414 | virtual int |
415 | sync(); |
416 | |
417 | virtual void |
418 | imbue(const locale& __loc); |
419 | |
420 | virtual streamsize |
421 | xsgetn(char_type* __s, streamsize __n); |
422 | |
423 | virtual streamsize |
424 | xsputn(const char_type* __s, streamsize __n); |
425 | |
426 | // Flushes output buffer, then writes unshift sequence. |
427 | bool |
428 | _M_terminate_output(); |
429 | |
430 | /** |
431 | * This function sets the pointers of the internal buffer, both get |
432 | * and put areas. Typically: |
433 | * |
434 | * __off == egptr() - eback() upon underflow/uflow (@b read mode); |
435 | * __off == 0 upon overflow (@b write mode); |
436 | * __off == -1 upon open, setbuf, seekoff/pos (@b uncommitted mode). |
437 | * |
438 | * NB: epptr() - pbase() == _M_buf_size - 1, since _M_buf_size |
439 | * reflects the actual allocated memory and the last cell is reserved |
440 | * for the overflow char of a full put area. |
441 | */ |
442 | void |
443 | _M_set_buffer(streamsize __off) |
444 | { |
445 | const bool __testin = _M_mode & ios_base::in; |
446 | const bool __testout = (_M_mode & ios_base::out |
447 | || _M_mode & ios_base::app); |
448 | |
449 | if (__testin && __off > 0) |
450 | this->setg(_M_buf, _M_buf, _M_buf + __off); |
451 | else |
452 | this->setg(_M_buf, _M_buf, _M_buf); |
453 | |
454 | if (__testout && __off == 0 && _M_buf_size > 1 ) |
455 | this->setp(_M_buf, _M_buf + _M_buf_size - 1); |
456 | else |
457 | this->setp(0, 0); |
458 | } |
459 | }; |
460 | |
461 | // [27.8.1.5] Template class basic_ifstream |
462 | /** |
463 | * @brief Controlling input for files. |
464 | * @ingroup io |
465 | * |
466 | * @tparam _CharT Type of character stream. |
467 | * @tparam _Traits Traits for character type, defaults to |
468 | * char_traits<_CharT>. |
469 | * |
470 | * This class supports reading from named files, using the inherited |
471 | * functions from std::basic_istream. To control the associated |
472 | * sequence, an instance of std::basic_filebuf is used, which this page |
473 | * refers to as @c sb. |
474 | */ |
475 | template<typename _CharT, typename _Traits> |
476 | class basic_ifstream : public basic_istream<_CharT, _Traits> |
477 | { |
478 | public: |
479 | // Types: |
480 | typedef _CharT char_type; |
481 | typedef _Traits traits_type; |
482 | typedef typename traits_type::int_type int_type; |
483 | typedef typename traits_type::pos_type pos_type; |
484 | typedef typename traits_type::off_type off_type; |
485 | |
486 | // Non-standard types: |
487 | typedef basic_filebuf<char_type, traits_type> __filebuf_type; |
488 | typedef basic_istream<char_type, traits_type> __istream_type; |
489 | |
490 | private: |
491 | __filebuf_type _M_filebuf; |
492 | |
493 | public: |
494 | // Constructors/Destructors: |
495 | /** |
496 | * @brief Default constructor. |
497 | * |
498 | * Initializes @c sb using its default constructor, and passes |
499 | * @c &sb to the base class initializer. Does not open any files |
500 | * (you haven't given it a filename to open). |
501 | */ |
502 | basic_ifstream() : __istream_type(), _M_filebuf() |
503 | { this->init(&_M_filebuf); } |
504 | |
505 | /** |
506 | * @brief Create an input file stream. |
507 | * @param __s Null terminated string specifying the filename. |
508 | * @param __mode Open file in specified mode (see std::ios_base). |
509 | * |
510 | * @c ios_base::in is automatically included in @a __mode. |
511 | */ |
512 | explicit |
513 | basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in) |
514 | : __istream_type(), _M_filebuf() |
515 | { |
516 | this->init(&_M_filebuf); |
517 | this->open(__s, __mode); |
518 | } |
519 | |
520 | #if __cplusplus >= 201103L |
521 | /** |
522 | * @brief Create an input file stream. |
523 | * @param __s std::string specifying the filename. |
524 | * @param __mode Open file in specified mode (see std::ios_base). |
525 | * |
526 | * @c ios_base::in is automatically included in @a __mode. |
527 | */ |
528 | explicit |
529 | basic_ifstream(const std::string& __s, |
530 | ios_base::openmode __mode = ios_base::in) |
531 | : __istream_type(), _M_filebuf() |
532 | { |
533 | this->init(&_M_filebuf); |
534 | this->open(__s, __mode); |
535 | } |
536 | |
537 | #if __cplusplus >= 201703L |
538 | /** |
539 | * @param Create an input file stream. |
540 | * @param __s filesystem::path specifying the filename. |
541 | * @param __mode Open file in specified mode (see std::ios_base). |
542 | * |
543 | * @c ios_base::in is automatically included in @a __mode. |
544 | */ |
545 | template<typename _Path, typename _Require = _If_fs_path<_Path>> |
546 | basic_ifstream(const _Path& __s, |
547 | ios_base::openmode __mode = ios_base::in) |
548 | : basic_ifstream(__s.c_str(), __mode) |
549 | { } |
550 | #endif // C++17 |
551 | |
552 | basic_ifstream(const basic_ifstream&) = delete; |
553 | |
554 | basic_ifstream(basic_ifstream&& __rhs) |
555 | : __istream_type(std::move(__rhs)), |
556 | _M_filebuf(std::move(__rhs._M_filebuf)) |
557 | { __istream_type::set_rdbuf(&_M_filebuf); } |
558 | #endif // C++11 |
559 | |
560 | /** |
561 | * @brief The destructor does nothing. |
562 | * |
563 | * The file is closed by the filebuf object, not the formatting |
564 | * stream. |
565 | */ |
566 | ~basic_ifstream() |
567 | { } |
568 | |
569 | #if __cplusplus >= 201103L |
570 | // 27.8.3.2 Assign and swap: |
571 | |
572 | basic_ifstream& |
573 | operator=(const basic_ifstream&) = delete; |
574 | |
575 | basic_ifstream& |
576 | operator=(basic_ifstream&& __rhs) |
577 | { |
578 | __istream_type::operator=(std::move(__rhs)); |
579 | _M_filebuf = std::move(__rhs._M_filebuf); |
580 | return *this; |
581 | } |
582 | |
583 | void |
584 | swap(basic_ifstream& __rhs) |
585 | { |
586 | __istream_type::swap(__rhs); |
587 | _M_filebuf.swap(__rhs._M_filebuf); |
588 | } |
589 | #endif |
590 | |
591 | // Members: |
592 | /** |
593 | * @brief Accessing the underlying buffer. |
594 | * @return The current basic_filebuf buffer. |
595 | * |
596 | * This hides both signatures of std::basic_ios::rdbuf(). |
597 | */ |
598 | __filebuf_type* |
599 | rdbuf() const |
600 | { return const_cast<__filebuf_type*>(&_M_filebuf); } |
601 | |
602 | /** |
603 | * @brief Wrapper to test for an open file. |
604 | * @return @c rdbuf()->is_open() |
605 | */ |
606 | bool |
607 | is_open() |
608 | { return _M_filebuf.is_open(); } |
609 | |
610 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
611 | // 365. Lack of const-qualification in clause 27 |
612 | bool |
613 | is_open() const |
614 | { return _M_filebuf.is_open(); } |
615 | |
616 | /** |
617 | * @brief Opens an external file. |
618 | * @param __s The name of the file. |
619 | * @param __mode The open mode flags. |
620 | * |
621 | * Calls @c std::basic_filebuf::open(s,__mode|in). If that function |
622 | * fails, @c failbit is set in the stream's error state. |
623 | */ |
624 | void |
625 | open(const char* __s, ios_base::openmode __mode = ios_base::in) |
626 | { |
627 | if (!_M_filebuf.open(__s, __mode | ios_base::in)) |
628 | this->setstate(ios_base::failbit); |
629 | else |
630 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
631 | // 409. Closing an fstream should clear error state |
632 | this->clear(); |
633 | } |
634 | |
635 | #if __cplusplus >= 201103L |
636 | /** |
637 | * @brief Opens an external file. |
638 | * @param __s The name of the file. |
639 | * @param __mode The open mode flags. |
640 | * |
641 | * Calls @c std::basic_filebuf::open(__s,__mode|in). If that function |
642 | * fails, @c failbit is set in the stream's error state. |
643 | */ |
644 | void |
645 | open(const std::string& __s, ios_base::openmode __mode = ios_base::in) |
646 | { |
647 | if (!_M_filebuf.open(__s, __mode | ios_base::in)) |
648 | this->setstate(ios_base::failbit); |
649 | else |
650 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
651 | // 409. Closing an fstream should clear error state |
652 | this->clear(); |
653 | } |
654 | |
655 | #if __cplusplus >= 201703L |
656 | /** |
657 | * @brief Opens an external file. |
658 | * @param __s The name of the file, as a filesystem::path. |
659 | * @param __mode The open mode flags. |
660 | * |
661 | * Calls @c std::basic_filebuf::open(__s,__mode|in). If that function |
662 | * fails, @c failbit is set in the stream's error state. |
663 | */ |
664 | template<typename _Path> |
665 | _If_fs_path<_Path, void> |
666 | open(const _Path& __s, ios_base::openmode __mode = ios_base::in) |
667 | { open(__s.c_str(), __mode); } |
668 | #endif // C++17 |
669 | #endif // C++11 |
670 | |
671 | /** |
672 | * @brief Close the file. |
673 | * |
674 | * Calls @c std::basic_filebuf::close(). If that function |
675 | * fails, @c failbit is set in the stream's error state. |
676 | */ |
677 | void |
678 | close() |
679 | { |
680 | if (!_M_filebuf.close()) |
681 | this->setstate(ios_base::failbit); |
682 | } |
683 | }; |
684 | |
685 | |
686 | // [27.8.1.8] Template class basic_ofstream |
687 | /** |
688 | * @brief Controlling output for files. |
689 | * @ingroup io |
690 | * |
691 | * @tparam _CharT Type of character stream. |
692 | * @tparam _Traits Traits for character type, defaults to |
693 | * char_traits<_CharT>. |
694 | * |
695 | * This class supports reading from named files, using the inherited |
696 | * functions from std::basic_ostream. To control the associated |
697 | * sequence, an instance of std::basic_filebuf is used, which this page |
698 | * refers to as @c sb. |
699 | */ |
700 | template<typename _CharT, typename _Traits> |
701 | class basic_ofstream : public basic_ostream<_CharT,_Traits> |
702 | { |
703 | public: |
704 | // Types: |
705 | typedef _CharT char_type; |
706 | typedef _Traits traits_type; |
707 | typedef typename traits_type::int_type int_type; |
708 | typedef typename traits_type::pos_type pos_type; |
709 | typedef typename traits_type::off_type off_type; |
710 | |
711 | // Non-standard types: |
712 | typedef basic_filebuf<char_type, traits_type> __filebuf_type; |
713 | typedef basic_ostream<char_type, traits_type> __ostream_type; |
714 | |
715 | private: |
716 | __filebuf_type _M_filebuf; |
717 | |
718 | public: |
719 | // Constructors: |
720 | /** |
721 | * @brief Default constructor. |
722 | * |
723 | * Initializes @c sb using its default constructor, and passes |
724 | * @c &sb to the base class initializer. Does not open any files |
725 | * (you haven't given it a filename to open). |
726 | */ |
727 | basic_ofstream(): __ostream_type(), _M_filebuf() |
728 | { this->init(&_M_filebuf); } |
729 | |
730 | /** |
731 | * @brief Create an output file stream. |
732 | * @param __s Null terminated string specifying the filename. |
733 | * @param __mode Open file in specified mode (see std::ios_base). |
734 | * |
735 | * @c ios_base::out is automatically included in @a __mode. |
736 | */ |
737 | explicit |
738 | basic_ofstream(const char* __s, |
739 | ios_base::openmode __mode = ios_base::out) |
740 | : __ostream_type(), _M_filebuf() |
741 | { |
742 | this->init(&_M_filebuf); |
743 | this->open(__s, __mode); |
744 | } |
745 | |
746 | #if __cplusplus >= 201103L |
747 | /** |
748 | * @brief Create an output file stream. |
749 | * @param __s std::string specifying the filename. |
750 | * @param __mode Open file in specified mode (see std::ios_base). |
751 | * |
752 | * @c ios_base::out is automatically included in @a __mode. |
753 | */ |
754 | explicit |
755 | basic_ofstream(const std::string& __s, |
756 | ios_base::openmode __mode = ios_base::out) |
757 | : __ostream_type(), _M_filebuf() |
758 | { |
759 | this->init(&_M_filebuf); |
760 | this->open(__s, __mode); |
761 | } |
762 | |
763 | #if __cplusplus >= 201703L |
764 | /** |
765 | * @param Create an output file stream. |
766 | * @param __s filesystem::path specifying the filename. |
767 | * @param __mode Open file in specified mode (see std::ios_base). |
768 | * |
769 | * @c ios_base::out is automatically included in @a __mode. |
770 | */ |
771 | template<typename _Path, typename _Require = _If_fs_path<_Path>> |
772 | basic_ofstream(const _Path& __s, |
773 | ios_base::openmode __mode = ios_base::out) |
774 | : basic_ofstream(__s.c_str(), __mode) |
775 | { } |
776 | #endif // C++17 |
777 | |
778 | basic_ofstream(const basic_ofstream&) = delete; |
779 | |
780 | basic_ofstream(basic_ofstream&& __rhs) |
781 | : __ostream_type(std::move(__rhs)), |
782 | _M_filebuf(std::move(__rhs._M_filebuf)) |
783 | { __ostream_type::set_rdbuf(&_M_filebuf); } |
784 | #endif |
785 | |
786 | /** |
787 | * @brief The destructor does nothing. |
788 | * |
789 | * The file is closed by the filebuf object, not the formatting |
790 | * stream. |
791 | */ |
792 | ~basic_ofstream() |
793 | { } |
794 | |
795 | #if __cplusplus >= 201103L |
796 | // 27.8.3.2 Assign and swap: |
797 | |
798 | basic_ofstream& |
799 | operator=(const basic_ofstream&) = delete; |
800 | |
801 | basic_ofstream& |
802 | operator=(basic_ofstream&& __rhs) |
803 | { |
804 | __ostream_type::operator=(std::move(__rhs)); |
805 | _M_filebuf = std::move(__rhs._M_filebuf); |
806 | return *this; |
807 | } |
808 | |
809 | void |
810 | swap(basic_ofstream& __rhs) |
811 | { |
812 | __ostream_type::swap(__rhs); |
813 | _M_filebuf.swap(__rhs._M_filebuf); |
814 | } |
815 | #endif |
816 | |
817 | // Members: |
818 | /** |
819 | * @brief Accessing the underlying buffer. |
820 | * @return The current basic_filebuf buffer. |
821 | * |
822 | * This hides both signatures of std::basic_ios::rdbuf(). |
823 | */ |
824 | __filebuf_type* |
825 | rdbuf() const |
826 | { return const_cast<__filebuf_type*>(&_M_filebuf); } |
827 | |
828 | /** |
829 | * @brief Wrapper to test for an open file. |
830 | * @return @c rdbuf()->is_open() |
831 | */ |
832 | bool |
833 | is_open() |
834 | { return _M_filebuf.is_open(); } |
835 | |
836 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
837 | // 365. Lack of const-qualification in clause 27 |
838 | bool |
839 | is_open() const |
840 | { return _M_filebuf.is_open(); } |
841 | |
842 | /** |
843 | * @brief Opens an external file. |
844 | * @param __s The name of the file. |
845 | * @param __mode The open mode flags. |
846 | * |
847 | * Calls @c std::basic_filebuf::open(__s,__mode|out). If that |
848 | * function fails, @c failbit is set in the stream's error state. |
849 | */ |
850 | void |
851 | open(const char* __s, ios_base::openmode __mode = ios_base::out) |
852 | { |
853 | if (!_M_filebuf.open(__s, __mode | ios_base::out)) |
854 | this->setstate(ios_base::failbit); |
855 | else |
856 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
857 | // 409. Closing an fstream should clear error state |
858 | this->clear(); |
859 | } |
860 | |
861 | #if __cplusplus >= 201103L |
862 | /** |
863 | * @brief Opens an external file. |
864 | * @param __s The name of the file. |
865 | * @param __mode The open mode flags. |
866 | * |
867 | * Calls @c std::basic_filebuf::open(s,mode|out). If that |
868 | * function fails, @c failbit is set in the stream's error state. |
869 | */ |
870 | void |
871 | open(const std::string& __s, ios_base::openmode __mode = ios_base::out) |
872 | { |
873 | if (!_M_filebuf.open(__s, __mode | ios_base::out)) |
874 | this->setstate(ios_base::failbit); |
875 | else |
876 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
877 | // 409. Closing an fstream should clear error state |
878 | this->clear(); |
879 | } |
880 | |
881 | #if __cplusplus >= 201703L |
882 | /** |
883 | * @brief Opens an external file. |
884 | * @param __s The name of the file, as a filesystem::path. |
885 | * @param __mode The open mode flags. |
886 | * |
887 | * Calls @c std::basic_filebuf::open(__s,__mode|out). If that |
888 | * function fails, @c failbit is set in the stream's error state. |
889 | */ |
890 | template<typename _Path> |
891 | _If_fs_path<_Path, void> |
892 | open(const _Path& __s, ios_base::openmode __mode = ios_base::out) |
893 | { open(__s.c_str(), __mode); } |
894 | #endif // C++17 |
895 | #endif // C++11 |
896 | |
897 | /** |
898 | * @brief Close the file. |
899 | * |
900 | * Calls @c std::basic_filebuf::close(). If that function |
901 | * fails, @c failbit is set in the stream's error state. |
902 | */ |
903 | void |
904 | close() |
905 | { |
906 | if (!_M_filebuf.close()) |
907 | this->setstate(ios_base::failbit); |
908 | } |
909 | }; |
910 | |
911 | |
912 | // [27.8.1.11] Template class basic_fstream |
913 | /** |
914 | * @brief Controlling input and output for files. |
915 | * @ingroup io |
916 | * |
917 | * @tparam _CharT Type of character stream. |
918 | * @tparam _Traits Traits for character type, defaults to |
919 | * char_traits<_CharT>. |
920 | * |
921 | * This class supports reading from and writing to named files, using |
922 | * the inherited functions from std::basic_iostream. To control the |
923 | * associated sequence, an instance of std::basic_filebuf is used, which |
924 | * this page refers to as @c sb. |
925 | */ |
926 | template<typename _CharT, typename _Traits> |
927 | class basic_fstream : public basic_iostream<_CharT, _Traits> |
928 | { |
929 | public: |
930 | // Types: |
931 | typedef _CharT char_type; |
932 | typedef _Traits traits_type; |
933 | typedef typename traits_type::int_type int_type; |
934 | typedef typename traits_type::pos_type pos_type; |
935 | typedef typename traits_type::off_type off_type; |
936 | |
937 | // Non-standard types: |
938 | typedef basic_filebuf<char_type, traits_type> __filebuf_type; |
939 | typedef basic_ios<char_type, traits_type> __ios_type; |
940 | typedef basic_iostream<char_type, traits_type> __iostream_type; |
941 | |
942 | private: |
943 | __filebuf_type _M_filebuf; |
944 | |
945 | public: |
946 | // Constructors/destructor: |
947 | /** |
948 | * @brief Default constructor. |
949 | * |
950 | * Initializes @c sb using its default constructor, and passes |
951 | * @c &sb to the base class initializer. Does not open any files |
952 | * (you haven't given it a filename to open). |
953 | */ |
954 | basic_fstream() |
955 | : __iostream_type(), _M_filebuf() |
956 | { this->init(&_M_filebuf); } |
957 | |
958 | /** |
959 | * @brief Create an input/output file stream. |
960 | * @param __s Null terminated string specifying the filename. |
961 | * @param __mode Open file in specified mode (see std::ios_base). |
962 | */ |
963 | explicit |
964 | basic_fstream(const char* __s, |
965 | ios_base::openmode __mode = ios_base::in | ios_base::out) |
966 | : __iostream_type(0), _M_filebuf() |
967 | { |
968 | this->init(&_M_filebuf); |
969 | this->open(__s, __mode); |
970 | } |
971 | |
972 | #if __cplusplus >= 201103L |
973 | /** |
974 | * @brief Create an input/output file stream. |
975 | * @param __s Null terminated string specifying the filename. |
976 | * @param __mode Open file in specified mode (see std::ios_base). |
977 | */ |
978 | explicit |
979 | basic_fstream(const std::string& __s, |
980 | ios_base::openmode __mode = ios_base::in | ios_base::out) |
981 | : __iostream_type(0), _M_filebuf() |
982 | { |
983 | this->init(&_M_filebuf); |
984 | this->open(__s, __mode); |
985 | } |
986 | |
987 | #if __cplusplus >= 201703L |
988 | /** |
989 | * @param Create an input/output file stream. |
990 | * @param __s filesystem::path specifying the filename. |
991 | * @param __mode Open file in specified mode (see std::ios_base). |
992 | */ |
993 | template<typename _Path, typename _Require = _If_fs_path<_Path>> |
994 | basic_fstream(const _Path& __s, |
995 | ios_base::openmode __mode = ios_base::in | ios_base::out) |
996 | : basic_fstream(__s.c_str(), __mode) |
997 | { } |
998 | #endif // C++17 |
999 | |
1000 | basic_fstream(const basic_fstream&) = delete; |
1001 | |
1002 | basic_fstream(basic_fstream&& __rhs) |
1003 | : __iostream_type(std::move(__rhs)), |
1004 | _M_filebuf(std::move(__rhs._M_filebuf)) |
1005 | { __iostream_type::set_rdbuf(&_M_filebuf); } |
1006 | #endif |
1007 | |
1008 | /** |
1009 | * @brief The destructor does nothing. |
1010 | * |
1011 | * The file is closed by the filebuf object, not the formatting |
1012 | * stream. |
1013 | */ |
1014 | ~basic_fstream() |
1015 | { } |
1016 | |
1017 | #if __cplusplus >= 201103L |
1018 | // 27.8.3.2 Assign and swap: |
1019 | |
1020 | basic_fstream& |
1021 | operator=(const basic_fstream&) = delete; |
1022 | |
1023 | basic_fstream& |
1024 | operator=(basic_fstream&& __rhs) |
1025 | { |
1026 | __iostream_type::operator=(std::move(__rhs)); |
1027 | _M_filebuf = std::move(__rhs._M_filebuf); |
1028 | return *this; |
1029 | } |
1030 | |
1031 | void |
1032 | swap(basic_fstream& __rhs) |
1033 | { |
1034 | __iostream_type::swap(__rhs); |
1035 | _M_filebuf.swap(__rhs._M_filebuf); |
1036 | } |
1037 | #endif |
1038 | |
1039 | // Members: |
1040 | /** |
1041 | * @brief Accessing the underlying buffer. |
1042 | * @return The current basic_filebuf buffer. |
1043 | * |
1044 | * This hides both signatures of std::basic_ios::rdbuf(). |
1045 | */ |
1046 | __filebuf_type* |
1047 | rdbuf() const |
1048 | { return const_cast<__filebuf_type*>(&_M_filebuf); } |
1049 | |
1050 | /** |
1051 | * @brief Wrapper to test for an open file. |
1052 | * @return @c rdbuf()->is_open() |
1053 | */ |
1054 | bool |
1055 | is_open() |
1056 | { return _M_filebuf.is_open(); } |
1057 | |
1058 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1059 | // 365. Lack of const-qualification in clause 27 |
1060 | bool |
1061 | is_open() const |
1062 | { return _M_filebuf.is_open(); } |
1063 | |
1064 | /** |
1065 | * @brief Opens an external file. |
1066 | * @param __s The name of the file. |
1067 | * @param __mode The open mode flags. |
1068 | * |
1069 | * Calls @c std::basic_filebuf::open(__s,__mode). If that |
1070 | * function fails, @c failbit is set in the stream's error state. |
1071 | */ |
1072 | void |
1073 | open(const char* __s, |
1074 | ios_base::openmode __mode = ios_base::in | ios_base::out) |
1075 | { |
1076 | if (!_M_filebuf.open(__s, __mode)) |
1077 | this->setstate(ios_base::failbit); |
1078 | else |
1079 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1080 | // 409. Closing an fstream should clear error state |
1081 | this->clear(); |
1082 | } |
1083 | |
1084 | #if __cplusplus >= 201103L |
1085 | /** |
1086 | * @brief Opens an external file. |
1087 | * @param __s The name of the file. |
1088 | * @param __mode The open mode flags. |
1089 | * |
1090 | * Calls @c std::basic_filebuf::open(__s,__mode). If that |
1091 | * function fails, @c failbit is set in the stream's error state. |
1092 | */ |
1093 | void |
1094 | open(const std::string& __s, |
1095 | ios_base::openmode __mode = ios_base::in | ios_base::out) |
1096 | { |
1097 | if (!_M_filebuf.open(__s, __mode)) |
1098 | this->setstate(ios_base::failbit); |
1099 | else |
1100 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
1101 | // 409. Closing an fstream should clear error state |
1102 | this->clear(); |
1103 | } |
1104 | |
1105 | #if __cplusplus >= 201703L |
1106 | /** |
1107 | * @brief Opens an external file. |
1108 | * @param __s The name of the file, as a filesystem::path. |
1109 | * @param __mode The open mode flags. |
1110 | * |
1111 | * Calls @c std::basic_filebuf::open(__s,__mode). If that |
1112 | * function fails, @c failbit is set in the stream's error state. |
1113 | */ |
1114 | template<typename _Path> |
1115 | _If_fs_path<_Path, void> |
1116 | open(const _Path& __s, |
1117 | ios_base::openmode __mode = ios_base::in | ios_base::out) |
1118 | { open(__s.c_str(), __mode); } |
1119 | #endif // C++17 |
1120 | #endif // C++11 |
1121 | |
1122 | /** |
1123 | * @brief Close the file. |
1124 | * |
1125 | * Calls @c std::basic_filebuf::close(). If that function |
1126 | * fails, @c failbit is set in the stream's error state. |
1127 | */ |
1128 | void |
1129 | close() |
1130 | { |
1131 | if (!_M_filebuf.close()) |
1132 | this->setstate(ios_base::failbit); |
1133 | } |
1134 | }; |
1135 | |
1136 | #if __cplusplus >= 201103L |
1137 | /// Swap specialization for filebufs. |
1138 | template <class _CharT, class _Traits> |
1139 | inline void |
1140 | swap(basic_filebuf<_CharT, _Traits>& __x, |
1141 | basic_filebuf<_CharT, _Traits>& __y) |
1142 | { __x.swap(__y); } |
1143 | |
1144 | /// Swap specialization for ifstreams. |
1145 | template <class _CharT, class _Traits> |
1146 | inline void |
1147 | swap(basic_ifstream<_CharT, _Traits>& __x, |
1148 | basic_ifstream<_CharT, _Traits>& __y) |
1149 | { __x.swap(__y); } |
1150 | |
1151 | /// Swap specialization for ofstreams. |
1152 | template <class _CharT, class _Traits> |
1153 | inline void |
1154 | swap(basic_ofstream<_CharT, _Traits>& __x, |
1155 | basic_ofstream<_CharT, _Traits>& __y) |
1156 | { __x.swap(__y); } |
1157 | |
1158 | /// Swap specialization for fstreams. |
1159 | template <class _CharT, class _Traits> |
1160 | inline void |
1161 | swap(basic_fstream<_CharT, _Traits>& __x, |
1162 | basic_fstream<_CharT, _Traits>& __y) |
1163 | { __x.swap(__y); } |
1164 | #endif |
1165 | |
1166 | _GLIBCXX_END_NAMESPACE_VERSION |
1167 | } // namespace |
1168 | |
1169 | #include <bits/fstream.tcc> |
1170 | |
1171 | #endif /* _GLIBCXX_FSTREAM */ |
1172 | |