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