From 519e77eba035f16b16eccf457c2c441343da9152 Mon Sep 17 00:00:00 2001 From: bkoz Date: Tue, 8 May 2001 03:07:56 +0000 Subject: [PATCH] 2001-05-07 Benjamin Kosnik libstdc++/2523 * include/bits/std_fstream.h (basic_filebuf): Change signature. * include/bits/fstream.tcc (basic_filebuf): Change bool argument to int_type, pass in buffer size info. * include/bits/std_streambuf.h (_M_is_indeterminate): Check for unbuffered situation. (underflow): Remove codecvt bits for the time being. * include/bits/istream.tcc (istream::sentry): Avoid sputbackc call. * include/bits/locale_facets.tcc (_M_extract): Cache dereference values from iterators, clean. * src/locale.cc: Ditto. * include/bits/sbuf_iter.h: Format. * src/ios.cc: Explicitly pass in buffer sizes at creation time. * testsuite/27_io/narrow_stream_objects.cc: Add tests. * testsuite/27_io/filebuf.cc: Tweaks. * testsuite/27_io/filebuf_members.cc: Tweaks. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41908 138bc75d-0d04-0410-961f-82ee72b054a4 --- libstdc++-v3/ChangeLog | 19 ++++ libstdc++-v3/include/bits/fstream.tcc | 61 ++---------- libstdc++-v3/include/bits/istream.tcc | 20 ++-- libstdc++-v3/include/bits/locale_facets.tcc | 12 +-- libstdc++-v3/include/bits/sbuf_iter.h | 42 ++++---- libstdc++-v3/include/bits/std_fstream.h | 3 +- libstdc++-v3/include/bits/std_streambuf.h | 15 +-- libstdc++-v3/src/ios.cc | 16 +-- libstdc++-v3/src/locale.cc | 110 +++++++++++---------- libstdc++-v3/testsuite/27_io/filebuf.cc | 3 + libstdc++-v3/testsuite/27_io/filebuf_members.cc | 2 +- .../testsuite/27_io/narrow_stream_objects.cc | 22 ++++- 12 files changed, 163 insertions(+), 162 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 6240492..13d9b06 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,22 @@ +2001-05-07 Benjamin Kosnik + + libstdc++/2523 + * include/bits/std_fstream.h (basic_filebuf): Change signature. + * include/bits/fstream.tcc (basic_filebuf): Change bool argument + to int_type, pass in buffer size info. + * include/bits/std_streambuf.h (_M_is_indeterminate): Check for + unbuffered situation. + (underflow): Remove codecvt bits for the time being. + * include/bits/istream.tcc (istream::sentry): Avoid sputbackc call. + * include/bits/locale_facets.tcc (_M_extract): Cache dereference + values from iterators, clean. + * src/locale.cc: Ditto. + * include/bits/sbuf_iter.h: Format. + * src/ios.cc: Explicitly pass in buffer sizes at creation time. + * testsuite/27_io/narrow_stream_objects.cc: Add tests. + * testsuite/27_io/filebuf.cc: Tweaks. + * testsuite/27_io/filebuf_members.cc: Tweaks. + 2001-05-07 Mark Mitchell * config/os/solaris/solaris2.7/bits/os_defines.h diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc index c1311e9..8b551ff 100644 --- a/libstdc++-v3/include/bits/fstream.tcc +++ b/libstdc++-v3/include/bits/fstream.tcc @@ -90,7 +90,7 @@ namespace std template basic_filebuf<_CharT, _Traits>:: - basic_filebuf(__c_file_type* __f, bool __s, ios_base::openmode __mode) + basic_filebuf(__c_file_type* __f, ios_base::openmode __mode, int_type __s) : __streambuf_type(), _M_file(NULL), _M_state_cur(__state_type()), _M_state_beg(__state_type()), _M_last_overflowed(false) { @@ -99,8 +99,9 @@ namespace std if (this->is_open()) { _M_mode = __mode; - if (!__s) + if (__s) { + _M_buf_size_opt = __s; _M_allocate_buffers(); _M_set_indeterminate(); } @@ -208,7 +209,9 @@ namespace std { int_type __ret = traits_type::eof(); bool __testin = _M_mode & ios_base::in; - + bool __testout = _M_mode & ios_base::out; + + // XXX Should re-enable codecvt bits disabled after 2.90.8. if (__testin) { // Check for pback madness, and if so swich back to the @@ -223,8 +226,6 @@ namespace std bool __testget = _M_in_cur && _M_in_beg < _M_in_cur; bool __testinit = _M_is_indeterminate(); - bool __testout = _M_mode & ios_base::out; - // Sync internal and external buffers. // NB: __testget -> __testput as _M_buf_unified here. if (__testget) @@ -238,7 +239,7 @@ namespace std if (__testinit || __testget) { -#if 1 + // Assume buffered case, need to refill internal buffers. streamsize __size = _M_file->xsgetn(_M_in_beg, _M_buf_size); if (0 < __size) { @@ -252,53 +253,7 @@ namespace std { // XXX Something is wrong, do error checking. } - } -#else - // 2000-08-04 bkoz disable - // Part one: (Re)fill external buf (_M_file->_IO_*) from - // external byte sequence (whatever physical byte sink or - // FILE actually is.) - char_type* __conv_buf = static_cast(__builtin_alloca(sizeof(char_type) * _M_buf_size)); - streamsize __size = _M_file->xsgetn(__conv_buf, _M_buf_size); - - // Part two: (Re)fill internal buf contents from external buf. - if (0 < __size) - { - _M_set_determinate(__size); - - char* __conv_cur = __conv_buf; - _M_state_beg = _M_state_cur; - __res_type __r = _M_fcvt->in(_M_state_cur, - __conv_buf, - __conv_buf + __size, - const_cast(__conv_cur), - _M_in_beg, _M_in_end, _M_in_cur); - - if (__r == codecvt_base::partial) - { - // XXX Retry with larger _M_buf size. - } - - // Set pointers to internal and external buffers - // correctly. . . - if (__r != codecvt_base::error) - { - if (__testout) - _M_out_cur = _M_in_cur; - __ret = traits_type::to_int_type(*_M_in_cur); - } - - // Part three: Sync the current internal buffer - // position with the (now overshot) external buffer - // position. - streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur, - ios_base::in); - if (__p == -1) - { - // XXX Something is wrong, do error checking. - } - } -#endif + } } } _M_last_overflowed = false; diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc index c13bf67..4f3ff96 100644 --- a/libstdc++-v3/include/bits/istream.tcc +++ b/libstdc++-v3/include/bits/istream.tcc @@ -44,24 +44,16 @@ namespace std { if (!__noskipws && (__in.flags() & ios_base::skipws)) { const __int_type __eof = traits_type::eof(); - __int_type __c = __int_type(0); - __streambuf_type* __sb = __in.rdbuf(); const __ctype_type* __ctype = __in._M_get_fctype_ios(); - bool __testsp = true; - bool __testeof = false; - - while (!__testeof && __testsp) - { - __c = __sb->sbumpc(); - __testeof = __c == __eof; - __testsp = __ctype->is(ctype_base::space, __c); - } + __streambuf_type* __sb = __in.rdbuf(); + __int_type __c = __sb->sgetc(); - if (!__testeof && !__testsp) - __sb->sputbackc(__c); + while (__c != __eof && __ctype->is(ctype_base::space, __c)) + __c = __sb->snextc(); + #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS //195. Should basic_istream::sentry's constructor ever set eofbit? - else + if (__c == __eof) __in.setstate(ios_base::eofbit); #endif } diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index edb3d17..482ed9f 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -189,15 +189,15 @@ namespace std switch (__ev) { case ios_base::erase_event: - delete static_cast<_Format_cache<_CharT>*> (__p); __p = 0; + delete static_cast<_Format_cache<_CharT>*>(__p); + __p = 0; break; case ios_base::copyfmt_event: // If just stored zero, the callback would get registered again. - try { - __p = new _Format_cache<_CharT>; - } - catch(...) { - } + try + { __p = new _Format_cache<_CharT>; } + catch(...) + { } break; case ios_base::imbue_event: static_cast<_Format_cache<_CharT>*>(__p)->_M_valid = false; diff --git a/libstdc++-v3/include/bits/sbuf_iter.h b/libstdc++-v3/include/bits/sbuf_iter.h index 4935c11..4d69b58 100644 --- a/libstdc++-v3/include/bits/sbuf_iter.h +++ b/libstdc++-v3/include/bits/sbuf_iter.h @@ -46,7 +46,12 @@ namespace std typedef _Traits traits_type; typedef basic_streambuf<_CharT, _Traits> streambuf_type; typedef basic_ostream<_CharT, _Traits> ostream_type; - + + private: + streambuf_type* _M_sbuf; + bool _M_failed; + + public: inline ostreambuf_iterator(ostream_type& __s) throw () : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { } @@ -72,10 +77,6 @@ namespace std bool failed() const throw() { return _M_failed; } - - private: - streambuf_type* _M_sbuf; - bool _M_failed; }; template @@ -90,13 +91,12 @@ namespace std // 24.5.3 Template class istreambuf_iterator - template + template class istreambuf_iterator : public iterator { public: - // Types: typedef _CharT char_type; typedef _Traits traits_type; @@ -106,6 +106,18 @@ namespace std // Non-standard Types: typedef istreambuf_iterator<_CharT, _Traits> __istreambufiter_type; + private: + // 24.5.3 istreambuf_iterator + // p 1 + // If the end of stream is reached (streambuf_type::sgetc() + // returns traits_type::eof()), the iterator becomes equal to + // the "end of stream" iterator value. + // NB: This implementation assumes the "end of stream" value + // is EOF, or -1. + streambuf_type* _M_sbuf; + int_type _M_c; + + public: istreambuf_iterator() throw() : _M_sbuf(NULL), _M_c(-2) { } @@ -174,17 +186,6 @@ namespace std return (__thiseof && __beof || (!__thiseof && !__beof)); } #endif - - private: - // 24.5.3 istreambuf_iterator - // p 1 - // If the end of stream is reached (streambuf_type::sgetc() - // returns traits_type::eof()), the iterator becomes equal to - // the "end of stream" iterator value. - // NB: This implementation assumes the "end of stream" value - // is EOF, or -1. - streambuf_type* _M_sbuf; - int_type _M_c; }; template @@ -198,10 +199,5 @@ namespace std operator!=(const istreambuf_iterator<_CharT, _Traits>& __a, const istreambuf_iterator<_CharT, _Traits>& __b) { return !__a.equal(__b); } - } // namespace std - #endif - - - diff --git a/libstdc++-v3/include/bits/std_fstream.h b/libstdc++-v3/include/bits/std_fstream.h index 63a86b9..479ee09 100644 --- a/libstdc++-v3/include/bits/std_fstream.h +++ b/libstdc++-v3/include/bits/std_fstream.h @@ -86,7 +86,8 @@ namespace std basic_filebuf(); // Non-standard ctor: - basic_filebuf(__c_file_type* __f, bool __s, ios_base::openmode __mode); + basic_filebuf(__c_file_type* __f, ios_base::openmode __mode, + int_type __s = static_cast(BUFSIZ)); virtual ~basic_filebuf() diff --git a/libstdc++-v3/include/bits/std_streambuf.h b/libstdc++-v3/include/bits/std_streambuf.h index 013d7e9..678c140 100644 --- a/libstdc++-v3/include/bits/std_streambuf.h +++ b/libstdc++-v3/include/bits/std_streambuf.h @@ -251,17 +251,20 @@ namespace std this->setg(_M_buf, _M_buf, _M_buf + __off); if (__testout) this->setp(_M_buf, _M_buf + __off); - } bool _M_is_indeterminate(void) { bool __ret = false; - if (_M_mode & ios_base::in) - __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end; - if (_M_mode & ios_base::out) - __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end; + // Don't return true if unbuffered. + if (_M_buf) + { + if (_M_mode & ios_base::in) + __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end; + if (_M_mode & ios_base::out) + __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end; + } return __ret; } @@ -350,7 +353,7 @@ namespace std { int_type __ret; if (_M_in_cur && _M_in_cur < _M_in_end) - __ret = traits_type::to_int_type(*gptr()); + __ret = traits_type::to_int_type(*(this->gptr())); else __ret = this->underflow(); return __ret; diff --git a/libstdc++-v3/src/ios.cc b/libstdc++-v3/src/ios.cc index de577d6..6d4039d 100644 --- a/libstdc++-v3/src/ios.cc +++ b/libstdc++-v3/src/ios.cc @@ -136,19 +136,21 @@ namespace std void ios_base::Init::_S_ios_create(bool __sync) { + int __bufsize = __sync ? 0 : static_cast(BUFSIZ); // NB: The file std_iostream.h creates the four standard files - // with NULL buffers. At this point, we swap out these - new (&cout) ostream(new filebuf(stdout, __sync, ios_base::out)); - new (&cin) istream(new filebuf(stdin, __sync, ios_base::in)); - new (&cerr) ostream(new filebuf(stderr, __sync, ios_base::out)); + // with NULL buffers. At this point, we swap out the dummy NULL + // buffers with the real deal. + new (&cout) ostream(new filebuf(stdout, ios_base::out, __bufsize)); + new (&cin) istream(new filebuf(stdin, ios_base::in, 1)); + new (&cerr) ostream(new filebuf(stderr, ios_base::out, __bufsize)); new (&clog) ostream(cerr.rdbuf()); cin.tie(&cout); cerr.flags(ios_base::unitbuf); #ifdef _GLIBCPP_USE_WCHAR_T - new (&wcout) wostream( new wfilebuf(stdout, __sync, ios_base::out)); - new (&wcin) wistream(new wfilebuf(stdin, __sync, ios_base::in)); - new (&wcerr) wostream(new wfilebuf(stderr, __sync, ios_base::out)); + new (&wcout) wostream( new wfilebuf(stdout, ios_base::out, __bufsize)); + new (&wcin) wistream(new wfilebuf(stdin, ios_base::in, 1)); + new (&wcerr) wostream(new wfilebuf(stderr, ios_base::out, __bufsize)); new (&wclog) wostream(wcerr.rdbuf()); wcin.tie(&wcout); wcerr.flags(ios_base::unitbuf); diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc index 3b43090..26bbc56 100644 --- a/libstdc++-v3/src/locale.cc +++ b/libstdc++-v3/src/locale.cc @@ -676,9 +676,9 @@ namespace std // Stage 2: extract characters. __cache_type const* __fmt = __cache_type::_S_get(__io); - bool __valid = __beg != __end; + // Fail quickly if !__valid - if (!__valid) + if (__beg == __end) { __err |= (ios_base::eofbit | ios_base::failbit); return; @@ -694,14 +694,19 @@ namespace std // Check first for sign bool __testsign = false; if ((__c == __lits[__cache_type::_S_minus]) - || (__c == __lits[__cache_type::_S_plus])) + || (__c == __lits[__cache_type::_S_plus])) { + __testsign = true; __xtrc[__pos++] = __c; ++__beg; - __testsign = true; - // whitespace may follow a sign - while ((__beg != __end) && (isspace(*__beg))) - ++__beg; + __c = * __beg; + + // Whitespace may follow a sign + while ((__beg != __end) && (isspace(__c))) + { + ++__beg; + __c = *__beg; + } // There had better be more to come... if (__beg == __end) @@ -712,20 +717,19 @@ namespace std } } - bool __testzero = false; // Has there been a leading zero? - - // Now check if first character is a zero - __c = *__beg; + // Now check if first character is a zero. + bool __testzero = false; if (__c == __lits[__cache_type::_S_digits]) { __testzero = true; ++__beg; + __c = *__beg; // We have to check for __beg == __end here. If so, // a plain '0' (possibly with a sign) can be got rid of now if (__beg == __end) { - __xtrc[__pos++] = __c; + __xtrc[__pos++] = __lits[__cache_type::_S_digits]; __xtrc[__pos] = '\0'; __err |= ios_base::eofbit; return; @@ -736,11 +740,11 @@ namespace std if (!__fp && __base != 10 && __base != 8) { // Here, __base == 0 or 16 - __c = *__beg; if ((__c == __lits[__cache_type::_S_x]) || (__c == __lits[__cache_type::_S_X])) { ++__beg; + __c = *__beg; __base = 16; __testzero = false; // "0x" is not a leading zero } @@ -751,9 +755,10 @@ namespace std // Remove any more leading zeros while (__beg != __end) { - if (*__beg == __lits[__cache_type::_S_digits]) + if (__c == __lits[__cache_type::_S_digits]) { ++__beg; + __c = *__beg; __testzero = true; } else @@ -767,44 +772,45 @@ namespace std // We may need to know if anything is found here. A leading zero // (removed by now) would count. bool __testunits = __testzero; - while (__valid && __beg != __end) + while (__beg != __end) { - __valid = false; - __c = *__beg; - const char* __p = strchr(__fmt->_S_literals, __c); + const char* __p = strchr(__lits, __c); // NB: strchr returns true for __c == 0x0 - if (__p && __c) - { - // Try first for acceptable digit; record it if found - if ((__p >= &__lits[__cache_type::_S_digits] - && __p < &__lits[__cache_type::_S_digits + __base]) - || (__p >= &__lits[__cache_type::_S_udigits] - && __p < &__lits[__cache_type::_S_udigits + __base])) - { - __xtrc[__pos++] = __c; - ++__sep_pos; - __valid = true; - __testunits = true; - } - } - else if (__c == __fmt->_M_thousands_sep - && __fmt->_M_use_grouping) - { + if (__p && __c + &&((__p >= &__lits[__cache_type::_S_digits] + && __p < &__lits[__cache_type::_S_digits + __base]) + || (__p >= &__lits[__cache_type::_S_udigits] + && __p < &__lits[__cache_type::_S_udigits + __base]))) + { + // Try first for acceptable digit; record it if found. + __xtrc[__pos++] = __c; + ++__sep_pos; + __testunits = true; + ++__beg; + __c = *__beg; + } + else if (__c == __fmt->_M_thousands_sep && __fmt->_M_use_grouping) + { // NB: Thousands separator at the beginning of a string // is a no-no, as is two consecutive thousands - // separators + // separators. if (__sep_pos) { __grp += static_cast(__sep_pos); __sep_pos = 0; - __valid = true; + ++__beg; + __c = *__beg; } else - __err |= ios_base::failbit; + { + __err |= ios_base::failbit; + break; + } } - if (__valid) - ++__beg; + else + // Not a valid input item. + break; } // Digit grouping is checked. If _M_groupings() doesn't @@ -852,7 +858,6 @@ namespace std // That's it for integer types. Remaining code is for floating point if (__fp && __beg != __end) { - __c = *__beg; // Check first for decimal point. There MUST be one if // __testunits is false. bool __testdec = false; // Is there a decimal point @@ -861,12 +866,13 @@ namespace std { __xtrc[__pos++] = '.'; ++__beg; + __c = *__beg; + // Now we get any digits after the decimal point // There MUST be some if __testunits is false. while (__beg != __end) { - __c = *__beg; - const char* __p = strchr(__fmt->_S_literals, __c); + const char* __p = strchr(__lits, __c); if ((__p >= &__lits[__cache_type::_S_digits] && __p < &__lits[__cache_type::_S_digits + __base]) || (__p >= &__lits[__cache_type::_S_udigits] @@ -874,6 +880,7 @@ namespace std { __xtrc[__pos++] = __c; ++__beg; + __c = *__beg; __testdec = true; } else @@ -892,25 +899,28 @@ namespace std // Now we may find an exponent if (__beg != __end) { - __c = *__beg; if ((__c == __lits[__cache_type::_S_ee]) || (__c == __lits[__cache_type::_S_Ee])) { __xtrc[__pos++] = __c; ++__beg; + __c = *__beg; + // Now there may be a sign if (__beg != __end) { - __c = *__beg; if ((__c == __lits[__cache_type::_S_minus]) || (__c == __lits[__cache_type::_S_plus])) { __xtrc[__pos++] = __c; ++__beg; + __c = *__beg; // whitespace may follow a sign - while ((__beg != __end) && (isspace(*__beg))) - ++__beg; - + while ((__beg != __end) && (isspace(__c))) + { + ++__beg; + __c = *__beg; + } } } // And now there must be some digits @@ -922,8 +932,7 @@ namespace std } while (__beg != __end) { - __c = *__beg; - const char* __p = strchr(__fmt->_S_literals, __c); + const char* __p = strchr(__lits, __c); if ((__p >= &__lits[__cache_type::_S_digits] && __p < &__lits[__cache_type::_S_digits + __base]) || (__p >= &__lits[__cache_type::_S_udigits] @@ -931,6 +940,7 @@ namespace std { __xtrc[__pos++] = __c; ++__beg; + __c = *__beg; } else break; diff --git a/libstdc++-v3/testsuite/27_io/filebuf.cc b/libstdc++-v3/testsuite/27_io/filebuf.cc index c59c291..d31614c 100644 --- a/libstdc++-v3/testsuite/27_io/filebuf.cc +++ b/libstdc++-v3/testsuite/27_io/filebuf.cc @@ -546,6 +546,9 @@ public: operator<(const gnu_char_type& __lhs) { return character < __lhs.character; } + // default ctor + gnu_char_type() { } + // to_char_type gnu_char_type(const unsigned long& __l) : character(__l) { } diff --git a/libstdc++-v3/testsuite/27_io/filebuf_members.cc b/libstdc++-v3/testsuite/27_io/filebuf_members.cc index 3eda6f5..2e21232 100644 --- a/libstdc++-v3/testsuite/27_io/filebuf_members.cc +++ b/libstdc++-v3/testsuite/27_io/filebuf_members.cc @@ -52,7 +52,7 @@ test_01() FILE* f2 = fopen(name_01, "r"); VERIFY( f2 != NULL ); { - std::filebuf fb(f2, false, std::ios_base::in); + std::filebuf fb(f2, std::ios_base::in, 512); } close_num = fclose(f2); VERIFY( close_num == 0 ); diff --git a/libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc b/libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc index 3fbe3dd..c1ca3ca 100644 --- a/libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc +++ b/libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc @@ -1,6 +1,6 @@ // 2000-08-02 bkoz -// Copyright (C) 2000 Free Software Foundation, Inc. +// Copyright (C) 2000, 2001 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -93,11 +93,31 @@ test01() return 0; } +// libstdc++/2523 +void test02() +{ + int i; + cin >> i; + cout << "i == " << i << endl; +} + +// libstdc++/2523 +void test03() +{ + ios_base::sync_with_stdio(false); + + int i; + cin >> i; + cout << "i == " << i << endl; +} int main() { test01(); + + // test02(); + // test03(); return 0; } -- 2.7.4