This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [FYI] A "problem" in money_get/money_put/time_put


Paolo Carlini wrote:

I'm now working on money_put and money_get.

The below is the corresponding patch, regtested x86-linux: turned out to be straightforward, but working on it made clear that money_get is currently using ctype::narrow and isn't using ctype::widen (see 22.2.6.1.2, p4 and note 237), thus the caching bits are even more urgent for the correctness implications (they bring the widened in and out atoms).

Will commit later today.

Paolo.

///////////
2004-02-18  Paolo Carlini  <pcarlini@suse.de>

	* include/bits/locale_facets.h (money_get<>::_M_extract):
	New, helper for do_get.
	(money_put<>::_M_insert): Likewise, for do_put.
	* include/bits/locale_facets.tcc (money_get<>::_M_extract,
	money_put<>::_M_insert): Define.
	(money_get<>::do_get(long double&), money_get<>::do_get(
	string_type&), money_put::do_put(long double),
	money_put::do_put(const string_type&)): Use the helpers.

diff -prN libstdc++-v3-orig/include/bits/locale_facets.h libstdc++-v3/include/bits/locale_facets.h
*** libstdc++-v3-orig/include/bits/locale_facets.h	Sun Feb  8 05:46:41 2004
--- libstdc++-v3/include/bits/locale_facets.h	Wed Feb 18 11:33:19 2004
*************** namespace std
*** 4056,4061 ****
--- 4056,4065 ----
        virtual iter_type
        do_get(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
  	     ios_base::iostate& __err, string_type& __digits) const;
+ 
+       iter_type
+       _M_extract(iter_type __s, iter_type __end, bool __intl, ios_base& __io,
+ 		 ios_base::iostate& __err, string_type& __digits) const;     
      };
  
    template<typename _CharT, typename _InIter>
*************** namespace std
*** 4189,4194 ****
--- 4193,4202 ----
        virtual iter_type
        do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
  	     const string_type& __digits) const;
+ 
+       iter_type
+       _M_insert(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+ 		const string_type& __digits) const;
      };
  
    template<typename _CharT, typename _OutIter>
diff -prN libstdc++-v3-orig/include/bits/locale_facets.tcc libstdc++-v3/include/bits/locale_facets.tcc
*** libstdc++-v3-orig/include/bits/locale_facets.tcc	Tue Feb 17 11:18:33 2004
--- libstdc++-v3/include/bits/locale_facets.tcc	Wed Feb 18 11:32:25 2004
*************** namespace std
*** 1130,1160 ****
        return __s;
      }
  
- 
-   template<typename _CharT, typename _InIter>
-     _InIter
-     money_get<_CharT, _InIter>::
-     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
- 	   ios_base::iostate& __err, long double& __units) const
-     {
-       string_type __str;
-       __beg = this->do_get(__beg, __end, __intl, __io, __err, __str);
- 
-       const int __cs_size = __str.size() + 1;
-       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
-       const locale __loc = __io.getloc();
-       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-       const _CharT* __wcs = __str.c_str();
-       __ctype.narrow(__wcs, __wcs + __cs_size, char(), __cs);
-       std::__convert_to_v(__cs, __units, __err, _S_get_c_locale());
-       return __beg;
-     }
- 
    template<typename _CharT, typename _InIter>
      _InIter
      money_get<_CharT, _InIter>::
!     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
! 	   ios_base::iostate& __err, string_type& __units) const
      {
        // These contortions are quite unfortunate.
        typedef moneypunct<_CharT, true>		__money_true;
--- 1130,1140 ----
        return __s;
      }
  
    template<typename _CharT, typename _InIter>
      _InIter
      money_get<_CharT, _InIter>::
!     _M_extract(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
! 	       ios_base::iostate& __err, string_type& __units) const
      {
        // These contortions are quite unfortunate.
        typedef moneypunct<_CharT, true>		__money_true;
*************** namespace std
*** 1358,1410 ****
        return __beg;
      }
  
