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] Last bits for Martin's issue


Hi,

if we want to be really *pedantic* (it costs nothing performance-wise
and the code isn't more complex) we have to look _first_  for
thousands_sep, then for decimal_point, *not* viceversa. My fault.

Also take the occasion to fix another corner case in _M_extract_float:
interestingly the fix makes the fast path... faster! ;) Anyway, more
important is the refined logic, useful when we'll try to replace the
code with something faster, avoiding strtod & co.

Tested x86-linux. Will commit tomorrow.

Paolo.

/////////////
2003-12-30  Paolo Carlini  <pcarlini@suse.de>

	* include/bits/locale_facets.tcc (num_get::_M_extract_int,
	num_get::_M_extract_float): According to 22.2.2.1.2, p8-9,
	_first_ look for thousands_sep, then for decimal_point and
	finally for digits.
	(num_get::_M_extract_float): After the decimal_point or
	'e'/'E', decimal_point and thousands_sep just break out the
	parsing loop.
	* testsuite/22_locale/num_get/get/char/11.cc: Add tests.
	* testsuite/22_locale/num_get/get/wchar_t/11.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	Mon Dec 22 12:00:43 2003
--- libstdc++-v3/include/bits/locale_facets.tcc	Tue Dec 23 16:31:29 2003
*************** namespace std
*** 212,250 ****
        const char_type* __p;
        while (__beg != __end)
          {
! 	  // According to 22.2.2.1.2, p8-9, first look for decimal_point
! 	  // and thousands_sep.
  	  const char_type __c = *__beg;
! 	  if (__traits_type::eq(__c, __lc->_M_decimal_point) 
! 	      && !__found_dec && !__found_sci)
  	    {
! 	      // According to the standard, if no grouping chars are seen,
! 	      // no grouping check is applied. Therefore __found_grouping
! 	      // must be adjusted only if __dec comes after some __sep.
! 	      if (__found_grouping.size())
! 		__found_grouping += static_cast<char>(__sep_pos);
! 	      __xtrc += '.';
! 	      __found_dec = true;
! 	      ++__beg;
! 	    }
!           else if (__lc->_M_use_grouping
! 		   && __traits_type::eq(__c, __lc->_M_thousands_sep)
! 		   && !__found_dec && !__found_sci)
! 	    {
!               // NB: Thousands separator at the beginning of a string
!               // is a no-no, as is two consecutive thousands separators.
!               if (__sep_pos)
!                 {
!                   __found_grouping += static_cast<char>(__sep_pos);
!                   __sep_pos = 0;
! 		  ++__beg;
!                 }
!               else
  		{
! 		  __err |= ios_base::failbit;
! 		  break;
  		}
              }
            else if (__p = __traits_type::find(__lit + _S_izero, 10, __c))
  	    {
  	      __xtrc += _S_atoms_in[__p - __lit];
--- 212,258 ----
        const char_type* __p;
        while (__beg != __end)
          {
! 	  // According to 22.2.2.1.2, p8-9, first look for thousands_sep
! 	  // and decimal_point.
  	  const char_type __c = *__beg;
!           if (__lc->_M_use_grouping
! 	      && __traits_type::eq(__c, __lc->_M_thousands_sep))
  	    {
! 	      if (!__found_dec && !__found_sci)
  		{
! 		  // NB: Thousands separator at the beginning of a string
! 		  // is a no-no, as is two consecutive thousands separators.
! 		  if (__sep_pos)
! 		    {
! 		      __found_grouping += static_cast<char>(__sep_pos);
! 		      __sep_pos = 0;
! 		      ++__beg;
! 		    }
! 		  else
! 		    {
! 		      __err |= ios_base::failbit;
! 		      break;
! 		    }
  		}
+ 	      else
+ 		break;
              }
+ 	  else if (__traits_type::eq(__c, __lc->_M_decimal_point))
+ 	    {
+ 	      if (!__found_dec && !__found_sci)
+ 		{
+ 		  // If no grouping chars are seen, no grouping check
+ 		  // is applied. Therefore __found_grouping is adjusted
+ 		  // only if decimal_point comes after some thousands_sep.
+ 		  if (__found_grouping.size())
+ 		    __found_grouping += static_cast<char>(__sep_pos);
+ 		  __xtrc += '.';
+ 		  __found_dec = true;
+ 		  ++__beg;
+ 		}
+ 	      else
+ 		break;
+ 	    }
            else if (__p = __traits_type::find(__lit + _S_izero, 10, __c))
  	    {
  	      __xtrc += _S_atoms_in[__p - __lit];
*************** namespace std
*** 385,397 ****
  	    const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
  	    for (; __beg != __end; ++__beg)
  	      {
! 		// According to 22.2.2.1.2, p8-9, first look for decimal_point
! 		// and thousands_sep.
! 		const char_type __c = *__beg;		
! 		if (__traits_type::eq(__c, __lc->_M_decimal_point))
! 		  break;
! 		else if (__lc->_M_use_grouping
! 			 && __traits_type::eq(__c, __lc->_M_thousands_sep))
  		  {
  		    // NB: Thousands separator at the beginning of a string
  		    // is a no-no, as is two consecutive thousands separators.
--- 393,403 ----
  	    const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
  	    for (; __beg != __end; ++__beg)
  	      {
! 		// According to 22.2.2.1.2, p8-9, first look for thousands_sep
! 		// and decimal_point.
! 		const char_type __c = *__beg;
! 		if (__lc->_M_use_grouping
! 		    && __traits_type::eq(__c, __lc->_M_thousands_sep))
  		  {
  		    // NB: Thousands separator at the beginning of a string
  		    // is a no-no, as is two consecutive thousands separators.
*************** namespace std
*** 406,411 ****
--- 412,419 ----
  			break;
  		      }
  		  }
+ 		else if (__traits_type::eq(__c, __lc->_M_decimal_point))
+ 		  break;
  		else if (__p = __traits_type::find(__lit_zero, __len, __c))
  		  {
  		    int __digit = __p - __lit_zero;
*************** namespace std
*** 432,442 ****
  	    const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
  	    for (; __beg != __end; ++__beg)
  	      {
! 		const char_type __c = *__beg;		
! 		if (__traits_type::eq(__c, __lc->_M_decimal_point))
! 		  break;
! 		else if (__lc->_M_use_grouping
! 			 && __traits_type::eq(__c, __lc->_M_thousands_sep))
  		  {
  		    if (__sep_pos)
  		      {
--- 440,448 ----
  	    const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
  	    for (; __beg != __end; ++__beg)
  	      {
! 		const char_type __c = *__beg;
! 		if (__lc->_M_use_grouping
! 		    && __traits_type::eq(__c, __lc->_M_thousands_sep))
  		  {
  		    if (__sep_pos)
  		      {
*************** namespace std
*** 448,454 ****
  			__err |= ios_base::failbit;
  			break;
  		      }
! 		  }
  		else if (__p = __traits_type::find(__lit_zero, __len, __c))
  		  {
  		    int __digit = __p - __lit_zero;
--- 454,462 ----
  			__err |= ios_base::failbit;
  			break;
  		      }
! 		  }	
! 		else if (__traits_type::eq(__c, __lc->_M_decimal_point))
! 		  break;
  		else if (__p = __traits_type::find(__lit_zero, __len, __c))
  		  {
  		    int __digit = __p - __lit_zero;
diff -prN libstdc++-v3-orig/testsuite/22_locale/num_get/get/char/11.cc libstdc++-v3/testsuite/22_locale/num_get/get/char/11.cc
*** libstdc++-v3-orig/testsuite/22_locale/num_get/get/char/11.cc	Mon Dec 22 12:00:42 2003
--- libstdc++-v3/testsuite/22_locale/num_get/get/char/11.cc	Tue Dec 23 18:20:15 2003
***************
*** 22,34 ****
  #include <sstream>
  #include <testsuite_hooks.h>
  
! struct Punct: std::numpunct<char>
  {
    std::string do_grouping() const { return "\1"; }
    char do_thousands_sep() const { return '2'; }
    char do_decimal_point() const { return '4'; }
  };
  
  // http://gcc.gnu.org/ml/libstdc++/2003-12/msg00201.html
  void test01()
  {
--- 22,41 ----
  #include <sstream>
  #include <testsuite_hooks.h>
  
! struct Punct1: std::numpunct<char>
  {
    std::string do_grouping() const { return "\1"; }
    char do_thousands_sep() const { return '2'; }
    char do_decimal_point() const { return '4'; }
  };
  
+ struct Punct2: std::numpunct<char>
+ {
+   std::string do_grouping() const { return "\1"; }
+   char do_thousands_sep() const { return '2'; }
+   char do_decimal_point() const { return '2'; }
+ };
+ 
  // http://gcc.gnu.org/ml/libstdc++/2003-12/msg00201.html
  void test01()
  {
*************** void test01()
*** 37,66 ****
    
    bool test __attribute__((unused)) = true;
  
!   istringstream iss;
!   iss.imbue(locale(iss.getloc(), static_cast<numpunct<char>*>(new Punct)));
!   const num_get<char>& ng = use_facet<num_get<char> >(iss.getloc()); 
    ios_base::iostate err = ios_base::goodbit;
    iterator_type end;
    double d = 0.0;
    double d1 = 13.0;
    long l = 0l;
    long l1 = 13l;
    
!   iss.str("1234");
    err = ios_base::goodbit;
!   end = ng.get(iss.rdbuf(), 0, iss, err, d);
    VERIFY( err == ios_base::eofbit );
    VERIFY( d == d1 );
  
!   iss.str("1234");
!   iss.clear();
    err = ios_base::goodbit;
!   end = ng.get(iss.rdbuf(), 0, iss, err, l);
    VERIFY( err == ios_base::goodbit );
    VERIFY( l == l1 );
- }
  
  
  int main()
  {
--- 44,105 ----
    
    bool test __attribute__((unused)) = true;
  
!   istringstream iss1, iss2;
!   iss1.imbue(locale(iss1.getloc(), static_cast<numpunct<char>*>(new Punct1)));
!   iss2.imbue(locale(iss2.getloc(), static_cast<numpunct<char>*>(new Punct2)));
!   const num_get<char>& ng1 = use_facet<num_get<char> >(iss1.getloc()); 
!   const num_get<char>& ng2 = use_facet<num_get<char> >(iss2.getloc()); 
! 
    ios_base::iostate err = ios_base::goodbit;
    iterator_type end;
    double d = 0.0;
    double d1 = 13.0;
+   double d2 = 1.0;
+   double d3 = 30.0;
    long l = 0l;
    long l1 = 13l;
+   long l2 = 10l;
    
!   iss1.str("1234");
    err = ios_base::goodbit;
!   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
    VERIFY( err == ios_base::eofbit );
    VERIFY( d == d1 );
  
!   iss1.str("142");
!   iss1.clear();
!   err = ios_base::goodbit;
!   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
!   VERIFY( err == ios_base::goodbit );
!   VERIFY( d == d2 );
! 
!   iss1.str("3e14");
!   iss1.clear();
!   err = ios_base::goodbit;
!   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
!   VERIFY( err == ios_base::goodbit );
!   VERIFY( d == d3 );
! 
!   iss1.str("1234");
!   iss1.clear();
    err = ios_base::goodbit;
!   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
    VERIFY( err == ios_base::goodbit );
    VERIFY( l == l1 );
  
+   iss2.str("123");
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, d);
+   VERIFY( err == ios_base::eofbit );
+   VERIFY( d == d1 );
+ 
+   iss2.str("120");
+   iss2.clear();
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, l);
+   VERIFY( err == ios_base::eofbit );
+   VERIFY( l == l2 );
+ }
  
  int main()
  {
diff -prN libstdc++-v3-orig/testsuite/22_locale/num_get/get/wchar_t/11.cc libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/11.cc
*** libstdc++-v3-orig/testsuite/22_locale/num_get/get/wchar_t/11.cc	Mon Dec 22 12:00:42 2003
--- libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/11.cc	Tue Dec 23 18:20:05 2003
***************
*** 22,34 ****
  #include <sstream>
  #include <testsuite_hooks.h>
  
! struct Punct: std::numpunct<wchar_t>
  {
    std::string do_grouping() const { return "\1"; }
    wchar_t do_thousands_sep() const { return L'2'; }
    wchar_t do_decimal_point() const { return L'4'; }
  };
  
  // http://gcc.gnu.org/ml/libstdc++/2003-12/msg00201.html
  void test01()
  {
--- 22,41 ----
  #include <sstream>
  #include <testsuite_hooks.h>
  
! struct Punct1: std::numpunct<wchar_t>
  {
    std::string do_grouping() const { return "\1"; }
    wchar_t do_thousands_sep() const { return L'2'; }
    wchar_t do_decimal_point() const { return L'4'; }
  };
  
+ struct Punct2: std::numpunct<wchar_t>
+ {
+   std::string do_grouping() const { return "\1"; }
+   wchar_t do_thousands_sep() const { return L'2'; }
+   wchar_t do_decimal_point() const { return L'2'; }
+ };
+ 
  // http://gcc.gnu.org/ml/libstdc++/2003-12/msg00201.html
  void test01()
  {
*************** void test01()
*** 37,66 ****
    
    bool test __attribute__((unused)) = true;
  
!   wistringstream iss;
!   iss.imbue(locale(iss.getloc(), static_cast<numpunct<wchar_t>*>(new Punct)));
!   const num_get<wchar_t>& ng = use_facet<num_get<wchar_t> >(iss.getloc()); 
    ios_base::iostate err = ios_base::goodbit;
    iterator_type end;
    double d = 0.0;
    double d1 = 13.0;
    long l = 0l;
    long l1 = 13l;
    
!   iss.str(L"1234");
    err = ios_base::goodbit;
!   end = ng.get(iss.rdbuf(), 0, iss, err, d);
    VERIFY( err == ios_base::eofbit );
    VERIFY( d == d1 );
  
!   iss.str(L"1234");
!   iss.clear();
    err = ios_base::goodbit;
!   end = ng.get(iss.rdbuf(), 0, iss, err, l);
    VERIFY( err == ios_base::goodbit );
    VERIFY( l == l1 );
- }
  
  
  int main()
  {
--- 44,105 ----
    
    bool test __attribute__((unused)) = true;
  
!   wistringstream iss1, iss2;
!   iss1.imbue(locale(iss1.getloc(), static_cast<numpunct<wchar_t>*>(new Punct1)));
!   iss2.imbue(locale(iss2.getloc(), static_cast<numpunct<wchar_t>*>(new Punct2)));
!   const num_get<wchar_t>& ng1 = use_facet<num_get<wchar_t> >(iss1.getloc()); 
!   const num_get<wchar_t>& ng2 = use_facet<num_get<wchar_t> >(iss2.getloc()); 
! 
    ios_base::iostate err = ios_base::goodbit;
    iterator_type end;
    double d = 0.0;
    double d1 = 13.0;
+   double d2 = 1.0;
+   double d3 = 30.0;
    long l = 0l;
    long l1 = 13l;
+   long l2 = 10l;
    
!   iss1.str(L"1234");
    err = ios_base::goodbit;
!   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
    VERIFY( err == ios_base::eofbit );
    VERIFY( d == d1 );
  
!   iss1.str(L"142");
!   iss1.clear();
!   err = ios_base::goodbit;
!   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
!   VERIFY( err == ios_base::goodbit );
!   VERIFY( d == d2 );
! 
!   iss1.str(L"3e14");
!   iss1.clear();
!   err = ios_base::goodbit;
!   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
!   VERIFY( err == ios_base::goodbit );
!   VERIFY( d == d3 );
! 
!   iss1.str(L"1234");
!   iss1.clear();
    err = ios_base::goodbit;
!   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
    VERIFY( err == ios_base::goodbit );
    VERIFY( l == l1 );
  
+   iss2.str(L"123");
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, d);
+   VERIFY( err == ios_base::eofbit );
+   VERIFY( d == d1 );
+ 
+   iss2.str(L"120");
+   iss2.clear();
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, l);
+   VERIFY( err == ios_base::eofbit );
+   VERIFY( l == l2 );
+ }
  
  int main()
  {

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