From 0cd1de6fc967a1683bb5ec34462bf6d3ef39cdc8 Mon Sep 17 00:00:00 2001 From: Benjamin Kosnik Date: Tue, 13 May 2003 20:13:15 +0000 Subject: [PATCH] std_fstream.h (basic_filebuf::_M_codecvt): Add cached member. 2003-05-12 Benjamin Kosnik * include/std/std_fstream.h (basic_filebuf::_M_codecvt): Add cached member. * include/bits/fstream.tcc (basic_filebuf::basic_filebuf): Initialize _M_codecvt. (basic_filebuf::imbue): Same. (basic_filebuf::showmanyc): Use it. (basic_filebuf::underflow): Use it. (basic_filebuf::_M_convert_to_external): Use it. (basic_filebuf::seekoff): Use it. (basic_filebuf::imbue): Use it, tweaks. * include/bits/localefwd.h (__check_facet): New. * include/bits/locale_classes.h: Tweaks. * include/bits/locale_facets.tcc: Tweaks. * include/bits/basic_ios.h (basic_ios::_M_check_facet): Remove. _M_fctype to _M_ctype, _M_fnumput to _M_num_put, _M_fnumget to _M_num_get. Change _M_check_facet to __check_facet. Tweaks. * include/bits/basic_ios.tcc: Same. * include/bits/istream.tcc: Same. * include/bits/ostream.tcc: Same. * include/std/std_streambuf.h: Same. * testsuite/27_io/basic_filebuf/imbue/char/2.cc: New. * testsuite/27_io/basic_filebuf/imbue/char/3.cc: New. * testsuite/27_io/basic_filebuf/imbue/wchar_t/1.cc: New. * testsuite/27_io/basic_filebuf/imbue/wchar_t/2.cc: New. * testsuite/27_io/basic_filebuf/imbue/wchar_t/3.cc: New. * testsuite/27_io/basic_filebuf/imbue/wchar_t/9322.cc: New. From-SVN: r66781 --- libstdc++-v3/ChangeLog | 29 ++++++ libstdc++-v3/include/bits/basic_ios.h | 18 +--- libstdc++-v3/include/bits/basic_ios.tcc | 20 +--- libstdc++-v3/include/bits/fstream.tcc | 88 ++++++++--------- libstdc++-v3/include/bits/istream.tcc | 47 ++++------ libstdc++-v3/include/bits/locale_classes.h | 10 +- libstdc++-v3/include/bits/locale_facets.tcc | 16 ++-- libstdc++-v3/include/bits/localefwd.h | 13 ++- libstdc++-v3/include/bits/ostream.tcc | 94 +++++++++---------- libstdc++-v3/include/std/std_fstream.h | 4 +- libstdc++-v3/include/std/std_streambuf.h | 11 ++- .../27_io/basic_filebuf/imbue/char/2.cc | 54 +++++++++++ .../27_io/basic_filebuf/imbue/char/3.cc | 55 +++++++++++ .../27_io/basic_filebuf/imbue/wchar_t/1.cc | 45 +++++++++ .../27_io/basic_filebuf/imbue/wchar_t/2.cc | 54 +++++++++++ .../27_io/basic_filebuf/imbue/wchar_t/3.cc | 55 +++++++++++ .../27_io/basic_filebuf/imbue/wchar_t/9322.cc | 53 +++++++++++ 17 files changed, 494 insertions(+), 172 deletions(-) create mode 100644 libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/2.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/3.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/1.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/2.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/3.cc create mode 100644 libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/9322.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 9ea0c9f2a29..c7273a27e39 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,32 @@ +2003-05-12 Benjamin Kosnik + + * include/std/std_fstream.h (basic_filebuf::_M_codecvt): Add + cached member. + * include/bits/fstream.tcc (basic_filebuf::basic_filebuf): + Initialize _M_codecvt. + (basic_filebuf::imbue): Same. + (basic_filebuf::showmanyc): Use it. + (basic_filebuf::underflow): Use it. + (basic_filebuf::_M_convert_to_external): Use it. + (basic_filebuf::seekoff): Use it. + (basic_filebuf::imbue): Use it, tweaks. + * include/bits/localefwd.h (__check_facet): New. + * include/bits/locale_classes.h: Tweaks. + * include/bits/locale_facets.tcc: Tweaks. + * include/bits/basic_ios.h (basic_ios::_M_check_facet): Remove. + _M_fctype to _M_ctype, _M_fnumput to _M_num_put, _M_fnumget to + _M_num_get. Change _M_check_facet to __check_facet. Tweaks. + * include/bits/basic_ios.tcc: Same. + * include/bits/istream.tcc: Same. + * include/bits/ostream.tcc: Same. + * include/std/std_streambuf.h: Same. + * testsuite/27_io/basic_filebuf/imbue/char/2.cc: New. + * testsuite/27_io/basic_filebuf/imbue/char/3.cc: New. + * testsuite/27_io/basic_filebuf/imbue/wchar_t/1.cc: New. + * testsuite/27_io/basic_filebuf/imbue/wchar_t/2.cc: New. + * testsuite/27_io/basic_filebuf/imbue/wchar_t/3.cc: New. + * testsuite/27_io/basic_filebuf/imbue/wchar_t/9322.cc: New. + 2003-05-12 Paolo Carlini * testsuite/27_io/basic_filebuf/sgetc/char/1.cc: Remove diff --git a/libstdc++-v3/include/bits/basic_ios.h b/libstdc++-v3/include/bits/basic_ios.h index 5be11a2590d..98b73cadd7c 100644 --- a/libstdc++-v3/include/bits/basic_ios.h +++ b/libstdc++-v3/include/bits/basic_ios.h @@ -90,11 +90,11 @@ namespace std basic_streambuf<_CharT, _Traits>* _M_streambuf; // Cached use_facet, which is based on the current locale info. - const __ctype_type* _M_fctype; + const __ctype_type* _M_ctype; // For ostream. - const __numput_type* _M_fnumput; + const __numput_type* _M_num_put; // For istream. - const __numget_type* _M_fnumget; + const __numget_type* _M_num_get; public: //@{ @@ -241,7 +241,7 @@ namespace std */ explicit basic_ios(basic_streambuf<_CharT, _Traits>* __sb) - : ios_base(), _M_fctype(0), _M_fnumput(0), _M_fnumget(0) + : ios_base(), _M_ctype(0), _M_num_put(0), _M_num_get(0) { this->init(__sb); } /** @@ -419,7 +419,7 @@ namespace std * The default constructor does nothing and is not normally * accessible to users. */ - basic_ios() : ios_base(), _M_fctype(0), _M_fnumput(0), _M_fnumget(0) + basic_ios() : ios_base(), _M_ctype(0), _M_num_put(0), _M_num_get(0) { } /** @@ -431,14 +431,6 @@ namespace std void init(basic_streambuf<_CharT, _Traits>* __sb); - bool - _M_check_facet(const locale::facet* __f) const - { - if (!__f) - __throw_bad_cast(); - return true; - } - void _M_cache_locale(const locale& __loc); diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc index 0c1e7357098..cf2701effb2 100644 --- a/libstdc++-v3/include/bits/basic_ios.tcc +++ b/libstdc++-v3/include/bits/basic_ios.tcc @@ -110,22 +110,12 @@ namespace std template char basic_ios<_CharT, _Traits>::narrow(char_type __c, char __dfault) const - { - char __ret = __dfault; - if (_M_check_facet(_M_fctype)) - __ret = _M_fctype->narrow(__c, __dfault); - return __ret; - } + { return __check_facet(_M_ctype).narrow(__c, __dfault); } template _CharT basic_ios<_CharT, _Traits>::widen(char __c) const - { - char_type __ret = char_type(); - if (_M_check_facet(_M_fctype)) - __ret = _M_fctype->widen(__c); - return __ret; - } + { return __check_facet(_M_ctype).widen(__c); } // Locales: template @@ -181,11 +171,11 @@ namespace std basic_ios<_CharT, _Traits>::_M_cache_locale(const locale& __loc) { if (__builtin_expect(has_facet<__ctype_type>(__loc), true)) - _M_fctype = &use_facet<__ctype_type>(__loc); + _M_ctype = &use_facet<__ctype_type>(__loc); if (__builtin_expect(has_facet<__numput_type>(__loc), true)) - _M_fnumput = &use_facet<__numput_type>(__loc); + _M_num_put = &use_facet<__numput_type>(__loc); if (__builtin_expect(has_facet<__numget_type>(__loc), true)) - _M_fnumget = &use_facet<__numget_type>(__loc); + _M_num_get = &use_facet<__numget_type>(__loc); static_cast<__locale_cache<_CharT>&>(_M_cache())._M_init(__loc); } diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc index 40d1ece324a..3397071bd84 100644 --- a/libstdc++-v3/include/bits/fstream.tcc +++ b/libstdc++-v3/include/bits/fstream.tcc @@ -78,8 +78,13 @@ namespace std _M_state_cur(__state_type()), _M_state_beg(__state_type()), _M_buf(NULL), _M_buf_size(BUFSIZ), _M_buf_allocated(false), _M_last_overflowed(false), _M_pback_cur_save(0), - _M_pback_end_save(0), _M_pback_init(false) - { this->_M_buf_unified = true; } + _M_pback_end_save(0), _M_pback_init(false), _M_codecvt(0) + { + this->_M_buf_unified = true; + if (__builtin_expect(has_facet<__codecvt_type>(this->_M_buf_locale), + true)) + _M_codecvt = &use_facet<__codecvt_type>(this->_M_buf_locale); + } template typename basic_filebuf<_CharT, _Traits>::__filebuf_type* @@ -163,17 +168,14 @@ namespace std { streamsize __ret = -1; const bool __testin = this->_M_mode & ios_base::in; - const locale __loc = this->getloc(); - const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc); if (__testin && this->is_open()) { - __ret = this->_M_in_end - this->_M_in_cur; - // For a stateful encoding (-1) the pending sequence might be just // shift and unshift prefixes with no actual character. - if (__cvt.encoding() >= 0) - __ret += _M_file.showmanyc() / __cvt.max_length(); + __ret = this->_M_in_end - this->_M_in_cur; + if (__check_facet(_M_codecvt).encoding() >= 0) + __ret += _M_file.showmanyc() / _M_codecvt->max_length(); } _M_last_overflowed = false; @@ -220,9 +222,8 @@ namespace std { streamsize __elen = 0; streamsize __ilen = 0; - const locale __loc = this->getloc(); - const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc); - if (__cvt.always_noconv()) + + if (__check_facet(_M_codecvt).always_noconv()) { __elen = _M_file.xsgetn(reinterpret_cast(this->_M_in_beg), _M_buf_size); __ilen = __elen; @@ -235,9 +236,9 @@ namespace std const char* __eend; char_type* __iend; codecvt_base::result __r; - __r = __cvt.in(_M_state_cur, __buf, __buf + __elen, __eend, - this->_M_in_beg, - this->_M_in_beg + _M_buf_size, __iend); + __r = _M_codecvt->in(_M_state_cur, __buf, __buf + __elen, + __eend, this->_M_in_beg, + this->_M_in_beg + _M_buf_size, __iend); if (__r == codecvt_base::ok) __ilen = __iend - this->_M_in_beg; else if (__r == codecvt_base::noconv) @@ -400,7 +401,6 @@ namespace std else __ret = this->_M_overflow(__c); } - _M_last_overflowed = false; // Set in _M_overflow, below. return __ret; } @@ -414,9 +414,7 @@ namespace std streamsize __elen = 0; streamsize __plen = 0; - const locale __loc = this->getloc(); - const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc); - if (__cvt.always_noconv() && __ilen) + if (__check_facet(_M_codecvt).always_noconv() && __ilen) { __elen += _M_file.xsputn(reinterpret_cast(__ibuf), __ilen); __plen += __ilen; @@ -424,7 +422,7 @@ namespace std else { // Worst-case number of external bytes needed. - int __ext_multiplier = __cvt.encoding(); + int __ext_multiplier = _M_codecvt->encoding(); if (__ext_multiplier == -1 || __ext_multiplier == 0) __ext_multiplier = sizeof(char_type); streamsize __blen = __ilen * __ext_multiplier; @@ -432,8 +430,8 @@ namespace std char* __bend; const char_type* __iend; codecvt_base::result __r; - __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen, - __iend, __buf, __buf + __blen, __bend); + __r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen, + __iend, __buf, __buf + __blen, __bend); if (__r == codecvt_base::ok || __r == codecvt_base::partial) __blen = __bend - __buf; @@ -460,8 +458,9 @@ namespace std { const char_type* __iresume = __iend; streamsize __rlen = this->_M_out_lim - __iend; - __r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen, - __iend, __buf, __buf + __blen, __bend); + __r = _M_codecvt->out(_M_state_cur, __iresume, + __iresume + __rlen, __iend, __buf, + __buf + __blen, __bend); if (__r != codecvt_base::error) { __rlen = __bend - __buf; @@ -470,7 +469,6 @@ namespace std } } } - return __elen && __elen == __plen; } @@ -510,8 +508,8 @@ namespace std const bool __testout = (ios_base::out & this->_M_mode & __mode) != 0; int __width = 0; - if (has_facet<__codecvt_type>(this->_M_buf_locale)) - __width = use_facet<__codecvt_type>(this->_M_buf_locale).encoding(); + if (_M_codecvt) + __width = _M_codecvt->encoding(); if (__width < 0) __width = 0; @@ -523,20 +521,19 @@ namespace std if (__way != ios_base::cur || __off != 0) { - off_type __computed_off = __width * __off; - + // Sync the internal and external streams. const bool __testget = this->_M_in_beg < this->_M_in_end; const bool __testput = this->_M_out_beg < this->_M_out_lim; - // Sync the internal and external streams. - // out + off_type __computed_off = __width * __off; + if (__testput || _M_last_overflowed) { // Part one: update the output sequence. this->sync(); + // Part two: output unshift sequence. _M_output_unshift(); } - //in else if (__testget && __way == ios_base::cur) __computed_off += this->_M_in_cur - _M_filepos; @@ -544,10 +541,10 @@ namespace std __ret = _M_file.seekoff(__computed_off, __way, __mode); _M_set_indeterminate(); } - // NB: Need to do this in case _M_file in indeterminate - // state, ie _M_file._offset == -1 else { + // NB: Need to do this in case _M_file in indeterminate + // state, ie _M_file._offset == -1 pos_type __tmp = _M_file.seekoff(__off, ios_base::cur, __mode); if (__tmp >= 0) { @@ -584,16 +581,23 @@ namespace std basic_filebuf<_CharT, _Traits>:: imbue(const locale& __loc) { - const bool __testbeg = this->_M_in_cur == this->_M_in_beg - && this->_M_out_cur == this->_M_out_beg; + const bool __testbeg = !this->seekoff(0, ios_base::cur, this->_M_mode); + const bool __teststate = __check_facet(_M_codecvt).encoding() == -1; - if (__testbeg && this->_M_buf_locale != __loc) - this->_M_buf_locale = __loc; - - // NB this may require the reconversion of previously - // converted chars. This in turn may cause the reconstruction - // of the original file. YIKES!! - // XXX The part in the above comment is not done. + if (this->_M_buf_locale != __loc + && (!this->is_open() || (__testbeg && !__teststate))) + { + this->_M_buf_locale = __loc; + if (__builtin_expect(has_facet<__codecvt_type>(__loc), true)) + _M_codecvt = &use_facet<__codecvt_type>(__loc); + + // NB This may require the reconversion of previously + // converted chars. This in turn may cause the + // reconstruction of the original file. YIKES!! This + // implementation interprets this requirement as requiring + // the file position be at the beginning, and a stateless + // encoding, or that the filebuf be closed. Opinions may differ. + } _M_last_overflowed = false; } diff --git a/libstdc++-v3/include/bits/istream.tcc b/libstdc++-v3/include/bits/istream.tcc index cc83f81a923..a9448b09c09 100644 --- a/libstdc++-v3/include/bits/istream.tcc +++ b/libstdc++-v3/include/bits/istream.tcc @@ -53,10 +53,10 @@ namespace std __streambuf_type* __sb = __in.rdbuf(); __int_type __c = __sb->sgetc(); - if (__in._M_check_facet(__in._M_fctype)) - while (!traits_type::eq_int_type(__c, __eof) - && __in._M_fctype->is(ctype_base::space, - traits_type::to_char_type(__c))) + __check_facet(__in._M_ctype); + while (!traits_type::eq_int_type(__c, __eof) + && __in._M_ctype->is(ctype_base::space, + traits_type::to_char_type(__c))) __c = __sb->snextc(); #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS @@ -114,8 +114,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) @@ -142,8 +141,7 @@ namespace std { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); long __l; - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __l); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __l); #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS // 118. basic_istream uses nonexistent num_get member functions. if (!(__err & ios_base::failbit) @@ -178,8 +176,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) @@ -206,8 +203,7 @@ namespace std { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); long __l; - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __l); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __l); #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS // 118. basic_istream uses nonexistent num_get member functions. if (!(__err & ios_base::failbit) @@ -242,8 +238,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) @@ -269,8 +264,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) @@ -296,8 +290,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) @@ -324,8 +317,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) @@ -351,8 +343,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) @@ -379,8 +370,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) @@ -406,8 +396,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) @@ -433,8 +422,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) @@ -460,8 +448,7 @@ namespace std try { ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); - if (_M_check_facet(this->_M_fnumget)) - this->_M_fnumget->get(*this, 0, *this, __err, __n); + __check_facet(this->_M_num_get).get(*this, 0, *this, __err, __n); this->setstate(__err); } catch(...) diff --git a/libstdc++-v3/include/bits/locale_classes.h b/libstdc++-v3/include/bits/locale_classes.h index 7c447e878f6..e7210f821fe 100644 --- a/libstdc++-v3/include/bits/locale_classes.h +++ b/libstdc++-v3/include/bits/locale_classes.h @@ -64,14 +64,14 @@ namespace std friend class facet; friend class _Impl; - template - friend const _Facet& - use_facet(const locale&); - template friend bool has_facet(const locale&) throw(); - + + template + friend const _Facet& + use_facet(const locale&); + // Category values: // NB: Order must match _S_facet_categories definition in locale.cc static const category none = 0; diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 6e09e407104..f44531799f0 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -67,23 +67,23 @@ namespace std } template - const _Facet& - use_facet(const locale& __loc) + inline bool + has_facet(const locale& __loc) throw() { size_t __i = _Facet::id._M_id(); const locale::facet** __facets = __loc._M_impl->_M_facets; - if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) - __throw_bad_cast(); - return static_cast(*__facets[__i]); + return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); } template - bool - has_facet(const locale& __loc) throw() + inline const _Facet& + use_facet(const locale& __loc) { size_t __i = _Facet::id._M_id(); const locale::facet** __facets = __loc._M_impl->_M_facets; - return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); + if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) + __throw_bad_cast(); + return static_cast(*__facets[__i]); } diff --git a/libstdc++-v3/include/bits/localefwd.h b/libstdc++-v3/include/bits/localefwd.h index ac9e1a95425..16fa8821e9a 100644 --- a/libstdc++-v3/include/bits/localefwd.h +++ b/libstdc++-v3/include/bits/localefwd.h @@ -171,13 +171,22 @@ namespace std template class messages_byname; + template + bool + has_facet(const locale& __loc) throw(); + template const _Facet& use_facet(const locale& __loc); template - bool - has_facet(const locale& __loc) throw(); + inline const _Facet& + __check_facet(const _Facet* __f) + { + if (!__f) + __throw_bad_cast(); + return *__f; + } } // namespace std #endif diff --git a/libstdc++-v3/include/bits/ostream.tcc b/libstdc++-v3/include/bits/ostream.tcc index fc7d08a1b6e..620458806a1 100644 --- a/libstdc++-v3/include/bits/ostream.tcc +++ b/libstdc++-v3/include/bits/ostream.tcc @@ -157,10 +157,10 @@ namespace std { try { - if (_M_check_facet(this->_M_fnumput)) - if (this->_M_fnumput->put(*this, *this, - this->fill(), __n).failed()) - this->setstate(ios_base::badbit); + __check_facet(this->_M_num_put); + if (this->_M_num_put->put(*this, *this, this->fill(), + __n).failed()) + this->setstate(ios_base::badbit); } catch(...) { @@ -183,23 +183,19 @@ namespace std { try { + bool __b = false; char_type __c = this->fill(); ios_base::fmtflags __fmt = this->flags() & ios_base::basefield; - if (_M_check_facet(this->_M_fnumput)) + __check_facet(this->_M_num_put); + if ((__fmt & ios_base::oct) || (__fmt & ios_base::hex)) { - bool __b = false; - if ((__fmt & ios_base::oct) || (__fmt & ios_base::hex)) - { - unsigned long __l = static_cast(__n); - __b = this->_M_fnumput->put(*this, *this, - __c, __l).failed(); - } - else - __b = this->_M_fnumput->put(*this, *this, - __c, __n).failed(); - if (__b) - this->setstate(ios_base::badbit); + unsigned long __l = static_cast(__n); + __b = this->_M_num_put->put(*this, *this, __c, __l).failed(); } + else + __b = this->_M_num_put->put(*this, *this, __c, __n).failed(); + if (__b) + this->setstate(ios_base::badbit); } catch(...) { @@ -222,10 +218,10 @@ namespace std { try { - if (_M_check_facet(this->_M_fnumput)) - if (this->_M_fnumput->put(*this, *this, - this->fill(), __n).failed()) - this->setstate(ios_base::badbit); + __check_facet(this->_M_num_put); + if (this->_M_num_put->put(*this, *this, this->fill(), + __n).failed()) + this->setstate(ios_base::badbit); } catch(...) { @@ -249,24 +245,20 @@ namespace std { try { + bool __b = false; char_type __c = this->fill(); ios_base::fmtflags __fmt = this->flags() & ios_base::basefield; - if (_M_check_facet(this->_M_fnumput)) + __check_facet(this->_M_num_put); + if ((__fmt & ios_base::oct) || (__fmt & ios_base::hex)) { - bool __b = false; - if ((__fmt & ios_base::oct) || (__fmt & ios_base::hex)) - { - unsigned long long __l; - __l = static_cast(__n); - __b = this->_M_fnumput->put(*this, *this, - __c, __l).failed(); - } - else - __b = this->_M_fnumput->put(*this, *this, - __c, __n).failed(); - if (__b) - this->setstate(ios_base::badbit); + unsigned long long __l; + __l = static_cast(__n); + __b = this->_M_num_put->put(*this, *this, __c, __l).failed(); } + else + __b = this->_M_num_put->put(*this, *this, __c, __n).failed(); + if (__b) + this->setstate(ios_base::badbit); } catch(...) { @@ -289,10 +281,10 @@ namespace std { try { - if (_M_check_facet(this->_M_fnumput)) - if (this->_M_fnumput->put(*this, *this, - this->fill(), __n).failed()) - this->setstate(ios_base::badbit); + __check_facet(this->_M_num_put); + if (this->_M_num_put->put(*this, *this, this->fill(), + __n).failed()) + this->setstate(ios_base::badbit); } catch(...) { @@ -316,10 +308,10 @@ namespace std { try { - if (_M_check_facet(this->_M_fnumput)) - if (this->_M_fnumput->put(*this, *this, - this->fill(), __n).failed()) - this->setstate(ios_base::badbit); + __check_facet(this->_M_num_put); + if (this->_M_num_put->put(*this, *this, this->fill(), + __n).failed()) + this->setstate(ios_base::badbit); } catch(...) { @@ -342,10 +334,10 @@ namespace std { try { - if (_M_check_facet(this->_M_fnumput)) - if (this->_M_fnumput->put(*this, *this, - this->fill(), __n).failed()) - this->setstate(ios_base::badbit); + __check_facet(this->_M_num_put); + if (this->_M_num_put->put(*this, *this, this->fill(), + __n).failed()) + this->setstate(ios_base::badbit); } catch(...) { @@ -368,10 +360,10 @@ namespace std { try { - if (_M_check_facet(this->_M_fnumput)) - if (this->_M_fnumput->put(*this, *this, - this->fill(), __n).failed()) - this->setstate(ios_base::badbit); + __check_facet(this->_M_num_put); + if (this->_M_num_put->put(*this, *this, this->fill(), + __n).failed()) + this->setstate(ios_base::badbit); } catch(...) { diff --git a/libstdc++-v3/include/std/std_fstream.h b/libstdc++-v3/include/std/std_fstream.h index 0781f0d5294..2ff4ec15d10 100644 --- a/libstdc++-v3/include/std/std_fstream.h +++ b/libstdc++-v3/include/std/std_fstream.h @@ -163,6 +163,9 @@ namespace std bool _M_pback_init; //@} + // Cached codecvt facet. + const __codecvt_type* _M_codecvt; + // Initializes pback buffers, and moves normal buffers to safety. // Assumptions: // _M_in_cur has already been moved back @@ -403,7 +406,6 @@ namespace std } else _M_file.sync(); - _M_last_overflowed = false; return __ret; } diff --git a/libstdc++-v3/include/std/std_streambuf.h b/libstdc++-v3/include/std/std_streambuf.h index 946e9bc600c..e258501c18b 100644 --- a/libstdc++-v3/include/std/std_streambuf.h +++ b/libstdc++-v3/include/std/std_streambuf.h @@ -343,9 +343,10 @@ namespace std int_type snextc() { - int_type __eof = traits_type::eof(); - return (traits_type::eq_int_type(this->sbumpc(), __eof) - ? __eof : this->sgetc()); + int_type __ret = traits_type::eof(); + if (!traits_type::eq_int_type(this->sbumpc(), __ret)) + __ret = this->sgetc(); + return __ret; } /** @@ -699,8 +700,8 @@ namespace std uflow() { int_type __ret = traits_type::eof(); - const bool __testeof = - traits_type::eq_int_type(this->underflow(), __ret); + const bool __testeof = traits_type::eq_int_type(this->underflow(), + __ret); if (!__testeof && _M_in_cur < _M_in_end) { __ret = traits_type::to_int_type(*_M_in_cur); diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/2.cc new file mode 100644 index 00000000000..de6e1339a0e --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/2.cc @@ -0,0 +1,54 @@ +// 2003-05-13 Benjamin Kosnik + +// Copyright (C) 2003 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 27.8.1.4 Overridden virtual functions + +#include +#include +#include + +void test02() +{ + using namespace std; + bool test = true; + const char name_01[] = "filebuf_virtuals-1.txt"; // file with data in it + + locale loc; + filebuf ob; + VERIFY( ob.getloc() == loc ); + ob.open(name_01, ios_base::in); + VERIFY( ob.is_open() ); + + typedef streambuf::pos_type pos_type; + pos_type bad = pos_type(streambuf::off_type(-1)); + pos_type p = ob.pubseekoff(2, ios_base::beg, ios_base::in); + VERIFY( p != bad); + + // 1 "if file is not positioned at its beginning" fails... + locale loc_de = __gnu_cxx_test::try_named_locale("de_DE"); + locale ret = ob.pubimbue(loc_de); + VERIFY( ob.getloc() == loc ); +} + +main() +{ + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/3.cc new file mode 100644 index 00000000000..1899278d415 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/3.cc @@ -0,0 +1,55 @@ +// 2003-05-13 Benjamin Kosnik + +// Copyright (C) 2003 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 27.8.1.4 Overridden virtual functions + +#include +#include +#include + +class state_codecvt : public std::codecvt +{ +protected: + int + do_encoding() const throw() + { return -1; } +}; + +void test03() +{ + using namespace std; + bool test = true; + + locale loc_s(locale::classic(), new state_codecvt); + filebuf ob; + ob.pubimbue(loc_s); + VERIFY( ob.getloc() == loc_s ); + + // 2 "if encoding of current locale is state dependent" fails... + locale loc_c = locale::classic(); + locale ret = ob.pubimbue(loc_s); + VERIFY( ob.getloc() == loc_s ); +} + +main() +{ + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/1.cc new file mode 100644 index 00000000000..621799e513f --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/1.cc @@ -0,0 +1,45 @@ +// 981208 bkoz test functionality of basic_stringbuf for char_type == char + +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 +// 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +#include +#include + +std::wfilebuf fbuf; + +// test the filebuf locale settings +void test02() +{ + std::locale loc_c = std::locale::classic(); + loc_c = fbuf.getloc(); + fbuf.pubimbue(loc_c); //This should initialize _M_init to true + std::locale loc_tmp = fbuf.getloc(); + VERIFY( loc_tmp == loc_c ); +} + +int main() +{ + test02(); + return 0; +} + + + +// more candy!!! diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/2.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/2.cc new file mode 100644 index 00000000000..4acff8123e7 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/2.cc @@ -0,0 +1,54 @@ +// 2003-05-13 Benjamin Kosnik + +// Copyright (C) 2003 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 27.8.1.4 Overridden virtual functions + +#include +#include +#include + +void test02() +{ + using namespace std; + bool test = true; + const char name_01[] = "filebuf_virtuals-1.txt"; // file with data in it + + locale loc; + wfilebuf ob; + VERIFY( ob.getloc() == loc ); + ob.open(name_01, ios_base::in); + VERIFY( ob.is_open() ); + + typedef streambuf::pos_type pos_type; + pos_type bad = pos_type(streambuf::off_type(-1)); + pos_type p = ob.pubseekoff(2, ios_base::beg, ios_base::in); + VERIFY( p != bad); + + // 1 "if file is not positioned at its beginning" fails... + locale loc_de = __gnu_cxx_test::try_named_locale("de_DE"); + locale ret = ob.pubimbue(loc_de); + VERIFY( ob.getloc() == loc ); +} + +main() +{ + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/3.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/3.cc new file mode 100644 index 00000000000..393732bee36 --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/3.cc @@ -0,0 +1,55 @@ +// 2003-05-13 Benjamin Kosnik + +// Copyright (C) 2003 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 27.8.1.4 Overridden virtual functions + +#include +#include +#include + +class state_codecvt : public std::codecvt +{ +protected: + int + do_encoding() const throw() + { return -1; } +}; + +void test03() +{ + using namespace std; + bool test = true; + + locale loc_s(locale::classic(), new state_codecvt); + wfilebuf ob; + ob.pubimbue(loc_s); + VERIFY( ob.getloc() == loc_s ); + + // 2 "if encoding of current locale is state dependent" fails... + locale loc_c = locale::classic(); + locale ret = ob.pubimbue(loc_s); + VERIFY( ob.getloc() == loc_s ); +} + +main() +{ + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/9322.cc b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/9322.cc new file mode 100644 index 00000000000..1b083fd023a --- /dev/null +++ b/libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/9322.cc @@ -0,0 +1,53 @@ +// 2001-05-21 Benjamin Kosnik + +// Copyright (C) 2001, 2002, 2003 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 2, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING. If not, write to the Free +// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 27.8.1.4 Overridden virtual functions + +#include +#include +#include + +// libstdc++/9322 +void test07() +{ + using std::locale; + bool test = true; + + locale loc; + std::wfilebuf ob; + VERIFY( ob.getloc() == loc ); + + locale::global(__gnu_cxx_test::try_named_locale("en_US")); + VERIFY( ob.getloc() == loc ); + + locale loc_de = __gnu_cxx_test::try_named_locale("de_DE"); + locale ret = ob.pubimbue(loc_de); + VERIFY( ob.getloc() == loc_de ); + VERIFY( ret == loc ); + + locale::global(loc); + VERIFY( ob.getloc() == loc_de ); +} + +main() +{ + test07(); + return 0; +} -- 2.30.2