!   template<typename _CharT, typename _OutIter>
!     _OutIter
!     money_put<_CharT, _OutIter>::
!     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
! 	   long double __units) const
      {
        const locale __loc = __io.getloc();
        const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
! #ifdef _GLIBCXX_USE_C99
!       // First try a buffer perhaps big enough.
!       int __cs_size = 64;
!       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
!       // _GLIBCXX_RESOLVE_LIB_DEFECTS
!       // 328. Bad sprintf format modifier in money_put<>::do_put()
!       int __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
! 					_S_get_c_locale());
!       // If the buffer was not large enough, try again with the correct size.
!       if (__len >= __cs_size)
! 	{
! 	  __cs_size = __len + 1;
! 	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
! 	  __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
! 					_S_get_c_locale());
! 	}
! #else
!       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
!       const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
!       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
!       int __len = std::__convert_from_v(__cs, 0, "%.0Lf", __units,
! 					_S_get_c_locale());
! #endif
!       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
! 							   * __cs_size));
!       __ctype.widen(__cs, __cs + __len, __ws);
!       const string_type __digits(__ws, __len);
!       return this->do_put(__s, __intl, __io, __fill, __digits);
      }
  
    template<typename _CharT, typename _OutIter>
      _OutIter
      money_put<_CharT, _OutIter>::
!     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
! 	   const string_type& __digits) const
      {
        typedef typename string_type::size_type	size_type;
        typedef money_base::part			part;
! 
        const locale __loc = __io.getloc();
        const size_type __width = static_cast<size_type>(__io.width());
  
--- 1338,1378 ----
        return __beg;
      }
  
!   template<typename _CharT, typename _InIter>
!     _InIter
!     money_get<_CharT, _InIter>::
!     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
! 	   ios_base::iostate& __err, long double& __units) const
      {
+       string_type __str;
+       __beg = _M_extract(__beg, __end, __intl, __io, __err, __str);
+ 
+       const int __cs_size = __str.size() + 1;
+       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
        const locale __loc = __io.getloc();
        const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
!       const _CharT* __wcs = __str.c_str();
!       __ctype.narrow(__wcs, __wcs + __cs_size, char(), __cs);
!       std::__convert_to_v(__cs, __units, __err, _S_get_c_locale());
!       return __beg;
      }
  
+   template<typename _CharT, typename _InIter>
+     _InIter
+     money_get<_CharT, _InIter>::
+     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
+ 	   ios_base::iostate& __err, string_type& __units) const
+     { return _M_extract(__beg, __end, __intl, __io, __err, __units); }
+ 
    template<typename _CharT, typename _OutIter>
      _OutIter
      money_put<_CharT, _OutIter>::
!     _M_insert(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
! 	      const string_type& __digits) const
      {
        typedef typename string_type::size_type	size_type;
        typedef money_base::part			part;
!       
        const locale __loc = __io.getloc();
        const size_type __width = static_cast<size_type>(__io.width());
  
*************** namespace std
*** 1556,1564 ****
  	  __s = std::__write(__s, __res.data(), __len);
  	}
        __io.width(0);
!       return __s;
      }
  
  
    // NB: Not especially useful. Without an ios_base object or some
    // kind of locale reference, we are left clawing at the air where
--- 1524,1576 ----
  	  __s = std::__write(__s, __res.data(), __len);
  	}
        __io.width(0);
!       return __s;    
      }
  
+   template<typename _CharT, typename _OutIter>
+     _OutIter
+     money_put<_CharT, _OutIter>::
+     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+ 	   long double __units) const
+     {
+       const locale __loc = __io.getloc();
+       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
+ #ifdef _GLIBCXX_USE_C99
+       // First try a buffer perhaps big enough.
+       int __cs_size = 64;
+       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
+       // 328. Bad sprintf format modifier in money_put<>::do_put()
+       int __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
+ 					_S_get_c_locale());
+       // If the buffer was not large enough, try again with the correct size.
+       if (__len >= __cs_size)
+ 	{
+ 	  __cs_size = __len + 1;
+ 	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+ 	  __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
+ 					_S_get_c_locale());
+ 	}
+ #else
+       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
+       const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
+       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
+       int __len = std::__convert_from_v(__cs, 0, "%.0Lf", __units,
+ 					_S_get_c_locale());
+ #endif
+       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
+ 							   * __cs_size));
+       __ctype.widen(__cs, __cs + __len, __ws);
+       const string_type __digits(__ws, __len);
+       return _M_insert(__s, __intl, __io, __fill, __digits);
+     }
+ 
+   template<typename _CharT, typename _OutIter>
+     _OutIter
+     money_put<_CharT, _OutIter>::
+     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
+ 	   const string_type& __digits) const
+     { return _M_insert(__s, __intl, __io, __fill, __digits); }
  
    // NB: Not especially useful. Without an ios_base object or some
    // kind of locale reference, we are left clawing at the air where

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]