streambuf_iterator.h

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