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
41namespace 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 */
882