libstdc++
streambuf_iterator.h
Go to the documentation of this file.
00001 // Streambuf iterators
00002 
00003 // Copyright (C) 1997-2015 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file bits/streambuf_iterator.h
00026  *  This is an internal header file, included by other library headers.
00027  *  Do not attempt to use it directly. @headername{iterator}
00028  */
00029 
00030 #ifndef _STREAMBUF_ITERATOR_H
00031 #define _STREAMBUF_ITERATOR_H 1
00032 
00033 #pragma GCC system_header
00034 
00035 #include <streambuf>
00036 #include <debug/debug.h>
00037 
00038 namespace std _GLIBCXX_VISIBILITY(default)
00039 {
00040 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00041      
00042   /**
00043    * @addtogroup iterators
00044    * @{
00045    */
00046 
00047   // 24.5.3 Template class istreambuf_iterator
00048   /// Provides input iterator semantics for streambufs.
00049   template<typename _CharT, typename _Traits>
00050     class istreambuf_iterator
00051     : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type,
00052                       _CharT*,
00053 #if __cplusplus >= 201103L
00054     // LWG 445.
00055                       _CharT>
00056 #else
00057                       _CharT&>
00058 #endif
00059     {
00060     public:
00061       // Types:
00062       //@{
00063       /// Public typedefs
00064       typedef _CharT                                    char_type;
00065       typedef _Traits                                   traits_type;
00066       typedef typename _Traits::int_type                int_type;
00067       typedef basic_streambuf<_CharT, _Traits>          streambuf_type;
00068       typedef basic_istream<_CharT, _Traits>            istream_type;
00069       //@}
00070 
00071       template<typename _CharT2>
00072         friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
00073                                     ostreambuf_iterator<_CharT2> >::__type
00074         copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
00075              ostreambuf_iterator<_CharT2>);
00076 
00077       template<bool _IsMove, typename _CharT2>
00078         friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value, 
00079                                                _CharT2*>::__type
00080         __copy_move_a2(istreambuf_iterator<_CharT2>,
00081                        istreambuf_iterator<_CharT2>, _CharT2*);
00082 
00083       template<typename _CharT2>
00084         friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
00085                                     istreambuf_iterator<_CharT2> >::__type
00086         find(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
00087              const _CharT2&);
00088 
00089     private:
00090       // 24.5.3 istreambuf_iterator
00091       // p 1
00092       // If the end of stream is reached (streambuf_type::sgetc()
00093       // returns traits_type::eof()), the iterator becomes equal to
00094       // the "end of stream" iterator value.
00095       // NB: This implementation assumes the "end of stream" value
00096       // is EOF, or -1.
00097       mutable streambuf_type*   _M_sbuf;
00098       mutable int_type          _M_c;
00099 
00100     public:
00101       ///  Construct end of input stream iterator.
00102       _GLIBCXX_CONSTEXPR istreambuf_iterator() _GLIBCXX_USE_NOEXCEPT
00103       : _M_sbuf(0), _M_c(traits_type::eof()) { }
00104 
00105 #if __cplusplus >= 201103L
00106       istreambuf_iterator(const istreambuf_iterator&) noexcept = default;
00107 
00108       ~istreambuf_iterator() = default;
00109 #endif
00110 
00111       ///  Construct start of input stream iterator.
00112       istreambuf_iterator(istream_type& __s) _GLIBCXX_USE_NOEXCEPT
00113       : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { }
00114 
00115       ///  Construct start of streambuf iterator.
00116       istreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
00117       : _M_sbuf(__s), _M_c(traits_type::eof()) { }
00118 
00119       ///  Return the current character pointed to by iterator.  This returns
00120       ///  streambuf.sgetc().  It cannot be assigned.  NB: The result of
00121       ///  operator*() on an end of stream is undefined.
00122       char_type
00123       operator*() const
00124       {
00125 #ifdef _GLIBCXX_DEBUG_PEDANTIC
00126         // Dereferencing a past-the-end istreambuf_iterator is a
00127         // libstdc++ extension
00128         __glibcxx_requires_cond(!_M_at_eof(),
00129                                 _M_message(__gnu_debug::__msg_deref_istreambuf)
00130                                 ._M_iterator(*this));
00131 #endif
00132         return traits_type::to_char_type(_M_get());
00133       }
00134 
00135       /// Advance the iterator.  Calls streambuf.sbumpc().
00136       istreambuf_iterator&
00137       operator++()
00138       {
00139         __glibcxx_requires_cond(!_M_at_eof(),
00140                                 _M_message(__gnu_debug::__msg_inc_istreambuf)
00141                                 ._M_iterator(*this));
00142         if (_M_sbuf)
00143           {
00144             _M_sbuf->sbumpc();
00145             _M_c = traits_type::eof();
00146           }
00147         return *this;
00148       }
00149 
00150       /// Advance the iterator.  Calls streambuf.sbumpc().
00151       istreambuf_iterator
00152       operator++(int)
00153       {
00154         __glibcxx_requires_cond(!_M_at_eof(),
00155                                 _M_message(__gnu_debug::__msg_inc_istreambuf)
00156                                 ._M_iterator(*this));
00157 
00158         istreambuf_iterator __old = *this;
00159         if (_M_sbuf)
00160           {
00161             __old._M_c = _M_sbuf->sbumpc();
00162             _M_c = traits_type::eof();
00163           }
00164         return __old;
00165       }
00166 
00167       // _GLIBCXX_RESOLVE_LIB_DEFECTS
00168       // 110 istreambuf_iterator::equal not const
00169       // NB: there is also number 111 (NAD, Future) pending on this function.
00170       /// Return true both iterators are end or both are not end.
00171       bool
00172       equal(const istreambuf_iterator& __b) const
00173       { return _M_at_eof() == __b._M_at_eof(); }
00174 
00175     private:
00176       int_type
00177       _M_get() const
00178       {
00179         const int_type __eof = traits_type::eof();
00180         int_type __ret = __eof;
00181         if (_M_sbuf)
00182           {
00183             if (!traits_type::eq_int_type(_M_c, __eof))
00184               __ret = _M_c;
00185             else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()),
00186                                                __eof))
00187               _M_c = __ret;
00188             else
00189               _M_sbuf = 0;
00190           }
00191         return __ret;
00192       }
00193 
00194       bool
00195       _M_at_eof() const
00196       {
00197         const int_type __eof = traits_type::eof();
00198         return traits_type::eq_int_type(_M_get(), __eof);
00199       }
00200     };
00201 
00202   template<typename _CharT, typename _Traits>
00203     inline bool
00204     operator==(const istreambuf_iterator<_CharT, _Traits>& __a,
00205                const istreambuf_iterator<_CharT, _Traits>& __b)
00206     { return __a.equal(__b); }
00207 
00208   template<typename _CharT, typename _Traits>
00209     inline bool
00210     operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
00211                const istreambuf_iterator<_CharT, _Traits>& __b)
00212     { return !__a.equal(__b); }
00213 
00214   /// Provides output iterator semantics for streambufs.
00215   template<typename _CharT, typename _Traits>
00216     class ostreambuf_iterator
00217     : public iterator<output_iterator_tag, void, void, void, void>
00218     {
00219     public:
00220       // Types:
00221       //@{
00222       /// Public typedefs
00223       typedef _CharT                           char_type;
00224       typedef _Traits                          traits_type;
00225       typedef basic_streambuf<_CharT, _Traits> streambuf_type;
00226       typedef basic_ostream<_CharT, _Traits>   ostream_type;
00227       //@}
00228 
00229       template<typename _CharT2>
00230         friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
00231                                     ostreambuf_iterator<_CharT2> >::__type
00232         copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
00233              ostreambuf_iterator<_CharT2>);
00234 
00235     private:
00236       streambuf_type*   _M_sbuf;
00237       bool              _M_failed;
00238 
00239     public:
00240       ///  Construct output iterator from ostream.
00241       ostreambuf_iterator(ostream_type& __s) _GLIBCXX_USE_NOEXCEPT
00242       : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
00243 
00244       ///  Construct output iterator from streambuf.
00245       ostreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
00246       : _M_sbuf(__s), _M_failed(!_M_sbuf) { }
00247 
00248       ///  Write character to streambuf.  Calls streambuf.sputc().
00249       ostreambuf_iterator&
00250       operator=(_CharT __c)
00251       {
00252         if (!_M_failed &&
00253             _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof()))
00254           _M_failed = true;
00255         return *this;
00256       }
00257 
00258       /// Return *this.
00259       ostreambuf_iterator&
00260       operator*()
00261       { return *this; }
00262 
00263       /// Return *this.
00264       ostreambuf_iterator&
00265       operator++(int)
00266       { return *this; }
00267 
00268       /// Return *this.
00269       ostreambuf_iterator&
00270       operator++()
00271       { return *this; }
00272 
00273       /// Return true if previous operator=() failed.
00274       bool
00275       failed() const _GLIBCXX_USE_NOEXCEPT
00276       { return _M_failed; }
00277 
00278       ostreambuf_iterator&
00279       _M_put(const _CharT* __ws, streamsize __len)
00280       {
00281         if (__builtin_expect(!_M_failed, true)
00282             && __builtin_expect(this->_M_sbuf->sputn(__ws, __len) != __len,
00283                                 false))
00284           _M_failed = true;
00285         return *this;
00286       }
00287     };
00288 
00289   // Overloads for streambuf iterators.
00290   template<typename _CharT>
00291     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
00292                                     ostreambuf_iterator<_CharT> >::__type
00293     copy(istreambuf_iterator<_CharT> __first,
00294          istreambuf_iterator<_CharT> __last,
00295          ostreambuf_iterator<_CharT> __result)
00296     {
00297       if (__first._M_sbuf && !__last._M_sbuf && !__result._M_failed)
00298         {
00299           bool __ineof;
00300           __copy_streambufs_eof(__first._M_sbuf, __result._M_sbuf, __ineof);
00301           if (!__ineof)
00302             __result._M_failed = true;
00303         }
00304       return __result;
00305     }
00306 
00307   template<bool _IsMove, typename _CharT>
00308     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 
00309                                     ostreambuf_iterator<_CharT> >::__type
00310     __copy_move_a2(_CharT* __first, _CharT* __last,
00311                    ostreambuf_iterator<_CharT> __result)
00312     {
00313       const streamsize __num = __last - __first;
00314       if (__num > 0)
00315         __result._M_put(__first, __num);
00316       return __result;
00317     }
00318 
00319   template<bool _IsMove, typename _CharT>
00320     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
00321                                     ostreambuf_iterator<_CharT> >::__type
00322     __copy_move_a2(const _CharT* __first, const _CharT* __last,
00323                    ostreambuf_iterator<_CharT> __result)
00324     {
00325       const streamsize __num = __last - __first;
00326       if (__num > 0)
00327         __result._M_put(__first, __num);
00328       return __result;
00329     }
00330 
00331   template<bool _IsMove, typename _CharT>
00332     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, 
00333                                     _CharT*>::__type
00334     __copy_move_a2(istreambuf_iterator<_CharT> __first,
00335                    istreambuf_iterator<_CharT> __last, _CharT* __result)
00336     {
00337       typedef istreambuf_iterator<_CharT>                  __is_iterator_type;
00338       typedef typename __is_iterator_type::traits_type     traits_type;
00339       typedef typename __is_iterator_type::streambuf_type  streambuf_type;
00340       typedef typename traits_type::int_type               int_type;
00341 
00342       if (__first._M_sbuf && !__last._M_sbuf)
00343         {
00344           streambuf_type* __sb = __first._M_sbuf;
00345           int_type __c = __sb->sgetc();
00346           while (!traits_type::eq_int_type(__c, traits_type::eof()))
00347             {
00348               const streamsize __n = __sb->egptr() - __sb->gptr();
00349               if (__n > 1)
00350                 {
00351                   traits_type::copy(__result, __sb->gptr(), __n);
00352                   __sb->__safe_gbump(__n);
00353                   __result += __n;
00354                   __c = __sb->underflow();
00355                 }
00356               else
00357                 {
00358                   *__result++ = traits_type::to_char_type(__c);
00359                   __c = __sb->snextc();
00360                 }
00361             }
00362         }
00363       return __result;
00364     }
00365 
00366   template<typename _CharT>
00367     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
00368                                     istreambuf_iterator<_CharT> >::__type
00369     find(istreambuf_iterator<_CharT> __first,
00370          istreambuf_iterator<_CharT> __last, const _CharT& __val)
00371     {
00372       typedef istreambuf_iterator<_CharT>                  __is_iterator_type;
00373       typedef typename __is_iterator_type::traits_type     traits_type;
00374       typedef typename __is_iterator_type::streambuf_type  streambuf_type;
00375       typedef typename traits_type::int_type               int_type;
00376 
00377       if (__first._M_sbuf && !__last._M_sbuf)
00378         {
00379           const int_type __ival = traits_type::to_int_type(__val);
00380           streambuf_type* __sb = __first._M_sbuf;
00381           int_type __c = __sb->sgetc();
00382           while (!traits_type::eq_int_type(__c, traits_type::eof())
00383                  && !traits_type::eq_int_type(__c, __ival))
00384             {
00385               streamsize __n = __sb->egptr() - __sb->gptr();
00386               if (__n > 1)
00387                 {
00388                   const _CharT* __p = traits_type::find(__sb->gptr(),
00389                                                         __n, __val);
00390                   if (__p)
00391                     __n = __p - __sb->gptr();
00392                   __sb->__safe_gbump(__n);
00393                   __c = __sb->sgetc();
00394                 }
00395               else
00396                 __c = __sb->snextc();
00397             }
00398 
00399           if (!traits_type::eq_int_type(__c, traits_type::eof()))
00400             __first._M_c = __c;
00401           else
00402             __first._M_sbuf = 0;
00403         }
00404       return __first;
00405     }
00406 
00407 // @} group iterators
00408 
00409 _GLIBCXX_END_NAMESPACE_VERSION
00410 } // namespace
00411 
00412 #endif