libstdc++
|
00001 // String based streams -*- C++ -*- 00002 00003 // Copyright (C) 1997-2017 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file include/sstream 00026 * This is a Standard C++ Library header. 00027 */ 00028 00029 // 00030 // ISO C++ 14882: 27.7 String-based streams 00031 // 00032 00033 #ifndef _GLIBCXX_SSTREAM 00034 #define _GLIBCXX_SSTREAM 1 00035 00036 #pragma GCC system_header 00037 00038 #include <istream> 00039 #include <ostream> 00040 00041 namespace std _GLIBCXX_VISIBILITY(default) 00042 { 00043 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00044 _GLIBCXX_BEGIN_NAMESPACE_CXX11 00045 00046 // [27.7.1] template class basic_stringbuf 00047 /** 00048 * @brief The actual work of input and output (for std::string). 00049 * @ingroup io 00050 * 00051 * @tparam _CharT Type of character stream. 00052 * @tparam _Traits Traits for character type, defaults to 00053 * char_traits<_CharT>. 00054 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 00055 * 00056 * This class associates either or both of its input and output sequences 00057 * with a sequence of characters, which can be initialized from, or made 00058 * available as, a @c std::basic_string. (Paraphrased from [27.7.1]/1.) 00059 * 00060 * For this class, open modes (of type @c ios_base::openmode) have 00061 * @c in set if the input sequence can be read, and @c out set if the 00062 * output sequence can be written. 00063 */ 00064 template<typename _CharT, typename _Traits, typename _Alloc> 00065 class basic_stringbuf : public basic_streambuf<_CharT, _Traits> 00066 { 00067 struct __xfer_bufptrs; 00068 public: 00069 // Types: 00070 typedef _CharT char_type; 00071 typedef _Traits traits_type; 00072 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00073 // 251. basic_stringbuf missing allocator_type 00074 typedef _Alloc allocator_type; 00075 typedef typename traits_type::int_type int_type; 00076 typedef typename traits_type::pos_type pos_type; 00077 typedef typename traits_type::off_type off_type; 00078 00079 typedef basic_streambuf<char_type, traits_type> __streambuf_type; 00080 typedef basic_string<char_type, _Traits, _Alloc> __string_type; 00081 typedef typename __string_type::size_type __size_type; 00082 00083 protected: 00084 /// Place to stash in || out || in | out settings for current stringbuf. 00085 ios_base::openmode _M_mode; 00086 00087 // Data Members: 00088 __string_type _M_string; 00089 00090 public: 00091 // Constructors: 00092 /** 00093 * @brief Starts with an empty string buffer. 00094 * @param __mode Whether the buffer can read, or write, or both. 00095 * 00096 * The default constructor initializes the parent class using its 00097 * own default ctor. 00098 */ 00099 explicit 00100 basic_stringbuf(ios_base::openmode __mode = ios_base::in | ios_base::out) 00101 : __streambuf_type(), _M_mode(__mode), _M_string() 00102 { } 00103 00104 /** 00105 * @brief Starts with an existing string buffer. 00106 * @param __str A string to copy as a starting buffer. 00107 * @param __mode Whether the buffer can read, or write, or both. 00108 * 00109 * This constructor initializes the parent class using its 00110 * own default ctor. 00111 */ 00112 explicit 00113 basic_stringbuf(const __string_type& __str, 00114 ios_base::openmode __mode = ios_base::in | ios_base::out) 00115 : __streambuf_type(), _M_mode(), _M_string(__str.data(), __str.size()) 00116 { _M_stringbuf_init(__mode); } 00117 00118 #if __cplusplus >= 201103L 00119 basic_stringbuf(const basic_stringbuf&) = delete; 00120 00121 basic_stringbuf(basic_stringbuf&& __rhs) 00122 : basic_stringbuf(std::move(__rhs), __xfer_bufptrs(__rhs, this)) 00123 { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); } 00124 00125 // 27.8.2.2 Assign and swap: 00126 00127 basic_stringbuf& 00128 operator=(const basic_stringbuf&) = delete; 00129 00130 basic_stringbuf& 00131 operator=(basic_stringbuf&& __rhs) 00132 { 00133 __xfer_bufptrs __st{__rhs, this}; 00134 const __streambuf_type& __base = __rhs; 00135 __streambuf_type::operator=(__base); 00136 this->pubimbue(__rhs.getloc()); 00137 _M_mode = __rhs._M_mode; 00138 _M_string = std::move(__rhs._M_string); 00139 __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); 00140 return *this; 00141 } 00142 00143 void 00144 swap(basic_stringbuf& __rhs) 00145 { 00146 __xfer_bufptrs __l_st{*this, std::__addressof(__rhs)}; 00147 __xfer_bufptrs __r_st{__rhs, this}; 00148 __streambuf_type& __base = __rhs; 00149 __streambuf_type::swap(__base); 00150 __rhs.pubimbue(this->pubimbue(__rhs.getloc())); 00151 std::swap(_M_mode, __rhs._M_mode); 00152 std::swap(_M_string, __rhs._M_string); 00153 } 00154 #endif 00155 00156 // Get and set: 00157 /** 00158 * @brief Copying out the string buffer. 00159 * @return A copy of one of the underlying sequences. 00160 * 00161 * <em>If the buffer is only created in input mode, the underlying 00162 * character sequence is equal to the input sequence; otherwise, it 00163 * is equal to the output sequence.</em> [27.7.1.2]/1 00164 */ 00165 __string_type 00166 str() const 00167 { 00168 __string_type __ret; 00169 if (this->pptr()) 00170 { 00171 // The current egptr() may not be the actual string end. 00172 if (this->pptr() > this->egptr()) 00173 __ret = __string_type(this->pbase(), this->pptr()); 00174 else 00175 __ret = __string_type(this->pbase(), this->egptr()); 00176 } 00177 else 00178 __ret = _M_string; 00179 return __ret; 00180 } 00181 00182 /** 00183 * @brief Setting a new buffer. 00184 * @param __s The string to use as a new sequence. 00185 * 00186 * Deallocates any previous stored sequence, then copies @a s to 00187 * use as a new one. 00188 */ 00189 void 00190 str(const __string_type& __s) 00191 { 00192 // Cannot use _M_string = __s, since v3 strings are COW 00193 // (not always true now but assign() always works). 00194 _M_string.assign(__s.data(), __s.size()); 00195 _M_stringbuf_init(_M_mode); 00196 } 00197 00198 protected: 00199 // Common initialization code goes here. 00200 void 00201 _M_stringbuf_init(ios_base::openmode __mode) 00202 { 00203 _M_mode = __mode; 00204 __size_type __len = 0; 00205 if (_M_mode & (ios_base::ate | ios_base::app)) 00206 __len = _M_string.size(); 00207 _M_sync(const_cast<char_type*>(_M_string.data()), 0, __len); 00208 } 00209 00210 virtual streamsize 00211 showmanyc() 00212 { 00213 streamsize __ret = -1; 00214 if (_M_mode & ios_base::in) 00215 { 00216 _M_update_egptr(); 00217 __ret = this->egptr() - this->gptr(); 00218 } 00219 return __ret; 00220 } 00221 00222 virtual int_type 00223 underflow(); 00224 00225 virtual int_type 00226 pbackfail(int_type __c = traits_type::eof()); 00227 00228 virtual int_type 00229 overflow(int_type __c = traits_type::eof()); 00230 00231 /** 00232 * @brief Manipulates the buffer. 00233 * @param __s Pointer to a buffer area. 00234 * @param __n Size of @a __s. 00235 * @return @c this 00236 * 00237 * If no buffer has already been created, and both @a __s and @a __n are 00238 * non-zero, then @c __s is used as a buffer; see 00239 * https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html#io.streambuf.buffering 00240 * for more. 00241 */ 00242 virtual __streambuf_type* 00243 setbuf(char_type* __s, streamsize __n) 00244 { 00245 if (__s && __n >= 0) 00246 { 00247 // This is implementation-defined behavior, and assumes 00248 // that an external char_type array of length __n exists 00249 // and has been pre-allocated. If this is not the case, 00250 // things will quickly blow up. 00251 00252 // Step 1: Destroy the current internal array. 00253 _M_string.clear(); 00254 00255 // Step 2: Use the external array. 00256 _M_sync(__s, __n, 0); 00257 } 00258 return this; 00259 } 00260 00261 virtual pos_type 00262 seekoff(off_type __off, ios_base::seekdir __way, 00263 ios_base::openmode __mode = ios_base::in | ios_base::out); 00264 00265 virtual pos_type 00266 seekpos(pos_type __sp, 00267 ios_base::openmode __mode = ios_base::in | ios_base::out); 00268 00269 // Internal function for correctly updating the internal buffer 00270 // for a particular _M_string, due to initialization or re-sizing 00271 // of an existing _M_string. 00272 void 00273 _M_sync(char_type* __base, __size_type __i, __size_type __o); 00274 00275 // Internal function for correctly updating egptr() to the actual 00276 // string end. 00277 void 00278 _M_update_egptr() 00279 { 00280 const bool __testin = _M_mode & ios_base::in; 00281 if (this->pptr() && this->pptr() > this->egptr()) 00282 { 00283 if (__testin) 00284 this->setg(this->eback(), this->gptr(), this->pptr()); 00285 else 00286 this->setg(this->pptr(), this->pptr(), this->pptr()); 00287 } 00288 } 00289 00290 // Works around the issue with pbump, part of the protected 00291 // interface of basic_streambuf, taking just an int. 00292 void 00293 _M_pbump(char_type* __pbeg, char_type* __pend, off_type __off); 00294 00295 private: 00296 #if __cplusplus >= 201103L 00297 #if _GLIBCXX_USE_CXX11_ABI 00298 // This type captures the state of the gptr / pptr pointers as offsets 00299 // so they can be restored in another object after moving the string. 00300 struct __xfer_bufptrs 00301 { 00302 __xfer_bufptrs(const basic_stringbuf& __from, basic_stringbuf* __to) 00303 : _M_to{__to}, _M_goff{-1, -1, -1}, _M_poff{-1, -1, -1} 00304 { 00305 const _CharT* const __str = __from._M_string.data(); 00306 const _CharT* __end = nullptr; 00307 if (__from.eback()) 00308 { 00309 _M_goff[0] = __from.eback() - __str; 00310 _M_goff[1] = __from.gptr() - __str; 00311 _M_goff[2] = __from.egptr() - __str; 00312 __end = __from.egptr(); 00313 } 00314 if (__from.pbase()) 00315 { 00316 _M_poff[0] = __from.pbase() - __str; 00317 _M_poff[1] = __from.pptr() - __from.pbase(); 00318 _M_poff[2] = __from.epptr() - __str; 00319 if (__from.pptr() > __end) 00320 __end = __from.pptr(); 00321 } 00322 00323 // Set _M_string length to the greater of the get and put areas. 00324 if (__end) 00325 { 00326 // The const_cast avoids changing this constructor's signature, 00327 // because it is exported from the dynamic library. 00328 auto& __mut_from = const_cast<basic_stringbuf&>(__from); 00329 __mut_from._M_string._M_length(__end - __str); 00330 } 00331 } 00332 00333 ~__xfer_bufptrs() 00334 { 00335 char_type* __str = const_cast<char_type*>(_M_to->_M_string.data()); 00336 if (_M_goff[0] != -1) 00337 _M_to->setg(__str+_M_goff[0], __str+_M_goff[1], __str+_M_goff[2]); 00338 if (_M_poff[0] != -1) 00339 _M_to->_M_pbump(__str+_M_poff[0], __str+_M_poff[2], _M_poff[1]); 00340 } 00341 00342 basic_stringbuf* _M_to; 00343 off_type _M_goff[3]; 00344 off_type _M_poff[3]; 00345 }; 00346 #else 00347 // This type does nothing when using Copy-On-Write strings. 00348 struct __xfer_bufptrs 00349 { 00350 __xfer_bufptrs(const basic_stringbuf&, basic_stringbuf*) { } 00351 }; 00352 #endif 00353 00354 // The move constructor initializes an __xfer_bufptrs temporary then 00355 // delegates to this constructor to performs moves during its lifetime. 00356 basic_stringbuf(basic_stringbuf&& __rhs, __xfer_bufptrs&&) 00357 : __streambuf_type(static_cast<const __streambuf_type&>(__rhs)), 00358 _M_mode(__rhs._M_mode), _M_string(std::move(__rhs._M_string)) 00359 { } 00360 #endif 00361 }; 00362 00363 00364 // [27.7.2] Template class basic_istringstream 00365 /** 00366 * @brief Controlling input for std::string. 00367 * @ingroup io 00368 * 00369 * @tparam _CharT Type of character stream. 00370 * @tparam _Traits Traits for character type, defaults to 00371 * char_traits<_CharT>. 00372 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 00373 * 00374 * This class supports reading from objects of type std::basic_string, 00375 * using the inherited functions from std::basic_istream. To control 00376 * the associated sequence, an instance of std::basic_stringbuf is used, 00377 * which this page refers to as @c sb. 00378 */ 00379 template<typename _CharT, typename _Traits, typename _Alloc> 00380 class basic_istringstream : public basic_istream<_CharT, _Traits> 00381 { 00382 public: 00383 // Types: 00384 typedef _CharT char_type; 00385 typedef _Traits traits_type; 00386 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00387 // 251. basic_stringbuf missing allocator_type 00388 typedef _Alloc allocator_type; 00389 typedef typename traits_type::int_type int_type; 00390 typedef typename traits_type::pos_type pos_type; 00391 typedef typename traits_type::off_type off_type; 00392 00393 // Non-standard types: 00394 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 00395 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type; 00396 typedef basic_istream<char_type, traits_type> __istream_type; 00397 00398 private: 00399 __stringbuf_type _M_stringbuf; 00400 00401 public: 00402 // Constructors: 00403 /** 00404 * @brief Default constructor starts with an empty string buffer. 00405 * @param __mode Whether the buffer can read, or write, or both. 00406 * 00407 * @c ios_base::in is automatically included in @a __mode. 00408 * 00409 * Initializes @c sb using @c __mode|in, and passes @c &sb to the base 00410 * class initializer. Does not allocate any buffer. 00411 * 00412 * That's a lie. We initialize the base class with NULL, because the 00413 * string class does its own memory management. 00414 */ 00415 explicit 00416 basic_istringstream(ios_base::openmode __mode = ios_base::in) 00417 : __istream_type(), _M_stringbuf(__mode | ios_base::in) 00418 { this->init(&_M_stringbuf); } 00419 00420 /** 00421 * @brief Starts with an existing string buffer. 00422 * @param __str A string to copy as a starting buffer. 00423 * @param __mode Whether the buffer can read, or write, or both. 00424 * 00425 * @c ios_base::in is automatically included in @a mode. 00426 * 00427 * Initializes @c sb using @a str and @c mode|in, and passes @c &sb 00428 * to the base class initializer. 00429 * 00430 * That's a lie. We initialize the base class with NULL, because the 00431 * string class does its own memory management. 00432 */ 00433 explicit 00434 basic_istringstream(const __string_type& __str, 00435 ios_base::openmode __mode = ios_base::in) 00436 : __istream_type(), _M_stringbuf(__str, __mode | ios_base::in) 00437 { this->init(&_M_stringbuf); } 00438 00439 /** 00440 * @brief The destructor does nothing. 00441 * 00442 * The buffer is deallocated by the stringbuf object, not the 00443 * formatting stream. 00444 */ 00445 ~basic_istringstream() 00446 { } 00447 00448 #if __cplusplus >= 201103L 00449 basic_istringstream(const basic_istringstream&) = delete; 00450 00451 basic_istringstream(basic_istringstream&& __rhs) 00452 : __istream_type(std::move(__rhs)), 00453 _M_stringbuf(std::move(__rhs._M_stringbuf)) 00454 { __istream_type::set_rdbuf(&_M_stringbuf); } 00455 00456 // 27.8.3.2 Assign and swap: 00457 00458 basic_istringstream& 00459 operator=(const basic_istringstream&) = delete; 00460 00461 basic_istringstream& 00462 operator=(basic_istringstream&& __rhs) 00463 { 00464 __istream_type::operator=(std::move(__rhs)); 00465 _M_stringbuf = std::move(__rhs._M_stringbuf); 00466 return *this; 00467 } 00468 00469 void 00470 swap(basic_istringstream& __rhs) 00471 { 00472 __istream_type::swap(__rhs); 00473 _M_stringbuf.swap(__rhs._M_stringbuf); 00474 } 00475 #endif 00476 00477 // Members: 00478 /** 00479 * @brief Accessing the underlying buffer. 00480 * @return The current basic_stringbuf buffer. 00481 * 00482 * This hides both signatures of std::basic_ios::rdbuf(). 00483 */ 00484 __stringbuf_type* 00485 rdbuf() const 00486 { return const_cast<__stringbuf_type*>(&_M_stringbuf); } 00487 00488 /** 00489 * @brief Copying out the string buffer. 00490 * @return @c rdbuf()->str() 00491 */ 00492 __string_type 00493 str() const 00494 { return _M_stringbuf.str(); } 00495 00496 /** 00497 * @brief Setting a new buffer. 00498 * @param __s The string to use as a new sequence. 00499 * 00500 * Calls @c rdbuf()->str(s). 00501 */ 00502 void 00503 str(const __string_type& __s) 00504 { _M_stringbuf.str(__s); } 00505 }; 00506 00507 00508 // [27.7.3] Template class basic_ostringstream 00509 /** 00510 * @brief Controlling output for std::string. 00511 * @ingroup io 00512 * 00513 * @tparam _CharT Type of character stream. 00514 * @tparam _Traits Traits for character type, defaults to 00515 * char_traits<_CharT>. 00516 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 00517 * 00518 * This class supports writing to objects of type std::basic_string, 00519 * using the inherited functions from std::basic_ostream. To control 00520 * the associated sequence, an instance of std::basic_stringbuf is used, 00521 * which this page refers to as @c sb. 00522 */ 00523 template <typename _CharT, typename _Traits, typename _Alloc> 00524 class basic_ostringstream : public basic_ostream<_CharT, _Traits> 00525 { 00526 public: 00527 // Types: 00528 typedef _CharT char_type; 00529 typedef _Traits traits_type; 00530 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00531 // 251. basic_stringbuf missing allocator_type 00532 typedef _Alloc allocator_type; 00533 typedef typename traits_type::int_type int_type; 00534 typedef typename traits_type::pos_type pos_type; 00535 typedef typename traits_type::off_type off_type; 00536 00537 // Non-standard types: 00538 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 00539 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type; 00540 typedef basic_ostream<char_type, traits_type> __ostream_type; 00541 00542 private: 00543 __stringbuf_type _M_stringbuf; 00544 00545 public: 00546 // Constructors/destructor: 00547 /** 00548 * @brief Default constructor starts with an empty string buffer. 00549 * @param __mode Whether the buffer can read, or write, or both. 00550 * 00551 * @c ios_base::out is automatically included in @a mode. 00552 * 00553 * Initializes @c sb using @c mode|out, and passes @c &sb to the base 00554 * class initializer. Does not allocate any buffer. 00555 * 00556 * That's a lie. We initialize the base class with NULL, because the 00557 * string class does its own memory management. 00558 */ 00559 explicit 00560 basic_ostringstream(ios_base::openmode __mode = ios_base::out) 00561 : __ostream_type(), _M_stringbuf(__mode | ios_base::out) 00562 { this->init(&_M_stringbuf); } 00563 00564 /** 00565 * @brief Starts with an existing string buffer. 00566 * @param __str A string to copy as a starting buffer. 00567 * @param __mode Whether the buffer can read, or write, or both. 00568 * 00569 * @c ios_base::out is automatically included in @a mode. 00570 * 00571 * Initializes @c sb using @a str and @c mode|out, and passes @c &sb 00572 * to the base class initializer. 00573 * 00574 * That's a lie. We initialize the base class with NULL, because the 00575 * string class does its own memory management. 00576 */ 00577 explicit 00578 basic_ostringstream(const __string_type& __str, 00579 ios_base::openmode __mode = ios_base::out) 00580 : __ostream_type(), _M_stringbuf(__str, __mode | ios_base::out) 00581 { this->init(&_M_stringbuf); } 00582 00583 /** 00584 * @brief The destructor does nothing. 00585 * 00586 * The buffer is deallocated by the stringbuf object, not the 00587 * formatting stream. 00588 */ 00589 ~basic_ostringstream() 00590 { } 00591 00592 #if __cplusplus >= 201103L 00593 basic_ostringstream(const basic_ostringstream&) = delete; 00594 00595 basic_ostringstream(basic_ostringstream&& __rhs) 00596 : __ostream_type(std::move(__rhs)), 00597 _M_stringbuf(std::move(__rhs._M_stringbuf)) 00598 { __ostream_type::set_rdbuf(&_M_stringbuf); } 00599 00600 // 27.8.3.2 Assign and swap: 00601 00602 basic_ostringstream& 00603 operator=(const basic_ostringstream&) = delete; 00604 00605 basic_ostringstream& 00606 operator=(basic_ostringstream&& __rhs) 00607 { 00608 __ostream_type::operator=(std::move(__rhs)); 00609 _M_stringbuf = std::move(__rhs._M_stringbuf); 00610 return *this; 00611 } 00612 00613 void 00614 swap(basic_ostringstream& __rhs) 00615 { 00616 __ostream_type::swap(__rhs); 00617 _M_stringbuf.swap(__rhs._M_stringbuf); 00618 } 00619 #endif 00620 00621 // Members: 00622 /** 00623 * @brief Accessing the underlying buffer. 00624 * @return The current basic_stringbuf buffer. 00625 * 00626 * This hides both signatures of std::basic_ios::rdbuf(). 00627 */ 00628 __stringbuf_type* 00629 rdbuf() const 00630 { return const_cast<__stringbuf_type*>(&_M_stringbuf); } 00631 00632 /** 00633 * @brief Copying out the string buffer. 00634 * @return @c rdbuf()->str() 00635 */ 00636 __string_type 00637 str() const 00638 { return _M_stringbuf.str(); } 00639 00640 /** 00641 * @brief Setting a new buffer. 00642 * @param __s The string to use as a new sequence. 00643 * 00644 * Calls @c rdbuf()->str(s). 00645 */ 00646 void 00647 str(const __string_type& __s) 00648 { _M_stringbuf.str(__s); } 00649 }; 00650 00651 00652 // [27.7.4] Template class basic_stringstream 00653 /** 00654 * @brief Controlling input and output for std::string. 00655 * @ingroup io 00656 * 00657 * @tparam _CharT Type of character stream. 00658 * @tparam _Traits Traits for character type, defaults to 00659 * char_traits<_CharT>. 00660 * @tparam _Alloc Allocator type, defaults to allocator<_CharT>. 00661 * 00662 * This class supports reading from and writing to objects of type 00663 * std::basic_string, using the inherited functions from 00664 * std::basic_iostream. To control the associated sequence, an instance 00665 * of std::basic_stringbuf is used, which this page refers to as @c sb. 00666 */ 00667 template <typename _CharT, typename _Traits, typename _Alloc> 00668 class basic_stringstream : public basic_iostream<_CharT, _Traits> 00669 { 00670 public: 00671 // Types: 00672 typedef _CharT char_type; 00673 typedef _Traits traits_type; 00674 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00675 // 251. basic_stringbuf missing allocator_type 00676 typedef _Alloc allocator_type; 00677 typedef typename traits_type::int_type int_type; 00678 typedef typename traits_type::pos_type pos_type; 00679 typedef typename traits_type::off_type off_type; 00680 00681 // Non-standard Types: 00682 typedef basic_string<_CharT, _Traits, _Alloc> __string_type; 00683 typedef basic_stringbuf<_CharT, _Traits, _Alloc> __stringbuf_type; 00684 typedef basic_iostream<char_type, traits_type> __iostream_type; 00685 00686 private: 00687 __stringbuf_type _M_stringbuf; 00688 00689 public: 00690 // Constructors/destructors 00691 /** 00692 * @brief Default constructor starts with an empty string buffer. 00693 * @param __m Whether the buffer can read, or write, or both. 00694 * 00695 * Initializes @c sb using the mode from @c __m, and passes @c 00696 * &sb to the base class initializer. Does not allocate any 00697 * buffer. 00698 * 00699 * That's a lie. We initialize the base class with NULL, because the 00700 * string class does its own memory management. 00701 */ 00702 explicit 00703 basic_stringstream(ios_base::openmode __m = ios_base::out | ios_base::in) 00704 : __iostream_type(), _M_stringbuf(__m) 00705 { this->init(&_M_stringbuf); } 00706 00707 /** 00708 * @brief Starts with an existing string buffer. 00709 * @param __str A string to copy as a starting buffer. 00710 * @param __m Whether the buffer can read, or write, or both. 00711 * 00712 * Initializes @c sb using @a __str and @c __m, and passes @c &sb 00713 * to the base class initializer. 00714 * 00715 * That's a lie. We initialize the base class with NULL, because the 00716 * string class does its own memory management. 00717 */ 00718 explicit 00719 basic_stringstream(const __string_type& __str, 00720 ios_base::openmode __m = ios_base::out | ios_base::in) 00721 : __iostream_type(), _M_stringbuf(__str, __m) 00722 { this->init(&_M_stringbuf); } 00723 00724 /** 00725 * @brief The destructor does nothing. 00726 * 00727 * The buffer is deallocated by the stringbuf object, not the 00728 * formatting stream. 00729 */ 00730 ~basic_stringstream() 00731 { } 00732 00733 #if __cplusplus >= 201103L 00734 basic_stringstream(const basic_stringstream&) = delete; 00735 00736 basic_stringstream(basic_stringstream&& __rhs) 00737 : __iostream_type(std::move(__rhs)), 00738 _M_stringbuf(std::move(__rhs._M_stringbuf)) 00739 { __iostream_type::set_rdbuf(&_M_stringbuf); } 00740 00741 // 27.8.3.2 Assign and swap: 00742 00743 basic_stringstream& 00744 operator=(const basic_stringstream&) = delete; 00745 00746 basic_stringstream& 00747 operator=(basic_stringstream&& __rhs) 00748 { 00749 __iostream_type::operator=(std::move(__rhs)); 00750 _M_stringbuf = std::move(__rhs._M_stringbuf); 00751 return *this; 00752 } 00753 00754 void 00755 swap(basic_stringstream& __rhs) 00756 { 00757 __iostream_type::swap(__rhs); 00758 _M_stringbuf.swap(__rhs._M_stringbuf); 00759 } 00760 #endif 00761 00762 // Members: 00763 /** 00764 * @brief Accessing the underlying buffer. 00765 * @return The current basic_stringbuf buffer. 00766 * 00767 * This hides both signatures of std::basic_ios::rdbuf(). 00768 */ 00769 __stringbuf_type* 00770 rdbuf() const 00771 { return const_cast<__stringbuf_type*>(&_M_stringbuf); } 00772 00773 /** 00774 * @brief Copying out the string buffer. 00775 * @return @c rdbuf()->str() 00776 */ 00777 __string_type 00778 str() const 00779 { return _M_stringbuf.str(); } 00780 00781 /** 00782 * @brief Setting a new buffer. 00783 * @param __s The string to use as a new sequence. 00784 * 00785 * Calls @c rdbuf()->str(s). 00786 */ 00787 void 00788 str(const __string_type& __s) 00789 { _M_stringbuf.str(__s); } 00790 }; 00791 00792 #if __cplusplus >= 201103L 00793 /// Swap specialization for stringbufs. 00794 template <class _CharT, class _Traits, class _Allocator> 00795 inline void 00796 swap(basic_stringbuf<_CharT, _Traits, _Allocator>& __x, 00797 basic_stringbuf<_CharT, _Traits, _Allocator>& __y) 00798 { __x.swap(__y); } 00799 00800 /// Swap specialization for istringstreams. 00801 template <class _CharT, class _Traits, class _Allocator> 00802 inline void 00803 swap(basic_istringstream<_CharT, _Traits, _Allocator>& __x, 00804 basic_istringstream<_CharT, _Traits, _Allocator>& __y) 00805 { __x.swap(__y); } 00806 00807 /// Swap specialization for ostringstreams. 00808 template <class _CharT, class _Traits, class _Allocator> 00809 inline void 00810 swap(basic_ostringstream<_CharT, _Traits, _Allocator>& __x, 00811 basic_ostringstream<_CharT, _Traits, _Allocator>& __y) 00812 { __x.swap(__y); } 00813 00814 /// Swap specialization for stringstreams. 00815 template <class _CharT, class _Traits, class _Allocator> 00816 inline void 00817 swap(basic_stringstream<_CharT, _Traits, _Allocator>& __x, 00818 basic_stringstream<_CharT, _Traits, _Allocator>& __y) 00819 { __x.swap(__y); } 00820 #endif 00821 00822 _GLIBCXX_END_NAMESPACE_CXX11 00823 _GLIBCXX_END_NAMESPACE_VERSION 00824 } // namespace 00825 00826 #include <bits/sstream.tcc> 00827 00828 #endif /* _GLIBCXX_SSTREAM */