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


Hi,

so here it is, quite easy to fix, as I imagined. I was a little bit
worried that performance could be affected, so I ran three times
the performance testsuite (p4-2400, -O2) and ifstream_extract_int
is:

3.4
---
612r  600u    7s        0mem    8pf
615r  607u    6s        0mem    8pf
610r  599u    7s        0mem    8pf

3.4 + patch
-----------
619r  601u    8s        0mem    7pf
615r  601u   11s        0mem    7pf
618r  601u   13s        0mem    7pf

so, the differences are in the noise, it seems...

Otherwise, the fix is straightforard: just reorder properly the
various branches.

Tested x86-linux, will wait 'til this evening italian time.

Paolo.

///////////
2003-12-19  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 decimal_point and thousands_sep.
	* testsuite/22_locale/num_get/get/char/11.cc: New.
	* 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	Thu Dec 18 23:47:04 2003
--- libstdc++-v3/include/bits/locale_facets.tcc	Fri Dec 19 14:18:46 2003
*************** namespace std
*** 169,186 ****
        string __found_grouping;
        int __sep_pos = 0;
        bool __e;
        while (__beg != __end)
          {
! 	  // Only look in digits.
  	  const char_type __c = *__beg;
!           const char_type* __p = __traits_type::find(__lit + _S_izero, 10, 
! 						     __c);
!           if (__p)
  	    {
! 	      // Try first for acceptable digit; record it if found.
! 	      __xtrc += _S_atoms_in[__p - __lit];
! 	      __found_mantissa = true;
! 	      ++__sep_pos;
  	      ++__beg;
  	    }
            else if (__lc->_M_use_grouping
--- 169,190 ----
        string __found_grouping;
        int __sep_pos = 0;
        bool __e;
+       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
*************** namespace std
*** 201,216 ****
  		  break;
  		}
              }
! 	  else 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 ((__e = __traits_type::eq(__c, __lit[_S_ie]) 
--- 205,215 ----
  		  break;
  		}
              }
!           else if (__p = __traits_type::find(__lit + _S_izero, 10, __c))
  	    {
! 	      __xtrc += _S_atoms_in[__p - __lit];
! 	      __found_mantissa = true;
! 	      ++__sep_pos;
  	      ++__beg;
  	    }
  	  else if ((__e = __traits_type::eq(__c, __lit[_S_ie]) 
*************** namespace std
*** 337,350 ****
  	bool __overflow = false;
  	_ValueT __result = 0;
  	const char_type* __lit_zero = __lit + _S_izero;
  	if (__negative)
  	  {
  	    const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
  	    for (; __beg != __end; ++__beg)
  	      {
! 		const char_type* __p = __traits_type::find(__lit_zero,
! 							   __len, *__beg);
! 		if (__p)
  		  {
  		    int __digit = __p - __lit_zero;
  		    if (__digit > 15)
--- 336,369 ----
  	bool __overflow = false;
  	_ValueT __result = 0;
  	const char_type* __lit_zero = __lit + _S_izero;
+ 	const char_type* __p;
  	if (__negative)
  	  {
  	    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.
! 		    if (__sep_pos)
! 		      {
! 			__found_grouping += static_cast<char>(__sep_pos);
! 			__sep_pos = 0;
! 		      }
! 		    else
! 		      {
! 			__err |= ios_base::failbit;
! 			break;
! 		      }
! 		  }
! 		else if (__p = __traits_type::find(__lit_zero, __len, __c))
  		  {
  		    int __digit = __p - __lit_zero;
  		    if (__digit > 15)
*************** namespace std
*** 360,370 ****
  			__found_num = true;
  		      }
  		  }
  		else if (__lc->_M_use_grouping
! 			 && __traits_type::eq(*__beg, __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);
--- 379,400 ----
  			__found_num = true;
  		      }
  		  }
+ 		else
+ 		  // Not a valid input item.
+ 		  break;
+ 	      }
+ 	  }
+ 	else
+ 	  {
+ 	    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)
  		      {
  			__found_grouping += static_cast<char>(__sep_pos);
*************** namespace std
*** 376,394 ****
  			break;
  		      }
  		  }
! 		else
! 		  // Not a valid input item.
! 		  break;
! 	      }
! 	  }
! 	else
! 	  {
! 	    const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
! 	    for (; __beg != __end; ++__beg)
! 	      {
! 		const char_type* __p = __traits_type::find(__lit_zero,
! 							   __len, *__beg);
! 		if (__p)
  		  {
  		    int __digit = __p - __lit_zero;
  		    if (__digit > 15)
--- 406,412 ----
  			break;
  		      }
  		  }
! 		else if (__p = __traits_type::find(__lit_zero, __len, __c))
  		  {
  		    int __digit = __p - __lit_zero;
  		    if (__digit > 15)
*************** namespace std
*** 404,423 ****
  			__found_num = true;
  		      }
  		  }
- 		else if (__lc->_M_use_grouping
- 			 && __traits_type::eq(*__beg, __lc->_M_thousands_sep))
- 		  {
- 		    if (__sep_pos)
- 		      {
- 			__found_grouping += static_cast<char>(__sep_pos);
- 			__sep_pos = 0;
- 		      }
- 		    else
- 		      {
- 			__err |= ios_base::failbit;
- 			break;
- 		      }
- 		  }
  		else
  		  break;
  	      }
--- 422,427 ----
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	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/22_locale/num_get/get/char/11.cc	Fri Dec 19 14:13:39 2003
***************
*** 0 ****
--- 1,68 ----
+ // Copyright (C) 2003 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 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'; }
+ };
+ 
+ void test01()
+ {
+   using namespace std;
+   typedef istreambuf_iterator<char> iterator_type;
+   
+   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()
+ {
+   test01();
+   return 0;
+ }
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	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/11.cc	Fri Dec 19 14:13:55 2003
***************
*** 0 ****
--- 1,68 ----
+ // Copyright (C) 2003 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 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'; }
+ };
+ 
+ void test01()
+ {
+   using namespace std;
+   typedef istreambuf_iterator<wchar_t> iterator_type;
+   
+   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()
+ {
+   test01();
+   return 0;
+ }

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