1 // Stream buffer classes -*- C++ -*- 2 3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 2, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // You should have received a copy of the GNU General Public License along 18 // with this library; see the file COPYING. If not, write to the Free 19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 20 // USA. 21 22 // As a special exception, you may use this file as part of a free software 23 // library without restriction. Specifically, if other files instantiate 24 // templates or use macros or inline functions from this file, or you compile 25 // this file and link it with other files to produce an executable, this 26 // file does not by itself cause the resulting executable to be covered by 27 // the GNU General Public License. This exception does not however 28 // invalidate any other reasons why the executable file might be covered by 29 // the GNU General Public License. 30 31 // 32 // ISO C++ 14882: 27.5 Stream buffers 33 // 34 35 /** @file streambuf 36 * This is a Standard C++ Library header. You should @c #include this header 37 * in your programs, rather than any of the "st[dl]_*.h" implementation files. 38 */ 39 40 #ifndef _CPP_STREAMBUF 41 #define _CPP_STREAMBUF 1 42 43 #pragma GCC system_header 44 45 #include <bits/c++config.h> 46 #include <iosfwd> 47 #include <cstdio> // For SEEK_SET, SEEK_CUR, SEEK_END 48 #include <bits/localefwd.h> 49 #include <bits/ios_base.h> 50 51 namespace std 52 { 53 template<typename _CharT, typename _Traits> 54 streamsize 55 __copy_streambufs(basic_ios<_CharT, _Traits>& _ios, 56 basic_streambuf<_CharT, _Traits>* __sbin, 57 basic_streambuf<_CharT, _Traits>* __sbout); 58 59 // 27.5.2 Template class basic_streambuf<_CharT, _Traits> 60 template<typename _CharT, typename _Traits> 61 class basic_streambuf 62 { 63 public: 64 // Types: 65 typedef _CharT char_type; 66 typedef _Traits traits_type; 67 typedef typename traits_type::int_type int_type; 68 typedef typename traits_type::pos_type pos_type; 69 typedef typename traits_type::off_type off_type; 70 71 // Non-standard Types: 72 typedef ctype<char_type> __ctype_type; 73 typedef basic_streambuf<char_type, traits_type> __streambuf_type; 74 75 friend class basic_ios<char_type, traits_type>; 76 friend class basic_istream<char_type, traits_type>; 77 friend class basic_ostream<char_type, traits_type>; 78 friend class istreambuf_iterator<char_type, traits_type>; 79 friend class ostreambuf_iterator<char_type, traits_type>; 80 81 friend streamsize 82 __copy_streambufs<>(basic_ios<char_type, traits_type>& __ios, 83 __streambuf_type* __sbin,__streambuf_type* __sbout); 84 85 protected: 86 // Pointer to the beginning of internally-allocated 87 // space. Filebuf manually allocates/deallocates this, whereas 88 // stringstreams attempt to use the built-in intelligence of the 89 // string class. If you are managing memory, set this. If not, 90 // leave it NULL. 91 char_type* _M_buf; 92 93 // Actual size of allocated internal buffer, in bytes. 94 int_type _M_buf_size; 95 96 // Optimal or preferred size of internal buffer, in bytes. 97 int_type _M_buf_size_opt; 98 99 // True iff _M_in_* and _M_out_* buffers should always point to 100 // the same place. True for fstreams, false for sstreams. 101 bool _M_buf_unified; 102 103 // This is based on _IO_FILE, just reordered to be more 104 // consistent, and is intended to be the most minimal abstraction 105 // for an internal buffer. 106 // get == input == read 107 // put == output == write 108 char_type* _M_in_beg; // Start of get area. 109 char_type* _M_in_cur; // Current read area. 110 char_type* _M_in_end; // End of get area. 111 char_type* _M_out_beg; // Start of put area. 112 char_type* _M_out_cur; // Current put area. 113 char_type* _M_out_end; // End of put area. 114 115 // Place to stash in || out || in | out settings for current streambuf. 116 ios_base::openmode _M_mode; 117 118 // Current locale setting. 119 locale _M_buf_locale; 120 121 // True iff locale is initialized. 122 bool _M_buf_locale_init; 123 124 // Necessary bits for putback buffer management. Only used in 125 // the basic_filebuf class, as necessary for the standard 126 // requirements. The only basic_streambuf member function that 127 // needs access to these data members is in_avail... 128 // NB: pbacks of over one character are not currently supported. 129 static const int_type _S_pback_size = 1; 130 char_type _M_pback[_S_pback_size]; 131 char_type* _M_pback_cur_save; 132 char_type* _M_pback_end_save; 133 bool _M_pback_init; 134 135 // Initializes pback buffers, and moves normal buffers to safety. 136 // Assumptions: 137 // _M_in_cur has already been moved back 138 void 139 _M_pback_create() 140 { 141 if (!_M_pback_init) 142 { 143 int_type __dist = _M_in_end - _M_in_cur; 144 int_type __len = min(_S_pback_size, __dist); 145 traits_type::copy(_M_pback, _M_in_cur, __len); 146 _M_pback_cur_save = _M_in_cur; 147 _M_pback_end_save = _M_in_end; 148 this->setg(_M_pback, _M_pback, _M_pback + __len); 149 _M_pback_init = true; 150 } 151 } 152 153 // Deactivates pback buffer contents, and restores normal buffer. 154 // Assumptions: 155 // The pback buffer has only moved forward. 156 void 157 _M_pback_destroy() 158 { 159 if (_M_pback_init) 160 { 161 // Length _M_in_cur moved in the pback buffer. 162 int_type __off_cur = _M_in_cur - _M_pback; 163 164 // For in | out buffers, the end can be pushed back... 165 int_type __off_end = 0; 166 int_type __pback_len = _M_in_end - _M_pback; 167 int_type __save_len = _M_pback_end_save - _M_buf; 168 if (__pback_len > __save_len) 169 __off_end = __pback_len - __save_len; 170 171 this->setg(_M_buf, _M_pback_cur_save + __off_cur, 172 _M_pback_end_save + __off_end); 173 _M_pback_cur_save = NULL; 174 _M_pback_end_save = NULL; 175 _M_pback_init = false; 176 } 177 } 178 179 // Correctly sets the _M_in_cur pointer, and bumps the 180 // _M_out_cur pointer as well if necessary. 181 void 182 _M_in_cur_move(off_type __n) // argument needs to be +- 183 { 184 bool __testout = _M_out_cur; 185 _M_in_cur += __n; 186 if (__testout && _M_buf_unified) 187 _M_out_cur += __n; 188 } 189 190 // Correctly sets the _M_out_cur pointer, and bumps the 191 // appropriate _M_*_end pointers as well. Necessary for the 192 // un-tied stringbufs, in in|out mode. 193 // Invariant: 194 // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size 195 // Assuming all _M_*_[beg, cur, end] pointers are operating on 196 // the same range: 197 // _M_buf <= _M_*_ <= _M_buf + _M_buf_size 198 void 199 _M_out_cur_move(off_type __n) // argument needs to be +- 200 { 201 bool __testin = _M_in_cur; 202 203 _M_out_cur += __n; 204 if (__testin && _M_buf_unified) 205 _M_in_cur += __n; 206 if (_M_out_cur > _M_out_end) 207 { 208 _M_out_end = _M_out_cur; 209 // NB: in | out buffers drag the _M_in_end pointer along... 210 if (__testin) 211 _M_in_end += __n; 212 } 213 } 214 215 // Return the size of the output buffer. This depends on the 216 // buffer in use: allocated buffers have a stored size in 217 // _M_buf_size and setbuf() buffers don't. 218 off_type 219 _M_out_buf_size() 220 { 221 off_type __ret = 0; 222 if (_M_out_cur) 223 { 224 // Using allocated buffer. 225 if (_M_out_beg == _M_buf) 226 __ret = _M_out_beg + _M_buf_size - _M_out_cur; 227 // Using non-allocated buffer. 228 else 229 __ret = _M_out_end - _M_out_cur; 230 } 231 return __ret; 232 } 233 234 public: 235 virtual 236 ~basic_streambuf() 237 { 238 _M_buf_unified = false; 239 _M_buf_size = 0; 240 _M_buf_size_opt = 0; 241 _M_mode = ios_base::openmode(0); 242 _M_buf_locale_init = false; 243 } 244 245 // Locales: 246 locale 247 pubimbue(const locale &__loc) 248 { 249 locale __tmp(this->getloc()); 250 this->imbue(__loc); 251 return __tmp; 252 } 253 254 locale 255 getloc() const 256 { 257 if (_M_buf_locale_init) 258 return _M_buf_locale; 259 else 260 return locale(); 261 } 262 263 // Buffer and positioning: 264 __streambuf_type* 265 pubsetbuf(char_type* __s, streamsize __n) 266 { return this->setbuf(__s, __n); } 267 268 pos_type 269 pubseekoff(off_type __off, ios_base::seekdir __way, 270 ios_base::openmode __mode = ios_base::in | ios_base::out) 271 { return this->seekoff(__off, __way, __mode); } 272 273 pos_type 274 pubseekpos(pos_type __sp, 275 ios_base::openmode __mode = ios_base::in | ios_base::out) 276 { return this->seekpos(__sp, __mode); } 277 278 int 279 pubsync() { return this->sync(); } 280 281 // Get and put areas: 282 // Get area: 283 streamsize 284 in_avail() 285 { 286 streamsize __ret; 287 if (_M_in_cur && _M_in_cur < _M_in_end) 288 { 289 if (_M_pback_init) 290 { 291 int_type __save_len = _M_pback_end_save - _M_pback_cur_save; 292 int_type __pback_len = _M_in_cur - _M_pback; 293 __ret = __save_len - __pback_len; 294 } 295 else 296 __ret = this->egptr() - this->gptr(); 297 } 298 else 299 __ret = this->showmanyc(); 300 return __ret; 301 } 302 303 int_type 304 snextc() 305 { 306 int_type __eof = traits_type::eof(); 307 return (this->sbumpc() == __eof ? __eof : this->sgetc()); 308 } 309 310 int_type 311 sbumpc(); 312 313 int_type 314 sgetc() 315 { 316 int_type __ret; 317 if (_M_in_cur && _M_in_cur < _M_in_end) 318 __ret = traits_type::to_int_type(*(this->gptr())); 319 else 320 __ret = this->underflow(); 321 return __ret; 322 } 323 324 streamsize 325 sgetn(char_type* __s, streamsize __n) 326 { return this->xsgetn(__s, __n); } 327 328 // Putback: 329 int_type 330 sputbackc(char_type __c); 331 332 int_type 333 sungetc(); 334 335 // Put area: 336 int_type 337 sputc(char_type __c); 338 339 streamsize 340 sputn(const char_type* __s, streamsize __n) 341 { return this->xsputn(__s, __n); } 342 343 protected: 344 basic_streambuf() 345 : _M_buf(NULL), _M_buf_size(0), 346 _M_buf_size_opt(static_cast<int_type>(BUFSIZ)), _M_buf_unified(false), 347 _M_in_beg(0), _M_in_cur(0), _M_in_end(0), _M_out_beg(0), _M_out_cur(0), 348 _M_out_end(0), _M_mode(ios_base::openmode(0)), _M_buf_locale(locale()), 349 _M_buf_locale_init(false), _M_pback_cur_save(0), _M_pback_end_save(0), 350 _M_pback_init(false) 351 { } 352 353 // Get area: 354 char_type* 355 eback() const { return _M_in_beg; } 356 357 char_type* 358 gptr() const { return _M_in_cur; } 359 360 char_type* 361 egptr() const { return _M_in_end; } 362 363 void 364 gbump(int __n) { _M_in_cur += __n; } 365 366 void 367 setg(char_type* __gbeg, char_type* __gnext, char_type* __gend) 368 { 369 _M_in_beg = __gbeg; 370 _M_in_cur = __gnext; 371 _M_in_end = __gend; 372 if (!(_M_mode & ios_base::in) && __gbeg && __gnext && __gend) 373 _M_mode = _M_mode | ios_base::in; 374 } 375 376 // Put area: 377 char_type* 378 pbase() const { return _M_out_beg; } 379 380 char_type* 381 pptr() const { return _M_out_cur; } 382 383 char_type* 384 epptr() const { return _M_out_end; } 385 386 void 387 pbump(int __n) { _M_out_cur += __n; } 388 389 void 390 setp(char_type* __pbeg, char_type* __pend) 391 { 392 _M_out_beg = _M_out_cur = __pbeg; 393 _M_out_end = __pend; 394 if (!(_M_mode & ios_base::out) && __pbeg && __pend) 395 _M_mode = _M_mode | ios_base::out; 396 } 397 398 // Virtual functions: 399 // Locales: 400 virtual void 401 imbue(const locale& __loc) 402 { 403 _M_buf_locale_init = true; 404 if (_M_buf_locale != __loc) 405 _M_buf_locale = __loc; 406 } 407 408 // Buffer management and positioning: 409 virtual basic_streambuf<char_type,_Traits>* 410 setbuf(char_type*, streamsize) 411 { return this; } 412 413 virtual pos_type 414 seekoff(off_type, ios_base::seekdir, 415 ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out) 416 { return pos_type(off_type(-1)); } 417 418 virtual pos_type 419 seekpos(pos_type, 420 ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out) 421 { return pos_type(off_type(-1)); } 422 423 virtual int 424 sync() { return 0; } 425 426 // Get area: 427 virtual streamsize 428 showmanyc() { return 0; } 429 430 virtual streamsize 431 xsgetn(char_type* __s, streamsize __n); 432 433 virtual int_type 434 underflow() 435 { return traits_type::eof(); } 436 437 virtual int_type 438 uflow() 439 { 440 int_type __ret = traits_type::eof(); 441 bool __testeof = this->underflow() == __ret; 442 bool __testpending = _M_in_cur && _M_in_cur < _M_in_end; 443 if (!__testeof && __testpending) 444 { 445 __ret = traits_type::to_int_type(*_M_in_cur); 446 ++_M_in_cur; 447 if (_M_buf_unified && _M_mode & ios_base::out) 448 ++_M_out_cur; 449 } 450 return __ret; 451 } 452 453 // Putback: 454 virtual int_type 455 pbackfail(int_type /* __c */ = traits_type::eof()) 456 { return traits_type::eof(); } 457 458 // Put area: 459 virtual streamsize 460 xsputn(const char_type* __s, streamsize __n); 461 462 virtual int_type 463 overflow(int_type /* __c */ = traits_type::eof()) 464 { return traits_type::eof(); } 465 466 #ifdef _GLIBCPP_DEPRECATED 467 public: 468 void 469 stossc() 470 { 471 if (_M_in_cur < _M_in_end) 472 ++_M_in_cur; 473 else 474 this->uflow(); 475 } 476 #endif 477 478 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS 479 // Side effect of DR 50. 480 private: 481 basic_streambuf(const __streambuf_type&) { }; 482 483 __streambuf_type& 484 operator=(const __streambuf_type&) { return *this; }; 485 #endif 486 }; 487 } // namespace std 488 489 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT 490 # define export 491 #endif 492 #ifdef _GLIBCPP_FULLY_COMPLIANT_HEADERS 493 #include <bits/streambuf.tcc> 494 #endif 495 496 #endif 497