//  iterator : headerfile for the free standard C++ library
//  
//  Copyright (C) 1999 by the free standard C++ Library Team
//                        see AUTHORS for more details
//
//  Homepage : http://www.inf.fu-berlin.de/~mkrueger/fscl/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either	
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Library General Public License for more details.
//  You should have received a copy of the GNU Library General Public
//  License along with this library; if not, write to the Free
//  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//  version : 0.1 last modified : 17.09.99


#ifndef __CPP_ITERATOR
#define __CPP_ITERATOR

#include<cstddef>
#include<iosfwd>
#include<streambuf>
#include<istream>
#include<ostream>

namespace std {

	// 24.3, primitives :
	struct input_iterator_tag                                             {};
	struct output_iterator_tag                                            {};	
	struct forward_iterator_tag       : public input_iterator_tag         {};	
	struct bidirectional_iterator_tag : public forward_iterator_tag       {};
	struct random_access_iterator_tag : public bidirectional_iterator_tag {};

	// 24.3.1 Iterator traits
	template<class Iterator> 
	struct iterator_traits 
	{
		typedef typename Iterator::difference_type   difference_type;
		typedef typename Iterator::value_type        value_type;
		typedef typename Iterator::pointer           pointer;
		typedef typename Iterator::reference         reference;
		typedef typename Iterator::iterator_category iterator_category;
	};
	
	
	template<class T>
	struct iterator_traits<T*> 
	{
		typedef ptrdiff_t difference_type;
		typedef T         value_type;
		typedef T*        pointer;
		typedef T&        reference;
		typedef random_access_iterator_tag iterator_category; 	
	};
	
	// not in the standard, but I did need it somewhere (can't remember where)
	template<class T>
	struct iterator_traits<const T*> 
	{
		typedef ptrdiff_t difference_type;
		typedef const T   value_type;
		typedef const T*  pointer;
		typedef const T&  reference;
		typedef random_access_iterator_tag iterator_category;
	};

	template<class Category, class T, class Distance = ptrdiff_t,
	         class Pointer = T*, class Reference = T&>
	struct iterator 
	{
		typedef T         value_type;
		typedef Distance  difference_type;
		typedef Pointer   pointer;
		typedef Reference reference;
		typedef Category  iterator_category;
	};	
	
	// 24.3.4, iterator operations:
	template <class InputIterator, class Distance>
	void advance(InputIterator& i, Distance n)
	{
		while (n--) 
			i++;
	}	
	
