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  

Generated on Wed May 1 19:19:38 2002 for libstdc++-v3 Source by doxygen1.2.15