std_fstream.h (basic_filebuf::_M_codecvt): Add cached member.
authorBenjamin Kosnik <bkoz@redhat.com>
Tue, 13 May 2003 20:13:15 +0000 (20:13 +0000)
committerBenjamin Kosnik <bkoz@gcc.gnu.org>
Tue, 13 May 2003 20:13:15 +0000 (20:13 +0000)
2003-05-12  Benjamin Kosnik  <bkoz@redhat.com>

* 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

17 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/basic_ios.h
libstdc++-v3/include/bits/basic_ios.tcc
libstdc++-v3/include/bits/fstream.tcc
libstdc++-v3/include/bits/istream.tcc
libstdc++-v3/include/bits/locale_classes.h
libstdc++-v3/include/bits/locale_facets.tcc
libstdc++-v3/include/bits/localefwd.h
libstdc++-v3/include/bits/ostream.tcc
libstdc++-v3/include/std/std_fstream.h
libstdc++-v3/include/std/std_streambuf.h
libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/char/3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/27_io/basic_filebuf/imbue/wchar_t/9322.cc [new file with mode: 0644]

index 9ea0c9f2a29d00a56e824fef3f93d4c9075e3bc5..c7273a27e392d82f013574eb6dd9972bc2c07f2d 100644 (file)
@@ -1,3 +1,32 @@
+2003-05-12  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * 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  <pcarlini@unitus.it>
 
        * testsuite/27_io/basic_filebuf/sgetc/char/1.cc: Remove
index 5be11a2590db4146fc3db9f180579ed05000c715..98b73cadd7cce3f442461b0637962d186941a7e3 100644 (file)
@@ -90,11 +90,11 @@ namespace std
       basic_streambuf<_CharT, _Traits>*              _M_streambuf;
 
       // Cached use_facet<ctype>, 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);
 
index 0c1e7357098cd78e9123cf8a321be658b89054c2..cf2701effb21725b675789377ea4a25b951e54d6 100644 (file)
@@ -110,22 +110,12 @@ namespace std
   template<typename _CharT, typename _Traits>
     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<typename _CharT, typename _Traits>
     _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<typename _CharT, typename _Traits>
@@ -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); 
     }
 
index 40d1ece324a317ee1393c6bc5a77544d9ccfd877..3397071bd84f465dcd97c57be97654735c8ae626 100644 (file)
@@ -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 _CharT, typename _Traits>
     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<char*>(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<char*>(__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;      
     }
 
index cc83f81a9237b272d0032c69000ee1daed2dd7c1..a9448b09c09f34e55e888bde7b7d8efbb5b2f1f2 100644 (file)
@@ -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(...)
index 7c447e878f67676cf0405badff765bb5bc6bb277..e7210f821fedc48b002333a6158c7ecb7b626bdb 100644 (file)
@@ -64,14 +64,14 @@ namespace std
     friend class facet;
     friend class _Impl;
 
-    template<typename _Facet>
-      friend const _Facet& 
-      use_facet(const locale&);
-    
     template<typename _Facet>
       friend bool 
       has_facet(const locale&) throw();
+
+    template<typename _Facet>
+      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;
index 6e09e407104979707c353389690e85b0e3e251f1..f44531799f015a21f17feddc8041c0d34c2b14e3 100644 (file)
@@ -67,23 +67,23 @@ namespace std
     }
 
   template<typename _Facet>
-    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<const _Facet&>(*__facets[__i]);
+      return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
     }
 
   template<typename _Facet>
-    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<const _Facet&>(*__facets[__i]);
     }
 
 
index ac9e1a95425a20b1829793542c132da01f6d6f1e..16fa8821e9a3d9b9973e6e803e2b4b9e8b44eae3 100644 (file)
@@ -171,13 +171,22 @@ namespace std
   template<typename _CharT> 
     class messages_byname;
 
+  template<typename _Facet>
+    bool
+    has_facet(const locale& __loc) throw();
+
   template<typename _Facet>
     const _Facet&
     use_facet(const locale& __loc);
 
   template<typename _Facet>
-    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
index fc7d08a1b6e0e5b444448d012bca3a33d4940579..620458806a14d3a9ad65e3cda723478afe4c8581 100644 (file)
@@ -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<unsigned long>(__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<unsigned long>(__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<unsigned long long>(__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<unsigned long long>(__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(...)
            {
index 0781f0d5294e6b993571eb23499a15e4949b4950..2ff4ec15d103c323497a33daa7639d3516397579 100644 (file)
@@ -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;
       }
index 946e9bc600c1daf69bfa90217a46a647b7079999..e258501c18b6e4521d8b5d64a864040062ff7805 100644 (file)
@@ -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 (file)
index 0000000..de6e133
--- /dev/null
@@ -0,0 +1,54 @@
+// 2003-05-13 Benjamin Kosnik  <bkoz@redhat.com>
+
+// 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 <fstream>
+#include <locale>
+#include <testsuite_hooks.h>
+
+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 (file)
index 0000000..1899278
--- /dev/null
@@ -0,0 +1,55 @@
+// 2003-05-13 Benjamin Kosnik  <bkoz@redhat.com>
+
+// 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 <fstream>
+#include <locale>
+#include <testsuite_hooks.h>
+
+class state_codecvt : public std::codecvt<char, char, std::mbstate_t>
+{
+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 (file)
index 0000000..621799e
--- /dev/null
@@ -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 <fstream>
+#include <testsuite_hooks.h>
+
+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 (file)
index 0000000..4acff81
--- /dev/null
@@ -0,0 +1,54 @@
+// 2003-05-13 Benjamin Kosnik  <bkoz@redhat.com>
+
+// 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 <fstream>
+#include <locale>
+#include <testsuite_hooks.h>
+
+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 (file)
index 0000000..393732b
--- /dev/null
@@ -0,0 +1,55 @@
+// 2003-05-13 Benjamin Kosnik  <bkoz@redhat.com>
+
+// 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 <fstream>
+#include <locale>
+#include <testsuite_hooks.h>
+
+class state_codecvt : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+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 (file)
index 0000000..1b083fd
--- /dev/null
@@ -0,0 +1,53 @@
+// 2001-05-21 Benjamin Kosnik  <bkoz@redhat.com>
+
+// 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 <fstream>
+#include <locale>
+#include <testsuite_hooks.h>
+
+// 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;
+}