OSDN Git Service

2003-04-27 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / sstream.tcc
1 // String based streams -*- C++ -*-
2
3 // Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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 //
32 // ISO C++ 14882: 27.7  String-based streams
33 //
34
35 #ifndef _CPP_BITS_SSTREAM_TCC
36 #define _CPP_BITS_SSTREAM_TCC   1
37
38 #pragma GCC system_header
39
40 #include <sstream>
41
42 namespace std
43 {
44   template <class _CharT, class _Traits, class _Alloc>
45     typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 
46     basic_stringbuf<_CharT, _Traits, _Alloc>::
47     pbackfail(int_type __c)
48     {
49       int_type __ret = traits_type::eof();
50       const bool __testeof = traits_type::eq_int_type(__c,
51                                                       traits_type::eof());
52       const bool __testpos = this->_M_in_beg < this->_M_in_cur; 
53       
54       // Try to put back __c into input sequence in one of three ways.
55       // Order these tests done in is unspecified by the standard.
56       if (__testpos)
57         {
58           if (traits_type::eq(traits_type::to_char_type(__c),
59                               this->_M_in_cur[-1])
60               && !__testeof)
61             {
62               --this->_M_in_cur;
63               __ret = __c;
64             }
65           else if (!__testeof)
66             {
67               --this->_M_in_cur;
68               *this->_M_in_cur = traits_type::to_char_type(__c);
69               __ret = __c;
70             }
71           else if (__testeof)
72             {
73               --this->_M_in_cur;
74               __ret = traits_type::not_eof(__c);
75             }
76         }
77       return __ret;
78     }
79   
80   template <class _CharT, class _Traits, class _Alloc>
81     typename basic_stringbuf<_CharT, _Traits, _Alloc>::int_type 
82     basic_stringbuf<_CharT, _Traits, _Alloc>::
83     overflow(int_type __c)
84     {
85       const bool __testout = this->_M_mode & ios_base::out;
86       if (__builtin_expect(!__testout, false))
87         return traits_type::eof();
88
89       const bool __testeof = traits_type::eq_int_type(__c,
90                                                       traits_type::eof());
91       if (__builtin_expect(__testeof, false))
92         return traits_type::not_eof(__c);
93
94       // NB: Start ostringstream buffers at 512 chars. This is an
95       // experimental value (pronounced "arbitrary" in some of the
96       // hipper english-speaking countries), and can be changed to
97       // suit particular needs.
98       __size_type __len = std::max(__size_type(_M_string.capacity() + 1),
99                                    __size_type(512));
100       const bool __testput = this->_M_out_cur < this->_M_out_end;
101       if (__builtin_expect(!__testput && __len > _M_string.max_size(), false))
102         return traits_type::eof();
103
104       // Try to append __c into output sequence in one of two ways.
105       // Order these tests done in is unspecified by the standard.
106       if (!__testput)
107         {
108           // Force-allocate, re-sync.
109           _M_string = this->str();
110           // In virtue of DR 169 (TC) we are allowed to grow more than
111           // one char. That's easy to implement thanks to the exponential
112           // growth policy builtin into basic_string.
113           _M_string.reserve(__len);
114           _M_really_sync(const_cast<char_type*>(_M_string.data()),
115                          this->_M_in_cur - this->_M_in_beg, 
116                          this->_M_out_cur - this->_M_out_beg);
117         }
118       return this->sputc(traits_type::to_char_type(__c));
119     }
120
121   template <class _CharT, class _Traits, class _Alloc>
122     typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
123     basic_stringbuf<_CharT, _Traits, _Alloc>::
124     seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
125     {
126       pos_type __ret =  pos_type(off_type(-1)); 
127       bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
128       bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
129       const bool __testboth = __testin && __testout && __way != ios_base::cur;
130       __testin &= !(__mode & ios_base::out);
131       __testout &= !(__mode & ios_base::in);
132
133       if (_M_string.capacity() && (__testin || __testout || __testboth))
134         {
135           char_type* __beg = this->_M_buf;
136           char_type* __curi = NULL;
137           char_type* __curo = NULL;
138           char_type* __endi = NULL;
139           char_type* __endo = NULL;
140
141           if (__testin || __testboth)
142             {
143               __curi = this->_M_in_cur;
144               __endi = this->_M_in_end;
145             }
146           if (__testout || __testboth)
147             {
148               __curo = this->_M_out_cur;
149               // Due to the resolution of DR169, ios_base::end
150               // is this->_M_out_lim, not _M_out_end.
151               __endo = this->_M_out_lim;
152             }
153
154           off_type __newoffi = 0;
155           off_type __newoffo = 0;
156           if (__way == ios_base::cur)
157             {
158               __newoffi = __curi - __beg;
159               __newoffo = __curo - __beg;
160             }
161           else if (__way == ios_base::end)
162             {
163               __newoffi = __endi - __beg;
164               __newoffo = __endo - __beg;
165             }
166
167           if ((__testin || __testboth)
168               && __newoffi + __off >= 0 && __endi - __beg >= __newoffi + __off)
169             {
170               this->_M_in_cur = __beg + __newoffi + __off;
171               __ret = pos_type(__newoffi);
172             }
173           if ((__testout || __testboth)
174               && __newoffo + __off >= 0 && __endo - __beg >= __newoffo + __off)
175             {
176               _M_move_out_cur(__newoffo + __off - (this->_M_out_cur - __beg));
177               __ret = pos_type(__newoffo);
178             }
179         }
180       return __ret;
181     }
182
183   template <class _CharT, class _Traits, class _Alloc>
184     typename basic_stringbuf<_CharT, _Traits, _Alloc>::pos_type
185     basic_stringbuf<_CharT, _Traits, _Alloc>::
186     seekpos(pos_type __sp, ios_base::openmode __mode)
187     {
188       pos_type __ret =  pos_type(off_type(-1)); 
189       
190       if (_M_string.capacity())
191         {
192           off_type __pos = __sp; // Use streamoff operator to do conversion.
193           char_type* __beg = NULL;
194           char_type* __end = NULL;
195           const bool __testin = (ios_base::in & this->_M_mode & __mode) != 0;
196           const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0;
197           
198           // NB: Ordered.
199           bool __testposi = false;
200           bool __testposo = false;
201           if (__testin)
202             {
203               __beg = this->_M_in_beg;
204               __end = this->_M_in_end;
205               if (0 <= __pos && __pos <= __end - __beg)
206                 __testposi = true;
207             }
208           if (__testout)
209             {
210               __beg = this->_M_out_beg;
211               __end = this->_M_out_end;
212               if (0 <= __pos && __pos <= __end - __beg)
213                 __testposo = true;
214             }
215           if (__testposi || __testposo)
216             {
217               if (__testposi)
218                 this->_M_in_cur = this->_M_in_beg + __pos;
219               if (__testposo)
220                 _M_move_out_cur((__pos) - (this->_M_out_cur - __beg));
221               __ret = pos_type(off_type(__pos));
222             }
223         }
224       return __ret;
225     }
226
227   // Inhibit implicit instantiations for required instantiations,
228   // which are defined via explicit instantiations elsewhere.  
229   // NB:  This syntax is a GNU extension.
230   extern template class basic_stringbuf<char>;
231   extern template class basic_istringstream<char>;
232   extern template class basic_ostringstream<char>;
233   extern template class basic_stringstream<char>;
234
235 #ifdef _GLIBCPP_USE_WCHAR_T
236   extern template class basic_stringbuf<wchar_t>;
237   extern template class basic_istringstream<wchar_t>;
238   extern template class basic_ostringstream<wchar_t>;
239   extern template class basic_stringstream<wchar_t>;
240 #endif
241 } // namespace std
242
243 #endif