# 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 {
    00058   template<typename _CharT, typename _Traits>
    00059     streamsize
    00060     __copy_streambufs(basic_ios<_CharT, _Traits>& _ios,
    00061               basic_streambuf<_CharT, _Traits>* __sbin,
    00062               basic_streambuf<_CharT, _Traits>* __sbout);
    00063
    00124   template<typename _CharT, typename _Traits>
    00125     class basic_streambuf
    00126     {
    00127     public:
    00129
    00134       typedef _CharT                    char_type;
    00135       typedef _Traits                   traits_type;
    00136       typedef typename traits_type::int_type        int_type;
    00137       typedef typename traits_type::pos_type        pos_type;
    00138       typedef typename traits_type::off_type        off_type;
    00140
    00142
    00147       typedef ctype<char_type>                  __ctype_type;
    00148       typedef basic_streambuf<char_type, traits_type>   __streambuf_type;
    00149       typedef typename traits_type::state_type      __state_type;
    00151
    00152       friend class basic_ios<char_type, traits_type>;
    00153       friend class basic_istream<char_type, traits_type>;
    00154       friend class basic_ostream<char_type, traits_type>;
    00155       friend class istreambuf_iterator<char_type, traits_type>;
    00156       friend class ostreambuf_iterator<char_type, traits_type>;
    00157
    00158       friend streamsize
    00159       __copy_streambufs<>(basic_ios<char_type, traits_type>& __ios,
    00160               __streambuf_type* __sbin,__streambuf_type* __sbout);
    00161
    00162     protected:
    00171       char_type*        _M_buf;
    00172
    00178       size_t            _M_buf_size;
    00179
    00185       size_t            _M_buf_size_opt;
    00186
    00193       bool          _M_buf_unified;
    00194
    00196
    00205       char_type*        _M_in_beg;      // Start of get area.
    00206       char_type*        _M_in_cur;  // Current read area.
    00207       char_type*        _M_in_end;  // End of get area.
    00208       char_type*        _M_out_beg;     // Start of put area.
    00209       char_type*        _M_out_cur;     // Current put area.
    00210       char_type*        _M_out_end;     // End of put area.
    00212
    00218       ios_base::openmode    _M_mode;
    00219
    00225       locale            _M_buf_locale;
    00226
    00232       bool          _M_buf_locale_init;
    00233
    00235
    00245       static const size_t       _S_pback_size = 1;
    00246       char_type         _M_pback[_S_pback_size];
    00247       char_type*        _M_pback_cur_save;
    00248       char_type*        _M_pback_end_save;
    00249       bool          _M_pback_init;
    00251
    00257       fpos<__state_type>    _M_pos;
    00258
    00259       // Initializes pback buffers, and moves normal buffers to safety.
    00260       // Assumptions:
    00261       // _M_in_cur has already been moved back
    00262       void
    00263       _M_pback_create()
    00264       {
    00265     if (!_M_pback_init)
    00266       {
    00267         size_t __dist = _M_in_end - _M_in_cur;
    00268         size_t __len = min(_S_pback_size, __dist);
    00269         traits_type::copy(_M_pback, _M_in_cur, __len);
    00270         _M_pback_cur_save = _M_in_cur;
    00271         _M_pback_end_save = _M_in_end;
    00272         this->setg(_M_pback, _M_pback, _M_pback + __len);
    00273         _M_pback_init = true;
    00274       }
    00275       }
    00276
    00277       // Deactivates pback buffer contents, and restores normal buffer.
    00278       // Assumptions:
    00279       // The pback buffer has only moved forward.
    00280       void
    00281       _M_pback_destroy()
    00282       {
    00283     if (_M_pback_init)
    00284       {
    00285         // Length _M_in_cur moved in the pback buffer.
    00286         size_t __off_cur = _M_in_cur - _M_pback;
    00287
    00288         // For in | out buffers, the end can be pushed back...
    00289         size_t __off_end = 0;
    00290         size_t __pback_len = _M_in_end - _M_pback;
    00291         size_t __save_len = _M_pback_end_save - _M_buf;
    00292         if (__pback_len > __save_len)
    00293           __off_end = __pback_len - __save_len;
    00294
    00295         this->setg(_M_buf, _M_pback_cur_save + __off_cur,
    00296                _M_pback_end_save + __off_end);
    00297         _M_pback_cur_save = NULL;
    00298         _M_pback_end_save = NULL;
    00299         _M_pback_init = false;
    00300       }
    00301       }
    00302
    00303       // Correctly sets the _M_in_cur pointer, and bumps the
    00304       // _M_out_cur pointer as well if necessary.
    00305       void
    00306       _M_in_cur_move(off_type __n) // argument needs to be +-
    00307       {
    00308     bool __testout = _M_out_cur;
    00309     _M_in_cur += __n;
    00310     if (__testout && _M_buf_unified)
    00311       _M_out_cur += __n;
    00312       }
    00313
    00314       // Correctly sets the _M_out_cur pointer, and bumps the
    00315       // appropriate _M_*_end pointers as well. Necessary for the
    00316       // un-tied stringbufs, in in|out mode.
    00317       // Invariant:
    00318       // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size
    00319       // Assuming all _M_*_[beg, cur, end] pointers are operating on
    00320       // the same range:
    00321       // _M_buf <= _M_*_ <= _M_buf + _M_buf_size
    00322       void
    00323       _M_out_cur_move(off_type __n) // argument needs to be +-
    00324       {
    00325     bool __testin = _M_in_cur;
    00326
    00327     _M_out_cur += __n;
    00328     if (__testin && _M_buf_unified)
    00329       _M_in_cur += __n;
    00330     if (_M_out_cur > _M_out_end)
    00331       {
    00332         _M_out_end = _M_out_cur;
    00333         // NB: in | out buffers drag the _M_in_end pointer along...
    00334         if (__testin)
    00335           _M_in_end += __n;
    00336       }
    00337       }
    00338
    00339       // Return the size of the output buffer.  This depends on the
    00340       // buffer in use: allocated buffers have a stored size in
    00341       // _M_buf_size and setbuf() buffers don't.
    00342       off_type
    00343       _M_out_buf_size()
    00344       {
    00345     off_type __ret = 0;
    00346     if (_M_out_cur)
    00347       {
    00348         // Using allocated buffer.
    00349         if (_M_out_beg == _M_buf)
    00350           __ret = _M_out_beg + _M_buf_size - _M_out_cur;
    00351         // Using non-allocated buffer.
    00352         else
    00353           __ret = _M_out_end - _M_out_cur;
    00354       }
    00355     return __ret;
    00356       }
    00357
    00358   public:
    00360       virtual
    00361       ~basic_streambuf()
    00362       {
    00363     _M_buf_unified = false;
    00364     _M_buf_size = 0;
    00365     _M_buf_size_opt = 0;
    00366     _M_mode = ios_base::openmode(0);
    00367     _M_buf_locale_init = false;
    00368       }
    00369
    00370       // [27.5.2.2.1] locales
    00378       locale
    00379       pubimbue(const locale &__loc)
    00380       {
    00381     locale __tmp(this->getloc());
    00382     this->imbue(__loc);
    00383     return __tmp;
    00384       }
    00385
    00394       locale
    00395       getloc() const
    00396       {
    00397     if (_M_buf_locale_init)
    00398       return _M_buf_locale;
    00399     else
    00400       return locale();
    00401       }
    00402
    00403       // [27.5.2.2.2] buffer management and positioning
    00405
    00412       __streambuf_type*
    00413       pubsetbuf(char_type* __s, streamsize __n)
    00414       { return this->setbuf(__s, __n); }
    00415
    00416       pos_type
    00417       pubseekoff(off_type __off, ios_base::seekdir __way,
    00418          ios_base::openmode __mode = ios_base::in | ios_base::out)
    00419       { return this->seekoff(__off, __way, __mode); }
    00420
    00421       pos_type
    00422       pubseekpos(pos_type __sp,
    00423          ios_base::openmode __mode = ios_base::in | ios_base::out)
    00424       { return this->seekpos(__sp, __mode); }
    00425
    00426       int
    00427       pubsync() { return this->sync(); }
    00429
    00430       // [27.5.2.2.3] get area
    00439       streamsize
    00440       in_avail()
    00441       {
    00442     streamsize __ret;
    00443     if (_M_in_cur && _M_in_cur < _M_in_end)
    00444       {
    00445         if (_M_pback_init)
    00446           {
    00447         size_t __save_len =  _M_pback_end_save - _M_pback_cur_save;
    00448         size_t __pback_len = _M_in_cur - _M_pback;
    00449         __ret = __save_len - __pback_len;
    00450           }
    00451         else
    00452           __ret = this->egptr() - this->gptr();
    00453       }
    00454     else
    00455       __ret = this->showmanyc();
    00456     return __ret;
    00457       }
    00458
    00466       int_type
    00467       snextc()
    00468       {
    00469     int_type __eof = traits_type::eof();
    00470     return (traits_type::eq_int_type(this->sbumpc(), __eof)
    00471         ? __eof : this->sgetc());
    00472       }
    00473
    00482       int_type
    00483       sbumpc();
    00484
    00493       int_type
    00494       sgetc()
    00495       {
    00496     int_type __ret;
    00497     if (_M_in_cur && _M_in_cur < _M_in_end)
    00498       __ret = traits_type::to_int_type(*(this->gptr()));
    00499     else
    00500       __ret = this->underflow();
    00501     return __ret;
    00502       }
    00503
    00512       streamsize
    00513       sgetn(char_type* __s, streamsize __n)
    00514       { return this->xsgetn(__s, __n); }
    00515
    00516       // [27.5.2.2.4] putback
    00526       int_type
    00527       sputbackc(char_type __c);
    00528
    00538       int_type
    00539       sungetc();
    00540
    00541       // [27.5.2.2.5] put area
    00554       int_type
    00555       sputc(char_type __c);
    00556
    00568       streamsize
    00569       sputn(const char_type* __s, streamsize __n)
    00570       { return this->xsputn(__s, __n); }
    00571
    00572     protected:
    00582       basic_streambuf()
    00583       : _M_buf(NULL), _M_buf_size(0), _M_buf_size_opt(BUFSIZ),
    00584       _M_buf_unified(false), _M_in_beg(0), _M_in_cur(0), _M_in_end(0),
    00585       _M_out_beg(0), _M_out_cur(0), _M_out_end(0),
    00586       _M_mode(ios_base::openmode(0)), _M_buf_locale(locale()),
    00587       _M_buf_locale_init(false), _M_pback_cur_save(0), _M_pback_end_save(0),
    00588       _M_pback_init(false)
    00589       { }
    00590
    00591       // [27.5.2.3.1] get area access
    00593
    00603       char_type*
    00604       eback() const { return _M_in_beg; }
    00605
    00606       char_type*
    00607       gptr()  const { return _M_in_cur;  }
    00608
    00609       char_type*
    00610       egptr() const { return _M_in_end; }
    00612
    00619       void
    00620       gbump(int __n) { _M_in_cur += __n; }
    00621
    00630       void
    00631       setg(char_type* __gbeg, char_type* __gnext, char_type* __gend)
    00632       {
    00633     _M_in_beg = __gbeg;
    00634     _M_in_cur = __gnext;
    00635     _M_in_end = __gend;
    00636     if (!(_M_mode & ios_base::in) && __gbeg && __gnext && __gend)
    00637       _M_mode = _M_mode | ios_base::in;
    00638       }
    00639
    00640       // [27.5.2.3.2] put area access
    00642
    00652       char_type*
    00653       pbase() const { return _M_out_beg; }
    00654
    00655       char_type*
    00656       pptr() const { return _M_out_cur; }
    00657
    00658       char_type*
    00659       epptr() const { return _M_out_end; }
    00661
    00668       void
    00669       pbump(int __n) { _M_out_cur += __n; }
    00670
    00678       void
    00679       setp(char_type* __pbeg, char_type* __pend)
    00680       {
    00681     _M_out_beg = _M_out_cur = __pbeg;
    00682     _M_out_end = __pend;
    00683     if (!(_M_mode & ios_base::out) && __pbeg && __pend)
    00684       _M_mode = _M_mode | ios_base::out;
    00685       }
    00686
    00687       // [27.5.2.4] virtual functions
    00688       // [27.5.2.4.1] locales
    00700       virtual void
    00701       imbue(const locale& __loc)
    00702       {
    00703     _M_buf_locale_init = true;
    00704     if (_M_buf_locale != __loc)
    00705       _M_buf_locale = __loc;
    00706       }
    00707
    00708       // [27.5.2.4.2] buffer management and positioning
    00719       virtual basic_streambuf<char_type,_Traits>*
    00720       setbuf(char_type*, streamsize)
    00721       { return this; }
    00722
    00730       virtual pos_type
    00731       seekoff(off_type, ios_base::seekdir,
    00732           ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
    00733       { return pos_type(off_type(-1)); }
    00734
    00742       virtual pos_type
    00743       seekpos(pos_type,
    00744           ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
    00745       { return pos_type(off_type(-1)); }
    00746
    00755       virtual int
    00756       sync() { return 0; }
    00757
    00758       // [27.5.2.4.3] get area
    00777       virtual streamsize
    00778       showmanyc() { return 0; }
    00779
    00793       virtual streamsize
    00794       xsgetn(char_type* __s, streamsize __n);
    00795
    00815       virtual int_type
    00816       underflow()
    00817       { return traits_type::eof(); }
    00818
    00828       virtual int_type
    00829       uflow()
    00830       {
    00831     int_type __ret = traits_type::eof();
    00832     bool __testeof = traits_type::eq_int_type(this->underflow(), __ret);
    00833     bool __testpending = _M_in_cur && _M_in_cur < _M_in_end;
    00834     if (!__testeof && __testpending)
    00835       {
    00836         __ret = traits_type::to_int_type(*_M_in_cur);
    00837         ++_M_in_cur;
    00838         if (_M_buf_unified && _M_mode & ios_base::out)
    00839           ++_M_out_cur;
    00840       }
    00841     return __ret;
    00842       }
    00843
    00844       // [27.5.2.4.4] putback
    00854       virtual int_type
    00855       pbackfail(int_type /* __c */  = traits_type::eof())
    00856       { return traits_type::eof(); }
    00857
    00858       // Put area:
    00872       virtual streamsize
    00873       xsputn(const char_type* __s, streamsize __n);
    00874
    00897       virtual int_type
    00898       overflow(int_type /* __c */ = traits_type::eof())
    00899       { return traits_type::eof(); }
    00900
    00901 #ifdef _GLIBCPP_DEPRECATED
    00902     // Annex D.6
    00903     public:
    00916       void
    00917       stossc()
    00918       {
    00919     if (_M_in_cur < _M_in_end)
    00920       ++_M_in_cur;
    00921     else
    00922       this->uflow();
    00923       }
    00924 #endif
    00925
    00926 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
    00927     // Side effect of DR 50.
    00928     private:
    00929       basic_streambuf(const __streambuf_type&) { };
    00930
    00931       __streambuf_type&
    00932       operator=(const __streambuf_type&) { return *this; };
    00933 #endif
    00934     };
    00935 } // namespace std
    00936
    00937 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
    00938 # define export
    00939 #endif
    00940 #ifdef  _GLIBCPP_FULLY_COMPLIANT_HEADERS
    00941 #include <bits/streambuf.tcc>
    00942 #endif
    00943
    00944 #endif