1// String based streams -*- C++ -*- 2 3// Copyright (C) 1997-2020 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 3, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// Under Section 7 of GPL version 3, you are granted additional 17// permissions described in the GCC Runtime Library Exception, version 18// 3.1, as published by the Free Software Foundation. 19 20// You should have received a copy of the GNU General Public License and 21// a copy of the GCC Runtime Library Exception along with this program; 22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23// <http://www.gnu.org/licenses/>. 24 25/** @file include/sstream 26 * This is a Standard C++ Library header. 27 */ 28 29// 30// ISO C++ 14882: 27.7 String-based streams 31// 32 33#ifndef _GLIBCXX_SSTREAM 34#define _GLIBCXX_SSTREAM 1 35 36#pragma GCC system_header 37 38#include <istream> 39#include <ostream> 40 41namespace std _GLIBCXX_VISIBILITY(default) 42{ 43_GLIBCXX_BEGIN_NAMESPACE_VERSION 44_GLIBCXX_BEGIN_NAMESPACE_CXX11 45 46 // [27.7.1] template class basic_stringbuf 47 /** 48 * @brief The actual work of input and output (for std::string). 49 * @ingroup io 50 * 51 * @tparam _CharT Type of character stream. 52 * @tparam _Traits Traits for character type, defaults to 53 * char_traits<_CharT>. 54 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 55 * 56 * This class associates either or both of its input and output sequences 57 * with a sequence of characters, which can be initialized from, or made 58 * available as, a @c std::basic_string. (Paraphrased from [27.7.1]/1.) 59 * 60 * For this class, open modes (of type @c ios_base::openmode) have 61 * @c in set if the input sequence can be read, and @c out set if the 62 * output sequence can be written. 63 */ 64 template<typename _CharT, typename _Traits, typename _Alloc> 65 class basic_stringbuf : public basic_streambuf<_CharT, _Traits> 66 { 67 struct __xfer_bufptrs; 68 public: 69 // Types: 70 typedef _CharT char_type; 71 typedef _Traits traits_type; 72 // _GLIBCXX_RESOLVE_LIB_DEFECTS 73 // 251. basic_stringbuf missing allocator_type 74 typedef _Alloc allocator_type; 75 typedef typename traits_type::int_type int_type; 76 typedef typename traits_type::pos_type pos_type; 77 typedef typename traits_type::off_type off_type; 78 79 typedef basic_streambuf<char_type, traits_type> __streambuf_type; 80 typedef basic_string<char_type, _Traits, _Alloc> __string_type; 81 typedef typename __string_type::size_type __size_type; 82 83 protected: 84 /// Place to stash in || out || in | out settings for current stringbuf. 85 ios_base::openmode _M_mode; 86 87 // Data Members: 88 __string_type _M_string; 89 90 public: 91 // Constructors: 92 93 /** 94 * @brief Starts with an empty string buffer. 95 * 96 * The default constructor initializes the parent class using its 97 * own default ctor. 98 */ 99 basic_stringbuf() 100 : __streambuf_type(), _M_mode(ios_base::in | ios_base::out), _M_string() 101 { } 102 103 /** 104 * @brief Starts with an empty string buffer. 105 * @param __mode Whether the buffer can read, or write, or both. 106 * 107 * The default constructor initializes the parent class using its 108 * own default ctor. 109 */ 110 explicit 111 basic_stringbuf(ios_base::openmode __mode) 112 : __streambuf_type(), _M_mode(__mode), _M_string() 113 { } 114 115 /** 116 * @brief Starts with an existing string buffer. 117 * @param __str A string to copy as a starting buffer. 118 * @param __mode Whether the buffer can read, or write, or both. 119 * 120 * This constructor initializes the parent class using its 121 * own default ctor. 122 */ 123 explicit 124 basic_stringbuf(const __string_type& __str, 125 ios_base::openmode __mode = ios_base::in | ios_base::out) 126 : __streambuf_type(), _M_mode(), 127 _M_string(__str.data(), __str.size(), __str.get_allocator()) 128 { _M_stringbuf_init(__mode); } 129 130#if __cplusplus >= 201103L 131 basic_stringbuf(const basic_stringbuf&) = delete; 132 133 basic_stringbuf(basic_stringbuf&& __rhs) 134 : basic_stringbuf(std::move(__rhs), __xfer_bufptrs(__rhs, this)) 135 { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); } 136 137 // 27.8.2.2 Assign and swap: 138 139 basic_stringbuf& 140 operator=(const basic_stringbuf&) = delete; 141 142 basic_stringbuf& 143 operator=(basic_stringbuf&& __rhs) 144 { 145 __xfer_bufptrs __st{__rhs, this}; 146 const __streambuf_type& __base = __rhs; 147 __streambuf_type::operator=(__base); 148 this->pubimbue(__rhs.getloc()); 149 _M_mode = __rhs._M_mode; 150 _M_string = std::move(__rhs._M_string); 151 __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); 152 return *this; 153 } 154 155 void 156 swap(basic_stringbuf& __rhs) 157 { 158 __xfer_bufptrs __l_st{*this, std::__addressof(__rhs)}; 159 __xfer_bufptrs __r_st{__rhs, this}; 160 __streambuf_type& __base = __rhs; 161 __streambuf_type::swap(__base); 162 __rhs.pubimbue(this->pubimbue(__rhs.getloc())); 163 std::swap(_M_mode, __rhs._M_mode); 164 std::swap(_M_string, __rhs._M_string); 165 } 166#endif 167 168 // Get and set: 169 /** 170 * @brief Copying out the string buffer. 171 * @return A copy of one of the underlying sequences. 172 * 173 * <em>If the buffer is only created in input mode, the underlying 174 * character sequence is equal to the input sequence; otherwise, it 175 * is equal to the output sequence.</em> [27.7.1.2]/1 176 */ 177 __string_type 178 str() const 179 { 180 __string_type __ret(_M_string.get_allocator()); 181 if (this->pptr()) 182 { 183 // The current egptr() may not be the actual string end. 184 if (this->pptr() > this->egptr()) 185 __ret.assign(this->pbase(), this->pptr()); 186 else 187 __ret.assign(this->pbase(), this->egptr()); 188 } 189 else 190 __ret = _M_string; 191 return __ret; 192 } 193 194 /** 195 * @brief Setting a new buffer. 196 * @param __s The string to use as a new sequence. 197 * 198 * Deallocates any previous stored sequence, then copies @a s to 199 * use as a new one. 200 */ 201 void 202 str(const __string_type& __s) 203 { 204 // Cannot use _M_string = __s, since v3 strings are COW 205 // (not always true now but assign() always works). 206 _M_string.assign(__s.data(), __s.size()); 207 _M_stringbuf_init(_M_mode); 208 } 209 210 protected: 211 // Common initialization code goes here. 212 void 213 _M_stringbuf_init(ios_base::openmode __mode) 214 { 215 _M_mode = __mode; 216 __size_type __len = 0; 217 if (_M_mode & (ios_base::ate | ios_base::app)) 218 __len = _M_string.size(); 219 _M_sync(const_cast<char_type*>(_M_string.data()), 0, __len); 220 } 221 222 virtual streamsize 223 showmanyc() 224 { 225 streamsize __ret = -1; 226 if (_M_mode & ios_base::in) 227 { 228 _M_update_egptr(); 229 __ret = this->egptr() - this->gptr(); 230 } 231 return __ret; 232 } 233 234 virtual int_type 235 underflow(); 236 237 virtual int_type 238 pbackfail(int_type __c = traits_type::eof()); 239 240 virtual int_type 241 overflow(int_type __c = traits_type::eof()); 242 243 /** 244 * @brief Manipulates the buffer. 245 * @param __s Pointer to a buffer area. 246 * @param __n Size of @a __s. 247 * @return @c this 248 * 249 * If no buffer has already been created, and both @a __s and @a __n are 250 * non-zero, then @c __s is used as a buffer; see 251 * https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html#io.streambuf.buffering 252 * for more. 253 */ 254 virtual __streambuf_type* 255 setbuf(char_type* __s, streamsize __n) 256 { 257 if (__s && __n >= 0) 258 { 259 // This is implementation-defined behavior, and assumes 260 // that an external char_type array of length __n exists 261 // and has been pre-allocated. If this is not the case, 262 // things will quickly blow up. 263 264 // Step 1: Destroy the current internal array. 265 _M_string.clear(); 266 267 // Step 2: Use the external array. 268 _M_sync(__s, __n, 0); 269 } 270 return this; 271 } 272 273 virtual pos_type 274 seekoff(off_type __off, ios_base::seekdir __way, 275 ios_base::openmode __mode = ios_base::in | ios_base::out); 276 277 virtual pos_type 278 seekpos(pos_type __sp, 279 ios_base::openmode __mode = ios_base::in | ios_base::out); 280 281 // Internal function for correctly updating the internal buffer 282 // for a particular _M_string, due to initialization or re-sizing 283 // of an existing _M_string. 284 void 285 _M_sync(char_type* __base, __size_type __i, __size_type __o); 286 287 // Internal function for correctly updating egptr() to the actual 288 // string end. 289 void 290 _M_update_egptr() 291 { 292 const bool __testin = _M_mode & ios_base::in; 293 if (this->pptr() && this->pptr() > this->egptr()) 294 { 295 if (__testin) 296 this->setg(this->eback(), this->gptr(), this->pptr()); 297 else 298 this->setg(this->pptr(), this->pptr(), this->pptr()); 299 } 300 } 301 302 // Works around the issue with pbump, part of the protected 303 // interface of basic_streambuf, taking just an int. 304 void 305 _M_pbump(char_type* __pbeg, char_type* __pend, off_type __off); 306 307 private: 308#if __cplusplus >= 201103L 309#if _GLIBCXX_USE_CXX11_ABI 310 // This type captures the state of the gptr / pptr pointers as offsets 311 // so they can be restored in another object after moving the string. 312 struct __xfer_bufptrs 313 { 314 __xfer_bufptrs(const basic_stringbuf& __from, basic_stringbuf* __to) 315 : _M_to{__to}, _M_goff{-1, -1, -1}, _M_poff{-1, -1, -1} 316 { 317 const _CharT* const __str = __from._M_string.data(); 318 const _CharT* __end = nullptr; 319 if (__from.eback()) 320 { 321 _M_goff[0] = __from.eback() - __str; 322 _M_goff[1] = __from.gptr() - __str; 323 _M_goff[2] = __from.egptr() - __str; 324 __end = __from.egptr(); 325 } 326 if (__from.pbase()) 327 { 328 _M_poff[0] = __from.pbase() - __str; 329 _M_poff[1] = __from.pptr() - __from.pbase(); 330 _M_poff[2] = __from.epptr() - __str; 331 if (__from.pptr() > __end) 332 __end = __from.pptr(); 333 } 334 335 // Set _M_string length to the greater of the get and put areas. 336 if (__end) 337 { 338 // The const_cast avoids changing this constructor's signature, 339 // because it is exported from the dynamic library. 340 auto& __mut_from = const_cast<basic_stringbuf&>(__from); 341 __mut_from._M_string._M_length(__end - __str); 342 } 343 } 344 345 ~__xfer_bufptrs() 346 { 347 char_type* __str = const_cast<char_type*>(_M_to->_M_string.data()); 348 if (_M_goff[0] != -1) 349 _M_to->setg(__str+_M_goff[0], __str+_M_goff[1], __str+_M_goff[2]); 350 if (_M_poff[0] != -1) 351 _M_to->_M_pbump(__str+_M_poff[0], __str+_M_poff[2], _M_poff[1]); 352 } 353 354 basic_stringbuf* _M_to; 355 off_type _M_goff[3]; 356 off_type _M_poff[3]; 357 }; 358#else 359 // This type does nothing when using Copy-On-Write strings. 360 struct __xfer_bufptrs 361 { 362 __xfer_bufptrs(const basic_stringbuf&, basic_stringbuf*) { } 363 }; 364#endif 365 366 // The move constructor initializes an __xfer_bufptrs temporary then 367 // delegates to this constructor to performs moves during its lifetime. 368 basic_stringbuf(basic_stringbuf&& __rhs, __xfer_bufptrs&&) 369 : __streambuf_type(static_cast<const __streambuf_type&>(__rhs)), 370 _M_mode(__rhs._M_mode), _M_string(std::move(__rhs._M_string)) 371 { } 372#endif 373 }; 374 375 376 // [27.7.2] Template class basic_istringstream 377 /** 378 * @brief Controlling input for std::string. 379 * @ingroup io 380 * 381 * @tparam _CharT Type of character stream. 382 * @tparam _Traits Traits for character type, defaults to 383 * char_traits<_CharT>. 384 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 385 * 386 * This class supports reading from objects of type std::basic_string, 387 * using the inherited functions from std::basic_istream. To control 388 * the associated sequence, an instance of std::basic_stringbuf is used, 389 * which this page refers to as @c sb. 390 */ 391 template<typename _CharT, typename _Traits, typename _Alloc> 392 class basic_istringstream : public basic_istream<_CharT, _Traits> 393 { 394 public: 395 // Types: 396 typedef _CharT char_type; 397 typedef _Traits traits_type; 398 // _GLIBCXX_RESOLVE_LIB_DEFECTS 399 // 251. basic_stringbuf missing allocator_type 400 typedef _Alloc allocator_type; 401 typedef typename traits_type::int_type int_type; 402 typedef typename traits_type::pos_type pos_type; 403 typedef typename traits_type::off_type off_type; 404 405 // Non-standard types: 406 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 407 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type; 408 typedef basic_istream<char_type, traits_type> __istream_type; 409 410 private: 411 __stringbuf_type _M_stringbuf; 412 413 public: 414 // Constructors: 415 416 /** 417 * @brief Default constructor starts with an empty string buffer. 418 * 419 * Initializes @c sb using @c in, and passes @c &sb to the base 420 * class initializer. Does not allocate any buffer. 421 * 422 * That's a lie. We initialize the base class with NULL, because the 423 * string class does its own memory management. 424 */ 425 basic_istringstream() 426 : __istream_type(), _M_stringbuf(ios_base::in) 427 { this->init(&_M_stringbuf); } 428 429 /** 430 * @brief Starts with an empty string buffer. 431 * @param __mode Whether the buffer can read, or write, or both. 432 * 433 * @c ios_base::in is automatically included in @a __mode. 434 * 435 * Initializes @c sb using @c __mode|in, and passes @c &sb to the base 436 * class initializer. Does not allocate any buffer. 437 * 438 * That's a lie. We initialize the base class with NULL, because the 439 * string class does its own memory management. 440 */ 441 explicit 442 basic_istringstream(ios_base::openmode __mode) 443 : __istream_type(), _M_stringbuf(__mode | ios_base::in) 444 { this->init(&_M_stringbuf); } 445 446 /** 447 * @brief Starts with an existing string buffer. 448 * @param __str A string to copy as a starting buffer. 449 * @param __mode Whether the buffer can read, or write, or both. 450 * 451 * @c ios_base::in is automatically included in @a mode. 452 * 453 * Initializes @c sb using @a str and @c mode|in, and passes @c &sb 454 * to the base class initializer. 455 * 456 * That's a lie. We initialize the base class with NULL, because the 457 * string class does its own memory management. 458 */ 459 explicit 460 basic_istringstream(const __string_type& __str, 461 ios_base::openmode __mode = ios_base::in) 462 : __istream_type(), _M_stringbuf(__str, __mode | ios_base::in) 463 { this->init(&_M_stringbuf); } 464 465 /** 466 * @brief The destructor does nothing. 467 * 468 * The buffer is deallocated by the stringbuf object, not the 469 * formatting stream. 470 */ 471 ~basic_istringstream() 472 { } 473 474#if __cplusplus >= 201103L 475 basic_istringstream(const basic_istringstream&) = delete; 476 477 basic_istringstream(basic_istringstream&& __rhs) 478 : __istream_type(std::move(__rhs)), 479 _M_stringbuf(std::move(__rhs._M_stringbuf)) 480 { __istream_type::set_rdbuf(&_M_stringbuf); } 481 482 // 27.8.3.2 Assign and swap: 483 484 basic_istringstream& 485 operator=(const basic_istringstream&) = delete; 486 487 basic_istringstream& 488 operator=(basic_istringstream&& __rhs) 489 { 490 __istream_type::operator=(std::move(__rhs)); 491 _M_stringbuf = std::move(__rhs._M_stringbuf); 492 return *this; 493 } 494 495 void 496 swap(basic_istringstream& __rhs) 497 { 498 __istream_type::swap(__rhs); 499 _M_stringbuf.swap(__rhs._M_stringbuf); 500 } 501#endif 502 503 // Members: 504 /** 505 * @brief Accessing the underlying buffer. 506 * @return The current basic_stringbuf buffer. 507 * 508 * This hides both signatures of std::basic_ios::rdbuf(). 509 */ 510 __stringbuf_type* 511 rdbuf() const 512 { return const_cast<__stringbuf_type*>(&_M_stringbuf); } 513 514 /** 515 * @brief Copying out the string buffer. 516 * @return @c rdbuf()->str() 517 */ 518 __string_type 519 str() const 520 { return _M_stringbuf.str(); } 521 522 /** 523 * @brief Setting a new buffer. 524 * @param __s The string to use as a new sequence. 525 * 526 * Calls @c rdbuf()->str(s). 527 */ 528 void 529 str(const __string_type& __s) 530 { _M_stringbuf.str(__s); } 531 }; 532 533 534 // [27.7.3] Template class basic_ostringstream 535 /** 536 * @brief Controlling output for std::string. 537 * @ingroup io 538 * 539 * @tparam _CharT Type of character stream. 540 * @tparam _Traits Traits for character type, defaults to 541 * char_traits<_CharT>. 542 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 543 * 544 * This class supports writing to objects of type std::basic_string, 545 * using the inherited functions from std::basic_ostream. To control 546 * the associated sequence, an instance of std::basic_stringbuf is used, 547 * which this page refers to as @c sb. 548 */ 549 template <typename _CharT, typename _Traits, typename _Alloc> 550 class basic_ostringstream : public basic_ostream<_CharT, _Traits> 551 { 552 public: 553 // Types: 554 typedef _CharT char_type; 555 typedef _Traits traits_type; 556 // _GLIBCXX_RESOLVE_LIB_DEFECTS 557 // 251. basic_stringbuf missing allocator_type 558 typedef _Alloc allocator_type; 559 typedef typename traits_type::int_type int_type; 560 typedef typename traits_type::pos_type pos_type; 561 typedef typename traits_type::off_type off_type; 562 563 // Non-standard types: 564 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 565 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type; 566 typedef basic_ostream<char_type, traits_type> __ostream_type; 567 568 private: 569 __stringbuf_type _M_stringbuf; 570 571 public: 572 // Constructors/destructor: 573 574 /** 575 * @brief Default constructor starts with an empty string buffer. 576 * 577 * Initializes @c sb using @c mode|out, and passes @c &sb to the base 578 * class initializer. Does not allocate any buffer. 579 * 580 * That's a lie. We initialize the base class with NULL, because the 581 * string class does its own memory management. 582 */ 583 basic_ostringstream() 584 : __ostream_type(), _M_stringbuf(ios_base::out) 585 { this->init(&_M_stringbuf); } 586 587 /** 588 * @brief Starts with an empty string buffer. 589 * @param __mode Whether the buffer can read, or write, or both. 590 * 591 * @c ios_base::out is automatically included in @a mode. 592 * 593 * Initializes @c sb using @c mode|out, and passes @c &sb to the base 594 * class initializer. Does not allocate any buffer. 595 * 596 * That's a lie. We initialize the base class with NULL, because the 597 * string class does its own memory management. 598 */ 599 explicit 600 basic_ostringstream(ios_base::openmode __mode) 601 : __ostream_type(), _M_stringbuf(__mode | ios_base::out) 602 { this->init(&_M_stringbuf); } 603 604 /** 605 * @brief Starts with an existing string buffer. 606 * @param __str A string to copy as a starting buffer. 607 * @param __mode Whether the buffer can read, or write, or both. 608 * 609 * @c ios_base::out is automatically included in @a mode. 610 * 611 * Initializes @c sb using @a str and @c mode|out, and passes @c &sb 612 * to the base class initializer. 613 * 614 * That's a lie. We initialize the base class with NULL, because the 615 * string class does its own memory management. 616 */ 617 explicit 618 basic_ostringstream(const __string_type& __str, 619 ios_base::openmode __mode = ios_base::out) 620 : __ostream_type(), _M_stringbuf(__str, __mode | ios_base::out) 621 { this->init(&_M_stringbuf); } 622 623 /** 624 * @brief The destructor does nothing. 625 * 626 * The buffer is deallocated by the stringbuf object, not the 627 * formatting stream. 628 */ 629 ~basic_ostringstream() 630 { } 631 632#if __cplusplus >= 201103L 633 basic_ostringstream(const basic_ostringstream&) = delete; 634 635 basic_ostringstream(basic_ostringstream&& __rhs) 636 : __ostream_type(std::move(__rhs)), 637 _M_stringbuf(std::move(__rhs._M_stringbuf)) 638 { __ostream_type::set_rdbuf(&_M_stringbuf); } 639 640 // 27.8.3.2 Assign and swap: 641 642 basic_ostringstream& 643 operator=(const basic_ostringstream&) = delete; 644 645 basic_ostringstream& 646 operator=(basic_ostringstream&& __rhs) 647 { 648 __ostream_type::operator=(std::move(__rhs)); 649 _M_stringbuf = std::move(__rhs._M_stringbuf); 650 return *this; 651 } 652 653 void 654 swap(basic_ostringstream& __rhs) 655 { 656 __ostream_type::swap(__rhs); 657 _M_stringbuf.swap(__rhs._M_stringbuf); 658 } 659#endif 660 661 // Members: 662 /** 663 * @brief Accessing the underlying buffer. 664 * @return The current basic_stringbuf buffer. 665 * 666 * This hides both signatures of std::basic_ios::rdbuf(). 667 */ 668 __stringbuf_type* 669 rdbuf() const 670 { return const_cast<__stringbuf_type*>(&_M_stringbuf); } 671 672 /** 673 * @brief Copying out the string buffer. 674 * @return @c rdbuf()->str() 675 */ 676 __string_type 677 str() const 678 { return _M_stringbuf.str(); } 679 680 /** 681 * @brief Setting a new buffer. 682 * @param __s The string to use as a new sequence. 683 * 684 * Calls @c rdbuf()->str(s). 685 */ 686 void 687 str(const __string_type& __s) 688 { _M_stringbuf.str(__s); } 689 }; 690 691 692 // [27.7.4] Template class basic_stringstream 693 /** 694 * @brief Controlling input and output for std::string. 695 * @ingroup io 696 * 697 * @tparam _CharT Type of character stream. 698 * @tparam _Traits Traits for character type, defaults to 699 * char_traits<_CharT>. 700 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 701 * 702 * This class supports reading from and writing to objects of type 703 * std::basic_string, using the inherited functions from 704 * std::basic_iostream. To control the associated sequence, an instance 705 * of std::basic_stringbuf is used, which this page refers to as @c sb. 706 */ 707 template <typename _CharT, typename _Traits, typename _Alloc> 708 class basic_stringstream : public basic_iostream<_CharT, _Traits> 709 { 710 public: 711 // Types: 712 typedef _CharT char_type; 713 typedef _Traits traits_type; 714 // _GLIBCXX_RESOLVE_LIB_DEFECTS 715 // 251. basic_stringbuf missing allocator_type 716 typedef _Alloc allocator_type; 717 typedef typename traits_type::int_type int_type; 718 typedef typename traits_type::pos_type pos_type; 719 typedef typename traits_type::off_type off_type; 720 721 // Non-standard Types: 722 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 723 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type; 724 typedef basic_iostream<char_type, traits_type> __iostream_type; 725 726 private: 727 __stringbuf_type _M_stringbuf; 728 729 public: 730 // Constructors/destructors 731 732 /** 733 * @brief Default constructor starts with an empty string buffer. 734 * 735 * Initializes @c sb using the mode @c in|out, and passes @c &sb 736 * to the base class initializer. Does not allocate any buffer. 737 * 738 * That's a lie. We initialize the base class with NULL, because the 739 * string class does its own memory management. 740 */ 741 basic_stringstream() 742 : __iostream_type(), _M_stringbuf(ios_base::out | ios_base::in) 743 { this->init(&_M_stringbuf); } 744 745 /** 746 * @brief Starts with an empty string buffer. 747 * @param __m Whether the buffer can read, or write, or both. 748 * 749 * Initializes @c sb using the mode from @c __m, and passes @c &sb 750 * to the base class initializer. Does not allocate any buffer. 751 * 752 * That's a lie. We initialize the base class with NULL, because the 753 * string class does its own memory management. 754 */ 755 explicit 756 basic_stringstream(ios_base::openmode __m) 757 : __iostream_type(), _M_stringbuf(__m) 758 { this->init(&_M_stringbuf); } 759 760 /** 761 * @brief Starts with an existing string buffer. 762 * @param __str A string to copy as a starting buffer. 763 * @param __m Whether the buffer can read, or write, or both. 764 * 765 * Initializes @c sb using @a __str and @c __m, and passes @c &sb 766 * to the base class initializer. 767 * 768 * That's a lie. We initialize the base class with NULL, because the 769 * string class does its own memory management. 770 */ 771 explicit 772 basic_stringstream(const __string_type& __str, 773 ios_base::openmode __m = ios_base::out | ios_base::in) 774 : __iostream_type(), _M_stringbuf(__str, __m) 775 { this->init(&_M_stringbuf); } 776 777 /** 778 * @brief The destructor does nothing. 779 * 780 * The buffer is deallocated by the stringbuf object, not the 781 * formatting stream. 782 */ 783 ~basic_stringstream() 784 { } 785 786#if __cplusplus >= 201103L 787 basic_stringstream(const basic_stringstream&) = delete; 788 789 basic_stringstream(basic_stringstream&& __rhs) 790 : __iostream_type(std::move(__rhs)), 791 _M_stringbuf(std::move(__rhs._M_stringbuf)) 792 { __iostream_type::set_rdbuf(&_M_stringbuf); } 793 794 // 27.8.3.2 Assign and swap: 795 796 basic_stringstream& 797 operator=(const basic_stringstream&) = delete; 798 799 basic_stringstream& 800 operator=(basic_stringstream&& __rhs) 801 { 802 __iostream_type::operator=(std::move(__rhs)); 803 _M_stringbuf = std::move(__rhs._M_stringbuf); 804 return *this; 805 } 806 807 void 808 swap(basic_stringstream& __rhs) 809 { 810 __iostream_type::swap(__rhs); 811 _M_stringbuf.swap(__rhs._M_stringbuf); 812 } 813#endif 814 815 // Members: 816 /** 817 * @brief Accessing the underlying buffer. 818 * @return The current basic_stringbuf buffer. 819 * 820 * This hides both signatures of std::basic_ios::rdbuf(). 821 */ 822 __stringbuf_type* 823 rdbuf() const 824 { return const_cast<__stringbuf_type*>(&_M_stringbuf); } 825 826 /** 827 * @brief Copying out the string buffer. 828 * @return @c rdbuf()->str() 829 */ 830 __string_type 831 str() const 832 { return _M_stringbuf.str(); } 833 834 /** 835 * @brief Setting a new buffer. 836 * @param __s The string to use as a new sequence. 837 * 838 * Calls @c rdbuf()->str(s). 839 */ 840 void 841 str(const __string_type& __s) 842 { _M_stringbuf.str(__s); } 843 }; 844 845#if __cplusplus >= 201103L 846 /// Swap specialization for stringbufs. 847 template <class _CharT, class _Traits, class _Allocator> 848 inline void 849 swap(basic_stringbuf<_CharT, _Traits, _Allocator>& __x, 850 basic_stringbuf<_CharT, _Traits, _Allocator>& __y) 851 { __x.swap(__y); } 852 853 /// Swap specialization for istringstreams. 854 template <class _CharT, class _Traits, class _Allocator> 855 inline void 856 swap(basic_istringstream<_CharT, _Traits, _Allocator>& __x, 857 basic_istringstream<_CharT, _Traits, _Allocator>& __y) 858 { __x.swap(__y); } 859 860 /// Swap specialization for ostringstreams. 861 template <class _CharT, class _Traits, class _Allocator> 862 inline void 863 swap(basic_ostringstream<_CharT, _Traits, _Allocator>& __x, 864 basic_ostringstream<_CharT, _Traits, _Allocator>& __y) 865 { __x.swap(__y); } 866 867 /// Swap specialization for stringstreams. 868 template <class _CharT, class _Traits, class _Allocator> 869 inline void 870 swap(basic_stringstream<_CharT, _Traits, _Allocator>& __x, 871 basic_stringstream<_CharT, _Traits, _Allocator>& __y) 872 { __x.swap(__y); } 873#endif 874 875_GLIBCXX_END_NAMESPACE_CXX11 876_GLIBCXX_END_NAMESPACE_VERSION 877} // namespace 878 879#include <bits/sstream.tcc> 880 881#endif /* _GLIBCXX_SSTREAM */ 882