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