libstdc++
sstream
Go to the documentation of this file.
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 */