std_fstream.h (filebuf::__file_type): Change to __basic_file<char>.
authorBenjamin Kosnik <bkoz@redhat.com>
Fri, 8 Feb 2002 01:34:41 +0000 (01:34 +0000)
committerBenjamin Kosnik <bkoz@gcc.gnu.org>
Fri, 8 Feb 2002 01:34:41 +0000 (01:34 +0000)
2002-02-07  Benjamin Kosnik  <bkoz@redhat.com>

libstdc++/5286
libstdc++/3860
* include/std/std_fstream.h (filebuf::__file_type): Change to
__basic_file<char>.
(filebuf::_M_convert_to_external): Declare.
* include/bits/fstream.tcc (filebuf::_M_convert_to_external): Define
codecvt bits for wide streams.
(filebuf::_M_really_overflow): Use it.
(filebuf::underflow): Use codecvt.
* config/locale/codecvt_specializations_ieee_1003.1-200x.h:
(codecvt<__enc_traits>::do_out): Deal with partial.
(codecvt<__enc_traits>::do_encoding): Return something useful.
* src/codecvt.cc (codecvt<wchar_t>::do_encoding): Return sizeof
wchar_t.
* testsuite/22_locale/codecvt_members_unicode_char.cc (test01):
Change expected encoding output.
(test02): Same.
* testsuite/22_locale/codecvt_members_wchar_t_char.cc (test01): Same.
(test02): Same.

From-SVN: r49601

libstdc++-v3/ChangeLog
libstdc++-v3/config/locale/codecvt_specializations_ieee_1003.1-200x.h
libstdc++-v3/include/bits/fstream.tcc
libstdc++-v3/include/std/std_fstream.h
libstdc++-v3/src/codecvt.cc
libstdc++-v3/testsuite/22_locale/codecvt_members_unicode_char.cc
libstdc++-v3/testsuite/22_locale/codecvt_members_wchar_t_char.cc

index d38dca4a57df5d43a3ef97b97c5a0a49eada264f..485d5d0ae275c9a2339db286d074ddde7e7d533b 100644 (file)
@@ -1,3 +1,25 @@
+2002-02-07  Benjamin Kosnik  <bkoz@redhat.com>
+
+       libstdc++/5286
+       libstdc++/3860
+       * include/std/std_fstream.h (filebuf::__file_type): Change to
+       __basic_file<char>.
+       (filebuf::_M_convert_to_external): Declare.
+       * include/bits/fstream.tcc (filebuf::_M_convert_to_external): Define
+       codecvt bits for wide streams.
+       (filebuf::_M_really_overflow): Use it.
+       (filebuf::underflow): Use codecvt.
+       * config/locale/codecvt_specializations_ieee_1003.1-200x.h: 
+       (codecvt<__enc_traits>::do_out): Deal with partial.
+       (codecvt<__enc_traits>::do_encoding): Return something useful.
+       * src/codecvt.cc (codecvt<wchar_t>::do_encoding): Return sizeof
+       wchar_t.
+       * testsuite/22_locale/codecvt_members_unicode_char.cc (test01):
+       Change expected encoding output.
+       (test02): Same.
+       * testsuite/22_locale/codecvt_members_wchar_t_char.cc (test01): Same.
+       (test02): Same.
+
 2002-02-07  Benjamin Kosnik  <bkoz@redhat.com>
             Wolfgang Bangerth  <wolfgang.bangerth@iwr.uni-heidelberg.de>
        
index 5cacffb81f88424af0962ba736c9a4f481225865..8cac2995d48f430171af56bcbc7189a5757cdf67 100644 (file)
 
   // This adaptor works around the signature problems of the second
   // argument to iconv():  SUSv2 and others use 'const char**', but glibc 2.2
-  // uses 'char**', which is what the standard is (apparently) due to use
-  // in the future.  Using this adaptor, g++ will do the work for us.
+  // uses 'char**', which matches the POSIX 1003.1-2001 standard.
+  // Using this adaptor, g++ will do the work for us.
   template<typename _T>
     inline size_t
