# fstream

Go to the documentation of this file.

    00001 // File based streams -*- C++ -*-
    00002
    00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
    00004 // Free Software Foundation, Inc.
    00005 //
    00006 // This file is part of the GNU ISO C++ Library.  This library is free
    00007 // software; you can redistribute it and/or modify it under the
    00008 // terms of the GNU General Public License as published by the
    00009 // Free Software Foundation; either version 2, or (at your option)
    00010 // any later version.
    00011
    00012 // This library is distributed in the hope that it will be useful,
    00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00015 // GNU General Public License for more details.
    00016
    00017 // You should have received a copy of the GNU General Public License along
    00018 // with this library; see the file COPYING.  If not, write to the Free
    00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
    00020 // USA.
    00021
    00022 // As a special exception, you may use this file as part of a free software
    00023 // library without restriction.  Specifically, if other files instantiate
    00024 // templates or use macros or inline functions from this file, or you compile
    00025 // this file and link it with other files to produce an executable, this
    00026 // file does not by itself cause the resulting executable to be covered by
    00027 // the GNU General Public License.  This exception does not however
    00028 // invalidate any other reasons why the executable file might be covered by
    00029 // the GNU General Public License.
    00030
    00031 //
    00032 // ISO C++ 14882: 27.8  File-based streams
    00033 //
    00034
    00040 #ifndef _CPP_FSTREAM
    00041 #define _CPP_FSTREAM    1
    00042
    00043 #pragma GCC system_header
    00044
    00045 #include <istream>
    00046 #include <ostream>
    00047 #include <locale>   // For codecvt
    00048 #include <bits/basic_file.h>
    00049 #include <bits/gthr.h>
    00050
    00051 namespace std
    00052 {
    00053   // [27.8.1.1] template class basic_filebuf
    00062   template<typename _CharT, typename _Traits>
    00063     class basic_filebuf : public basic_streambuf<_CharT, _Traits>
    00064     {
    00065     public:
    00066       // Types:
    00067       typedef _CharT                                char_type;
    00068       typedef _Traits                               traits_type;
    00069       typedef typename traits_type::int_type        int_type;
    00070       typedef typename traits_type::pos_type        pos_type;
    00071       typedef typename traits_type::off_type        off_type;
    00072
    00074
    00079       typedef basic_streambuf<char_type, traits_type>   __streambuf_type;
    00080       typedef basic_filebuf<char_type, traits_type>     __filebuf_type;
    00081       typedef __basic_file<char>                __file_type;
    00082       typedef typename traits_type::state_type          __state_type;
    00083       typedef codecvt<char_type, char, __state_type>    __codecvt_type;
    00084       typedef typename __codecvt_type::result           __res_type;
    00085       typedef ctype<char_type>                          __ctype_type;
    00087
    00088       friend class ios_base; // For sync_with_stdio.
    00089
    00090     protected:
    00091       // Data Members:
    00092       // MT lock inherited from libio or other low-level io library.
    00098       __c_lock              _M_lock;
    00099
    00100       // External buffer.
    00106       __file_type       _M_file;
    00107
    00108       // Current and beginning state type for codecvt.
    00114       __state_type      _M_state_cur;
    00115       __state_type      _M_state_beg;
    00116
    00117       // Set iff _M_buf is allocated memory from _M_allocate_internal_buffer.
    00123       bool          _M_buf_allocated;
    00124
    00125       // XXX Needed?
    00126       bool          _M_last_overflowed;
    00127
    00128       // The position in the buffer corresponding to the external file
    00129       // pointer.
    00135       char_type*        _M_filepos;
    00136
    00137     public:
    00138       // Constructors/destructor:
    00145       basic_filebuf();
    00146
    00150       virtual
    00151       ~basic_filebuf()
    00152       {
    00153     this->close();
    00154     _M_last_overflowed = false;
    00155       }
    00156
    00157       // Members:
    00161       bool
    00162       is_open() const { return _M_file.is_open(); }
    00163
    00177       __filebuf_type*
    00178       open(const char* __s, ios_base::openmode __mode);
    00179
    00191       __filebuf_type*
    00192       close();
    00193
    00194     protected:
    00200       void
    00201       _M_allocate_internal_buffer();
    00202
    00208       void
    00209       _M_destroy_internal_buffer();
    00210
    00211       // [27.8.1.4] overridden virtual functions
    00212       // [documentation is inherited]
    00213       virtual streamsize
    00214       showmanyc();
    00215
    00216       // Stroustrup, 1998, p. 628
    00217       // underflow() and uflow() functions are called to get the next
    00218       // charater from the real input source when the buffer is empty.
    00219       // Buffered input uses underflow()
    00220
    00221       // The only difference between underflow() and uflow() is that the
    00222       // latter bumps _M_in_cur after the read.  In the sync_with_stdio
    00223       // case, this is important, as we need to unget the read character in
    00224       // the underflow() case in order to maintain synchronization.  So
    00225       // instead of calling underflow() from uflow(), we create a common
    00226       // subroutine to do the real work.
    00232       int_type
    00233       _M_underflow_common(bool __bump);
    00234
    00235       // [documentation is inherited]
    00236       virtual int_type
    00237       underflow() { return _M_underflow_common(false); }
    00238
    00239       // [documentation is inherited]
    00240       virtual int_type
    00241       uflow() { return _M_underflow_common(true); }
    00242
    00243       // [documentation is inherited]
    00244       virtual int_type
    00245       pbackfail(int_type __c = _Traits::eof());
    00246
    00247       // NB: For what the standard expects of the overflow function,
    00248       // see _M_really_overflow(), below. Because basic_streambuf's
    00249       // sputc/sputn call overflow directly, and the complications of
    00250       // this implementation's setting of the initial pointers all
    00251       // equal to _M_buf when initializing, it seems essential to have
    00252       // this in actuality be a helper function that checks for the
    00253       // eccentricities of this implementation, and then call
    00254       // overflow() if indeed the buffer is full.
    00255
    00256       // [documentation is inherited]
    00257       virtual int_type
    00258       overflow(int_type __c = _Traits::eof());
    00259
    00260       // Stroustrup, 1998, p 648
    00261       // The overflow() function is called to transfer characters to the
    00262       // real output destination when the buffer is full. A call to
    00263       // overflow(c) outputs the contents of the buffer plus the
    00264       // character c.
    00265       // 27.5.2.4.5
    00266       // Consume some sequence of the characters in the pending sequence.
    00272       int_type
    00273       _M_really_overflow(int_type __c = _Traits::eof());
    00274
    00275       // Convert internal byte sequence to external, char-based
    00276       // sequence via codecvt.
    00282       void
    00283       _M_convert_to_external(char_type*, streamsize, streamsize&, streamsize&);
    00284
    00297       virtual __streambuf_type*
    00298       setbuf(char_type* __s, streamsize __n);
    00299
    00300       // [documentation is inherited]
    00301       virtual pos_type
    00302       seekoff(off_type __off, ios_base::seekdir __way,
    00303           ios_base::openmode __mode = ios_base::in | ios_base::out);
    00304
    00305       // [documentation is inherited]
    00306       virtual pos_type
    00307       seekpos(pos_type __pos,
    00308           ios_base::openmode __mode = ios_base::in | ios_base::out);
    00309
    00310       // [documentation is inherited]
    00311       virtual int
    00312       sync()
    00313       {
    00314     bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
    00315
    00316     // Make sure that the internal buffer resyncs its idea of
    00317     // the file position with the external file.
    00318     if (__testput)
    00319       {
    00320         // Need to restore current position after the write.
    00321         off_type __off = _M_out_cur - _M_out_end;
    00322         _M_really_overflow(); // _M_file.sync() will be called within
    00323         if (__off)
    00324           _M_file.seekoff(__off, ios_base::cur);
    00325       }
    00326     else
    00327       _M_file.sync();
    00328     _M_last_overflowed = false;
    00329     return 0;
    00330       }
    00331
    00332       // [documentation is inherited]
    00333       virtual void
    00334       imbue(const locale& __loc);
    00335
    00336       // [documentation is inherited]
    00337       virtual streamsize
    00338       xsgetn(char_type* __s, streamsize __n)
    00339       {
    00340     streamsize __ret = 0;
    00341     // Clear out pback buffer before going on to the real deal...
    00342     if (_M_pback_init)
    00343       {
    00344         while (__ret < __n && _M_in_cur < _M_in_end)
    00345           {
    00346         *__s = *_M_in_cur;
    00347         ++__ret;
    00348         ++__s;
    00349         ++_M_in_cur;
    00350           }
    00351         _M_pback_destroy();
    00352       }
    00353     if (__ret < __n)
    00354       __ret += __streambuf_type::xsgetn(__s, __n - __ret);
    00355     return __ret;
    00356       }
    00357
    00358       // [documentation is inherited]
    00359       virtual streamsize
    00360       xsputn(const char_type* __s, streamsize __n)
    00361       {
    00362     _M_pback_destroy();
    00363     return __streambuf_type::xsputn(__s, __n);
    00364       }
    00365
    00371       void
    00372       _M_output_unshift();
    00373
    00374       // These three functions are used to clarify internal buffer
    00375       // maintenance. After an overflow, or after a seekoff call that
    00376       // started at beg or end, or possibly when the stream becomes
    00377       // unbuffered, and a myrid other obscure corner cases, the
    00378       // internal buffer does not truly reflect the contents of the
    00379       // external buffer. At this point, for whatever reason, it is in
    00380       // an indeterminate state.
    00386       void
    00387       _M_set_indeterminate(void)
    00388       {
    00389     if (_M_mode & ios_base::in)
    00390       this->setg(_M_buf, _M_buf, _M_buf);
    00391     if (_M_mode & ios_base::out)
    00392       this->setp(_M_buf, _M_buf);
    00393     _M_filepos = _M_buf;
    00394       }
    00395
    00401       void
    00402       _M_set_determinate(off_type __off)
    00403       {
    00404     bool __testin = _M_mode & ios_base::in;
    00405     bool __testout = _M_mode & ios_base::out;
    00406     if (__testin)
    00407       this->setg(_M_buf, _M_buf, _M_buf + __off);
    00408     if (__testout)
    00409       this->setp(_M_buf, _M_buf + __off);
    00410     _M_filepos = _M_buf + __off;
    00411       }
    00412
    00418       bool
    00419       _M_is_indeterminate(void)
    00420       {
    00421     bool __ret = false;
    00422     // Don't return true if unbuffered.
    00423     if (_M_buf)
    00424       {
    00425         if (_M_mode & ios_base::in)
    00426           __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end;
    00427         if (_M_mode & ios_base::out)
    00428           __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end;
    00429       }
    00430     return __ret;
    00431       }
    00432     };
    00433
    00434   // Explicit specializations, defined in src/fstream.cc.
    00435   template<>
    00436     basic_filebuf<char>::int_type
    00437     basic_filebuf<char>::_M_underflow_common(bool __bump);
    00438
    00439  #ifdef _GLIBCPP_USE_WCHAR_T
    00440   template<>
    00441     basic_filebuf<wchar_t>::int_type
    00442     basic_filebuf<wchar_t>::_M_underflow_common(bool __bump);
    00443  #endif
    00444
    00445   // [27.8.1.5] Template class basic_ifstream
    00454   template<typename _CharT, typename _Traits>
    00455     class basic_ifstream : public basic_istream<_CharT, _Traits>
    00456     {
    00457     public:
    00458       // Types:
    00459       typedef _CharT                    char_type;
    00460       typedef _Traits                   traits_type;
    00461       typedef typename traits_type::int_type        int_type;
    00462       typedef typename traits_type::pos_type        pos_type;
    00463       typedef typename traits_type::off_type        off_type;
    00464
    00465       // Non-standard types:
    00466       typedef basic_filebuf<char_type, traits_type>     __filebuf_type;
    00467       typedef basic_istream<char_type, traits_type> __istream_type;
    00468
    00469     private:
    00475       __filebuf_type    _M_filebuf;
    00476
    00477     public:
    00478       // Constructors/Destructors:
    00486       basic_ifstream()
    00487       : __istream_type(NULL), _M_filebuf()
    00488       { this->init(&_M_filebuf); }
    00489
    00500       explicit
    00501       basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in)
    00502       : __istream_type(NULL), _M_filebuf()
    00503       {
    00504     this->init(&_M_filebuf);
    00505     this->open(__s, __mode);
    00506       }
    00507
    00514       ~basic_ifstream()
    00515       { }
    00516
    00517       // Members:
    00524       __filebuf_type*
    00525       rdbuf() const
    00526       { return const_cast<__filebuf_type*>(&_M_filebuf); }
    00527
    00532       bool
    00533       is_open() { return _M_filebuf.is_open(); }
    00534
    00546       void
    00547       open(const char* __s, ios_base::openmode __mode = ios_base::in)
    00548       {
    00549     if (!_M_filebuf.open(__s, __mode | ios_base::in))
    00550       this->setstate(ios_base::failbit);
    00551       }
    00552
    00559       void
    00560       close()
    00561       {
    00562     if (!_M_filebuf.close())
    00563       this->setstate(ios_base::failbit);
    00564       }
    00565     };
    00566
    00567
    00568   // [27.8.1.8] Template class basic_ofstream
    00577   template<typename _CharT, typename _Traits>
    00578     class basic_ofstream : public basic_ostream<_CharT,_Traits>
    00579     {
    00580     public:
    00581       // Types:
    00582       typedef _CharT                    char_type;
    00583       typedef _Traits                   traits_type;
    00584       typedef typename traits_type::int_type        int_type;
    00585       typedef typename traits_type::pos_type        pos_type;
    00586       typedef typename traits_type::off_type        off_type;
    00587
    00588       // Non-standard types:
    00589       typedef basic_filebuf<char_type, traits_type>     __filebuf_type;
    00590       typedef basic_ostream<char_type, traits_type> __ostream_type;
    00591
    00592     private:
    00598       __filebuf_type    _M_filebuf;
    00599
    00600     public:
    00601       // Constructors:
    00609       basic_ofstream()
    00610       : __ostream_type(NULL), _M_filebuf()
    00611       { this->init(&_M_filebuf); }
    00612
    00624       explicit
    00625       basic_ofstream(const char* __s,
    00626              ios_base::openmode __mode = ios_base::out|ios_base::trunc)
    00627       : __ostream_type(NULL), _M_filebuf()
    00628       {
    00629     this->init(&_M_filebuf);
    00630     this->open(__s, __mode);
    00631       }
    00632
    00639       ~basic_ofstream()
    00640       { }
    00641
    00642       // Members:
    00649       __filebuf_type*
    00650       rdbuf() const
    00651       { return const_cast<__filebuf_type*>(&_M_filebuf); }
    00652
    00657       bool
    00658       is_open() { return _M_filebuf.is_open(); }
    00659
    00671       void
    00672       open(const char* __s,
    00673        ios_base::openmode __mode = ios_base::out | ios_base::trunc)
    00674       {
    00675     if (!_M_filebuf.open(__s, __mode | ios_base::out))
    00676       this->setstate(ios_base::failbit);
    00677       }
    00678
    00685       void
    00686       close()
    00687       {
    00688     if (!_M_filebuf.close())
    00689       this->setstate(ios_base::failbit);
    00690       }
    00691     };
    00692
    00693
    00694   // [27.8.1.11] Template class basic_fstream
    00703   template<typename _CharT, typename _Traits>
    00704     class basic_fstream : public basic_iostream<_CharT, _Traits>
    00705     {
    00706     public:
    00707       // Types:
    00708       typedef _CharT                    char_type;
    00709       typedef _Traits                   traits_type;
    00710       typedef typename traits_type::int_type        int_type;
    00711       typedef typename traits_type::pos_type        pos_type;
    00712       typedef typename traits_type::off_type        off_type;
    00713
    00714       // Non-standard types:
    00715       typedef basic_filebuf<char_type, traits_type>     __filebuf_type;
    00716       typedef basic_ios<char_type, traits_type>     __ios_type;
    00717       typedef basic_iostream<char_type, traits_type>    __iostream_type;
    00718
    00719     private:
    00725       __filebuf_type    _M_filebuf;
    00726
    00727     public:
    00728       // Constructors/destructor:
    00736       basic_fstream()
    00737       : __iostream_type(NULL), _M_filebuf()
    00738       { this->init(&_M_filebuf); }
    00739
    00748       explicit
    00749       basic_fstream(const char* __s,
    00750             ios_base::openmode __mode = ios_base::in | ios_base::out)
    00751       : __iostream_type(NULL), _M_filebuf()
    00752       {
    00753     this->init(&_M_filebuf);
    00754     this->open(__s, __mode);
    00755       }
    00756
    00763       ~basic_fstream()
    00764       { }
    00765
    00766       // Members:
    00773       __filebuf_type*
    00774       rdbuf() const
    00775       { return const_cast<__filebuf_type*>(&_M_filebuf); }
    00776
    00781       bool
    00782       is_open() { return _M_filebuf.is_open(); }
    00783
    00795       void
    00796       open(const char* __s,
    00797        ios_base::openmode __mode = ios_base::in | ios_base::out)
    00798       {
    00799     if (!_M_filebuf.open(__s, __mode))
    00800       setstate(ios_base::failbit);
    00801       }
    00802
    00809       void
    00810       close()
    00811       {
    00812     if (!_M_filebuf.close())
    00813       setstate(ios_base::failbit);
    00814       }
    00815     };
    00816 } // namespace std
    00817
    00818 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
    00819 # define export
    00820 #endif
    00821 #ifdef  _GLIBCPP_FULLY_COMPLIANT_HEADERS
    00822 # include <bits/fstream.tcc>
    00823 #endif
    00824
    00825 #endif