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*,
     55 #ifdef __GXX_EXPERIMENTAL_CXX0X__
     56     // LWG 445.
     57 		      _CharT>
     58 #else
     59 		      _CharT&>
     60 #endif
     61     {
     62     public:
     63       // Types:
     64       //@{
     65       /// Public typedefs
     66       typedef _CharT					char_type;
     67       typedef _Traits					traits_type;
     68       typedef typename _Traits::int_type		int_type;
     69       typedef basic_streambuf<_CharT, _Traits>		streambuf_type;
     70       typedef basic_istream<_CharT, _Traits>		istream_type;
     71       //@}
     72 
     73       template<typename _CharT2>
     74 	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
     75 		                    ostreambuf_iterator<_CharT2> >::__type
     76 	copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
     77 	     ostreambuf_iterator<_CharT2>);
     78 
     79       template<bool _IsMove, typename _CharT2>
     80 	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
     81 					       _CharT2*>::__type
     82 	__copy_move_a2(istreambuf_iterator<_CharT2>,
     83 		       istreambuf_iterator<_CharT2>, _CharT2*);
     84 
     85       template<typename _CharT2>
     86 	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
     87 			            istreambuf_iterator<_CharT2> >::__type
     88 	find(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
     89 	     const _CharT2&);
     90 
     91     private:
     92       // 24.5.3 istreambuf_iterator
     93       // p 1
     94       // If the end of stream is reached (streambuf_type::sgetc()
     95       // returns traits_type::eof()), the iterator becomes equal to
     96       // the "end of stream" iterator value.
     97       // NB: This implementation assumes the "end of stream" value
     98       // is EOF, or -1.
     99       mutable streambuf_type*	_M_sbuf;
    100       mutable int_type		_M_c;
    101 
    102     public:
    103       ///  Construct end of input stream iterator.
    104       _GLIBCXX_CONSTEXPR istreambuf_iterator() _GLIBCXX_USE_NOEXCEPT
    105       : _M_sbuf(0), _M_c(traits_type::eof()) { }
    106 
    107 #ifdef __GXX_EXPERIMENTAL_CXX0X__
    108       istreambuf_iterator(const istreambuf_iterator&) noexcept = default;
    109 
    110       ~istreambuf_iterator() = default;
    111 #endif
    112 
    113       ///  Construct start of input stream iterator.
    114       istreambuf_iterator(istream_type& __s) _GLIBCXX_USE_NOEXCEPT
    115       : _M_sbuf(__s.rdbuf()), _M_c(traits_type::eof()) { }
    116 
    117       ///  Construct start of streambuf iterator.
    118       istreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
    119       : _M_sbuf(__s), _M_c(traits_type::eof()) { }
    120 
    121       ///  Return the current character pointed to by iterator.  This returns
    122       ///  streambuf.sgetc().  It cannot be assigned.  NB: The result of
    123       ///  operator*() on an end of stream is undefined.
    124       char_type
    125       operator*() const
    126       {
    127 #ifdef _GLIBCXX_DEBUG_PEDANTIC
    128 	// Dereferencing a past-the-end istreambuf_iterator is a
    129 	// libstdc++ extension
    130 	__glibcxx_requires_cond(!_M_at_eof(),
    131 				_M_message(__gnu_debug::__msg_deref_istreambuf)
    132 				._M_iterator(*this));
    133 #endif
    134 	return traits_type::to_char_type(_M_get());
    135       }
    136 
    137       /// Advance the iterator.  Calls streambuf.sbumpc().
    138       istreambuf_iterator&
    139       operator++()
    140       {
    141 	__glibcxx_requires_cond(!_M_at_eof(),
    142 				_M_message(__gnu_debug::__msg_inc_istreambuf)
    143 				._M_iterator(*this));
    144 	if (_M_sbuf)
    145 	  {
    146 	    _M_sbuf->sbumpc();
    147 	    _M_c = traits_type::eof();
    148 	  }
    149 	return *this;
    150       }
    151 
    152       /// Advance the iterator.  Calls streambuf.sbumpc().
    153       istreambuf_iterator
    154       operator++(int)
    155       {
    156 	__glibcxx_requires_cond(!_M_at_eof(),
    157 				_M_message(__gnu_debug::__msg_inc_istreambuf)
    158 				._M_iterator(*this));
    159 
    160 	istreambuf_iterator __old = *this;
    161 	if (_M_sbuf)
    162 	  {
    163 	    __old._M_c = _M_sbuf->sbumpc();
    164 	    _M_c = traits_type::eof();
    165 	  }
    166 	return __old;
    167       }
    168 
    169       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    170       // 110 istreambuf_iterator::equal not const
    171       // NB: there is also number 111 (NAD, Future) pending on this function.
    172       /// Return true both iterators are end or both are not end.
    173       bool
    174       equal(const istreambuf_iterator& __b) const
    175       { return _M_at_eof() == __b._M_at_eof(); }
    176 
    177     private:
    178       int_type
    179       _M_get() const
    180       {
    181 	const int_type __eof = traits_type::eof();
    182 	int_type __ret = __eof;
    183 	if (_M_sbuf)
    184 	  {
    185 	    if (!traits_type::eq_int_type(_M_c, __eof))
    186 	      __ret = _M_c;
    187 	    else if (!traits_type::eq_int_type((__ret = _M_sbuf->sgetc()),
    188 					       __eof))
    189 	      _M_c = __ret;
    190 	    else
    191 	      _M_sbuf = 0;
    192 	  }
    193 	return __ret;
    194       }
    195 
    196       bool
    197       _M_at_eof() const
    198       {
    199 	const int_type __eof = traits_type::eof();
    200 	return traits_type::eq_int_type(_M_get(), __eof);
    201       }
    202     };
    203 
    204   template<typename _CharT, typename _Traits>
    205     inline bool
    206     operator==(const istreambuf_iterator<_CharT, _Traits>& __a,
    207 	       const istreambuf_iterator<_CharT, _Traits>& __b)
    208     { return __a.equal(__b); }
    209 
    210   template<typename _CharT, typename _Traits>
    211     inline bool
    212     operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
    213 	       const istreambuf_iterator<_CharT, _Traits>& __b)
    214     { return !__a.equal(__b); }
    215 
    216   /// Provides output iterator semantics for streambufs.
    217   template<typename _CharT, typename _Traits>
    218     class ostreambuf_iterator
    219     : public iterator<output_iterator_tag, void, void, void, void>
    220     {
    221     public:
    222       // Types:
    223       //@{
    224       /// Public typedefs
    225       typedef _CharT                           char_type;
    226       typedef _Traits                          traits_type;
    227       typedef basic_streambuf<_CharT, _Traits> streambuf_type;
    228       typedef basic_ostream<_CharT, _Traits>   ostream_type;
    229       //@}
    230 
    231       template<typename _CharT2>
    232 	friend typename __gnu_cxx::__enable_if<__is_char<_CharT2>::__value,
    233 		                    ostreambuf_iterator<_CharT2> >::__type
    234 	copy(istreambuf_iterator<_CharT2>, istreambuf_iterator<_CharT2>,
    235 	     ostreambuf_iterator<_CharT2>);
    236 
    237     private:
    238       streambuf_type*	_M_sbuf;
    239       bool		_M_failed;
    240 
    241     public:
    242       ///  Construct output iterator from ostream.
    243       ostreambuf_iterator(ostream_type& __s) _GLIBCXX_USE_NOEXCEPT
    244       : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
    245 
    246       ///  Construct output iterator from streambuf.
    247       ostreambuf_iterator(streambuf_type* __s) _GLIBCXX_USE_NOEXCEPT
    248       : _M_sbuf(__s), _M_failed(!_M_sbuf) { }
    249 
    250       ///  Write character to streambuf.  Calls streambuf.sputc().
    251       ostreambuf_iterator&
    252       operator=(_CharT __c)
    253       {
    254 	if (!_M_failed &&
    255 	    _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof()))
    256 	  _M_failed = true;
    257 	return *this;
    258       }
    259 
    260       /// Return *this.
    261       ostreambuf_iterator&
    262       operator*()
    263       { return *this; }
    264 
    265       /// Return *this.
    266       ostreambuf_iterator&
    267       operator++(int)
    268       { return *this; }
    269 
    270       /// Return *this.
    271       ostreambuf_iterator&
    272       operator++()
    273       { return *this; }
    274 
    275       /// Return true if previous operator=() failed.
    276       bool
    277       failed() const _GLIBCXX_USE_NOEXCEPT
    278       { return _M_failed; }
    279 
    280       ostreambuf_iterator&
    281       _M_put(const _CharT* __ws, streamsize __len)
    282       {
    283 	if (__builtin_expect(!_M_failed, true)
    284 	    && __builtin_expect(this->_M_sbuf->sputn(__ws, __len) != __len,
    285 				false))
    286 	  _M_failed = true;
    287 	return *this;
    288       }
    289     };
    290 
    291   // Overloads for streambuf iterators.
    292   template<typename _CharT>
    293     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    294     	                 	    ostreambuf_iterator<_CharT> >::__type
    295     copy(istreambuf_iterator<_CharT> __first,
    296 	 istreambuf_iterator<_CharT> __last,
    297 	 ostreambuf_iterator<_CharT> __result)
    298     {
    299       if (__first._M_sbuf && !__last._M_sbuf && !__result._M_failed)
    300 	{
    301 	  bool __ineof;
    302 	  __copy_streambufs_eof(__first._M_sbuf, __result._M_sbuf, __ineof);
    303 	  if (!__ineof)
    304 	    __result._M_failed = true;
    305 	}
    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(_CharT* __first, _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 				    ostreambuf_iterator<_CharT> >::__type
    324     __copy_move_a2(const _CharT* __first, const _CharT* __last,
    325 		   ostreambuf_iterator<_CharT> __result)
    326     {
    327       const streamsize __num = __last - __first;
    328       if (__num > 0)
    329 	__result._M_put(__first, __num);
    330       return __result;
    331     }
    332 
    333   template<bool _IsMove, typename _CharT>
    334     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    335     				    _CharT*>::__type
    336     __copy_move_a2(istreambuf_iterator<_CharT> __first,
    337 		   istreambuf_iterator<_CharT> __last, _CharT* __result)
    338     {
    339       typedef istreambuf_iterator<_CharT>                  __is_iterator_type;
    340       typedef typename __is_iterator_type::traits_type     traits_type;
    341       typedef typename __is_iterator_type::streambuf_type  streambuf_type;
    342       typedef typename traits_type::int_type               int_type;
    343 
    344       if (__first._M_sbuf && !__last._M_sbuf)
    345 	{
    346 	  streambuf_type* __sb = __first._M_sbuf;
    347 	  int_type __c = __sb->sgetc();
    348 	  while (!traits_type::eq_int_type(__c, traits_type::eof()))
    349 	    {
    350 	      const streamsize __n = __sb->egptr() - __sb->gptr();
    351 	      if (__n > 1)
    352 		{
    353 		  traits_type::copy(__result, __sb->gptr(), __n);
    354 		  __sb->__safe_gbump(__n);
    355 		  __result += __n;
    356 		  __c = __sb->underflow();
    357 		}
    358 	      else
    359 		{
    360 		  *__result++ = traits_type::to_char_type(__c);
    361 		  __c = __sb->snextc();
    362 		}
    363 	    }
    364 	}
    365       return __result;
    366     }
    367 
    368   template<typename _CharT>
    369     typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value,
    370 		  		    istreambuf_iterator<_CharT> >::__type
    371     find(istreambuf_iterator<_CharT> __first,
    372 	 istreambuf_iterator<_CharT> __last, const _CharT& __val)
    373     {
    374       typedef istreambuf_iterator<_CharT>                  __is_iterator_type;
    375       typedef typename __is_iterator_type::traits_type     traits_type;
    376       typedef typename __is_iterator_type::streambuf_type  streambuf_type;
    377       typedef typename traits_type::int_type               int_type;
    378 
    379       if (__first._M_sbuf && !__last._M_sbuf)
    380 	{
    381 	  const int_type __ival = traits_type::to_int_type(__val);
    382 	  streambuf_type* __sb = __first._M_sbuf;
    383 	  int_type __c = __sb->sgetc();
    384 	  while (!traits_type::eq_int_type(__c, traits_type::eof())
    385 		 && !traits_type::eq_int_type(__c, __ival))
    386 	    {
    387 	      streamsize __n = __sb->egptr() - __sb->gptr();
    388 	      if (__n > 1)
    389 		{
    390 		  const _CharT* __p = traits_type::find(__sb->gptr(),
    391 							__n, __val);
    392 		  if (__p)
    393 		    __n = __p - __sb->gptr();
    394 		  __sb->__safe_gbump(__n);
    395 		  __c = __sb->sgetc();
    396 		}
    397 	      else
    398 		__c = __sb->snextc();
    399 	    }
    400 
    401 	  if (!traits_type::eq_int_type(__c, traits_type::eof()))
    402 	    __first._M_c = __c;
    403 	  else
    404 	    __first._M_sbuf = 0;
    405 	}
    406       return __first;
    407     }
    408 
    409 // @} group iterators
    410 
    411 _GLIBCXX_END_NAMESPACE_VERSION
    412 } // namespace
    413 
    414 #endif
    415