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