STL/stl/inc/streambuf

420 строки
15 KiB
C++

// streambuf standard header
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef _STREAMBUF_
#define _STREAMBUF_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <xiosbase>
#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
_STD_BEGIN
_EXPORT_STD extern "C++" template <class _Elem, class _Traits>
class basic_streambuf { // control read/write buffers
protected:
__CLR_OR_THIS_CALL basic_streambuf() : _Plocale(new locale) {
_Init();
}
__CLR_OR_THIS_CALL basic_streambuf(_Uninitialized) noexcept {}
__CLR_OR_THIS_CALL basic_streambuf(const basic_streambuf& _Right) : _Plocale(new locale{_Right.getloc()}) {
_Init();
setp(_Right.pbase(), _Right.pptr(), _Right.epptr());
setg(_Right.eback(), _Right.gptr(), _Right.egptr());
}
basic_streambuf& __CLR_OR_THIS_CALL operator=(const basic_streambuf& _Right) {
if (this != _STD addressof(_Right)) {
setp(_Right.pbase(), _Right.pptr(), _Right.epptr());
setg(_Right.eback(), _Right.gptr(), _Right.egptr());
pubimbue(_Right.getloc());
}
return *this;
}
void __CLR_OR_THIS_CALL swap(basic_streambuf& _Right) noexcept /* strengthened */ {
if (this != _STD addressof(_Right)) {
_Elem* _Pfirst0 = pbase();
_Elem* _Pnext0 = pptr();
_Elem* _Pend = epptr();
_Elem* _Gfirst0 = eback();
_Elem* _Gnext0 = gptr();
_Elem* _Gend = egptr();
setp(_Right.pbase(), _Right.pptr(), _Right.epptr());
_Right.setp(_Pfirst0, _Pnext0, _Pend);
setg(_Right.eback(), _Right.gptr(), _Right.egptr());
_Right.setg(_Gfirst0, _Gnext0, _Gend);
_STD swap(_Plocale, _Right._Plocale);
}
}
public:
using char_type = _Elem;
using traits_type = _Traits;
virtual __CLR_OR_THIS_CALL ~basic_streambuf() noexcept {
delete _Plocale;
}
using int_type = typename _Traits::int_type;
using pos_type = typename _Traits::pos_type;
using off_type = typename _Traits::off_type;
pos_type __CLR_OR_THIS_CALL 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);
}
#if _HAS_OLD_IOSTREAMS_MEMBERS
pos_type __CLR_OR_THIS_CALL 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, static_cast<ios_base::seekdir>(_Way), static_cast<ios_base::openmode>(_Mode));
}
#endif // _HAS_OLD_IOSTREAMS_MEMBERS
pos_type __CLR_OR_THIS_CALL 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);
}
#if _HAS_OLD_IOSTREAMS_MEMBERS
pos_type __CLR_OR_THIS_CALL pubseekpos(pos_type _Pos,
ios_base::open_mode _Mode) { // change position to _Pos, according to _Mode (old style)
return seekpos(_Pos, static_cast<ios_base::openmode>(_Mode));
}
#endif // _HAS_OLD_IOSTREAMS_MEMBERS
basic_streambuf* __CLR_OR_THIS_CALL pubsetbuf(_Elem* _Buffer,
streamsize _Count) { // offer _Buffer to external agent
return setbuf(_Buffer, _Count);
}
locale __CLR_OR_THIS_CALL pubimbue(const locale& _Newlocale) { // set locale to argument
locale _Oldlocale = *_Plocale;
imbue(_Newlocale);
*_Plocale = _Newlocale;
return _Oldlocale;
}
locale __CLR_OR_THIS_CALL getloc() const noexcept /* strengthened */ { // get locale
return *_Plocale;
}
streamsize __CLR_OR_THIS_CALL in_avail() {
streamsize _Res = _Gnavail();
return 0 < _Res ? _Res : showmanyc();
}
int __CLR_OR_THIS_CALL pubsync() { // synchronize with external agent
return sync();
}
int_type __CLR_OR_THIS_CALL sbumpc() { // get a character and point past it
return 0 < _Gnavail() ? _Traits::to_int_type(*_Gninc()) : uflow();
}
int_type __CLR_OR_THIS_CALL sgetc() { // get a character and don't point past it
return 0 < _Gnavail() ? _Traits::to_int_type(*gptr()) : underflow();
}
streamsize __CLR_OR_THIS_CALL sgetn(_Elem* _Ptr,
streamsize _Count) { // get up to _Count characters into array beginning at _Ptr
return xsgetn(_Ptr, _Count);
}
int_type __CLR_OR_THIS_CALL snextc() { // point to next character and return it
return 1 < _Gnavail() ? _Traits::to_int_type(*_Gnpreinc())
: _Traits::eq_int_type(_Traits::eof(), sbumpc()) ? _Traits::eof()
: sgetc();
}
int_type __CLR_OR_THIS_CALL sputbackc(_Elem _Ch) { // put back _Ch
if (gptr() && eback() < gptr() && _Traits::eq(_Ch, gptr()[-1])) {
return _Traits::to_int_type(*_Gndec());
}
return pbackfail(_Traits::to_int_type(_Ch));
}
#if _HAS_OLD_IOSTREAMS_MEMBERS
void __CLR_OR_THIS_CALL stossc() { // point past a character
if (0 < _Gnavail()) {
_Gninc();
} else {
uflow();
}
}
#endif // _HAS_OLD_IOSTREAMS_MEMBERS
int_type __CLR_OR_THIS_CALL sungetc() { // back up one position
return gptr() && eback() < gptr() ? _Traits::to_int_type(*_Gndec()) : pbackfail();
}
int_type __CLR_OR_THIS_CALL sputc(_Elem _Ch) { // put a character
return 0 < _Pnavail() ? _Traits::to_int_type(*_Pninc() = _Ch) : overflow(_Traits::to_int_type(_Ch));
}
streamsize __CLR_OR_THIS_CALL sputn(const _Elem* _Ptr,
streamsize _Count) { // put _Count characters from array beginning at _Ptr
return xsputn(_Ptr, _Count);
}
virtual void __CLR_OR_THIS_CALL _Lock() {} // set the thread lock (overridden by basic_filebuf)
virtual void __CLR_OR_THIS_CALL _Unlock() {} // clear the thread lock (overridden by basic_filebuf)
protected:
_Elem* __CLR_OR_THIS_CALL eback() const noexcept /* strengthened */ {
return *_IGfirst;
}
_Elem* __CLR_OR_THIS_CALL gptr() const noexcept /* strengthened */ {
return *_IGnext;
}
_Elem* __CLR_OR_THIS_CALL pbase() const noexcept /* strengthened */ {
return *_IPfirst;
}
_Elem* __CLR_OR_THIS_CALL pptr() const noexcept /* strengthened */ {
return *_IPnext;
}
_Elem* __CLR_OR_THIS_CALL egptr() const noexcept /* strengthened */ {
return *_IGnext + *_IGcount;
}
void __CLR_OR_THIS_CALL gbump(int _Off) noexcept /* strengthened */ {
// alter current position in read buffer by _Off
*_IGcount -= _Off;
*_IGnext += _Off;
}
void __CLR_OR_THIS_CALL setg(_Elem* _First, _Elem* _Next, _Elem* _Last) noexcept /* strengthened */ {
// set pointers for read buffer
*_IGfirst = _First;
*_IGnext = _Next;
*_IGcount = static_cast<int>(_Last - _Next);
}
_Elem* __CLR_OR_THIS_CALL epptr() const noexcept /* strengthened */ {
return *_IPnext + *_IPcount;
}
_Elem* __CLR_OR_THIS_CALL _Gndec() noexcept { // decrement current position in read buffer
++*_IGcount;
return --*_IGnext;
}
_Elem* __CLR_OR_THIS_CALL _Gninc() noexcept { // increment current position in read buffer
--*_IGcount;
return (*_IGnext)++;
}
_Elem* __CLR_OR_THIS_CALL _Gnpreinc() noexcept { // preincrement current position in read buffer
--*_IGcount;
return ++(*_IGnext);
}
streamsize __CLR_OR_THIS_CALL _Gnavail() const noexcept { // count number of available elements in read buffer
return *_IGnext ? *_IGcount : 0;
}
void __CLR_OR_THIS_CALL pbump(int _Off) noexcept /* strengthened */ {
// alter current position in write buffer by _Off
*_IPcount -= _Off;
*_IPnext += _Off;
}
void __CLR_OR_THIS_CALL setp(_Elem* _First, _Elem* _Last) noexcept /* strengthened */ {
// set pointers for write buffer
*_IPfirst = _First;
*_IPnext = _First;
*_IPcount = static_cast<int>(_Last - _First);
}
void __CLR_OR_THIS_CALL setp(_Elem* _First, _Elem* _Next, _Elem* _Last) noexcept /* strengthened */ {
// set pointers for write buffer, extended version
*_IPfirst = _First;
*_IPnext = _Next;
*_IPcount = static_cast<int>(_Last - _Next);
}
_Elem* __CLR_OR_THIS_CALL _Pninc() noexcept { // increment current position in write buffer
--*_IPcount;
return (*_IPnext)++;
}
streamsize __CLR_OR_THIS_CALL _Pnavail() const noexcept { // count number of available positions in write buffer
return *_IPnext ? *_IPcount : 0;
}
void __CLR_OR_THIS_CALL _Init() noexcept { // initialize buffer parameters for no buffers
_IGfirst = &_Gfirst;
_IPfirst = &_Pfirst;
_IGnext = &_Gnext;
_IPnext = &_Pnext;
_IGcount = &_Gcount;
_IPcount = &_Pcount;
setp(nullptr, nullptr);
setg(nullptr, nullptr, nullptr);
}
void __CLR_OR_THIS_CALL _Init(_Elem** _Gf, _Elem** _Gn, int* _Gc, _Elem** _Pf, _Elem** _Pn, int* _Pc) noexcept {
// initialize buffer parameters as specified
_IGfirst = _Gf;
_IPfirst = _Pf;
_IGnext = _Gn;
_IPnext = _Pn;
_IGcount = _Gc;
_IPcount = _Pc;
}
virtual int_type __CLR_OR_THIS_CALL overflow(int_type = _Traits::eof()) { // put a character to stream (always fail)
return _Traits::eof();
}
virtual int_type __CLR_OR_THIS_CALL pbackfail(int_type = _Traits::eof()) {
// put a character back to stream (always fail)
return _Traits::eof();
}
virtual streamsize __CLR_OR_THIS_CALL showmanyc() {
return 0;
}
virtual int_type __CLR_OR_THIS_CALL underflow() { // get a character from stream, but don't point past it
return _Traits::eof();
}
virtual int_type __CLR_OR_THIS_CALL 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 __CLR_OR_THIS_CALL xsgetn(_Elem* _Ptr, streamsize _Count) { // get _Count characters from stream
const streamsize _Start_count = _Count;
while (0 < _Count) {
streamsize _Size = _Gnavail();
if (0 < _Size) { // copy from read buffer
if (_Count < _Size) {
_Size = _Count;
}
_Traits::copy(_Ptr, gptr(), static_cast<size_t>(_Size));
_Ptr += _Size;
_Count -= _Size;
gbump(static_cast<int>(_Size));
} else {
const int_type _Meta = uflow();
if (_Traits::eq_int_type(_Traits::eof(), _Meta)) {
break; // end of file, quit
}
// get a single character
*_Ptr++ = _Traits::to_char_type(_Meta);
--_Count;
}
}
return _Start_count - _Count;
}
virtual streamsize __CLR_OR_THIS_CALL xsputn(const _Elem* _Ptr, streamsize _Count) {
// put _Count characters to stream
const streamsize _Start_count = _Count;
while (0 < _Count) {
streamsize _Size = _Pnavail();
if (0 < _Size) { // copy to write buffer
if (_Count < _Size) {
_Size = _Count;
}
_Traits::copy(pptr(), _Ptr, static_cast<size_t>(_Size));
_Ptr += _Size;
_Count -= _Size;
pbump(static_cast<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;
--_Count;
}
}
return _Start_count - _Count;
}
virtual pos_type __CLR_OR_THIS_CALL 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 pos_type{off_type{-1}};
}
virtual pos_type __CLR_OR_THIS_CALL seekpos(pos_type, ios_base::openmode = ios_base::in | ios_base::out) {
// change to specified position, according to mode
return pos_type{off_type{-1}};
}
virtual basic_streambuf* __CLR_OR_THIS_CALL setbuf(_Elem*, streamsize) {
// offer buffer to external agent (do nothing)
return this;
}
virtual int __CLR_OR_THIS_CALL sync() { // synchronize with external agent (do nothing)
return 0;
}
virtual void __CLR_OR_THIS_CALL imbue(const locale&) {} // set locale to argument (do nothing)
private:
_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
protected:
locale* _Plocale{}; // pointer to imbued locale object
};
#if defined(_DLL_CPPLIB)
#if !defined(_CRTBLD) || defined(__FORCE_INSTANCE)
template class _CRTIMP2_PURE_IMPORT basic_streambuf<char, char_traits<char>>;
template class _CRTIMP2_PURE_IMPORT basic_streambuf<wchar_t, char_traits<wchar_t>>;
#endif // !defined(_CRTBLD) || defined(__FORCE_INSTANCE)
#ifdef __FORCE_INSTANCE
template class _CRTIMP2_PURE_IMPORT basic_streambuf<unsigned short, char_traits<unsigned short>>;
#endif // defined(__FORCE_INSTANCE)
#endif // defined(_DLL_CPPLIB)
_STD_END
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _STREAMBUF_