	template <class InputIterator>
	typename iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last)
	{
		return last - first;
	}
	
	// 24.4, predefined iterators:

	// 24.4.1.1 Template class reverse_iterator
	template <class Iterator>
	class reverse_iterator : 
	public iterator<iterator_traits<Iterator>::iterator_category,
	                iterator_traits<Iterator>::value_type,
	                iterator_traits<Iterator>::difference_type,
	                iterator_traits<Iterator>::pointer,
	                iterator_traits<Iterator>::reference> 
 	{
		protected:
			Iterator current;
		public:
			typedef Iterator                                            iterator_type;
			typedef typename iterator_traits<Iterator>::difference_type difference_type;
			typedef typename iterator_traits<Iterator>::reference       reference;
			typedef typename iterator_traits<Iterator>::pointer         pointer;

			reverse_iterator() 
			: current()
			{
			}

			explicit reverse_iterator(Iterator x) 
			: current(x)
			{
			}

			Iterator base() const
			{
				return current;
			}
		
			reference operator*() const
			{
				Iterator tmp = current;
				return *--tmp;
			}
		
			pointer operator->() const
			{
				return &(operator*());
			}

			reverse_iterator& operator++()
			{
				--current;
				return *this;
			}
		
			reverse_iterator  operator++(int)
			{
				reverse_iterator tmp = *this;
				--current;
				return tmp;
			}
		
			reverse_iterator& operator--()
			{
				++current;
				return *this;
			}
		
			reverse_iterator operator--(int)
			{
				reverse_iterator tmp = *this;
				++current;
				return tmp;
			}
		
			reverse_iterator  operator+(difference_type n) const
			{
				return reverse_iterator(current - n);
			}
		
			reverse_iterator& operator+=(difference_type n)
			{
				current -= n;
				return *this;
			}
		
			reverse_iterator  operator-(difference_type n) const
			{
				return reverse_iterator(current + n);
			}
		
			reverse_iterator& operator-=(difference_type n)
			{
				current += n;
				return *this;		
			}
		
			reference operator[](difference_type n) const
			{
				return current[-n-1];
			}
	};
	
	template <class Iterator>
	inline bool operator==(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)
	{
		return x.base() == y.base();
	}
	template <class Iterator>
	inline bool operator<(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)
	{
		return y.base() < x.base(); 
	}
	template <class Iterator>
	inline bool operator!=(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)
	{
		return !(x.base() == y.base());
	}
	template <class Iterator>
	inline bool operator>(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)
	{
		return x.base() < y.base();
	}
	template <class Iterator>
	inline bool operator>=(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)
	{
		return !(x < y);
	}
	template <class Iterator>
	inline bool operator<=(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)
	{
		return !(y < x);
	}
	
	template <class Iterator>
	inline typename reverse_iterator<Iterator>::difference_type operator-(const reverse_iterator<Iterator>& x, const reverse_iterator<Iterator>& y)
	{
		return y.base() - x.base();
	}

	template <class Iterator>
	inline reverse_iterator<Iterator> operator+(typename reverse_iterator<Iterator>::difference_type n, const reverse_iterator<Iterator>& x)
	{
		return reverse_iterator<Iterator> (x.base() - n);
	}

	template <class Container>
	class back_insert_iterator : public iterator<output_iterator_tag, void, void, void, void>
	{
		protected:
			Container& container;
		public:
			typedef Container container_type;
			explicit back_insert_iterator(Container& x) : container(x)
			{	
			}
		
			back_insert_iterator<Container>& operator=(const typename Container::value_type& value)
			{
				container->push_back(value);
				return *this;
			}
		
			back_insert_iterator<Container>& operator*()
			{
				return *this;
			}

			back_insert_iterator<Container>& operator++()
			{
				return *this;
			}

			back_insert_iterator<Container> operator++(int)
			{
				return *this;
			}
	};

	template <class Container>
	inline back_insert_iterator<Container> back_inserter(Container& x)
	{
		return back_insert_iterator<Container>(x);
	}

	// 24.4.2.3 Template class front_insert_iterator
	template <class Container>
	class front_insert_iterator : public iterator<output_iterator_tag, void, void, void, void>
	{
		protected:
			Container& container;
		public:
			typedef Container container_type;
			typedef typename Container::value_type value_type;
		
			explicit front_insert_iterator(Container& x) : container(x)
			{
			}

			front_insert_iterator<Container>& operator=(const typename Container::value_type& value)
			{
				container.push_front(value);
				return *this;
			}

			front_insert_iterator<Container>& operator*()
			{
				return *this; 
			}

			front_insert_iterator<Container>& operator++()
			{
				return *this; 
			}

			front_insert_iterator<Container> operator++(int)
			{
				return *this; 
			}

	};

	template <class Container>
	inline front_insert_iterator<Container> front_inserter(Container& x)
	{
		return front_insert_iterator<Container>(x);
	}
	
	// 24.4.2.5 Template class insert_iterator
	template <class Container> 
	class insert_iterator : public iterator<output_iterator_tag, void, void, void, void>
	{
		protected:
			Container& container;
			typename Container::iterator iter;
		public:
			typedef Container container_type;
			insert_iterator(Container& x, typename Container::iterator i)
			:container(x), iter(i)
			{
			}
			insert_iterator<Container>& operator=(const typename Container::value_type& value)
			{
				iter = container.insert(iter, value);
				return *this;
			}
			insert_iterator<Container>& operator*()
			{
				return *this;
			}
			insert_iterator<Container>& operator++()
			{
				return *this;
			}
			insert_iterator<Container>& operator++(int)
			{
				return *this;
			}
	};

	template <class Container, class Iterator>
	inline insert_iterator<Container> inserter(Container& x, Iterator i)
	{
		return insert_iterator<Container>(x, Container::iterator(i));
	}

	// 24.5, stream iterators:
	template <class T, class charT = char, class traits = char_traits<charT>, class Distance = ptrdiff_t>
	class istream_iterator : public iterator<input_iterator_tag, T, Distance, const T*, const T&>
	{
		public:
			typedef charT                        char_type;
			typedef traits                       traits_type;
			typedef basic_istream<charT, traits> istream_type;
		
			istream_iterator() : in_stream(0)
			{
				eof = true;
			}
			
			istream_iterator(istream_type& s) : in_stream(&s)
			{
				eof = false;
				*in_stream >> value;
			}
					
			istream_iterator(const istream_iterator<T,charT,traits,Distance>& x) : in_stream(x.in_stream)
			{
				eof = false;
			}
		
			~istream_iterator()
			{
			}
		
			const T &operator*() const
			{
				return value;
			}
			
			const T *operator->() const
			{
				return &(operator*());
			}
		
			istream_iterator<T, charT, traits, Distance>& operator++()
			{
				*in_stream >> value;
				return *this;
			}
			
			istream_iterator<T, charT, traits, Distance> operator++(int)
			{
				istream_iterator<T, charT, traits, Distance> tmp = *this;
				*in_stream >> value;
				return tmp;
			}
		private:
			basic_istream<charT,traits> *in_stream;
			bool eof;
			T value;
	};

	// TODO : TEST STREAM ITERATORS
	template <class T, class charT, class traits, class Distance>
	inline bool operator==(const istream_iterator<T,charT,traits,Distance>& x, const istream_iterator<T,charT,traits,Distance>& y)
	{ 
		return *x.in_stream == *y.in_stream;
	}

	template <class T, class charT, class traits, class Distance>
	inline bool operator!=(const istream_iterator<T,charT,traits,Distance>& x, const istream_iterator<T,charT,traits,Distance>& y)
	{
		return !(x == y);
	}

	// 24.5.2 Template class ostream_iterator
	template <class T, class charT = char, class traits = char_traits<charT> >
	class ostream_iterator : public iterator<output_iterator_tag, void, void, void, void> 
	{
		private:
			basic_ostream<charT,traits> *out_stream;
			const char *delim;
	    public:
			typedef charT  char_type;
			typedef traits traits_type;
			typedef basic_ostream<charT,traits> ostream_type;
		
			ostream_iterator(ostream_type &s) 
			: out_stream(&s), delim(0)
			{
			}
		
			ostream_iterator(ostream_type &s, const charT* delimiter) 
			: out_stream(&s), delim(delimiter)
			{
			}
		
			ostream_iterator(const ostream_iterator<T,charT,traits> &x) 
			{
				out_stream = x.out_stream;
				delim      = x.delim;
			}	
		
			~ostream_iterator()
			{
			}

			ostream_iterator<T,charT,traits> &operator=(const T& value)
			{
				*out_stream << value;
				if (delim != 0)
					*out_stream << delim;
				return *this;
			}

			ostream_iterator<T,charT,traits> &operator*()
			{
				return *this;
			}

			ostream_iterator<T,charT,traits> &operator++()
			{
				return *this;
			}

			ostream_iterator<T,charT,traits> &operator++(int)
			{
				return *this;
			}
	};

	template<class charT, class traits = char_traits<charT> >
	class istreambuf_iterator : public iterator<input_iterator_tag, charT, typename traits::off_type, charT*, charT&>
	{
		private:
			basic_streambuf<charT,traits> *sbuf;
		public:
			typedef charT                         char_type;
			typedef traits                        traits_type;
			typedef typename traits::int_type     int_type;
			typedef basic_streambuf<charT,traits> streambuf_type;
			typedef basic_istream<charT,traits>   istream_type;

			class proxy
			{
				public:
					proxy(charT c,  basic_streambuf<charT, traits>* sb) : keep(c), sbuf(sb)
					{
					}
					charT operator*()
					{
						return keep;
					}
				protected:
					charT keep;
					basic_streambuf<charT,traits>* sbuf;					
			};

			istreambuf_iterator() throw() : sbuf(0)
			{
			}		
			
			istreambuf_iterator(istream_type &s) throw() : sbuf(*s) // or sbuf(*(s.rdbuf())
			{
			}
			
			istreambuf_iterator(streambuf_type* s) throw() : sbuf(*s) // or sbuf(*(s.rdbuf())
			{
			}
					
			istreambuf_iterator(const proxy& p) throw() : sbuf(p.sb)
			{
			}

			charT operator*() const
			{
				return sbuf->sgetc();
			}

			istreambuf_iterator<charT,traits>& operator++()
			{
				sbuf->sbumpc();
				return *this;
			}

			proxy operator++(int)
			{
				istreambuf_iterator<charT,traits> tmp = *this;
				sbuf->sbumpc();
				return tmp;
			}

			bool equal(istreambuf_iterator &b)
			{
				return b.eos && sbuf.eos || !(!b.eos && !sbuf.eos);
			}
	};

	template <class charT, class traits>
	inline bool operator==(const istreambuf_iterator<charT,traits>& a, const istreambuf_iterator<charT,traits>& b)
	{
		return a.equal(b);
	}

	template <class charT, class traits>
	inline bool operator!=(const istreambuf_iterator<charT,traits>& a, const istreambuf_iterator<charT,traits>& b)
	{
		return !a.equal(b);
	}

	template <class charT, class traits = char_traits<charT> >
	class ostreambuf_iterator : iterator<output_iterator_tag, void, void, void, void>
	{
		private:
			bool teof;
			basic_streambuf<charT,traits>* sbuf;
		public:
			typedef charT                         char_type;
			typedef traits                        traits_type;
			typedef basic_streambuf<charT,traits> streambuf_type;
			typedef basic_ostream<charT,traits>   ostream_type;
			
			ostreambuf_iterator(ostream_type &s) throw() : sbuf(s.rdbuf()), teof(false)
			{
			}

			ostreambuf_iterator(streambuf_type *s) throw() : sbuf(s), teof(false)
			{
			}

			ostreambuf_iterator& operator=(charT c)
			{
				if (sbuf->failed())
					if (sbuf->sputc(c) == traits::eof())
						teof = true;
				return *this;
			}

			ostreambuf_iterator& operator*()
			{
				return *this;
			}

			ostreambuf_iterator& operator++()
			{
				return *this;
			}

			ostreambuf_iterator& operator++(int)			
			{
				return *this;
			}

			bool failed() const throw()
			{
				return teof;
			}
	};
}

#endif
