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