Home | History | Annotate | Download | only in bits
      1 // Streambuf iterators
      2 
      3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
      4 // 2006, 2007, 2009, 2010, 2011
      5 // Free Software Foundation, Inc.
      6 //
      7 // This file is part of the GNU ISO C++ Library.  This library is free
      8 // software; you can redistribute it and/or modify it under the
      9 // terms of the GNU General Public License as published by the
     10 // Free Software Foundation; either version 3, or (at your option)
     11 // any later version.
     12 
     13 // This library is distributed in the hope that it will be useful,
     14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 // GNU General Public License for more details.
     17 
     18 // Under Section 7 of GPL version 3, you are granted additional
     19 // permissions described in the GCC Runtime Library Exception, version
     20 // 3.1, as published by the Free Software Foundation.
     21 
     22 // You should have received a copy of the GNU General Public License and
     23 // a copy of the GCC Runtime Library Exception along with this program;
     24 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     25 // <http://www.gnu.org/licenses/>.
     26 
     27 /** @file bits/streambuf_iterator.h
     28  *  This is an internal header file, included by other library headers.
     29  *  Do not attempt to use it directly. @headername{iterator}
     30  */
     31 
     32 #ifndef _STREAMBUF_ITERATOR_H
     33 #define _STREAMBUF_ITERATOR_H 1
     34 
     35 #pragma GCC system_header
     36 
     37 #include <streambuf>
     38 #include <debug/debug.h>
     39 
     40 namespace std _GLIBCXX_VISIBILITY(default)
     41 {
     42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     43 
     44   /**
     45    * @addtogroup iterators
     46    * @{
     47    */
     48 
     49   // 24.5.3 Template class istreambuf_iterator
     50   /// Provides input iterator semantics for streambufs.
     51   template<typename _CharT, typename _Traits>
     52     class istreambuf_iterator
     53     : public iterator<input_iterator_tag, _CharT, typename _Traits::off_type,
     54 		      _CharT*, _CharT&>
     55     {
     56     public:
     57       // Types:
     58       //@{
     59       /// Public typedefs
     60       typedef _CharT					char_type;
     61       typedef _Traits					traits_type;
     62       typedef typename _Traits::int_type		int_type;
     63       typedef basic_streambuf<_CharT, _Traits>		streambuf_type;
     64       typedef basic_istream<_CharT, _Traits>		istream_type;
     65       //@}
     66 
     67       template<typename _CharT2>
     68 	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
     69 		                    ostreambuf_iterator<_CharT2> >::__type
     70 	copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
     71 	     ostreambuf_iterator<_CharT2>);
     72 
     73       template<bool _IsMove, typename _CharT2>
     74 	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
     75 					       _CharT2*>::__type
     76 	__copy_move_a2(istreambuf_iterator<_CharT2>,
     77 		       istreambuf_iterator<_CharT2>, _CharT2*);
     78 
     79       template<typename _CharT2>
     80 	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
     81 			            istreambuf_iterator<_CharT2> >::__type
     82 	find(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
     83 	     const _CharT2&);
     84 
     85     private:
     86       // 24.5.3 istreambuf_iterator
     87       // p 1
     88       // If the end of stream is reached (streambuf_type::sgetc()
     89       // returns traits_type::eof()), the iterator becomes equal to
     90       // the "end of stream" iterator value.
     91       // NB: This implementation assumes the "end of stream" value
     92       // is EOF, or -1.
     93       mutable streambuf_type*	_M_sbuf;
     94       mutable int_type		_M_c;
     95 
     96     public:
     97       ///  Construct end of input stream iterator.
     98       _GLIBCXX_CONSTEXPR istreambuf_iterator() throw()
     99       : _M_sbuf(0), _M_c(traits_type::eof()) { }
    100 
    101       ///  Construct start of input stream iterator.
    102       istreambuf_iterator(istream_type& __s) throw()
    103       : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { }
    104 
    105       ///  Construct start of streambuf iterator.
    106       istreambuf_iterator(streambuf_type* __s) throw()
    107       : _M_sbuf(__s), _M_c(traits_type::eof()) { }
    108 
    109       ///  Return the current character pointed to by iterator.  This returns
    110       ///  streambuf.sgetc().  It cannot be assigned.  NB: The result of
    111       ///  operator*() on an end of stream is undefined.
    112       char_type
    113       operator*() const
    114       {
    115 #ifdef _GLIBCXX_DEBUG_PEDANTIC
    116 	// Dereferencing a past-the-end istreambuf_iterator is a
    117 	// libstdc++ extension
    118 	__glibcxx_requires_cond(!_M_at_eof(),
    119 				_M_message(__gnu_debug::__msg_deref_istreambuf)
    120 				._M_iterator(*this));
    121 #endif
    122 	return traits_type::to_char_type(_M_get());
    123       }
    124 
    125       /// Advance the iterator.  Calls streambuf.sbumpc().
    126       istreambuf_iterator&
    127       operator++()
    128       {
    129 	__glibcxx_requires_cond(!_M_at_eof(),
    130 				_M_message(__gnu_debug::__msg_inc_istreambuf)
    131 				._M_iterator(*this));
    132 	if (_M_sbuf)
    133 	  {
    134 	    _M_sbuf->sbumpc();
    135 	    _M_c = traits_type::eof();
    136 	  }
    137 	return *this;
    138       }
    139 
    140       /// Advance the iterator.  Calls streambuf.sbumpc().
    141       istreambuf_iterator
    142       operator++(int)
    143       {
    144 	__glibcxx_requires_cond(!_M_at_eof(),
    145 				_M_message(__gnu_debug::__msg_inc_istreambuf)
    146 				._M_iterator(*this));
    147 
    148 	istreambuf_iterator __old = *this;
    149 	if (_M_sbuf)
    150 	  {
    151 	    __old._M_c = _M_sbuf->sbumpc();
    152 	    _M_c = traits_type::eof();
    153 	  }
    154 	return __old;
    155       }
    156 
    157       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    158       // 110 istreambuf_iterator::equal not const
    159       // NB: there is also number 111 (NAD, Future) pending on this function.
    160       /// Return true both iterators are end or both are not end.
    161       bool
    162       equal(const istreambuf_iterator& __b) const
    163       { return _M_at_eof() == __b._M_at_eof(); }
    164 
    165     private:
    166       int_type
    167       _M_get() const
    168       {
    169 	const int_type __eof = traits_type::eof();
    170 	int_type __ret = __eof;
    171 	if (_M_sbuf)
    172 	  {
    173 	    if (!traits_type::eq_int_type(_M_c, __eof))
    174 	      __ret = _M_c;
    175 	    else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()),
    176 					       __eof))
    177 	      _M_c = __ret;
    178 	    else
    179 	      _M_sbuf = 0;
    180 	  }
    181 	return __ret;
    182       }
    183 
    184       bool
    185       _M_at_eof() const
    186       {
    187 	const int_type __eof = traits_type::eof();
    188 	return traits_type::eq_int_type(_M_get(), __eof);
    189       }
    190     };
    191 
    192   template<typename _CharT, typename _Traits>
    193     inline bool
    194     operator==(const istreambuf_iterator<_CharT, _Traits>& __a,
    195 	       const istreambuf_iterator<_CharT, _Traits>& __b)
    196     { return __a.equal(__b); }
    197 
    198   template<typename _CharT, typename _Traits>
    199     inline bool
    200     operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
    201 	       const istreambuf_iterator<_CharT, _Traits>& __b)
    202     { return !__a.equal(__b); }
    203 
    204   /// Provides output iterator semantics for streambufs.
    205   template<typename _CharT, typename _Traits>
    206     class ostreambuf_iterator
    207     : public iterator<output_iterator_tag, void, void, void, void>
    208     {
    209     public:
    210       // Types:
    211       //@{
    212       /// Public typedefs
    213       typedef _CharT                           char_type;
    214       typedef _Traits                          traits_type;
    215       typedef basic_streambuf<_CharT, _Traits> streambuf_type;
    216       typedef basic_ostream<_CharT, _Traits>   ostream_type;
    217       //@}
    218 
    219       template<typename _CharT2>
    220 	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
    221 		                    ostreambuf_iterator<_CharT2> >::__type
    222 	copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
    223 	     ostreambuf_iterator<_CharT2>);
    224 
    225     private:
    226       streambuf_type*	_M_sbuf;
    227       bool		_M_failed;
    228 
    229     public:
    230       ///  Construct output iterator from ostream.
    231       ostreambuf_iterator(ostream_type& __s) throw ()
    232       : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
    233 
    234       ///  Construct output iterator from streambuf.
    235       ostreambuf_iterator(streambuf_type* __s) throw ()
    236       : _M_sbuf(__s), _M_failed(!_M_sbuf) { }
    237 
    238       ///  Write character to streambuf.  Calls streambuf.sputc().
    239       ostreambuf_iterator&
    240       operator=(_CharT __c)
    241       {
    242 	if (!_M_failed &&
    243 	    _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof()))
    244 	  _M_failed = true;
    245 	return *this;
    246       }
    247 
    248       /// Return *this.
    249       ostreambuf_iterator&
    250       operator*()
    251       { return *this; }
    252 
    253       /// Return *this.
    254       ostreambuf_iterator&
    255       operator++(int)
    256       { return *this; }
    257 
    258       /// Return *this.
    259       ostreambuf_iterator&
    260       operator++()
    261       { return *this; }
    262 
    263       /// Return true if previous operator=() failed.
    264       bool
    265       failed() const throw()
    266       { return _M_failed; }
    267 
    268       ostreambuf_iterator&
    269       _M_put(const _CharT* __ws, streamsize __len)
    270       {
    271 	if (__builtin_expect(!_M_failed, true)
    272 	    && __builtin_expect(this->_M_sbuf->sputn(__ws, __len) != __len,
    273 				false))
    274 	  _M_failed = true;
    275 	return *this;
    276       }
    277     };
    278 
    279   // Overloads for streambuf iterators.
    280   template<typename _CharT>
    281     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    282     	                 	    ostreambuf_iterator<_CharT> >::__type
    283     copy(istreambuf_iterator<_CharT> __first,
    284 	 istreambuf_iterator<_CharT> __last,
    285 	 ostreambuf_iterator<_CharT> __result)
    286     {
    287       if (__first._M_sbuf && !__last._M_sbuf && !__result._M_failed)
    288 	{
    289 	  bool __ineof;
    290 	  __copy_streambufs_eof(__first._M_sbuf, __result._M_sbuf, __ineof);
    291 	  if (!__ineof)
    292 	    __result._M_failed = true;
    293 	}
    294       return __result;
    295     }
    296 
    297   template<bool _IsMove, typename _CharT>
    298     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    299     				    ostreambuf_iterator<_CharT> >::__type
    300     __copy_move_a2(_CharT* __first, _CharT* __last,
    301 		   ostreambuf_iterator<_CharT> __result)
    302     {
    303       const streamsize __num = __last - __first;
    304       if (__num > 0)
    305 	__result._M_put(__first, __num);
    306       return __result;
    307     }
    308 
    309   template<bool _IsMove, typename _CharT>
    310     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    311 				    ostreambuf_iterator<_CharT> >::__type
    312     __copy_move_a2(const _CharT* __first, const _CharT* __last,
    313 		   ostreambuf_iterator<_CharT> __result)
    314     {
    315       const streamsize __num = __last - __first;
    316       if (__num > 0)
    317 	__result._M_put(__first, __num);
    318       return __result;
    319     }
    320 
    321   template<bool _IsMove, typename _CharT>
    322     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    323     				    _CharT*>::__type
    324     __copy_move_a2(istreambuf_iterator<_CharT> __first,
    325 		   istreambuf_iterator<_CharT> __last, _CharT* __result)
    326     {
    327       typedef istreambuf_iterator<_CharT>                  __is_iterator_type;
    328       typedef typename __is_iterator_type::traits_type     traits_type;
    329       typedef typename __is_iterator_type::streambuf_type  streambuf_type;
    330       typedef typename traits_type::int_type               int_type;
    331 
    332       if (__first._M_sbuf && !__last._M_sbuf)
    333 	{
    334 	  streambuf_type* __sb = __first._M_sbuf;
    335 	  int_type __c = __sb->sgetc();
    336 	  while (!traits_type::eq_int_type(__c, traits_type::eof()))
    337 	    {
    338 	      const streamsize __n = __sb->egptr() - __sb->gptr();
    339 	      if (__n > 1)
    340 		{
    341 		  traits_type::copy(__result, __sb->gptr(), __n);
    342 		  __sb->__safe_gbump(__n);
    343 		  __result += __n;
    344 		  __c = __sb->underflow();
    345 		}
    346 	      else
    347 		{
    348 		  *__result++ = traits_type::to_char_type(__c);
    349 		  __c = __sb->snextc();
    350 		}
    351 	    }
    352 	}
    353       return __result;
    354     }
    355 
    356   template<typename _CharT>
    357     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    358 		  		    istreambuf_iterator<_CharT> >::__type
    359     find(istreambuf_iterator<_CharT> __first,
    360 	 istreambuf_iterator<_CharT> __last, const _CharT& __val)
    361     {
    362       typedef istreambuf_iterator<_CharT>                  __is_iterator_type;
    363       typedef typename __is_iterator_type::traits_type     traits_type;
    364       typedef typename __is_iterator_type::streambuf_type  streambuf_type;
    365       typedef typename traits_type::int_type               int_type;
    366 
    367       if (__first._M_sbuf && !__last._M_sbuf)
    368 	{
    369 	  const int_type __ival = traits_type::to_int_type(__val);
    370 	  streambuf_type* __sb = __first._M_sbuf;
    371 	  int_type __c = __sb->sgetc();
    372 	  while (!traits_type::eq_int_type(__c, traits_type::eof())
    373 		 && !traits_type::eq_int_type(__c, __ival))
    374 	    {
    375 	      streamsize __n = __sb->egptr() - __sb->gptr();
    376 	      if (__n > 1)
    377 		{
    378 		  const _CharT* __p = traits_type::find(__sb->gptr(),
    379 							__n, __val);
    380 		  if (__p)
    381 		    __n = __p - __sb->gptr();
    382 		  __sb->__safe_gbump(__n);
    383 		  __c = __sb->sgetc();
    384 		}
    385 	      else
    386 		__c = __sb->snextc();
    387 	    }
    388 
    389 	  if (!traits_type::eq_int_type(__c, traits_type::eof()))
    390 	    __first._M_c = __c;
    391 	  else
    392 	    __first._M_sbuf = 0;
    393 	}
    394       return __first;
    395     }
    396 
    397 // @} group iterators
    398 
    399 _GLIBCXX_END_NAMESPACE_VERSION
    400 } // namespace
    401 
    402 #endif
    403