100db7afdSDavid E. O'Brien // String based streams -*- C++ -*-
200db7afdSDavid E. O'Brien 
3*f8a1b7d9SAlexander Kabaev // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
400db7afdSDavid E. O'Brien // Free Software Foundation, Inc.
500db7afdSDavid E. O'Brien //
600db7afdSDavid E. O'Brien // This file is part of the GNU ISO C++ Library.  This library is free
700db7afdSDavid E. O'Brien // software; you can redistribute it and/or modify it under the
800db7afdSDavid E. O'Brien // terms of the GNU General Public License as published by the
900db7afdSDavid E. O'Brien // Free Software Foundation; either version 2, or (at your option)
1000db7afdSDavid E. O'Brien // any later version.
1100db7afdSDavid E. O'Brien 
1200db7afdSDavid E. O'Brien // This library is distributed in the hope that it will be useful,
1300db7afdSDavid E. O'Brien // but WITHOUT ANY WARRANTY; without even the implied warranty of
1400db7afdSDavid E. O'Brien // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1500db7afdSDavid E. O'Brien // GNU General Public License for more details.
1600db7afdSDavid E. O'Brien 
1700db7afdSDavid E. O'Brien // You should have received a copy of the GNU General Public License along
1800db7afdSDavid E. O'Brien // with this library; see the file COPYING.  If not, write to the Free
19*f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
2000db7afdSDavid E. O'Brien // USA.
2100db7afdSDavid E. O'Brien 
2200db7afdSDavid E. O'Brien // As a special exception, you may use this file as part of a free software
2300db7afdSDavid E. O'Brien // library without restriction.  Specifically, if other files instantiate
2400db7afdSDavid E. O'Brien // templates or use macros or inline functions from this file, or you compile
2500db7afdSDavid E. O'Brien // this file and link it with other files to produce an executable, this
2600db7afdSDavid E. O'Brien // file does not by itself cause the resulting executable to be covered by
2700db7afdSDavid E. O'Brien // the GNU General Public License.  This exception does not however
2800db7afdSDavid E. O'Brien // invalidate any other reasons why the executable file might be covered by
2900db7afdSDavid E. O'Brien // the GNU General Public License.
3000db7afdSDavid E. O'Brien 
31*f8a1b7d9SAlexander Kabaev /** @file sstream.tcc
32*f8a1b7d9SAlexander Kabaev  *  This is an internal header file, included by other library headers.
33*f8a1b7d9SAlexander Kabaev  *  You should not attempt to use it directly.
34*f8a1b7d9SAlexander Kabaev  */
35*f8a1b7d9SAlexander Kabaev 
3600db7afdSDavid E. O'Brien //
3700db7afdSDavid E. O'Brien // ISO C++ 14882: 27.7  String-based streams
3800db7afdSDavid E. O'Brien //
3900db7afdSDavid E. O'Brien 
40ffeaf689SAlexander Kabaev #ifndef _SSTREAM_TCC
41ffeaf689SAlexander Kabaev #define _SSTREAM_TCC 1
4200db7afdSDavid E. O'Brien 
4300db7afdSDavid E. O'Brien #pragma GCC system_header
4400db7afdSDavid E. O'Brien 
4500db7afdSDavid E. O'Brien #include <sstream>
4600db7afdSDavid E. O'Brien 
_GLIBCXX_BEGIN_NAMESPACE(std)47*f8a1b7d9SAlexander Kabaev _GLIBCXX_BEGIN_NAMESPACE(std)
48*f8a1b7d9SAlexander Kabaev 
4900db7afdSDavid E. O'Brien   template <class _CharT, class _Traits, class _Alloc>
5000db7afdSDavid E. O'Brien     typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type
5100db7afdSDavid E. O'Brien     basic_stringbuf<_CharT, _Traits, _Alloc>::
5200db7afdSDavid E. O'Brien     pbackfail(int_type __c)
5300db7afdSDavid E. O'Brien     {
5400db7afdSDavid E. O'Brien       int_type __ret = traits_type::eof();
55ffeaf689SAlexander Kabaev       if (this->eback() < this->gptr())
56ffeaf689SAlexander Kabaev 	{
5700db7afdSDavid E. O'Brien 	  // Try to put back __c into input sequence in one of three ways.
5800db7afdSDavid E. O'Brien 	  // Order these tests done in is unspecified by the standard.
59*f8a1b7d9SAlexander Kabaev 	  const bool __testeof = traits_type::eq_int_type(__c, __ret);
60*f8a1b7d9SAlexander Kabaev 	  if (!__testeof)
61ffeaf689SAlexander Kabaev 	    {
62*f8a1b7d9SAlexander Kabaev 	      const bool __testeq = traits_type::eq(traits_type::
63*f8a1b7d9SAlexander Kabaev 						    to_char_type(__c),
64*f8a1b7d9SAlexander Kabaev 						    this->gptr()[-1]);
65*f8a1b7d9SAlexander Kabaev 	      const bool __testout = this->_M_mode & ios_base::out;
66*f8a1b7d9SAlexander Kabaev 	      if (__testeq || __testout)
67*f8a1b7d9SAlexander Kabaev 		{
68*f8a1b7d9SAlexander Kabaev 		  this->gbump(-1);
69*f8a1b7d9SAlexander Kabaev 		  if (!__testeq)
70ffeaf689SAlexander Kabaev 		    *this->gptr() = traits_type::to_char_type(__c);
71ffeaf689SAlexander Kabaev 		  __ret = __c;
7200db7afdSDavid E. O'Brien 		}
7300db7afdSDavid E. O'Brien 	    }
74*f8a1b7d9SAlexander Kabaev 	  else
75*f8a1b7d9SAlexander Kabaev 	    {
76*f8a1b7d9SAlexander Kabaev 	      this->gbump(-1);
77*f8a1b7d9SAlexander Kabaev 	      __ret = traits_type::not_eof(__c);
78*f8a1b7d9SAlexander Kabaev 	    }
79*f8a1b7d9SAlexander Kabaev 	}
8000db7afdSDavid E. O'Brien       return __ret;
8100db7afdSDavid E. O'Brien     }
8200db7afdSDavid E. O'Brien 
8300db7afdSDavid E. O'Brien   template <class _CharT, class _Traits, class _Alloc>
8400db7afdSDavid E. O'Brien     typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type
8500db7afdSDavid E. O'Brien     basic_stringbuf<_CharT, _Traits, _Alloc>::
overflow(int_type __c)8600db7afdSDavid E. O'Brien     overflow(int_type __c)
8700db7afdSDavid E. O'Brien     {
88ffeaf689SAlexander Kabaev       const bool __testout = this->_M_mode & ios_base::out;
89ffeaf689SAlexander Kabaev       if (__builtin_expect(!__testout, false))
90ffeaf689SAlexander Kabaev 	return traits_type::eof();
91ffeaf689SAlexander Kabaev 
92ffeaf689SAlexander Kabaev       const bool __testeof = traits_type::eq_int_type(__c, traits_type::eof());
93ffeaf689SAlexander Kabaev       if (__builtin_expect(__testeof, false))
94ffeaf689SAlexander Kabaev 	return traits_type::not_eof(__c);
95ffeaf689SAlexander Kabaev 
96ffeaf689SAlexander Kabaev       const __size_type __capacity = _M_string.capacity();
97ffeaf689SAlexander Kabaev       const __size_type __max_size = _M_string.max_size();
98ffeaf689SAlexander Kabaev       const bool __testput = this->pptr() < this->epptr();
99ffeaf689SAlexander Kabaev       if (__builtin_expect(!__testput && __capacity == __max_size, false))
100ffeaf689SAlexander Kabaev 	return traits_type::eof();
10100db7afdSDavid E. O'Brien 
10200db7afdSDavid E. O'Brien       // Try to append __c into output sequence in one of two ways.
10300db7afdSDavid E. O'Brien       // Order these tests done in is unspecified by the standard.
104*f8a1b7d9SAlexander Kabaev       const char_type __conv = traits_type::to_char_type(__c);
105ffeaf689SAlexander Kabaev       if (!__testput)
10600db7afdSDavid E. O'Brien 	{
107ffeaf689SAlexander Kabaev 	  // NB: Start ostringstream buffers at 512 chars.  This is an
108ffeaf689SAlexander Kabaev 	  // experimental value (pronounced "arbitrary" in some of the
109ffeaf689SAlexander Kabaev 	  // hipper english-speaking countries), and can be changed to
110ffeaf689SAlexander Kabaev 	  // suit particular needs.
111*f8a1b7d9SAlexander Kabaev 	  //
112*f8a1b7d9SAlexander Kabaev 	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
113*f8a1b7d9SAlexander Kabaev 	  // 169. Bad efficiency of overflow() mandated
114*f8a1b7d9SAlexander Kabaev 	  // 432. stringbuf::overflow() makes only one write position
115*f8a1b7d9SAlexander Kabaev 	  //      available
116ffeaf689SAlexander Kabaev 	  const __size_type __opt_len = std::max(__size_type(2 * __capacity),
117ffeaf689SAlexander Kabaev 						 __size_type(512));
118ffeaf689SAlexander Kabaev 	  const __size_type __len = std::min(__opt_len, __max_size);
119ffeaf689SAlexander Kabaev 	  __string_type __tmp;
120ffeaf689SAlexander Kabaev 	  __tmp.reserve(__len);
121*f8a1b7d9SAlexander Kabaev 	  if (this->pbase())
122*f8a1b7d9SAlexander Kabaev 	    __tmp.assign(this->pbase(), this->epptr() - this->pbase());
123*f8a1b7d9SAlexander Kabaev 	  __tmp.push_back(__conv);
124ffeaf689SAlexander Kabaev 	  _M_string.swap(__tmp);
125ffeaf689SAlexander Kabaev 	  _M_sync(const_cast<char_type*>(_M_string.data()),
126ffeaf689SAlexander Kabaev 		  this->gptr() - this->eback(), this->pptr() - this->pbase());
127ffeaf689SAlexander Kabaev 	}
128*f8a1b7d9SAlexander Kabaev       else
129*f8a1b7d9SAlexander Kabaev 	*this->pptr() = __conv;
130*f8a1b7d9SAlexander Kabaev       this->pbump(1);
131*f8a1b7d9SAlexander Kabaev       return __c;
132ffeaf689SAlexander Kabaev     }
13300db7afdSDavid E. O'Brien 
134ffeaf689SAlexander Kabaev   template <class _CharT, class _Traits, class _Alloc>
135ffeaf689SAlexander Kabaev     typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type
136ffeaf689SAlexander Kabaev     basic_stringbuf<_CharT, _Traits, _Alloc>::
underflow()137ffeaf689SAlexander Kabaev     underflow()
13800db7afdSDavid E. O'Brien     {
139ffeaf689SAlexander Kabaev       int_type __ret = traits_type::eof();
140ffeaf689SAlexander Kabaev       const bool __testin = this->_M_mode & ios_base::in;
141ffeaf689SAlexander Kabaev       if (__testin)
142ffeaf689SAlexander Kabaev 	{
143ffeaf689SAlexander Kabaev 	  // Update egptr() to match the actual string end.
144ffeaf689SAlexander Kabaev 	  _M_update_egptr();
145f260e61bSAlexander Kabaev 
146ffeaf689SAlexander Kabaev 	  if (this->gptr() < this->egptr())
147ffeaf689SAlexander Kabaev 	    __ret = traits_type::to_int_type(*this->gptr());
14800db7afdSDavid E. O'Brien 	}
14900db7afdSDavid E. O'Brien       return __ret;
15000db7afdSDavid E. O'Brien     }
15100db7afdSDavid E. O'Brien 
15200db7afdSDavid E. O'Brien   template <class _CharT, class _Traits, class _Alloc>
15300db7afdSDavid E. O'Brien     typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
15400db7afdSDavid E. O'Brien     basic_stringbuf<_CharT, _Traits, _Alloc>::
seekoff(off_type __off,ios_base::seekdir __way,ios_base::openmode __mode)15500db7afdSDavid E. O'Brien     seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
15600db7afdSDavid E. O'Brien     {
15700db7afdSDavid E. O'Brien       pos_type __ret =  pos_type(off_type(-1));
158ffeaf689SAlexander Kabaev       bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
159ffeaf689SAlexander Kabaev       bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
160ffeaf689SAlexander Kabaev       const bool __testboth = __testin && __testout && __way != ios_base::cur;
16100db7afdSDavid E. O'Brien       __testin &= !(__mode & ios_base::out);
16200db7afdSDavid E. O'Brien       __testout &= !(__mode & ios_base::in);
16300db7afdSDavid E. O'Brien 
164f260e61bSAlexander Kabaev       // _GLIBCXX_RESOLVE_LIB_DEFECTS
165f260e61bSAlexander Kabaev       // 453. basic_stringbuf::seekoff need not always fail for an empty stream.
166f260e61bSAlexander Kabaev       const char_type* __beg = __testin ? this->eback() : this->pbase();
167f260e61bSAlexander Kabaev       if ((__beg || !__off) && (__testin || __testout || __testboth))
16800db7afdSDavid E. O'Brien 	{
169ffeaf689SAlexander Kabaev 	  _M_update_egptr();
17000db7afdSDavid E. O'Brien 
171*f8a1b7d9SAlexander Kabaev 	  off_type __newoffi = __off;
172*f8a1b7d9SAlexander Kabaev 	  off_type __newoffo = __newoffi;
17300db7afdSDavid E. O'Brien 	  if (__way == ios_base::cur)
17400db7afdSDavid E. O'Brien 	    {
175*f8a1b7d9SAlexander Kabaev 	      __newoffi += this->gptr() - __beg;
176*f8a1b7d9SAlexander Kabaev 	      __newoffo += this->pptr() - __beg;
17700db7afdSDavid E. O'Brien 	    }
17800db7afdSDavid E. O'Brien 	  else if (__way == ios_base::end)
179*f8a1b7d9SAlexander Kabaev 	    __newoffo = __newoffi += this->egptr() - __beg;
18000db7afdSDavid E. O'Brien 
18100db7afdSDavid E. O'Brien 	  if ((__testin || __testboth)
182*f8a1b7d9SAlexander Kabaev 	      && __newoffi >= 0
183*f8a1b7d9SAlexander Kabaev 	      && this->egptr() - __beg >= __newoffi)
18400db7afdSDavid E. O'Brien 	    {
185*f8a1b7d9SAlexander Kabaev 	      this->gbump((__beg + __newoffi) - this->gptr());
18600db7afdSDavid E. O'Brien 	      __ret = pos_type(__newoffi);
18700db7afdSDavid E. O'Brien 	    }
18800db7afdSDavid E. O'Brien 	  if ((__testout || __testboth)
189*f8a1b7d9SAlexander Kabaev 	      && __newoffo >= 0
190*f8a1b7d9SAlexander Kabaev 	      && this->egptr() - __beg >= __newoffo)
19100db7afdSDavid E. O'Brien 	    {
192*f8a1b7d9SAlexander Kabaev 	      this->pbump((__beg + __newoffo) - this->pptr());
19300db7afdSDavid E. O'Brien 	      __ret = pos_type(__newoffo);
19400db7afdSDavid E. O'Brien 	    }
19500db7afdSDavid E. O'Brien 	}
19600db7afdSDavid E. O'Brien       return __ret;
19700db7afdSDavid E. O'Brien     }
19800db7afdSDavid E. O'Brien 
19900db7afdSDavid E. O'Brien   template <class _CharT, class _Traits, class _Alloc>
20000db7afdSDavid E. O'Brien     typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
20100db7afdSDavid E. O'Brien     basic_stringbuf<_CharT, _Traits, _Alloc>::
seekpos(pos_type __sp,ios_base::openmode __mode)20200db7afdSDavid E. O'Brien     seekpos(pos_type __sp, ios_base::openmode __mode)
20300db7afdSDavid E. O'Brien     {
20400db7afdSDavid E. O'Brien       pos_type __ret =  pos_type(off_type(-1));
205ffeaf689SAlexander Kabaev       const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
206ffeaf689SAlexander Kabaev       const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
20700db7afdSDavid E. O'Brien 
208f260e61bSAlexander Kabaev       const char_type* __beg = __testin ? this->eback() : this->pbase();
209*f8a1b7d9SAlexander Kabaev       if ((__beg || !off_type(__sp)) && (__testin || __testout))
210f260e61bSAlexander Kabaev 	{
211ffeaf689SAlexander Kabaev 	  _M_update_egptr();
21200db7afdSDavid E. O'Brien 
213*f8a1b7d9SAlexander Kabaev 	  const off_type __pos(__sp);
214*f8a1b7d9SAlexander Kabaev 	  const bool __testpos = (0 <= __pos
215*f8a1b7d9SAlexander Kabaev 				  && __pos <= this->egptr() - __beg);
216*f8a1b7d9SAlexander Kabaev 	  if (__testpos)
21700db7afdSDavid E. O'Brien 	    {
218ffeaf689SAlexander Kabaev 	      if (__testin)
219ffeaf689SAlexander Kabaev 		this->gbump((__beg + __pos) - this->gptr());
220ffeaf689SAlexander Kabaev 	      if (__testout)
221ffeaf689SAlexander Kabaev                 this->pbump((__beg + __pos) - this->pptr());
222f260e61bSAlexander Kabaev 	      __ret = __sp;
22300db7afdSDavid E. O'Brien 	    }
22400db7afdSDavid E. O'Brien 	}
22500db7afdSDavid E. O'Brien       return __ret;
22600db7afdSDavid E. O'Brien     }
22700db7afdSDavid E. O'Brien 
228*f8a1b7d9SAlexander Kabaev   template <class _CharT, class _Traits, class _Alloc>
229*f8a1b7d9SAlexander Kabaev     void
230*f8a1b7d9SAlexander Kabaev     basic_stringbuf<_CharT, _Traits, _Alloc>::
_M_sync(char_type * __base,__size_type __i,__size_type __o)231*f8a1b7d9SAlexander Kabaev     _M_sync(char_type* __base, __size_type __i, __size_type __o)
232*f8a1b7d9SAlexander Kabaev     {
233*f8a1b7d9SAlexander Kabaev       const bool __testin = _M_mode & ios_base::in;
234*f8a1b7d9SAlexander Kabaev       const bool __testout = _M_mode & ios_base::out;
235*f8a1b7d9SAlexander Kabaev       char_type* __endg = __base + _M_string.size();
236*f8a1b7d9SAlexander Kabaev       char_type* __endp = __base + _M_string.capacity();
237*f8a1b7d9SAlexander Kabaev 
238*f8a1b7d9SAlexander Kabaev       if (__base != _M_string.data())
239*f8a1b7d9SAlexander Kabaev 	{
240*f8a1b7d9SAlexander Kabaev 	  // setbuf: __i == size of buffer area (_M_string.size() == 0).
241*f8a1b7d9SAlexander Kabaev 	  __endg += __i;
242*f8a1b7d9SAlexander Kabaev 	  __i = 0;
243*f8a1b7d9SAlexander Kabaev 	  __endp = __endg;
244*f8a1b7d9SAlexander Kabaev 	}
245*f8a1b7d9SAlexander Kabaev 
246*f8a1b7d9SAlexander Kabaev       if (__testin)
247*f8a1b7d9SAlexander Kabaev 	this->setg(__base, __base + __i, __endg);
248*f8a1b7d9SAlexander Kabaev       if (__testout)
249*f8a1b7d9SAlexander Kabaev 	{
250*f8a1b7d9SAlexander Kabaev 	  this->setp(__base, __endp);
251*f8a1b7d9SAlexander Kabaev 	  this->pbump(__o);
252*f8a1b7d9SAlexander Kabaev 	  // egptr() always tracks the string end.  When !__testin,
253*f8a1b7d9SAlexander Kabaev 	  // for the correct functioning of the streambuf inlines
254*f8a1b7d9SAlexander Kabaev 	  // the other get area pointers are identical.
255*f8a1b7d9SAlexander Kabaev 	  if (!__testin)
256*f8a1b7d9SAlexander Kabaev 	    this->setg(__endg, __endg, __endg);
257*f8a1b7d9SAlexander Kabaev 	}
258*f8a1b7d9SAlexander Kabaev     }
259*f8a1b7d9SAlexander Kabaev 
26000db7afdSDavid E. O'Brien   // Inhibit implicit instantiations for required instantiations,
26100db7afdSDavid E. O'Brien   // which are defined via explicit instantiations elsewhere.
26200db7afdSDavid E. O'Brien   // NB:  This syntax is a GNU extension.
263ffeaf689SAlexander Kabaev #if _GLIBCXX_EXTERN_TEMPLATE
26400db7afdSDavid E. O'Brien   extern template class basic_stringbuf<char>;
26500db7afdSDavid E. O'Brien   extern template class basic_istringstream<char>;
26600db7afdSDavid E. O'Brien   extern template class basic_ostringstream<char>;
26700db7afdSDavid E. O'Brien   extern template class basic_stringstream<char>;
2688f1134fbSDavid E. O'Brien 
269ffeaf689SAlexander Kabaev #ifdef _GLIBCXX_USE_WCHAR_T
2708f1134fbSDavid E. O'Brien   extern template class basic_stringbuf<wchar_t>;
2718f1134fbSDavid E. O'Brien   extern template class basic_istringstream<wchar_t>;
2728f1134fbSDavid E. O'Brien   extern template class basic_ostringstream<wchar_t>;
27300db7afdSDavid E. O'Brien   extern template class basic_stringstream<wchar_t>;
2748f1134fbSDavid E. O'Brien #endif
275ffeaf689SAlexander Kabaev #endif
276*f8a1b7d9SAlexander Kabaev 
277*f8a1b7d9SAlexander Kabaev _GLIBCXX_END_NAMESPACE
27800db7afdSDavid E. O'Brien 
27900db7afdSDavid E. O'Brien #endif
280