-    __iconv_adaptor(size_t(*iconv_func)(iconv_t, _T, size_t*, char**, size_t*),
-                    iconv_t cd, char** inbuf, size_t* inbytesleft,
-                    char** outbuf, size_t* outbytesleft)
-    { return iconv_func(cd, (_T)inbuf, inbytesleft, outbuf, outbytesleft); }
+    __iconv_adaptor(size_t(*__func)(iconv_t, _T, size_t*, char**, size_t*),
+                    iconv_t __cd, char** __inbuf, size_t* __inbytes,
+                    char** __outbuf, size_t* __outbytes)
+    { return __func(__cd, (_T)__inbuf, __inbytes, __outbuf, __outbytes); }
 
   template<typename _InternT, typename _ExternT>
     codecvt_base::result
          typedef state_type::__desc_type       __desc_type;
          const __desc_type* __desc = __state._M_get_out_descriptor();
          const size_t __fmultiple = sizeof(intern_type) / sizeof(char);
-         size_t __flen = __fmultiple * (__from_end - __from);
+         size_t __fbytes = __fmultiple * (__from_end - __from);
          const size_t __tmultiple = sizeof(extern_type) / sizeof(char);
-         size_t __tlen = __tmultiple * (__to_end - __to); 
+         size_t __tbytes = __tmultiple * (__to_end - __to); 
          
          // Argument list for iconv specifies a byte sequence. Thus,
          // all to/from arrays must be brutally casted to char*.
              char_traits<intern_type>::copy(__cfixed + 1, __from, __size);
              __cfrom = reinterpret_cast<char*>(__cfixed);
              __conv = __iconv_adaptor(iconv, *__desc, &__cfrom,
-                                        &__flen, &__cto, &__tlen); 
+                                        &__fbytes, &__cto, &__tbytes); 
            }
          else
            {
              intern_type* __cfixed = const_cast<intern_type*>(__from);
              __cfrom = reinterpret_cast<char*>(__cfixed);
-             __conv = __iconv_adaptor(iconv, *__desc, &__cfrom,
-                                       &__flen, &__cto, &__tlen); 
+             __conv = __iconv_adaptor(iconv, *__desc, &__cfrom, &__fbytes, 
+                                      &__cto, &__tbytes); 
            }
 
          if (__conv != size_t(-1))
            }
          else 
            {
-             if (__flen < static_cast<size_t>(__from_end - __from))
+             if (__fbytes < __fmultiple * (__from_end - __from))
                {
                  __from_next = reinterpret_cast<const intern_type*>(__cfrom);
                  __to_next = reinterpret_cast<extern_type*>(__cto);
     int 
     codecvt<_InternT, _ExternT, __enc_traits>::
     do_encoding() const throw()
-    { return 0; }
+    {
+      int __ret = 0;
+      if (sizeof(_ExternT) <= sizeof(_InternT))
+       __ret = sizeof(_InternT)/sizeof(_ExternT);
+      return __ret; 
+    }
   
   template<typename _InternT, typename _ExternT>
     bool 
index 85a0e085e3f744e6dae589b44787b65520943b66..4ef0bcccecceb361c393b0fece1a786918c1a16b 100644 (file)
@@ -246,7 +246,6 @@ namespace std
       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
@@ -259,10 +258,10 @@ namespace std
                return traits_type::to_int_type(*_M_in_cur);
            }
 
-         bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
-         bool __testinit = _M_is_indeterminate();
          // Sync internal and external buffers.
          // NB: __testget -> __testput as _M_buf_unified here.
+         bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
+         bool __testinit = _M_is_indeterminate();
          if (__testget)
            {
              if (__testout)
@@ -278,26 +277,51 @@ namespace std
 
          if (__testinit || __testget)
            {
-             // Assume buffered case, need to refill internal buffers.
-             streamsize __size = _M_file->xsgetn(_M_in_beg, _M_buf_size);
-             if (0 < __size)
+             typedef codecvt<char_type, char, __state_type> __codecvt_type;
+             const locale __loc = this->getloc();
+             const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc); 
+
+             streamsize __elen = 0;
+             streamsize __ilen = 0;
+             if (__cvt.always_noconv())
+               {
+                 __elen = _M_file->xsgetn(reinterpret_cast<char*>(_M_in_beg), 
+                                          _M_buf_size);
+                 __ilen = __elen;
+               }
+             else
                {
-                 _M_set_determinate(__size);
+                 char* __buf = static_cast<char*>(__builtin_alloca(_M_buf_size));
+                 __elen = _M_file->xsgetn(__buf, _M_buf_size);
+
+                 const char* __eend;
+                 char_type* __iend;
+                 __res_type __r = __cvt.in(_M_state_cur, __buf, 
+                                           __buf + __elen, __eend, _M_in_beg, 
+                                           _M_in_beg + _M_buf_size, __iend);
+                 if (__r == codecvt_base::ok)
+                   __ilen = __iend - _M_in_beg;
+                 else 
+                   {
+                     // Unwind.
+                     __ilen = 0;
+                     _M_file->seekoff(-__elen, ios_base::cur, ios_base::in);
+                   }
+               }
+
+             if (0 < __ilen)
+               {
+                 _M_set_determinate(__ilen);
                  if (__testout)
                    _M_out_cur = _M_in_cur;
                  __ret = traits_type::to_int_type(*_M_in_cur);
 #if _GLIBCPP_AVOID_FSEEK
-                 if (__size == 1)
+                 if (__elen == 1)
                    _M_file->sys_ungetc(*_M_in_cur);
                  else
                    {
 #endif
-                 streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur, 
-                                                  ios_base::in);
-                 if (__p == -1)
-                   {
-                     // XXX Something is wrong, do error checking.
-                   }
+                     _M_file->seekoff(-__elen, ios_base::cur, ios_base::in);
 #if _GLIBCPP_AVOID_FSEEK
                    }
 #endif
@@ -401,6 +425,66 @@ namespace std
       return __ret;
     }
   
+  template<typename _CharT, typename _Traits>
+    void
+    basic_filebuf<_CharT, _Traits>::
+    _M_convert_to_external(_CharT* __ibuf, streamsize __ilen,
+                          streamsize& __elen, streamsize& __plen)
+    {
+      typedef codecvt<char_type, char, __state_type> __codecvt_type;
+      const locale __loc = this->getloc();
+      const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
+      
+      if (__cvt.always_noconv() && __ilen)
+       {
+         __elen += _M_file->xsputn(reinterpret_cast<char*>(__ibuf), __ilen);
+         __plen += __ilen;
+       }
+      else
+       {
+         // Worst-case number of external bytes needed.
+         int __ext_multiplier = __cvt.encoding();
+         if (__ext_multiplier ==  -1 || __ext_multiplier == 0)
+           __ext_multiplier = sizeof(char_type);
+         streamsize __blen = __ilen * __ext_multiplier;
+         char* __buf = static_cast<char*>(__builtin_alloca(__blen));
+         char* __bend;
+         const char_type* __iend;
+         __res_type __r = __cvt.out(_M_state_cur, __ibuf, __ibuf + __ilen, 
+                                    __iend, __buf, __buf + __blen, __bend);
+         // Result == ok, partial, noconv
+         if (__r != codecvt_base::error)
+           __blen = __bend - __buf;
+         // Result == error
+         else 
+           __blen = 0;
+         
+         if (__blen)
+           {
+             __elen += _M_file->xsputn(__buf, __blen);
+             __plen += __blen;
+           }
+
+         // Try once more for partial conversions.
+         if (__r == codecvt_base::partial)
+           {
+             const char_type* __iresume = __iend;
+             streamsize __rlen = _M_out_end - __iend;
+             __r = __cvt.out(_M_state_cur, __iresume, __iresume + __rlen, 
+                             __iend, __buf, __buf + __blen, __bend);
+             if (__r != codecvt_base::error)
+               __rlen = __bend - __buf;
+             else 
+               __rlen = 0;
+             if (__rlen)
+               {
+                 __elen += _M_file->xsputn(__buf, __rlen);
+                 __plen += __rlen;
+               }
+           }
+       }
+    }
+
   template<typename _CharT, typename _Traits>
     typename basic_filebuf<_CharT, _Traits>::int_type 
     basic_filebuf<_CharT, _Traits>::
@@ -412,68 +496,31 @@ namespace std
 
       if (__testput || __testunbuffered)
        {
-#if 1
-         int __plen = _M_out_end - _M_out_beg;
-         streamsize __len = 0;
-
-         if (__plen)
-           __len = _M_file->xsputn(_M_out_beg, __plen);
-
-         if (__c != traits_type::eof())
+         // Sizes of external and pending output.
+         streamsize __elen = 0;
+         streamsize __plen = 0;
+
+         // Convert internal buffer to external representation, output.
+         // NB: In the unbuffered case, no internal buffer exists. 
+         if (!__testunbuffered)
+           _M_convert_to_external(_M_out_beg,  _M_out_end - _M_out_beg, 
+                                  __elen, __plen);
+
+         // Convert pending sequence to external representation, output.
+         if (!traits_type::eq_int_type(__c, traits_type::eof()))
            {
-             char_type __pending = traits_type::to_char_type(__c);
-             __len += _M_file->xsputn(&__pending, 1);
-             ++__plen;
+             char_type __pending = traits_type::to_char_type(__c);
+             _M_convert_to_external(&__pending, 1, __elen, __plen);
            }
 
+         // Last, sync internal and external buffers.
          // NB: Need this so that external byte sequence reflects
-         // internal buffer.
-         if (__len == __plen && !_M_file->sync())
+         // internal buffer plus pending sequence.
+         if (__elen == __plen && !_M_file->sync())
            {
              _M_set_indeterminate();
              __ret = traits_type::not_eof(__c);
            }
-#else
-         // Part one: Allocate temporary conversion buffer on
-         // stack. Convert internal buffer plus __c (ie,
-         // "pending sequence") to temporary conversion buffer.
-         int __plen = _M_out_end - _M_out_beg;
-         char_type* __pbuf = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen + 1));
-         traits_type::copy(__pbuf, this->pbase(), __plen);
-         if (!__testeof)
-           {
-             __pbuf[__plen] = traits_type::to_char_type(__c);
-             ++__plen;
-           }
-
-         char_type* __pend;
-         char* __conv_buf = static_cast<char*>(__builtin_alloca(__plen));
-         char* __conv_end;
-         _M_state_beg = _M_state_cur;
-
-         __res_type __r = _M_fcvt->out(_M_state_cur, 
-                                       __pbuf, __pbuf + __plen,
-                                       const_cast<const char_type*&>(__pend),
-                                       __conv_buf, __conv_buf + __plen,
-                                       __conv_end);
-         
-         // Part two: (Re)spill converted "pending sequence"
-         // contents (now in temporary conversion buffer) to
-         // external buffer (_M_file->_IO_*) using
-         // _M_file->sys_write(), and do error (minimal) checking.
-         if (__r != codecvt_base::error)
-           {
-             streamsize __len = _M_file->xsputn(__conv_buf, __plen);
-             // NB: Need this so that external byte sequence reflects
-             // internal buffer.
-             _M_file->sync(); // XXX error check
-             if (__len == __plen)
-               {
-                 _M_set_indeterminate();
-                 __ret = traits_type::not_eof(__c);
-               }
-           }
-#endif
        }             
       _M_last_overflowed = true;       
       return __ret;
