501 lines
14 KiB
Plaintext
501 lines
14 KiB
Plaintext
// sstream standard header
|
|
#pragma once
|
|
#ifndef _SSTREAM_
|
|
#define _SSTREAM_
|
|
#include <string>
|
|
|
|
#pragma pack(push,8)
|
|
#pragma warning(push,3)
|
|
#pragma warning(disable: 4251)
|
|
_STD_BEGIN
|
|
|
|
// 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
|
|
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 (_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, (void *)0);
|
|
}
|
|
|
|
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, (void *)0);
|
|
_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;
|
|
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(default: 4251)
|
|
#pragma warning(pop)
|
|
#pragma pack(pop)
|
|
|
|
#endif /* _SSTREAM_ */
|
|
|
|
/*
|
|
* Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
|
|
* Consult your license regarding permissions and restrictions.
|
|
V3.10:0009 */
|