STL/stl/inc/istream

943 строки
34 KiB
C++

// istream standard header
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef _ISTREAM_
#define _ISTREAM_
#include <yvals_core.h>
#if _STL_COMPILER_PREPROCESSOR
#include <ostream>
#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
#pragma vtordisp(push, 2) // compiler bug workaround
_EXPORT_STD extern "C++" template <class _Elem, class _Traits>
class basic_istream : virtual public basic_ios<_Elem, _Traits> { // control extractions from a stream buffer
public:
using _Myios = basic_ios<_Elem, _Traits>;
using _Mysb = basic_streambuf<_Elem, _Traits>;
using _Iter = istreambuf_iterator<_Elem, _Traits>;
using _Ctype = ctype<_Elem>;
using _Nget = num_get<_Elem, _Iter>;
#if defined(__FORCE_INSTANCE)
explicit __CLR_OR_THIS_CALL basic_istream(_Mysb* _Strbuf, bool _Isstd, bool _Skip_init) : _Chcount(0) {
if (!_Skip_init) {
_Myios::init(_Strbuf, _Isstd);
}
}
#endif // defined(__FORCE_INSTANCE)
explicit __CLR_OR_THIS_CALL basic_istream(_Mysb* _Strbuf, bool _Isstd = false) : _Chcount(0) {
_Myios::init(_Strbuf, _Isstd);
}
__CLR_OR_THIS_CALL basic_istream(_Uninitialized) {
this->_Addstd(this);
}
protected:
__CLR_OR_THIS_CALL basic_istream(basic_istream&& _Right) noexcept(false) : _Chcount(_Right._Chcount) {
_Myios::init();
_Myios::move(_STD move(_Right));
_Right._Chcount = 0;
}
basic_istream& __CLR_OR_THIS_CALL operator=(basic_istream&& _Right) noexcept /* strengthened */ {
this->swap(_Right);
return *this;
}
void __CLR_OR_THIS_CALL swap(basic_istream& _Right) noexcept /* strengthened */ {
_Myios::swap(_Right);
_STD swap(_Chcount, _Right._Chcount);
}
public:
__CLR_OR_THIS_CALL basic_istream(const basic_istream&) = delete;
basic_istream& __CLR_OR_THIS_CALL operator=(const basic_istream&) = delete;
__CLR_OR_THIS_CALL ~basic_istream() noexcept override {}
using int_type = typename _Traits::int_type;
using pos_type = typename _Traits::pos_type;
using off_type = typename _Traits::off_type;
class _Sentry_base {
public:
__CLR_OR_THIS_CALL _Sentry_base(basic_istream& _Istr) : _Myistr(_Istr) {
const auto _Rdbuf = _Myistr.rdbuf();
if (_Rdbuf) {
_Rdbuf->_Lock();
}
}
__CLR_OR_THIS_CALL ~_Sentry_base() noexcept {
const auto _Rdbuf = _Myistr.rdbuf();
if (_Rdbuf) {
_Rdbuf->_Unlock();
}
}
basic_istream& _Myistr;
_Sentry_base& operator=(const _Sentry_base&) = delete;
};
class sentry : public _Sentry_base {
public:
explicit __CLR_OR_THIS_CALL sentry(basic_istream& _Istr, bool _Noskip = false)
: _Sentry_base(_Istr), _Ok(_Sentry_base::_Myistr._Ipfx(_Noskip)) {}
explicit __CLR_OR_THIS_CALL operator bool() const {
return _Ok;
}
__CLR_OR_THIS_CALL sentry(const sentry&) = delete;
sentry& __CLR_OR_THIS_CALL operator=(const sentry&) = delete;
private:
bool _Ok; // true if _Ipfx succeeded at construction
};
bool __CLR_OR_THIS_CALL _Ipfx(bool _Noskip = false) { // test stream state and skip whitespace as needed
if (!this->good()) {
_Myios::setstate(ios_base::failbit);
return false;
}
// state okay, flush tied stream and skip whitespace
const auto _Tied = _Myios::tie();
if (_Tied) {
_Tied->flush();
}
bool _Eof = false;
if (!_Noskip && this->flags() & ios_base::skipws) { // skip whitespace
const _Ctype& _Ctype_fac = _STD use_facet<_Ctype>(this->getloc());
_TRY_IO_BEGIN
int_type _Meta = _Myios::rdbuf()->sgetc();
for (;; _Meta = _Myios::rdbuf()->snextc()) {
if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // end of file, quit
_Eof = true;
break;
} else if (!_Ctype_fac.is(_Ctype::space, _Traits::to_char_type(_Meta))) {
break; // not whitespace, quit
}
}
_CATCH_IO_END
}
if (_Eof) {
_Myios::setstate(ios_base::eofbit | ios_base::failbit);
}
return this->good();
}
#pragma push_macro("ipfx")
#pragma push_macro("isfx")
#undef ipfx
#undef isfx
// TRANSITION, ABI: non-Standard ipfx() is preserved for binary compatibility
_DEPRECATE_IO_PFX_SFX bool __CLR_OR_THIS_CALL ipfx(bool _Noskip = false) {
// test stream state and skip whitespace as needed
return _Ipfx(_Noskip);
}
// TRANSITION, ABI: non-Standard isfx() is preserved for binary compatibility
_DEPRECATE_IO_PFX_SFX void __CLR_OR_THIS_CALL isfx() {} // perform any wrapup
#pragma pop_macro("isfx")
#pragma pop_macro("ipfx")
#ifdef _M_CEE_PURE
basic_istream& __CLR_OR_THIS_CALL operator>>(basic_istream&(__clrcall* _Pfn)(basic_istream&) ) {
// call basic_istream manipulator
return _Pfn(*this);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(_Myios&(__clrcall* _Pfn)(_Myios&) ) { // call basic_ios manipulator
_Pfn(*this);
return *this;
}
basic_istream& __CLR_OR_THIS_CALL operator>>(ios_base&(__clrcall* _Pfn)(ios_base&) ) { // call ios_base manipulator
_Pfn(*this);
return *this;
}
#endif // defined(_M_CEE_PURE)
basic_istream& __CLR_OR_THIS_CALL operator>>(basic_istream&(__cdecl* _Pfn)(basic_istream&) ) {
// call basic_istream manipulator
return _Pfn(*this);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(_Myios&(__cdecl* _Pfn)(_Myios&) ) { // call basic_ios manipulator
_Pfn(*this);
return *this;
}
basic_istream& __CLR_OR_THIS_CALL operator>>(ios_base&(__cdecl* _Pfn)(ios_base&) ) { // call ios_base manipulator
_Pfn(*this);
return *this;
}
private:
template <class _Ty>
basic_istream& _Common_extract_with_num_get(_Ty& _Val) { // formatted extract with num_get
ios_base::iostate _Err = ios_base::goodbit;
const sentry _Ok(*this);
if (_Ok) { // state okay, use facet to extract
_TRY_IO_BEGIN
_STD use_facet<_Nget>(this->getloc()).get(*this, {}, *this, _Err, _Val);
_CATCH_IO_END
}
_Myios::setstate(_Err);
return *this;
}
template <class = void>
void _Increment_gcount() noexcept {
if (_Chcount != (numeric_limits<streamsize>::max)()) {
++_Chcount;
}
}
public:
basic_istream& __CLR_OR_THIS_CALL operator>>(bool& _Val) { // extract a boolean
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(short& _Val) { // extract a short
ios_base::iostate _Err = ios_base::goodbit;
const sentry _Ok(*this);
if (_Ok) { // state okay, use facet to extract
_TRY_IO_BEGIN
long _Lval;
_STD use_facet<_Nget>(this->getloc()).get(*this, {}, *this, _Err, _Lval);
if (_Lval < SHRT_MIN) {
_Err |= ios_base::failbit;
_Val = SHRT_MIN;
} else if (_Lval > SHRT_MAX) {
_Err |= ios_base::failbit;
_Val = SHRT_MAX;
} else {
_Val = static_cast<short>(_Lval);
}
_CATCH_IO_END
}
_Myios::setstate(_Err);
return *this;
}
// NOTE:
// If you are not using native wchar_t, the unsigned short extractor
// is masked by an explicit specialization that treats an unsigned
// short as a wide character.
// To read or write unsigned shorts as integers with wchar_t streams,
// make wchar_t a native type with the command line option /Zc:wchar_t.
basic_istream& __CLR_OR_THIS_CALL operator>>(unsigned short& _Val) { // extract an unsigned short
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(int& _Val) { // extract an int
static_assert(sizeof(int) == sizeof(long), "Bad overflow assumptions due to sizeof(int) != sizeof(long)");
long _Result = _Val;
_Common_extract_with_num_get(_Result);
_Val = _Result;
return *this;
}
basic_istream& __CLR_OR_THIS_CALL operator>>(unsigned int& _Val) { // extract an unsigned int
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(long& _Val) { // extract a long
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(unsigned long& _Val) { // extract an unsigned long
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(long long& _Val) { // extract a long long
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(unsigned long long& _Val) { // extract an unsigned long long
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(float& _Val) { // extract a float
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(double& _Val) { // extract a double
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(long double& _Val) { // extract a long double
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(void*& _Val) { // extract a void pointer
return _Common_extract_with_num_get(_Val);
}
basic_istream& __CLR_OR_THIS_CALL operator>>(_Mysb* _Strbuf) { // extract until end-of-file into a stream buffer
_Chcount = 0; // behaves as an unformatted input function
const sentry _Ok(*this, true);
ios_base::iostate _State = ios_base::goodbit;
if (_Ok && _Strbuf) { // state okay, extract characters
_TRY_IO_BEGIN
for (int_type _Meta = _Myios::rdbuf()->sgetc();; _Meta = _Myios::rdbuf()->snextc()) {
if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // end of file, quit
_State |= ios_base::eofbit;
break;
}
// got a character, insert it into buffer
_TRY_BEGIN
if (_Traits::eq_int_type(_Traits::eof(), _Strbuf->sputc(_Traits::to_char_type(_Meta)))) {
break;
}
_CATCH_ALL
break;
_CATCH_END
_Increment_gcount();
}
_CATCH_IO_END
}
if (_Chcount == 0) { // If the function inserts no characters, it calls setstate(failbit)
_State |= ios_base::failbit;
}
_Myios::setstate(_State);
return *this;
}
int_type __CLR_OR_THIS_CALL get() { // extract a metacharacter
int_type _Meta = 0;
ios_base::iostate _State = ios_base::goodbit;
_Chcount = 0;
const sentry _Ok(*this, true);
if (!_Ok) {
_Meta = _Traits::eof(); // state not okay, return EOF
} else { // state okay, extract a character
_TRY_IO_BEGIN
_Meta = _Myios::rdbuf()->sgetc();
if (_Traits::eq_int_type(_Traits::eof(), _Meta)) {
_State |= ios_base::eofbit | ios_base::failbit; // end of file
} else { // got a character, count it
_Myios::rdbuf()->sbumpc();
_Chcount = 1;
}
_CATCH_IO_END
}
_Myios::setstate(_State);
return _Meta;
}
basic_istream& __CLR_OR_THIS_CALL get(_Elem* _Str, streamsize _Count) { // get up to _Count characters into NTCS
return get(_Str, _Count, _Myios::widen('\n'));
}
basic_istream& __CLR_OR_THIS_CALL get(_Elem* _Str, streamsize _Count, _Elem _Delim) {
// get up to _Count characters into NTCS, stop before _Delim
ios_base::iostate _State = ios_base::goodbit;
_Chcount = 0;
const sentry _Ok(*this, true);
if (_Ok && 0 < _Count) { // state okay, extract characters
_TRY_IO_BEGIN
int_type _Meta = _Myios::rdbuf()->sgetc();
for (; 0 < --_Count; _Meta = _Myios::rdbuf()->snextc()) {
if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // end of file, quit
_State |= ios_base::eofbit;
break;
} else if (_Traits::to_char_type(_Meta) == _Delim) {
break; // got a delimiter, quit
} else { // got a character, add it to string
*_Str++ = _Traits::to_char_type(_Meta);
_Increment_gcount();
}
}
_CATCH_IO_END
}
_Myios::setstate(_Chcount == 0 ? _State | ios_base::failbit : _State);
*_Str = _Elem(); // add terminating null character
return *this;
}
basic_istream& __CLR_OR_THIS_CALL get(_Elem& _Ch) { // get a character
int_type _Meta = get();
if (!_Traits::eq_int_type(_Traits::eof(), _Meta)) {
_Ch = _Traits::to_char_type(_Meta);
}
return *this;
}
basic_istream& __CLR_OR_THIS_CALL get(_Mysb& _Strbuf) { // extract up to newline and insert into stream buffer
return get(_Strbuf, _Myios::widen('\n'));
}
basic_istream& __CLR_OR_THIS_CALL get(_Mysb& _Strbuf, _Elem _Delim) {
// extract up to delimiter and insert into stream buffer
ios_base::iostate _State = ios_base::goodbit;
_Chcount = 0;
const sentry _Ok(*this, true);
if (_Ok) { // state okay, use facet to extract
_TRY_IO_BEGIN
int_type _Meta = _Myios::rdbuf()->sgetc();
for (;; _Meta = _Myios::rdbuf()->snextc()) {
if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // end of file, quit
_State |= ios_base::eofbit;
break;
} else { // got a character, insert it into stream buffer
_TRY_BEGIN
_Elem _Ch = _Traits::to_char_type(_Meta);
if (_Ch == _Delim || _Traits::eq_int_type(_Traits::eof(), _Strbuf.sputc(_Ch))) {
break;
}
_CATCH_ALL
break;
_CATCH_END
_Increment_gcount();
}
}
_CATCH_IO_END
}
if (_Chcount == 0) {
_State |= ios_base::failbit;
}
_Myios::setstate(_State);
return *this;
}
basic_istream& __CLR_OR_THIS_CALL getline(_Elem* _Str, streamsize _Count) {
// get up to _Count characters into NTCS, discard newline
return getline(_Str, _Count, _Myios::widen('\n'));
}
basic_istream& __CLR_OR_THIS_CALL getline(_Elem* _Str, streamsize _Count, _Elem _Delim) {
// get up to _Count characters into NTCS, discard _Delim
ios_base::iostate _State = ios_base::goodbit;
_Chcount = 0;
const sentry _Ok(*this, true);
if (_Ok && 0 < _Count) { // state okay, use facet to extract
int_type _Metadelim = _Traits::to_int_type(_Delim);
_TRY_IO_BEGIN
int_type _Meta = _Myios::rdbuf()->sgetc();
for (;; _Meta = _Myios::rdbuf()->snextc()) {
if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // end of file, quit
_State |= ios_base::eofbit;
break;
} else if (_Meta == _Metadelim) { // got a delimiter, discard it and quit
_Increment_gcount();
_Myios::rdbuf()->sbumpc();
break;
} else if (--_Count <= 0) { // buffer full, quit
_State |= ios_base::failbit;
break;
} else { // got a character, add it to string
*_Str++ = _Traits::to_char_type(_Meta);
_Increment_gcount();
}
}
_CATCH_IO_END
}
*_Str = _Elem(); // add terminating null character
_Myios::setstate(_Chcount == 0 ? _State | ios_base::failbit : _State);
return *this;
}
basic_istream& __CLR_OR_THIS_CALL ignore(streamsize _Count = 1, int_type _Metadelim = _Traits::eof()) {
// ignore up to _Count characters, discarding delimiter
ios_base::iostate _State = ios_base::goodbit;
_Chcount = 0;
const sentry _Ok(*this, true);
if (_Ok && 0 < _Count) { // state okay, use facet to extract
_TRY_IO_BEGIN
for (;;) { // get a metacharacter if more room in buffer
int_type _Meta;
if (_Count != (numeric_limits<streamsize>::max)() && --_Count < 0) {
break; // buffer full, quit
} else if (_Traits::eq_int_type(_Traits::eof(),
_Meta = _Myios::rdbuf()->sbumpc())) { // end of file, quit
_State |= ios_base::eofbit;
break;
} else { // got a character, count it
_Increment_gcount();
if (_Meta == _Metadelim) {
break; // got a delimiter, quit
}
}
}
_CATCH_IO_END
}
_Myios::setstate(_State);
return *this;
}
basic_istream& __CLR_OR_THIS_CALL read(_Elem* _Str, streamsize _Count) { // read up to _Count characters into buffer
ios_base::iostate _State = ios_base::goodbit;
_Chcount = 0;
const sentry _Ok(*this, true);
if (_Ok && 0 < _Count) { // state okay, use facet to extract
_TRY_IO_BEGIN
const streamsize _Num = _Myios::rdbuf()->sgetn(_Str, _Count);
_Chcount = _Num;
if (_Num != _Count) {
_State |= ios_base::eofbit | ios_base::failbit; // short read
}
_CATCH_IO_END
}
_Myios::setstate(_State);
return *this;
}
streamsize __CLR_OR_THIS_CALL readsome(_Elem* _Str, streamsize _Count) {
// read up to _Count characters into buffer, without blocking
ios_base::iostate _State = ios_base::goodbit;
_Chcount = 0;
const sentry _Ok(*this, true);
streamsize _Num;
if (!_Ok) {
_State |= ios_base::failbit; // no buffer, fail
} else if ((_Num = _Myios::rdbuf()->in_avail()) < 0) {
_State |= ios_base::eofbit; // no characters available
} else if (0 < _Count && 0 < _Num) { // read available
read(_Str, _Num < _Count ? _Num : _Count);
}
_Myios::setstate(_State);
return gcount();
}
int_type __CLR_OR_THIS_CALL peek() {
ios_base::iostate _State = ios_base::goodbit;
_Chcount = 0;
int_type _Meta = 0;
const sentry _Ok(*this, true);
if (!_Ok) {
_Meta = _Traits::eof(); // state not okay, return EOF
} else { // state okay, read a character
_TRY_IO_BEGIN
if (_Traits::eq_int_type(_Traits::eof(), _Meta = _Myios::rdbuf()->sgetc())) {
_State |= ios_base::eofbit;
}
_CATCH_IO_END
}
_Myios::setstate(_State);
return _Meta;
}
basic_istream& __CLR_OR_THIS_CALL putback(_Elem _Ch) { // put back a character
_Chcount = 0;
ios_base::iostate _State = ios_base::goodbit;
ios_base::iostate _Oldstate = _Myios::rdstate();
_Myios::clear(_Oldstate & ~ios_base::eofbit);
const sentry _Ok(*this, true);
if (_Ok) { // state okay, put character back
_TRY_IO_BEGIN
if (_Traits::eq_int_type(_Traits::eof(), _Myios::rdbuf()->sputbackc(_Ch))) {
_State |= ios_base::badbit | _Oldstate;
}
_CATCH_IO_END
}
_Myios::setstate(_State);
return *this;
}
basic_istream& __CLR_OR_THIS_CALL unget() { // put back last read character
_Chcount = 0;
ios_base::iostate _State = ios_base::goodbit;
ios_base::iostate _Oldstate = _Myios::rdstate();
_Myios::clear(_Oldstate & ~ios_base::eofbit);
const sentry _Ok(*this, true);
if (_Ok) { // state okay, put character back
_TRY_IO_BEGIN
if (_Traits::eq_int_type(_Traits::eof(), _Myios::rdbuf()->sungetc())) {
_State |= ios_base::badbit | _Oldstate;
}
_CATCH_IO_END
}
_Myios::setstate(_State);
return *this;
}
_NODISCARD streamsize __CLR_OR_THIS_CALL gcount() const noexcept /* strengthened */ {
// get count from last extraction
return _Chcount;
}
int __CLR_OR_THIS_CALL sync() { // synchronize with input source
const sentry _Ok(*this, true);
const auto _Rdbuf = _Myios::rdbuf();
if (!_Rdbuf) {
return -1;
}
ios_base::iostate _State = ios_base::goodbit;
_TRY_BEGIN
if (_Rdbuf->pubsync() == -1) {
_State |= ios_base::badbit;
}
_CATCH_ALL
_Myios::setstate(ios_base::badbit, true);
return -1;
_CATCH_END
if (_State & ios_base::badbit) {
_Myios::setstate(ios_base::badbit);
return -1;
}
return 0;
}
basic_istream& __CLR_OR_THIS_CALL seekg(pos_type _Pos) { // set input stream position to _Pos
ios_base::iostate _State = ios_base::goodbit;
ios_base::iostate _Oldstate = _Myios::rdstate();
_Myios::clear(_Oldstate & ~ios_base::eofbit);
const sentry _Ok(*this, true);
if (!this->fail()) {
_TRY_IO_BEGIN
if (static_cast<off_type>(_Myios::rdbuf()->pubseekpos(_Pos, ios_base::in)) == -1) {
_State |= ios_base::failbit;
}
_CATCH_IO_END
}
_Myios::setstate(_State);
return *this;
}
basic_istream& __CLR_OR_THIS_CALL seekg(off_type _Off, ios_base::seekdir _Way) {
// change input stream position by _Off, according to _Way
ios_base::iostate _State = ios_base::goodbit;
ios_base::iostate _Oldstate = _Myios::rdstate();
_Myios::clear(_Oldstate & ~ios_base::eofbit);
const sentry _Ok(*this, true);
if (!this->fail()) {
_TRY_IO_BEGIN
if (static_cast<off_type>(_Myios::rdbuf()->pubseekoff(_Off, _Way, ios_base::in)) == -1) {
_State |= ios_base::failbit;
}
_CATCH_IO_END
}
_Myios::setstate(_State);
return *this;
}
pos_type __CLR_OR_THIS_CALL tellg() {
const sentry _Ok(*this, true);
if (!this->fail()) {
_TRY_IO_BEGIN
return _Myios::rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in);
_CATCH_IO_END
}
return pos_type{off_type{-1}};
}
private:
streamsize _Chcount{}; // the character count
};
#pragma vtordisp(pop) // compiler bug workaround
#ifndef _NATIVE_WCHAR_T_DEFINED
template <class _Elem, class _Traits>
basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, _Elem& _Ch);
// NOTE:
// If you are not using native wchar_t, the following explicit
// specialization will mask the member function (above) that treats
// an unsigned short as an integer.
// To read or write unsigned shorts as integers with wchar_t streams,
// make wchar_t a native type with the command line option /Zc:wchar_t.
template <>
inline basic_istream<unsigned short, char_traits<unsigned short>>& __CLR_OR_THIS_CALL basic_istream<unsigned short,
char_traits<unsigned short>>::operator>>(unsigned short& _Ch) { // extract a character
return _STD operator>>(*this, _Ch);
}
#endif // !defined(_NATIVE_WCHAR_T_DEFINED)
#if defined(_DLL_CPPLIB)
#if !defined(_CRTBLD) || defined(__FORCE_INSTANCE)
template class _CRTIMP2_PURE_IMPORT basic_istream<char, char_traits<char>>;
template class _CRTIMP2_PURE_IMPORT basic_istream<wchar_t, char_traits<wchar_t>>;
#endif // !defined(_CRTBLD) || defined(__FORCE_INSTANCE)
#ifdef __FORCE_INSTANCE
template class _CRTIMP2_PURE_IMPORT basic_istream<unsigned short, char_traits<unsigned short>>;
#endif // defined(__FORCE_INSTANCE)
#endif // defined(_DLL_CPPLIB)
_EXPORT_STD extern "C++" template <class _Elem, class _Traits>
class basic_iostream : public basic_istream<_Elem, _Traits>,
public basic_ostream<_Elem, _Traits> { // control insertions and extractions from a stream buffer
public:
using _Myis = basic_istream<_Elem, _Traits>;
using _Myos = basic_ostream<_Elem, _Traits>;
using _Myios = basic_ios<_Elem, _Traits>;
using char_type = _Elem;
using traits_type = _Traits;
using int_type = typename _Traits::int_type;
using pos_type = typename _Traits::pos_type;
using off_type = typename _Traits::off_type;
explicit __CLR_OR_THIS_CALL basic_iostream(basic_streambuf<_Elem, _Traits>* _Strbuf)
: _Myis(_Strbuf, false), _Myos(_Noinit, false) {}
protected:
__CLR_OR_THIS_CALL basic_iostream(basic_iostream&& _Right) noexcept(false)
: _Myis(_Right.rdbuf(), false), _Myos(_Noinit, false) {
_Myios::init();
_Myios::move(_STD move(_Right));
}
basic_iostream& __CLR_OR_THIS_CALL operator=(basic_iostream&& _Right) noexcept /* strengthened */ {
this->swap(_Right);
return *this;
}
void __CLR_OR_THIS_CALL swap(basic_iostream& _Right) noexcept /* strengthened */ {
if (this != _STD addressof(_Right)) {
_Myios::swap(_Right);
}
}
public:
__CLR_OR_THIS_CALL basic_iostream(const basic_iostream&) = delete;
basic_iostream& __CLR_OR_THIS_CALL operator=(const basic_iostream&) = delete;
__CLR_OR_THIS_CALL ~basic_iostream() noexcept override {}
};
#if defined(_DLL_CPPLIB)
#if !defined(_CRTBLD) || defined(__FORCE_INSTANCE)
template class _CRTIMP2_PURE_IMPORT basic_iostream<char, char_traits<char>>;
template class _CRTIMP2_PURE_IMPORT basic_iostream<wchar_t, char_traits<wchar_t>>;
#endif // !defined(_CRTBLD) || defined(__FORCE_INSTANCE)
#ifdef __FORCE_INSTANCE
template class _CRTIMP2_PURE_IMPORT basic_iostream<unsigned short, char_traits<unsigned short>>;
#endif // defined(__FORCE_INSTANCE)
#endif // defined(_DLL_CPPLIB)
template <class _Elem, class _Traits>
basic_istream<_Elem, _Traits>& _Istream_extract_into_buffer(
basic_istream<_Elem, _Traits>& _Istr, size_t _Size, _Elem* _Str) {
using _Myis = basic_istream<_Elem, _Traits>;
using _Ctype = ctype<_Elem>;
ios_base::iostate _State = ios_base::goodbit;
size_t _Current = 0;
const typename _Myis::sentry _Ok(_Istr);
if (_Ok) { // state okay, extract characters
const _Ctype& _Ctype_fac = _STD use_facet<_Ctype>(_Istr.getloc());
_TRY_IO_BEGIN
size_t _Count = _Size;
const size_t _Width = static_cast<size_t>(_Istr.width());
if (_Width > 0 && _Width < _Size) {
_Count = _Width;
}
typename _Myis::int_type _Meta = _Istr.rdbuf()->sgetc();
_Elem _Ch;
for (; _Current < _Count - 1; _Meta = _Istr.rdbuf()->snextc(), (void) ++_Current) {
if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // end of file, quit
_State |= ios_base::eofbit;
break;
} else if (_Ctype_fac.is(_Ctype::space, _Ch = _Traits::to_char_type(_Meta)) || _Ch == _Elem()) {
break; // whitespace or nul, quit
} else {
_Str[_Current] = _Traits::to_char_type(_Meta); // add it to string
}
}
_CATCH_IO_(ios_base, _Istr)
}
_Analysis_assume_(static_cast<size_t>(_Current) < _Size); // TRANSITION, VSO-860375
_Str[_Current] = _Elem(); // add terminating null character
_Istr.width(0);
if (_Current == 0) {
_State |= ios_base::failbit;
}
_Istr.setstate(_State);
return _Istr;
}
#if _HAS_CXX20 // P0487R1 Fixing operator>>(basic_istream&, CharT*)
#pragma warning(push)
#pragma warning(disable : 6001) // Using uninitialized memory '_Str'.
_EXPORT_STD template <class _Elem, class _Traits, size_t _Size>
basic_istream<_Elem, _Traits>& operator>>(
basic_istream<_Elem, _Traits>& _Istr, _Out_writes_z_(_Size) _Elem (&_Str)[_Size]) {
return _Istream_extract_into_buffer(_Istr, _Size, _Str);
}
_EXPORT_STD template <class _Traits, size_t _Size>
basic_istream<char, _Traits>& operator>>(
basic_istream<char, _Traits>& _Istr, _Out_writes_z_(_Size) signed char (&_Str)[_Size]) {
return _Istream_extract_into_buffer(_Istr, _Size, reinterpret_cast<char*>(_Str));
}
_EXPORT_STD template <class _Traits, size_t _Size>
basic_istream<char, _Traits>& operator>>(
basic_istream<char, _Traits>& _Istr, _Out_writes_z_(_Size) unsigned char (&_Str)[_Size]) {
return _Istream_extract_into_buffer(_Istr, _Size, reinterpret_cast<char*>(_Str));
}
#pragma warning(pop)
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
template <class _Elem, class _Traits>
basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, _Elem* _Str) {
return _Istream_extract_into_buffer(_Istr, SIZE_MAX, _Str);
}
template <class _Traits>
basic_istream<char, _Traits>& operator>>(basic_istream<char, _Traits>& _Istr, signed char* _Str) {
return _Istream_extract_into_buffer(_Istr, SIZE_MAX, reinterpret_cast<char*>(_Str));
}
template <class _Traits>
basic_istream<char, _Traits>& operator>>(basic_istream<char, _Traits>& _Istr, unsigned char* _Str) {
return _Istream_extract_into_buffer(_Istr, SIZE_MAX, reinterpret_cast<char*>(_Str));
}
#endif // ^^^ !_HAS_CXX20 ^^^
_EXPORT_STD template <class _Elem, class _Traits>
basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, _Elem& _Ch) { // extract a character
using _Myis = basic_istream<_Elem, _Traits>;
typename _Myis::int_type _Meta;
ios_base::iostate _State = ios_base::goodbit;
const typename _Myis::sentry _Ok(_Istr);
if (_Ok) { // state okay, extract characters
_TRY_IO_BEGIN
_Meta = _Istr.rdbuf()->sbumpc();
if (_Traits::eq_int_type(_Traits::eof(), _Meta)) {
_State |= ios_base::eofbit | ios_base::failbit; // end of file
} else {
_Ch = _Traits::to_char_type(_Meta); // got a character
}
_CATCH_IO_(ios_base, _Istr)
}
_Istr.setstate(_State);
return _Istr;
}
_EXPORT_STD template <class _Traits>
basic_istream<char, _Traits>& operator>>(basic_istream<char, _Traits>& _Istr, signed char& _Ch) {
// extract a signed char
return _Istr >> reinterpret_cast<char&>(_Ch);
}
_EXPORT_STD template <class _Traits>
basic_istream<char, _Traits>& operator>>(basic_istream<char, _Traits>& _Istr, unsigned char& _Ch) {
// extract an unsigned char
return _Istr >> reinterpret_cast<char&>(_Ch);
}
template <class _Istr, class _Ty, class = void>
struct _Can_stream_in : false_type {};
template <class _Istr, class _Ty>
struct _Can_stream_in<_Istr, _Ty, void_t<decltype(_STD declval<_Istr&>() >> _STD declval<_Ty>())>> : true_type {};
_EXPORT_STD template <class _Istr, class _Ty,
enable_if_t<conjunction_v<is_convertible<_Istr*, ios_base*>, _Can_stream_in<_Istr, _Ty>>, int> = 0>
_Istr&& operator>>(_Istr&& _Is, _Ty&& _Val) { // extract from rvalue stream
_Is >> _STD forward<_Ty>(_Val);
return _STD move(_Is);
}
_EXPORT_STD template <class _Elem, class _Traits>
basic_istream<_Elem, _Traits>& __CLRCALL_OR_CDECL ws(basic_istream<_Elem, _Traits>& _Istr) { // consume whitespace
const typename basic_istream<_Elem, _Traits>::sentry _Ok(_Istr, true);
if (_Ok) { // state okay, extract characters
ios_base::iostate _State = ios_base::goodbit;
const auto& _Ctype_fac = _STD use_facet<ctype<_Elem>>(_Istr.getloc());
_TRY_IO_BEGIN
for (typename _Traits::int_type _Meta = _Istr.rdbuf()->sgetc();; _Meta = _Istr.rdbuf()->snextc()) {
if (_Traits::eq_int_type(_Traits::eof(), _Meta)) { // end of file, quit
_State |= ios_base::eofbit;
break;
} else if (!_Ctype_fac.is(ctype<_Elem>::space, _Traits::to_char_type(_Meta))) {
break; // not whitespace, quit
}
}
_CATCH_IO_(ios_base, _Istr)
_Istr.setstate(_State);
}
return _Istr;
}
_STD_END
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _ISTREAM_