// sstream standard header #pragma once #ifndef _SSTREAM_ #define _SSTREAM_ #include #pragma pack(push,8) #pragma warning(push,3) #pragma warning(disable: 4251) _STD_BEGIN // TEMPLATE CLASS basic_stringbuf template 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, allocator >; template class _CRTIMP2 basic_stringbuf, allocator >; #endif // _DLL_CPPLIB // TEMPLATE CLASS basic_istringstream template 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, allocator >; template class _CRTIMP2 basic_istringstream, allocator >; #endif // _DLL_CPPLIB // TEMPLATE CLASS basic_ostringstream template 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, allocator >; template class _CRTIMP2 basic_ostringstream, allocator >; #endif // _DLL_CPPLIB // TEMPLATE CLASS basic_stringstream template 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, allocator >; template class _CRTIMP2 basic_stringstream, allocator >; #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 */