Branch data Line data Source code
1 : : // Streambuf iterators
2 : :
3 : : // Copyright (C) 1997-2013 Free Software Foundation, Inc.
4 : : //
5 : : // This file is part of the GNU ISO C++ Library. This library is free
6 : : // software; you can redistribute it and/or modify it under the
7 : : // terms of the GNU General Public License as published by the
8 : : // Free Software Foundation; either version 3, or (at your option)
9 : : // any later version.
10 : :
11 : : // This library is distributed in the hope that it will be useful,
12 : : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : // GNU General Public License for more details.
15 : :
16 : : // Under Section 7 of GPL version 3, you are granted additional
17 : : // permissions described in the GCC Runtime Library Exception, version
18 : : // 3.1, as published by the Free Software Foundation.
19 : :
20 : : // You should have received a copy of the GNU General Public License and
21 : : // a copy of the GCC Runtime Library Exception along with this program;
22 : : // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 : : // <http://www.gnu.org/licenses/>.
24 : :
25 : : /** @file bits/streambuf_iterator.h
26 : : * This is an internal header file, included by other library headers.
27 : : * Do not attempt to use it directly. @headername{iterator}
28 : : */
29 : :
30 : : #ifndef _STREAMBUF_ITERATOR_H
31 : : #define _STREAMBUF_ITERATOR_H 1
32 : :
33 : : #pragma GCC system_header
34 : :
35 : : #include <streambuf>
36 : : #include <debug/debug.h>
37 : :
38 : : namespace std _GLIBCXX_VISIBILITY(default)
39 : : {
40 : : _GLIBCXX_BEGIN_NAMESPACE_VERSION
41 : :
42 : : /**
43 : : * @addtogroup iterators
44 : : * @{
45 : : */
46 : :
47 : : // 24.5.3 Template class istreambuf_iterator
48 : : /// Provides input iterator semantics for streambufs.
49 : : template<typename _CharT, typename _Traits>
50 : : class istreambuf_iterator
51 : : : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type,
52 : : _CharT*,
53 : : #if __cplusplus >= 201103L
54 : : // LWG 445.
55 : : _CharT>
56 : : #else
57 : : _CharT&>
58 : : #endif
59 : : {
60 : : public:
61 : : // Types:
62 : : //@{
63 : : /// Public typedefs
64 : : typedef _CharT char_type;
65 : : typedef _Traits traits_type;
66 : : typedef typename _Traits::int_type int_type;
67 : : typedef basic_streambuf<_CharT, _Traits> streambuf_type;
68 : : typedef basic_istream<_CharT, _Traits> istream_type;
69 : : //@}
70 : :
71 : : template<typename _CharT2>
72 : : friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
73 : : ostreambuf_iterator<_CharT2> >::__type
74 : : copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
75 : : ostreambuf_iterator<_CharT2>);
76 : :
77 : : template<bool _IsMove, typename _CharT2>
78 : : friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
79 : : _CharT2*>::__type
80 : : __copy_move_a2(istreambuf_iterator<_CharT2>,
81 : : istreambuf_iterator<_CharT2>, _CharT2*);
82 : :
83 : : template<typename _CharT2>
84 : : friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
85 : : istreambuf_iterator<_CharT2> >::__type
86 : : find(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
87 : : const _CharT2&);
88 : :
89 : : private:
90 : : // 24.5.3 istreambuf_iterator
91 : : // p 1
92 : : // If the end of stream is reached (streambuf_type::sgetc()
93 : : // returns traits_type::eof()), the iterator becomes equal to
94 : : // the "end of stream" iterator value.
95 : : // NB: This implementation assumes the "end of stream" value
96 : : // is EOF, or -1.
97 : : mutable streambuf_type* _M_sbuf;
98 : : mutable int_type _M_c;
99 : :
100 : : public:
101 : : /// Construct end of input stream iterator.
102 : 1 : _GLIBCXX_CONSTEXPR istreambuf_iterator() _GLIBCXX_USE_NOEXCEPT
103 : 1 : : _M_sbuf(0), _M_c(traits_type::eof()) { }
104 : :
105 : : #if __cplusplus >= 201103L
106 : : istreambuf_iterator(const istreambuf_iterator&) noexcept = default;
107 : :
108 : : ~istreambuf_iterator() = default;
109 : : #endif
110 : :
111 : : /// Construct start of input stream iterator.
112 : 75 : istreambuf_iterator(istream_type& __s) _GLIBCXX_USE_NOEXCEPT
113 [ + - ][ # # ]: 75 : : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { }
114 : :
115 : : /// Construct start of streambuf iterator.
116 : : istreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
117 : : : _M_sbuf(__s), _M_c(traits_type::eof()) { }
118 : :
119 : : /// Return the current character pointed to by iterator. This returns
120 : : /// streambuf.sgetc(). It cannot be assigned. NB: The result of
121 : : /// operator*() on an end of stream is undefined.
122 : : char_type
123 : 1477324 : operator*() const
124 : : {
125 : : #ifdef _GLIBCXX_DEBUG_PEDANTIC
126 : : // Dereferencing a past-the-end istreambuf_iterator is a
127 : : // libstdc++ extension
128 : : __glibcxx_requires_cond(!_M_at_eof(),
129 : : _M_message(__gnu_debug::__msg_deref_istreambuf)
130 : : ._M_iterator(*this));
131 : : #endif
132 : 1477324 : return traits_type::to_char_type(_M_get());
133 : : }
134 : :
135 : : /// Advance the iterator. Calls streambuf.sbumpc().
136 : : istreambuf_iterator&
137 : 1477308 : operator++()
138 : : {
139 : : __glibcxx_requires_cond(!_M_at_eof(),
140 : : _M_message(__gnu_debug::__msg_inc_istreambuf)
141 : : ._M_iterator(*this));
142 [ + - ]: 1477308 : if (_M_sbuf)
143 : : {
144 : 1477308 : _M_sbuf->sbumpc();
145 : 1477308 : _M_c = traits_type::eof();
146 : : }
147 : 1477308 : return *this;
148 : : }
149 : :
150 : : /// Advance the iterator. Calls streambuf.sbumpc().
151 : : istreambuf_iterator
152 : : operator++(int)
153 : : {
154 : : __glibcxx_requires_cond(!_M_at_eof(),
155 : : _M_message(__gnu_debug::__msg_inc_istreambuf)
156 : : ._M_iterator(*this));
157 : :
158 : : istreambuf_iterator __old = *this;
159 : : if (_M_sbuf)
160 : : {
161 : : __old._M_c = _M_sbuf->sbumpc();
162 : : _M_c = traits_type::eof();
163 : : }
164 : : return __old;
165 : : }
166 : :
167 : : // _GLIBCXX_RESOLVE_LIB_DEFECTS
168 : : // 110 istreambuf_iterator::equal not const
169 : : // NB: there is also number 111 (NAD, Future) pending on this function.
170 : : /// Return true both iterators are end or both are not end.
171 : : bool
172 : 1902782 : equal(const istreambuf_iterator& __b) const
173 : 1902782 : { return _M_at_eof() == __b._M_at_eof(); }
174 : :
175 : : private:
176 : : int_type
177 : 5282888 : _M_get() const
178 : : {
179 : 5282888 : const int_type __eof = traits_type::eof();
180 : 5282888 : int_type __ret = __eof;
181 [ + + ]: 5282888 : if (_M_sbuf)
182 : : {
183 [ + + ]: 3379838 : if (!traits_type::eq_int_type(_M_c, __eof))
184 : 1902455 : __ret = _M_c;
185 [ + - + + ]: 2954766 : else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()),
186 : 1477383 : __eof))
187 : 1477324 : _M_c = __ret;
188 : : else
189 : 3379838 : _M_sbuf = 0;
190 : : }
191 : 5282888 : return __ret;
192 : : }
193 : :
194 : : bool
195 : 3805564 : _M_at_eof() const
196 : : {
197 : 3805564 : const int_type __eof = traits_type::eof();
198 [ + - ]: 3805564 : return traits_type::eq_int_type(_M_get(), __eof);
199 : : }
200 : : };
201 : :
202 : : template<typename _CharT, typename _Traits>
203 : : inline bool
204 : 1902782 : operator==(const istreambuf_iterator<_CharT, _Traits>& __a,
205 : : const istreambuf_iterator<_CharT, _Traits>& __b)
206 : 1902782 : { return __a.equal(__b); }
207 : :
208 : : template<typename _CharT, typename _Traits>
209 : : inline bool
210 : : operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
211 : : const istreambuf_iterator<_CharT, _Traits>& __b)
212 : : { return !__a.equal(__b); }
213 : :
214 : : /// Provides output iterator semantics for streambufs.
215 : : template<typename _CharT, typename _Traits>
216 : : class ostreambuf_iterator
217 : : : public iterator<output_iterator_tag, void, void, void, void>
218 : : {
219 : : public:
220 : : // Types:
221 : : //@{
222 : : /// Public typedefs
223 : : typedef _CharT char_type;
224 : : typedef _Traits traits_type;
225 : : typedef basic_streambuf<_CharT, _Traits> streambuf_type;
226 : : typedef basic_ostream<_CharT, _Traits> ostream_type;
227 : : //@}
228 : :
229 : : template<typename _CharT2>
230 : : friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
231 : : ostreambuf_iterator<_CharT2> >::__type
232 : : copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
233 : : ostreambuf_iterator<_CharT2>);
234 : :
235 : : private:
236 : : streambuf_type* _M_sbuf;
237 : : bool _M_failed;
238 : :
239 : : public:
240 : : /// Construct output iterator from ostream.
241 : : ostreambuf_iterator(ostream_type& __s) _GLIBCXX_USE_NOEXCEPT
242 : : : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
243 : :
244 : : /// Construct output iterator from streambuf.
245 : : ostreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
246 : : : _M_sbuf(__s), _M_failed(!_M_sbuf) { }
247 : :
248 : : /// Write character to streambuf. Calls streambuf.sputc().
249 : : ostreambuf_iterator&
250 : : operator=(_CharT __c)
251 : : {
252 : : if (!_M_failed &&
253 : : _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof()))
254 : : _M_failed = true;
255 : : return *this;
256 : : }
257 : :
258 : : /// Return *this.
259 : : ostreambuf_iterator&
260 : : operator*()
261 : : { return *this; }
262 : :
263 : : /// Return *this.
264 : : ostreambuf_iterator&
265 : : operator++(int)
266 : : { return *this; }
267 : :
268 : : /// Return *this.
269 : : ostreambuf_iterator&
270 : : operator++()
271 : : { return *this; }
272 : :
273 : : /// Return true if previous operator=() failed.
274 : : bool
275 : : failed() const _GLIBCXX_USE_NOEXCEPT
276 : : { return _M_failed; }
277 : :
278 : : ostreambuf_iterator&
279 : : _M_put(const _CharT* __ws, streamsize __len)
280 : : {
281 : : if (__builtin_expect(!_M_failed, true)
282 : : && __builtin_expect(this->_M_sbuf->sputn(__ws, __len) != __len,
283 : : false))
284 : : _M_failed = true;
285 : : return *this;
286 : : }
287 : : };
288 : :
289 : : // Overloads for streambuf iterators.
290 : : template<typename _CharT>
291 : : typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
292 : : ostreambuf_iterator<_CharT> >::__type
293 : : copy(istreambuf_iterator<_CharT> __first,
294 : : istreambuf_iterator<_CharT> __last,
295 : : ostreambuf_iterator<_CharT> __result)
296 : : {
297 : : if (__first._M_sbuf && !__last._M_sbuf && !__result._M_failed)
298 : : {
299 : : bool __ineof;
300 : : __copy_streambufs_eof(__first._M_sbuf, __result._M_sbuf, __ineof);
301 : : if (!__ineof)
302 : : __result._M_failed = true;
303 : : }
304 : : return __result;
305 : : }
306 : :
307 : : template<bool _IsMove, typename _CharT>
308 : : typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
309 : : ostreambuf_iterator<_CharT> >::__type
310 : : __copy_move_a2(_CharT* __first, _CharT* __last,
311 : : ostreambuf_iterator<_CharT> __result)
312 : : {
313 : : const streamsize __num = __last - __first;
314 : : if (__num > 0)
315 : : __result._M_put(__first, __num);
316 : : return __result;
317 : : }
318 : :
319 : : template<bool _IsMove, typename _CharT>
320 : : typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
321 : : ostreambuf_iterator<_CharT> >::__type
322 : : __copy_move_a2(const _CharT* __first, const _CharT* __last,
323 : : ostreambuf_iterator<_CharT> __result)
324 : : {
325 : : const streamsize __num = __last - __first;
326 : : if (__num > 0)
327 : : __result._M_put(__first, __num);
328 : : return __result;
329 : : }
330 : :
331 : : template<bool _IsMove, typename _CharT>
332 : : typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
333 : : _CharT*>::__type
334 : : __copy_move_a2(istreambuf_iterator<_CharT> __first,
335 : : istreambuf_iterator<_CharT> __last, _CharT* __result)
336 : : {
337 : : typedef istreambuf_iterator<_CharT> __is_iterator_type;
338 : : typedef typename __is_iterator_type::traits_type traits_type;
339 : : typedef typename __is_iterator_type::streambuf_type streambuf_type;
340 : : typedef typename traits_type::int_type int_type;
341 : :
342 : : if (__first._M_sbuf && !__last._M_sbuf)
343 : : {
344 : : streambuf_type* __sb = __first._M_sbuf;
345 : : int_type __c = __sb->sgetc();
346 : : while (!traits_type::eq_int_type(__c, traits_type::eof()))
347 : : {
348 : : const streamsize __n = __sb->egptr() - __sb->gptr();
349 : : if (__n > 1)
350 : : {
351 : : traits_type::copy(__result, __sb->gptr(), __n);
352 : : __sb->__safe_gbump(__n);
353 : : __result += __n;
354 : : __c = __sb->underflow();
355 : : }
356 : : else
357 : : {
358 : : *__result++ = traits_type::to_char_type(__c);
359 : : __c = __sb->snextc();
360 : : }
361 : : }
362 : : }
363 : : return __result;
364 : : }
365 : :
366 : : template<typename _CharT>
367 : : typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
368 : : istreambuf_iterator<_CharT> >::__type
369 : : find(istreambuf_iterator<_CharT> __first,
370 : : istreambuf_iterator<_CharT> __last, const _CharT& __val)
371 : : {
372 : : typedef istreambuf_iterator<_CharT> __is_iterator_type;
373 : : typedef typename __is_iterator_type::traits_type traits_type;
374 : : typedef typename __is_iterator_type::streambuf_type streambuf_type;
375 : : typedef typename traits_type::int_type int_type;
376 : :
377 : : if (__first._M_sbuf && !__last._M_sbuf)
378 : : {
379 : : const int_type __ival = traits_type::to_int_type(__val);
380 : : streambuf_type* __sb = __first._M_sbuf;
381 : : int_type __c = __sb->sgetc();
382 : : while (!traits_type::eq_int_type(__c, traits_type::eof())
383 : : && !traits_type::eq_int_type(__c, __ival))
384 : : {
385 : : streamsize __n = __sb->egptr() - __sb->gptr();
386 : : if (__n > 1)
387 : : {
388 : : const _CharT* __p = traits_type::find(__sb->gptr(),
389 : : __n, __val);
390 : : if (__p)
391 : : __n = __p - __sb->gptr();
392 : : __sb->__safe_gbump(__n);
393 : : __c = __sb->sgetc();
394 : : }
395 : : else
396 : : __c = __sb->snextc();
397 : : }
398 : :
399 : : if (!traits_type::eq_int_type(__c, traits_type::eof()))
400 : : __first._M_c = __c;
401 : : else
402 : : __first._M_sbuf = 0;
403 : : }
404 : : return __first;
405 : : }
406 : :
407 : : // @} group iterators
408 : :
409 : : _GLIBCXX_END_NAMESPACE_VERSION
410 : : } // namespace
411 : :
412 : : #endif
|