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