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: [RFC] Doubts about digit grouping corner cases


Paolo Carlini wrote:

It seems to me that we could deal easily - and in a strictly conforming
way - with __sep_pos == 0 in __verify_grouping, thus simplifying the
Stage2 parsing loop.

For concreteness, the below is what I have in mind (+ the corresponding tweaks to a few testcases and a consistent change to money_get::do_get, which also uses __verify_grouping).

Paolo.

/////////////
diff -urN libstdc++-v3-orig/include/bits/locale_facets.tcc libstdc++-v3/include/bits/locale_facets.tcc
--- libstdc++-v3-orig/include/bits/locale_facets.tcc	2003-12-31 09:28:08.000000000 +0100
+++ libstdc++-v3/include/bits/locale_facets.tcc	2004-01-03 18:49:56.000000000 +0100
@@ -209,6 +209,7 @@
       string __found_grouping;
       int __sep_pos = 0;
       bool __e;
+      const char_type* __lit_zero = __lit + _S_izero;
       const char_type* __p;
       while (__beg != __end)
         {
@@ -220,19 +221,9 @@
 	    {
 	      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;
-		    }
+		  __found_grouping += static_cast<char>(__sep_pos);
+		  __sep_pos = 0;
+		  ++__beg;
 		}
 	      else
 		break;
@@ -253,7 +244,7 @@
 	      else
 		break;
 	    }
-          else if (__p = __traits_type::find(__lit + _S_izero, 10, __c))
+          else if (__p = __traits_type::find(__lit_zero, 10, __c))
 	    {
 	      __xtrc += _S_atoms_in[__p - __lit];
 	      __found_mantissa = true;
@@ -399,18 +390,8 @@
 		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.
-		    if (__sep_pos)
-		      {
-			__found_grouping += static_cast<char>(__sep_pos);
-			__sep_pos = 0;
-		      }
-		    else
-		      {
-			__err |= ios_base::failbit;
-			break;
-		      }
+		    __found_grouping += static_cast<char>(__sep_pos);
+		    __sep_pos = 0;
 		  }
 		else if (__traits_type::eq(__c, __lc->_M_decimal_point))
 		  break;
@@ -444,16 +425,8 @@
 		if (__lc->_M_use_grouping
 		    && __traits_type::eq(__c, __lc->_M_thousands_sep))
 		  {
-		    if (__sep_pos)
-		      {
-			__found_grouping += static_cast<char>(__sep_pos);
-			__sep_pos = 0;
-		      }
-		    else
-		      {
-			__err |= ios_base::failbit;
-			break;
-		      }
+		    __found_grouping += static_cast<char>(__sep_pos);
+		    __sep_pos = 0;
 		  }	
 		else if (__traits_type::eq(__c, __lc->_M_decimal_point))
 		  break;
@@ -1245,23 +1218,21 @@
 		  }
 		else if (__c == __d && !__testdecfound)
 		  {
-		    __grouping_tmp += static_cast<char>(__sep_pos);
+		    if (__grouping_tmp.size())
+		      __grouping_tmp += static_cast<char>(__sep_pos);
 		    __sep_pos = 0;
 		    __testdecfound = true;
 		  }
-		else if (__c == __sep)
+		else if (__grouping.size() && __c == __sep)
 		  {
-		    if (__grouping.size())
+		    if (!__testdecfound)
 		      {
 			// Mark position for later analysis.
 			__grouping_tmp += static_cast<char>(__sep_pos);
 			__sep_pos = 0;
 		      }
 		    else
-		      {
-			__testvalid = false;
-			break;
-		      }
+		      break;
 		  }
 		else
 		  break;
@@ -2286,7 +2257,8 @@
 	__test = __grouping_tmp[__i] == __grouping[__min];
       // ... but the last parsed grouping can be <= numpunct
       // grouping.
-      __test &= __grouping_tmp[0] <= __grouping[__min];
+      __test &= __grouping_tmp[0]
+	        && __grouping_tmp[0] <= __grouping[__min];
       return __test;
     }
 
diff -urN libstdc++-v3-orig/testsuite/22_locale/num_get/get/char/12.cc libstdc++-v3/testsuite/22_locale/num_get/get/char/12.cc
--- libstdc++-v3-orig/testsuite/22_locale/num_get/get/char/12.cc	2003-12-22 12:00:42.000000000 +0100
+++ libstdc++-v3/testsuite/22_locale/num_get/get/char/12.cc	2004-01-03 19:17:09.000000000 +0100
@@ -66,8 +66,7 @@
   iss1.str("+3");
   err = ios_base::goodbit;
   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
