This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

[v3] Some work on the locale facets


Hi,

I'm committing to mainline the below, tested x86-linux.

Paolo.

//////////////
2004-03-01  Paolo Carlini  <pcarlini@suse.de>

	* include/bits/locale_facets.tcc (num_get<>::_M_extract_float):
	Also when parsing exponent sign, first look for thousands_sep
	and decimal_point; tweak a bit.
	* testsuite/22_locale/num_get/get/char/15.cc: New.
	* testsuite/22_locale/num_get/get/wchar_t/15.cc: New.
	
	* include/bits/locale_facets.tcc (num_get<>::_M_extract_float,
	num_get<>::_M_extract_int): Reorder some conditionals.
2004-03-01  Paolo Carlini  <pcarlini@suse.de>

	* include/bits/locale_facets.tcc (money_get<>::_M_extract):
	Consistently with numpunct, enforce the requirements in
	22.2.6.3, p3 for the thousands separators; tweak a bit.
	* testsuite/22_locale/money_get/get/char/15.cc: New.
	* testsuite/22_locale/money_get/get/wchar_t/15.cc: New.
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	2004-02-28 21:10:08.000000000 +0100
+++ libstdc++-v3/include/bits/locale_facets.tcc	2004-03-01 10:53:04.000000000 +0100
@@ -184,9 +184,9 @@
 	  const char_type __c = *__beg;
 	  const bool __plus = __traits_type::eq(__c, __lit[_S_iplus]);
 	  if ((__plus || __traits_type::eq(__c, __lit[_S_iminus]))
-	      && !__traits_type::eq(__c, __lc->_M_decimal_point)
 	      && (!__lc->_M_use_grouping
-		  || !__traits_type::eq(__c, __lc->_M_thousands_sep)))
+		  || !__traits_type::eq(__c, __lc->_M_thousands_sep))
+	      && !__traits_type::eq(__c, __lc->_M_decimal_point))
 	    {
 	      __xtrc += __plus ? '+' : '-';
 	      ++__beg;
@@ -197,9 +197,9 @@
       while (__beg != __end)
 	{
 	  const char_type __c = *__beg;
-	  if (__traits_type::eq(__c, __lc->_M_decimal_point)
-	      || (__lc->_M_use_grouping
-		  && __traits_type::eq(__c, __lc->_M_thousands_sep)))
+	  if (__lc->_M_use_grouping
+	      && __traits_type::eq(__c, __lc->_M_thousands_sep)
+	      || __traits_type::eq(__c, __lc->_M_decimal_point))
 	    break;
 	  else if (__traits_type::eq(__c, __lit[_S_izero]))
 	    {
@@ -221,7 +221,6 @@
       if (__lc->_M_use_grouping)
 	__found_grouping.reserve(32);
       int __sep_pos = 0;
-      bool __e;
       const char_type* __lit_zero = __lit + _S_izero;
       const char_type* __q;
       while (__beg != __end)
@@ -274,14 +273,14 @@
 	      ++__sep_pos;
 	      ++__beg;
 	    }
-	  else if ((__e = __traits_type::eq(__c, __lit[_S_ie])
+	  else if ((__traits_type::eq(__c, __lit[_S_ie])
 		    || __traits_type::eq(__c, __lit[_S_iE]))
 		   && __found_mantissa && !__found_sci)
 	    {
 	      // Scientific notation.
 	      if (__found_grouping.size() && !__found_dec)
 		__found_grouping += static_cast<char>(__sep_pos);
-	      __xtrc += __e ? 'e' : 'E';
+	      __xtrc += 'e';
 	      __found_sci = true;
 
 	      // Remove optional plus or minus sign, if they exist.
@@ -289,7 +288,10 @@
 		{
 		  const bool __plus = __traits_type::eq(*__beg,
 							__lit[_S_iplus]);
-		  if (__plus || __traits_type::eq(*__beg, __lit[_S_iminus]))
+		  if ((__plus || __traits_type::eq(*__beg, __lit[_S_iminus]))
+		      && (!__lc->_M_use_grouping
+			  || !__traits_type::eq(*__beg, __lc->_M_thousands_sep))
+		      && !__traits_type::eq(*__beg, __lc->_M_decimal_point))
 		    {
 		      __xtrc += __plus ? '+' : '-';
 		      ++__beg;
@@ -351,9 +353,9 @@
 	    if (numeric_limits<_ValueT>::is_signed)
 	      __negative = __traits_type::eq(__c, __lit[_S_iminus]);
 	    if ((__negative || __traits_type::eq(__c, __lit[_S_iplus]))
-		&& !__traits_type::eq(__c, __lc->_M_decimal_point)
 		&& (!__lc->_M_use_grouping
-		    || !__traits_type::eq(__c, __lc->_M_thousands_sep)))
+		    || !__traits_type::eq(__c, __lc->_M_thousands_sep))
+		&& !__traits_type::eq(__c, __lc->_M_decimal_point))
 	      ++__beg;
 	  }
 
@@ -362,9 +364,9 @@
 	while (__beg != __end)
 	  {
 	    const char_type __c = *__beg;
-	    if (__traits_type::eq(__c, __lc->_M_decimal_point)
-		|| (__lc->_M_use_grouping
-		    && __traits_type::eq(__c, __lc->_M_thousands_sep)))
+	    if (__lc->_M_use_grouping
+		&& __traits_type::eq(__c, __lc->_M_thousands_sep)
+		|| __traits_type::eq(__c, __lc->_M_decimal_point))
 	      break;
 	    else if (__traits_type::eq(__c, __lit[_S_izero])
 		     && (!__found_num || __base == 10))
@@ -1201,8 +1203,10 @@
 	string __grouping_tmp;
 	if (__lc->_M_use_grouping)
 	  __grouping_tmp.reserve(32);
-	// Marker for thousands_sep position.
-	int __sep_pos = 0;
+	// Last position before the decimal point.
+	int __last_pos = 0;
+	// Separator positions, then, possibly, fractional digits.
+	int __n = 0;
 	// If input iterator is in a valid state.
 	bool __testvalid = true;
 	// Flag marking when a decimal point is found.
@@ -1277,26 +1281,23 @@
 		  if (__q = __traits_type::find(__lit_zero, 10, *__beg))
 		    {
 		      __res += _S_atoms[__q - __lit];
-		      ++__sep_pos;
+		      ++__n;
 		    }
 		  else if (*__beg == __lc->_M_decimal_point && !__testdecfound)
 		    {
-		      // If no grouping chars are seen, no grouping check
-		      // is applied. Therefore __grouping_tmp is adjusted
-		      // only if decimal_point comes after some thousands_sep.
-		      if (__grouping_tmp.size())
-			__grouping_tmp += static_cast<char>(__sep_pos);
-		      __sep_pos = 0;
+		      __last_pos = __n;
+		      __n = 0;
 		      __testdecfound = true;
 		    }
 		  else if (__lc->_M_use_grouping
-			   && *__beg == __lc->_M_thousands_sep)
+			   && *__beg == __lc->_M_thousands_sep
+			   && !__testdecfound)
 		    {
-		      if (!__testdecfound)
+		      if (__n)
 			{
 			  // Mark position for later analysis.
-			  __grouping_tmp += static_cast<char>(__sep_pos);
-			  __sep_pos = 0;
+			  __grouping_tmp += static_cast<char>(__n);
+			  __n = 0;
 			}
 		      else
 			{
@@ -1350,10 +1351,9 @@
 	    // Test for grouping fidelity.
 	    if (__grouping_tmp.size())
 	      {
-		// Add the ending grouping if a decimal wasn't found.
-		if (!__testdecfound)
-		  __grouping_tmp += static_cast<char>(__sep_pos);
-		
+		// Add the ending grouping.
+		__grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
+						                   : __n);
 		if (!std::__verify_grouping(__lc->_M_grouping,
 					    __lc->_M_grouping_size,
 					    __grouping_tmp))
@@ -1362,7 +1362,7 @@
 	    
 	    // Iff not enough digits were supplied after the decimal-point.
 	    if (__testdecfound && __lc->_M_frac_digits > 0
-		&& __sep_pos != __lc->_M_frac_digits)
+		&& __n != __lc->_M_frac_digits)
 	      __testvalid = false;
 	  }
 	else
diff -urN libstdc++-v3-orig/testsuite/22_locale/money_get/get/char/15.cc libstdc++-v3/testsuite/22_locale/money_get/get/char/15.cc
--- libstdc++-v3-orig/testsuite/22_locale/money_get/get/char/15.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/22_locale/money_get/get/char/15.cc	2004-02-29 22:54:51.000000000 +0100
@@ -0,0 +1,68 @@
+// 2004-03-01  Paolo Carlini  <pcarlini@suse.de>
+
+// Copyright (C) 2004 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.6.1.1 money_get members
+
+#include <locale>
+#include <sstream>
+#include <testsuite_hooks.h>
+
+// The grammar doesn't allow thousands separator at the beginning of a
+// string, neither two consecutive thousands separators. 
+void test01()
+{
+  using namespace std;
+  bool test __attribute__((unused)) = true;
+
+  typedef istreambuf_iterator<char> iterator_type;
+
+  // basic construction
+  locale loc_c = locale::classic();
+  locale loc_de = __gnu_test::try_named_locale("de_DE@euro");
+  VERIFY( loc_c != loc_de );
+
+  iterator_type end01, end02;
+  istringstream iss;
+  iss.imbue(loc_de);
+  // cache the money_get facet
+  const money_get<char>& mon_get = use_facet<money_get<char> >(iss.getloc()); 
+
+  iss.str(".100");
+  iterator_type is_it01(iss);
+  long double result1;
+  ios_base::iostate err01 = ios_base::goodbit;
+  end01 = mon_get.get(is_it01, end01, true, iss, err01, result1);
+  VERIFY( err01 == ios_base::failbit );
+  VERIFY( *end01 == '.' );
+
+  iss.str("30..0");
+  iterator_type is_it02(iss);
+  long double result2;
+  ios_base::iostate err02 = ios_base::goodbit;
+  end02 = mon_get.get(is_it02, end02, false, iss, err02, result2);
+  VERIFY( err02 == ios_base::failbit );
+  VERIFY( *end02 == '.' );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/22_locale/money_get/get/wchar_t/15.cc libstdc++-v3/testsuite/22_locale/money_get/get/wchar_t/15.cc
--- libstdc++-v3-orig/testsuite/22_locale/money_get/get/wchar_t/15.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/22_locale/money_get/get/wchar_t/15.cc	2004-02-29 22:56:18.000000000 +0100
@@ -0,0 +1,69 @@
+// 2004-03-01  Paolo Carlini  <pcarlini@suse.de>
+
+// Copyright (C) 2004 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.6.1.1 money_get members
+
+#include <locale>
+#include <sstream>
+#include <testsuite_hooks.h>
+
+// The grammar doesn't allow thousands separator at the beginning of a
+// string, neither two consecutive thousands separators. 
+void test01()
+{
+  using namespace std;
+  bool test __attribute__((unused)) = true;
+
+  typedef istreambuf_iterator<wchar_t> iterator_type;
+
+  // basic construction
+  locale loc_c = locale::classic();
+  locale loc_de = __gnu_test::try_named_locale("de_DE@euro");
+  VERIFY( loc_c != loc_de );
+
+  iterator_type end01, end02;
+  wistringstream iss;
+  iss.imbue(loc_de);
+  // cache the money_get facet
+  const money_get<wchar_t>& mon_get =
+    use_facet<money_get<wchar_t> >(iss.getloc()); 
+
+  iss.str(L".100");
+  iterator_type is_it01(iss);
+  long double result1;
+  ios_base::iostate err01 = ios_base::goodbit;
+  end01 = mon_get.get(is_it01, end01, true, iss, err01, result1);
+  VERIFY( err01 == ios_base::failbit );
+  VERIFY( *end01 == L'.' );
+
+  iss.str(L"30..0");
+  iterator_type is_it02(iss);
+  long double result2;
+  ios_base::iostate err02 = ios_base::goodbit;
+  end02 = mon_get.get(is_it02, end02, false, iss, err02, result2);
+  VERIFY( err02 == ios_base::failbit );
+  VERIFY( *end02 == L'.' );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/22_locale/num_get/get/char/15.cc libstdc++-v3/testsuite/22_locale/num_get/get/char/15.cc
--- libstdc++-v3-orig/testsuite/22_locale/num_get/get/char/15.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/22_locale/num_get/get/char/15.cc	2004-03-01 01:49:27.000000000 +0100
@@ -0,0 +1,75 @@
+// 2004-03-01  Paolo Carlini  <pcarlini@suse.de>
+
+// Copyright (C) 2004 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.1.1  num_get members
+
+#include <locale>
+#include <sstream>
+#include <testsuite_hooks.h>
+
+struct Punct1: std::numpunct<char>
+{
+  std::string do_grouping() const { return "\1"; }
+  char do_thousands_sep() const { return '+'; }
+};
+
+struct Punct2: std::numpunct<char>
+{
+  char do_decimal_point() const { return '-'; }
+};
+
+// http://gcc.gnu.org/ml/libstdc++/2003-12/msg00201.html
+void test01()
+{
+  using namespace std;
+  typedef istreambuf_iterator<char> iterator_type;
+  
+  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 = 1.0;
+  double d2 = 3.0;
+  
+  iss1.str("1e+2");
+  err = ios_base::goodbit;
+  end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
+  VERIFY( err == ios_base::goodbit );
+  VERIFY( d == d1 );
+
+  iss2.str("3e-1");
+  err = ios_base::goodbit;
+  end = ng2.get(iss2.rdbuf(), 0, iss2, err, d);
+  VERIFY( err == ios_base::goodbit );
+  VERIFY( d == d2 );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/22_locale/num_get/get/wchar_t/15.cc libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/15.cc
--- libstdc++-v3-orig/testsuite/22_locale/num_get/get/wchar_t/15.cc	1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/15.cc	2004-03-01 01:49:40.000000000 +0100
@@ -0,0 +1,75 @@
+// 2004-03-01  Paolo Carlini  <pcarlini@suse.de>
+
+// Copyright (C) 2004 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.1.1  num_get members
+
+#include <locale>
+#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'+'; }
+};
+
+struct Punct2: std::numpunct<wchar_t>
+{
+  wchar_t do_decimal_point() const { return L'-'; }
+};
+
+// http://gcc.gnu.org/ml/libstdc++/2003-12/msg00201.html
+void test01()
+{
+  using namespace std;
+  typedef istreambuf_iterator<wchar_t> iterator_type;
+  
+  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 = 1.0;
+  double d2 = 3.0;
+  
+  iss1.str(L"1e+2");
+  err = ios_base::goodbit;
+  end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
+  VERIFY( err == ios_base::goodbit );
+  VERIFY( d == d1 );
+
+  iss2.str(L"3e-1");
+  err = ios_base::goodbit;
+  end = ng2.get(iss2.rdbuf(), 0, iss2, err, d);
+  VERIFY( err == ios_base::goodbit );
+  VERIFY( d == d2 );
+}
+
+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]