406 lines
10 KiB
Plaintext
406 lines
10 KiB
Plaintext
|
// streambuf standard header
|
||
|
#pragma once
|
||
|
#ifndef _STREAMBUF_
|
||
|
#define _STREAMBUF_
|
||
|
#include <xiosbase>
|
||
|
|
||
|
#pragma pack(push,8)
|
||
|
#pragma warning(push,3)
|
||
|
_STD_BEGIN
|
||
|
|
||
|
// TEMPLATE CLASS basic_streambuf
|
||
|
template<class _Elem, class _Traits>
|
||
|
class basic_streambuf
|
||
|
{ // control read/write buffers
|
||
|
basic_streambuf(const basic_streambuf<_Elem, _Traits>&); // not defined
|
||
|
basic_streambuf<_Elem, _Traits>&
|
||
|
operator=(const basic_streambuf<_Elem, _Traits>&); // not defined
|
||
|
|
||
|
protected:
|
||
|
basic_streambuf()
|
||
|
: _Plocale(_NEW_CRT locale)
|
||
|
{ // construct with no buffers
|
||
|
_Init();
|
||
|
}
|
||
|
|
||
|
basic_streambuf(_Uninitialized)
|
||
|
{ // construct uninitialized
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
typedef basic_streambuf<_Elem, _Traits> _Myt;
|
||
|
typedef _Elem char_type;
|
||
|
typedef _Traits traits_type;
|
||
|
|
||
|
virtual ~basic_streambuf()
|
||
|
{ // destroy the object
|
||
|
_DELETE_CRT(_Plocale);
|
||
|
}
|
||
|
|
||
|
typedef typename _Traits::int_type int_type;
|
||
|
typedef typename _Traits::pos_type pos_type;
|
||
|
typedef typename _Traits::off_type off_type;
|
||
|
|
||
|
pos_type pubseekoff(off_type _Off, ios_base::seekdir _Way,
|
||
|
ios_base::openmode _Mode = ios_base::in | ios_base::out)
|
||
|
{ // change position by _Off, according to _Way, _Mode
|
||
|
return (seekoff(_Off, _Way, _Mode));
|
||
|
}
|
||
|
|
||
|
pos_type pubseekoff(off_type _Off, ios_base::seek_dir _Way,
|
||
|
ios_base::open_mode _Mode)
|
||
|
{ // change position by _Off, according to _Way, _Mode (old style)
|
||
|
return (pubseekoff(_Off, (ios_base::seekdir)_Way,
|
||
|
(ios_base::openmode)_Mode));
|
||
|
}
|
||
|
|
||
|
pos_type pubseekpos(pos_type _Pos,
|
||
|
ios_base::openmode _Mode = ios_base::in | ios_base::out)
|
||
|
{ // change position to _Pos, according to _Mode
|
||
|
return (seekpos(_Pos, _Mode));
|
||
|
}
|
||
|
|
||
|
pos_type pubseekpos(pos_type _Pos, ios_base::open_mode _Mode)
|
||
|
{ // change position to _Pos, according to _Mode (old style)
|
||
|
return (seekpos(_Pos, (ios_base::openmode)_Mode));
|
||
|
}
|
||
|
|
||
|
_Myt *pubsetbuf(_Elem *_Buffer, streamsize _Count)
|
||
|
{ // offer _Buffer to external agent
|
||
|
return (setbuf(_Buffer, _Count));
|
||
|
}
|
||
|
|
||
|
locale pubimbue(const locale &_Newlocale)
|
||
|
{ // set locale to argument
|
||
|
locale _Oldlocale = *_Plocale;
|
||
|
imbue(_Newlocale);
|
||
|
*_Plocale = _Newlocale;
|
||
|
return (_Oldlocale);
|
||
|
}
|
||
|
|
||
|
locale getloc() const
|
||
|
{ // get locale
|
||
|
return (*_Plocale);
|
||
|
}
|
||
|
|
||
|
streamsize in_avail()
|
||
|
{ // return count of buffered input characters
|
||
|
return (gptr() != 0 && gptr() < egptr()
|
||
|
? (streamsize)(egptr() - gptr()) : showmanyc());
|
||
|
}
|
||
|
|
||
|
int pubsync()
|
||
|
{ // synchronize with external agent
|
||
|
return (sync());
|
||
|
}
|
||
|
|
||
|
int_type sbumpc()
|
||
|
{ // get a character and point past it
|
||
|
return (gptr() != 0 && gptr() < egptr()
|
||
|
? _Traits::to_int_type(*_Gninc()) : uflow());
|
||
|
}
|
||
|
|
||
|
int_type sgetc()
|
||
|
{ // get a character and don't point past it
|
||
|
return (gptr() != 0 && gptr() < egptr()
|
||
|
? _Traits::to_int_type(*gptr()) : underflow());
|
||
|
}
|
||
|
|
||
|
streamsize sgetn(_Elem *_Ptr, streamsize _Count)
|
||
|
{ // get up to _Count characters into array beginning at _Ptr
|
||
|
return (xsgetn(_Ptr, _Count));
|
||
|
}
|
||
|
|
||
|
int_type snextc()
|
||
|
{ // point to next character and return it
|
||
|
return (_Traits::eq_int_type(_Traits::eof(), sbumpc())
|
||
|
? _Traits::eof() : sgetc());
|
||
|
}
|
||
|
|
||
|
int_type sputbackc(_Elem _Ch)
|
||
|
{ // put back _Ch
|
||
|
return (gptr() != 0 && eback() < gptr()
|
||
|
&& _Traits::eq(_Ch, gptr()[-1])
|
||
|
? _Traits::to_int_type(*_Gndec())
|
||
|
: pbackfail(_Traits::to_int_type(_Ch)));
|
||
|
}
|
||
|
|
||
|
void stossc()
|
||
|
{ // point past a character
|
||
|
if (gptr() != 0 && gptr() < egptr())
|
||
|
_Gninc();
|
||
|
else
|
||
|
uflow();
|
||
|
}
|
||
|
|
||
|
int_type sungetc()
|
||
|
{ // back up one position
|
||
|
return (gptr() != 0 && eback() < gptr()
|
||
|
? _Traits::to_int_type(*_Gndec()) : pbackfail());
|
||
|
}
|
||
|
|
||
|
int_type sputc(_Elem _Ch)
|
||
|
{ // put a character
|
||
|
return (pptr() != 0 && pptr() < epptr()
|
||
|
? _Traits::to_int_type(*_Pninc() = _Ch)
|
||
|
: overflow(_Traits::to_int_type(_Ch)));
|
||
|
}
|
||
|
|
||
|
streamsize sputn(const _Elem *_Ptr, streamsize _Count)
|
||
|
{ // put _Count characters from array beginning at _Ptr
|
||
|
return (xsputn(_Ptr, _Count));
|
||
|
}
|
||
|
|
||
|
void _Lock()
|
||
|
{ // set the thread lock
|
||
|
_Mylock._Lock();
|
||
|
}
|
||
|
|
||
|
void _Unlock()
|
||
|
{ // clear the thread lock
|
||
|
_Mylock._Unlock();
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
_Elem *eback() const
|
||
|
{ // return beginning of read buffer
|
||
|
return (*_IGfirst);
|
||
|
}
|
||
|
|
||
|
_Elem *gptr() const
|
||
|
{ // return current position in read buffer
|
||
|
return (*_IGnext);
|
||
|
}
|
||
|
|
||
|
_Elem *pbase() const
|
||
|
{ // return beginning of write buffer
|
||
|
return (*_IPfirst);
|
||
|
}
|
||
|
|
||
|
_Elem *pptr() const
|
||
|
{ // return current position in write buffer
|
||
|
return (*_IPnext);
|
||
|
}
|
||
|
|
||
|
_Elem *egptr() const
|
||
|
{ // return end of read buffer
|
||
|
return (*_IGnext + *_IGcount);
|
||
|
}
|
||
|
|
||
|
void gbump(int _Off)
|
||
|
{ // alter current position in read buffer by _Off
|
||
|
*_IGcount -= _Off;
|
||
|
*_IGnext += _Off;
|
||
|
}
|
||
|
|
||
|
void setg(_Elem *_First, _Elem *_Next, _Elem *_Last)
|
||
|
{ // set pointers for read buffer
|
||
|
*_IGfirst = _First;
|
||
|
*_IGnext = _Next;
|
||
|
*_IGcount = (int)(_Last - _Next);
|
||
|
}
|
||
|
|
||
|
_Elem *epptr() const
|
||
|
{ // return end of write buffer
|
||
|
return (*_IPnext + *_IPcount);
|
||
|
}
|
||
|
|
||
|
_Elem *_Gndec()
|
||
|
{ // decrement current position in read buffer
|
||
|
++*_IGcount;
|
||
|
return (--*_IGnext);
|
||
|
}
|
||
|
|
||
|
_Elem *_Gninc()
|
||
|
{ // increment current position in read buffer
|
||
|
--*_IGcount;
|
||
|
return ((*_IGnext)++);
|
||
|
}
|
||
|
|
||
|
void pbump(int _Off)
|
||
|
{ // alter current position in write buffer by _Off
|
||
|
*_IPcount -= _Off;
|
||
|
*_IPnext += _Off;
|
||
|
}
|
||
|
|
||
|
void setp(_Elem *_First, _Elem *_Last)
|
||
|
{ // set pointers for write buffer
|
||
|
*_IPfirst = _First;
|
||
|
*_IPnext = _First;
|
||
|
*_IPcount = (int)(_Last - _First);
|
||
|
}
|
||
|
|
||
|
void setp(_Elem *_First, _Elem *_Next, _Elem *_Last)
|
||
|
{ // set pointers for write buffer, extended version
|
||
|
*_IPfirst = _First;
|
||
|
*_IPnext = _Next;
|
||
|
*_IPcount = (int)(_Last - _Next);
|
||
|
}
|
||
|
|
||
|
_Elem *_Pninc()
|
||
|
{ // decrement current position in write buffer
|
||
|
--*_IPcount;
|
||
|
return ((*_IPnext)++);
|
||
|
}
|
||
|
|
||
|
void _Init()
|
||
|
{ // initialize buffer parameters for no buffers
|
||
|
_IGfirst = &_Gfirst, _IPfirst = &_Pfirst;
|
||
|
_IGnext = &_Gnext, _IPnext = &_Pnext;
|
||
|
_IGcount = &_Gcount, _IPcount = &_Pcount;
|
||
|
setp(0, 0), setg(0, 0, 0);
|
||
|
}
|
||
|
|
||
|
void _Init(_Elem **_Gf, _Elem **_Gn, int *_Gc,
|
||
|
_Elem **_Pf, _Elem **_Pn, int *_Pc)
|
||
|
{ // initialize buffer parameters as specified
|
||
|
_IGfirst = _Gf, _IPfirst = _Pf;
|
||
|
_IGnext = _Gn, _IPnext = _Pn;
|
||
|
_IGcount = _Gc, _IPcount = _Pc;
|
||
|
}
|
||
|
|
||
|
virtual int_type overflow(int_type = _Traits::eof())
|
||
|
{ // put a character to stream (always fail)
|
||
|
return (_Traits::eof());
|
||
|
}
|
||
|
|
||
|
virtual int_type pbackfail(int_type = _Traits::eof())
|
||
|
{ // put a character back to stream (always fail)
|
||
|
return (_Traits::eof());
|
||
|
}
|
||
|
|
||
|
virtual streamsize showmanyc()
|
||
|
{ // return count of input characters
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
virtual int_type underflow()
|
||
|
{ // get a character from stream, but don't point past it
|
||
|
return (_Traits::eof());
|
||
|
}
|
||
|
|
||
|
virtual int_type uflow()
|
||
|
{ // get a character from stream, point past it
|
||
|
return (_Traits::eq_int_type(_Traits::eof(), underflow())
|
||
|
? _Traits::eof() : _Traits::to_int_type(*_Gninc()));
|
||
|
}
|
||
|
|
||
|
virtual streamsize xsgetn(_Elem * _Ptr, streamsize _Count)
|
||
|
{ // get _Count characters from stream
|
||
|
int_type _Meta;
|
||
|
streamsize _Size, _Copied;
|
||
|
|
||
|
for (_Copied = 0; 0 < _Count; )
|
||
|
if (gptr() != 0 && 0 < (_Size = (streamsize)(egptr() - gptr())))
|
||
|
{ // copy from read buffer
|
||
|
if (_Count < _Size)
|
||
|
_Size = _Count;
|
||
|
_Traits::copy(_Ptr, gptr(), _Size);
|
||
|
_Ptr += _Size;
|
||
|
_Copied += _Size;
|
||
|
_Count -= _Size;
|
||
|
gbump((int)_Size);
|
||
|
}
|
||
|
else if (_Traits::eq_int_type(_Traits::eof(), _Meta = uflow()))
|
||
|
break; // end of file, quit
|
||
|
else
|
||
|
{ // get a single character
|
||
|
*_Ptr++ = _Traits::to_char_type(_Meta);
|
||
|
++_Copied;
|
||
|
--_Count;
|
||
|
}
|
||
|
|
||
|
return (_Copied);
|
||
|
}
|
||
|
|
||
|
virtual streamsize xsputn(const _Elem *_Ptr, streamsize _Count)
|
||
|
{ // put _Count characters to stream
|
||
|
streamsize _Size, _Copied;
|
||
|
|
||
|
for (_Copied = 0; 0 < _Count; )
|
||
|
if (pptr() != 0 && 0 < (_Size = (streamsize)(epptr() - pptr())))
|
||
|
{ // copy to write buffer
|
||
|
if (_Count < _Size)
|
||
|
_Size = _Count;
|
||
|
_Traits::copy(pptr(), _Ptr, _Size);
|
||
|
_Ptr += _Size;
|
||
|
_Copied += _Size;
|
||
|
_Count -= _Size;
|
||
|
pbump((int)_Size);
|
||
|
}
|
||
|
else if (_Traits::eq_int_type(_Traits::eof(),
|
||
|
overflow(_Traits::to_int_type(*_Ptr))))
|
||
|
break; // single character put failed, quit
|
||
|
else
|
||
|
{ // count character successfully put
|
||
|
++_Ptr;
|
||
|
++_Copied;
|
||
|
--_Count;
|
||
|
}
|
||
|
|
||
|
return (_Copied);
|
||
|
}
|
||
|
|
||
|
virtual pos_type seekoff(off_type, ios_base::seekdir,
|
||
|
ios_base::openmode = ios_base::in | ios_base::out)
|
||
|
{ // change position by offset, according to way and mode
|
||
|
return (streampos(_BADOFF));
|
||
|
}
|
||
|
|
||
|
virtual pos_type seekpos(pos_type,
|
||
|
ios_base::openmode = ios_base::in | ios_base::out)
|
||
|
{ // change to specified position, according to mode
|
||
|
return (streampos(_BADOFF));
|
||
|
}
|
||
|
|
||
|
virtual _Myt *setbuf(_Elem *, streamsize)
|
||
|
{ // offer buffer to external agent (do nothing)
|
||
|
return (this);
|
||
|
}
|
||
|
|
||
|
virtual int sync()
|
||
|
{ // synchronize with external agent (do nothing)
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
virtual void imbue(const locale&)
|
||
|
{ // set locale to argument (do nothing)
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
_Mutex _Mylock; // thread lock
|
||
|
_Elem *_Gfirst; // beginning of read buffer
|
||
|
_Elem *_Pfirst; // beginning of write buffer
|
||
|
_Elem **_IGfirst; // pointer to beginning of read buffer
|
||
|
_Elem **_IPfirst; // pointer to beginning of write buffer
|
||
|
_Elem *_Gnext; // current position in read buffer
|
||
|
_Elem *_Pnext; // current position in write buffer
|
||
|
_Elem **_IGnext; // pointer to current position in read buffer
|
||
|
_Elem **_IPnext; // pointer to current position in write buffer
|
||
|
int _Gcount; // length of read buffer
|
||
|
int _Pcount; // length of write buffer
|
||
|
int *_IGcount; // pointer to length of read buffer
|
||
|
int *_IPcount; // pointer to length of write buffer
|
||
|
locale *_Plocale; // pointer to imbued locale object
|
||
|
};
|
||
|
|
||
|
#ifdef _DLL_CPPLIB
|
||
|
#ifdef __FORCE_INSTANCE
|
||
|
template class _CRTIMP2 basic_streambuf<char, char_traits<char> >;
|
||
|
template class _CRTIMP2 basic_streambuf<wchar_t, char_traits<wchar_t> >;
|
||
|
#ifdef _CRTBLD_NATIVE_WCHAR_T
|
||
|
template class _CRTIMP2 basic_streambuf<unsigned short, char_traits<unsigned short> >;
|
||
|
#endif
|
||
|
#endif // __FORCE_INSTANCE
|
||
|
#endif // _DLL_CPPLIB
|
||
|
_STD_END
|
||
|
#pragma warning(pop)
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
#endif /* _STREAMBUF_ */
|
||
|
|
||
|
/*
|
||
|
* Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
|
||
|
* Consult your license regarding permissions and restrictions.
|
||
|
V3.10:0009 */
|