1// String based streams -*- C++ -*-
2
3// Copyright (C) 1997-2019 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