// iterator standard header
#ifndef _ITERATOR_
#define _ITERATOR_
#include <istream>
#include <xutility>
_STD_BEGIN

		// TEMPLATE CLASS back_insert_iterator
template<class _Container>
	class back_insert_iterator
		: public _Outit
	{	// wrap pushes to back of container as output iterator
public:
	typedef _Container container_type;
	typedef typename _Container::reference reference;

	explicit back_insert_iterator(_Container& _Cont)
		: container(&_Cont)
		{	// construct with container
		}

	back_insert_iterator<_Container>& operator=(
		typename _Container::const_reference _Val)
		{	// push value into container
		container->push_back(_Val);
		return (*this);
		}

	back_insert_iterator<_Container>& operator*()
		{	// pretend to return designated value
		return (*this);
		}

	back_insert_iterator<_Container>& operator++()
		{	// pretend to preincrement
		return (*this);
		}

	back_insert_iterator<_Container> operator++(int)
		{	// pretend to postincrement
		return (*this);
		}

protected:
	_Container *container;	// pointer to container
	};

		// TEMPLATE FUNCTION back_inserter
template<class _Container> inline
	back_insert_iterator<_Container> back_inserter(_Container& _Cont)
	{	// return a back_insert_iterator
	return (_STD back_insert_iterator<_Container>(_Cont));
	}

		// TEMPLATE CLASS front_insert_iterator
template<class _Container>
	class front_insert_iterator
		: public _Outit
	{	// wrap pushes to front of container as output iterator
public:
	typedef _Container container_type;
	typedef typename _Container::reference reference;

	explicit front_insert_iterator(_Container& _Cont)
		: container(&_Cont)
		{	// construct with container
		}

	front_insert_iterator<_Container>& operator=(
		typename _Container::const_reference _Val)
		{	// push value into container
		container->push_front(_Val);
		return (*this);
		}

	front_insert_iterator<_Container>& operator*()
		{	// pretend to return designated value
		return (*this);
		}

	front_insert_iterator<_Container>& operator++()
		{	// pretend to preincrement
		return (*this);
		}

	front_insert_iterator<_Container> operator++(int)
		{	// pretend to postincrement
		return (*this);
		}

protected:
	_Container *container;	// pointer to container
	};

		// TEMPLATE FUNCTION front_inserter
template<class _Container> inline
	front_insert_iterator<_Container> front_inserter(_Container& _Cont)
	{	// return front_insert_iterator
	return (_STD front_insert_iterator<_Container>(_Cont));
	}

		// TEMPLATE CLASS insert_iterator
template<class _Container>
	class insert_iterator
		: public _Outit
	{	// wrap inserts into container as output iterator
public:
	typedef _Container container_type;
	typedef typename _Container::reference reference;

	insert_iterator(_Container& _Cont, typename _Container::iterator _Where)
		: container(&_Cont), iter(_Where)
		{	// construct with container and iterator
		}

	insert_iterator<_Container>& operator=(
		typename _Container::const_reference _Val)
		{	// insert into container and increment stored iterator
		iter = container->insert(iter, _Val);
		++iter;
		return (*this);
		}

	insert_iterator<_Container>& operator*()
		{	// pretend to return designated value
		return (*this);
		}

	insert_iterator<_Container>& operator++()
		{	// pretend to preincrement
		return (*this);
		}

	insert_iterator<_Container>& operator++(int)
		{	// pretend to postincrement
		return (*this);
		}

protected:
	_Container *container;	// pointer to container
	typename _Container::iterator iter;	// iterator into container
	};

		// TEMPLATE FUNCTION inserter
template<class _Container,
	class _Iter> inline
	insert_iterator<_Container> inserter(_Container& _Cont, _Iter _Where)
	{	// return insert_iterator
	return (_STD insert_iterator<_Container>(_Cont, _Where));
	}

		// TEMPLATE CLASS istream_iterator

 #if _IS_EMBEDDED
template<class _Ty,
	class _Elem,
	class _Traits,
	class _Diff>
	struct _Istream_iter_base
		: public iterator<input_iterator_tag, _Ty, _Diff,
			const _Ty *, const _Ty&>
	{	// define istream_type
	typedef istream istream_type;
	};

