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]

[Patch] Fix libstdc++/20914


Hi!

The below is the best fix I have for this annoying issue. It's nice that
actually fixing it this way (i.e., as already discussed: prepend 
numeric base or sign *after* the grouping) allows for quite a bit of
clean up elsewhere.

I believe the ChangeLog entry and the code are sufficiently clear,
please let me know if something doesn't convince you, otherwise I'm
going to test it a bit more and probably apply tomorrow (and rather
soon, after the release, to 4_0-branch too).

Tested x86-linux.

Paolo.

////////////////
2005-04-17  Paolo Carlini  <pcarlini@suse.de>

	PR libstdc++/20914
	* include/bits/locale_facets.tcc (__int_to_char(_CharT*, _ValueT,
	const _CharT*, ios_base::fmtflags, bool)): Don't deal with numeric
	base or sign here, instead...
	(_M_insert_int(_OutIter, ios_base&, _CharT, _ValueT)): ... here,
	after adding the grouping. This fixes the bug and also allows to
	clean-up the code dealing with integer types.
	(_M_group_int(const char*, size_t, _CharT, ios_base&, _CharT*,
	_CharT*, int&)): Simplify, remove bits dealing with numeric base.
	(__int_to_char(_CharT*, unsigned long, const _CharT*,
	ios_base::fmtflags), __int_to_char(_CharT*, unsigned long long,
	const _CharT*, ios_base::fmtflags)): Remove hackish fix for
	libstdc++/15565.
	(__int_to_char(_CharT*, long, const _CharT*, ios_base::fmtflags),
	__int_to_char(_CharT*, long long, const _CharT*, ios_base::fmtflags)):
	Simplify, don't pass the sign.
	(_M_insert_float(_OutIter, ios_base&, _CharT, char, _ValueT)):
	Deal with a sign at the beginning of __cs; robustify the grouping	
	check.
	* testsuite/22_locale/num_put/put/char/20914.cc: New.
	* testsuite/22_locale/num_put/put/wchar_t/20914.cc: Likewise.
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	Sat Apr  9 02:08:56 2005
--- libstdc++-v3/include/bits/locale_facets.tcc	Sat Apr 16 15:43:40 2005
***************
*** 1,6 ****
  // Locale support -*- C++ -*-
  
! // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
  // Free Software Foundation, Inc.
  //
  // This file is part of the GNU ISO C++ Library.  This library is free
--- 1,6 ----
  // Locale support -*- C++ -*-
  
! // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
  // Free Software Foundation, Inc.
  //
  // This file is part of the GNU ISO C++ Library.  This library is free
*************** namespace std
*** 853,876 ****
  		  ios_base::fmtflags __flags)
      {
        unsigned long __ul = static_cast<unsigned long>(__v);
-       bool __neg = false;
        if (__v < 0)
! 	{
! 	  __ul = -__ul;
! 	  __neg = true;
! 	}
!       return __int_to_char(__bufend, __ul, __lit, __flags, __neg);
      }
  
    template<typename _CharT>
      inline int
      __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
  		  ios_base::fmtflags __flags)
!     {
!       // About showpos, see Table 60 and C99 7.19.6.1, p6 (+).
!       return __int_to_char(__bufend, __v, __lit,
! 			   __flags & ~ios_base::showpos, false);
!     }
  
  #ifdef _GLIBCXX_USE_LONG_LONG
    template<typename _CharT>
--- 853,868 ----
  		  ios_base::fmtflags __flags)
      {
        unsigned long __ul = static_cast<unsigned long>(__v);
        if (__v < 0)
! 	__ul = -__ul;
!       return __int_to_char(__bufend, __ul, __lit, __flags, false);
      }
  
    template<typename _CharT>
      inline int
      __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
  		  ios_base::fmtflags __flags)
!     { return __int_to_char(__bufend, __v, __lit, __flags, false); }
  
  #ifdef _GLIBCXX_USE_LONG_LONG
    template<typename _CharT>
*************** namespace std
*** 879,937 ****
  		  ios_base::fmtflags __flags)
      {
        unsigned long long __ull = static_cast<unsigned long long>(__v);
-       bool __neg = false;
        if (__v < 0)
! 	{
! 	  __ull = -__ull;
! 	  __neg = true;
! 	}
!       return __int_to_char(__bufend, __ull, __lit, __flags, __neg);
      }
  
    template<typename _CharT>
      inline int
      __int_to_char(_CharT* __bufend, unsigned long long __v, 
  		  const _CharT* __lit, ios_base::fmtflags __flags)
