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