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