// sstream standard header
#pragma once
#ifndef _SSTREAM_
#define _SSTREAM_
#include <string>

#pragma pack(push,8)
#pragma warning(push,3)
_STD_BEGIN

  #pragma warning(disable:4251)

		// TEMPLATE CLASS basic_stringbuf
template<class _Elem,
	class _Traits,
	class _Alloc>
	class basic_stringbuf
		: public basic_streambuf<_Elem, _Traits>
	{	// stream buffer maintaining an allocated character array
public:
	typedef _Alloc allocator_type;
	typedef basic_streambuf<_Elem, _Traits> _Mysb;
	typedef basic_string<_Elem, _Traits, _Alloc> _Mystr;

	explicit basic_stringbuf(ios_base::openmode _Mode =
		ios_base::in | ios_base::out)
		{	// construct empty character buffer from mode
		_Init(0, 0, _Getstate(_Mode));
		}

	explicit basic_stringbuf(const _Mystr& _Str,
		ios_base::openmode _Mode = ios_base::in | ios_base::out)
		{	// construct character buffer from string, mode
		_Init(_Str.c_str(), _Str.size(), _Getstate(_Mode));
		}

	virtual ~basic_stringbuf()
		{	// destroy the object
		_Tidy();
		}

	enum
		{	// constants for bits in stream state
		_Allocated = 1,	// set if character array storage has been allocated
		_Constant = 2,	// set if character array nonmutable
		_Noread = 4,	// set if character array cannot be read
		_Append = 8};	// set if all writes are appends
	typedef int _Strstate;

	typedef typename _Traits::int_type int_type;
	typedef typename _Traits::pos_type pos_type;
	typedef typename _Traits::off_type off_type;

	_Mystr str() const
		{	// return string copy of character array
		if (!(_Mystate & _Constant) && _Mysb::pptr() != 0)
			{	// writable, make string from write buffer
			_Mystr _Str(_Mysb::pbase(), (_Seekhigh < _Mysb::pptr()
				? _Mysb::pptr() : _Seekhigh) - _Mysb::pbase());
			return (_Str);
			}
		else if (!(_Mystate & _Noread) && _Mysb::gptr() != 0)
			{	// readable, make string from read buffer
			_Mystr _Str(_Mysb::eback(), _Mysb::egptr() - _Mysb::eback());
			return (_Str);
			}
		else
			{	// inaccessible, return empty string
			_Mystr _Nul;
			return (_Nul);
			}
		}

	void str(const _Mystr& _Newstr)
		{	// replace character array from string
		_Tidy();
		_Init(_Newstr.c_str(), _Newstr.size(), _Mystate);
		}

protected:
	virtual int_type overflow(int_type _Meta = _Traits::eof())
		{	// put an element to stream
		if (_Mystate & _Append
			&& _Mysb::pptr() != 0 && _Mysb::pptr() < _Seekhigh)
			_Mysb::setp(_Mysb::pbase(), _Seekhigh, _Mysb::epptr());

		if (_Traits::eq_int_type(_Traits::eof(), _Meta))
			return (_Traits::not_eof(_Meta));	// EOF, return success code
		else if (_Mysb::pptr() != 0
			&& _Mysb::pptr() < _Mysb::epptr())
			{	// room in buffer, store it
			*_Mysb::_Pninc() = _Traits::to_char_type(_Meta);
			return (_Meta);
			}
		else if (_Mystate & _Constant)
			return (_Traits::eof());	// array nonmutable, fail
		else
			{	// grow buffer and store element
			size_t _Oldsize = _Mysb::pptr() == 0
				? 0 : _Mysb::epptr() - _Mysb::eback();
			size_t _Newsize = _Oldsize;
			size_t _Inc = _Newsize / 2 < _MINSIZE
				? _MINSIZE : _Newsize / 2;	// grow by 50 per cent
			_Elem *_Ptr = 0;

			while (0 < _Inc && INT_MAX - _Inc < _Newsize)
				_Inc /= 2;	// increment causes overflow, halve it
			if (0 < _Inc)
				{	// finite increment, allocate new character array
				_Newsize += _Inc;
				_Ptr = _Al.allocate(_Newsize);
				}

			if (0 < _Oldsize)
				_Traits::copy(_Ptr, _Mysb::eback(), _Oldsize);
			if (_Mystate & _Allocated)
				_Al.deallocate(_Mysb::eback(), _Oldsize);
			_Mystate |= _Allocated;

			if (_Oldsize == 0)
				{	// first growth, set up pointers
				_Seekhigh = _Ptr;
				_Mysb::setp(_Ptr, _Ptr + _Newsize);
				if (_Mystate & _Noread)
					_Mysb::setg(_Ptr, 0, _Ptr);
				else
					_Mysb::setg(_Ptr, _Ptr, _Ptr + 1);
				}
			else
				{	// not first growth, adjust pointers
				_Seekhigh = _Seekhigh - _Mysb::eback() + _Ptr;
				_Mysb::setp(_Mysb::pbase() - _Mysb::eback() + _Ptr,
					_Mysb::pptr() - _Mysb::eback() + _Ptr, _Ptr + _Newsize);
				if (_Mystate & _Noread)
					_Mysb::setg(_Ptr, 0, _Ptr);
				else
					_Mysb::setg(_Ptr,
						_Mysb::gptr() - _Mysb::eback() + _Ptr,
						_Mysb::pptr() + 1);
				}

			*_Mysb::_Pninc() = _Traits::to_char_type(_Meta);
			return (_Meta);
			}
		}

	virtual int_type pbackfail(int_type _Meta = _Traits::eof())
		{	// put an element back to stream
		if (_Mysb::gptr() == 0
			|| _Mysb::gptr() <= _Mysb::eback()
			|| !_Traits::eq_int_type(_Traits::eof(), _Meta)
			&& !_Traits::eq(_Traits::to_char_type(_Meta), _Mysb::gptr()[-1])
			&& _Mystate & _Constant)
			return (_Traits::eof());	// can't put back, fail
		else
			{	// back up one position and store put-back character
			_Mysb::gbump(-1);
			if (!_Traits::eq_int_type(_Traits::eof(), _Meta))
				*_Mysb::gptr() = _Traits::to_char_type(_Meta);
			return (_Traits::not_eof(_Meta));
			}
		}

	virtual int_type underflow()
		{	// get an element from stream, but don't point past it
		if (_Mysb::gptr() == 0)
			return (_Traits::eof());	// no character buffer, fail
		else if (_Mysb::gptr() < _Mysb::egptr())
			return (_Traits::to_int_type(*_Mysb::gptr()));	// return buffered
		else if (_Mystate & _Noread || _Mysb::pptr() == 0
			|| _Mysb::pptr() <= _Mysb::gptr() && _Seekhigh <= _Mysb::gptr())
			return (_Traits::eof());	// can't read, fail
		else
			{	// extend read buffer into written area, then return buffered
			if (_Seekhigh < _Mysb::pptr())
				_Seekhigh = _Mysb::pptr();
			_Mysb::setg(_Mysb::eback(), _Mysb::gptr(), _Seekhigh);
			return (_Traits::to_int_type(*_Mysb::gptr()));
			}
		}

	virtual pos_type seekoff(off_type _Off,
		ios_base::seekdir _Way,
		ios_base::openmode _Which = ios_base::in | ios_base::out)
		{	// change position by _Off, according to _Way, _Mode
		if (_Mysb::pptr() != 0 && _Seekhigh < _Mysb::pptr())
			_Seekhigh = _Mysb::pptr();	// update high-water pointer

		if (_Which & ios_base::in && _Mysb::gptr() != 0)
			{	// position within read buffer
			if (_Way == ios_base::end)
				_Off += (off_type)(_Seekhigh - _Mysb::eback());
			else if (_Way == ios_base::cur
				&& (_Which & ios_base::out) == 0)
				_Off += (off_type)(_Mysb::gptr() - _Mysb::eback());
			else if (_Way != ios_base::beg)
				_Off = _BADOFF;

			if (0 <= _Off && _Off <= _Seekhigh - _Mysb::eback())
				{	// change read position
				_Mysb::gbump((int)(_Mysb::eback() - _Mysb::gptr() + _Off));
				if (_Which & ios_base::out && _Mysb::pptr() != 0)
					_Mysb::setp(_Mysb::pbase(), _Mysb::gptr(),
						_Mysb::epptr());	// change write position to match
				}
			else
				_Off = _BADOFF;
			}
		else if (_Which & ios_base::out && _Mysb::pptr() != 0)
			{	// position within write buffer
			if (_Way == ios_base::end)
				_Off += (off_type)(_Seekhigh - _Mysb::eback());
			else if (_Way == ios_base::cur)
				_Off += (off_type)(_Mysb::pptr() - _Mysb::eback());
			else if (_Way != ios_base::beg)
				_Off = _BADOFF;

			if (0 <= _Off && _Off <= _Seekhigh - _Mysb::eback())
				_Mysb::pbump((int)(_Mysb::eback()
					- _Mysb::pptr() + _Off));	// change write position
			else
				_Off = _BADOFF;
			}
		else
			_Off = _BADOFF;	// neither read nor write buffer selected, fail
		return (pos_type(_Off));
		}

	virtual pos_type seekpos(pos_type _Ptr,
		ios_base::openmode _Mode = ios_base::in | ios_base::out)
		{	// change position to _Pos, according to _Mode
		streamoff _Off = (streamoff)_Ptr;
		if (_Mysb::pptr() != 0 && _Seekhigh < _Mysb::pptr())
			_Seekhigh = _Mysb::pptr();	// update high-water pointer

		if (_Off == _BADOFF)
			;
		else if (_Mode & ios_base::in && _Mysb::gptr() != 0)
			{	// position within read buffer
			if (0 <= _Off && _Off <= _Seekhigh - _Mysb::eback())
				{	// change read position
				_Mysb::gbump((int)(_Mysb::eback() - _Mysb::gptr() + _Off));
				if (_Mode & ios_base::out && _Mysb::pptr() != 0)
					_Mysb::setp(_Mysb::pbase(), _Mysb::gptr(),
						_Mysb::epptr());	// change write position to match
				}
			else
				_Off = _BADOFF;
			}
		else if (_Mode & ios_base::out && _Mysb::pptr() != 0)
			{	// position within write buffer
			if (0 <= _Off && _Off <= _Seekhigh - _Mysb::eback())
				_Mysb::pbump((int)(_Mysb::eback()
					- _Mysb::pptr() + _Off));	// change write position
			else
				_Off = _BADOFF;
			}
		else
			_Off = _BADOFF;
		return (streampos(_Off));
		}

	void _Init(const _Elem *_Ptr,
		size_t _Count, _Strstate _State)
		{	// initialize buffer to [_Ptr, _Ptr + _Count), set state
		_Seekhigh = 0;
		_Mystate = _State;

		if (_Count != 0
			&& (_Mystate & (_Noread | _Constant)) != (_Noread | _Constant))
			{	// finite buffer that can be read or written, set it up
			_Elem *_Pnew = _Al.allocate(_Count);
			_Traits::copy(_Pnew, _Ptr, _Count);
			_Seekhigh = _Pnew + _Count;

			if (!(_Mystate & _Noread))
				_Mysb::setg(_Pnew, _Pnew,
					_Pnew + _Count);	// setup read buffer
			if (!(_Mystate & _Constant))
				{	// setup write buffer, and maybe read buffer
				_Mysb::setp(_Pnew, _Pnew + _Count);
				if (_Mysb::gptr() == 0)
					_Mysb::setg(_Pnew, 0, _Pnew);
				}
			_Mystate |= _Allocated;
			}
		}

	void _Tidy()
		{	// discard any allocated buffer and clear pointers
		if (_Mystate & _Allocated)
			_Al.deallocate(_Mysb::eback(),
				(_Mysb::pptr() != 0 ? _Mysb::epptr()
					: _Mysb::egptr()) - _Mysb::eback());
		_Mysb::setg(0, 0, 0);
		_Mysb::setp(0, 0);
		_Seekhigh = 0;
		_Mystate &= ~_Allocated;
		}

private:
	enum
		{	// constant for minimum buffer size
		_MINSIZE = 32};

	_Strstate _Getstate(ios_base::openmode _Mode)
		{	// convert open mode to stream state bits
		_Strstate _State = (_Strstate)0;
		if (!(_Mode & ios_base::in))
			_State |= _Noread;
		if (!(_Mode & ios_base::out))
			_State |= _Constant;
		if (_Mode & ios_base::app)
			_State |= _Append;
		return (_State);
		}

	_Elem *_Seekhigh;	// the high-water pointer in character array
	_Strstate _Mystate;	// the stream state
	allocator_type _Al;	// the allocator object
	};

 #ifdef _DLL_CPPLIB

