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