# 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   template<typename _CharT, typename _Traits>
    00054     class basic_filebuf : public basic_streambuf<_CharT, _Traits>
    00055     {
    00056     public:
    00057       // Types:
    00058       typedef _CharT                                char_type;
    00059       typedef _Traits                               traits_type;
    00060       typedef typename traits_type::int_type        int_type;
    00061       typedef typename traits_type::pos_type        pos_type;
    00062       typedef typename traits_type::off_type        off_type;
    00063
    00064       // Non-standard Types:
    00065       typedef basic_streambuf<char_type, traits_type>   __streambuf_type;
    00066       typedef basic_filebuf<char_type, traits_type>     __filebuf_type;
    00067       typedef __basic_file<char>                __file_type;
    00068       typedef typename traits_type::state_type          __state_type;
    00069       typedef codecvt<char_type, char, __state_type>    __codecvt_type;
    00070       typedef typename __codecvt_type::result           __res_type;
    00071       typedef ctype<char_type>                          __ctype_type;
    00072
    00073       friend class ios_base; // For sync_with_stdio.
    00074
    00075     protected:
    00076       // Data Members:
    00077       // MT lock inherited from libio or other low-level io library.
    00078       __c_lock              _M_lock;
    00079
    00080       // External buffer.
    00081       __file_type       _M_file;
    00082
    00083       // Current and beginning state type for codecvt.
    00084       __state_type      _M_state_cur;
    00085       __state_type      _M_state_beg;
    00086
    00087       // Set iff _M_buf is allocated memory from _M_allocate_internal_buffer.
    00088       bool          _M_buf_allocated;
    00089
    00090       // XXX Needed?
    00091       bool          _M_last_overflowed;
    00092
    00093       // The position in the buffer corresponding to the external file
    00094       // pointer.
    00095       char_type*        _M_filepos;
    00096
    00097     public:
    00098       // Constructors/destructor:
    00099       basic_filebuf();
    00100
    00101       virtual
    00102       ~basic_filebuf()
    00103       {
    00104     this->close();
    00105     _M_last_overflowed = false;
    00106       }
    00107
    00108       // Members:
    00109       bool
    00110       is_open() const { return _M_file.is_open(); }
    00111
    00112       __filebuf_type*
    00113       open(const char* __s, ios_base::openmode __mode);
    00114
    00115       __filebuf_type*
    00116       close();
    00117
    00118     protected:
    00119       void
    00120       _M_allocate_internal_buffer();
    00121
    00122       void
    00123       _M_destroy_internal_buffer();
    00124
    00125       // Overridden virtual functions:
    00126       virtual streamsize
    00127       showmanyc();
    00128
    00129       // Stroustrup, 1998, p. 628
    00130       // underflow() and uflow() functions are called to get the next
    00131       // charater from the real input source when the buffer is empty.
    00132       // Buffered input uses underflow()
    00133
    00134       // The only difference between underflow() and uflow() is that the
    00135       // latter bumps _M_in_cur after the read.  In the sync_with_stdio
    00136       // case, this is important, as we need to unget the read character in
    00137       // the underflow() case in order to maintain synchronization.  So
    00138       // instead of calling underflow() from uflow(), we create a common
    00139       // subroutine to do the real work.
    00140       int_type
    00141       _M_underflow_common(bool __bump);
    00142
    00143       virtual int_type
    00144       underflow() { return _M_underflow_common(false); }
    00145
    00146       virtual int_type
    00147       uflow() { return _M_underflow_common(true); }
    00148
    00149       virtual int_type
    00150       pbackfail(int_type __c = _Traits::eof());
    00151
    00152       // NB: For what the standard expects of the overflow function,
    00153       // see _M_really_overflow(), below. Because basic_streambuf's
    00154       // sputc/sputn call overflow directly, and the complications of
    00155       // this implementation's setting of the initial pointers all
    00156       // equal to _M_buf when initializing, it seems essential to have
    00157       // this in actuality be a helper function that checks for the
    00158       // eccentricities of this implementation, and then call
    00159       // overflow() if indeed the buffer is full.
    00160       virtual int_type
    00161       overflow(int_type __c = _Traits::eof());
    00162
    00163       // Stroustrup, 1998, p 648
    00164       // The overflow() function is called to transfer characters to the
    00165       // real output destination when the buffer is full. A call to
    00166       // overflow(c) outputs the contents of the buffer plus the
    00167       // character c.
    00168       // 27.5.2.4.5
    00169       // Consume some sequence of the characters in the pending sequence.
    00170       int_type
    00171       _M_really_overflow(int_type __c = _Traits::eof());
    00172
    00173       // Convert internal byte sequence to external, char-based
    00174       // sequence via codecvt.
    00175       void
    00176       _M_convert_to_external(char_type*, streamsize, streamsize&, streamsize&);
    00177
    00178       virtual __streambuf_type*
    00179       setbuf(char_type* __s, streamsize __n);
    00180
    00181       virtual pos_type
    00182       seekoff(off_type __off, ios_base::seekdir __way,
    00183           ios_base::openmode __mode = ios_base::in | ios_base::out);
    00184
    00185       virtual pos_type
    00186       seekpos(pos_type __pos,
    00187           ios_base::openmode __mode = ios_base::in | ios_base::out);
    00188
    00189       virtual int
    00190       sync()
    00191       {
    00192     bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
    00193
    00194     // Make sure that the internal buffer resyncs its idea of
    00195     // the file position with the external file.
    00196     if (__testput)
    00197       {
    00198         // Need to restore current position after the write.
    00199         off_type __off = _M_out_cur - _M_out_end;
    00200         _M_really_overflow(); // _M_file.sync() will be called within
    00201         if (__off)
    00202           _M_file.seekoff(__off, ios_base::cur);
    00203       }
    00204     else
    00205       _M_file.sync();
    00206     _M_last_overflowed = false;
    00207     return 0;
    00208       }
    00209
    00210       virtual void
    00211       imbue(const locale& __loc);
    00212
    00213       virtual streamsize
    00214       xsgetn(char_type* __s, streamsize __n)
    00215       {
    00216     streamsize __ret = 0;
    00217     // Clear out pback buffer before going on to the real deal...
    00218     if (_M_pback_init)
    00219       {
    00220         while (__ret < __n && _M_in_cur < _M_in_end)
    00221           {
    00222         *__s = *_M_in_cur;
    00223         ++__ret;
    00224         ++__s;
    00225         ++_M_in_cur;
    00226           }
    00227         _M_pback_destroy();
    00228       }
    00229     if (__ret < __n)
    00230       __ret += __streambuf_type::xsgetn(__s, __n - __ret);
    00231     return __ret;
    00232       }
    00233
    00234       virtual streamsize
    00235       xsputn(const char_type* __s, streamsize __n)
    00236       {
    00237     _M_pback_destroy();
    00238     return __streambuf_type::xsputn(__s, __n);
    00239       }
    00240
    00241       void
    00242       _M_output_unshift();
    00243
    00244       // These three functions are used to clarify internal buffer
    00245       // maintenance. After an overflow, or after a seekoff call that
    00246       // started at beg or end, or possibly when the stream becomes
    00247       // unbuffered, and a myrid other obscure corner cases, the
    00248       // internal buffer does not truly reflect the contents of the
    00249       // external buffer. At this point, for whatever reason, it is in
    00250       // an indeterminate state.
    00251       void
    00252       _M_set_indeterminate(void)
    00253       {
    00254     if (_M_mode & ios_base::in)
    00255       this->setg(_M_buf, _M_buf, _M_buf);
    00256     if (_M_mode & ios_base::out)
    00257       this->setp(_M_buf, _M_buf);
    00258     _M_filepos = _M_buf;
    00259       }
    00260
    00261       void
    00262       _M_set_determinate(off_type __off)
    00263       {
    00264     bool __testin = _M_mode & ios_base::in;
    00265     bool __testout = _M_mode & ios_base::out;
    00266     if (__testin)
    00267       this->setg(_M_buf, _M_buf, _M_buf + __off);
    00268     if (__testout)
    00269       this->setp(_M_buf, _M_buf + __off);
    00270     _M_filepos = _M_buf + __off;
    00271       }
    00272
    00273       bool
    00274       _M_is_indeterminate(void)
    00275       {
    00276     bool __ret = false;
    00277     // Don't return true if unbuffered.
    00278     if (_M_buf)
    00279       {
    00280         if (_M_mode & ios_base::in)
    00281           __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end;
    00282         if (_M_mode & ios_base::out)
    00283           __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end;
    00284       }
    00285     return __ret;
    00286       }
    00287     };
    00288
    00289
    00290
    00291   // 27.8.1.5  Template class basic_ifstream
    00295   template<typename _CharT, typename _Traits>
    00296     class basic_ifstream : public basic_istream<_CharT, _Traits>
    00297     {
    00298     public:
    00299       // Types:
    00300       typedef _CharT                    char_type;
    00301       typedef _Traits                   traits_type;
    00302       typedef typename traits_type::int_type        int_type;
    00303       typedef typename traits_type::pos_type        pos_type;
    00304       typedef typename traits_type::off_type        off_type;
    00305
    00306       // Non-standard types:
    00307       typedef basic_filebuf<char_type, traits_type>     __filebuf_type;
    00308       typedef basic_istream<char_type, traits_type> __istream_type;
    00309
    00310     private:
    00311       __filebuf_type    _M_filebuf;
    00312
    00313     public:
    00314      // Constructors/Destructors:
    00316       basic_ifstream()
    00317       : __istream_type(NULL), _M_filebuf()
    00318       { this->init(&_M_filebuf); }
    00319
    00328       explicit
    00329       basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in)
    00330       : __istream_type(NULL), _M_filebuf()
    00331       {
    00332     this->init(&_M_filebuf);
    00333     this->open(__s, __mode);
    00334       }
    00335
    00336       ~basic_ifstream()
    00337       { }
    00338
    00339       // Members:
    00344       __filebuf_type*
    00345       rdbuf() const
    00346       { return const_cast<__filebuf_type*>(&_M_filebuf); }
    00347
    00348       bool
    00349       is_open() { return _M_filebuf.is_open(); }
    00350
    00351       void
    00352       open(const char* __s, ios_base::openmode __mode = ios_base::in)
    00353       {
    00354     if (!_M_filebuf.open(__s, __mode | ios_base::in))
    00355       this->setstate(ios_base::failbit);
    00356       }
    00357
    00359       void
    00360       close()
    00361       {
    00362     if (!_M_filebuf.close())
    00363       this->setstate(ios_base::failbit);
    00364       }
    00365     };
    00366
    00367
    00368   // 27.8.1.8  Template class basic_ofstream
    00372   template<typename _CharT, typename _Traits>
    00373     class basic_ofstream : public basic_ostream<_CharT,_Traits>
    00374     {
    00375     public:
    00376       // Types:
    00377       typedef _CharT                    char_type;
    00378       typedef _Traits                   traits_type;
    00379       typedef typename traits_type::int_type        int_type;
    00380       typedef typename traits_type::pos_type        pos_type;
    00381       typedef typename traits_type::off_type        off_type;
    00382
    00383       // Non-standard types:
    00384       typedef basic_filebuf<char_type, traits_type>     __filebuf_type;
    00385       typedef basic_ostream<char_type, traits_type> __ostream_type;
    00386
    00387     private:
    00388       __filebuf_type    _M_filebuf;
    00389
    00390     public:
    00391       // Constructors:
    00393       basic_ofstream()
    00394       : __ostream_type(NULL), _M_filebuf()
    00395       { this->init(&_M_filebuf); }
    00396
    00405       explicit
    00406       basic_ofstream(const char* __s,
    00407              ios_base::openmode __mode = ios_base::out|ios_base::trunc)
    00408       : __ostream_type(NULL), _M_filebuf()
    00409       {
    00410     this->init(&_M_filebuf);
    00411     this->open(__s, __mode);
    00412       }
    00413
    00414       ~basic_ofstream()
    00415       { }
    00416
    00417       // Members:
    00422       __filebuf_type*
    00423       rdbuf() const
    00424       { return const_cast<__filebuf_type*>(&_M_filebuf); }
    00425
    00430       bool
    00431       is_open() { return _M_filebuf.is_open(); }
    00432
    00441       void
    00442       open(const char* __s,
    00443        ios_base::openmode __mode = ios_base::out | ios_base::trunc)
    00444       {
    00445     if (!_M_filebuf.open(__s, __mode | ios_base::out))
    00446       this->setstate(ios_base::failbit);
    00447       }
    00448
    00450       void
    00451       close()
    00452       {
    00453     if (!_M_filebuf.close())
    00454       this->setstate(ios_base::failbit);
    00455       }
    00456     };
    00457
    00458
    00459   // 27.8.1.11  Template class basic_fstream
    00463   template<typename _CharT, typename _Traits>
    00464     class basic_fstream : public basic_iostream<_CharT, _Traits>
    00465     {
    00466     public:
    00467       // Types:
    00468       typedef _CharT                    char_type;
    00469       typedef _Traits                   traits_type;
    00470       typedef typename traits_type::int_type        int_type;
    00471       typedef typename traits_type::pos_type        pos_type;
    00472       typedef typename traits_type::off_type        off_type;
    00473
    00474       // Non-standard types:
    00475       typedef basic_filebuf<char_type, traits_type>     __filebuf_type;
    00476       typedef basic_ios<char_type, traits_type>     __ios_type;
    00477       typedef basic_iostream<char_type, traits_type>    __iostream_type;
    00478
    00479     private:
    00480       __filebuf_type    _M_filebuf;
    00481
    00482     public:
    00483       // Constructors/destructor:
    00485       basic_fstream()
    00486       : __iostream_type(NULL), _M_filebuf()
    00487       { this->init(&_M_filebuf); }
    00488
    00497       explicit
    00498       basic_fstream(const char* __s,
    00499             ios_base::openmode __mode = ios_base::in | ios_base::out)
    00500       : __iostream_type(NULL), _M_filebuf()
    00501       {
    00502     this->init(&_M_filebuf);
    00503     this->open(__s, __mode);
    00504       }
    00505
    00506       ~basic_fstream()
    00507       { }
    00508
    00509       // Members:
    00514       __filebuf_type*
    00515       rdbuf() const
    00516       { return const_cast<__filebuf_type*>(&_M_filebuf); }
    00517
    00522       bool
    00523       is_open() { return _M_filebuf.is_open(); }
    00524
    00533       void
    00534       open(const char* __s,
    00535        ios_base::openmode __mode = ios_base::in | ios_base::out)
    00536       {
    00537     if (!_M_filebuf.open(__s, __mode))
    00538       setstate(ios_base::failbit);
    00539       }
    00540
    00542       void
    00543       close()
    00544       {
    00545     if (!_M_filebuf.close())
    00546       setstate(ios_base::failbit);
    00547       }
    00548     };
    00549 } // namespace std
    00550
    00551 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
    00552 # define export
    00553 #endif
    00554 #ifdef  _GLIBCPP_FULLY_COMPLIANT_HEADERS
    00555 # include <bits/fstream.tcc>
    00556 #endif
    00557
    00558 #endif