!     { return __int_to_char(__bufend, __v, __lit,
! 			   __flags & ~ios_base::showpos, false); }
  #endif
  
    template<typename _CharT, typename _ValueT>
      int
      __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
! 		  ios_base::fmtflags __flags, bool __neg)
      {
-       // Don't write base if already 0.
-       const bool __showbase = (__flags & ios_base::showbase) && __v;
        const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
!       _CharT* __buf = __bufend - 1;
  
!       if (__builtin_expect(__basefield != ios_base::oct &&
! 			   __basefield != ios_base::hex, true))
  	{
  	  // Decimal.
  	  do
  	    {
! 	      *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits];
  	      __v /= 10;
  	    }
  	  while (__v != 0);
- 	  if (__neg)
- 	    *__buf-- = __lit[__num_base::_S_ominus];
- 	  else if (__flags & ios_base::showpos)
- 	    *__buf-- = __lit[__num_base::_S_oplus];
  	}
        else if (__basefield == ios_base::oct)
  	{
  	  // Octal.
  	  do
  	    {
! 	      *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits];
  	      __v >>= 3;
  	    }
  	  while (__v != 0);
- 	  if (__showbase)
- 	    *__buf-- = __lit[__num_base::_S_odigits];
  	}
        else
  	{
--- 871,917 ----
  		  ios_base::fmtflags __flags)
      {
        unsigned long long __ull = static_cast<unsigned long long>(__v);
        if (__v < 0)
! 	__ull = -__ull;
!       return __int_to_char(__bufend, __ull, __lit, __flags, false);
      }
  
    template<typename _CharT>
      inline int
      __int_to_char(_CharT* __bufend, unsigned long long __v, 
  		  const _CharT* __lit, ios_base::fmtflags __flags)
!     { return __int_to_char(__bufend, __v, __lit, __flags, false); }
  #endif
  
+   // N.B. The last argument is currently unused (see libstdc++/20914).
    template<typename _CharT, typename _ValueT>
      int
      __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
! 		  ios_base::fmtflags __flags, bool)
      {
        const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
!       _CharT* __buf = __bufend;
  
!       if (__builtin_expect(__basefield != ios_base::oct
! 			   && __basefield != ios_base::hex, true))
  	{
  	  // Decimal.
  	  do
  	    {
! 	      *--__buf = __lit[(__v % 10) + __num_base::_S_odigits];
  	      __v /= 10;
  	    }
  	  while (__v != 0);
  	}
        else if (__basefield == ios_base::oct)
  	{
  	  // Octal.
  	  do
  	    {
! 	      *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits];
  	      __v >>= 3;
  	    }
  	  while (__v != 0);
  	}
        else
  	{
*************** namespace std
*** 941,993 ****
  	                                        : __num_base::_S_odigits;
  	  do
  	    {
! 	      *__buf-- = __lit[(__v & 0xf) + __case_offset];
  	      __v >>= 4;
  	    }
  	  while (__v != 0);
- 	  if (__showbase)
- 	    {
- 	      // 'x' or 'X'
- 	      *__buf-- = __lit[__num_base::_S_ox + __uppercase];
- 	      // '0'
- 	      *__buf-- = __lit[__num_base::_S_odigits];
- 	    }
  	}
!       return __bufend - __buf - 1;
      }
  
    template<typename _CharT, typename _OutIter>
      void
      num_put<_CharT, _OutIter>::
      _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
! 		 ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const
      {
!       // By itself __add_grouping cannot deal correctly with __cs when
!       // ios::showbase is set and ios_base::oct || ios_base::hex.
!       // Therefore we take care "by hand" of the initial 0, 0x or 0X.
!       // However, remember that the latter do not occur if the number
!       // printed is '0' (__len == 1).
!       streamsize __off = 0;
!       const ios_base::fmtflags __basefield = __io.flags()
! 	                                     & ios_base::basefield;
!       if ((__io.flags() & ios_base::showbase) && __len > 1)
! 	if (__basefield == ios_base::oct)
! 	  {
! 	    __off = 1;
! 	    __new[0] = __cs[0];
! 	  }
! 	else if (__basefield == ios_base::hex)
! 	  {
! 	    __off = 2;
! 	    __new[0] = __cs[0];
! 	    __new[1] = __cs[1];
! 	  }
!       _CharT* __p = std::__add_grouping(__new + __off, __sep, __grouping,
! 					__grouping_size, __cs + __off,
! 					__cs + __len);
        __len = __p - __new;
      }
