# 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
    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 streambuf_iterator.h
    00028  *  This is an internal header file, included by other library headers.
    00029  *  You should not attempt to use it directly.
    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 _GLIBCXX_BEGIN_NAMESPACE(std)
    00041
    00042   // 24.5.3 Template class istreambuf_iterator
    00043   /// Provides input iterator semantics for streambufs.
    00044   template<typename _CharT, typename _Traits>
    00045     class istreambuf_iterator
    00046     : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type,
    00047               _CharT*, _CharT&>
    00048     {
    00049     public:
    00050       // Types:
    00051       //@{
    00052       /// Public typedefs
    00053       typedef _CharT                    char_type;
    00054       typedef _Traits                   traits_type;
    00055       typedef typename _Traits::int_type        int_type;
    00056       typedef basic_streambuf<_CharT, _Traits>      streambuf_type;
    00057       typedef basic_istream<_CharT, _Traits>        istream_type;
    00058       //@}
    00059
    00060       template<typename _CharT2>
    00061     friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
    00062                             ostreambuf_iterator<_CharT2> >::__type
    00063     copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
    00064          ostreambuf_iterator<_CharT2>);
    00065
    00066       template<bool _IsMove, typename _CharT2>
    00067     friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
    00068                            _CharT2*>::__type
    00069     __copy_move_a2(istreambuf_iterator<_CharT2>,
    00070                istreambuf_iterator<_CharT2>, _CharT2*);
    00071
    00072       template<typename _CharT2>
    00073     friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
    00074                         istreambuf_iterator<_CharT2> >::__type
    00075     find(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
    00076          const _CharT2&);
    00077
    00078     private:
    00079       // 24.5.3 istreambuf_iterator
    00080       // p 1
    00081       // If the end of stream is reached (streambuf_type::sgetc()
    00082       // returns traits_type::eof()), the iterator becomes equal to
    00083       // the "end of stream" iterator value.
    00084       // NB: This implementation assumes the "end of stream" value
    00085       // is EOF, or -1.
    00086       mutable streambuf_type*   _M_sbuf;
    00087       mutable int_type      _M_c;
    00088
    00089     public:
    00090       ///  Construct end of input stream iterator.
    00091       istreambuf_iterator() throw()
    00092       : _M_sbuf(0), _M_c(traits_type::eof()) { }
    00093
    00094       ///  Construct start of input stream iterator.
    00095       istreambuf_iterator(istream_type& __s) throw()
    00096       : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { }
    00097
    00098       ///  Construct start of streambuf iterator.
    00099       istreambuf_iterator(streambuf_type* __s) throw()
    00100       : _M_sbuf(__s), _M_c(traits_type::eof()) { }
    00101
    00102       ///  Return the current character pointed to by iterator.  This returns
    00103       ///  streambuf.sgetc().  It cannot be assigned.  NB: The result of
    00104       ///  operator*() on an end of stream is undefined.
    00105       char_type
    00106       operator*() const
    00107       {
    00108 #ifdef _GLIBCXX_DEBUG_PEDANTIC
    00109     // Dereferencing a past-the-end istreambuf_iterator is a
    00110     // libstdc++ extension
    00111     __glibcxx_requires_cond(!_M_at_eof(),
    00112                 _M_message(__gnu_debug::__msg_deref_istreambuf)
    00113                 ._M_iterator(*this));
    00114 #endif
    00115     return traits_type::to_char_type(_M_get());
    00116       }
    00117
    00118       /// Advance the iterator.  Calls streambuf.sbumpc().
    00119       istreambuf_iterator&
    00120       operator++()
    00121       {
    00122     __glibcxx_requires_cond(!_M_at_eof(),
    00123                 _M_message(__gnu_debug::__msg_inc_istreambuf)
    00124                 ._M_iterator(*this));
    00125     if (_M_sbuf)
    00126       {
    00127         _M_sbuf->sbumpc();
    00128         _M_c = traits_type::eof();
    00129       }
    00130     return *this;
    00131       }
    00132
    00133       /// Advance the iterator.  Calls streambuf.sbumpc().
    00134       istreambuf_iterator
    00135       operator++(int)
    00136       {
    00137     __glibcxx_requires_cond(!_M_at_eof(),
    00138                 _M_message(__gnu_debug::__msg_inc_istreambuf)
    00139                 ._M_iterator(*this));
    00140
    00141     istreambuf_iterator __old = *this;
    00142     if (_M_sbuf)
    00143       {
    00144         __old._M_c = _M_sbuf->sbumpc();
    00145         _M_c = traits_type::eof();
    00146       }
    00147     return __old;
    00148       }
    00149
    00150       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00151       // 110 istreambuf_iterator::equal not const
    00152       // NB: there is also number 111 (NAD, Future) pending on this function.
    00153       /// Return true both iterators are end or both are not end.
    00154       bool
    00155       equal(const istreambuf_iterator& __b) const
    00156       { return _M_at_eof() == __b._M_at_eof(); }
    00157
    00158     private:
    00159       int_type
    00160       _M_get() const
    00161       {
    00162     const int_type __eof = traits_type::eof();
    00163     int_type __ret = __eof;
    00164     if (_M_sbuf)
    00165       {
    00166         if (!traits_type::eq_int_type(_M_c, __eof))
    00167           __ret = _M_c;
    00168         else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()),
    00169                            __eof))
    00170           _M_c = __ret;
    00171         else
    00172           _M_sbuf = 0;
    00173       }
    00174     return __ret;
    00175       }
    00176
    00177       bool
    00178       _M_at_eof() const
    00179       {
    00180     const int_type __eof = traits_type::eof();
    00181     return traits_type::eq_int_type(_M_get(), __eof);
    00182       }
    00183     };
    00184
    00185   template<typename _CharT, typename _Traits>
    00186     inline bool
    00187     operator==(const istreambuf_iterator<_CharT, _Traits>& __a,
    00188            const istreambuf_iterator<_CharT, _Traits>& __b)
    00189     { return __a.equal(__b); }
    00190
    00191   template<typename _CharT, typename _Traits>
    00192     inline bool
    00193     operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
    00194            const istreambuf_iterator<_CharT, _Traits>& __b)
    00195     { return !__a.equal(__b); }
    00196
    00197   /// Provides output iterator semantics for streambufs.
    00198   template<typename _CharT, typename _Traits>
    00199     class ostreambuf_iterator
    00200     : public iterator<output_iterator_tag, void, void, void, void>
    00201     {
    00202     public:
    00203       // Types:
    00204       //@{
    00205       /// Public typedefs
    00206       typedef _CharT                           char_type;
    00207       typedef _Traits                          traits_type;
    00208       typedef basic_streambuf<_CharT, _Traits> streambuf_type;
    00209       typedef basic_ostream<_CharT, _Traits>   ostream_type;
    00210       //@}
    00211
    00212       template<typename _CharT2>
    00213     friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
    00214                             ostreambuf_iterator<_CharT2> >::__type
    00215     copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
    00216          ostreambuf_iterator<_CharT2>);
    00217
    00218     private:
    00219       streambuf_type*   _M_sbuf;
    00220       bool      _M_failed;
    00221
    00222     public:
    00223       ///  Construct output iterator from ostream.
    00224       ostreambuf_iterator(ostream_type& __s) throw ()
    00225       : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
    00226
    00227       ///  Construct output iterator from streambuf.
    00228       ostreambuf_iterator(streambuf_type* __s) throw ()
    00229       : _M_sbuf(__s), _M_failed(!_M_sbuf) { }
    00230
    00231       ///  Write character to streambuf.  Calls streambuf.sputc().
    00232       ostreambuf_iterator&
    00233       operator=(_CharT __c)
    00234       {
    00235     if (!_M_failed &&
    00236         _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof()))
    00237       _M_failed = true;
    00238     return *this;
    00239       }
    00240
    00241       /// Return *this.
    00242       ostreambuf_iterator&
    00243       operator*()
    00244       { return *this; }
    00245
    00246       /// Return *this.
    00247       ostreambuf_iterator&
    00248       operator++(int)
    00249       { return *this; }
    00250
    00251       /// Return *this.
    00252       ostreambuf_iterator&
    00253       operator++()
    00254       { return *this; }
    00255
    00256       /// Return true if previous operator=() failed.
    00257       bool
    00258       failed() const throw()
    00259       { return _M_failed; }
    00260
    00261       ostreambuf_iterator&
    00262       _M_put(const _CharT* __ws, streamsize __len)
    00263       {
    00264     if (__builtin_expect(!_M_failed, true)
    00265         && __builtin_expect(this->_M_sbuf->sputn(__ws, __len) != __len,
    00266                 false))
    00267       _M_failed = true;
    00268     return *this;
    00269       }
    00270     };
    00271
    00272   // Overloads for streambuf iterators.
    00273   template<typename _CharT>
    00274     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    00275                                 ostreambuf_iterator<_CharT> >::__type
    00276     copy(istreambuf_iterator<_CharT> __first,
    00277      istreambuf_iterator<_CharT> __last,
    00278      ostreambuf_iterator<_CharT> __result)
    00279     {
    00280       if (__first._M_sbuf && !__last._M_sbuf && !__result._M_failed)
    00281     {
    00282       bool __ineof;
    00283       __copy_streambufs_eof(__first._M_sbuf, __result._M_sbuf, __ineof);
    00284       if (!__ineof)
    00285         __result._M_failed = true;
    00286     }
    00287       return __result;
    00288     }
    00289
    00290   template<bool _IsMove, typename _CharT>
    00291     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    00292                         ostreambuf_iterator<_CharT> >::__type
    00293     __copy_move_a2(_CharT* __first, _CharT* __last,
    00294            ostreambuf_iterator<_CharT> __result)
    00295     {
    00296       const streamsize __num = __last - __first;
    00297       if (__num > 0)
    00298     __result._M_put(__first, __num);
    00299       return __result;
    00300     }
    00301
    00302   template<bool _IsMove, typename _CharT>
    00303     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    00304                     ostreambuf_iterator<_CharT> >::__type
    00305     __copy_move_a2(const _CharT* __first, const _CharT* __last,
    00306            ostreambuf_iterator<_CharT> __result)
    00307     {
    00308       const streamsize __num = __last - __first;
    00309       if (__num > 0)
    00310     __result._M_put(__first, __num);
    00311       return __result;
    00312     }
    00313
    00314   template<bool _IsMove, typename _CharT>
    00315     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    00316                         _CharT*>::__type
    00317     __copy_move_a2(istreambuf_iterator<_CharT> __first,
    00318            istreambuf_iterator<_CharT> __last, _CharT* __result)
    00319     {
    00320       typedef istreambuf_iterator<_CharT>                  __is_iterator_type;
    00321       typedef typename __is_iterator_type::traits_type     traits_type;
    00322       typedef typename __is_iterator_type::streambuf_type  streambuf_type;
    00323       typedef typename traits_type::int_type               int_type;
    00324
    00325       if (__first._M_sbuf && !__last._M_sbuf)
    00326     {
    00327       streambuf_type* __sb = __first._M_sbuf;
    00328       int_type __c = __sb->sgetc();
    00329       while (!traits_type::eq_int_type(__c, traits_type::eof()))
    00330         {
    00331           const streamsize __n = __sb->egptr() - __sb->gptr();
    00332           if (__n > 1)
    00333         {
    00334           traits_type::copy(__result, __sb->gptr(), __n);
    00335           __sb->gbump(__n);
    00336           __result += __n;
    00337           __c = __sb->underflow();
    00338         }
    00339           else
    00340         {
    00341           *__result++ = traits_type::to_char_type(__c);
    00342           __c = __sb->snextc();
    00343         }
    00344         }
    00345     }
    00346       return __result;
    00347     }
    00348
    00349   template<typename _CharT>
    00350     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    00351                     istreambuf_iterator<_CharT> >::__type
    00352     find(istreambuf_iterator<_CharT> __first,
    00353      istreambuf_iterator<_CharT> __last, const _CharT& __val)
    00354     {
    00355       typedef istreambuf_iterator<_CharT>                  __is_iterator_type;
    00356       typedef typename __is_iterator_type::traits_type     traits_type;
    00357       typedef typename __is_iterator_type::streambuf_type  streambuf_type;
    00358       typedef typename traits_type::int_type               int_type;
    00359
    00360       if (__first._M_sbuf && !__last._M_sbuf)
    00361     {
    00362       const int_type __ival = traits_type::to_int_type(__val);
    00363       streambuf_type* __sb = __first._M_sbuf;
    00364       int_type __c = __sb->sgetc();
    00365       while (!traits_type::eq_int_type(__c, traits_type::eof())
    00366          && !traits_type::eq_int_type(__c, __ival))
    00367         {
    00368           streamsize __n = __sb->egptr() - __sb->gptr();
    00369           if (__n > 1)
    00370         {
    00371           const _CharT* __p = traits_type::find(__sb->gptr(),
    00372                             __n, __val);
    00373           if (__p)
    00374             __n = __p - __sb->gptr();
    00375           __sb->gbump(__n);
    00376           __c = __sb->sgetc();
    00377         }
    00378           else
    00379         __c = __sb->snextc();
    00380         }
    00381
    00382       if (!traits_type::eq_int_type(__c, traits_type::eof()))
    00383         __first._M_c = __c;
    00384       else
    00385         __first._M_sbuf = 0;
    00386     }
    00387       return __first;
    00388     }
    00389
    00390 _GLIBCXX_END_NAMESPACE
    00391
    00392 #endif