Imbuing streams to auto-codecvt [was Re: _M_underflow_common missing]

Brad Spencer spencer@infointeractive.com
Wed Sep 4 13:07:00 GMT 2002


On Wed, Sep 04, 2002 at 10:01:31AM -0500, Benjamin Kosnik wrote:
> 
> I'm interested in what you are doing but currently am busy with other
> things. If you can give me a couple of days I'd appreciate it.

I'm working on this partly out of need, but mostly out of
interest :)  It'll take me at least a couple of days to get
up-to-speed on what's going on in that part of the library.

> If you can post complete code samples that demonstrate what you are
> doing it would be helpful.

I will followup with a complete (small) sample program in a few
minutes.

After getting everything working on i686-pc-linux-gnu, I moved on to
my usual cross compilers, targetted for sparc-sun-solaris2.8.  Here's
where a few more questions show up

1. sparc-sun-solaris2.8 seems to have a _lot_ of ISO C99's
   wide-character support, but not quite all of it.  I
   _think_ it has enough to turn on the specializations in the library
   for wchar_t; I'm working on trying this out.  None of the missing
   functions are actually used in any way except "using std::SYMBOL;".

2. I took a guess and said that sparc-sun-solaris2.8 uses
   "ieee_1003.1-2001"-style locales.  Not sure if that's true or not,
   but it looks like the code for that style is out-of-date.  I've
   added the missing pieces from "generic", changed the function
   signatures to match, and removed a couple of methods that were
   reported as being defined elsewhere (and were).  Attached (to avoid
   word-wrap) is a patch against the gcc-3.2 version of the library.
   (Should I be providing ChangeLog entries for stuff like this?)

   I'm not sure if this is as good as the implementation can do for
   this style.  Switching locales to call sscanf sounds fairly
   sub-optimal. 

-- 
------------------------------------------------------------------
Brad Spencer - spencer@infointeractive.com - "It's quite nice..."
Systems Architect | InfoInterActive Corp. | A Canadian AOL Company
-------------- next part --------------
*** ./config/locale/ieee_1003.1-2001/messages_members.h.orig	Wed Sep  4 13:55:46 2002
--- ./config/locale/ieee_1003.1-2001/messages_members.h	Wed Sep  4 15:05:20 2002
***************
*** 40,50 ****
  			   const char*) const
      { return this->do_open(__s, __loc); }
  