template class _CRTIMP2 basic_stringbuf<char,
	char_traits<char>, allocator<char> >;
template class _CRTIMP2 basic_stringbuf<wchar_t,
	char_traits<wchar_t>, allocator<wchar_t> >;



 #endif /* _DLL_CPPLIB */

		// TEMPLATE CLASS basic_istringstream
template<class _Elem,
	class _Traits,
	class _Alloc>
	class basic_istringstream
		: public basic_istream<_Elem, _Traits>
	{	// input stream associated with a character array
public:
	typedef _Alloc allocator_type;
	typedef basic_stringbuf<_Elem, _Traits, _Alloc> _Mysb;
	typedef basic_string<_Elem, _Traits, _Alloc> _Mystr;

	explicit basic_istringstream(ios_base::openmode _Mode = ios_base::in)
		: basic_istream<_Elem, _Traits>(&_Stringbuffer),
			_Stringbuffer(_Mode | ios_base::in)
		{	// construct empty readable character buffer
		}

	explicit basic_istringstream(const _Mystr& _Str,
		ios_base::openmode _Mode = ios_base::in)
		: basic_istream<_Elem, _Traits>(&_Stringbuffer),
			_Stringbuffer(_Str, _Mode | ios_base::in)
		{	// construct readable character buffer from NTCS
		}

	virtual ~basic_istringstream()
		{	// destroy the object
		}

	_Mysb *rdbuf() const
		{	// return pointer to file buffer
		return ((_Mysb *)&_Stringbuffer);
		}

	_Mystr str() const
		{	// return string copy of character array
		return (_Stringbuffer.str());
		}

	void str(const _Mystr& _Newstr)
		{	// replace character array from string
		_Stringbuffer.str(_Newstr);
		}

private:
	_Mysb _Stringbuffer;	// the string buffer
	};

 #ifdef _DLL_CPPLIB

