LCOV - code coverage report
Current view: top level - 11/bits - streambuf_iterator.h (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 29 33 87.9 %
Date: 2025-08-24 09:11:10 Functions: 11 13 84.6 %

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

Generated by: LCOV version 1.14