! 
    template<typename _CharT, typename _OutIter>
      template<typename _ValueT>
        _OutIter
--- 921,945 ----
  	                                        : __num_base::_S_odigits;
  	  do
  	    {
! 	      *--__buf = __lit[(__v & 0xf) + __case_offset];
  	      __v >>= 4;
  	    }
  	  while (__v != 0);
  	}
!       return __bufend - __buf;
      }
  
    template<typename _CharT, typename _OutIter>
      void
      num_put<_CharT, _OutIter>::
      _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
! 		 ios_base&, _CharT* __new, _CharT* __cs, int& __len) const
      {
!       _CharT* __p = std::__add_grouping(__new, __sep, __grouping,
! 					__grouping_size, __cs, __cs + __len);
        __len = __p - __new;
      }
!   
    template<typename _CharT, typename _OutIter>
      template<typename _ValueT>
        _OutIter
*************** namespace std
*** 1000,1027 ****
  	const locale& __loc = __io._M_getloc();
  	const __cache_type* __lc = __uc(__loc);
  	const _CharT* __lit = __lc->_M_atoms_out;
  
  	// Long enough to hold hex, dec, and octal representations.
! 	const int __ilen = 4 * sizeof(_ValueT);
  	_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
  							     * __ilen));
  
  	// [22.2.2.2.2] Stage 1, numeric conversion to character.
  	// Result is returned right-justified in the buffer.
  	int __len;
! 	__len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags());
  	__cs += __ilen - __len;
  
  	// Add grouping, if necessary.
  	if (__lc->_M_use_grouping)
  	  {
! 	    // Grouping can add (almost) as many separators as the
! 	    // number of digits, but no more.
  	    _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
! 								  * __len * 2));
  	    _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
! 			 __lc->_M_thousands_sep, __io, __cs2, __cs, __len);
! 	    __cs = __cs2;
  	  }
  
  	// Pad.
--- 952,1016 ----
  	const locale& __loc = __io._M_getloc();
  	const __cache_type* __lc = __uc(__loc);
  	const _CharT* __lit = __lc->_M_atoms_out;
+ 	const ios_base::fmtflags __flags = __io.flags();
  
  	// Long enough to hold hex, dec, and octal representations.
! 	const int __ilen = 5 * sizeof(_ValueT);
  	_CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
  							     * __ilen));
  
  	// [22.2.2.2.2] Stage 1, numeric conversion to character.
  	// Result is returned right-justified in the buffer.
  	int __len;
! 	__len = __int_to_char(__cs + __ilen, __v, __lit, __flags);
  	__cs += __ilen - __len;
  
  	// Add grouping, if necessary.
  	if (__lc->_M_use_grouping)
  	  {
! 	    // Grouping can add (almost) as many separators as the number
! 	    // of digits + space is reserved for numeric base or sign.
  	    _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
! 								  * (__len + 1)
! 								  * 2));
  	    _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
! 			 __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len);
! 	    __cs = __cs2 + 2;
! 	  }
! 
! 	// Complete Stage 1, prepend numeric base or sign.
! 	const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
! 	if (__builtin_expect(__basefield != ios_base::oct
! 			     && __basefield != ios_base::hex, true))
! 	  {
! 	    // Decimal.
! 	    if (__v > 0)
! 	      {
! 		if (__flags & ios_base::showpos
! 		    && numeric_limits<_ValueT>::is_signed)
! 		  *--__cs = __lit[__num_base::_S_oplus], ++__len;
! 	      }
! 	    else if (__v)
! 	      *--__cs = __lit[__num_base::_S_ominus], ++__len;
! 	  }
! 	else if (__basefield == ios_base::oct)
! 	  {
! 	    // Octal.
! 	    if (__flags & ios_base::showbase && __v)
! 	      *--__cs = __lit[__num_base::_S_odigits], ++__len;
! 	  }
! 	else
! 	  {
! 	    // Hex.
! 	    if (__flags & ios_base::showbase && __v)
! 	      {
! 		// 'x' or 'X'
! 		const bool __uppercase = __flags & ios_base::uppercase;
! 		*--__cs = __lit[__num_base::_S_ox + __uppercase];
! 		// '0'
! 		*--__cs = __lit[__num_base::_S_odigits];
! 		__len += 2;
! 	      }
  	  }
  
  	// Pad.
