//  sstream : 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_SSTREAM
#define __CPP_SSTREAM

#include<iosfwd>
#include<streambuf>
#include<string>

namespace std {
	
	template <class charT, class traits, class Allocator>
	class basic_stringbuf : public basic_streambuf<charT,traits>
	{
		public:
			typedef charT                     char_type;
			typedef typename traits::int_type int_type;
			typedef typename traits::pos_type pos_type;
			typedef typename traits::off_type off_type;
			
			explicit basic_stringbuf(ios_base::openmode which = ios_base::in | ios_base::out)	
			: basic_streambuf<charT, traits>()
			{
				mode = which;
				curchar = 0;
			}

			explicit basic_stringbuf(const basic_string<charT,traits,Allocator>& s, ios_base::openmode which = ios_base::in | ios_base::out)
			: basic_streambuf<charT, traits>()
			{
				mode = which;
				str(s);
			}

			basic_string<charT,traits,Allocator> str() const
			{
				return *s;
			}

			void str(const basic_string<charT,traits,Allocator> &s)
			{
				curchar = 0;
				this->s = (basic_string<charT,traits,Allocator>*)&s;
			}

		protected:

			virtual int_type underflow()
			{
				if (curchar >= s->size()-1) 
					return traits::eof();
				return traits::to_int_type((*s)[curchar++]);
			}

			virtual int_type   pbackfail(int_type c = traits::eof())
			{
				if (!traits::eq_int_type(c,traits::eof()))
					(*s)[curchar] = c;
				curchar--;
				return c;
			}
			
			virtual int_type   overflow (int_type c = traits::eof())
			{
				if (!traits::eq_int_type(c,traits::eof()))
					(*s) += traits::to_char_type(c);
				return c;
			}
			
			virtual  basic_streambuf<charT,traits>* setbuf(charT*, streamsize)
			{
				return this;
			}

			/* TODO
			virtual pos_type   seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out)
			{			
			}
			
			virtual pos_type   seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out)
			{
			}*/
			
		private:
			ios_base::openmode                    mode;
			basic_string<charT,traits,Allocator>* s;
			size_t                                curchar;
	};
	
	typedef basic_stringbuf<char>     stringbuf;
	typedef basic_stringbuf<wchar_t> wstringbuf;
	
	template <class charT, class traits, class Allocator>
	class basic_istringstream : public basic_istream<charT,traits>
	{
		public:
			typedef charT                     char_type;
			typedef typename traits::int_type int_type;
			typedef typename traits::pos_type pos_type;
			typedef typename traits::off_type off_type;

			explicit basic_istringstream(ios_base::openmode which = ios_base::in)
			: basic_istream<charT, traits>(&sb), basic_ios<charT, traits>(&sb)
			{
			}
			
			explicit basic_istringstream(const basic_string<charT,traits,Allocator>& str, ios_base::openmode which = ios_base::in)
			: basic_istream<charT, traits>(&sb), basic_ios<charT, traits>(&sb)			
			{
				sb.str(str);
			}

			basic_stringbuf<charT,traits,Allocator>* rdbuf() const
			{
				return this->sb;
			}
			
			basic_string<charT,traits,Allocator> str() const
			{
				return sb.str();
			}
			
			void str(const basic_string<charT,traits,Allocator>& s)
			{
				sb.str(s);
			}
			
		private:
			basic_stringbuf<charT,traits,Allocator> sb;
	};
	
	typedef basic_istringstream<char>     istringstream;
	typedef basic_istringstream<wchar_t> wistringstream;
	
	template <class charT, class traits, class Allocator>
	class basic_ostringstream : public basic_ostream<charT,traits>
	{
		public:
			typedef charT            char_type;
			typedef typename traits::int_type int_type;
			typedef typename traits::pos_type pos_type;
			typedef typename traits::off_type off_type;

			explicit basic_ostringstream(ios_base::openmode which = ios_base::out)
			: basic_ostream<charT, traits>(&sb), basic_ios<charT, traits>(&sb)
			{
			}
			
			explicit basic_ostringstream(const basic_string<charT,traits,Allocator>& str, ios_base::openmode which = ios_base::out)
			: basic_ostream<charT, traits>(&sb), basic_ios<charT, traits>(&sb)
			{
				sb.str(str);
			}
			
			virtual ~basic_ostringstream()
			{
			}
			
			basic_stringbuf<charT,traits,Allocator>* rdbuf() const
			{
				return this->sb;
			}
			
			basic_string<charT,traits,Allocator> str() const
			{
				return sb.str();
			}
			
			void    str(const basic_string<charT,traits,Allocator>& s)
			{
				sb.str(s);
			}
			
		private:
			basic_stringbuf<charT,traits,Allocator> sb;
	};
	
	typedef basic_ostringstream<char>     ostringstream;
	typedef basic_ostringstream<wchar_t> wostringstream;
	
	// TODO
	template <class charT, class traits, class Allocator>
	class basic_stringstream : public basic_iostream<charT,traits> 
	{
		public:
			typedef charT                     char_type;
			typedef typename traits::int_type int_type;
			typedef typename traits::pos_type pos_type;
			typedef typename traits::off_type off_type;
			
			explicit basic_stringstream(ios_base::openmode which = ios_base::out|ios_base::in)
			: basic_istream<charT, traits>(&sb), basic_ostream<charT, traits>(&sb), basic_ios<charT, traits>(&sb)
			{
			}
			
			explicit basic_stringstream(const basic_string<charT,traits,Allocator>& str, ios_base::openmode which = ios_base::out|ios_base::in)
			: basic_istream<charT, traits>(&sb), basic_ostream<charT, traits>(&sb), basic_ios<charT, traits>(&sb)
			{
				sb.str(str);
			}

			basic_stringbuf<charT,traits,Allocator>* rdbuf() const
			{
				return this->sb;
			}
			
			basic_string<charT,traits,Allocator> str() const
			{
				return sb.str();
			}
			
			void str(const basic_string<charT,traits,Allocator>& str)
			{
				return str();
			}
			
		private:
			basic_stringbuf<charT, traits> sb;
	};
	
	typedef basic_stringstream<char>     stringstream;
	typedef basic_stringstream<wchar_t> wstringstream;
}

#endif
