1// String based streams -*- C++ -*- 2 3// Copyright (C) 1997-2021 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#include <bits/alloc_traits.h> // allocator_traits, __allocator_like 41 42#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 43# define _GLIBCXX_LVAL_REF_QUAL & 44#else 45# define _GLIBCXX_LVAL_REF_QUAL 46#endif 47 48namespace std _GLIBCXX_VISIBILITY(default) 49{ 50_GLIBCXX_BEGIN_NAMESPACE_VERSION 51_GLIBCXX_BEGIN_NAMESPACE_CXX11 52 53 // [27.7.1] template class basic_stringbuf 54 /** 55 * @brief The actual work of input and output (for std::string). 56 * @ingroup io 57 * 58 * @tparam _CharT Type of character stream. 59 * @tparam _Traits Traits for character type, defaults to 60 * char_traits<_CharT>. 61 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 62 * 63 * This class associates either or both of its input and output sequences 64 * with a sequence of characters, which can be initialized from, or made 65 * available as, a @c std::basic_string. (Paraphrased from [27.7.1]/1.) 66 * 67 * For this class, open modes (of type @c ios_base::openmode) have 68 * @c in set if the input sequence can be read, and @c out set if the 69 * output sequence can be written. 70 */ 71 template<typename _CharT, typename _Traits, typename _Alloc> 72 class basic_stringbuf : public basic_streambuf<_CharT, _Traits> 73 { 74 struct __xfer_bufptrs; 75 76#if __cplusplus >= 201103L 77 using allocator_traits = std::allocator_traits<_Alloc>; 78 using _Noexcept_swap 79 = __or_<typename allocator_traits::propagate_on_container_swap, 80 typename allocator_traits::is_always_equal>; 81#endif 82 83 public: 84 // Types: 85 typedef _CharT char_type; 86 typedef _Traits traits_type; 87 // _GLIBCXX_RESOLVE_LIB_DEFECTS 88 // 251. basic_stringbuf missing allocator_type 89 typedef _Alloc allocator_type; 90 typedef typename traits_type::int_type int_type; 91 typedef typename traits_type::pos_type pos_type; 92 typedef typename traits_type::off_type off_type; 93 94 typedef basic_streambuf<char_type, traits_type> __streambuf_type; 95 typedef basic_string<char_type, _Traits, _Alloc> __string_type; 96 typedef typename __string_type::size_type __size_type; 97 98 protected: 99 /// Place to stash in || out || in | out settings for current stringbuf. 100 ios_base::openmode _M_mode; 101 102 // Data Members: 103 __string_type _M_string; 104 105 public: 106 // Constructors: 107 108 /** 109 * @brief Starts with an empty string buffer. 110 * 111 * The default constructor initializes the parent class using its 112 * own default ctor. 113 */ 114 basic_stringbuf() 115 : __streambuf_type(), _M_mode(ios_base::in | ios_base::out), _M_string() 116 { } 117 118 /** 119 * @brief Starts with an empty string buffer. 120 * @param __mode Whether the buffer can read, or write, or both. 121 * 122 * The default constructor initializes the parent class using its 123 * own default ctor. 124 */ 125 explicit 126 basic_stringbuf(ios_base::openmode __mode) 127 : __streambuf_type(), _M_mode(__mode), _M_string() 128 { } 129 130 /** 131 * @brief Starts with an existing string buffer. 132 * @param __str A string to copy as a starting buffer. 133 * @param __mode Whether the buffer can read, or write, or both. 134 * 135 * This constructor initializes the parent class using its 136 * own default ctor. 137 */ 138 explicit 139 basic_stringbuf(const __string_type& __str, 140 ios_base::openmode __mode = ios_base::in | ios_base::out) 141 : __streambuf_type(), _M_mode(), 142 _M_string(__str.data(), __str.size(), __str.get_allocator()) 143 { _M_stringbuf_init(__mode); } 144 145#if __cplusplus >= 201103L 146 basic_stringbuf(const basic_stringbuf&) = delete; 147 148 basic_stringbuf(basic_stringbuf&& __rhs) 149 : basic_stringbuf(std::move(__rhs), __xfer_bufptrs(__rhs, this)) 150 { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); } 151 152#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 153 explicit 154 basic_stringbuf(const allocator_type& __a) 155 : basic_stringbuf(ios_base::in | std::ios_base::out, __a) 156 { } 157 158 basic_stringbuf(ios_base::openmode __mode, 159 const allocator_type& __a) 160 : __streambuf_type(), _M_mode(__mode), _M_string(__a) 161 { } 162 163 explicit 164 basic_stringbuf(__string_type&& __s, 165 ios_base::openmode __mode = ios_base::in 166 | ios_base::out) 167 : __streambuf_type(), _M_mode(__mode), _M_string(std::move(__s)) 168 { _M_stringbuf_init(__mode); } 169 170 template<typename _SAlloc> 171 basic_stringbuf(const basic_string<_CharT, _Traits, _SAlloc>& __s, 172 const allocator_type& __a) 173 : basic_stringbuf(__s, ios_base::in | std::ios_base::out, __a) 174 { } 175 176 template<typename _SAlloc> 177 basic_stringbuf(const basic_string<_CharT, _Traits, _SAlloc>& __s, 178 ios_base::openmode __mode, 179 const allocator_type& __a) 180 : __streambuf_type(), _M_mode(__mode), 181 _M_string(__s.data(), __s.size(), __a) 182 { _M_stringbuf_init(__mode); } 183 184 template<typename _SAlloc> 185 explicit 186 basic_stringbuf(const basic_string<_CharT, _Traits, _SAlloc>& __s, 187 ios_base::openmode __mode = ios_base::in 188 | ios_base::out) 189 : basic_stringbuf(__s, __mode, allocator_type{}) 190 { } 191 192 basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& __a) 193 : basic_stringbuf(std::move(__rhs), __a, __xfer_bufptrs(__rhs, this)) 194 { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); } 195 196 allocator_type get_allocator() const noexcept 197 { return _M_string.get_allocator(); } 198#endif // C++20 199 200 // 27.8.2.2 Assign and swap: 201 202 basic_stringbuf& 203 operator=(const basic_stringbuf&) = delete; 204 205 basic_stringbuf& 206 operator=(basic_stringbuf&& __rhs) 207 { 208 __xfer_bufptrs __st{__rhs, this}; 209 const __streambuf_type& __base = __rhs; 210 __streambuf_type::operator=(__base); 211 this->pubimbue(__rhs.getloc()); 212 _M_mode = __rhs._M_mode; 213 _M_string = std::move(__rhs._M_string); 214 __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); 215 return *this; 216 } 217 218 void 219 swap(basic_stringbuf& __rhs) noexcept(_Noexcept_swap::value) 220 { 221 __xfer_bufptrs __l_st{*this, std::__addressof(__rhs)}; 222 __xfer_bufptrs __r_st{__rhs, this}; 223 __streambuf_type& __base = __rhs; 224 __streambuf_type::swap(__base); 225 __rhs.pubimbue(this->pubimbue(__rhs.getloc())); 226 std::swap(_M_mode, __rhs._M_mode); 227 std::swap(_M_string, __rhs._M_string); // XXX not exception safe 228 } 229#endif // C++11 230 231 // Getters and setters: 232 233 /** 234 * @brief Copying out the string buffer. 235 * @return A copy of one of the underlying sequences. 236 * 237 * <em>If the buffer is only created in input mode, the underlying 238 * character sequence is equal to the input sequence; otherwise, it 239 * is equal to the output sequence.</em> [27.7.1.2]/1 240 */ 241 __string_type 242 str() const _GLIBCXX_LVAL_REF_QUAL 243 { 244 __string_type __ret(_M_string.get_allocator()); 245 if (char_type* __hi = _M_high_mark()) 246 __ret.assign(this->pbase(), __hi); 247 else 248 __ret = _M_string; 249 return __ret; 250 } 251 252#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 253#if __cpp_concepts 254 template<__allocator_like _SAlloc> 255 basic_string<_CharT, _Traits, _SAlloc> 256 str(const _SAlloc& __sa) const 257 { 258 auto __sv = view(); 259 return { __sv.data(), __sv.size(), __sa }; 260 } 261#endif 262 263 __string_type 264 str() && 265 { 266 if (char_type* __hi = _M_high_mark()) 267 { 268 // Set length to end of character sequence and add null terminator. 269 _M_string._M_set_length(_M_high_mark() - this->pbase()); 270 } 271 auto __str = std::move(_M_string); 272 _M_string.clear(); 273 _M_sync(_M_string.data(), 0, 0); 274 return __str; 275 } 276 277 basic_string_view<char_type, traits_type> 278 view() const noexcept 279 { 280 if (char_type* __hi = _M_high_mark()) 281 return { this->pbase(), __hi }; 282 else 283 return _M_string; 284 } 285#endif // C++20 286 287 /** 288 * @brief Setting a new buffer. 289 * @param __s The string to use as a new sequence. 290 * 291 * Deallocates any previous stored sequence, then copies @a s to 292 * use as a new one. 293 */ 294 void 295 str(const __string_type& __s) 296 { 297 // Cannot use _M_string = __s, since v3 strings are COW 298 // (not always true now but assign() always works). 299 _M_string.assign(__s.data(), __s.size()); 300 _M_stringbuf_init(_M_mode); 301 } 302 303#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 304#if __cpp_concepts 305 template<__allocator_like _SAlloc> 306 requires (!is_same_v<_SAlloc, _Alloc>) 307 void 308 str(const basic_string<_CharT, _Traits, _SAlloc>& __s) 309 { 310 _M_string.assign(__s.data(), __s.size()); 311 _M_stringbuf_init(_M_mode); 312 } 313#endif 314 315 void 316 str(__string_type&& __s) 317 { 318 _M_string = std::move(__s); 319 _M_stringbuf_init(_M_mode); 320 } 321#endif 322 323 protected: 324 // Common initialization code goes here. 325 void 326 _M_stringbuf_init(ios_base::openmode __mode) 327 { 328 _M_mode = __mode; 329 __size_type __len = 0; 330 if (_M_mode & (ios_base::ate | ios_base::app)) 331 __len = _M_string.size(); 332 _M_sync(const_cast<char_type*>(_M_string.data()), 0, __len); 333 } 334 335 virtual streamsize 336 showmanyc() 337 { 338 streamsize __ret = -1; 339 if (_M_mode & ios_base::in) 340 { 341 _M_update_egptr(); 342 __ret = this->egptr() - this->gptr(); 343 } 344 return __ret; 345 } 346 347 virtual int_type 348 underflow(); 349 350 virtual int_type 351 pbackfail(int_type __c = traits_type::eof()); 352 353 virtual int_type 354 overflow(int_type __c = traits_type::eof()); 355 356 /** 357 * @brief Manipulates the buffer. 358 * @param __s Pointer to a buffer area. 359 * @param __n Size of @a __s. 360 * @return @c this 361 * 362 * If no buffer has already been created, and both @a __s and @a __n are 363 * non-zero, then @c __s is used as a buffer; see 364 * https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html#io.streambuf.buffering 365 * for more. 366 */ 367 virtual __streambuf_type* 368 setbuf(char_type* __s, streamsize __n) 369 { 370 if (__s && __n >= 0) 371 { 372 // This is implementation-defined behavior, and assumes 373 // that an external char_type array of length __n exists 374 // and has been pre-allocated. If this is not the case, 375 // things will quickly blow up. 376 377 // Step 1: Destroy the current internal array. 378 _M_string.clear(); 379 380 // Step 2: Use the external array. 381 _M_sync(__s, __n, 0); 382 } 383 return this; 384 } 385 386 virtual pos_type 387 seekoff(off_type __off, ios_base::seekdir __way, 388 ios_base::openmode __mode = ios_base::in | ios_base::out); 389 390 virtual pos_type 391 seekpos(pos_type __sp, 392 ios_base::openmode __mode = ios_base::in | ios_base::out); 393 394 // Internal function for correctly updating the internal buffer 395 // for a particular _M_string, due to initialization or re-sizing 396 // of an existing _M_string. 397 void 398 _M_sync(char_type* __base, __size_type __i, __size_type __o); 399 400 // Internal function for correctly updating egptr() to the actual 401 // string end. 402 void 403 _M_update_egptr() 404 { 405 if (char_type* __pptr = this->pptr()) 406 { 407 char_type* __egptr = this->egptr(); 408 if (!__egptr || __pptr > __egptr) 409 { 410 if (_M_mode & ios_base::in) 411 this->setg(this->eback(), this->gptr(), __pptr); 412 else 413 this->setg(__pptr, __pptr, __pptr); 414 } 415 } 416 } 417 418 // Works around the issue with pbump, part of the protected 419 // interface of basic_streambuf, taking just an int. 420 void 421 _M_pbump(char_type* __pbeg, char_type* __pend, off_type __off); 422 423 private: 424 // Return a pointer to the end of the underlying character sequence. 425 // This might not be the same character as _M_string.end() because 426 // basic_stringbuf::overflow might have written to unused capacity 427 // in _M_string without updating its length. 428 char_type* 429 _M_high_mark() const _GLIBCXX_NOEXCEPT 430 { 431 if (char_type* __pptr = this->pptr()) 432 { 433 char_type* __egptr = this->egptr(); 434 if (!__egptr || __pptr > __egptr) 435 return __pptr; // Underlying sequence is [pbase, pptr). 436 else 437 return __egptr; // Underlying sequence is [pbase, egptr). 438 } 439 return 0; // Underlying character sequence is just _M_string. 440 } 441 442#if __cplusplus >= 201103L 443#if _GLIBCXX_USE_CXX11_ABI 444 // This type captures the state of the gptr / pptr pointers as offsets 445 // so they can be restored in another object after moving the string. 446 struct __xfer_bufptrs 447 { 448 __xfer_bufptrs(const basic_stringbuf& __from, basic_stringbuf* __to) 449 : _M_to{__to}, _M_goff{-1, -1, -1}, _M_poff{-1, -1, -1} 450 { 451 const _CharT* const __str = __from._M_string.data(); 452 const _CharT* __end = nullptr; 453 if (__from.eback()) 454 { 455 _M_goff[0] = __from.eback() - __str; 456 _M_goff[1] = __from.gptr() - __str; 457 _M_goff[2] = __from.egptr() - __str; 458 __end = __from.egptr(); 459 } 460 if (__from.pbase()) 461 { 462 _M_poff[0] = __from.pbase() - __str; 463 _M_poff[1] = __from.pptr() - __from.pbase(); 464 _M_poff[2] = __from.epptr() - __str; 465 if (!__end || __from.pptr() > __end) 466 __end = __from.pptr(); 467 } 468 469 // Set _M_string length to the greater of the get and put areas. 470 if (__end) 471 { 472 // The const_cast avoids changing this constructor's signature, 473 // because it is exported from the dynamic library. 474 auto& __mut_from = const_cast<basic_stringbuf&>(__from); 475 __mut_from._M_string._M_length(__end - __str); 476 } 477 } 478 479 ~__xfer_bufptrs() 480 { 481 char_type* __str = const_cast<char_type*>(_M_to->_M_string.data()); 482 if (_M_goff[0] != -1) 483 _M_to->setg(__str+_M_goff[0], __str+_M_goff[1], __str+_M_goff[2]); 484 if (_M_poff[0] != -1) 485 _M_to->_M_pbump(__str+_M_poff[0], __str+_M_poff[2], _M_poff[1]); 486 } 487 488 basic_stringbuf* _M_to; 489 off_type _M_goff[3]; 490 off_type _M_poff[3]; 491 }; 492#else 493 // This type does nothing when using Copy-On-Write strings. 494 struct __xfer_bufptrs 495 { 496 __xfer_bufptrs(const basic_stringbuf&, basic_stringbuf*) { } 497 }; 498#endif 499 500 // The move constructor initializes an __xfer_bufptrs temporary then 501 // delegates to this constructor to performs moves during its lifetime. 502 basic_stringbuf(basic_stringbuf&& __rhs, __xfer_bufptrs&&) 503 : __streambuf_type(static_cast<const __streambuf_type&>(__rhs)), 504 _M_mode(__rhs._M_mode), _M_string(std::move(__rhs._M_string)) 505 { } 506 507#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 508 // The move constructor initializes an __xfer_bufptrs temporary then 509 // delegates to this constructor to performs moves during its lifetime. 510 basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& __a, 511 __xfer_bufptrs&&) 512 : __streambuf_type(static_cast<const __streambuf_type&>(__rhs)), 513 _M_mode(__rhs._M_mode), _M_string(std::move(__rhs._M_string), __a) 514 { } 515#endif 516#endif // C++11 517 }; 518 519 520 // [27.7.2] Template class basic_istringstream 521 /** 522 * @brief Controlling input for std::string. 523 * @ingroup io 524 * 525 * @tparam _CharT Type of character stream. 526 * @tparam _Traits Traits for character type, defaults to 527 * char_traits<_CharT>. 528 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 529 * 530 * This class supports reading from objects of type std::basic_string, 531 * using the inherited functions from std::basic_istream. To control 532 * the associated sequence, an instance of std::basic_stringbuf is used, 533 * which this page refers to as @c sb. 534 */ 535 template<typename _CharT, typename _Traits, typename _Alloc> 536 class basic_istringstream : public basic_istream<_CharT, _Traits> 537 { 538 public: 539 // Types: 540 typedef _CharT char_type; 541 typedef _Traits traits_type; 542 // _GLIBCXX_RESOLVE_LIB_DEFECTS 543 // 251. basic_stringbuf missing allocator_type 544 typedef _Alloc allocator_type; 545 typedef typename traits_type::int_type int_type; 546 typedef typename traits_type::pos_type pos_type; 547 typedef typename traits_type::off_type off_type; 548 549 // Non-standard types: 550 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 551 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type; 552 typedef basic_istream<char_type, traits_type> __istream_type; 553 554 private: 555 __stringbuf_type _M_stringbuf; 556 557 public: 558 // Constructors: 559 560 /** 561 * @brief Default constructor starts with an empty string buffer. 562 * 563 * Initializes @c sb using @c in, and passes @c &sb to the base 564 * class initializer. Does not allocate any buffer. 565 * 566 * That's a lie. We initialize the base class with NULL, because the 567 * string class does its own memory management. 568 */ 569 basic_istringstream() 570 : __istream_type(), _M_stringbuf(ios_base::in) 571 { this->init(&_M_stringbuf); } 572 573 /** 574 * @brief Starts with an empty string buffer. 575 * @param __mode Whether the buffer can read, or write, or both. 576 * 577 * @c ios_base::in is automatically included in @a __mode. 578 * 579 * Initializes @c sb using @c __mode|in, and passes @c &sb to the base 580 * class initializer. Does not allocate any buffer. 581 * 582 * That's a lie. We initialize the base class with NULL, because the 583 * string class does its own memory management. 584 */ 585 explicit 586 basic_istringstream(ios_base::openmode __mode) 587 : __istream_type(), _M_stringbuf(__mode | ios_base::in) 588 { this->init(&_M_stringbuf); } 589 590 /** 591 * @brief Starts with an existing string buffer. 592 * @param __str A string to copy as a starting buffer. 593 * @param __mode Whether the buffer can read, or write, or both. 594 * 595 * @c ios_base::in is automatically included in @a mode. 596 * 597 * Initializes @c sb using @a str and @c mode|in, and passes @c &sb 598 * to the base class initializer. 599 * 600 * That's a lie. We initialize the base class with NULL, because the 601 * string class does its own memory management. 602 */ 603 explicit 604 basic_istringstream(const __string_type& __str, 605 ios_base::openmode __mode = ios_base::in) 606 : __istream_type(), _M_stringbuf(__str, __mode | ios_base::in) 607 { this->init(&_M_stringbuf); } 608 609 /** 610 * @brief The destructor does nothing. 611 * 612 * The buffer is deallocated by the stringbuf object, not the 613 * formatting stream. 614 */ 615 ~basic_istringstream() 616 { } 617 618#if __cplusplus >= 201103L 619 basic_istringstream(const basic_istringstream&) = delete; 620 621 basic_istringstream(basic_istringstream&& __rhs) 622 : __istream_type(std::move(__rhs)), 623 _M_stringbuf(std::move(__rhs._M_stringbuf)) 624 { __istream_type::set_rdbuf(&_M_stringbuf); } 625 626#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 627 basic_istringstream(ios_base::openmode __mode, const allocator_type& __a) 628 : __istream_type(), _M_stringbuf(__mode | ios_base::in, __a) 629 { this->init(std::__addressof(_M_stringbuf)); } 630 631 explicit 632 basic_istringstream(__string_type&& __str, 633 ios_base::openmode __mode = ios_base::in) 634 : __istream_type(), _M_stringbuf(std::move(__str), __mode | ios_base::in) 635 { this->init(std::__addressof(_M_stringbuf)); } 636 637 template<typename _SAlloc> 638 basic_istringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str, 639 const allocator_type& __a) 640 : basic_istringstream(__str, ios_base::in, __a) 641 { } 642 643 template<typename _SAlloc> 644 basic_istringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str, 645 ios_base::openmode __mode, 646 const allocator_type& __a) 647 : __istream_type(), _M_stringbuf(__str, __mode | ios_base::in, __a) 648 { this->init(std::__addressof(_M_stringbuf)); } 649 650 template<typename _SAlloc> 651 explicit 652 basic_istringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str, 653 ios_base::openmode __mode = ios_base::in) 654 : basic_istringstream(__str, __mode, allocator_type()) 655 { } 656#endif // C++20 657 658 // 27.8.3.2 Assign and swap: 659 660 basic_istringstream& 661 operator=(const basic_istringstream&) = delete; 662 663 basic_istringstream& 664 operator=(basic_istringstream&& __rhs) 665 { 666 __istream_type::operator=(std::move(__rhs)); 667 _M_stringbuf = std::move(__rhs._M_stringbuf); 668 return *this; 669 } 670 671 void 672 swap(basic_istringstream& __rhs) 673 { 674 __istream_type::swap(__rhs); 675 _M_stringbuf.swap(__rhs._M_stringbuf); 676 } 677#endif // C++11 678 679 // Members: 680 /** 681 * @brief Accessing the underlying buffer. 682 * @return The current basic_stringbuf buffer. 683 * 684 * This hides both signatures of std::basic_ios::rdbuf(). 685 */ 686 __stringbuf_type* 687 rdbuf() const 688 { return const_cast<__stringbuf_type*>(&_M_stringbuf); } 689 690 /** 691 * @brief Copying out the string buffer. 692 * @return @c rdbuf()->str() 693 */ 694 __string_type 695 str() const _GLIBCXX_LVAL_REF_QUAL 696 { return _M_stringbuf.str(); } 697 698#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 699#if __cpp_concepts 700 template<__allocator_like _SAlloc> 701 basic_string<_CharT, _Traits, _SAlloc> 702 str(const _SAlloc& __sa) const 703 { return _M_stringbuf.str(__sa); } 704#endif 705 706 __string_type 707 str() && 708 { return std::move(_M_stringbuf).str(); } 709 710 basic_string_view<char_type, traits_type> 711 view() const noexcept 712 { return _M_stringbuf.view(); } 713#endif 714 715 /** 716 * @brief Setting a new buffer. 717 * @param __s The string to use as a new sequence. 718 * 719 * Calls @c rdbuf()->str(s). 720 */ 721 void 722 str(const __string_type& __s) 723 { _M_stringbuf.str(__s); } 724 725#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 726#if __cpp_concepts 727 template<__allocator_like _SAlloc> 728 requires (!is_same_v<_SAlloc, _Alloc>) 729 void 730 str(const basic_string<_CharT, _Traits, _SAlloc>& __s) 731 { _M_stringbuf.str(__s); } 732#endif 733 734 void 735 str(__string_type&& __s) 736 { _M_stringbuf.str(std::move(__s)); } 737#endif 738 }; 739 740 741 // [27.7.3] Template class basic_ostringstream 742 /** 743 * @brief Controlling output for std::string. 744 * @ingroup io 745 * 746 * @tparam _CharT Type of character stream. 747 * @tparam _Traits Traits for character type, defaults to 748 * char_traits<_CharT>. 749 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 750 * 751 * This class supports writing to objects of type std::basic_string, 752 * using the inherited functions from std::basic_ostream. To control 753 * the associated sequence, an instance of std::basic_stringbuf is used, 754 * which this page refers to as @c sb. 755 */ 756 template <typename _CharT, typename _Traits, typename _Alloc> 757 class basic_ostringstream : public basic_ostream<_CharT, _Traits> 758 { 759 public: 760 // Types: 761 typedef _CharT char_type; 762 typedef _Traits traits_type; 763 // _GLIBCXX_RESOLVE_LIB_DEFECTS 764 // 251. basic_stringbuf missing allocator_type 765 typedef _Alloc allocator_type; 766 typedef typename traits_type::int_type int_type; 767 typedef typename traits_type::pos_type pos_type; 768 typedef typename traits_type::off_type off_type; 769 770 // Non-standard types: 771 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 772 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type; 773 typedef basic_ostream<char_type, traits_type> __ostream_type; 774 775 private: 776 __stringbuf_type _M_stringbuf; 777 778 public: 779 // Constructors/destructor: 780 781 /** 782 * @brief Default constructor starts with an empty string buffer. 783 * 784 * Initializes @c sb using @c mode|out, and passes @c &sb to the base 785 * class initializer. Does not allocate any buffer. 786 * 787 * That's a lie. We initialize the base class with NULL, because the 788 * string class does its own memory management. 789 */ 790 basic_ostringstream() 791 : __ostream_type(), _M_stringbuf(ios_base::out) 792 { this->init(&_M_stringbuf); } 793 794 /** 795 * @brief Starts with an empty string buffer. 796 * @param __mode Whether the buffer can read, or write, or both. 797 * 798 * @c ios_base::out is automatically included in @a mode. 799 * 800 * Initializes @c sb using @c mode|out, and passes @c &sb to the base 801 * class initializer. Does not allocate any buffer. 802 * 803 * That's a lie. We initialize the base class with NULL, because the 804 * string class does its own memory management. 805 */ 806 explicit 807 basic_ostringstream(ios_base::openmode __mode) 808 : __ostream_type(), _M_stringbuf(__mode | ios_base::out) 809 { this->init(&_M_stringbuf); } 810 811 /** 812 * @brief Starts with an existing string buffer. 813 * @param __str A string to copy as a starting buffer. 814 * @param __mode Whether the buffer can read, or write, or both. 815 * 816 * @c ios_base::out is automatically included in @a mode. 817 * 818 * Initializes @c sb using @a str and @c mode|out, and passes @c &sb 819 * to the base class initializer. 820 * 821 * That's a lie. We initialize the base class with NULL, because the 822 * string class does its own memory management. 823 */ 824 explicit 825 basic_ostringstream(const __string_type& __str, 826 ios_base::openmode __mode = ios_base::out) 827 : __ostream_type(), _M_stringbuf(__str, __mode | ios_base::out) 828 { this->init(&_M_stringbuf); } 829 830 /** 831 * @brief The destructor does nothing. 832 * 833 * The buffer is deallocated by the stringbuf object, not the 834 * formatting stream. 835 */ 836 ~basic_ostringstream() 837 { } 838 839#if __cplusplus >= 201103L 840 basic_ostringstream(const basic_ostringstream&) = delete; 841 842 basic_ostringstream(basic_ostringstream&& __rhs) 843 : __ostream_type(std::move(__rhs)), 844 _M_stringbuf(std::move(__rhs._M_stringbuf)) 845 { __ostream_type::set_rdbuf(&_M_stringbuf); } 846 847#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 848 basic_ostringstream(ios_base::openmode __mode, const allocator_type& __a) 849 : __ostream_type(), _M_stringbuf(__mode | ios_base::out, __a) 850 { this->init(std::__addressof(_M_stringbuf)); } 851 852 explicit 853 basic_ostringstream(__string_type&& __str, 854 ios_base::openmode __mode = ios_base::out) 855 : __ostream_type(), _M_stringbuf(std::move(__str), __mode | ios_base::out) 856 { this->init(std::__addressof(_M_stringbuf)); } 857 858 template<typename _SAlloc> 859 basic_ostringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str, 860 const allocator_type& __a) 861 : basic_ostringstream(__str, ios_base::out, __a) 862 { } 863 864 template<typename _SAlloc> 865 basic_ostringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str, 866 ios_base::openmode __mode, 867 const allocator_type& __a) 868 : __ostream_type(), _M_stringbuf(__str, __mode | ios_base::out, __a) 869 { this->init(std::__addressof(_M_stringbuf)); } 870 871 template<typename _SAlloc> 872 explicit 873 basic_ostringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str, 874 ios_base::openmode __mode = ios_base::out) 875 : basic_ostringstream(__str, __mode, allocator_type()) 876 { } 877#endif // C++20 878 879 // 27.8.3.2 Assign and swap: 880 881 basic_ostringstream& 882 operator=(const basic_ostringstream&) = delete; 883 884 basic_ostringstream& 885 operator=(basic_ostringstream&& __rhs) 886 { 887 __ostream_type::operator=(std::move(__rhs)); 888 _M_stringbuf = std::move(__rhs._M_stringbuf); 889 return *this; 890 } 891 892 void 893 swap(basic_ostringstream& __rhs) 894 { 895 __ostream_type::swap(__rhs); 896 _M_stringbuf.swap(__rhs._M_stringbuf); 897 } 898#endif // C++11 899 900 // Members: 901 /** 902 * @brief Accessing the underlying buffer. 903 * @return The current basic_stringbuf buffer. 904 * 905 * This hides both signatures of std::basic_ios::rdbuf(). 906 */ 907 __stringbuf_type* 908 rdbuf() const 909 { return const_cast<__stringbuf_type*>(&_M_stringbuf); } 910 911 /** 912 * @brief Copying out the string buffer. 913 * @return @c rdbuf()->str() 914 */ 915 __string_type 916 str() const _GLIBCXX_LVAL_REF_QUAL 917 { return _M_stringbuf.str(); } 918 919#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 920#if __cpp_concepts 921 template<__allocator_like _SAlloc> 922 basic_string<_CharT, _Traits, _SAlloc> 923 str(const _SAlloc& __sa) const 924 { return _M_stringbuf.str(__sa); } 925#endif 926 927 __string_type 928 str() && 929 { return std::move(_M_stringbuf).str(); } 930 931 basic_string_view<char_type, traits_type> 932 view() const noexcept 933 { return _M_stringbuf.view(); } 934#endif 935 936 /** 937 * @brief Setting a new buffer. 938 * @param __s The string to use as a new sequence. 939 * 940 * Calls @c rdbuf()->str(s). 941 */ 942 void 943 str(const __string_type& __s) 944 { _M_stringbuf.str(__s); } 945 946#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 947#if __cpp_concepts 948 template<__allocator_like _SAlloc> 949 requires (!is_same_v<_SAlloc, _Alloc>) 950 void 951 str(const basic_string<_CharT, _Traits, _SAlloc>& __s) 952 { _M_stringbuf.str(__s); } 953#endif 954 955 void 956 str(__string_type&& __s) 957 { _M_stringbuf.str(std::move(__s)); } 958#endif 959 }; 960 961 962 // [27.7.4] Template class basic_stringstream 963 /** 964 * @brief Controlling input and output for std::string. 965 * @ingroup io 966 * 967 * @tparam _CharT Type of character stream. 968 * @tparam _Traits Traits for character type, defaults to 969 * char_traits<_CharT>. 970 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 971 * 972 * This class supports reading from and writing to objects of type 973 * std::basic_string, using the inherited functions from 974 * std::basic_iostream. To control the associated sequence, an instance 975 * of std::basic_stringbuf is used, which this page refers to as @c sb. 976 */ 977 template <typename _CharT, typename _Traits, typename _Alloc> 978 class basic_stringstream : public basic_iostream<_CharT, _Traits> 979 { 980 public: 981 // Types: 982 typedef _CharT char_type; 983 typedef _Traits traits_type; 984 // _GLIBCXX_RESOLVE_LIB_DEFECTS 985 // 251. basic_stringbuf missing allocator_type 986 typedef _Alloc allocator_type; 987 typedef typename traits_type::int_type int_type; 988 typedef typename traits_type::pos_type pos_type; 989 typedef typename traits_type::off_type off_type; 990 991 // Non-standard Types: 992 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 993 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type; 994 typedef basic_iostream<char_type, traits_type> __iostream_type; 995 996 private: 997 __stringbuf_type _M_stringbuf; 998 999 public: 1000 // Constructors/destructors 1001 1002 /** 1003 * @brief Default constructor starts with an empty string buffer. 1004 * 1005 * Initializes @c sb using the mode @c in|out, and passes @c &sb 1006 * to the base class initializer. Does not allocate any buffer. 1007 * 1008 * That's a lie. We initialize the base class with NULL, because the 1009 * string class does its own memory management. 1010 */ 1011 basic_stringstream() 1012 : __iostream_type(), _M_stringbuf(ios_base::out | ios_base::in) 1013 { this->init(&_M_stringbuf); } 1014 1015 /** 1016 * @brief Starts with an empty string buffer. 1017 * @param __m Whether the buffer can read, or write, or both. 1018 * 1019 * Initializes @c sb using the mode from @c __m, and passes @c &sb 1020 * to the base class initializer. Does not allocate any buffer. 1021 * 1022 * That's a lie. We initialize the base class with NULL, because the 1023 * string class does its own memory management. 1024 */ 1025 explicit 1026 basic_stringstream(ios_base::openmode __m) 1027 : __iostream_type(), _M_stringbuf(__m) 1028 { this->init(&_M_stringbuf); } 1029 1030 /** 1031 * @brief Starts with an existing string buffer. 1032 * @param __str A string to copy as a starting buffer. 1033 * @param __m Whether the buffer can read, or write, or both. 1034 * 1035 * Initializes @c sb using @a __str and @c __m, and passes @c &sb 1036 * to the base class initializer. 1037 * 1038 * That's a lie. We initialize the base class with NULL, because the 1039 * string class does its own memory management. 1040 */ 1041 explicit 1042 basic_stringstream(const __string_type& __str, 1043 ios_base::openmode __m = ios_base::out | ios_base::in) 1044 : __iostream_type(), _M_stringbuf(__str, __m) 1045 { this->init(&_M_stringbuf); } 1046 1047 /** 1048 * @brief The destructor does nothing. 1049 * 1050 * The buffer is deallocated by the stringbuf object, not the 1051 * formatting stream. 1052 */ 1053 ~basic_stringstream() 1054 { } 1055 1056#if __cplusplus >= 201103L 1057 basic_stringstream(const basic_stringstream&) = delete; 1058 1059 basic_stringstream(basic_stringstream&& __rhs) 1060 : __iostream_type(std::move(__rhs)), 1061 _M_stringbuf(std::move(__rhs._M_stringbuf)) 1062 { __iostream_type::set_rdbuf(&_M_stringbuf); } 1063 1064#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 1065 basic_stringstream(ios_base::openmode __mode, const allocator_type& __a) 1066 : __iostream_type(), _M_stringbuf(__mode, __a) 1067 { this->init(&_M_stringbuf); } 1068 1069 explicit 1070 basic_stringstream(__string_type&& __str, 1071 ios_base::openmode __mode = ios_base::in 1072 | ios_base::out) 1073 : __iostream_type(), _M_stringbuf(std::move(__str), __mode) 1074 { this->init(std::__addressof(_M_stringbuf)); } 1075 1076 template<typename _SAlloc> 1077 basic_stringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str, 1078 const allocator_type& __a) 1079 : basic_stringstream(__str, ios_base::in | ios_base::out, __a) 1080 { } 1081 1082 template<typename _SAlloc> 1083 basic_stringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str, 1084 ios_base::openmode __mode, 1085 const allocator_type& __a) 1086 : __iostream_type(), _M_stringbuf(__str, __mode, __a) 1087 { this->init(std::__addressof(_M_stringbuf)); } 1088 1089 template<typename _SAlloc> 1090 explicit 1091 basic_stringstream(const basic_string<_CharT, _Traits, _SAlloc>& __str, 1092 ios_base::openmode __mode = ios_base::in 1093 | ios_base::out) 1094 : basic_stringstream(__str, __mode, allocator_type()) 1095 { } 1096#endif // C++20 1097 1098 // 27.8.3.2 Assign and swap: 1099 1100 basic_stringstream& 1101 operator=(const basic_stringstream&) = delete; 1102 1103 basic_stringstream& 1104 operator=(basic_stringstream&& __rhs) 1105 { 1106 __iostream_type::operator=(std::move(__rhs)); 1107 _M_stringbuf = std::move(__rhs._M_stringbuf); 1108 return *this; 1109 } 1110 1111 void 1112 swap(basic_stringstream& __rhs) 1113 { 1114 __iostream_type::swap(__rhs); 1115 _M_stringbuf.swap(__rhs._M_stringbuf); 1116 } 1117#endif // C++11 1118 1119 // Members: 1120 /** 1121 * @brief Accessing the underlying buffer. 1122 * @return The current basic_stringbuf buffer. 1123 * 1124 * This hides both signatures of std::basic_ios::rdbuf(). 1125 */ 1126 __stringbuf_type* 1127 rdbuf() const 1128 { return const_cast<__stringbuf_type*>(&_M_stringbuf); } 1129 1130 /** 1131 * @brief Copying out the string buffer. 1132 * @return @c rdbuf()->str() 1133 */ 1134 __string_type 1135 str() const _GLIBCXX_LVAL_REF_QUAL 1136 { return _M_stringbuf.str(); } 1137 1138#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 1139#if __cpp_concepts 1140 template<__allocator_like _SAlloc> 1141 basic_string<_CharT, _Traits, _SAlloc> 1142 str(const _SAlloc& __sa) const 1143 { return _M_stringbuf.str(__sa); } 1144#endif 1145 1146 __string_type 1147 str() && 1148 { return std::move(_M_stringbuf).str(); } 1149 1150 basic_string_view<char_type, traits_type> 1151 view() const noexcept 1152 { return _M_stringbuf.view(); } 1153#endif 1154 1155 /** 1156 * @brief Setting a new buffer. 1157 * @param __s The string to use as a new sequence. 1158 * 1159 * Calls @c rdbuf()->str(s). 1160 */ 1161 void 1162 str(const __string_type& __s) 1163 { _M_stringbuf.str(__s); } 1164 1165#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI 1166#if __cpp_concepts 1167 template<__allocator_like _SAlloc> 1168 requires (!is_same_v<_SAlloc, _Alloc>) 1169 void 1170 str(const basic_string<_CharT, _Traits, _SAlloc>& __s) 1171 { _M_stringbuf.str(__s); } 1172#endif 1173 1174 void 1175 str(__string_type&& __s) 1176 { _M_stringbuf.str(std::move(__s)); } 1177#endif 1178 }; 1179 1180#if __cplusplus >= 201103L 1181 /// Swap specialization for stringbufs. 1182 template <class _CharT, class _Traits, class _Allocator> 1183 inline void 1184 swap(basic_stringbuf<_CharT, _Traits, _Allocator>& __x, 1185 basic_stringbuf<_CharT, _Traits, _Allocator>& __y) 1186 noexcept(noexcept(__x.swap(__y))) 1187 { __x.swap(__y); } 1188 1189 /// Swap specialization for istringstreams. 1190 template <class _CharT, class _Traits, class _Allocator> 1191 inline void 1192 swap(basic_istringstream<_CharT, _Traits, _Allocator>& __x, 1193 basic_istringstream<_CharT, _Traits, _Allocator>& __y) 1194 { __x.swap(__y); } 1195 1196 /// Swap specialization for ostringstreams. 1197 template <class _CharT, class _Traits, class _Allocator> 1198 inline void 1199 swap(basic_ostringstream<_CharT, _Traits, _Allocator>& __x, 1200 basic_ostringstream<_CharT, _Traits, _Allocator>& __y) 1201 { __x.swap(__y); } 1202 1203 /// Swap specialization for stringstreams. 1204 template <class _CharT, class _Traits, class _Allocator> 1205 inline void 1206 swap(basic_stringstream<_CharT, _Traits, _Allocator>& __x, 1207 basic_stringstream<_CharT, _Traits, _Allocator>& __y) 1208 { __x.swap(__y); } 1209#endif // C++11 1210 1211_GLIBCXX_END_NAMESPACE_CXX11 1212_GLIBCXX_END_NAMESPACE_VERSION 1213} // namespace 1214 1215#undef _GLIBCXX_LVAL_REF_QUAL 1216 1217#include <bits/sstream.tcc> 1218 1219#endif /* _GLIBCXX_SSTREAM */ 1220