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  

Generated on Thu Nov 21 03:12:51 2002 for libstdc++-v3 Source by doxygen1.2.18-20021030