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