1 // String based streams -*- C++ -*- 2 3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 2, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // You should have received a copy of the GNU General Public License along 18 // with this library; see the file COPYING. If not, write to the Free 19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 20 // USA. 21 22 // As a special exception, you may use this file as part of a free software 23 // library without restriction. Specifically, if other files instantiate 24 // templates or use macros or inline functions from this file, or you compile 25 // this file and link it with other files to produce an executable, this 26 // file does not by itself cause the resulting executable to be covered by 27 // the GNU General Public License. This exception does not however 28 // invalidate any other reasons why the executable file might be covered by 29 // the GNU General Public License. 30 31 /** @file sstream.tcc 32 * This is an internal header file, included by other library headers. 33 * You should not attempt to use it directly. 34 */ 35 36 // 37 // ISO C++ 14882: 27.7 String-based streams 38 // 39 40 #ifndef _SSTREAM_TCC 41 #define _SSTREAM_TCC 1 42 43 #pragma GCC system_header 44 45 #include <sstream> 46 47 _GLIBCXX_BEGIN_NAMESPACE(std) 48 49 template <class _CharT, class _Traits, class _Alloc> 50 typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 51 basic_stringbuf<_CharT, _Traits, _Alloc>:: 52 pbackfail(int_type __c) 53 { 54 int_type __ret = traits_type::eof(); 55 if (this->eback() < this->gptr()) 56 { 57 // Try to put back __c into input sequence in one of three ways. 58 // Order these tests done in is unspecified by the standard. 59 const bool __testeof = traits_type::eq_int_type(__c, __ret); 60 if (!__testeof) 61 { 62 const bool __testeq = traits_type::eq(traits_type:: 63 to_char_type(__c), 64 this->gptr()[-1]); 65 const bool __testout = this->_M_mode & ios_base::out; 66 if (__testeq || __testout) 67 { 68 this->gbump(-1); 69 if (!__testeq) 70 *this->gptr() = traits_type::to_char_type(__c); 71 __ret = __c; 72 } 73 } 74 else 75 { 76 this->gbump(-1); 77 __ret = traits_type::not_eof(__c); 78 } 79 } 80 return __ret; 81 } 82 83 template <class _CharT, class _Traits, class _Alloc> 84 typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 85 basic_stringbuf<_CharT, _Traits, _Alloc>:: 86 overflow(int_type __c) 87 { 88 const bool __testout = this->_M_mode & ios_base::out; 89 if (__builtin_expect(!__testout, false)) 90 return traits_type::eof(); 91 92 const bool __testeof = traits_type::eq_int_type(__c, traits_type::eof()); 93 if (__builtin_expect(__testeof, false)) 94 return traits_type::not_eof(__c); 95 96 const __size_type __capacity = _M_string.capacity(); 97 const __size_type __max_size = _M_string.max_size(); 98 const bool __testput = this->pptr() < this->epptr(); 99 if (__builtin_expect(!__testput && __capacity == __max_size, false)) 100 return traits_type::eof(); 101 102 // Try to append __c into output sequence in one of two ways. 103 // Order these tests done in is unspecified by the standard. 104 const char_type __conv = traits_type::to_char_type(__c); 105 if (!__testput) 106 { 107 // NB: Start ostringstream buffers at 512 chars. This is an 108 // experimental value (pronounced "arbitrary" in some of the 109 // hipper english-speaking countries), and can be changed to 110 // suit particular needs. 111 // 112 // _GLIBCXX_RESOLVE_LIB_DEFECTS 113 // 169. Bad efficiency of overflow() mandated 114 // 432. stringbuf::overflow() makes only one write position 115 // available 116 const __size_type __opt_len = std::max(__size_type(2 * __capacity), 117 __size_type(512)); 118 const __size_type __len = std::min(__opt_len, __max_size); 119 __string_type __tmp; 120 __tmp.reserve(__len); 121 if (this->pbase()) 122 __tmp.assign(this->pbase(), this->epptr() - this->pbase()); 123 __tmp.push_back(__conv); 124 _M_string.swap(__tmp); 125 _M_sync(const_cast<char_type*>(_M_string.data()), 126 this->gptr() - this->eback(), this->pptr() - this->pbase()); 127 } 128 else 129 *this->pptr() = __conv; 130 this->pbump(1); 131 return __c; 132 } 133 134 template <class _CharT, class _Traits, class _Alloc> 135 typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 136 basic_stringbuf<_CharT, _Traits, _Alloc>:: 137 underflow() 138 { 139 int_type __ret = traits_type::eof(); 140 const bool __testin = this->_M_mode & ios_base::in; 141 if (__testin) 142 { 143 // Update egptr() to match the actual string end. 144 _M_update_egptr(); 145 146 if (this->gptr() < this->egptr()) 147 __ret = traits_type::to_int_type(*this->gptr()); 148 } 149 return __ret; 150 } 151 152 template <class _CharT, class _Traits, class _Alloc> 153 typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type 154 basic_stringbuf<_CharT, _Traits, _Alloc>:: 155 seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode) 156 { 157 pos_type __ret = pos_type(off_type(-1)); 158 bool __testin = (ios_base::in & this->_M_mode & __mode) != 0; 159 bool __testout = (ios_base::out & this->_M_mode & __mode) != 0; 160 const bool __testboth = __testin && __testout && __way != ios_base::cur; 161 __testin &= !(__mode & ios_base::out); 162 __testout &= !(__mode & ios_base::in); 163 164 // _GLIBCXX_RESOLVE_LIB_DEFECTS 165 // 453. basic_stringbuf::seekoff need not always fail for an empty stream. 166 const char_type* __beg = __testin ? this->eback() : this->pbase(); 167 if ((__beg || !__off) && (__testin || __testout || __testboth)) 168 { 169 _M_update_egptr(); 170 171 off_type __newoffi = __off; 172 off_type __newoffo = __newoffi; 173 if (__way == ios_base::cur) 174 { 175 __newoffi += this->gptr() - __beg; 176 __newoffo += this->pptr() - __beg; 177 } 178 else if (__way == ios_base::end) 179 __newoffo = __newoffi += this->egptr() - __beg; 180 181 if ((__testin || __testboth) 182 && __newoffi >= 0 183 && this->egptr() - __beg >= __newoffi) 184 { 185 this->gbump((__beg + __newoffi) - this->gptr()); 186 __ret = pos_type(__newoffi); 187 } 188 if ((__testout || __testboth) 189 && __newoffo >= 0 190 && this->egptr() - __beg >= __newoffo) 191 { 192 this->pbump((__beg + __newoffo) - this->pptr()); 193 __ret = pos_type(__newoffo); 194 } 195 } 196 return __ret; 197 } 198 199 template <class _CharT, class _Traits, class _Alloc> 200 typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type 201 basic_stringbuf<_CharT, _Traits, _Alloc>:: 202 seekpos(pos_type __sp, ios_base::openmode __mode) 203 { 204 pos_type __ret = pos_type(off_type(-1)); 205 const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0; 206 const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0; 207 208 const char_type* __beg = __testin ? this->eback() : this->pbase(); 209 if ((__beg || !off_type(__sp)) && (__testin || __testout)) 210 { 211 _M_update_egptr(); 212 213 const off_type __pos(__sp); 214 const bool __testpos = (0 <= __pos 215 && __pos <= this->egptr() - __beg); 216 if (__testpos) 217 { 218 if (__testin) 219 this->gbump((__beg + __pos) - this->gptr()); 220 if (__testout) 221 this->pbump((__beg + __pos) - this->pptr()); 222 __ret = __sp; 223 } 224 } 225 return __ret; 226 } 227 228 template <class _CharT, class _Traits, class _Alloc> 229 void 230 basic_stringbuf<_CharT, _Traits, _Alloc>:: 231 _M_sync(char_type* __base, __size_type __i, __size_type __o) 232 { 233 const bool __testin = _M_mode & ios_base::in; 234 const bool __testout = _M_mode & ios_base::out; 235 char_type* __endg = __base + _M_string.size(); 236 char_type* __endp = __base + _M_string.capacity(); 237 238 if (__base != _M_string.data()) 239 { 240 // setbuf: __i == size of buffer area (_M_string.size() == 0). 241 __endg += __i; 242 __i = 0; 243 __endp = __endg; 244 } 245 246 if (__testin) 247 this->setg(__base, __base + __i, __endg); 248 if (__testout) 249 { 250 this->setp(__base, __endp); 251 this->pbump(__o); 252 // egptr() always tracks the string end. When !__testin, 253 // for the correct functioning of the streambuf inlines 254 // the other get area pointers are identical. 255 if (!__testin) 256 this->setg(__endg, __endg, __endg); 257 } 258 } 259 260 // Inhibit implicit instantiations for required instantiations, 261 // which are defined via explicit instantiations elsewhere. 262 // NB: This syntax is a GNU extension. 263 #if _GLIBCXX_EXTERN_TEMPLATE 264 extern template class basic_stringbuf<char>; 265 extern template class basic_istringstream<char>; 266 extern template class basic_ostringstream<char>; 267 extern template class basic_stringstream<char>; 268 269 #ifdef _GLIBCXX_USE_WCHAR_T 270 extern template class basic_stringbuf<wchar_t>; 271 extern template class basic_istringstream<wchar_t>; 272 extern template class basic_ostringstream<wchar_t>; 273 extern template class basic_stringstream<wchar_t>; 274 #endif 275 #endif 276 277 _GLIBCXX_END_NAMESPACE 278 279 #endif 280