Whole document tree std_streambuf.hGo 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 ![]() |