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