first commit
This commit is contained in:
804
extern/stdcxx/4.2.1/include/istream.cc
vendored
Normal file
804
extern/stdcxx/4.2.1/include/istream.cc
vendored
Normal file
@@ -0,0 +1,804 @@
|
||||
/***************************************************************************
|
||||
*
|
||||
* istream.cc - definitions of basic_istream members
|
||||
*
|
||||
* $Id: istream.cc 637130 2008-03-14 15:16:33Z faridz $
|
||||
*
|
||||
***************************************************************************
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed
|
||||
* with this work for additional information regarding copyright
|
||||
* ownership. The ASF licenses this file to you under the Apache
|
||||
* License, Version 2.0 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*
|
||||
* Copyright 1994-2006 Rogue Wave Software.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
_RWSTD_NAMESPACE (__rw) {
|
||||
|
||||
|
||||
_EXPORT
|
||||
template <class _CharT, class _Traits, class _NativeType>
|
||||
_STD::basic_istream<_CharT, _Traits>&
|
||||
__rw_extract (_STD::basic_istream<_CharT, _Traits> &__strm,
|
||||
_NativeType &__val)
|
||||
{
|
||||
_RWSTD_ASSERT (0 != __strm.rdbuf ());
|
||||
|
||||
typedef _STD::istreambuf_iterator<_CharT, _Traits> _Iter;
|
||||
typedef _STD::num_get<_CharT, _Iter> _NumGet;
|
||||
|
||||
_STD::ios_base::iostate __err = _STD::ios_base::goodbit;
|
||||
|
||||
// eat leading whitespace, catching exceptions from sentry
|
||||
const _TYPENAME _STD::basic_istream<_CharT, _Traits>::sentry
|
||||
__ipfx (__strm /* , noskipws = false */);
|
||||
|
||||
if (__ipfx) {
|
||||
_TRY {
|
||||
_STD_USE_FACET (_NumGet, __strm.getloc ())
|
||||
.get (_Iter (__strm), _Iter (), __strm, __err, __val);
|
||||
}
|
||||
_CATCH (...) {
|
||||
__strm.setstate (__strm.badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
}
|
||||
|
||||
if (_STD::ios_base::goodbit != __err)
|
||||
__strm.setstate (__err);
|
||||
|
||||
return __strm;
|
||||
}
|
||||
|
||||
|
||||
} // namespace __rw
|
||||
|
||||
|
||||
_RWSTD_NAMESPACE (std) {
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
basic_istream<_CharT, _Traits>::
|
||||
_C_ipfx (bool __noskipws, ios_base::iostate __errbits)
|
||||
{
|
||||
// extension - zero out irrespective of state so that gcount()
|
||||
// called after any failed extraction (even formatted) reports 0
|
||||
// and always count _all_ extracted characters
|
||||
|
||||
if (ios_base::goodbit != this->rdstate ()) {
|
||||
this->setstate (ios_base::failbit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ios_base::iostate __state = ios_base::goodbit;
|
||||
|
||||
_TRY {
|
||||
if (this->tie ())
|
||||
this->tie ()->flush ();
|
||||
|
||||
if ( ios_base::eofbit == __errbits // passed by std::ws
|
||||
|| !__noskipws && this->flags () & ios_base::skipws) {
|
||||
|
||||
// skip over leading whitespace
|
||||
|
||||
basic_streambuf<char_type, traits_type>* const __rdbuf =
|
||||
this->rdbuf ();
|
||||
|
||||
_RWSTD_ASSERT (0 != __rdbuf);
|
||||
|
||||
const ctype<char_type> &__ctp =
|
||||
_USE_FACET (ctype<char_type>, this->getloc ());
|
||||
|
||||
for ( ; ; ) {
|
||||
|
||||
const char_type* const __gptr = __rdbuf->gptr ();
|
||||
const char_type* const __egptr = __rdbuf->egptr ();
|
||||
|
||||
if (__gptr < __egptr) {
|
||||
|
||||
// scan the sequence for the first non-whitespace char
|
||||
const streamsize __nskip =
|
||||
__ctp.scan_not (__ctp.space, __gptr, __egptr)
|
||||
- __gptr;
|
||||
|
||||
__rdbuf->gbump (__nskip);
|
||||
|
||||
if (__nskip < __egptr - __gptr)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
||||
const int_type __c (__rdbuf->sgetc ());
|
||||
|
||||
if (traits_type::eq_int_type (__c, traits_type::eof ())) {
|
||||
__state = __errbits;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!__ctp.is (__ctp.space,
|
||||
traits_type::to_char_type (__c)))
|
||||
break;
|
||||
|
||||
__rdbuf->sbumpc ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_CATCH (...) {
|
||||
this->setstate (ios_base::badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
|
||||
if (__state)
|
||||
this->setstate (__state);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
_TYPENAME basic_istream<_CharT, _Traits>::int_type
|
||||
basic_istream<_CharT, _Traits>::
|
||||
_C_unsafe_get (streamsize *__cnt /* = 0 */,
|
||||
int_type __delim /* = eof() */,
|
||||
int __flags /* = 0 */)
|
||||
{
|
||||
_RWSTD_ASSERT (0 != this->rdbuf ());
|
||||
|
||||
ios_base::iostate __err = ios_base::goodbit;
|
||||
|
||||
// initialize in case sgetc() below throws
|
||||
int_type __c (traits_type::eof ());
|
||||
|
||||
_TRY {
|
||||
|
||||
// get next char without extracting
|
||||
__c = this->rdbuf ()->sgetc ();
|
||||
|
||||
// extract delimiter or eos only if asked to
|
||||
// extract whitespace only if it doesn't terminate input
|
||||
if (traits_type::eq_int_type (__c, traits_type::eof ()))
|
||||
__err = ios_base::eofbit
|
||||
| (__flags & _C_faileof ? this->failbit : this->goodbit);
|
||||
else if ( ( _C_eatdelim & __flags
|
||||
|| !traits_type::eq_int_type (__c, __delim))
|
||||
&& ( _C_eatnull & __flags
|
||||
|| !traits_type::eq (traits_type::to_char_type (__c),
|
||||
char_type ()))
|
||||
&& ( !(_C_wsterm & __flags)
|
||||
|| !_USE_FACET (ctype<char_type>, this->getloc ())
|
||||
.is (ctype_base::space,
|
||||
traits_type::to_char_type (__c)))) {
|
||||
if (traits_type::eq_int_type (this->rdbuf ()->sbumpc (),
|
||||
traits_type::eof ()))
|
||||
__err = ios_base::failbit;
|
||||
else if (__cnt)
|
||||
++*__cnt; // increment number of extracted chars
|
||||
}
|
||||
}
|
||||
_CATCH (...) {
|
||||
this->setstate (ios_base::badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
|
||||
if (__err)
|
||||
this->setstate (__err);
|
||||
|
||||
return __c;
|
||||
}
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
basic_istream<_CharT, _Traits>::
|
||||
_C_get (basic_streambuf<char_type, traits_type> &__sb, int_type __delim)
|
||||
{
|
||||
_RWSTD_ASSERT (0 != this->rdbuf ());
|
||||
|
||||
ios_base::iostate __err = ios_base::goodbit;
|
||||
|
||||
const sentry __ipfx (*this, true /* noskipws */);
|
||||
|
||||
if (__ipfx) {
|
||||
|
||||
_C_gcount = 0;
|
||||
|
||||
_TRY {
|
||||
for ( ; ; ) {
|
||||
int_type __c (this->rdbuf ()->sgetc ());
|
||||
|
||||
if (traits_type::eq_int_type (__c, traits_type::eof ())) {
|
||||
__err = ios_base::eofbit;
|
||||
break;
|
||||
}
|
||||
|
||||
if (traits_type::eq_int_type (__c, __delim))
|
||||
break;
|
||||
|
||||
_TRY {
|
||||
__c = __sb.sputc (traits_type::to_char_type (__c));
|
||||
}
|
||||
_CATCH (...) {
|
||||
|
||||
// indicate to the outer catch block the the
|
||||
// exception rethrown from the call to setstate()
|
||||
// below should be propagated without setting
|
||||
// badbit (whose purpose is to indicates the
|
||||
// "badness" of *this, not some other object)
|
||||
__err = ios_base::failbit | _RW::__rw_rethrow;
|
||||
|
||||
// set failbit and rethrow if failbit is set in
|
||||
// exceptions() despite 27.6.1.3, p12, bullet 4
|
||||
this->setstate (__err);
|
||||
break;
|
||||
}
|
||||
|
||||
if (traits_type::eq_int_type (__c, traits_type::eof ())) {
|
||||
__err = ios_base::failbit;
|
||||
break;
|
||||
}
|
||||
|
||||
++_C_gcount;
|
||||
this->rdbuf ()->sbumpc ();
|
||||
}
|
||||
}
|
||||
_CATCH (...) {
|
||||
// will rethrow if `err' is set since the caught exception
|
||||
// is the one thrown during output and rethrown by setstate()
|
||||
// in the nested catch block above
|
||||
if (ios_base::goodbit == __err)
|
||||
__err = ios_base::badbit;
|
||||
|
||||
this->setstate (__err | _RW::__rw_rethrow);
|
||||
}
|
||||
}
|
||||
|
||||
// 27.6.1.3, p13
|
||||
if (!gcount ())
|
||||
__err |= ios_base::failbit;
|
||||
|
||||
if (__err)
|
||||
this->setstate (__err);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
basic_istream<_CharT, _Traits>::
|
||||
read (char_type *__s, streamsize __n, int_type __delim, int __flags)
|
||||
{
|
||||
// if __s is 0 function doesn't store characters (used by ignore)
|
||||
|
||||
_RWSTD_ASSERT (0 <= __n);
|
||||
_RWSTD_ASSERT (0 != this->rdbuf ());
|
||||
|
||||
const char_type __eos = char_type ();
|
||||
|
||||
const bool __getline = (_C_failend | _C_nullterm)
|
||||
== ((_C_failend | _C_nullterm) & __flags);
|
||||
|
||||
// "clear" buffer if reading a null-terminated string
|
||||
// follows the proposed resolution of lwg issue 243
|
||||
if (__getline)
|
||||
traits_type::assign (*__s, __eos);
|
||||
|
||||
// read and getline are unformatted (noskipws), others are formatted
|
||||
const sentry __ipfx (*this, !(_C_skipws & __flags));
|
||||
|
||||
// 27.6.1.2.1, p1 and 27.6.1.3, p1: proceed iff sentry is okay
|
||||
if (__ipfx) {
|
||||
|
||||
_C_gcount = 0;
|
||||
|
||||
// read at most n - 1 characters when null-terminating
|
||||
while (__n) {
|
||||
|
||||
// handle 27.6.1.3, p17 and p18
|
||||
if (0 == --__n && _C_nullterm & __flags) {
|
||||
if (!__getline)
|
||||
break;
|
||||
|
||||
const int_type __c (this->rdbuf ()->sgetc ());
|
||||
|
||||
if ( !traits_type::eq_int_type (__c, traits_type::eof ())
|
||||
&& !traits_type::eq_int_type (__c, __delim))
|
||||
break;
|
||||
|
||||
__flags &= ~_C_failend; // prevent failbit from being set
|
||||
|
||||
// will break out in the check below...
|
||||
}
|
||||
|
||||
// get (possibly extract) next char
|
||||
const int_type __c (_C_unsafe_get (&_C_gcount, __delim, __flags));
|
||||
|
||||
// eof or delimiter may terminate input
|
||||
if ( traits_type::eq_int_type (__c, traits_type::eof())
|
||||
|| traits_type::eq_int_type (__c, __delim))
|
||||
break;
|
||||
|
||||
const char_type __ch = traits_type::to_char_type (__c);
|
||||
|
||||
// space or eos char may terminate input
|
||||
if ( !(_C_eatnull & __flags) && traits_type::eq (__ch, __eos)
|
||||
|| _C_wsterm & __flags
|
||||
&& _USE_FACET (ctype<char_type>, this->getloc ())
|
||||
.is (ctype_base::space, __ch))
|
||||
break;
|
||||
|
||||
// ignore input if __s is null
|
||||
if (__s)
|
||||
traits_type::assign (*__s++, __ch);
|
||||
}
|
||||
|
||||
if (_C_nullterm & __flags && __s)
|
||||
traits_type::assign (*__s, __eos);
|
||||
}
|
||||
|
||||
// fail if no chars extracted or if end of buffer has been reached
|
||||
if ( _C_failnoi & __flags && !gcount ()
|
||||
|| _C_failend & __flags && !__n)
|
||||
this->setstate (ios_base::failbit);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// 27.6.1.3, p28
|
||||
template<class _CharT, class _Traits>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
basic_istream<_CharT, _Traits>::
|
||||
read (char_type *__s, streamsize __n)
|
||||
{
|
||||
_RWSTD_ASSERT (0 <= __n);
|
||||
_RWSTD_ASSERT (0 != this->rdbuf ());
|
||||
|
||||
// 27.6.1.3, p28: sets ios_base::failbit if !this->good()
|
||||
const sentry __ipfx (*this, true /* noskipws */);
|
||||
|
||||
// 27.6.1.2.1, p1 and 27.6.1.3, p1: proceed iff sentry is okay
|
||||
if (__ipfx) {
|
||||
|
||||
_C_gcount = 0;
|
||||
|
||||
streamsize __nread = 0;
|
||||
|
||||
_TRY {
|
||||
__nread = this->rdbuf ()->sgetn (__s, __n);
|
||||
|
||||
if (__nread >= 0)
|
||||
_C_gcount = __nread;
|
||||
}
|
||||
_CATCH (...) {
|
||||
this->setstate (ios_base::badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
|
||||
if (__n != __nread)
|
||||
this->setstate (ios_base::eofbit | ios_base::failbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
streamsize
|
||||
basic_istream<_CharT, _Traits>::
|
||||
readsome (char_type *__s, streamsize __n)
|
||||
{
|
||||
_RWSTD_ASSERT (0 != __s);
|
||||
_RWSTD_ASSERT (0 <= __n);
|
||||
_RWSTD_ASSERT (0 != this->rdbuf());
|
||||
|
||||
const sentry __ipfx (*this, true /* noskipws */);
|
||||
|
||||
if (__ipfx) {
|
||||
|
||||
_C_gcount = 0;
|
||||
|
||||
streamsize __nread = 0;
|
||||
|
||||
_TRY {
|
||||
|
||||
const streamsize __in_avail = this->rdbuf ()->in_avail ();
|
||||
|
||||
if (!__in_avail)
|
||||
return 0;
|
||||
|
||||
if (__n > __in_avail)
|
||||
__n = __in_avail;
|
||||
|
||||
// the call to sgetn() below is required to return >= 0
|
||||
__nread = __n >= 0 ? this->rdbuf ()->sgetn (__s, __n) : -1;
|
||||
|
||||
if (__nread >= 0)
|
||||
_C_gcount = __nread;
|
||||
}
|
||||
_CATCH (...) {
|
||||
this->setstate (ios_base::badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
|
||||
if (__nread < 0) {
|
||||
this->setstate (ios_base::eofbit);
|
||||
__nread = 0;
|
||||
}
|
||||
|
||||
return __nread;
|
||||
}
|
||||
else
|
||||
this->setstate (ios_base::failbit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
_TYPENAME basic_istream<_CharT, _Traits>::pos_type
|
||||
basic_istream<_CharT, _Traits>::
|
||||
tellg ()
|
||||
{
|
||||
_RWSTD_ASSERT (0 != this->rdbuf ());
|
||||
|
||||
const sentry __ipfx (*this, true /* noskipws */);
|
||||
|
||||
if (__ipfx && !this->fail ()) {
|
||||
|
||||
_TRY {
|
||||
return this->rdbuf ()->pubseekoff (0, ios_base::cur, ios_base::in);
|
||||
}
|
||||
_CATCH (...) {
|
||||
this->setstate (ios_base::badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
}
|
||||
|
||||
return off_type (-1);
|
||||
}
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
basic_istream<_CharT, _Traits>::
|
||||
putback (char_type __c)
|
||||
{
|
||||
const sentry __ipfx (*this, true /* noskipws */);
|
||||
|
||||
if (__ipfx) {
|
||||
|
||||
if (this->rdbuf ()) {
|
||||
_TRY {
|
||||
if (!traits_type::eq_int_type (this->rdbuf ()->sputbackc (__c),
|
||||
traits_type::eof ()))
|
||||
return *this;
|
||||
}
|
||||
_CATCH (...) {
|
||||
this->setstate (ios_base::badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
}
|
||||
|
||||
this->setstate (ios_base::badbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
basic_istream<_CharT, _Traits>::
|
||||
unget ()
|
||||
{
|
||||
const sentry __ipfx (*this, true /* noskipws */);
|
||||
|
||||
if (__ipfx) {
|
||||
|
||||
if (this->rdbuf ()) {
|
||||
|
||||
_TRY {
|
||||
|
||||
if (!traits_type::eq_int_type (this->rdbuf ()->sungetc (),
|
||||
traits_type::eof ()))
|
||||
return *this;
|
||||
}
|
||||
_CATCH (...) {
|
||||
this->setstate (ios_base::badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
}
|
||||
|
||||
this->setstate (ios_base::badbit);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
int
|
||||
basic_istream<_CharT, _Traits>::
|
||||
sync ()
|
||||
{
|
||||
const sentry __ipfx (*this, true /* noskipws */);
|
||||
|
||||
if (__ipfx && this->rdbuf ()) {
|
||||
|
||||
_TRY {
|
||||
if (-1 != this->rdbuf ()->pubsync ())
|
||||
return 0;
|
||||
}
|
||||
_CATCH (...) {
|
||||
this->setstate (ios_base::badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
|
||||
this->setstate (ios_base::badbit);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
basic_istream<_CharT, _Traits>::
|
||||
get (char_type *__s, streamsize __n, char_type __delim)
|
||||
{
|
||||
_RWSTD_ASSERT (0 != this->rdbuf ());
|
||||
|
||||
if (0 < __n) {
|
||||
// lwg issue 243: store the NUL character before
|
||||
// constructing the sentry object in case it throws
|
||||
traits_type::assign (__s [0], char_type ());
|
||||
}
|
||||
|
||||
const sentry __ipfx (*this, true /* noskipws */);
|
||||
|
||||
ios_base::iostate __err = ios_base::goodbit;
|
||||
|
||||
if (__ipfx) {
|
||||
|
||||
_C_gcount = 0;
|
||||
|
||||
_TRY {
|
||||
|
||||
basic_streambuf<char_type, traits_type>* const __rdbuf =
|
||||
this->rdbuf ();
|
||||
|
||||
for ( ; __n > 1; ) {
|
||||
|
||||
streamsize __navail =
|
||||
streamsize (__rdbuf->egptr () - __rdbuf->gptr ());
|
||||
|
||||
if (__n - 1 < __navail)
|
||||
__navail = __n - 1;
|
||||
|
||||
if (__navail) {
|
||||
|
||||
char_type* const __gptr = __rdbuf->gptr ();
|
||||
|
||||
const char_type* const __pdelim =
|
||||
traits_type::find (__gptr, __navail, __delim);
|
||||
|
||||
if (__pdelim) {
|
||||
__navail = streamsize (__pdelim - __gptr);
|
||||
|
||||
if (!__navail)
|
||||
break;
|
||||
}
|
||||
|
||||
traits_type::copy (__s + _C_gcount, __gptr, __navail);
|
||||
|
||||
__rdbuf->gbump (__navail);
|
||||
|
||||
_C_gcount += __navail;
|
||||
__n -= __navail;
|
||||
}
|
||||
else {
|
||||
|
||||
const int_type __c (__rdbuf->sgetc ());
|
||||
|
||||
if (traits_type::eq_int_type (__c, traits_type::eof ())) {
|
||||
__err = ios_base::eofbit;
|
||||
break;
|
||||
}
|
||||
|
||||
const char_type __ch = traits_type::to_char_type (__c);
|
||||
|
||||
if (traits_type::eq (__ch, __delim))
|
||||
break;
|
||||
|
||||
traits_type::assign (__s [_C_gcount++], __ch);
|
||||
--__n;
|
||||
|
||||
__rdbuf->sbumpc ();
|
||||
}
|
||||
}
|
||||
|
||||
traits_type::assign (__s [_C_gcount], char_type ());
|
||||
|
||||
if (!_C_gcount)
|
||||
__err |= ios_base::failbit;
|
||||
}
|
||||
_CATCH (...) {
|
||||
this->setstate (ios_base::badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
}
|
||||
|
||||
if (ios_base::goodbit != __err)
|
||||
this->setstate (__err);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<class _CharT, class _Traits>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
basic_istream<_CharT, _Traits>::
|
||||
getline (char_type *__line, streamsize __size, char_type __delim)
|
||||
{
|
||||
_RWSTD_ASSERT (__size >= 0);
|
||||
_RWSTD_ASSERT (!__size || __line);
|
||||
_RWSTD_ASSERT (0 != this->rdbuf ());
|
||||
|
||||
char_type __dummy;
|
||||
|
||||
if (0 < __size) {
|
||||
// lwg issue 243: store the NUL character before
|
||||
// constructing the sentry object in case it throws
|
||||
traits_type::assign (__line [0], char_type ());
|
||||
}
|
||||
else {
|
||||
// use a dummy buffer to avoid having to check size
|
||||
// again below, and prevent undefined behavior when
|
||||
// size is negative
|
||||
__line = &__dummy;
|
||||
__size = 0;
|
||||
}
|
||||
|
||||
const sentry __ipfx (*this, true /* noskipws */);
|
||||
|
||||
ios_base::iostate __err = ios_base::goodbit;
|
||||
|
||||
if (__ipfx) {
|
||||
|
||||
_C_gcount = 0;
|
||||
|
||||
basic_streambuf<char_type, traits_type>* const __rdbuf =
|
||||
this->rdbuf ();
|
||||
|
||||
_TRY {
|
||||
|
||||
for ( ; ; ) {
|
||||
|
||||
const char_type* const __gptr = __rdbuf->gptr ();
|
||||
const char_type* const __egptr = __rdbuf->egptr ();
|
||||
|
||||
// compute the lesser of the number of characters in the
|
||||
// stream buffer and the size of the destination buffer
|
||||
streamsize __navail = __egptr - __gptr;
|
||||
if (__size < __navail)
|
||||
__navail = __size;
|
||||
|
||||
if (__navail) {
|
||||
|
||||
// find the delimiter in the sequence if it exists
|
||||
const char_type* const __pdel =
|
||||
traits_type::find (__gptr, __navail, __delim);
|
||||
|
||||
if (__pdel) {
|
||||
__navail = __pdel - __gptr + 1;
|
||||
__size -= __navail - 1;
|
||||
}
|
||||
else if (__size == __navail)
|
||||
__size -= --__navail;
|
||||
else
|
||||
__size -= __navail;
|
||||
|
||||
// copy including delimiter, if any
|
||||
// (delimiter will be overwritten below)
|
||||
traits_type::copy (__line + _C_gcount, __gptr, __navail);
|
||||
|
||||
_C_gcount += __navail;
|
||||
|
||||
// advance gptr()
|
||||
__rdbuf->gbump (__navail);
|
||||
|
||||
if (__pdel) {
|
||||
traits_type::assign (__line [_C_gcount - 1],
|
||||
char_type ());
|
||||
break;
|
||||
}
|
||||
|
||||
if (2 > __size && __egptr - __gptr != __navail) {
|
||||
traits_type::assign (__line [_C_gcount], char_type ());
|
||||
__err = ios_base::failbit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// no data in buffer, trigger underflow()
|
||||
// note that streambuf may be unbuffered
|
||||
const int_type __c (__rdbuf->sgetc ());
|
||||
|
||||
if (traits_type::eq_int_type (__c, traits_type::eof ())) {
|
||||
traits_type::assign (__line [_C_gcount], char_type ());
|
||||
__err = ios_base::eofbit;
|
||||
break;
|
||||
}
|
||||
|
||||
const char_type __ch = traits_type::to_char_type (__c);
|
||||
if (traits_type::eq (__ch, __delim)) {
|
||||
traits_type::assign (__line [_C_gcount], char_type ());
|
||||
__rdbuf->sbumpc ();
|
||||
_C_gcount++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (2 > __size) {
|
||||
traits_type::assign (__line [_C_gcount], char_type ());
|
||||
__err = ios_base::failbit;
|
||||
break;
|
||||
}
|
||||
|
||||
traits_type::assign (__line [_C_gcount], __ch);
|
||||
--__size;
|
||||
|
||||
__rdbuf->sbumpc ();
|
||||
|
||||
// increment gcount only _after_ sbumpc() but _before_
|
||||
// the subsequent call to sgetc() to correctly reflect
|
||||
// the number of extracted characters in the presence
|
||||
// of exceptions thrown from streambuf virtuals
|
||||
++_C_gcount;
|
||||
}
|
||||
}
|
||||
}
|
||||
_CATCH (...) {
|
||||
this->setstate (ios_base::badbit | _RW::__rw_rethrow);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == _C_gcount)
|
||||
__err |= ios_base::failbit;
|
||||
|
||||
if (__err)
|
||||
this->setstate (__err);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _RWSTD_NO_UNDEFINED_TEMPLATES
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
basic_istream<_CharT, _Traits>::sentry::
|
||||
sentry (const sentry&)
|
||||
: _RW::__rw_guard (0)
|
||||
{
|
||||
_RWSTD_ASSERT (!"not callable");
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
void
|
||||
basic_istream<_CharT, _Traits>::sentry::
|
||||
operator= (const sentry&)
|
||||
{
|
||||
_RWSTD_ASSERT (!"not callable");
|
||||
}
|
||||
|
||||
#endif // _RWSTD_NO_UNDEFINED_TEMPLATES
|
||||
|
||||
|
||||
} // namespace std
|
||||
Reference in New Issue
Block a user