-   // Virtual member functions.
-   template<typename _CharT>
-     messages<_CharT>::~messages()
-     { }
- 
    template<typename _CharT>
      typename messages<_CharT>::catalog 
      messages<_CharT>::do_open(const basic_string<char>& __s, 
--- 40,45 ----
*** ./config/locale/ieee_1003.1-2001/c_locale.cc.orig	Wed Sep  4 14:10:18 2002
--- ./config/locale/ieee_1003.1-2001/c_locale.cc	Wed Sep  4 15:50:38 2002
***************
*** 37,112 ****
  
  namespace std 
  {
!   void
!   locale::facet::_S_create_c_locale(__c_locale&, const char*, __c_locale*)
!   { }
  
!   void
!   locale::facet::_S_destroy_c_locale(__c_locale&)
!   { }
  
!   __c_locale
!   locale::facet::_S_clone_c_locale(__c_locale&)
!   { return __c_locale(); }
  
!   template<> 
      void
!     numpunct<char>::_M_initialize_numpunct(__c_locale)
      {
!       // "C" locale
!       _M_decimal_point = '.';
!       _M_thousands_sep = ',';
!       _M_grouping = "";
!       _M_truename = "true";
!       _M_falsename = "false";
!     }
!       
! #ifdef _GLIBCPP_USE_WCHAR_T
!   template<> 
!     void
!     numpunct<wchar_t>::_M_initialize_numpunct(__c_locale)
!     {
!       // "C" locale
!       _M_decimal_point = L'.';
!       _M_thousands_sep = L',';
!       _M_grouping = "";
!       _M_truename = L"true";
!       _M_falsename = L"false";
      }
  #endif
  
!   template<> 
      void
!     moneypunct<char>::_M_initialize_moneypunct(__c_locale)
      {
!       // "C" locale
!       _M_decimal_point = '.';
!       _M_thousands_sep = ',';
!       _M_grouping = "";
!       _M_curr_symbol = string_type();
!       _M_positive_sign = string_type();
!       _M_negative_sign = string_type();
!       _M_frac_digits = 0;
!       _M_pos_format = money_base::_S_default_pattern;
!       _M_neg_format = money_base::_S_default_pattern;
!     }
! 
! #ifdef _GLIBCPP_USE_WCHAR_T
!   template<> 
!     void
!     moneypunct<wchar_t>::_M_initialize_moneypunct(__c_locale)
!     {
!       // "C" locale
!       _M_decimal_point = L'.';
!       _M_thousands_sep = L',';
!       _M_grouping = "";
!       _M_curr_symbol = string_type();
!       _M_positive_sign = string_type();
!       _M_negative_sign = string_type();
!       _M_frac_digits = 0;
!       _M_pos_format = money_base::_S_default_pattern;
!       _M_neg_format = money_base::_S_default_pattern;
      }
  #endif
  }  // namespace std
  
--- 37,226 ----
  
  namespace std 
  {
!   // Using the same __convert_to_v as generic right now.  Perhaps these belong
!   // in a separate file so we can just use them directly from there?
!   
!   // Specializations for all types used in num_get.
!   template<>
!     void
!     __convert_to_v(const char* __s, long& __v, ios_base::iostate& __err, 
! 		   const __c_locale&, int __base)
!     {
!       if (!(__err & ios_base::failbit))
!       {
! 	char* __sanity;
! 	errno = 0;
! 	long __l = strtol(__s, &__sanity, __base);
! 	if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
! 	  __v = __l;
! 	else
! 	  __err |= ios_base::failbit;
!       }
!     }
  
!   template<>
!     void
!     __convert_to_v(const char* __s, unsigned long& __v, 
! 		   ios_base::iostate& __err, const __c_locale&, int __base)
!     {
!       if (!(__err & ios_base::failbit))
! 	{
! 	  char* __sanity;
! 	  errno = 0;
! 	  unsigned long __ul = strtoul(__s, &__sanity, __base);
!           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
! 	    __v = __ul;
! 	  else
! 	    __err |= ios_base::failbit;
! 	}
!     }
  
! #ifdef _GLIBCPP_USE_LONG_LONG
!   template<>
!     void
!     __convert_to_v(const char* __s, long long& __v, ios_base::iostate& __err, 
! 		   const __c_locale&, int __base)
!     {
!       if (!(__err & ios_base::failbit))
! 	{
! 	  char* __sanity;
! 	  errno = 0;
! 	  long long __ll = strtoll(__s, &__sanity, __base);
!           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
! 	    __v = __ll;
! 	  else
! 	    __err |= ios_base::failbit;
! 	}
!     }
  
!   template<>
      void
!     __convert_to_v(const char* __s, unsigned long long& __v, 
! 		   ios_base::iostate& __err, const __c_locale&, int __base)
      {
!       if (!(__err & ios_base::failbit))
! 	{      
! 	  char* __sanity;
! 	  errno = 0;
! 	  unsigned long long __ull = strtoull(__s, &__sanity, __base);
!           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
! 	    __v = __ull;
! 	  else
! 	    __err |= ios_base::failbit;
! 	}  
      }
  #endif
  
!   template<>
!     void
!     __convert_to_v(const char* __s, float& __v, ios_base::iostate& __err, 
! 		   const __c_locale&, int) 	      
!     {
!       if (!(__err & ios_base::failbit))
! 	{
! 	  // Assumes __s formatted for "C" locale.
! 	  char* __old = strdup(setlocale(LC_ALL, NULL));
! 	  setlocale(LC_ALL, "C");
! 	  char* __sanity;
! 	  errno = 0;
! #if defined(_GLIBCPP_USE_C99)
! 	  float __f = strtof(__s, &__sanity);
! #else
! 	  double __d = strtod(__s, &__sanity);
! 	  float __f = static_cast<float>(__d);
! #ifdef _GLIBCPP_HAVE_FINITEF
! 	  if (!finitef (__f))
! 	    errno = ERANGE;
! #elif defined (_GLIBCPP_HAVE_FINITE)
! 	  if (!finite (static_cast<double> (__f)))
! 	    errno = ERANGE;
! #elif defined (_GLIBCPP_HAVE_ISINF)
! 	  if (isinf (static_cast<double> (__f)))
! 	    errno = ERANGE;
! #else
! 	  if (fabs(__d) > numeric_limits<float>::max())
! 	    errno = ERANGE;
! #endif
! #endif
!           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
! 	    __v = __f;
! 	  else
! 	    __err |= ios_base::failbit;
! 	  setlocale(LC_ALL, __old);
! 	  free(__old);
! 	}
!     }
! 
!   template<>
      void
!     __convert_to_v(const char* __s, double& __v, ios_base::iostate& __err, 
! 		   const __c_locale&, int) 
      {
!       if (!(__err & ios_base::failbit))
! 	{
! 	  // Assumes __s formatted for "C" locale.
! 	  char* __old = strdup(setlocale(LC_ALL, NULL));
! 	  setlocale(LC_ALL, "C");
! 	  char* __sanity;
! 	  errno = 0;
! 	  double __d = strtod(__s, &__sanity);
!           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
! 	    __v = __d;
! 	  else
! 	    __err |= ios_base::failbit;
! 	  setlocale(LC_ALL, __old);
! 	  free(__old);
! 	}
      }
+ 
+   template<>
+     void
+     __convert_to_v(const char* __s, long double& __v, 
+ 		   ios_base::iostate& __err, const __c_locale&, int) 
+     {
+       if (!(__err & ios_base::failbit))
+ 	{
+ 	  // Assumes __s formatted for "C" locale.
+ 	  char* __old = strdup(setlocale(LC_ALL, NULL));
+ 	  setlocale(LC_ALL, "C");
+ #if defined(_GLIBCPP_USE_C99)
+ 	  char* __sanity;
+ 	  errno = 0;
+ 	  long double __ld = strtold(__s, &__sanity);
+           if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
+ 	    __v = __ld;
+ #else
+ 	  typedef char_traits<char>::int_type int_type;
+ 	  long double __ld;
+ 	  errno = 0;
+ 	  int __p = sscanf(__s, "%Lf", &__ld);
+ 	  if (errno == ERANGE)
+ 	    __p = 0;
+ #ifdef _GLIBCPP_HAVE_FINITEL
+ 	  if ((__p == 1) && !finitel (__ld))
+ 	    __p = 0;
+ #endif
+ 	  if (__p && static_cast<int_type>(__p) != char_traits<char>::eof())
+ 	    __v = __ld;
  #endif
+ 	  else
+ 	    __err |= ios_base::failbit;
+ 	  setlocale(LC_ALL, __old);
+ 	  free(__old);
+ 	}
+     }
+ 
+   void
+   locale::facet::_S_create_c_locale(__c_locale&, const char*, __c_locale)
+   { }
+ 
+   void
+   locale::facet::_S_destroy_c_locale(__c_locale&)
+   { }
+ 
+   __c_locale
+   locale::facet::_S_clone_c_locale(__c_locale&)
+   { return __c_locale(); }
+ 
  }  // namespace std
  


More information about the Libstdc++ mailing list