index 4483e3f489933b0a0a90d0ed485327caee81c743..92839753bd6f0ca7995776cc1ce15694961af60a 100644 (file)
@@ -64,7 +64,7 @@ namespace std
       // Non-standard Types:
       typedef basic_streambuf<char_type, traits_type>          __streambuf_type;
       typedef basic_filebuf<char_type, traits_type>     __filebuf_type;
-      typedef __basic_file<char_type>                  __file_type;
+      typedef __basic_file<char>                       __file_type;
       typedef typename traits_type::state_type          __state_type;
       typedef codecvt<char_type, char, __state_type>    __codecvt_type;
       typedef typename __codecvt_type::result          __res_type;
@@ -111,13 +111,13 @@ namespace std
 
       // Members:
       bool
-      is_open(void) const { return _M_file ? _M_file->is_open() : false; }
+      is_open() const { return _M_file ? _M_file->is_open() : false; }
 
       __filebuf_type*
       open(const char* __s, ios_base::openmode __mode);
 
       __filebuf_type*
-      close(void);
+      close();
 
     protected:
       void
@@ -135,14 +135,14 @@ namespace std
 
       // Overridden virtual functions:
       virtual streamsize
-      showmanyc(void);
+      showmanyc();
 
       // Stroustrup, 1998, p. 628
       // underflow() and uflow() functions are called to get the next
       // charater from the real input source when the buffer is empty.
       // Buffered input uses underflow()
       virtual int_type
