# streambuf

Go to the documentation of this file.

    00001 // Stream buffer classes -*- 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.5  Stream buffers
    00033 //
    00034
    00040 #ifndef _CPP_STREAMBUF
    00041 #define _CPP_STREAMBUF  1
    00042
    00043 #pragma GCC system_header
    00044
    00045 #include <bits/c++config.h>
    00046 #include <iosfwd>
    00047 #include <cstdio>   // For SEEK_SET, SEEK_CUR, SEEK_END
    00048 #include <bits/localefwd.h>
    00049 #include <bits/ios_base.h>
    00050
    00051 namespace std
    00052 {
    00053   template<typename _CharT, typename _Traits>
    00054     streamsize
    00055     __copy_streambufs(basic_ios<_CharT, _Traits>& _ios,
    00056               basic_streambuf<_CharT, _Traits>* __sbin,
    00057               basic_streambuf<_CharT, _Traits>* __sbout);
    00058
    00059   // 27.5.2 Template class basic_streambuf<_CharT, _Traits>
    00060   template<typename _CharT, typename _Traits>
    00061     class basic_streambuf
    00062     {
    00063     public:
    00064       // Types:
    00065       typedef _CharT                    char_type;
    00066       typedef _Traits                   traits_type;
    00067       typedef typename traits_type::int_type        int_type;
    00068       typedef typename traits_type::pos_type        pos_type;
    00069       typedef typename traits_type::off_type        off_type;
    00070
    00071       // Non-standard Types:
    00072       typedef ctype<char_type>                  __ctype_type;
    00073       typedef basic_streambuf<char_type, traits_type>   __streambuf_type;
    00074
    00075       friend class basic_ios<char_type, traits_type>;
    00076       friend class basic_istream<char_type, traits_type>;
    00077       friend class basic_ostream<char_type, traits_type>;
    00078       friend class istreambuf_iterator<char_type, traits_type>;
    00079       friend class ostreambuf_iterator<char_type, traits_type>;
    00080
    00081       friend streamsize
    00082       __copy_streambufs<>(basic_ios<char_type, traits_type>& __ios,
    00083               __streambuf_type* __sbin,__streambuf_type* __sbout);
    00084
    00085     protected:
    00086       // Pointer to the beginning of internally-allocated
    00087       // space. Filebuf manually allocates/deallocates this, whereas
    00088       // stringstreams attempt to use the built-in intelligence of the
    00089       // string class. If you are managing memory, set this. If not,
    00090       // leave it NULL.
    00091       char_type*        _M_buf;
    00092
    00093       // Actual size of allocated internal buffer, in bytes.
    00094       int_type          _M_buf_size;
    00095
    00096       // Optimal or preferred size of internal buffer, in bytes.
    00097       int_type          _M_buf_size_opt;
    00098
    00099       // True iff _M_in_* and _M_out_* buffers should always point to
    00100       // the same place.  True for fstreams, false for sstreams.
    00101       bool          _M_buf_unified;
    00102
    00103       // This is based on _IO_FILE, just reordered to be more
    00104       // consistent, and is intended to be the most minimal abstraction
    00105       // for an internal buffer.
    00106       // get == input == read
    00107       // put == output == write
    00108       char_type*        _M_in_beg;      // Start of get area.
    00109       char_type*        _M_in_cur;  // Current read area.
    00110       char_type*        _M_in_end;  // End of get area.
    00111       char_type*        _M_out_beg;     // Start of put area.
    00112       char_type*        _M_out_cur;     // Current put area.
    00113       char_type*        _M_out_end;     // End of put area.
    00114
    00115       // Place to stash in || out || in | out settings for current streambuf.
    00116       ios_base::openmode    _M_mode;
    00117
    00118       // Current locale setting.
    00119       locale            _M_buf_locale;
    00120
    00121       // True iff locale is initialized.
    00122       bool          _M_buf_locale_init;
    00123
    00124       // Necessary bits for putback buffer management. Only used in
    00125       // the basic_filebuf class, as necessary for the standard
    00126       // requirements. The only basic_streambuf member function that
    00127       // needs access to these data members is in_avail...
    00128       // NB: pbacks of over one character are not currently supported.
    00129       static const int_type     _S_pback_size = 1;
    00130       char_type         _M_pback[_S_pback_size];
    00131       char_type*        _M_pback_cur_save;
    00132       char_type*        _M_pback_end_save;
    00133       bool          _M_pback_init;
    00134
    00135       // Initializes pback buffers, and moves normal buffers to safety.
    00136       // Assumptions:
    00137       // _M_in_cur has already been moved back
    00138       void
    00139       _M_pback_create()
    00140       {
    00141     if (!_M_pback_init)
    00142       {
    00143         int_type __dist = _M_in_end - _M_in_cur;
    00144         int_type __len = min(_S_pback_size, __dist);
    00145         traits_type::copy(_M_pback, _M_in_cur, __len);
    00146         _M_pback_cur_save = _M_in_cur;
    00147         _M_pback_end_save = _M_in_end;
    00148         this->setg(_M_pback, _M_pback, _M_pback + __len);
    00149         _M_pback_init = true;
    00150       }
    00151       }
    00152
    00153       // Deactivates pback buffer contents, and restores normal buffer.
    00154       // Assumptions:
    00155       // The pback buffer has only moved forward.
    00156       void
    00157       _M_pback_destroy()
    00158       {
    00159     if (_M_pback_init)
    00160       {
    00161         // Length _M_in_cur moved in the pback buffer.
    00162         int_type __off_cur = _M_in_cur - _M_pback;
    00163
    00164         // For in | out buffers, the end can be pushed back...
    00165         int_type __off_end = 0;
    00166         int_type __pback_len = _M_in_end - _M_pback;
    00167         int_type __save_len = _M_pback_end_save - _M_buf;
    00168         if (__pback_len > __save_len)
    00169           __off_end = __pback_len - __save_len;
    00170
    00171         this->setg(_M_buf, _M_pback_cur_save + __off_cur,
    00172                _M_pback_end_save + __off_end);
    00173         _M_pback_cur_save = NULL;
    00174         _M_pback_end_save = NULL;
    00175         _M_pback_init = false;
    00176       }
    00177       }
    00178
    00179       // Correctly sets the _M_in_cur pointer, and bumps the
    00180       // _M_out_cur pointer as well if necessary.
    00181       void
    00182       _M_in_cur_move(off_type __n) // argument needs to be +-
    00183       {
    00184     bool __testout = _M_out_cur;
    00185     _M_in_cur += __n;
    00186     if (__testout && _M_buf_unified)
    00187       _M_out_cur += __n;
    00188       }
    00189
    00190       // Correctly sets the _M_out_cur pointer, and bumps the
    00191       // appropriate _M_*_end pointers as well. Necessary for the
    00192       // un-tied stringbufs, in in|out mode.
    00193       // Invariant:
    00194       // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size
    00195       // Assuming all _M_*_[beg, cur, end] pointers are operating on
    00196       // the same range:
    00197       // _M_buf <= _M_*_ <= _M_buf + _M_buf_size
    00198       void
    00199       _M_out_cur_move(off_type __n) // argument needs to be +-
    00200       {
    00201     bool __testin = _M_in_cur;
    00202
    00203     _M_out_cur += __n;
    00204     if (__testin && _M_buf_unified)
    00205       _M_in_cur += __n;
    00206     if (_M_out_cur > _M_out_end)
    00207       {
    00208         _M_out_end = _M_out_cur;
    00209         // NB: in | out buffers drag the _M_in_end pointer along...
    00210         if (__testin)
    00211           _M_in_end += __n;
    00212       }
    00213       }
    00214
    00215       // Return the size of the output buffer.  This depends on the
    00216       // buffer in use: allocated buffers have a stored size in
    00217       // _M_buf_size and setbuf() buffers don't.
    00218       off_type
    00219       _M_out_buf_size()
    00220       {
    00221     off_type __ret = 0;
    00222     if (_M_out_cur)
    00223       {
    00224         // Using allocated buffer.
    00225         if (_M_out_beg == _M_buf)
    00226           __ret = _M_out_beg + _M_buf_size - _M_out_cur;
    00227         // Using non-allocated buffer.
    00228         else
    00229           __ret = _M_out_end - _M_out_cur;
    00230       }
    00231     return __ret;
    00232       }
    00233
    00234   public:
    00235       virtual
    00236       ~basic_streambuf()
    00237       {
    00238     _M_buf_unified = false;
    00239     _M_buf_size = 0;
    00240     _M_buf_size_opt = 0;
    00241     _M_mode = ios_base::openmode(0);
    00242     _M_buf_locale_init = false;
    00243       }
    00244
    00245       // Locales:
    00246       locale
    00247       pubimbue(const locale &__loc)
    00248       {
    00249     locale __tmp(this->getloc());
    00250     this->imbue(__loc);
    00251     return __tmp;
    00252       }
    00253
    00254       locale
    00255       getloc() const
    00256       {
    00257     if (_M_buf_locale_init)
    00258       return _M_buf_locale;
    00259     else
    00260       return locale();
    00261       }
    00262
    00263       // Buffer and positioning:
    00264       __streambuf_type*
    00265       pubsetbuf(char_type* __s, streamsize __n)
    00266       { return this->setbuf(__s, __n); }
    00267
    00268       pos_type
    00269       pubseekoff(off_type __off, ios_base::seekdir __way,
    00270          ios_base::openmode __mode = ios_base::in | ios_base::out)
    00271       { return this->seekoff(__off, __way, __mode); }
    00272
    00273       pos_type
    00274       pubseekpos(pos_type __sp,
    00275          ios_base::openmode __mode = ios_base::in | ios_base::out)
    00276       { return this->seekpos(__sp, __mode); }
    00277
    00278       int
    00279       pubsync() { return this->sync(); }
    00280
    00281       // Get and put areas:
    00282       // Get area:
    00283       streamsize
    00284       in_avail()
    00285       {
    00286     streamsize __ret;
    00287     if (_M_in_cur && _M_in_cur < _M_in_end)
    00288       {
    00289         if (_M_pback_init)
    00290           {
    00291         int_type __save_len =  _M_pback_end_save - _M_pback_cur_save;
    00292         int_type __pback_len = _M_in_cur - _M_pback;
    00293         __ret = __save_len - __pback_len;
    00294           }
    00295         else
    00296           __ret = this->egptr() - this->gptr();
    00297       }
    00298     else
    00299       __ret = this->showmanyc();
    00300     return __ret;
    00301       }
    00302
    00303       int_type
    00304       snextc()
    00305       {
    00306     int_type __eof = traits_type::eof();
    00307     return (this->sbumpc() == __eof ? __eof : this->sgetc());
    00308       }
    00309
    00310       int_type
    00311       sbumpc();
    00312
    00313       int_type
    00314       sgetc()
    00315       {
    00316     int_type __ret;
    00317     if (_M_in_cur && _M_in_cur < _M_in_end)
    00318       __ret = traits_type::to_int_type(*(this->gptr()));
    00319     else
    00320       __ret = this->underflow();
    00321     return __ret;
    00322       }
    00323
    00324       streamsize
    00325       sgetn(char_type* __s, streamsize __n)
    00326       { return this->xsgetn(__s, __n); }
    00327
    00328       // Putback:
    00329       int_type
    00330       sputbackc(char_type __c);
    00331
    00332       int_type
    00333       sungetc();
    00334
    00335       // Put area:
    00336       int_type
    00337       sputc(char_type __c);
    00338
    00339       streamsize
    00340       sputn(const char_type* __s, streamsize __n)
    00341       { return this->xsputn(__s, __n); }
    00342
    00343     protected:
    00344       basic_streambuf()
    00345       : _M_buf(NULL), _M_buf_size(0),
    00346       _M_buf_size_opt(static_cast<int_type>(BUFSIZ)), _M_buf_unified(false),
    00347       _M_in_beg(0), _M_in_cur(0), _M_in_end(0), _M_out_beg(0), _M_out_cur(0),
    00348       _M_out_end(0), _M_mode(ios_base::openmode(0)), _M_buf_locale(locale()),
    00349       _M_buf_locale_init(false), _M_pback_cur_save(0), _M_pback_end_save(0),
    00350       _M_pback_init(false)
    00351       { }
    00352
    00353       // Get area:
    00354       char_type*
    00355       eback() const { return _M_in_beg; }
    00356
    00357       char_type*
    00358       gptr()  const { return _M_in_cur;  }
    00359
    00360       char_type*
    00361       egptr() const { return _M_in_end; }
    00362
    00363       void
    00364       gbump(int __n) { _M_in_cur += __n; }
    00365
    00366       void
    00367       setg(char_type* __gbeg, char_type* __gnext, char_type* __gend)
    00368       {
    00369     _M_in_beg = __gbeg;
    00370     _M_in_cur = __gnext;
    00371     _M_in_end = __gend;
    00372     if (!(_M_mode & ios_base::in) && __gbeg && __gnext && __gend)
    00373       _M_mode = _M_mode | ios_base::in;
    00374       }
    00375
    00376       // Put area:
    00377       char_type*
    00378       pbase() const { return _M_out_beg; }
    00379
    00380       char_type*
    00381       pptr() const { return _M_out_cur; }
    00382
    00383       char_type*
    00384       epptr() const { return _M_out_end; }
    00385
    00386       void
    00387       pbump(int __n) { _M_out_cur += __n; }
    00388
    00389       void
    00390       setp(char_type* __pbeg, char_type* __pend)
    00391       {
    00392     _M_out_beg = _M_out_cur = __pbeg;
    00393     _M_out_end = __pend;
    00394     if (!(_M_mode & ios_base::out) && __pbeg && __pend)
    00395       _M_mode = _M_mode | ios_base::out;
    00396       }
    00397
    00398       // Virtual functions:
    00399       // Locales:
    00400       virtual void
    00401       imbue(const locale& __loc)
    00402       {
    00403     _M_buf_locale_init = true;
    00404     if (_M_buf_locale != __loc)
    00405       _M_buf_locale = __loc;
    00406       }
    00407
    00408       // Buffer management and positioning:
    00409       virtual basic_streambuf<char_type,_Traits>*
    00410       setbuf(char_type*, streamsize)
    00411       { return this; }
    00412
    00413       virtual pos_type
    00414       seekoff(off_type, ios_base::seekdir,
    00415           ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
    00416       { return pos_type(off_type(-1)); }
    00417
    00418       virtual pos_type
    00419       seekpos(pos_type,
    00420           ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
    00421       { return pos_type(off_type(-1)); }
    00422
    00423       virtual int
    00424       sync() { return 0; }
    00425
    00426       // Get area:
    00427       virtual streamsize
    00428       showmanyc() { return 0; }
    00429
    00430       virtual streamsize
    00431       xsgetn(char_type* __s, streamsize __n);
    00432
    00433       virtual int_type
    00434       underflow()
    00435       { return traits_type::eof(); }
    00436
    00437       virtual int_type
    00438       uflow()
    00439       {
    00440     int_type __ret = traits_type::eof();
    00441     bool __testeof = this->underflow() == __ret;
    00442     bool __testpending = _M_in_cur && _M_in_cur < _M_in_end;
    00443     if (!__testeof && __testpending)
    00444       {
    00445         __ret = traits_type::to_int_type(*_M_in_cur);
    00446         ++_M_in_cur;
    00447         if (_M_buf_unified && _M_mode & ios_base::out)
    00448           ++_M_out_cur;
    00449       }
    00450     return __ret;
    00451       }
    00452
    00453       // Putback:
    00454       virtual int_type
    00455       pbackfail(int_type /* __c */  = traits_type::eof())
    00456       { return traits_type::eof(); }
    00457
    00458       // Put area:
    00459       virtual streamsize
    00460       xsputn(const char_type* __s, streamsize __n);
    00461
    00462       virtual int_type
    00463       overflow(int_type /* __c */ = traits_type::eof())
    00464       { return traits_type::eof(); }
    00465
    00466 #ifdef _GLIBCPP_DEPRECATED
    00467     public:
    00468       void
    00469       stossc()
    00470       {
    00471     if (_M_in_cur < _M_in_end)
    00472       ++_M_in_cur;
    00473     else
    00474       this->uflow();
    00475       }
    00476 #endif
    00477
    00478 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
    00479     // Side effect of DR 50.
    00480     private:
    00481       basic_streambuf(const __streambuf_type&) { };
    00482
    00483       __streambuf_type&
    00484       operator=(const __streambuf_type&) { return *this; };
    00485 #endif
    00486     };
    00487 } // namespace std
    00488
    00489 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
    00490 # define export
    00491 #endif
    00492 #ifdef  _GLIBCPP_FULLY_COMPLIANT_HEADERS
    00493 #include <bits/streambuf.tcc>
    00494 #endif
    00495
    00496 #endif