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