// istream standard header // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #pragma once #ifndef _ISTREAM_ #define _ISTREAM_ #include #if _STL_COMPILER_PREPROCESSOR #include #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 // CLASS TEMPLATE basic_istream template 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) : _Chcount(_Right._Chcount) { _Myios::init(); _Myios::move(_STD move(_Right)); _Right._Chcount = 0; } basic_istream& __CLR_OR_THIS_CALL operator=(basic_istream&& _Right) { this->swap(_Right); return *this; } void __CLR_OR_THIS_CALL swap(basic_istream& _Right) { _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; virtual __CLR_OR_THIS_CALL ~basic_istream() noexcept {} using int_type = typename _Traits::int_type; using pos_type = typename _Traits::pos_type; using off_type = typename _Traits::off_type; // CLASS TEMPLATE sentry 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(); } // TRANSITION, ABI: non-Standard ipfx() is preserved for binary compatibility 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 void __CLR_OR_THIS_CALL isfx() { // perform any wrapup } #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 // _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 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; } 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(_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 ++_Chcount; } _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; } _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); ++_Chcount; } } _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 ++_Chcount; } } _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 ++_Chcount; _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); ++_Chcount; } } _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::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 ++_Chcount; 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 { // 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; } bool _Sync_failed = true; // sync fails if an exception is thrown _TRY_IO_BEGIN _Sync_failed = _Rdbuf->pubsync() == -1; _CATCH_IO_END if (_Sync_failed) { _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() && static_cast(_Myios::rdbuf()->pubseekpos(_Pos, ios_base::in)) == -1) { _Myios::setstate(_State | ios_base::failbit); } 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() && static_cast(_Myios::rdbuf()->pubseekoff(_Off, _Way, ios_base::in)) == -1) { _Myios::setstate(_State | ios_base::failbit); } return *this; } pos_type __CLR_OR_THIS_CALL tellg() { const sentry _Ok(*this, true); if (!this->fail()) { return _Myios::rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in); } else { return pos_type(-1); } } private: streamsize _Chcount; // the character count }; #pragma vtordisp(pop) // compiler bug workaround #ifndef _NATIVE_WCHAR_T_DEFINED template 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>& __CLR_OR_THIS_CALL basic_istream>::operator>>(unsigned short& _Ch) { // extract a character return _STD operator>>(*this, _Ch); } #endif // _NATIVE_WCHAR_T_DEFINED #if defined(_DLL_CPPLIB) #if !defined(_CRTBLD) || defined(__FORCE_INSTANCE) template class _CRTIMP2_PURE_IMPORT basic_istream>; template class _CRTIMP2_PURE_IMPORT basic_istream>; #endif // !defined(_CRTBLD) || defined(__FORCE_INSTANCE) #ifdef __FORCE_INSTANCE template class _CRTIMP2_PURE_IMPORT basic_istream>; #endif // __FORCE_INSTANCE #endif // defined(_DLL_CPPLIB) // CLASS TEMPLATE basic_iostream template 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) : _Myis(_Right.rdbuf(), false), _Myos(_Noinit, false) { _Myios::init(); _Myios::move(_STD move(_Right)); } basic_iostream& __CLR_OR_THIS_CALL operator=(basic_iostream&& _Right) { this->swap(_Right); return *this; } void __CLR_OR_THIS_CALL swap(basic_iostream& _Right) { 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; virtual __CLR_OR_THIS_CALL ~basic_iostream() noexcept {} }; #if defined(_DLL_CPPLIB) #if !defined(_CRTBLD) || defined(__FORCE_INSTANCE) template class _CRTIMP2_PURE_IMPORT basic_iostream>; template class _CRTIMP2_PURE_IMPORT basic_iostream>; #endif // !defined(_CRTBLD) || defined(__FORCE_INSTANCE) #ifdef __FORCE_INSTANCE template class _CRTIMP2_PURE_IMPORT basic_iostream>; #endif // __FORCE_INSTANCE #endif // defined(_DLL_CPPLIB) // EXTRACTORS template 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(_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(_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'. template 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); } template basic_istream& operator>>( basic_istream& _Istr, _Out_writes_z_(_Size) signed char (&_Str)[_Size]) { return _Istream_extract_into_buffer(_Istr, _Size, reinterpret_cast(_Str)); } template basic_istream& operator>>( basic_istream& _Istr, _Out_writes_z_(_Size) unsigned char (&_Str)[_Size]) { return _Istream_extract_into_buffer(_Istr, _Size, reinterpret_cast(_Str)); } #pragma warning(pop) #else // _HAS_CXX20 template basic_istream<_Elem, _Traits>& operator>>(basic_istream<_Elem, _Traits>& _Istr, _Elem* _Str) { return _Istream_extract_into_buffer(_Istr, SIZE_MAX, _Str); } template basic_istream& operator>>(basic_istream& _Istr, signed char* _Str) { return _Istream_extract_into_buffer(_Istr, SIZE_MAX, reinterpret_cast(_Str)); } template basic_istream& operator>>(basic_istream& _Istr, unsigned char* _Str) { return _Istream_extract_into_buffer(_Istr, SIZE_MAX, reinterpret_cast(_Str)); } #endif // _HAS_CXX20 template 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; } template basic_istream& operator>>( basic_istream& _Istr, signed char& _Ch) { // extract a signed char return _Istr >> reinterpret_cast(_Ch); } template basic_istream& operator>>( basic_istream& _Istr, unsigned char& _Ch) { // extract an unsigned char return _Istr >> reinterpret_cast(_Ch); } template struct _Can_stream_in : false_type {}; template struct _Can_stream_in<_Istr, _Ty, void_t() >> _STD declval<_Ty>())>> : true_type {}; template >, is_base_of, _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); } // MANIPULATORS template 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>(_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_