-      underflow(void);
+      underflow();
 
       virtual int_type
       pbackfail(int_type __c = _Traits::eof());
@@ -168,6 +168,11 @@ namespace std
       int_type
       _M_really_overflow(int_type __c = _Traits::eof());
 
+      // Convert internal byte sequence to external, char-based
+      // sequence via codecvt.
+      void
+      _M_convert_to_external(char_type*, streamsize, streamsize&, streamsize&);
+
       virtual __streambuf_type*
       setbuf(char_type* __s, streamsize __n);
 
@@ -180,7 +185,7 @@ namespace std
              ios_base::openmode __mode = ios_base::in | ios_base::out);
 
       virtual int
-      sync(void)
+      sync()
       {
        bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
 
@@ -296,7 +301,7 @@ namespace std
       { return const_cast<__filebuf_type*>(&_M_filebuf); }
 
       bool
-      is_open(void) { return _M_filebuf.is_open(); }
+      is_open() { return _M_filebuf.is_open(); }
 
       void
       open(const char* __s, ios_base::openmode __mode = ios_base::in)
@@ -307,7 +312,7 @@ namespace std
 
       /** Close the file.  */
       void
-      close(void)
+      close()
       {
        if (!_M_filebuf.close())
          this->setstate(ios_base::failbit);
@@ -370,7 +375,7 @@ namespace std
        *  @return Pointer to basic_filebuf.
       */
       __filebuf_type*
-      rdbuf(void) const
+      rdbuf() const
       { return const_cast<__filebuf_type*>(&_M_filebuf); }
 
       /**
@@ -378,7 +383,7 @@ namespace std
        *  @return True if stream is open.
       */
       bool
-      is_open(void) { return _M_filebuf.is_open(); }
+      is_open() { return _M_filebuf.is_open(); }
 
       /**
        *  @brief Specify a file to open for output.
@@ -398,7 +403,7 @@ namespace std
 
       /** Close the file stream.  */
       void
-      close(void)
+      close()
       {
        if (!_M_filebuf.close())
          this->setstate(ios_base::failbit);
@@ -462,7 +467,7 @@ namespace std
        *  @return Pointer to basic_filebuf.
       */
       __filebuf_type*
-      rdbuf(void) const
+      rdbuf() const
       { return const_cast<__filebuf_type*>(&_M_filebuf); }
 
       /**
@@ -470,7 +475,7 @@ namespace std
        *  @return True if stream is open.
       */
       bool
-      is_open(void) { return _M_filebuf.is_open(); }
+      is_open() { return _M_filebuf.is_open(); }
 
       /**
        *  @brief Specify a file to open for input and/or output.
@@ -490,7 +495,7 @@ namespace std
 
       /** Close the file stream.  */
       void
-      close(void)
+      close()
       {
        if (!_M_filebuf.close())
          setstate(ios_base::failbit);
index c5474c6c7a7a5be37d76a3e9979c1af14277ad7f..032667e3f13307f047b73357a70beedd34c2e1e4 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2000 Free Software Foundation, Inc.
+// Copyright (C) 2000, 2002 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
@@ -181,7 +181,7 @@ namespace std
   int 
   codecvt<wchar_t, char, mbstate_t>::
   do_encoding() const throw()
-  { return 0; }
+  { return sizeof(wchar_t); }
   
   bool 
   codecvt<wchar_t, char, mbstate_t>::
index 2a135f67df111001ac87ff9319eab67c9ccb3c42..026e6091397eb1327cec71a50e2290f0a8fca85f 100644 (file)
@@ -1,6 +1,6 @@
 // 2000-08-22 Benjamin Kosnik <bkoz@cygnus.com>
 
-// Copyright (C) 2000, 2001 Free Software Foundation
+// Copyright (C) 2000, 2001, 2002 Free Software Foundation
 //
 // 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
@@ -124,7 +124,7 @@ void test01()
   VERIFY( eto_next == e_arr );
 
   int i = cvt.encoding();
-  VERIFY( i == 0 );
+  VERIFY( i == 2 ); // Target-dependent.
 
   VERIFY( !cvt.always_noconv() );
 
@@ -210,7 +210,7 @@ void test02()
   VERIFY( eto_next == e_arr );
 
   int i = cvt.encoding();
-  VERIFY( i == 0 );
+  VERIFY( i == 2 ); // Target-dependent.
 
   VERIFY( !cvt.always_noconv() );
 
index 9ff83e9069a71c4470481f83844a2cc9b43d51f9..45655b7a6011af63ea699b29a257ee40205b3d7a 100644 (file)
@@ -95,7 +95,7 @@ void test01()
   VERIFY( eto_next == e_arr );
 
   int i = cvt->encoding();
-  VERIFY( i == 0 );
+  VERIFY( i == 4 ); // Target-dependent.
 
   VERIFY( !cvt->always_noconv() );