-  VERIFY( err == ios_base::failbit );
-  VERIFY( *end == '+' );
+  VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
 
   iss1.str("0x1");
   iss1.clear();
@@ -97,8 +96,7 @@
   iss1.clear();
   err = ios_base::goodbit;
   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
-  VERIFY( err == ios_base::failbit );
-  VERIFY( *end == '+' );
+  VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
 
   iss1.str("x4");
   iss1.clear();
@@ -126,8 +124,7 @@
   iss2.unsetf(ios::basefield);
   err = ios_base::goodbit;
   end = ng2.get(iss2.rdbuf(), 0, iss2, err, l);
-  VERIFY( err == ios_base::failbit );
-  VERIFY( *end == 'X' );
+  VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
 
   iss2.str("000778");
   iss2.clear();
@@ -141,8 +138,7 @@
   iss2.clear();
   err = ios_base::goodbit;
   end = ng2.get(iss2.rdbuf(), 0, iss2, err, d);
-  VERIFY( err == ios_base::failbit );
-  VERIFY( *end == 'X' );
+  VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
 
   iss2.str("-1");
   iss2.clear();
diff -urN libstdc++-v3-orig/testsuite/22_locale/num_get/get/wchar_t/12.cc libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/12.cc
--- libstdc++-v3-orig/testsuite/22_locale/num_get/get/wchar_t/12.cc	2003-12-22 12:00:42.000000000 +0100
+++ libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/12.cc	2004-01-03 19:28:44.000000000 +0100
@@ -66,8 +66,7 @@
   iss1.str(L"+3");
   err = ios_base::goodbit;
   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
-  VERIFY( err == ios_base::failbit );
-  VERIFY( *end == L'+' );
+  VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
 
   iss1.str(L"0x1");
   iss1.clear();
@@ -97,8 +96,7 @@
   iss1.clear();
   err = ios_base::goodbit;
   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
-  VERIFY( err == ios_base::failbit );
-  VERIFY( *end == L'+' );
+  VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
 
   iss1.str(L"x4");
   iss1.clear();
@@ -126,8 +124,7 @@
   iss2.unsetf(ios::basefield);
   err = ios_base::goodbit;
   end = ng2.get(iss2.rdbuf(), 0, iss2, err, l);
-  VERIFY( err == ios_base::failbit );
-  VERIFY( *end == L'X' );
+  VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
 
   iss2.str(L"000778");
   iss2.clear();
@@ -141,8 +138,7 @@
   iss2.clear();
   err = ios_base::goodbit;
   end = ng2.get(iss2.rdbuf(), 0, iss2, err, d);
-  VERIFY( err == ios_base::failbit );
-  VERIFY( *end == L'X' );
+  VERIFY( err == (ios_base::failbit | ios_base::eofbit) );
 
   iss2.str(L"-1");
   iss2.clear();
diff -urN libstdc++-v3-orig/testsuite/27_io/basic_istream/extractors_arithmetic/char/07.cc libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/char/07.cc
--- libstdc++-v3-orig/testsuite/27_io/basic_istream/extractors_arithmetic/char/07.cc	2003-09-23 22:03:06.000000000 +0200
+++ libstdc++-v3/testsuite/27_io/basic_istream/extractors_arithmetic/char/07.cc	2004-01-03 18:03:16.000000000 +0100
@@ -20,9 +20,7 @@
 
 // 27.6.1.2.2 arithmetic extractors
 
-#include <cstdio> // for printf
 #include <istream>
-#include <ostream>
 #include <sstream>
 #include <locale>
 #include <testsuite_hooks.h>
@@ -100,20 +98,11 @@
   VERIFY( h4 == 0 );
   VERIFY( static_cast<bool>(is.rdstate() & std::ios_base::failbit) );
   is.clear();
-  is >> c;
-  VERIFY( c == ',' );
-  VERIFY( is.good() );
 
-  is.ignore(3);
   is >> f1; 
   VERIFY( f1 == 0.0 );
   VERIFY( static_cast<bool>(is.rdstate() & std::ios_base::failbit) );
   is.clear();
-  is >> c;
-  VERIFY( c == ',' );
-  is >> c;
-  VERIFY( c == '4' );
-  VERIFY( is.good() );
 
   is >> f1; 
   VERIFY( f1 == 0.25 );
@@ -137,9 +126,6 @@
   VERIFY( h3 == 0 );
   VERIFY( static_cast<bool>(is.rdstate() & std::ios_base::failbit) );
   is.clear();
-  is >> c;
-  VERIFY( c == ',' ); // second one
-  VERIFY( is.good() );
 
   is >> h2; 
   VERIFY( h2 == 0 );

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