streambuf

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

Generated on Wed Sep 29 13:54:53 2004 for libstdc++-v3 Source by doxygen 1.3.7