X-Git-Url: http://git.buserror.net/cgi-bin/gitweb.cgi?p=polintos%2Fscott%2Fpriv.git;a=blobdiff_plain;f=include%2Fc%2B%2B%2Fstl%2Fstl%2F_istream.c;fp=include%2Fc%2B%2B%2Fstl%2Fstl%2F_istream.c;h=32ec4a940910afe0b10005ab7530ddcc708e9a36;hp=0000000000000000000000000000000000000000;hb=173d8903eb9d51a4ea7d7fa3e52dc86c9bb6d4f1;hpb=b024710fe2b60cd4a42a8993b61333d6cdb56ca3 diff --git a/include/c++/stl/stl/_istream.c b/include/c++/stl/stl/_istream.c new file mode 100644 index 0000000..32ec4a9 --- /dev/null +++ b/include/c++/stl/stl/_istream.c @@ -0,0 +1,1429 @@ +/* + * Copyright (c) 1999 + * Silicon Graphics Computer Systems, Inc. + * + * Copyright (c) 1999 + * Boris Fomitchev + * + * This material is provided "as is", with absolutely no warranty expressed + * or implied. Any use is at your own risk. + * + * Permission to use or copy this software for any purpose is hereby granted + * without fee, provided the above notices are retained on all copies. + * Permission to modify the code and to distribute modified code is granted, + * provided the above notices are retained, and a notice that the code was + * modified is included with the above copyright notice. + * + */ +#ifndef _STLP_ISTREAM_C +#define _STLP_ISTREAM_C + +#ifndef _STLP_INTERNAL_ISTREAM +# include +#endif + +#ifndef _STLP_INTERNAL_LIMITS +# include +#endif + +#ifndef _STLP_INTERNAL_NUM_GET_H +# include +#endif + +#if defined ( _STLP_NESTED_TYPE_PARAM_BUG ) +// no wchar_t is supported for this mode +# define __BIS_int_type__ int +# define __BIS_pos_type__ streampos +# define __BIS_off_type__ streamoff +#else +# define __BIS_int_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_istream<_CharT, _Traits>::int_type +# define __BIS_pos_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_istream<_CharT, _Traits>::pos_type +# define __BIS_off_type__ _STLP_TYPENAME_ON_RETURN_TYPE basic_istream<_CharT, _Traits>::off_type +#endif + +_STLP_BEGIN_NAMESPACE + +//---------------------------------------------------------------------- +// Function object structs used by some member functions. + +_STLP_MOVE_TO_PRIV_NAMESPACE + +template +struct _Is_not_wspace { + typedef typename _Traits::char_type argument_type; + typedef bool result_type; + + const ctype* _M_ctype; + + _Is_not_wspace(const ctype* __c_type) : _M_ctype(__c_type) {} + bool operator()(argument_type __c) const + { return !_M_ctype->is(ctype_base::space, __c); } +}; + +template +struct _Is_wspace_null { + typedef typename _Traits::char_type argument_type; + typedef bool result_type; + + const ctype* _M_ctype; + + _Is_wspace_null(const ctype* __c_type) : _M_ctype(__c_type) {} + bool operator()(argument_type __c) const { + return _Traits::eq(__c, argument_type()) || + _M_ctype->is(ctype_base::space, __c); + } +}; + +template +struct _Scan_for_wspace { + typedef typename _Traits::char_type char_type; + typedef char_type* first_argument_type; + typedef char_type* second_argument_type; + typedef char_type* result_type; + + const ctype* _M_ctype; + + _Scan_for_wspace(const ctype* __ctype) : _M_ctype(__ctype) {} + const char_type* + operator()(const char_type* __first, const char_type* __last) const { + return _M_ctype->scan_is(ctype_base::space, __first, __last); + } +}; + +template +struct _Scan_wspace_null { + typedef typename _Traits::char_type char_type; + typedef char_type* first_argument_type; + typedef char_type* second_argument_type; + typedef char_type* result_type; + + const ctype* _M_ctype; + + _Scan_wspace_null(const ctype* __c_type) : _M_ctype(__c_type) {} + const char_type* + operator()(const char_type* __first, const char_type* __last) const { + __last = find_if(__first, __last, + _Eq_char_bound<_Traits>(char_type())); + return _M_ctype->scan_is(ctype_base::space, __first, __last); + } +}; + +template +struct _Scan_for_not_wspace { + typedef typename _Traits::char_type char_type; + typedef char_type* first_argument_type; + typedef char_type* second_argument_type; + typedef char_type* result_type; + + const ctype* _M_ctype; + + _Scan_for_not_wspace(const ctype* __c_type) : _M_ctype(__c_type) {} + const char_type* + operator()(const char_type* __first, const char_type* __last) const { + return _M_ctype->scan_not(ctype_base::space, __first, __last); + } +}; + +template +struct _Scan_for_char_val { + typedef typename _Traits::char_type char_type; + typedef char_type* first_argument_type; + typedef char_type* second_argument_type; + typedef char_type* result_type; + + char_type _M_val; + + _Scan_for_char_val(char_type __val) : _M_val(__val) {} + + const char_type* + operator()(const char_type* __first, const char_type* __last) const { + return find_if(__first, __last, _Eq_char_bound<_Traits>(_M_val)); + } +}; + +template +struct _Scan_for_int_val { + typedef typename _Traits::char_type char_type; + typedef typename _Traits::int_type int_type; + typedef char_type* first_argument_type; + typedef char_type* second_argument_type; + typedef char_type* result_type; + + int_type _M_val; + + _Scan_for_int_val(int_type __val) : _M_val(__val) {} + + const char_type* + operator()(const char_type* __first, const char_type* __last) const { + return find_if(__first, __last, + _Eq_int_bound<_Traits>(_M_val)); + } +}; + +// Helper function: try to push back a character to a streambuf, +// return true if the pushback succeeded. Does not throw. + +template +bool _STLP_CALL +__pushback(basic_streambuf<_CharT, _Traits>* __buf, _CharT __c) { + bool ret; + _STLP_TRY { + const typename _Traits::int_type __eof = _Traits::eof(); + ret = !_Traits::eq_int_type(__buf->sputbackc(__c), __eof); + } + _STLP_CATCH_ALL { + ret = false; + } + return ret; +} + +//---------------------------------------------------------------------- +// Definitions of basic_istream<>'s noninline member functions. + +// Helper function for formatted input of numbers. +template +ios_base::iostate _STLP_CALL +__get_num(basic_istream<_CharT, _Traits>& __that, _Number& __val) { + typedef typename basic_istream<_CharT, _Traits>::sentry _Sentry; + ios_base::iostate __err = 0; + _Sentry __sentry( __that ); // Skip whitespace. + if (__sentry) { + typedef num_get<_CharT, istreambuf_iterator<_CharT, _Traits> > _Num_get; + _STLP_TRY { + ((const _Num_get&)use_facet<_Num_get>(__that.getloc())).get(istreambuf_iterator<_CharT, _Traits>(__that.rdbuf()), + 0, __that, __err, __val); + } + _STLP_CATCH_ALL { + __that._M_handle_exception(ios_base::badbit); + } + if (__err) __that.setstate(__err); + } + return __err; +} + +_STLP_MOVE_TO_STD_NAMESPACE + +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (short& __val) { + long __lval; + _STLP_PRIV __get_num(*this, __lval); + if ( this->fail() ) { + return *this; + } + short __tmp = __STATIC_CAST(short, __lval); + unsigned short __uval = __STATIC_CAST(unsigned short, __lval); + // check if we lose digits + // if ((__val != __lval) && ((unsigned short)__val != __lval)) + if ((__tmp != __lval) && ((long)__uval != __lval)) + this->setstate(ios_base::failbit); + else + __val = __tmp; + return *this; +} + +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (int& __val) { + long __lval; + _STLP_PRIV __get_num(*this, __lval); + if ( this->fail() ) { + return *this; + } + int __tmp = __lval; + unsigned int __uval = __lval; + // check if we lose digits + // if ((__val != __lval) && ((unsigned int)__val != __lval)) + if ((__tmp != __lval) && ((long)__uval != __lval)) + this->setstate(ios_base::failbit); + else + __val = __tmp; + return *this; +} + +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (unsigned short& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} + +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (unsigned int& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} + +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (long& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} + +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (unsigned long& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} + +#if defined (_STLP_LONG_LONG) +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (_STLP_LONG_LONG& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} + +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (unsigned _STLP_LONG_LONG& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} +#endif +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (float& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (double& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} +#if !defined (_STLP_NO_LONG_DOUBLE) +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (long double& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} +#endif +#if !defined (_STLP_NO_BOOL) +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (bool& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} +#endif + +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>> (void*& __val) { + _STLP_PRIV __get_num(*this, __val); + return *this; +} + +// Unformatted input + +template +__BIS_int_type__ +basic_istream<_CharT, _Traits>::peek() { + typename _Traits::int_type __tmp = _Traits::eof(); + + this->_M_gcount = 0; + sentry __sentry(*this, _No_Skip_WS()); + + if (__sentry) { + _STLP_TRY { + __tmp = this->rdbuf()->sgetc(); + } + _STLP_CATCH_ALL { + this->_M_handle_exception(ios_base::badbit); + } + if (this->_S_eof(__tmp)) + this->setstate(ios_base::eofbit); + } + + return __tmp; +} + + +template +__BIS_int_type__ +basic_istream<_CharT, _Traits>::get() { + typename _Traits::int_type __tmp = _Traits::eof(); + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry) { + _STLP_TRY { + __tmp = this->rdbuf()->sbumpc(); + } + _STLP_CATCH_ALL { + this->_M_handle_exception(ios_base::badbit); + } + + if (!this->_S_eof(__tmp)) + this->_M_gcount = 1; + } + + if (_M_gcount == 0) + this->setstate(ios_base::eofbit | ios_base::failbit); + + return __tmp; +} + +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::get(_CharT& __c) { + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry) { + typename _Traits::int_type __tmp = _Traits::eof(); + _STLP_TRY { + __tmp = this->rdbuf()->sbumpc(); + } + _STLP_CATCH_ALL { + this->_M_handle_exception(ios_base::badbit); + } + + if (!this->_S_eof(__tmp)) { + this->_M_gcount = 1; + __c = _Traits::to_char_type(__tmp); + } + } + + if (this->_M_gcount == 0) + this->setstate(ios_base::eofbit | ios_base::failbit); + + return *this; +} + + +// Read characters and discard them. The standard specifies a single +// function with two arguments, each with a default. We instead use +// three overloded functions, because it's possible to implement the +// first two more efficiently than the fully general third version. +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::ignore() { + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry) { + int_type __c; + _STLP_TRY { + __c = this->rdbuf()->sbumpc(); + } + _STLP_CATCH_ALL { + this->_M_handle_exception(ios_base::badbit); + return *this; + } + + if (!this->_S_eof(__c)) + this->_M_gcount = 1; + else + this->setstate(ios_base::eofbit); + } + + return *this; +} + +// Putback + +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::putback(_CharT __c) { + this->_M_gcount = 0; + sentry __sentry(*this, _No_Skip_WS()); + + if (__sentry) { + typename _Traits::int_type __tmp = _Traits::eof(); + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); +// if (!__buf || this->_S_eof(__buf->sputbackc(__c))) + if (__buf) { + _STLP_TRY { + __tmp = __buf->sputbackc(__c); + } + _STLP_CATCH_ALL { + this->_M_handle_exception(ios_base::badbit); + } + } + if (this->_S_eof(__tmp)) + this->setstate(ios_base::badbit); + } + else + this->setstate(ios_base::failbit); + + return *this; +} + +template +basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::unget() { + this->_M_gcount = 0; + + sentry __sentry(*this, _No_Skip_WS()); + + if (__sentry) { + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + // if (!__buf || _Traits::eq_int_type(__buf->sungetc(), _Traits::eof())) + if (__buf) { + _STLP_TRY { + if (this->_S_eof(__buf->sungetc())) + this->setstate(ios_base::badbit); + } + _STLP_CATCH_ALL { + this->_M_handle_exception(ios_base::badbit); + } + } else + this->setstate(ios_base::badbit); + } + else + this->setstate(ios_base::failbit); + + return *this; +} + +// Positioning and buffer control. + +template +int basic_istream<_CharT, _Traits>::sync() { + sentry __sentry(*this, _No_Skip_WS()); + + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + if (__buf) { + if (__buf->pubsync() == -1) { + this->setstate(ios_base::badbit); + return -1; + } + else + return 0; + } + else + return -1; +} + +template +__BIS_pos_type__ +basic_istream<_CharT, _Traits>::tellg() { + sentry __sentry(*this, _No_Skip_WS()); + + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + return (__buf && !this->fail()) ? __buf->pubseekoff(0, ios_base::cur, ios_base::in) + : pos_type(-1); +} + +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::seekg(pos_type __pos) { + sentry __sentry(*this, _No_Skip_WS()); + + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + if (!this->fail() && __buf) { + if (__buf->pubseekpos(__pos) == pos_type(-1)) { + this->setstate(ios_base::failbit); + } + } + return *this; +} + +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::seekg(off_type __off, ios_base::seekdir __dir) { + sentry __sentry(*this, _No_Skip_WS()); + + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + if (!this->fail() && __buf) + __buf->pubseekoff(__off, __dir); + return *this; +} + +// Formatted input of characters and character arrays. + +template +void basic_istream<_CharT, _Traits>::_M_formatted_get(_CharT& __c) { +// typename _Traits::int_type __tmp = _Traits::eof(); + + sentry __sentry(*this); // Skip whitespace. + + if (__sentry) { + typename _Traits::int_type __tmp;// = _Traits::eof(); + + _STLP_TRY { + __tmp = this->rdbuf()->sbumpc(); + } + _STLP_CATCH_ALL { + this->_M_handle_exception(ios_base::badbit); + return; + } + + if (!this->_S_eof(__tmp)) + __c = _Traits::to_char_type(__tmp); + else + this->setstate(ios_base::eofbit | ios_base::failbit); + } +} + + +//--------------------------------------------------------------------------- +// istream's helper functions. + +// A generic function for unbuffered input. We stop when we reach EOF, +// or when we have extracted _Num characters, or when the function object +// __is_delim return true. In the last case, it extracts the character +// for which __is_delim is true, if and only if __extract_delim is true. +// It appends a null character to the end of the string; this means that +// it may store up to _Num + 1 characters. +// +// __is_getline governs two corner cases: reading _Num characters without +// encountering delim or eof (in which case failbit is set if __is_getline +// is true); and reading _Num characters where the _Num+1'st character is +// eof (in which case eofbit is set if __is_getline is true). +// +// It is assumed that __is_delim never throws. +// +// Return value is the number of characters extracted, including the +// delimiter if it is extracted. Note that the number of characaters +// extracted isn't necessarily the same as the number stored. + +_STLP_MOVE_TO_PRIV_NAMESPACE + +template < class _CharT, class _Traits, class _Is_Delim> +streamsize _STLP_CALL +__read_unbuffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __buf, + streamsize _Num, _CharT* __s, + _Is_Delim __is_delim, + bool __extract_delim, bool __append_null, + bool __is_getline) { + streamsize __n = 0; + ios_base::iostate __status = 0; + + typedef typename basic_istream<_CharT, _Traits>::int_type int_type; + // The operations that can potentially throw are sbumpc, snextc, and sgetc. + _STLP_TRY { + for (;;) { + int_type __c = __buf->sbumpc(); // sschwarz + + if (__that->_S_eof(__c)) { + if (__n < _Num || __is_getline) + __status |= ios_base::eofbit; + break; + } + else if (__is_delim(_Traits::to_char_type(__c))) { + if (__extract_delim) { // Extract and discard current character. + ++__n; + } else if ( !__pushback(__buf, _Traits::to_char_type(__c)) ) { // leave delimiter + __status |= ios_base::failbit; + } + break; + } + else { // regular character + *__s++ = _Traits::to_char_type(__c); + ++__n; + } + + if (__n == _Num) { + if (__is_getline) // didn't find delimiter as one of the _Num chars + __status |= ios_base::failbit; + break; + } + } + } + _STLP_CATCH_ALL { + __that->_M_handle_exception(ios_base::badbit); + *__s = _STLP_DEFAULT_CONSTRUCTED(_CharT); + return __n; + } + + if (__append_null) + *__s = _STLP_DEFAULT_CONSTRUCTED(_CharT); + if (__status) + __that->setstate(__status); // This might throw. + return __n; +} + +// Much like __read_unbuffered, but with one additional function object: +// __scan_delim(first, last) returns the first pointer p in [first, last) +// such that __is_delim(p) is true. + +template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim> +streamsize _STLP_CALL +__read_buffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __buf, + streamsize _Num, _CharT* __s, + _Is_Delim __is_delim, _Scan_Delim __scan_delim, + bool __extract_delim, bool __append_null, + bool __is_getline) { + streamsize __n = 0; + ios_base::iostate __status = 0; + bool __done = false; + + _STLP_TRY { + while (__buf->_M_egptr() != __buf->_M_gptr() && !__done) { + const _CharT* __first = __buf->_M_gptr(); + const _CharT* __last = __buf->_M_egptr(); + //casting numeric_limits::max to streamsize only works is ptrdiff_t is signed or streamsize representation + //is larger than ptrdiff_t one. + _STLP_STATIC_ASSERT((sizeof(streamsize) > sizeof(ptrdiff_t)) || + (sizeof(streamsize) == sizeof(ptrdiff_t)) && numeric_limits::is_signed) + ptrdiff_t __request = __STATIC_CAST(ptrdiff_t, (min) (__STATIC_CAST(streamsize, (numeric_limits::max)()), _Num - __n)); + + const _CharT* __p = __scan_delim(__first, __last); + ptrdiff_t __chunk = (min) (ptrdiff_t(__p - __first), __request); + _Traits::copy(__s, __first, __chunk); + __s += __chunk; + __n += __chunk; + __buf->_M_gbump((int)__chunk); + + // We terminated by finding delim. + if (__p != __last && __p - __first <= __request) { + if (__extract_delim) { + __n += 1; + __buf->_M_gbump(1); + } + __done = true; + } + + // We terminated by reading all the characters we were asked for. + else if (__n == _Num) { + + // Find out if we have reached eof. This matters for getline. + if (__is_getline) { + if (__chunk == __last - __first) { + if (__that->_S_eof(__buf->sgetc())) + __status |= ios_base::eofbit; + } + else + __status |= ios_base::failbit; + } + __done = true; + } + + // The buffer contained fewer than _Num - __n characters. Either we're + // at eof, or we should refill the buffer and try again. + else { + if (__that->_S_eof(__buf->sgetc())) { + __status |= ios_base::eofbit; + __done = true; + } + } + } // Close the while loop. + } + _STLP_CATCH_ALL { + __that->_M_handle_exception(ios_base::badbit); + __done = true; + } + + if (__done) { + if (__append_null) + *__s = _STLP_DEFAULT_CONSTRUCTED(_CharT); + if (__status != 0) + __that->setstate(__status); // This might throw. + return __n; + } + + // If execution has reached this point, then we have an empty buffer but + // we have not reached eof. What that means is that the streambuf has + // decided to switch from buffered to unbuffered input. We switch to + // to __read_unbuffered. + + return __n + __read_unbuffered(__that, __buf, _Num - __n, __s, __is_delim, + __extract_delim,__append_null,__is_getline); +} + +_STLP_MOVE_TO_STD_NAMESPACE + +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::get(_CharT* __s, streamsize __n, + _CharT __delim) { + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry) { + if (__n > 0) { + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + + if (__buf->egptr() != __buf->gptr()) + this->_M_gcount = + _STLP_PRIV __read_buffered(this, __buf, __n - 1, __s, + _STLP_PRIV _Eq_char_bound<_Traits>(__delim), + _STLP_PRIV _Scan_for_char_val<_Traits>(__delim), + false, true, false); + else + this->_M_gcount = + _STLP_PRIV __read_unbuffered(this, __buf, __n - 1, __s, + _STLP_PRIV _Eq_char_bound<_Traits>(__delim), + false, true, false); + } + } + + if (this->_M_gcount == 0) + this->setstate(ios_base::failbit); + + return *this; +} + +// Getline is essentially identical to get, except that it extracts +// the delimiter. +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::getline(_CharT* __s, streamsize __n, + _CharT __delim) { + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry) { + if (__n > 0) { + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + this->_M_gcount = __buf->egptr() != __buf->gptr() + ? _STLP_PRIV __read_buffered(this, __buf, __n - 1, __s, + _STLP_PRIV _Eq_char_bound<_Traits>(__delim), + _STLP_PRIV _Scan_for_char_val<_Traits>(__delim), + true, true, true) + : _STLP_PRIV __read_unbuffered(this, __buf, __n - 1, __s, + _STLP_PRIV _Eq_char_bound<_Traits>(__delim), + true, true, true); + } + } + + if (this->_M_gcount == 0) + this->setstate(ios_base::failbit); + + return *this; +} + +// Read n characters. We don't look for any delimiter, and we don't +// put in a terminating null character. +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::read(char_type* __s, streamsize __n) { + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry && !this->eof()) { + basic_streambuf<_CharT, _Traits>*__buf = this->rdbuf(); + if (__buf->gptr() != __buf->egptr()) + _M_gcount + = _STLP_PRIV __read_buffered(this, __buf, __n, __s, + _STLP_PRIV _Constant_unary_fun(false), + _STLP_PRIV _Project2nd(), + false, false, false); + else + _M_gcount + = _STLP_PRIV __read_unbuffered(this, __buf, __n, __s, + _STLP_PRIV _Constant_unary_fun(false), + false, false, false); + } + else + this->setstate(ios_base::failbit); + + if (this->eof()) + this->setstate(ios_base::eofbit | ios_base::failbit); + + return *this; +} + + +// Read n or fewer characters. We don't look for any delimiter, and +// we don't put in a terminating null character. +template +streamsize +basic_istream<_CharT, _Traits>::readsome(char_type* __s, streamsize __nmax) { + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry && !this->eof() && __nmax >= 0) { + + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + streamsize __avail = __buf->in_avail(); + + // fbp : isn't full-blown setstate required here ? + if (__avail == -1) + this->_M_setstate_nothrow(ios_base::eofbit); + + else if (__avail != 0) { + + if (__buf->gptr() != __buf->egptr()) + _M_gcount + = _STLP_PRIV __read_buffered(this, __buf, (min) (__avail, __nmax), __s, + _STLP_PRIV _Constant_unary_fun(false), + _STLP_PRIV _Project2nd(), + false, false, false); + else + _M_gcount + = _STLP_PRIV __read_unbuffered(this, __buf, (min) (__avail, __nmax), __s, + _STLP_PRIV _Constant_unary_fun(false), + false, false, false); + } + } + else { + // fbp : changed so that failbit is set only there, to pass Dietmar's test + if (this->eof()) + this->setstate(ios_base::eofbit | ios_base::failbit); + else + this->setstate(ios_base::failbit); + } + + // if (this->eof()) + // this->setstate(ios_base::eofbit | ios_base::failbit); + + return _M_gcount; +} + +template +void basic_istream<_CharT, _Traits>::_M_formatted_get(_CharT* __s) { + sentry __sentry(*this); // Skip whitespace. + + if (__sentry) { + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + streamsize __nmax = this->width() > 0 + ? this->width() - 1 + : ((numeric_limits::max)() / sizeof(_CharT)) - 1; + + streamsize __n = __buf->gptr() != __buf->egptr() + ? _STLP_PRIV __read_buffered(this, __buf, __nmax, __s, + _STLP_PRIV _Is_wspace_null<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), + _STLP_PRIV _Scan_wspace_null<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), + false, true, false) + : _STLP_PRIV __read_unbuffered(this, __buf, __nmax, __s, + _STLP_PRIV _Is_wspace_null<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), + false, true, false); + if (__n == 0) + this->setstate(ios_base::failbit); + } + this->width(0); +} + +// A generic unbuffered function for ignoring characters. We stop +// when we reach EOF, or when the function object __is_delim returns +// true. In the last case, it extracts the character for which +// __is_delim is true, if and only if __extract_delim is true. + +template < class _CharT, class _Traits, class _Is_Delim> +void _STLP_CALL +_M_ignore_unbuffered(basic_istream<_CharT, _Traits>* __that, + basic_streambuf<_CharT, _Traits>* __buf, + _Is_Delim __is_delim, + bool __extract_delim, bool __set_failbit) { + bool __done = false; + ios_base::iostate __status = 0; + typedef typename basic_istream<_CharT, _Traits>::int_type int_type; + + _STLP_TRY { + while (!__done) { + int_type __c = __buf->sbumpc(); + + if (__that->_S_eof(__c)) { + __done = true; + __status |= __set_failbit ? ios_base::eofbit | ios_base::failbit + : ios_base::eofbit; + } + + else if (__is_delim(_Traits::to_char_type(__c))) { + __done = true; + if (!__extract_delim) + if (__that->_S_eof(__buf->sputbackc(_Traits::to_char_type(__c)))) + __status |= ios_base::failbit; + } + } + } + _STLP_CATCH_ALL { + __that->_M_handle_exception(ios_base::badbit); + } + + __that->setstate(__status); +} + +// A generic buffered function for ignoring characters. Much like +// _M_ignore_unbuffered, but with one additional function object: +// __scan_delim(first, last) returns the first pointer p in [first, +// last) such that __is_delim(p) is true. + +template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim> +void _STLP_CALL +_M_ignore_buffered(basic_istream<_CharT, _Traits>* __that, + basic_streambuf<_CharT, _Traits>* __buf, + _Is_Delim __is_delim, _Scan_Delim __scan_delim, + bool __extract_delim, bool __set_failbit) { + bool __at_eof = false; + bool __found_delim = false; + + _STLP_TRY { + while (__buf->_M_egptr() != __buf->_M_gptr() && !__at_eof && !__found_delim) { + const _CharT* __p = __scan_delim(__buf->_M_gptr(), __buf->_M_egptr()); + __buf->_M_gbump((int)(__p - __buf->_M_gptr())); + + if (__p != __buf->_M_egptr()) { // We found delim, so we're done. + if (__extract_delim) + __buf->_M_gbump(1); + __found_delim = true; + } + + else // No delim. Try to refil the buffer. + __at_eof = __that->_S_eof(__buf->sgetc()); + } // Close the while loop. + } + _STLP_CATCH_ALL { + __that->_M_handle_exception(ios_base::badbit); + return; + } + + if (__at_eof) { + __that->setstate(__set_failbit ? ios_base::eofbit | ios_base::failbit + : ios_base::eofbit); + return; + } + if (__found_delim) + return; + + // If execution has reached this point, then we have an empty buffer but + // we have not reached eof. What that means is that the streambuf has + // decided to switch from a buffered to an unbuffered mode. We switch + // to _M_ignore_unbuffered. + _M_ignore_unbuffered(__that, __buf, __is_delim, __extract_delim, __set_failbit); +} + +// Overloaded versions of _M_ignore_unbuffered and _M_ignore_unbuffered +// with an explicit count _Num. Return value is the number of +// characters extracted. +// +// The function object __max_chars takes two arguments, _Num and __n +// (the latter being the number of characters we have already read), +// and returns the maximum number of characters to read from the buffer. +// We parameterize _M_ignore_buffered so that we can use it for both +// bounded and unbounded input; for the former the function object should +// be minus<>, and for the latter it should return a constant maximum value. + +template < class _CharT, class _Traits, class _Max_Chars, class _Is_Delim> +streamsize _STLP_CALL +_M_ignore_unbuffered(basic_istream<_CharT, _Traits>* __that, + basic_streambuf<_CharT, _Traits>* __buf, + streamsize _Num, _Max_Chars __max_chars, + _Is_Delim __is_delim, + bool __extract_delim, bool __set_failbit) { + streamsize __n = 0; + ios_base::iostate __status = 0; + typedef typename basic_istream<_CharT, _Traits>::int_type int_type; + + _STLP_TRY { + while (__max_chars(_Num, __n) > 0) { + int_type __c = __buf->sbumpc(); + + if (__that->_S_eof(__c)) { + __status |= __set_failbit ? ios_base::eofbit | ios_base::failbit + : ios_base::eofbit; + break; + } + + else if (__is_delim(_Traits::to_char_type(__c))) { + if (__extract_delim) + ++__n; + else if (__that->_S_eof(__buf->sputbackc(_Traits::to_char_type(__c)))) + __status |= ios_base::failbit; + + break; + } + // fbp : added counter increment to pass Dietmar's test + ++__n; + } + } + _STLP_CATCH_ALL { + __that->_M_handle_exception(ios_base::badbit); + } + + if (__status) + __that->setstate(__status); // This might throw. + return __n; +} + +template < class _CharT, class _Traits, class _Max_Chars, class _Is_Delim, class _Scan_Delim> +streamsize _STLP_CALL +_M_ignore_buffered(basic_istream<_CharT, _Traits>* __that, + basic_streambuf<_CharT, _Traits>* __buf, + streamsize _Num, + _Max_Chars __max_chars, + _Is_Delim __is_delim, _Scan_Delim __scan_delim, + bool __extract_delim, bool __set_failbit) { + streamsize __n = 0; + bool __at_eof = false; + bool __done = false; + + _STLP_TRY { + while (__buf->_M_egptr() != __buf->_M_gptr() && !__done) { + ptrdiff_t __avail = __buf->_M_egptr() - __buf->_M_gptr(); + streamsize __m = __max_chars(_Num, __n); + + if (__avail >= __m) { // We have more characters than we need. + const _CharT* __last = __buf->_M_gptr() + __STATIC_CAST(ptrdiff_t, __m); + const _CharT* __p = __scan_delim(__buf->_M_gptr(), __last); + ptrdiff_t __chunk = __p - __buf->_M_gptr(); + __n += __chunk; + __buf->_M_gbump((int)__chunk); + + if (__extract_delim && __p != __last) { + __n += 1; + __buf->_M_gbump(1); + } + + __done = true; + } + + else { + const _CharT* __p = __scan_delim(__buf->_M_gptr(), __buf->_M_egptr()); + ptrdiff_t __chunk = __p - __buf->_M_gptr(); + __n += __chunk; + __buf->_M_gbump((int)__chunk); + + if (__p != __buf->_M_egptr()) { // We found delim. + if (__extract_delim) { + __n += 1; + __buf->_M_gbump(1); + } + + __done = true; + } + + // We didn't find delim. Try to refill the buffer. + else if (__that->_S_eof(__buf->sgetc())) { + __done = true; + __at_eof = true; + } + } + } // Close the while loop. + } + _STLP_CATCH_ALL { + __that->_M_handle_exception(ios_base::badbit); + return __n; + } + + if (__at_eof) + __that->setstate(__set_failbit ? ios_base::eofbit | ios_base::failbit + : ios_base::eofbit); + + if (__done) + return __n; + + // If execution has reached this point, then we have an empty buffer but + // we have not reached eof. What that means is that the streambuf has + // decided to switch from buffered to unbuffered input. We switch to + // to _M_ignore_unbuffered. + + return __n + _M_ignore_unbuffered(__that, __buf, _Num, __max_chars, + __is_delim, __extract_delim, __set_failbit); +} + + +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::ignore(streamsize __n) { + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry) { + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + typedef _STLP_PRIV _Constant_unary_fun _Const_bool; + typedef _STLP_PRIV _Constant_binary_fun _Const_streamsize; + const streamsize __maxss = (numeric_limits::max)(); + + if (__n == (numeric_limits::max)()) { + if (__buf->gptr() != __buf->egptr()) + _M_gcount = _M_ignore_buffered(this, __buf, + __maxss, _Const_streamsize(__maxss), + _Const_bool(false), + _STLP_PRIV _Project2nd(), + false, false); + else + _M_gcount = _M_ignore_unbuffered(this, __buf, + __maxss, _Const_streamsize(__maxss), + _Const_bool(false), false, false); + } + else { + if (__buf->gptr() != __buf->egptr()) + _M_gcount = _M_ignore_buffered(this, __buf, + __n, minus(), + _Const_bool(false), + _STLP_PRIV _Project2nd(), + false, false); + else + _M_gcount = _M_ignore_unbuffered(this, __buf, __n, minus(), + _Const_bool(false), false, false); + } + } + + return *this; +} + +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __delim) { + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry) { + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + typedef _STLP_PRIV _Constant_unary_fun _Const_bool; + typedef _STLP_PRIV _Constant_binary_fun + _Const_streamsize; + const streamsize __maxss = (numeric_limits::max)(); + + if (__n == (numeric_limits::max)()) { + if (__buf->gptr() != __buf->egptr()) + _M_gcount = _M_ignore_buffered(this, __buf, + __maxss, _Const_streamsize(__maxss), + _STLP_PRIV _Eq_int_bound<_Traits>(__delim), + _STLP_PRIV _Scan_for_int_val<_Traits>(__delim), + true, false); + else + _M_gcount = _M_ignore_unbuffered(this, __buf, + __maxss, _Const_streamsize(__maxss), + _STLP_PRIV _Eq_int_bound<_Traits>(__delim), + true, false); + } + else { + if (__buf->gptr() != __buf->egptr()) + _M_gcount = _M_ignore_buffered(this, __buf, + __n, minus(), + _STLP_PRIV _Eq_int_bound<_Traits>(__delim), + _STLP_PRIV _Scan_for_int_val<_Traits>(__delim), + true, false); + else + _M_gcount = _M_ignore_unbuffered(this, __buf, __n, minus(), + _STLP_PRIV _Eq_int_bound<_Traits>(__delim), + true, false); + } + } + + return *this; +} + +// This member function does not construct a sentry object, because +// it is called from sentry's constructor. +template +void basic_istream<_CharT, _Traits>::_M_skip_whitespace(bool __set_failbit) { + basic_streambuf<_CharT, _Traits>* __buf = this->rdbuf(); + if (!__buf) + this->setstate(ios_base::badbit); + else if (__buf->gptr() != __buf->egptr()) + _M_ignore_buffered(this, __buf, + _STLP_PRIV _Is_not_wspace<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), + _STLP_PRIV _Scan_for_not_wspace<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), + false, __set_failbit); + else + _M_ignore_unbuffered(this, __buf, + _STLP_PRIV _Is_not_wspace<_Traits>(__STATIC_CAST(const ctype<_CharT>*, this->_M_ctype_facet())), + false, __set_failbit); +} + + +// This is a very simple loop that reads characters from __src and puts +// them into __dest. It looks complicated because of the (standard- +// mandated) exception handling policy. +// +// We stop when we get an exception, when we fail to insert into the +// output streambuf, or when __is_delim is true. + +_STLP_MOVE_TO_PRIV_NAMESPACE + +template < class _CharT, class _Traits, class _Is_Delim> +streamsize _STLP_CALL +__copy_unbuffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __src, + basic_streambuf<_CharT, _Traits>* __dest, + _Is_Delim __is_delim, + bool __extract_delim, bool __rethrow) { + streamsize __extracted = 0; + ios_base::iostate __status = 0; + typedef typename basic_istream<_CharT, _Traits>::int_type int_type; + int_type __c; + + _STLP_TRY { + for (;;) { + // Get a character. If there's an exception, catch and (maybe) rethrow it. + __c = __src->sbumpc(); + + // If we failed to get a character, then quit. + if (__that->_S_eof(__c)) { + __status |= ios_base::eofbit; + break; + } + // If it's the delimiter, then quit. + else if (__is_delim(_Traits::to_char_type(__c))) { + if (!__extract_delim && !__pushback(__src, _Traits::to_char_type(__c))) + __status |= ios_base::failbit; + break; + } + else { + // Try to put the character in the output streambuf. + bool __failed = false; + _STLP_TRY { + if (!__that->_S_eof(__dest->sputc(_Traits::to_char_type(__c)))) + ++__extracted; + else + __failed = true; + } + _STLP_CATCH_ALL { + __failed = true; + } + + // If we failed to put the character in the output streambuf, then + // try to push it back to the input streambuf. + if (__failed && !__pushback(__src, _Traits::to_char_type(__c))) + __status |= ios_base::failbit; + + // fbp : avoiding infinite loop in io-27-6-1-2-3.exp + if (__failed) + break; + } + + } /* for (;;) */ + + } + // fbp : this try/catch moved here in reasonable assumption + // __is_delim never throw (__pushback is guaranteed not to) + _STLP_CATCH_ALL { + // See 27.6.1.2.3, paragraph 13. + if (__rethrow && __extracted == 0) + __that->_M_handle_exception(ios_base::failbit); + } + __that->setstate(__status); + return __extracted; +} + +// Buffered copying from one streambuf to another. We copy the characters +// in chunks, rather than one at a time. We still have to worry about all +// of the error conditions we checked in __copy_unbuffered, plus one more: +// the streambuf might decide to switch from a buffered to an unbuffered mode. + +template < class _CharT, class _Traits, class _Is_Delim, class _Scan_Delim> +streamsize _STLP_CALL +__copy_buffered(basic_istream<_CharT, _Traits>* __that, basic_streambuf<_CharT, _Traits>* __src, + basic_streambuf<_CharT, _Traits>* __dest, + _Scan_Delim __scan_delim, _Is_Delim __is_delim, + bool __extract_delim, bool __rethrow) { + streamsize __extracted = 0; + ios_base::iostate __status = 0; + typedef typename basic_istream<_CharT, _Traits>::int_type int_type; + //Borland compiler generates a warning if assignment because value is never used: + int_type __c /*= _Traits::eof()*/; + _CharT* __first = __src->_M_gptr(); + ptrdiff_t __avail = __src->_M_egptr() - __first; + // fbp : introduced to move catch/try blocks out of the loop + bool __do_handle_exceptions = false; + + _STLP_TRY { + for (;;) { + const _CharT* __last = __scan_delim(__first, __src->_M_egptr()); + + // Try to copy the entire input buffer to the output buffer. + streamsize __n = __dest->sputn(__first, __extract_delim && __last != __src->_M_egptr() + ? (__last - __first) + 1 + : (__last - __first)); + __src->_M_gbump((int)__n); + __extracted += __n; + + // from this on, catch() will call _M_handle_exceptions() + __do_handle_exceptions = true; + + if (__n < __avail) // We found the delimiter, or else failed to + break; // copy some characters. + + __c = __src->sgetc(); + + // Three possibilities: we succeeded in refilling the buffer, or + // we got EOF, or the streambuf has switched to unbuffered mode. + __first = __src->_M_gptr(); + __avail = __src->_M_egptr() - __first; + + if (__avail > 0) + {} // dwa 1/16/00 -- suppress a Metrowerks warning + else if (__that->_S_eof(__c)) { + __status |= ios_base::eofbit; + break; + } + else { + return __extracted + __copy_unbuffered(__that, __src, __dest, __is_delim, + __extract_delim, __rethrow); + } + + __do_handle_exceptions = false; + } + } + + _STLP_CATCH_ALL { + // See 27.6.1.2.3, paragraph 13. + if (__rethrow && __do_handle_exceptions && __extracted == 0) + __that->_M_handle_exception(ios_base::failbit); + } + + if (__status) + __that->setstate(__status); // This might throw. + return __extracted; +} + +_STLP_MOVE_TO_STD_NAMESPACE + +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits> + ::get(basic_streambuf<_CharT, _Traits>& __dest, _CharT __delim) { + sentry __sentry(*this, _No_Skip_WS()); + this->_M_gcount = 0; + + if (__sentry) { + basic_streambuf<_CharT, _Traits>* __src = this->rdbuf(); + + if (__src) + this->_M_gcount = __src->egptr() != __src->gptr() + ? _STLP_PRIV __copy_buffered(this, __src, &__dest, + _STLP_PRIV _Scan_for_char_val<_Traits>(__delim), + _STLP_PRIV _Eq_char_bound<_Traits>(__delim), + false, false) + : _STLP_PRIV __copy_unbuffered(this, __src, &__dest, + _STLP_PRIV _Eq_char_bound<_Traits>(__delim), + false, false); + } + + if (this->_M_gcount == 0) + this->setstate(ios_base::failbit); + + return *this; +} + +// Copying characters into a streambuf. +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits> + ::operator>>(basic_streambuf<_CharT, _Traits>* __dest) { + streamsize __n = 0; + typedef typename basic_istream<_CharT, _Traits>::sentry _Sentry; + _Sentry __sentry(*this); + if (__sentry) { + basic_streambuf<_CharT, _Traits>* __src = this->rdbuf(); + if (__src && __dest) + __n = __src->egptr() != __src->gptr() + ? _STLP_PRIV __copy_buffered(this, __src, __dest, + _STLP_PRIV _Project2nd(), + _STLP_PRIV _Constant_unary_fun(false), + false, true) + : _STLP_PRIV __copy_unbuffered(this, __src, __dest, + _STLP_PRIV _Constant_unary_fun(false), + false, true); + } + + if (__n == 0) + this->setstate(ios_base::failbit); + + return *this; +} + +// ---------------------------------------------------------------- +// basic_iostream<> class +// ---------------------------------------------------------------- + +template +basic_iostream<_CharT, _Traits> + ::basic_iostream(basic_streambuf<_CharT, _Traits>* __buf) + : basic_ios<_CharT, _Traits>(), + basic_istream<_CharT, _Traits>(__buf), + basic_ostream<_CharT, _Traits>(__buf) { + this->init(__buf); +} + +template +basic_iostream<_CharT, _Traits>::~basic_iostream() +{} + +_STLP_END_NAMESPACE + +#undef __BIS_int_type__ +#undef __BIS_pos_type__ +#undef __BIS_off_type__ + +#endif /* _STLP_ISTREAM_C */ + +// Local Variables: +// mode:C++ +// End: