197403Sobrien// String based streams -*- C++ -*- 297403Sobrien 3169691Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 497403Sobrien// Free Software Foundation, Inc. 597403Sobrien// 697403Sobrien// This file is part of the GNU ISO C++ Library. This library is free 797403Sobrien// software; you can redistribute it and/or modify it under the 897403Sobrien// terms of the GNU General Public License as published by the 997403Sobrien// Free Software Foundation; either version 2, or (at your option) 1097403Sobrien// any later version. 1197403Sobrien 1297403Sobrien// This library is distributed in the hope that it will be useful, 1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of 1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1597403Sobrien// GNU General Public License for more details. 1697403Sobrien 1797403Sobrien// You should have received a copy of the GNU General Public License along 1897403Sobrien// with this library; see the file COPYING. If not, write to the Free 19169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 2097403Sobrien// USA. 2197403Sobrien 2297403Sobrien// As a special exception, you may use this file as part of a free software 2397403Sobrien// library without restriction. Specifically, if other files instantiate 2497403Sobrien// templates or use macros or inline functions from this file, or you compile 2597403Sobrien// this file and link it with other files to produce an executable, this 2697403Sobrien// file does not by itself cause the resulting executable to be covered by 2797403Sobrien// the GNU General Public License. This exception does not however 2897403Sobrien// invalidate any other reasons why the executable file might be covered by 2997403Sobrien// the GNU General Public License. 3097403Sobrien 31169691Skan/** @file sstream.tcc 32169691Skan * This is an internal header file, included by other library headers. 33169691Skan * You should not attempt to use it directly. 34169691Skan */ 35169691Skan 3697403Sobrien// 3797403Sobrien// ISO C++ 14882: 27.7 String-based streams 3897403Sobrien// 3997403Sobrien 40132720Skan#ifndef _SSTREAM_TCC 41132720Skan#define _SSTREAM_TCC 1 4297403Sobrien 4397403Sobrien#pragma GCC system_header 4497403Sobrien 4597403Sobrien#include <sstream> 4697403Sobrien 47169691Skan_GLIBCXX_BEGIN_NAMESPACE(std) 48169691Skan 4997403Sobrien template <class _CharT, class _Traits, class _Alloc> 50132720Skan typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 5197403Sobrien basic_stringbuf<_CharT, _Traits, _Alloc>:: 5297403Sobrien pbackfail(int_type __c) 5397403Sobrien { 5497403Sobrien int_type __ret = traits_type::eof(); 55132720Skan if (this->eback() < this->gptr()) 5697403Sobrien { 57132720Skan // Try to put back __c into input sequence in one of three ways. 58132720Skan // Order these tests done in is unspecified by the standard. 59169691Skan const bool __testeof = traits_type::eq_int_type(__c, __ret); 60169691Skan if (!__testeof) 61169691Skan { 62169691Skan const bool __testeq = traits_type::eq(traits_type:: 63169691Skan to_char_type(__c), 64169691Skan this->gptr()[-1]); 65169691Skan const bool __testout = this->_M_mode & ios_base::out; 66169691Skan if (__testeq || __testout) 67169691Skan { 68169691Skan this->gbump(-1); 69169691Skan if (!__testeq) 70169691Skan *this->gptr() = traits_type::to_char_type(__c); 71169691Skan __ret = __c; 72169691Skan } 73169691Skan } 74132720Skan else 7597403Sobrien { 76169691Skan this->gbump(-1); 77169691Skan __ret = traits_type::not_eof(__c); 7897403Sobrien } 7997403Sobrien } 8097403Sobrien return __ret; 8197403Sobrien } 82132720Skan 8397403Sobrien template <class _CharT, class _Traits, class _Alloc> 84132720Skan typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 8597403Sobrien basic_stringbuf<_CharT, _Traits, _Alloc>:: 8697403Sobrien overflow(int_type __c) 8797403Sobrien { 88132720Skan const bool __testout = this->_M_mode & ios_base::out; 89132720Skan if (__builtin_expect(!__testout, false)) 90132720Skan return traits_type::eof(); 9197403Sobrien 92132720Skan const bool __testeof = traits_type::eq_int_type(__c, traits_type::eof()); 93132720Skan if (__builtin_expect(__testeof, false)) 94132720Skan return traits_type::not_eof(__c); 95132720Skan 96132720Skan const __size_type __capacity = _M_string.capacity(); 97132720Skan const __size_type __max_size = _M_string.max_size(); 98132720Skan const bool __testput = this->pptr() < this->epptr(); 99132720Skan if (__builtin_expect(!__testput && __capacity == __max_size, false)) 100132720Skan return traits_type::eof(); 101132720Skan 10297403Sobrien // Try to append __c into output sequence in one of two ways. 10397403Sobrien // Order these tests done in is unspecified by the standard. 104169691Skan const char_type __conv = traits_type::to_char_type(__c); 105132720Skan if (!__testput) 10697403Sobrien { 107169691Skan // NB: Start ostringstream buffers at 512 chars. This is an 108132720Skan // experimental value (pronounced "arbitrary" in some of the 109132720Skan // hipper english-speaking countries), and can be changed to 110132720Skan // suit particular needs. 111169691Skan // 112169691Skan // _GLIBCXX_RESOLVE_LIB_DEFECTS 113169691Skan // 169. Bad efficiency of overflow() mandated 114169691Skan // 432. stringbuf::overflow() makes only one write position 115169691Skan // available 116132720Skan const __size_type __opt_len = std::max(__size_type(2 * __capacity), 117132720Skan __size_type(512)); 118132720Skan const __size_type __len = std::min(__opt_len, __max_size); 119132720Skan __string_type __tmp; 120132720Skan __tmp.reserve(__len); 121169691Skan if (this->pbase()) 122169691Skan __tmp.assign(this->pbase(), this->epptr() - this->pbase()); 123169691Skan __tmp.push_back(__conv); 124132720Skan _M_string.swap(__tmp); 125132720Skan _M_sync(const_cast<char_type*>(_M_string.data()), 126132720Skan this->gptr() - this->eback(), this->pptr() - this->pbase()); 127132720Skan } 128169691Skan else 129169691Skan *this->pptr() = __conv; 130169691Skan this->pbump(1); 131169691Skan return __c; 132132720Skan } 13397403Sobrien 134132720Skan template <class _CharT, class _Traits, class _Alloc> 135132720Skan typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 136132720Skan basic_stringbuf<_CharT, _Traits, _Alloc>:: 137132720Skan underflow() 138132720Skan { 139132720Skan int_type __ret = traits_type::eof(); 140132720Skan const bool __testin = this->_M_mode & ios_base::in; 141132720Skan if (__testin) 142132720Skan { 143132720Skan // Update egptr() to match the actual string end. 144132720Skan _M_update_egptr(); 145146897Skan 146132720Skan if (this->gptr() < this->egptr()) 147132720Skan __ret = traits_type::to_int_type(*this->gptr()); 14897403Sobrien } 14997403Sobrien return __ret; 15097403Sobrien } 15197403Sobrien 15297403Sobrien template <class _CharT, class _Traits, class _Alloc> 15397403Sobrien typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type 15497403Sobrien basic_stringbuf<_CharT, _Traits, _Alloc>:: 15597403Sobrien seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode) 15697403Sobrien { 157132720Skan pos_type __ret = pos_type(off_type(-1)); 158132720Skan bool __testin = (ios_base::in & this->_M_mode & __mode) != 0; 159132720Skan bool __testout = (ios_base::out & this->_M_mode & __mode) != 0; 160132720Skan const bool __testboth = __testin && __testout && __way != ios_base::cur; 16197403Sobrien __testin &= !(__mode & ios_base::out); 16297403Sobrien __testout &= !(__mode & ios_base::in); 16397403Sobrien 164146897Skan // _GLIBCXX_RESOLVE_LIB_DEFECTS 165146897Skan // 453. basic_stringbuf::seekoff need not always fail for an empty stream. 166146897Skan const char_type* __beg = __testin ? this->eback() : this->pbase(); 167146897Skan if ((__beg || !__off) && (__testin || __testout || __testboth)) 16897403Sobrien { 169132720Skan _M_update_egptr(); 17097403Sobrien 171169691Skan off_type __newoffi = __off; 172169691Skan off_type __newoffo = __newoffi; 17397403Sobrien if (__way == ios_base::cur) 17497403Sobrien { 175169691Skan __newoffi += this->gptr() - __beg; 176169691Skan __newoffo += this->pptr() - __beg; 17797403Sobrien } 17897403Sobrien else if (__way == ios_base::end) 179169691Skan __newoffo = __newoffi += this->egptr() - __beg; 18097403Sobrien 18197403Sobrien if ((__testin || __testboth) 182169691Skan && __newoffi >= 0 183169691Skan && this->egptr() - __beg >= __newoffi) 18497403Sobrien { 185169691Skan this->gbump((__beg + __newoffi) - this->gptr()); 18697403Sobrien __ret = pos_type(__newoffi); 18797403Sobrien } 18897403Sobrien if ((__testout || __testboth) 189169691Skan && __newoffo >= 0 190169691Skan && this->egptr() - __beg >= __newoffo) 19197403Sobrien { 192169691Skan this->pbump((__beg + __newoffo) - this->pptr()); 19397403Sobrien __ret = pos_type(__newoffo); 19497403Sobrien } 19597403Sobrien } 19697403Sobrien return __ret; 19797403Sobrien } 19897403Sobrien 19997403Sobrien template <class _CharT, class _Traits, class _Alloc> 20097403Sobrien typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type 20197403Sobrien basic_stringbuf<_CharT, _Traits, _Alloc>:: 20297403Sobrien seekpos(pos_type __sp, ios_base::openmode __mode) 20397403Sobrien { 204132720Skan pos_type __ret = pos_type(off_type(-1)); 205146897Skan const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0; 206146897Skan const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0; 207146897Skan 208146897Skan const char_type* __beg = __testin ? this->eback() : this->pbase(); 209169691Skan if ((__beg || !off_type(__sp)) && (__testin || __testout)) 21097403Sobrien { 211132720Skan _M_update_egptr(); 212132720Skan 213169691Skan const off_type __pos(__sp); 214169691Skan const bool __testpos = (0 <= __pos 215169691Skan && __pos <= this->egptr() - __beg); 216169691Skan if (__testpos) 21797403Sobrien { 218132720Skan if (__testin) 219132720Skan this->gbump((__beg + __pos) - this->gptr()); 220132720Skan if (__testout) 221132720Skan this->pbump((__beg + __pos) - this->pptr()); 222146897Skan __ret = __sp; 22397403Sobrien } 22497403Sobrien } 22597403Sobrien return __ret; 22697403Sobrien } 22797403Sobrien 228169691Skan template <class _CharT, class _Traits, class _Alloc> 229169691Skan void 230169691Skan basic_stringbuf<_CharT, _Traits, _Alloc>:: 231169691Skan _M_sync(char_type* __base, __size_type __i, __size_type __o) 232169691Skan { 233169691Skan const bool __testin = _M_mode & ios_base::in; 234169691Skan const bool __testout = _M_mode & ios_base::out; 235169691Skan char_type* __endg = __base + _M_string.size(); 236169691Skan char_type* __endp = __base + _M_string.capacity(); 237169691Skan 238169691Skan if (__base != _M_string.data()) 239169691Skan { 240169691Skan // setbuf: __i == size of buffer area (_M_string.size() == 0). 241169691Skan __endg += __i; 242169691Skan __i = 0; 243169691Skan __endp = __endg; 244169691Skan } 245169691Skan 246169691Skan if (__testin) 247169691Skan this->setg(__base, __base + __i, __endg); 248169691Skan if (__testout) 249169691Skan { 250169691Skan this->setp(__base, __endp); 251169691Skan this->pbump(__o); 252169691Skan // egptr() always tracks the string end. When !__testin, 253169691Skan // for the correct functioning of the streambuf inlines 254169691Skan // the other get area pointers are identical. 255169691Skan if (!__testin) 256169691Skan this->setg(__endg, __endg, __endg); 257169691Skan } 258169691Skan } 259169691Skan 26097403Sobrien // Inhibit implicit instantiations for required instantiations, 261132720Skan // which are defined via explicit instantiations elsewhere. 26297403Sobrien // NB: This syntax is a GNU extension. 263132720Skan#if _GLIBCXX_EXTERN_TEMPLATE 26497403Sobrien extern template class basic_stringbuf<char>; 265107606Sobrien extern template class basic_istringstream<char>; 266107606Sobrien extern template class basic_ostringstream<char>; 267107606Sobrien extern template class basic_stringstream<char>; 268107606Sobrien 269132720Skan#ifdef _GLIBCXX_USE_WCHAR_T 27097403Sobrien extern template class basic_stringbuf<wchar_t>; 27197403Sobrien extern template class basic_istringstream<wchar_t>; 27297403Sobrien extern template class basic_ostringstream<wchar_t>; 27397403Sobrien extern template class basic_stringstream<wchar_t>; 274107606Sobrien#endif 275132720Skan#endif 27697403Sobrien 277169691Skan_GLIBCXX_END_NAMESPACE 278169691Skan 27997403Sobrien#endif 280