*************** namespace std
*** 1137,1189 ****
  				      _S_get_c_locale(), __prec);
  #endif
  
!       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
!       // numpunct.decimal_point() values for '.' and adding grouping.
!       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
! 
!       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
! 							   * __len));
!       __ctype.widen(__cs, __cs + __len, __ws);
! 
!       // Replace decimal point.
!       const _CharT __cdec = __ctype.widen('.');
!       const _CharT __dec = __lc->_M_decimal_point;
!       const _CharT* __p = char_traits<_CharT>::find(__ws, __len, __cdec);
!       if (__p)
! 	__ws[__p - __ws] = __dec;
! 
!       // Add grouping, if necessary.
!       // N.B. Make sure to not group things like 2e20, i.e., no decimal
!       // point, scientific notation.
!       if (__lc->_M_use_grouping
! 	  && (__p || __len < 3 || (__cs[1] != 'e' && __cs[2] != 'e'
! 				   && __cs[1] != 'E' && __cs[2] != 'E')))
! 	{
! 	  // Grouping can add (almost) as many separators as the
! 	  // number of digits, but no more.
! 	  _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
! 								* __len * 2));
! 	  _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
! 			 __lc->_M_thousands_sep, __p, __ws2, __ws, __len);
! 	  __ws = __ws2;
! 	}
! 
!       // Pad.
!       const streamsize __w = __io.width();
!       if (__w > static_cast<streamsize>(__len))
! 	{
! 	  _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
! 								* __w));
! 	  _M_pad(__fill, __w, __io, __ws3, __ws, __len);
! 	  __ws = __ws3;
! 	}
!       __io.width(0);
  
!       // [22.2.2.2.2] Stage 4.
!       // Write resulting, fully-formatted string to output iterator.
!       return std::__write(__s, __ws, __len);
        }
! 
    template<typename _CharT, typename _OutIter>
      _OutIter
      num_put<_CharT, _OutIter>::
--- 1126,1190 ----
  				      _S_get_c_locale(), __prec);
  #endif
  
! 	// [22.2.2.2.2] Stage 2, convert to char_type, using correct
! 	// numpunct.decimal_point() values for '.' and adding grouping.
! 	const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
! 	
! 	_CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
! 							     * __len));
! 	__ctype.widen(__cs, __cs + __len, __ws);
! 	
! 	// Replace decimal point.
! 	const _CharT __cdec = __ctype.widen('.');
! 	const _CharT __dec = __lc->_M_decimal_point;
! 	const _CharT* __p = char_traits<_CharT>::find(__ws, __len, __cdec);
! 	if (__p)
! 	  __ws[__p - __ws] = __dec;
! 	
! 	// Add grouping, if necessary.
! 	// N.B. Make sure to not group things like 2e20, i.e., no decimal
! 	// point, scientific notation.
! 	if (__lc->_M_use_grouping
! 	    && (__p || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9'
! 				     && __cs[1] >= '0' && __cs[2] >= '0')))
! 	  {
! 	    // Grouping can add (almost) as many separators as the
! 	    // number of digits, but no more.
! 	    _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
! 								  * __len * 2));
! 	    
! 	    streamsize __off = 0;
! 	    if (__cs[0] == '-' || __cs[0] == '+')
! 	      {
! 		__off = 1;
! 		__ws2[0] = __ws[0];
! 		__len -= 1;
! 	      }
! 	    
! 	    _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
! 			   __lc->_M_thousands_sep, __p, __ws2 + __off,
! 			   __ws + __off, __len);
! 	    __len += __off;
! 	    
! 	    __ws = __ws2;
! 	  }
  
! 	// Pad.
! 	const streamsize __w = __io.width();
! 	if (__w > static_cast<streamsize>(__len))
! 	  {
! 	    _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
! 								  * __w));
! 	    _M_pad(__fill, __w, __io, __ws3, __ws, __len);
! 	    __ws = __ws3;
! 	  }
! 	__io.width(0);
! 	
! 	// [22.2.2.2.2] Stage 4.
! 	// Write resulting, fully-formatted string to output iterator.
! 	return std::__write(__s, __ws, __len);
        }
!   
    template<typename _CharT, typename _OutIter>
      _OutIter
      num_put<_CharT, _OutIter>::