template class _CRTIMP2 basic_istringstream<char,
	char_traits<char>, allocator<char> >;
template class _CRTIMP2 basic_istringstream<wchar_t,
	char_traits<wchar_t>, allocator<wchar_t> >;



 #endif /* _DLL_CPPLIB */

		// TEMPLATE CLASS basic_ostringstream
template<class _Elem,
	class _Traits,
	class _Alloc>
	class basic_ostringstream
		: public basic_ostream<_Elem, _Traits>
	{	// output stream associated with a character array
public:
	typedef _Alloc allocator_type;
	typedef basic_stringbuf<_Elem, _Traits, _Alloc> _Mysb;
	typedef basic_string<_Elem, _Traits, _Alloc> _Mystr;

	explicit basic_ostringstream(ios_base::openmode _Mode = ios_base::out)
		: basic_ostream<_Elem, _Traits>(&_Stringbuffer),
			_Stringbuffer(_Mode | ios_base::out)
		{	// construct empty writable character buffer
		}

	explicit basic_ostringstream(const _Mystr& _Str,
		ios_base::openmode _Mode = ios_base::out)
		: basic_ostream<_Elem, _Traits>(&_Stringbuffer),
			_Stringbuffer(_Str, _Mode | ios_base::out)
		{	// construct writable character buffer from NTCS
		}

	virtual ~basic_ostringstream()
		{	// destroy the object
		}

	_Mysb *rdbuf() const
		{	// return pointer to buffer
		return ((_Mysb *)&_Stringbuffer);
		}

	_Mystr str() const
		{	// return string copy of character array
		return (_Stringbuffer.str());
		}

	void str(const _Mystr& _Newstr)
		{	// replace character array from string
		_Stringbuffer.str(_Newstr);
		}

private:
	_Mysb _Stringbuffer;	// the string buffer
	};

 #ifdef _DLL_CPPLIB

