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