diff -prN libstdc++-v3-orig/testsuite/22_locale/num_put/put/char/20914.cc libstdc++-v3/testsuite/22_locale/num_put/put/char/20914.cc
*** libstdc++-v3-orig/testsuite/22_locale/num_put/put/char/20914.cc	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/22_locale/num_put/put/char/20914.cc	Sat Apr 16 10:24:21 2005
***************
*** 0 ****
--- 1,79 ----
+ // 2005-04-17  Paolo Carlini  <pcarlini@suse.de>
+ 
+ // Copyright (C) 2005 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
+ // 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.
+ 
+ // 22.2.2.2.1  num_put members
+ 
+ #include <locale>
+ #include <sstream>
+ #include <testsuite_hooks.h>
+ 
+ // libstdc++/20914
+ void test01()
+ {
+   using namespace std;
+   bool test __attribute__((unused)) = true;
+ 
+   // A locale that expects grouping.
+   locale loc_de = __gnu_test::try_named_locale("de_DE");
+ 
+   const string empty;
+   string result;
+ 
+   ostringstream oss;
+   oss.imbue(loc_de);
+   const num_put<char>& np = use_facet<num_put<char> >(oss.getloc()); 
+ 
+   long l0 = -300000;
+   long l1 = 300;
+   double d0 = -300000;
+   double d1 = 300;
+ 
+   oss.str(empty);
+   oss.clear();
+   np.put(oss.rdbuf(), oss, '*', l0);
+   result = oss.str();
+   VERIFY( result == "-300.000" );
+ 
+   oss.str(empty);
+   oss.clear();
+   np.put(oss.rdbuf(), oss, '*', d0);
+   result = oss.str();
+   VERIFY( result == "-300.000" );
+ 
+   oss.str(empty);
+   oss.clear();
+   oss.setf(ios::showpos);
+   np.put(oss.rdbuf(), oss, '*', l1);
+   result = oss.str();
+   VERIFY( result == "+300" );
+ 
+   oss.str(empty);
+   oss.clear();
+   oss.setf(ios::showpos);
+   np.put(oss.rdbuf(), oss, '*', d1);
+   result = oss.str();
+   VERIFY( result == "+300" );
+ }
+ 
+ int main()
+ {
+   test01();
+   return 0;
+ }
diff -prN libstdc++-v3-orig/testsuite/22_locale/num_put/put/wchar_t/20914.cc libstdc++-v3/testsuite/22_locale/num_put/put/wchar_t/20914.cc
*** libstdc++-v3-orig/testsuite/22_locale/num_put/put/wchar_t/20914.cc	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/22_locale/num_put/put/wchar_t/20914.cc	Sat Apr 16 10:24:21 2005
***************
*** 0 ****
--- 1,79 ----
+ // 2005-04-17  Paolo Carlini  <pcarlini@suse.de>
+ 
+ // Copyright (C) 2005 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
+ // 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.
+ 
+ // 22.2.2.2.1  num_put members
+ 
+ #include <locale>
+ #include <sstream>
+ #include <testsuite_hooks.h>
+ 
+ // libstdc++/20914
+ void test01()
+ {
+   using namespace std;
+   bool test __attribute__((unused)) = true;
+ 
+   // A locale that expects grouping.
+   locale loc_de = __gnu_test::try_named_locale("de_DE");
+ 
+   const wstring empty;
+   wstring result;
+ 
+   wostringstream oss;
+   oss.imbue(loc_de);
+   const num_put<wchar_t>& np = use_facet<num_put<wchar_t> >(oss.getloc()); 
+ 
+   long l0 = -300000;
+   long l1 = 300;
+   double d0 = -300000;
+   double d1 = 300;
+ 
+   oss.str(empty);
+   oss.clear();
+   np.put(oss.rdbuf(), oss, L'*', l0);
+   result = oss.str();
+   VERIFY( result == L"-300.000" );
+ 
+   oss.str(empty);
+   oss.clear();
+   np.put(oss.rdbuf(), oss, L'*', d0);
+   result = oss.str();
+   VERIFY( result == L"-300.000" );
+ 
+   oss.str(empty);
+   oss.clear();
+   oss.setf(ios::showpos);
+   np.put(oss.rdbuf(), oss, L'*', l1);
+   result = oss.str();
+   VERIFY( result == L"+300" );
+ 
+   oss.str(empty);
+   oss.clear();
+   oss.setf(ios::showpos);
+   np.put(oss.rdbuf(), oss, L'*', d1);
+   result = oss.str();
+   VERIFY( result == L"+300" );
+ }
+ 
+ int main()
+ {
+   test01();
+   return 0;
+ }

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