Whole document tree
    

Whole document tree

std_streambuf.h Source File
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

std_streambuf.h

Go to the documentation of this file.
00001 // Stream buffer classes -*- C++ -*-
00002 
00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License along
00017 // with this library; see the file COPYING.  If not, write to the Free
00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00019 // USA.
00020 
00021 // As a special exception, you may use this file as part of a free software
00022 // library without restriction.  Specifically, if other files instantiate
00023 // templates or use macros or inline functions from this file, or you compile
00024 // this file and link it with other files to produce an executable, this
00025 // file does not by itself cause the resulting executable to be covered by
00026 // the GNU General Public License.  This exception does not however
00027 // invalidate any other reasons why the executable file might be covered by
00028 // the GNU General Public License.
00029 
00030 //
00031 // ISO C++ 14882: 27.5  Stream buffers
00032 //
00033 
00034 #ifndef _CPP_STREAMBUF
00035 #define _CPP_STREAMBUF  1
00036 
00037 #pragma GCC system_header
00038 
00039 #include <bits/c++config.h>
00040 #include <bits/std_iosfwd.h>
00041 #include <bits/std_cstdio.h>    // For SEEK_SET, SEEK_CUR, SEEK_END
00042 #include <bits/localefwd.h>
00043 #include <bits/ios_base.h>
00044 
00045 namespace std
00046 {
00047   template<typename _CharT, typename _Traits>
00048     streamsize
00049     __copy_streambufs(basic_ios<_CharT, _Traits>& _ios,
00050               basic_streambuf<_CharT, _Traits>* __sbin,
00051               basic_streambuf<_CharT, _Traits>* __sbout);
00052   
00053   // 27.5.2 Template class basic_streambuf<_CharT, _Traits>
00054   template<typename _CharT, typename _Traits>
00055     class basic_streambuf 
00056     {
00057     public:
00058       // Types:
00059       typedef _CharT                    char_type;
00060       typedef _Traits                   traits_type;
00061       typedef typename traits_type::int_type        int_type;
00062       typedef typename traits_type::pos_type        pos_type;
00063       typedef typename traits_type::off_type        off_type;
00064 
00065       // Non-standard Types:
00066       typedef ctype<char_type>                  __ctype_type;
00067       typedef basic_streambuf<char_type, traits_type>   __streambuf_type;
00068       
00069       friend class basic_ios<char_type, traits_type>;
00070       friend class basic_istream<char_type, traits_type>;
00071       friend class basic_ostream<char_type, traits_type>;
00072       friend class istreambuf_iterator<char_type, traits_type>;
00073       friend class ostreambuf_iterator<char_type, traits_type>;
00074 
00075       friend streamsize
00076       __copy_streambufs<>(basic_ios<char_type, traits_type>& __ios,
00077               __streambuf_type* __sbin,__streambuf_type* __sbout);
00078       
00079     protected:
00080 
00081       // Pointer to the beginning of internally-allocated
00082       // space. Filebuf manually allocates/deallocates this, whereas
00083       // stringstreams attempt to use the built-in intelligence of the
00084       // string class. If you are managing memory, set this. If not,
00085       // leave it NULL.
00086       char_type*        _M_buf;     
00087 
00088       // Actual size of allocated internal buffer, in bytes.
00089       int_type          _M_buf_size;
00090 
00091       // Optimal or preferred size of internal buffer, in bytes.
00092       int_type          _M_buf_size_opt;
00093 
00094       // True iff _M_in_* and _M_out_* buffers should always point to
00095       // the same place.  True for fstreams, false for sstreams.
00096       bool          _M_buf_unified; 
00097 
00098        // This is based on _IO_FILE, just reordered to be more
00099       // consistent, and is intended to be the most minimal abstraction
00100       // for an internal buffer.
00101       // get == input == read
00102       // put == output == write
00103       char_type*        _M_in_beg;      // Start of get area. 
00104       char_type*        _M_in_cur;  // Current read area. 
00105       char_type*        _M_in_end;  // End of get area. 
00106       char_type*        _M_out_beg;     // Start of put area. 
00107       char_type*        _M_out_cur;     // Current put area. 
00108       char_type*        _M_out_end;     // End of put area. 
00109 
00110       // Place to stash in || out || in | out settings for current streambuf.
00111       ios_base::openmode    _M_mode;    
00112 
00113       // Current locale setting.
00114       locale            _M_buf_locale;  
00115 
00116       // True iff locale is initialized.
00117       bool          _M_buf_locale_init;
00118 
00119       // Necessary bits for putback buffer management. Only used in
00120       // the basic_filebuf class, as necessary for the standard
00121       // requirements. The only basic_streambuf member function that
00122       // needs access to these data members is in_avail...
00123       // NB: pbacks of over one character are not currently supported.
00124       int_type          _M_pback_size; 
00125       char_type*        _M_pback; 
00126       char_type*        _M_pback_cur_save;
00127       char_type*        _M_pback_end_save;
00128       bool          _M_pback_init; 
00129 
00130       // Initializes pback buffers, and moves normal buffers to safety.
00131       // Assumptions:
00132       // _M_in_cur has already been moved back
00133       void
00134       _M_pback_create()
00135       {
00136     if (!_M_pback_init)
00137       {
00138         int_type __dist = _M_in_end - _M_in_cur;
00139         int_type __len = min(_M_pback_size, __dist);
00140         traits_type::copy(_M_pback, _M_in_cur, __len);
00141         _M_pback_cur_save = _M_in_cur;
00142         _M_pback_end_save = _M_in_end;
00143         this->setg(_M_pback, _M_pback, _M_pback + __len);
00144         _M_pback_init = true;
00145       }
00146       }
00147 
00148       // Deactivates pback buffer contents, and restores normal buffer.
00149       // Assumptions:
00150       // The pback buffer has only moved forward.
00151       void
00152       _M_pback_destroy()
00153       {
00154     if (_M_pback_init)
00155       {
00156         // Length _M_in_cur moved in the pback buffer.
00157         int_type __off_cur = _M_in_cur - _M_pback;
00158         
00159         // For in | out buffers, the end can be pushed back...
00160         int_type __off_end = 0;
00161         int_type __pback_len = _M_in_end - _M_pback;
00162         int_type __save_len = _M_pback_end_save - _M_buf;
00163         if (__pback_len > __save_len)
00164           __off_end = __pback_len - __save_len;
00165 
00166         this->setg(_M_buf, _M_pback_cur_save + __off_cur, 
00167                _M_pback_end_save + __off_end);
00168         _M_pback_cur_save = NULL;
00169         _M_pback_end_save = NULL;
00170         _M_pback_init = false;
00171       }
00172       }
00173 
00174       // Correctly sets the _M_in_cur pointer, and bumps the
00175       // _M_out_cur pointer as well if necessary.
00176       void 
00177       _M_in_cur_move(off_type __n) // argument needs to be +-
00178       {
00179     bool __testout = _M_out_cur;
00180     _M_in_cur += __n;
00181     if (__testout && _M_buf_unified)
00182       _M_out_cur += __n;
00183       }
00184 
00185       // Correctly sets the _M_out_cur pointer, and bumps the
00186       // appropriate _M_*_end pointers as well. Necessary for the
00187       // un-tied stringbufs, in in|out mode.
00188       // Invariant:
00189       // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size
00190       // Assuming all _M_*_[beg, cur, end] pointers are operating on
00191       // the same range:
00192       // _M_buf <= _M_*_ <= _M_buf + _M_buf_size
00193       void 
00194       _M_out_cur_move(off_type __n) // argument needs to be +-
00195       {
00196     bool __testin = _M_in_cur;
00197 
00198     _M_out_cur += __n;
00199     if (__testin && _M_buf_unified)
00200       _M_in_cur += __n;
00201     if (_M_out_cur > _M_out_end)
00202       {
00203         _M_out_end = _M_out_cur;
00204         // NB: in | out buffers drag the _M_in_end pointer along...
00205         if (__testin)
00206           _M_in_end += __n;
00207       }
00208       }
00209 
00210       // Return the size of the output buffer.  This depends on the
00211       // buffer in use: allocated buffers have a stored size in
00212       // _M_buf_size and setbuf() buffers don't.
00213       off_type
00214       _M_out_buf_size()
00215       {
00216     off_type __ret = 0;
00217     if (_M_out_cur)
00218       {
00219         // Using allocated buffer.
00220         if (_M_out_beg == _M_buf)
00221           __ret = _M_out_beg + _M_buf_size - _M_out_cur;
00222         // Using non-allocated buffer.
00223         else
00224           __ret = _M_out_end - _M_out_cur;
00225       }
00226     return __ret;
00227       }
00228 
00229       // These three functions are used to clarify internal buffer
00230       // maintenance. After an overflow, or after a seekoff call that
00231       // started at beg or end, or possibly when the stream becomes
00232       // unbuffered, and a myrid other obscure corner cases, the
00233       // internal buffer does not truly reflect the contents of the
00234       // external buffer. At this point, for whatever reason, it is in
00235       // an indeterminate state.
00236       void
00237       _M_set_indeterminate(void)
00238       {
00239     if (_M_mode & ios_base::in)
00240       this->setg(_M_buf, _M_buf, _M_buf);
00241     if (_M_mode & ios_base::out)
00242       this->setp(_M_buf, _M_buf);
00243       }
00244 
00245       void
00246       _M_set_determinate(off_type __off)
00247       {
00248     bool __testin = _M_mode & ios_base::in;
00249     bool __testout = _M_mode & ios_base::out;
00250     if (__testin)
00251       this->setg(_M_buf, _M_buf, _M_buf + __off);
00252     if (__testout)
00253       this->setp(_M_buf, _M_buf + __off);
00254       }
00255 
00256       bool
00257       _M_is_indeterminate(void)
00258       { 
00259     bool __ret = false;
00260     // Don't return true if unbuffered.
00261     if (_M_buf)
00262       {
00263         if (_M_mode & ios_base::in)
00264           __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end;
00265         if (_M_mode & ios_base::out)
00266           __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end;
00267       }
00268     return __ret;
00269       }
00270 
00271   public:
00272       virtual 
00273       ~basic_streambuf() 
00274       {
00275     _M_buf_unified = false;
00276     _M_buf_size = 0;
00277     _M_buf_size_opt = 0;
00278     _M_mode = ios_base::openmode(0);
00279     _M_buf_locale_init = false;
00280       }
00281 
00282       // Locales:
00283       locale 
00284       pubimbue(const locale &__loc)
00285       {
00286     locale __tmp(this->getloc());
00287     this->imbue(__loc);
00288     return __tmp;
00289       }
00290 
00291       locale   
00292       getloc() const
00293       {
00294     if (_M_buf_locale_init)
00295       return _M_buf_locale; 
00296     else 
00297       return locale();
00298       } 
00299 
00300       // Buffer and positioning:
00301       __streambuf_type* 
00302       pubsetbuf(char_type* __s, streamsize __n) 
00303       { return this->setbuf(__s, __n); }
00304 
00305       pos_type 
00306       pubseekoff(off_type __off, ios_base::seekdir __way, 
00307          ios_base::openmode __mode = ios_base::in | ios_base::out)
00308       { return this->seekoff(__off, __way, __mode); }
00309 
00310       pos_type 
00311       pubseekpos(pos_type __sp,
00312          ios_base::openmode __mode = ios_base::in | ios_base::out)
00313       { return this->seekpos(__sp, __mode); }
00314 
00315       int 
00316       pubsync() { return this->sync(); }
00317 
00318       // Get and put areas:
00319       // Get area:
00320       streamsize 
00321       in_avail() 
00322       { 
00323     streamsize __ret;
00324     if (_M_in_cur && _M_in_cur < _M_in_end)
00325       {
00326         if (_M_pback_init)
00327           {
00328         int_type __save_len =  _M_pback_end_save - _M_pback_cur_save;
00329         int_type __pback_len = _M_in_cur - _M_pback;
00330         __ret = __save_len - __pback_len;
00331           }
00332         else
00333           __ret = this->egptr() - this->gptr();
00334       }
00335     else
00336       __ret = this->showmanyc();
00337     return __ret;
00338       }
00339 
00340       int_type 
00341       snextc()
00342       {
00343     int_type __eof = traits_type::eof();
00344     return (this->sbumpc() == __eof ? __eof : this->sgetc()); 
00345       }
00346 
00347       int_type 
00348       sbumpc();
00349 
00350       int_type 
00351       sgetc()
00352       {
00353     int_type __ret;
00354     if (_M_in_cur && _M_in_cur < _M_in_end)
00355       __ret = traits_type::to_int_type(*(this->gptr()));
00356     else 
00357       __ret = this->underflow();
00358     return __ret;
00359       }
00360 
00361       streamsize 
00362       sgetn(char_type* __s, streamsize __n)
00363       { return this->xsgetn(__s, __n); }
00364 
00365       // Putback:
00366       int_type 
00367       sputbackc(char_type __c);
00368 
00369       int_type 
00370       sungetc();
00371 
00372       // Put area:
00373       int_type 
00374       sputc(char_type __c);
00375 
00376       streamsize 
00377       sputn(const char_type* __s, streamsize __n)
00378       { return this->xsputn(__s, __n); }
00379 
00380     protected:
00381       basic_streambuf()
00382       : _M_buf(NULL), _M_buf_size(0), 
00383       _M_buf_size_opt(static_cast<int_type>(BUFSIZ)), _M_buf_unified(false), 
00384       _M_in_beg(0), _M_in_cur(0), _M_in_end(0), _M_out_beg(0), _M_out_cur(0), 
00385       _M_out_end(0), _M_mode(ios_base::openmode(0)), _M_buf_locale(locale()), 
00386       _M_buf_locale_init(false), _M_pback_size(1), _M_pback(NULL), 
00387       _M_pback_cur_save(NULL), _M_pback_end_save(NULL), _M_pback_init(false)
00388       { }
00389 
00390       // Get area:
00391       char_type* 
00392       eback() const { return _M_in_beg; }
00393 
00394       char_type* 
00395       gptr()  const { return _M_in_cur;  }
00396 
00397       char_type* 
00398       egptr() const { return _M_in_end; }
00399 
00400       void 
00401       gbump(int __n) { _M_in_cur += __n; }
00402 
00403       void 
00404       setg(char_type* __gbeg, char_type* __gnext, char_type* __gend)
00405       {
00406     _M_in_beg = __gbeg;
00407     _M_in_cur = __gnext;
00408     _M_in_end = __gend;
00409     if (!(_M_mode & ios_base::in) && __gbeg && __gnext && __gend)
00410       _M_mode = _M_mode | ios_base::in;
00411       }
00412 
00413       // Put area:
00414       char_type* 
00415       pbase() const { return _M_out_beg; }
00416 
00417       char_type* 
00418       pptr() const { return _M_out_cur; }
00419 
00420       char_type* 
00421       epptr() const { return _M_out_end; }
00422 
00423       void 
00424       pbump(int __n) { _M_out_cur += __n; }
00425 
00426       void 
00427       setp(char_type* __pbeg, char_type* __pend)
00428       { 
00429     _M_out_beg = _M_out_cur = __pbeg; 
00430     _M_out_end = __pend; 
00431     if (!(_M_mode & ios_base::out) && __pbeg && __pend)
00432       _M_mode = _M_mode | ios_base::out;
00433       }
00434 
00435       // Virtual functions:
00436       // Locales:
00437       virtual void 
00438       imbue(const locale& __loc) 
00439       { 
00440     _M_buf_locale_init = true;
00441     if (_M_buf_locale != __loc)
00442       _M_buf_locale = __loc;
00443       }
00444 
00445       // Buffer management and positioning:
00446       virtual basic_streambuf<char_type,_Traits>* 
00447       setbuf(char_type*, streamsize)
00448       { return this; }
00449       
00450       virtual pos_type 
00451       seekoff(off_type, ios_base::seekdir,
00452           ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
00453       { return pos_type(off_type(-1)); } 
00454 
00455       virtual pos_type 
00456       seekpos(pos_type, 
00457           ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
00458       { return pos_type(off_type(-1)); } 
00459 
00460       virtual int 
00461       sync() { return 0; }
00462 
00463       // Get area:
00464       virtual streamsize 
00465       showmanyc() { return 0; }
00466 
00467       virtual streamsize 
00468       xsgetn(char_type* __s, streamsize __n);
00469 
00470       virtual int_type 
00471       underflow()
00472       { return traits_type::eof(); }
00473 
00474       virtual int_type 
00475       uflow() 
00476       {
00477     int_type __ret = traits_type::eof();
00478     bool __testeof = this->underflow() == __ret;
00479     bool __testpending = _M_in_cur && _M_in_cur < _M_in_end;
00480     if (!__testeof && __testpending)
00481       {
00482         __ret = traits_type::to_int_type(*_M_in_cur);
00483         ++_M_in_cur;
00484         if (_M_buf_unified && _M_mode & ios_base::out)
00485           ++_M_out_cur;
00486       }
00487     return __ret;    
00488       }
00489 
00490       // Putback:
00491       virtual int_type 
00492       pbackfail(int_type /* __c */  = traits_type::eof())
00493       { return traits_type::eof(); }
00494 
00495       // Put area:
00496       virtual streamsize 
00497       xsputn(const char_type* __s, streamsize __n);
00498 
00499       virtual int_type 
00500       overflow(int_type /* __c */ = traits_type::eof())
00501       { return traits_type::eof(); }
00502 
00503 #ifdef _GLIBCPP_DEPRECATED
00504     public:
00505       void 
00506       stossc() 
00507       {
00508     if (_M_in_cur < _M_in_end) 
00509       ++_M_in_cur;
00510     else 
00511       this->uflow();
00512       }
00513 #endif
00514 
00515 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
00516     private:
00517       basic_streambuf(const __streambuf_type&);
00518 
00519       __streambuf_type& 
00520       operator=(const __streambuf_type&);
00521 #endif
00522     };
00523 
00524 } // namespace std
00525 
00526 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
00527 # define export
00528 #ifdef  _GLIBCPP_FULLY_COMPLIANT_HEADERS
00529 #include <bits/streambuf.tcc>
00530 #endif
00531 #endif
00532 
00533 #endif  /* _CPP_STREAMBUF */
00534 

Generated on Mon Apr 8 03:11:35 2002 for libstdc++-v3 Source by doxygen1.2.15