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 */ |
1220 | |