libstdc++
streambuf_iterator.h
Go to the documentation of this file.
1 // Streambuf iterators
2 
3 // Copyright (C) 1997-2022 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 // Ignore warnings about std::iterator.
48 #pragma GCC diagnostic push
49 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
50  // 24.5.3 Template class istreambuf_iterator
51  /// Provides input iterator semantics for streambufs.
52  template<typename _CharT, typename _Traits>
54  : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type,
55  _CharT*, _CharT>
56  {
57  public:
58  // Types:
59  ///@{
60  /// Public typedefs
61 #if __cplusplus < 201103L
62  typedef _CharT& reference; // Changed to _CharT by LWG 445
63 #elif __cplusplus > 201703L
64  // _GLIBCXX_RESOLVE_LIB_DEFECTS
65  // 3188. istreambuf_iterator::pointer should not be unspecified
66  using pointer = void;
67 #endif
68 
69  typedef _CharT char_type;
70  typedef _Traits traits_type;
71  typedef typename _Traits::int_type int_type;
74  ///@}
75 
76  template<typename _CharT2>
77  friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
81 
82  template<bool _IsMove, typename _CharT2>
83  friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
84  _CharT2*>::__type
85  __copy_move_a2(istreambuf_iterator<_CharT2>,
87 
88  template<typename _CharT2, typename _Size>
89  friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
90  _CharT2*>::__type
91  __copy_n_a(istreambuf_iterator<_CharT2>, _Size, _CharT2*, bool);
92 
93  template<typename _CharT2>
94  friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
97  const _CharT2&);
98 
99  template<typename _CharT2, typename _Distance>
100  friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
101  void>::__type
102  advance(istreambuf_iterator<_CharT2>&, _Distance);
103 
104  private:
105  // 24.5.3 istreambuf_iterator
106  // p 1
107  // If the end of stream is reached (streambuf_type::sgetc()
108  // returns traits_type::eof()), the iterator becomes equal to
109  // the "end of stream" iterator value.
110  // NB: This implementation assumes the "end of stream" value
111  // is EOF, or -1.
112  mutable streambuf_type* _M_sbuf;
113  int_type _M_c;
114 
115  public:
116  /// Construct end of input stream iterator.
117  _GLIBCXX_CONSTEXPR istreambuf_iterator() _GLIBCXX_USE_NOEXCEPT
118  : _M_sbuf(0), _M_c(traits_type::eof()) { }
119 
120 #if __cplusplus > 201703L && __cpp_lib_concepts
121  constexpr istreambuf_iterator(default_sentinel_t) noexcept
122  : istreambuf_iterator() { }
123 #endif
124 
125 #if __cplusplus >= 201103L
126  istreambuf_iterator(const istreambuf_iterator&) noexcept = default;
127 
128  ~istreambuf_iterator() = default;
129 #endif
130 
131  /// Construct start of input stream iterator.
132  istreambuf_iterator(istream_type& __s) _GLIBCXX_USE_NOEXCEPT
133  : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { }
134 
135  /// Construct start of streambuf iterator.
136  istreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
137  : _M_sbuf(__s), _M_c(traits_type::eof()) { }
138 
139 #if __cplusplus >= 201103L
141  operator=(const istreambuf_iterator&) noexcept = default;
142 #endif
143 
144  /// Return the current character pointed to by iterator. This returns
145  /// streambuf.sgetc(). It cannot be assigned. NB: The result of
146  /// operator*() on an end of stream is undefined.
147  _GLIBCXX_NODISCARD
148  char_type
149  operator*() const
150  {
151  int_type __c = _M_get();
152 
153 #ifdef _GLIBCXX_DEBUG_PEDANTIC
154  // Dereferencing a past-the-end istreambuf_iterator is a
155  // libstdc++ extension
156  __glibcxx_requires_cond(!_S_is_eof(__c),
157  _M_message(__gnu_debug::__msg_deref_istreambuf)
158  ._M_iterator(*this));
159 #endif
160  return traits_type::to_char_type(__c);
161  }
162 
163  /// Advance the iterator. Calls streambuf.sbumpc().
166  {
167  __glibcxx_requires_cond(_M_sbuf &&
168  (!_S_is_eof(_M_c) || !_S_is_eof(_M_sbuf->sgetc())),
169  _M_message(__gnu_debug::__msg_inc_istreambuf)
170  ._M_iterator(*this));
171 
172  _M_sbuf->sbumpc();
173  _M_c = traits_type::eof();
174  return *this;
175  }
176 
177  /// Advance the iterator. Calls streambuf.sbumpc().
180  {
181  __glibcxx_requires_cond(_M_sbuf &&
182  (!_S_is_eof(_M_c) || !_S_is_eof(_M_sbuf->sgetc())),
183  _M_message(__gnu_debug::__msg_inc_istreambuf)
184  ._M_iterator(*this));
185 
186  istreambuf_iterator __old = *this;
187  __old._M_c = _M_sbuf->sbumpc();
188  _M_c = traits_type::eof();
189  return __old;
190  }
191 
192  // _GLIBCXX_RESOLVE_LIB_DEFECTS
193  // 110 istreambuf_iterator::equal not const
194  // NB: there is also number 111 (NAD) relevant to this function.
195  /// Return true both iterators are end or both are not end.
196  _GLIBCXX_NODISCARD
197  bool
198  equal(const istreambuf_iterator& __b) const
199  { return _M_at_eof() == __b._M_at_eof(); }
200 
201  private:
202  int_type
203  _M_get() const
204  {
205  int_type __ret = _M_c;
206  if (_M_sbuf && _S_is_eof(__ret) && _S_is_eof(__ret = _M_sbuf->sgetc()))
207  _M_sbuf = 0;
208  return __ret;
209  }
210 
211  bool
212  _M_at_eof() const
213  { return _S_is_eof(_M_get()); }
214 
215  static bool
216  _S_is_eof(int_type __c)
217  {
218  const int_type __eof = traits_type::eof();
219  return traits_type::eq_int_type(__c, __eof);
220  }
221 
222 #if __cplusplus > 201703L && __cpp_lib_concepts
223  [[nodiscard]]
224  friend bool
225  operator==(const istreambuf_iterator& __i, default_sentinel_t __s)
226  { return __i._M_at_eof(); }
227 #endif
228  };
229 
230  template<typename _CharT, typename _Traits>
231  _GLIBCXX_NODISCARD
232  inline bool
233  operator==(const istreambuf_iterator<_CharT, _Traits>& __a,
234  const istreambuf_iterator<_CharT, _Traits>& __b)
235  { return __a.equal(__b); }
236 
237 #if __cpp_impl_three_way_comparison < 201907L
238  template<typename _CharT, typename _Traits>
239  _GLIBCXX_NODISCARD
240  inline bool
241  operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
242  const istreambuf_iterator<_CharT, _Traits>& __b)
243  { return !__a.equal(__b); }
244 #endif
245 
246  /// Provides output iterator semantics for streambufs.
247  template<typename _CharT, typename _Traits>
249  : public iterator<output_iterator_tag, void, void, void, void>
250  {
251  public:
252  // Types:
253  ///@{
254  /// Public typedefs
255 #if __cplusplus > 201703L
256  using difference_type = ptrdiff_t;
257 #endif
258  typedef _CharT char_type;
259  typedef _Traits traits_type;
262  ///@}
263 
264  template<typename _CharT2>
265  friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
269 
270  private:
271  streambuf_type* _M_sbuf;
272  bool _M_failed;
273 
274  public:
275 
276 #if __cplusplus > 201703L
277  constexpr
278  ostreambuf_iterator() noexcept
279  : _M_sbuf(nullptr), _M_failed(true) { }
280 #endif
281 
282  /// Construct output iterator from ostream.
283  ostreambuf_iterator(ostream_type& __s) _GLIBCXX_USE_NOEXCEPT
284  : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
285 
286  /// Construct output iterator from streambuf.
287  ostreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
288  : _M_sbuf(__s), _M_failed(!_M_sbuf) { }
289 
290  /// Write character to streambuf. Calls streambuf.sputc().
292  operator=(_CharT __c)
293  {
294  if (!_M_failed &&
295  _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof()))
296  _M_failed = true;
297  return *this;
298  }
299 
300  /// Return *this.
301  _GLIBCXX_NODISCARD
304  { return *this; }
305 
306  /// Return *this.
309  { return *this; }
310 
311  /// Return *this.
314  { return *this; }
315 
316  /// Return true if previous operator=() failed.
317  _GLIBCXX_NODISCARD
318  bool
319  failed() const _GLIBCXX_USE_NOEXCEPT
320  { return _M_failed; }
321 
323  _M_put(const _CharT* __ws, streamsize __len)
324  {
325  if (__builtin_expect(!_M_failed, true)
326  && __builtin_expect(this->_M_sbuf->sputn(__ws, __len) != __len,
327  false))
328  _M_failed = true;
329  return *this;
330  }
331  };
332 #pragma GCC diagnostic pop
333 
334  // Overloads for streambuf iterators.
335  template<typename _CharT>
336  typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
337  ostreambuf_iterator<_CharT> >::__type
338  copy(istreambuf_iterator<_CharT> __first,
339  istreambuf_iterator<_CharT> __last,
340  ostreambuf_iterator<_CharT> __result)
341  {
342  if (__first._M_sbuf && !__last._M_sbuf && !__result._M_failed)
343  {
344  bool __ineof;
345  __copy_streambufs_eof(__first._M_sbuf, __result._M_sbuf, __ineof);
346  if (!__ineof)
347  __result._M_failed = true;
348  }
349  return __result;
350  }
351 
352  template<bool _IsMove, typename _CharT>
353  typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
354  ostreambuf_iterator<_CharT> >::__type
355  __copy_move_a2(_CharT* __first, _CharT* __last,
356  ostreambuf_iterator<_CharT> __result)
357  {
358  const streamsize __num = __last - __first;
359  if (__num > 0)
360  __result._M_put(__first, __num);
361  return __result;
362  }
363 
364  template<bool _IsMove, typename _CharT>
365  typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
366  ostreambuf_iterator<_CharT> >::__type
367  __copy_move_a2(const _CharT* __first, const _CharT* __last,
368  ostreambuf_iterator<_CharT> __result)
369  {
370  const streamsize __num = __last - __first;
371  if (__num > 0)
372  __result._M_put(__first, __num);
373  return __result;
374  }
375 
376  template<bool _IsMove, typename _CharT>
377  typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
378  _CharT*>::__type
379  __copy_move_a2(istreambuf_iterator<_CharT> __first,
380  istreambuf_iterator<_CharT> __last, _CharT* __result)
381  {
382  typedef istreambuf_iterator<_CharT> __is_iterator_type;
383  typedef typename __is_iterator_type::traits_type traits_type;
384  typedef typename __is_iterator_type::streambuf_type streambuf_type;
385  typedef typename traits_type::int_type int_type;
386 
387  if (__first._M_sbuf && !__last._M_sbuf)
388  {
389  streambuf_type* __sb = __first._M_sbuf;
390  int_type __c = __sb->sgetc();
391  while (!traits_type::eq_int_type(__c, traits_type::eof()))
392  {
393  const streamsize __n = __sb->egptr() - __sb->gptr();
394  if (__n > 1)
395  {
396  traits_type::copy(__result, __sb->gptr(), __n);
397  __sb->__safe_gbump(__n);
398  __result += __n;
399  __c = __sb->underflow();
400  }
401  else
402  {
403  *__result++ = traits_type::to_char_type(__c);
404  __c = __sb->snextc();
405  }
406  }
407  }
408  return __result;
409  }
410 
411  template<typename _CharT, typename _Size>
412  typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
413  _CharT*>::__type
414  __copy_n_a(istreambuf_iterator<_CharT> __it, _Size __n, _CharT* __result,
415  bool __strict __attribute__((__unused__)))
416  {
417  if (__n == 0)
418  return __result;
419 
420  __glibcxx_requires_cond(__it._M_sbuf,
421  _M_message(__gnu_debug::__msg_inc_istreambuf)
422  ._M_iterator(__it));
423  _CharT* __beg = __result;
424  __result += __it._M_sbuf->sgetn(__beg, __n);
425  __glibcxx_requires_cond(!__strict || __result - __beg == __n,
426  _M_message(__gnu_debug::__msg_inc_istreambuf)
427  ._M_iterator(__it));
428  return __result;
429  }
430 
431  template<typename _CharT>
432  typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
433  istreambuf_iterator<_CharT> >::__type
434  find(istreambuf_iterator<_CharT> __first,
435  istreambuf_iterator<_CharT> __last, const _CharT& __val)
436  {
437  typedef istreambuf_iterator<_CharT> __is_iterator_type;
438  typedef typename __is_iterator_type::traits_type traits_type;
439  typedef typename __is_iterator_type::streambuf_type streambuf_type;
440  typedef typename traits_type::int_type int_type;
441  const int_type __eof = traits_type::eof();
442 
443  if (__first._M_sbuf && !__last._M_sbuf)
444  {
445  const int_type __ival = traits_type::to_int_type(__val);
446  streambuf_type* __sb = __first._M_sbuf;
447  int_type __c = __sb->sgetc();
448  while (!traits_type::eq_int_type(__c, __eof)
449  && !traits_type::eq_int_type(__c, __ival))
450  {
451  streamsize __n = __sb->egptr() - __sb->gptr();
452  if (__n > 1)
453  {
454  const _CharT* __p = traits_type::find(__sb->gptr(),
455  __n, __val);
456  if (__p)
457  __n = __p - __sb->gptr();
458  __sb->__safe_gbump(__n);
459  __c = __sb->sgetc();
460  }
461  else
462  __c = __sb->snextc();
463  }
464 
465  __first._M_c = __eof;
466  }
467 
468  return __first;
469  }
470 
471  template<typename _CharT, typename _Distance>
472  typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
473  void>::__type
474  advance(istreambuf_iterator<_CharT>& __i, _Distance __n)
475  {
476  if (__n == 0)
477  return;
478 
479  __glibcxx_assert(__n > 0);
480  __glibcxx_requires_cond(!__i._M_at_eof(),
481  _M_message(__gnu_debug::__msg_inc_istreambuf)
482  ._M_iterator(__i));
483 
484  typedef istreambuf_iterator<_CharT> __is_iterator_type;
485  typedef typename __is_iterator_type::traits_type traits_type;
486  typedef typename __is_iterator_type::streambuf_type streambuf_type;
487  typedef typename traits_type::int_type int_type;
488  const int_type __eof = traits_type::eof();
489 
490  streambuf_type* __sb = __i._M_sbuf;
491  while (__n > 0)
492  {
493  streamsize __size = __sb->egptr() - __sb->gptr();
494  if (__size > __n)
495  {
496  __sb->__safe_gbump(__n);
497  break;
498  }
499 
500  __sb->__safe_gbump(__size);
501  __n -= __size;
502  if (traits_type::eq_int_type(__sb->underflow(), __eof))
503  {
504  __glibcxx_requires_cond(__n == 0,
505  _M_message(__gnu_debug::__msg_inc_istreambuf)
506  ._M_iterator(__i));
507  break;
508  }
509  }
510 
511  __i._M_c = __eof;
512  }
513 
514 /// @} group iterators
515 
516 _GLIBCXX_END_NAMESPACE_VERSION
517 } // namespace
518 
519 #endif
ISO C++ entities toplevel namespace is std.
ptrdiff_t streamsize
Integral type for I/O operation counts and buffer sizes.
Definition: postypes.h:68
constexpr void advance(_InputIterator &__i, _Distance __n)
A generalization of pointer arithmetic.
The actual work of input and output (interface).
Definition: streambuf:123
streamsize sputn(const char_type *__s, streamsize __n)
Entry point for all single-character output functions.
Definition: streambuf:455
int_type sbumpc()
Getting the next character.
Definition: streambuf:321
int_type sgetc()
Getting the next character.
Definition: streambuf:343
int_type sputc(char_type __c)
Entry point for all single-character output functions.
Definition: streambuf:429
Template class basic_istream.
Definition: istream:59
Template class basic_ostream.
Definition: ostream:59
Provides input iterator semantics for streambufs.
basic_streambuf< _CharT, _Traits > streambuf_type
Public typedefs.
void pointer
Public typedefs.
istreambuf_iterator & operator++()
Advance the iterator. Calls streambuf.sbumpc().
constexpr istreambuf_iterator() noexcept
Construct end of input stream iterator.
basic_istream< _CharT, _Traits > istream_type
Public typedefs.
char_type operator*() const
Return the current character pointed to by iterator. This returns streambuf.sgetc()....
bool equal(const istreambuf_iterator &__b) const
Return true both iterators are end or both are not end.
_Traits traits_type
Public typedefs.
istreambuf_iterator(istream_type &__s) noexcept
Construct start of input stream iterator.
istreambuf_iterator operator++(int)
Advance the iterator. Calls streambuf.sbumpc().
_CharT char_type
Public typedefs.
istreambuf_iterator(streambuf_type *__s) noexcept
Construct start of streambuf iterator.
_Traits::int_type int_type
Public typedefs.
Provides output iterator semantics for streambufs.
ostreambuf_iterator & operator++()
Return *this.
ostreambuf_iterator & operator*()
Return *this.
ptrdiff_t difference_type
Public typedefs.
bool failed() const noexcept
Return true if previous operator=() failed.
_Traits traits_type
Public typedefs.
basic_ostream< _CharT, _Traits > ostream_type
Public typedefs.
basic_streambuf< _CharT, _Traits > streambuf_type
Public typedefs.
ostreambuf_iterator & operator=(_CharT __c)
Write character to streambuf. Calls streambuf.sputc().
ostreambuf_iterator(ostream_type &__s) noexcept
Construct output iterator from ostream.
ostreambuf_iterator & operator++(int)
Return *this.
_CharT char_type
Public typedefs.
ostreambuf_iterator(streambuf_type *__s) noexcept
Construct output iterator from streambuf.
Common iterator class.