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

Generated on Thu Jul 23 21:16:24 2009 for libstdc++ by  doxygen 1.5.8