OSDN Git Service

2003-02-13 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / streambuf.tcc
1 // Stream buffer classes -*- C++ -*-
2
3 // Copyright (C) 1997, 1998, 1999, 2000, 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.5  Stream buffers
33 //
34
35 #ifndef _CPP_BITS_STREAMBUF_TCC
36 #define _CPP_BITS_STREAMBUF_TCC 1
37
38 #pragma GCC system_header
39
40 namespace std 
41 {
42   template<typename _CharT, typename _Traits>
43     const size_t
44     basic_streambuf<_CharT, _Traits>::_S_pback_size;
45
46   template<typename _CharT, typename _Traits>
47     typename basic_streambuf<_CharT, _Traits>::int_type
48     basic_streambuf<_CharT, _Traits>::
49     sbumpc()
50     {
51       int_type __ret;
52       if (_M_in_cur && _M_in_cur < _M_in_end)
53         {
54           char_type __c = *(this->gptr());
55           _M_in_cur_move(1);
56           __ret = traits_type::to_int_type(__c);
57         }
58       else 
59         __ret = this->uflow();
60       return __ret;
61     }
62
63   template<typename _CharT, typename _Traits>
64     typename basic_streambuf<_CharT, _Traits>::int_type
65     basic_streambuf<_CharT, _Traits>::
66     sputbackc(char_type __c) 
67     {
68       int_type __ret;
69       bool __testpos = _M_in_cur && _M_in_beg < _M_in_cur;
70       if (!__testpos || !traits_type::eq(__c, this->gptr()[-1]))
71         __ret = this->pbackfail(traits_type::to_int_type(__c));
72       else 
73         {
74           _M_in_cur_move(-1);
75           __ret = traits_type::to_int_type(*this->gptr());
76         }
77       return __ret;
78     }
79   
80   template<typename _CharT, typename _Traits>
81     typename basic_streambuf<_CharT, _Traits>::int_type
82     basic_streambuf<_CharT, _Traits>::
83     sungetc()
84     {
85       int_type __ret;
86       if (_M_in_cur && _M_in_beg < _M_in_cur)
87         {
88           _M_in_cur_move(-1);
89           __ret = traits_type::to_int_type(*_M_in_cur);
90         }
91       else 
92         __ret = this->pbackfail();
93       return __ret;
94     }
95
96   // Don't test against _M_buf + _M_buf_size, because _M_buf reflects
97   // allocated space, and on certain (rare but entirely legal)
98   // situations, there will be no allocated space yet the internal
99   // buffers will still be valid. (This happens if setp is used to set
100   // the internal buffer to say some externally-allocated sequence.)
101   template<typename _CharT, typename _Traits>
102     typename basic_streambuf<_CharT, _Traits>::int_type
103     basic_streambuf<_CharT, _Traits>::
104     sputc(char_type __c)
105     {
106       int_type __ret;
107       if (_M_out_buf_size())
108         {
109           *_M_out_cur = __c;
110           _M_out_cur_move(1);
111           __ret = traits_type::to_int_type(__c);
112         }
113       else
114         __ret = this->overflow(traits_type::to_int_type(__c));
115       return __ret;
116     }
117
118   template<typename _CharT, typename _Traits>
119     streamsize
120     basic_streambuf<_CharT, _Traits>::
121     xsgetn(char_type* __s, streamsize __n)
122     {
123       streamsize __ret = 0;
124       while (__ret < __n)
125         {
126           size_t __buf_len = _M_in_end - _M_in_cur;
127           if (__buf_len > 0)
128             {
129               size_t __remaining = __n - __ret;
130               size_t __len = std::min(__buf_len, __remaining);
131               traits_type::copy(__s, _M_in_cur, __len);
132               __ret += __len;
133               __s += __len;
134               _M_in_cur_move(__len);
135             }
136           
137           if (__ret < __n)
138             {
139               int_type __c = this->uflow();  
140               if (!traits_type::eq_int_type(__c, traits_type::eof()))
141                 {
142                   traits_type::assign(*__s++, traits_type::to_char_type(__c));
143                   ++__ret;
144                 }
145               else
146                 break;
147             }
148         }
149       return __ret;
150     }
151
152   // Don't test against _M_buf + _M_buf_size, because _M_buf reflects
153   // allocated space, and on certain (rare but entirely legal)
154   // situations, there will be no allocated space yet the internal
155   // buffers will still be valid. (This happens if setp is used to set
156   // the internal buffer to say some externally-allocated sequence.)
157   template<typename _CharT, typename _Traits>
158     streamsize
159     basic_streambuf<_CharT, _Traits>::
160     xsputn(const char_type* __s, streamsize __n)
161     {
162       streamsize __ret = 0;
163       while (__ret < __n)
164         {
165           off_type __buf_len = _M_out_buf_size();
166           if (__buf_len > 0)
167             {
168               off_type __remaining = __n - __ret;
169               off_type __len = std::min(__buf_len, __remaining);
170               traits_type::copy(_M_out_cur, __s, __len);
171               __ret += __len;
172               __s += __len;
173               _M_out_cur_move(__len);
174             }
175
176           if (__ret < __n)
177             {
178               int_type __c = this->overflow(traits_type::to_int_type(*__s));
179               if (!traits_type::eq_int_type(__c, traits_type::eof()))
180                 {
181                   ++__ret;
182                   ++__s;
183                 }
184               else
185                 break;
186             }
187         }
188       return __ret;
189     }
190
191   // Conceivably, this could be used to implement buffer-to-buffer
192   // copies, if this was ever desired in an un-ambiguous way by the
193   // standard. If so, then checks for __ios being zero would be
194   // necessary.
195   template<typename _CharT, typename _Traits>
196     streamsize
197     __copy_streambufs(basic_ios<_CharT, _Traits>& __ios,
198                       basic_streambuf<_CharT, _Traits>* __sbin,
199                       basic_streambuf<_CharT, _Traits>* __sbout) 
200   {
201       typedef typename _Traits::int_type        int_type;
202
203       streamsize __ret = 0;
204       streamsize __bufsize = __sbin->in_avail();
205       streamsize __xtrct;
206       try 
207         {
208           while (__bufsize != -1)
209             {
210               if (__bufsize != 0 && __sbin->gptr() != NULL
211                   && __sbin->gptr() + __bufsize <= __sbin->egptr()) 
212                 {
213                   __xtrct = __sbout->sputn(__sbin->gptr(), __bufsize);
214                   __ret += __xtrct;
215                   __sbin->_M_in_cur_move(__xtrct);
216                   if (__xtrct != __bufsize)
217                     break;
218                 }
219               else 
220                 {
221                   size_t __size =
222                     __sbin->_M_buf_size_opt > 0 ? __sbin->_M_buf_size_opt : 1;
223                   _CharT* __buf =
224                     static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __size));
225                   streamsize __charsread = __sbin->sgetn(__buf, __size);
226                   __xtrct = __sbout->sputn(__buf, __charsread);
227                   __ret += __xtrct;
228                   if (__xtrct != __charsread)
229                     break;
230                 }
231               if (_Traits::eq_int_type(__sbin->sgetc(), _Traits::eof()))
232                 break;
233               __bufsize = __sbin->in_avail();
234             }
235         }
236       catch(exception& __fail) 
237         {
238           __ios.setstate(ios_base::failbit);
239           if ((__ios.exceptions() & ios_base::failbit) != 0)
240             __throw_exception_again;
241         }
242       return __ret;
243     }
244
245   // Inhibit implicit instantiations for required instantiations,
246   // which are defined via explicit instantiations elsewhere.  
247   // NB:  This syntax is a GNU extension.
248 #if _GLIBCPP_EXTERN_TEMPLATE
249   extern template class basic_streambuf<char>;
250   extern template
251     streamsize
252     __copy_streambufs(basic_ios<char>&, basic_streambuf<char>*,
253                       basic_streambuf<char>*); 
254
255 #ifdef _GLIBCPP_USE_WCHAR_T
256   extern template class basic_streambuf<wchar_t>;
257   extern template
258     streamsize
259     __copy_streambufs(basic_ios<wchar_t>&, basic_streambuf<wchar_t>*,
260                       basic_streambuf<wchar_t>*); 
261 #endif
262 #endif
263 } // namespace std
264
265 #endif