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