//  ostream : 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_OSTREAM
#define __CPP_OSTREAM

#include<cstddef>
#include<new>

#include<iosfwd>
#include<ios>
#include<cstdio>

namespace std {
	
	template <class charT, class traits>
	class basic_ostream : virtual public basic_ios<charT,traits>
	{
		public:
			typedef typename traits::int_type int_type;
			typedef typename traits::pos_type pos_type;
			typedef typename traits::off_type off_type;	
			
			explicit basic_ostream(basic_streambuf<charT,traits> *sb) : basic_ios<charT, traits>(sb)
			{
			}
			
			virtual ~basic_ostream()
			{
			}
			
 			class sentry
			{
					bool ok_;
				public:
					explicit sentry(basic_ostream<charT,traits> &os)
					{
					}
					
					~sentry()
					{
					}
					
					operator bool() 
					{
						return ok_;
					} 
			};
			
			basic_ostream<charT,traits> &operator<<(basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&))
			{			
				return pf(*this);
			}
			
			basic_ostream<charT,traits> &operator<<(basic_ios<charT,traits>& (*pf)(basic_ios<charT,traits>&))
			{
				pf(*this);
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(ios_base& (*pf)(ios_base &))
			{
				pf(*this);
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(charT* p)
			{
				write(p, traits::length(p));
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(const charT* p)
			{
				write(p, traits::length(p));
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(bool n)
			{
/*				if (flags()&&ios_base::boolalpha)
					put((charT)n ? 't' : 'f'); 
				else */
					put((charT)n ? '1' : '0'); // 1 - 0
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(short n)
			{
				if (n < 0) {
					put( (charT)'-');
					n*=-1;
				}
				if (n >= curfmt.base)
					*this << (n / curfmt.base);
				put((charT)numbers[n%curfmt.base]);				
				return *this;
			}
			
			
			basic_ostream<charT,traits> &operator<<(unsigned short n)
			{
				if (n >= curfmt.base)
					*this << (n / curfmt.base);				
				put((charT)numbers[n%curfmt.base]);
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(int n)
			{
				if (n < 0) {
					put( (charT)'-');
					n*=-1;
				}
				if (n >= curfmt.base)
					*this << (n / curfmt.base);
				put((charT)numbers[n%curfmt.base]);				
				
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(unsigned int n)
			{
				if (n >= (unsigned int)curfmt.base)
					*this << (n / curfmt.base);
				put((charT)numbers[n%curfmt.base]);				
				return *this;
			}
						
			basic_ostream<charT,traits> &operator<<(long n)
			{
				if (n < 0) {
					put( (charT)'-');
					n*=-1;
				}
				if (n >= curfmt.base)
					*this << (n / curfmt.base);				
				put((charT)numbers[n%curfmt.base]);				
				
				return *this;
			}

			basic_ostream<charT,traits> &operator<<(unsigned long n)
			{
				if (n >=(unsigned long) curfmt.base)
					*this << (n / curfmt.base);
				put((charT)numbers[n%curfmt.base]);
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(float f)
			{
				printf("todo11\n");
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(double f)
			{
				printf("todo12\n");
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(long double f)
			{
				printf("todo13\n");
				return *this;
			}
			
			basic_ostream<charT,traits> &operator<<(void* p)
			{
				while ((int)*p) 
					put((charT)*p++);
				return *this;
			}

			basic_ostream<charT,traits> &operator<<(basic_streambuf<charT, traits>* sb)
			{ // TODO : TEST THIS FUNCTION
				if (sb == 0)
					setstate(badbit);
				int_type read = sb->bumpc();
				while (read != traits::eof()) {
					put(traits::to_char_type(read));
					read = sb->bumpc();
				}
				return *this;
			}
			
			basic_ostream<charT, traits> &put(charT c)
			{
				rdbuf()->sputc(c);
				return *this;
			}			

			basic_ostream<charT,traits> &write(const charT *s, streamsize n)
			{
				rdbuf()->sputn(s, n);
				return *this;
			}
			
			basic_ostream<charT,traits> &flush()
			{
				if (rdbuf() !=0 )
					if (rdbuf()->pubsync() == -1)
						setstate(ios_base::badbit);
				return *this;
			}
			
			pos_type tellp()
			{
				if (!fail())
					return rdbuf()->pubseekoff(0, cur, out);
				else
					return pos_type(-1); 
			}

			basic_ostream<charT,traits> &seekp(pos_type)
			{
				if (!fail())
					rdbuf()->pubseekpos(pos);
				return *this;
			}

			basic_ostream<charT,traits> &seekp(off_type, ios_base::seekdir)
			{
				if (!fail())
					rdbuf()->pubseekoff(off, dir);
				return *this;
			}
		private:
			static const char* numbers;
	};
	
	template <class charT, class traits >
	const char* basic_ostream<charT,traits>::numbers = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

	typedef basic_ostream<char>     ostream;
	typedef basic_ostream<wchar_t> wostream;

	template <class charT, class traits>
	basic_ostream<charT,traits> &endl(basic_ostream<charT,traits> &os)
	{		
		return os.put('\n');
	}

	template <class charT, class traits>
	basic_ostream<charT,traits> &ends(basic_ostream<charT,traits> &os)
	{
		return os.put('\0');
	}

	template <class charT, class traits>
	basic_ostream<charT,traits> &flush(basic_ostream<charT,traits> &os)
	{
		return os.flush();
	}
	
	// Character inserters
	template <class charT, class traits>
	basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out, char c)
	{
		out.put(c);
		return out;
	}
	
	template <class charT, class traits>
	basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& out, unsigned char c)
	{
		out.put(c);
		return out;
	}

}
#endif
