OSDN Git Service

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