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 47namespace 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 if (!__testput) 105 { 106 // NB: Start ostringstream buffers at 512 chars. This is an 107 // experimental value (pronounced "arbitrary" in some of the 108 // hipper english-speaking countries), and can be changed to 109 // suit particular needs. 110 // Then, in virtue of DR 169 (TC) we are allowed to grow more 111 // than one char. 112 const __size_type __opt_len = std::max(__size_type(2 * __capacity), 113 __size_type(512)); 114 const __size_type __len = std::min(__opt_len, __max_size); 115 __string_type __tmp; 116 __tmp.reserve(__len); 117 if (this->pbase()) 118 __tmp.assign(this->pbase(), this->epptr() - this->pbase()); 119 _M_string.swap(__tmp); 120 _M_sync(const_cast<char_type*>(_M_string.data()), 121 this->gptr() - this->eback(), this->pptr() - this->pbase()); 122 } 123 return this->sputc(traits_type::to_char_type(__c)); 124 } 125 126 template <class _CharT, class _Traits, class _Alloc> 127 typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 128 basic_stringbuf<_CharT, _Traits, _Alloc>:: 129 underflow() 130 { 131 int_type __ret = traits_type::eof(); 132 const bool __testin = this->_M_mode & ios_base::in; 133 if (__testin) 134 { 135 // Update egptr() to match the actual string end. 136 _M_update_egptr(); 137 138 if (this->gptr() < this->egptr()) 139 __ret = traits_type::to_int_type(*this->gptr()); 140 } 141 return __ret; 142 } 143 144 template <class _CharT, class _Traits, class _Alloc> 145 typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type 146 basic_stringbuf<_CharT, _Traits, _Alloc>:: 147 seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode) 148 { 149 pos_type __ret = pos_type(off_type(-1)); 150 bool __testin = (ios_base::in & this->_M_mode & __mode) != 0; 151 bool __testout = (ios_base::out & this->_M_mode & __mode) != 0; 152 const bool __testboth = __testin && __testout && __way != ios_base::cur; 153 __testin &= !(__mode & ios_base::out); 154 __testout &= !(__mode & ios_base::in); 155 156 // _GLIBCXX_RESOLVE_LIB_DEFECTS 157 // 453. basic_stringbuf::seekoff need not always fail for an empty stream. 158 const char_type* __beg = __testin ? this->eback() : this->pbase(); 159 if ((__beg || !__off) && (__testin || __testout || __testboth)) 160 { 161 _M_update_egptr(); 162 163 off_type __newoffi = __off; 164 off_type __newoffo = __newoffi; 165 if (__way == ios_base::cur) 166 { 167 __newoffi += this->gptr() - __beg; 168 __newoffo += this->pptr() - __beg; 169 } 170 else if (__way == ios_base::end) 171 __newoffo = __newoffi += this->egptr() - __beg; 172 173 if ((__testin || __testboth) 174 && __newoffi >= 0 175 && this->egptr() - __beg >= __newoffi) 176 { 177 this->gbump((__beg + __newoffi) - this->gptr()); 178 __ret = pos_type(__newoffi); 179 } 180 if ((__testout || __testboth) 181 && __newoffo >= 0 182 && this->egptr() - __beg >= __newoffo) 183 { 184 this->pbump((__beg + __newoffo) - this->pptr()); 185 __ret = pos_type(__newoffo); 186 } 187 } 188 return __ret; 189 } 190 191 template <class _CharT, class _Traits, class _Alloc> 192 typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type 193 basic_stringbuf<_CharT, _Traits, _Alloc>:: 194 seekpos(pos_type __sp, ios_base::openmode __mode) 195 { 196 pos_type __ret = pos_type(off_type(-1)); 197 const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0; 198 const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0; 199 200 const char_type* __beg = __testin ? this->eback() : this->pbase(); 201 if ((__beg || !off_type(__sp)) && (__testin || __testout)) 202 { 203 _M_update_egptr(); 204 205 const off_type __pos(__sp); 206 const bool __testpos = 0 <= __pos 207 && __pos <= this->egptr() - __beg; 208 if (__testpos) 209 { 210 if (__testin) 211 this->gbump((__beg + __pos) - this->gptr()); 212 if (__testout) 213 this->pbump((__beg + __pos) - this->pptr()); 214 __ret = __sp; 215 } 216 } 217 return __ret; 218 } 219 220 template <class _CharT, class _Traits, class _Alloc> 221 void 222 basic_stringbuf<_CharT, _Traits, _Alloc>:: 223 _M_sync(char_type* __base, __size_type __i, __size_type __o) 224 { 225 const bool __testin = _M_mode & ios_base::in; 226 const bool __testout = _M_mode & ios_base::out; 227 char_type* __endg = __base + _M_string.size(); 228 char_type* __endp = __base + _M_string.capacity(); 229 230 if (__base != _M_string.data()) 231 { 232 // setbuf: __i == size of buffer area (_M_string.size() == 0). 233 __endg += __i; 234 __i = 0; 235 __endp = __endg; 236 } 237 238 if (__testin) 239 this->setg(__base, __base + __i, __endg); 240 if (__testout) 241 { 242 this->setp(__base, __endp); 243 this->pbump(__o); 244 // egptr() always tracks the string end. When !__testin, 245 // for the correct functioning of the streambuf inlines 246 // the other get area pointers are identical. 247 if (!__testin) 248 this->setg(__endg, __endg, __endg); 249 } 250 } 251 252 // Inhibit implicit instantiations for required instantiations, 253 // which are defined via explicit instantiations elsewhere. 254 // NB: This syntax is a GNU extension. 255#if _GLIBCXX_EXTERN_TEMPLATE 256 extern template class basic_stringbuf<char>; 257 extern template class basic_istringstream<char>; 258 extern template class basic_ostringstream<char>; 259 extern template class basic_stringstream<char>; 260 261#ifdef _GLIBCXX_USE_WCHAR_T 262 extern template class basic_stringbuf<wchar_t>; 263 extern template class basic_istringstream<wchar_t>; 264 extern template class basic_ostringstream<wchar_t>; 265 extern template class basic_stringstream<wchar_t>; 266#endif 267#endif 268} // namespace std 269 270#endif 271