]>
Commit | Line | Data |
---|---|---|
725dc051 BK |
1 | // Stream buffer classes -*- C++ -*- |
2 | ||
6f48900c BK |
3 | // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 |
4 | // Free Software Foundation, Inc. | |
725dc051 BK |
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 | ||
3b794528 BK |
38 | #pragma GCC system_header |
39 | ||
6f48900c BK |
40 | namespace std |
41 | { | |
d3a193e3 | 42 | template<typename _CharT, typename _Traits> |
49433044 | 43 | const size_t |
d3a193e3 BK |
44 | basic_streambuf<_CharT, _Traits>::_S_pback_size; |
45 | ||
725dc051 | 46 | template<typename _CharT, typename _Traits> |
31bfa177 | 47 | typename basic_streambuf<_CharT, _Traits>::int_type |
725dc051 BK |
48 | basic_streambuf<_CharT, _Traits>:: |
49 | sbumpc() | |
50 | { | |
51 | int_type __ret; | |
52 | if (_M_in_cur && _M_in_cur < _M_in_end) | |
53 | { | |
9a4b4cfc | 54 | char_type __c = *(this->gptr()); |
13187a45 | 55 | _M_in_cur_move(1); |
725dc051 BK |
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> | |
31bfa177 | 64 | typename basic_streambuf<_CharT, _Traits>::int_type |
725dc051 BK |
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 | { | |
13187a45 | 75 | _M_in_cur_move(-1); |
725dc051 BK |
76 | __ret = traits_type::to_int_type(*this->gptr()); |
77 | } | |
78 | return __ret; | |
79 | } | |
80 | ||
81 | template<typename _CharT, typename _Traits> | |
31bfa177 | 82 | typename basic_streambuf<_CharT, _Traits>::int_type |
725dc051 BK |
83 | basic_streambuf<_CharT, _Traits>:: |
84 | sungetc() | |
85 | { | |
86 | int_type __ret; | |
87 | if (_M_in_cur && _M_in_beg < _M_in_cur) | |
88 | { | |
13187a45 | 89 | _M_in_cur_move(-1); |
725dc051 BK |
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> | |
31bfa177 | 103 | typename basic_streambuf<_CharT, _Traits>::int_type |
725dc051 BK |
104 | basic_streambuf<_CharT, _Traits>:: |
105 | sputc(char_type __c) | |
106 | { | |
107 | int_type __ret; | |
13187a45 | 108 | if (_M_out_buf_size()) |
725dc051 BK |
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 | { | |
725dc051 | 124 | streamsize __ret = 0; |
13187a45 | 125 | while (__ret < __n) |
725dc051 | 126 | { |
13187a45 BK |
127 | size_t __buf_len = _M_in_end - _M_in_cur; |
128 | if (__buf_len > 0) | |
725dc051 | 129 | { |
13187a45 BK |
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(); | |
49433044 | 141 | if (!traits_type::eq_int_type(__c, traits_type::eof())) |
5fa9abc3 BK |
142 | { |
143 | traits_type::assign(*__s++, traits_type::to_char_type(__c)); | |
144 | ++__ret; | |
145 | } | |
146 | else | |
13187a45 | 147 | break; |
725dc051 BK |
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; | |
13187a45 | 164 | while (__ret < __n) |
725dc051 | 165 | { |
13187a45 BK |
166 | off_type __buf_len = _M_out_buf_size(); |
167 | if (__buf_len > 0) | |
725dc051 | 168 | { |
13187a45 BK |
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 | { | |
5fa9abc3 | 179 | int_type __c = this->overflow(traits_type::to_int_type(*__s)); |
49433044 | 180 | if (!traits_type::eq_int_type(__c, traits_type::eof())) |
5fa9abc3 BK |
181 | { |
182 | ++__ret; | |
183 | ++__s; | |
184 | } | |
185 | else | |
13187a45 | 186 | break; |
725dc051 BK |
187 | } |
188 | } | |
189 | return __ret; | |
190 | } | |
191 | ||
725dc051 BK |
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 | |
72ed2836 BK |
198 | __copy_streambufs(basic_ios<_CharT, _Traits>& __ios, |
199 | basic_streambuf<_CharT, _Traits>* __sbin, | |
200 | basic_streambuf<_CharT, _Traits>* __sbout) | |
201 | { | |
725dc051 BK |
202 | typedef typename _Traits::int_type int_type; |
203 | ||
204 | streamsize __ret = 0; | |
205 | streamsize __bufsize = __sbin->in_avail(); | |
206 | streamsize __xtrct; | |
725dc051 | 207 | bool __testput = __sbout->_M_mode & ios_base::out; |
6cf5465d BK |
208 | try |
209 | { | |
210 | while (__testput && __bufsize != -1) | |
3279e88a JL |
211 | { |
212 | if (__bufsize != 0 && __sbin->gptr() != NULL) | |
6cf5465d | 213 | { |
3279e88a JL |
214 | __xtrct = __sbout->sputn(__sbin->gptr(), __bufsize); |
215 | __ret += __xtrct; | |
216 | __sbin->_M_in_cur_move(__xtrct); | |
217 | if (__xtrct != __bufsize) | |
6cf5465d | 218 | break; |
6cf5465d | 219 | } |
3279e88a JL |
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 | } | |
6cf5465d BK |
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 | } | |
725dc051 BK |
240 | return __ret; |
241 | } | |
a32e3c09 BK |
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 | extern template class basic_streambuf<wchar_t>; | |
253 | extern template | |
254 | streamsize | |
255 | __copy_streambufs(basic_ios<wchar_t>&, basic_streambuf<wchar_t>*, | |
256 | basic_streambuf<wchar_t>*); | |
725dc051 BK |
257 | } // namespace std |
258 | ||
6f48900c | 259 | #endif |