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