template<class _Ty,
	class _Elem = char,
	class _Traits = char_traits,
	class _Diff = ptrdiff_t>
	class istream_iterator
		: public _Istream_iter_base<_Ty, _Elem, _Traits, _Diff>
	{	// wrap _Ty extracts from input stream as input iterator
	typedef _Istream_iter_base<_Ty, _Elem, _Traits, _Diff> _Mybase;
	typedef istream_iterator<_Ty, _Elem, _Traits, _Diff> _Myt;
public:
	typedef _Elem char_type;
	typedef _Traits traits_type;
	typedef typename _Mybase::istream_type istream_type;

 #else /* _IS_EMBEDDED */
template<class _Ty,
	class _Elem = char,
	class _Traits = char_traits<_Elem>,
	class _Diff = ptrdiff_t>
	class istream_iterator
		: public iterator<input_iterator_tag, _Ty, _Diff,
			const _Ty *, const _Ty&>
	{	// wrap _Ty extracts from input stream as input iterator
	typedef istream_iterator<_Ty, _Elem, _Traits, _Diff> _Myt;
public:
	typedef _Elem char_type;
	typedef _Traits traits_type;
	typedef basic_istream<_Elem, _Traits> istream_type;
 #endif /* _IS_EMBEDDED */

	istream_iterator()
		: _Myistr(0)
		{	// construct singular iterator
		}

	istream_iterator(istream_type& _Istr)
		: _Myistr(&_Istr)
		{	// construct with input stream
		_Getval();
		}

	const _Ty& operator*() const
		{	// return designated value

 #if _HAS_ITERATOR_DEBUGGING
		if (_Myistr == 0)
			_DEBUG_ERROR("istream_iterator is not dereferencable");
 #endif /* _HAS_ITERATOR_DEBUGGING */

		return (_Myval);
		}

	const _Ty *operator->() const
		{	// return pointer to class object
		return (&**this);
		}

	_Myt& operator++()
		{	// preincrement

 #if _HAS_ITERATOR_DEBUGGING
		if (_Myistr == 0)
			_DEBUG_ERROR("istream_iterator is not incrementable");
 #endif /* _HAS_ITERATOR_DEBUGGING */

		_Getval();
		return (*this);
		}

	_Myt operator++(int)
		{	// postincrement
		_Myt _Tmp = *this;
		++*this;
		return (_Tmp);
		}

	bool _Equal(const _Myt& _Right) const
		{	// test for iterator equality
		return (_Myistr == _Right._Myistr);
		}

protected:
	void _Getval()
		{	// get a _Ty value if possible
		if (_Myistr != 0 && !(*_Myistr >> _Myval))
			_Myistr = 0;
		}

	istream_type *_Myistr;	// pointer to input stream
	_Ty _Myval;	// lookahead value (valid if _Myistr is not null)
	};

		// istream_iterator TEMPLATE OPERATORS
template<class _Ty,
	class _Elem,
	class _Traits,
	class _Diff> inline
	bool operator==(
		const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _Left,
		const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _Right)
	{	// test for istream_iterator equality
	return (_Left._Equal(_Right));
	}

template<class _Ty,
	class _Elem,
	class _Traits,
	class _Diff> inline
	bool operator!=(
		const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _Left,
		const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _Right)
	{	// test for istream_iterator inequality
	return (!(_Left == _Right));
	}

		// TEMPLATE CLASS ostream_iterator

 #if _IS_EMBEDDED
template<class _Ty,
	class _Elem,
	class _Traits>
	struct _Ostream_iter_base
		: public _Outit
	{	// define ostream_type
	typedef ostream ostream_type;
	};

template<class _Ty,
	class _Elem = char,
	class _Traits = char_traits >
	class ostream_iterator
		: public _Ostream_iter_base<_Ty, _Elem, _Traits>
	{	// wrap _Ty inserts to output stream as output iterator
	typedef _Ostream_iter_base<_Ty, _Elem, _Traits> _Mybase;
public:
	typedef _Elem char_type;
	typedef _Traits traits_type;
	typedef typename _Mybase::ostream_type ostream_type;

 #else /* _IS_EMBEDDED */
template<class _Ty,
	class _Elem = char,
	class _Traits = char_traits<_Elem> >
	class ostream_iterator
		: public _Outit
	{	// wrap _Ty inserts to output stream as output iterator
public:
	typedef _Elem char_type;
	typedef _Traits traits_type;
	typedef basic_ostream<_Elem, _Traits> ostream_type;
 #endif /* _IS_EMBEDDED */

	ostream_iterator(ostream_type& _Ostr,
		const _Elem *_Delim = 0)
		: _Myostr(&_Ostr), _Mydelim(_Delim)
		{	// construct from output stream and delimiter
		}

	ostream_iterator<_Ty, _Elem, _Traits>& operator=(const _Ty& _Val)
		{	// insert value into output stream, followed by delimiter
		*_Myostr << _Val;
		if (_Mydelim != 0)
			*_Myostr << _Mydelim;

 #if _HAS_ITERATOR_DEBUGGING
		if (!*_Myostr)
			_DEBUG_ERROR("ostream_iterator is not dereferencable");
 #endif /* _HAS_ITERATOR_DEBUGGING */

		return (*this);
		}

	ostream_iterator<_Ty, _Elem, _Traits>& operator*()
		{	// pretend to return designated value
		return (*this);
		}

	ostream_iterator<_Ty, _Elem, _Traits>& operator++()
		{	// pretend to preincrement
		return (*this);
		}

	ostream_iterator<_Ty, _Elem, _Traits> operator++(int)
		{	// pretend to postincrement
		return (*this);
		}

protected:
	const _Elem *_Mydelim;	// pointer to delimiter string (NB: not freed)
	ostream_type *_Myostr;	// pointer to output stream
	};
_STD_END
#endif /* _ITERATOR_ */

/*
 * Copyright (c) 1992-2003 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 */

/*
 * This file is derived from software bearing the following
 * restrictions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this
 * software and its documentation for any purpose is hereby
 * granted without fee, provided that the above copyright notice
 * appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation.
 * Hewlett-Packard Company makes no representations about the
 * suitability of this software for any purpose. It is provided
 * "as is" without express or implied warranty.
V4.02:0216 */