template class _CRTIMP2 basic_ostringstream<char,
	char_traits<char>, allocator<char> >;
template class _CRTIMP2 basic_ostringstream<wchar_t,
	char_traits<wchar_t>, allocator<wchar_t> >;



 #endif /* _DLL_CPPLIB */

		// TEMPLATE CLASS basic_stringstream
template<class _Elem,
	class _Traits,
	class _Alloc>
	class basic_stringstream
		: public basic_iostream<_Elem, _Traits>
	{	// input/output stream associated with a character array
public:
	typedef _Elem char_type;
	typedef _Traits traits_type;
	typedef _Alloc allocator_type;
	typedef typename _Traits::int_type int_type;
	typedef typename _Traits::pos_type pos_type;
	typedef typename _Traits::off_type off_type;
	typedef basic_string<_Elem, _Traits, _Alloc> _Mystr;

	explicit basic_stringstream(ios_base::openmode _Mode =
		ios_base::in | ios_base::out)
		: basic_iostream<_Elem, _Traits>(&_Stringbuffer),
			_Stringbuffer(_Mode)
		{	// construct empty character buffer
		}

	explicit basic_stringstream(const _Mystr& _Str,
		ios_base::openmode _Mode = ios_base::in | ios_base::out)
		: basic_iostream<_Elem, _Traits>(&_Stringbuffer),
			_Stringbuffer(_Str, _Mode)
		{	// construct character buffer from NTCS
		}

	virtual ~basic_stringstream()
		{	// destroy the object
		}

	basic_stringbuf<_Elem, _Traits, _Alloc> *rdbuf() const
		{	// return pointer to buffer
		return ((basic_stringbuf<_Elem, _Traits, _Alloc> *)&_Stringbuffer);
		}

	_Mystr str() const
		{	// return string copy of character array
		return (_Stringbuffer.str());
		}

	void str(const _Mystr& _Newstr)
		{	// replace character array from string
		_Stringbuffer.str(_Newstr);
		}

private:
	basic_stringbuf<_Elem, _Traits, _Alloc>
		_Stringbuffer;	// the string buffer
	};

 #ifdef _DLL_CPPLIB

template class _CRTIMP2 basic_stringstream<char,
	char_traits<char>, allocator<char> >;
template class _CRTIMP2 basic_stringstream<wchar_t,
	char_traits<wchar_t>, allocator<wchar_t> >;



 #endif /* _DLL_CPPLIB */
_STD_END
#pragma warning(pop)
#pragma pack(pop)

#endif /* _SSTREAM_ */

/*
 * Copyright (c) 1992-2002 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 V3.13:0009 */
