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


Hi,

this is the second, final batch, dealing with the initial parsing
of sign, leading zeros, 0, 0x, 0X in the case of integer types.

Interestingly, notwithstanding the numerous correctness fixes
(accompanied by clean ups, eh!), the current performance for
reading back 1,000,000 integers from 0 to 999,999 with:

 std::ifstream in("input_test");
 for (int j, i = 0; i < 10000000; ++i)
   in >> j;

are as follows (P4-2400, -O2):

3.4
---
5.570u 0.070s 0:05.68 99.2%     0+0k 0+0io 203pf+0w

vs

2.96-99
-------
6.080u 0.060s 0:06.18 99.3%     0+0k 0+0io 135pf+0w

vs

3.3.2
-----
41.790u 0.110s 0:42.22 99.2%    0+0k 0+0io 214pf+0w

Tested x86-linux, would like to commit on monday... one of my
last for this year...

Paolo.

/////////////
2003-12-22  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, when parsing
	sign, leading zeros (and 0, Ox, 0X for integer types) too.
	* testsuite/22_locale/num_get/get/char/12.cc: New.
	* testsuite/22_locale/num_get/get/wchar_t/12.cc: Likewise.

	* testsuite/22_locale/num_get/get/char/11.cc: Add a comment.
	* 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	Fri Dec 19 14:18:46 2003
--- libstdc++-v3/include/bits/locale_facets.tcc	Sat Dec 20 20:03:47 2003
*************** namespace std
*** 138,149 ****
        const __cache_type* __lc = __uc(__loc);
        const _CharT* __lit = __lc->_M_atoms_in;
  
        // First check for sign.
        if (__beg != __end)
  	{
  	  const char_type __c = *__beg;
  	  const bool __plus = __traits_type::eq(__c, __lit[_S_iplus]);
! 	  if (__plus || __traits_type::eq(__c, __lit[_S_iminus]))
  	    {
  	      __xtrc += __plus ? _S_atoms_in[_S_iplus]
  		               : _S_atoms_in[_S_iminus];
--- 138,155 ----
        const __cache_type* __lc = __uc(__loc);
        const _CharT* __lit = __lc->_M_atoms_in;
  
+       // True if a mantissa is found.
+       bool __found_mantissa = false;
+ 
        // First check for sign.
        if (__beg != __end)
  	{
  	  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)))
  	    {
  	      __xtrc += __plus ? _S_atoms_in[_S_iplus]
  		               : _S_atoms_in[_S_iminus];
*************** namespace std
*** 151,166 ****
  	    }
  	}
  	  
!       // Next, look for a zero...
!       bool __found_mantissa = false;
!       if (__beg != __end && __traits_type::eq(*__beg, __lit[_S_izero]))
  	{
! 	  __xtrc += _S_atoms_in[_S_izero];
! 	  __found_mantissa = true;
! 	  ++__beg;
! 	  // ... and skip the additional ones.
! 	  for (; __beg != __end
! 		 && __traits_type::eq(*__beg, __lit[_S_izero]); ++__beg);
  	}
  
        // Only need acceptable digits for floating point numbers.
--- 157,181 ----
  	    }
  	}
  	  
!       // Next, look for leading zeros.
!       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)))
! 	    break;
! 	  else if (__traits_type::eq(__c, __lit[_S_izero]))
! 	    {
! 	      if (!__found_mantissa)
! 		{
! 		  __xtrc += _S_atoms_in[_S_izero];
! 		  __found_mantissa = true;
! 		}
! 	      ++__beg;
! 	    }
! 	  else
! 	    break;
  	}
  
        // Only need acceptable digits for floating point numbers.
*************** namespace std
*** 282,329 ****
  	// First check for sign.
  	bool __negative = false;
  	if (__beg != __end)
! 	  {
  	    if (numeric_limits<_ValueT>::is_signed)
! 	      __negative = __traits_type::eq(*__beg, __lit[_S_iminus]);
! 	    if (__negative || __traits_type::eq(*__beg, __lit[_S_iplus]))
  	      ++__beg;
  	  }
  
  	// Next, look for leading zeros and check required digits
  	// for base formats.
! 	if (__beg != __end && __traits_type::eq(*__beg, __lit[_S_izero]))
  	  {
! 	    __found_num = true;
! 	    ++__beg;
! 	    if (__builtin_expect(__base == 10, true))
  	      {
! 		// Skip the additional zeros.
! 		for (; __beg != __end
! 		       && __traits_type::eq(*__beg, __lit[_S_izero]); ++__beg);
! 		
! 		// Check required digits.
! 		if (__beg != __end && __basefield == 0)
! 		  {	  
! 		    const bool __x = __traits_type::eq(*__beg, __lit[_S_ix]);
! 		    if (__x || __traits_type::eq(*__beg, __lit[_S_iX]))
! 		      {
! 			__base = 16;
! 			++__beg;
! 			__found_num = false;
! 		      }
! 		    else
! 		      __base = 8;
! 		  }	      
  	      }
! 	    else if (__base == 16 && __beg != __end)
  	      {
! 		const bool __x = __traits_type::eq(*__beg, __lit[_S_ix]);
! 		if (__x || __traits_type::eq(*__beg, __lit[_S_iX]))
  		  {
! 		    ++__beg;
! 		    __found_num = false;
  		  }
  	      }
  	  }
  
  	// At this point, base is determined. If not hex, only allow
--- 297,347 ----
  	// First check for sign.
  	bool __negative = false;
  	if (__beg != __end)
! 	  { 
! 	    const char_type __c = *__beg;
  	    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)))
  	      ++__beg;
  	  }
  
  	// Next, look for leading zeros and check required digits
  	// for base formats.
! 	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)))
! 	      break;
! 	    else if (__traits_type::eq(__c, __lit[_S_izero])
! 		     && (!__found_num || __base == 10))
  	      {
! 		__found_num = true;
! 		++__beg;
  	      }
! 	    else if (__found_num)
  	      {
! 		if (__traits_type::eq(__c, __lit[_S_ix])
! 		    || __traits_type::eq(__c, __lit[_S_iX]))
  		  {
! 		    if (__basefield == 0)
! 		      __base = 16;
! 		    if (__base == 16)
! 		      {
! 			__found_num = false;
! 			++__beg;
! 		      }
  		  }
+ 		else if (__basefield == 0)
+ 		  __base = 8;
+ 		break;
  	      }
+ 	    else
+ 	      break;
  	  }
  
  	// At this point, base is determined. If not hex, only allow
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	Fri Dec 19 15:00:13 2003
--- libstdc++-v3/testsuite/22_locale/num_get/get/char/11.cc	Sat Dec 20 23:33:20 2003
*************** struct Punct: std::numpunct<char>
*** 29,34 ****
--- 29,35 ----
    char do_decimal_point() const { return '4'; }
  };
  
+ // http://gcc.gnu.org/ml/libstdc++/2003-12/msg00201.html
  void test01()
  {
    using namespace std;
diff -prN 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	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/22_locale/num_get/get/char/12.cc	Sun Dec 21 00:37:49 2003
***************
*** 0 ****
--- 1,160 ----
+ // 2003-12-22  Paolo Carlini  <pcarlini@suse.de>
+ 
+ // 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 Punct1: std::numpunct<char>
+ {
+   std::string do_grouping() const { return "\1"; }
+   char do_thousands_sep() const { return '+'; }
+   char do_decimal_point() const { return 'x'; }
+ };
+ 
+ struct Punct2: std::numpunct<char>
+ {
+   std::string do_grouping() const { return "\1"; }
+   char do_thousands_sep() const { return 'X'; }
+   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;
+   long l = 1l;
+   long l1 = 0l;
+   long l2 = 10l;
+   long l3 = 1l;
+   long l4 = 63l;
+   double d = 0.0;
+   double d1 = .4;  
+   double d2 = .1;
+ 
+   iss1.str("+3");
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
+   VERIFY( err == ios_base::failbit );
+   VERIFY( *end == '+' );
+ 
+   iss1.str("0x1");
+   iss1.clear();
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
+   VERIFY( err == ios_base::goodbit );
+   VERIFY( *end == 'x' );
+   VERIFY( l == l1 );
+ 
+   iss1.str("0Xa");
+   iss1.clear();
+   iss1.unsetf(ios::basefield);
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
+   VERIFY( err == ios_base::eofbit );
+   VERIFY( l == l2 );
+ 
+   iss1.str("0xa");
+   iss1.clear();
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
+   VERIFY( err == ios_base::goodbit );
+   VERIFY( *end == 'x' );
+   VERIFY( l == l1 );  
+ 
+   iss1.str("+5");
+   iss1.clear();
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
+   VERIFY( err == ios_base::failbit );
+   VERIFY( *end == '+' );
+ 
+   iss1.str("x4");
+   iss1.clear();
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
+   VERIFY( err == ios_base::eofbit );
+   VERIFY( d == d1 );
+ 
+   iss2.str("0001-");
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, l);
+   VERIFY( err == ios_base::goodbit );
+   VERIFY( *end == '-' );
+   VERIFY( l == l3 );
+ 
+   iss2.str("-2");
+   iss2.clear();
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, l);
+   VERIFY( err == ios_base::failbit );
+   VERIFY( *end == '-' );
+ 
+   iss2.str("0X1");
+   iss2.clear();
+   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' );
+ 
+   iss2.str("000778");
+   iss2.clear();
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, l);
+   VERIFY( err == ios_base::goodbit );
+   VERIFY( *end == '8' );
+   VERIFY( l == l4 );
+ 
+   iss2.str("00X");
+   iss2.clear();
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, d);
+   VERIFY( err == ios_base::failbit );
+   VERIFY( *end == 'X' );
+ 
+   iss2.str("-1");
+   iss2.clear();
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, d);
+   VERIFY( err == ios_base::eofbit );
+   VERIFY( d == d2 );  
+ }
+ 
+ 
+ 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	Fri Dec 19 15:00:27 2003
--- libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/11.cc	Sat Dec 20 23:33:49 2003
*************** struct Punct: std::numpunct<wchar_t>
*** 29,34 ****
--- 29,35 ----
    wchar_t do_decimal_point() const { return L'4'; }
  };
  
+ // http://gcc.gnu.org/ml/libstdc++/2003-12/msg00201.html
  void test01()
  {
    using namespace std;
diff -prN 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	Thu Jan  1 01:00:00 1970
--- libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/12.cc	Sun Dec 21 00:38:01 2003
***************
*** 0 ****
--- 1,160 ----
+ // 2003-12-22  Paolo Carlini  <pcarlini@suse.de>
+ 
+ // 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 Punct1: std::numpunct<wchar_t>
+ {
+   std::string do_grouping() const { return "\1"; }
+   wchar_t do_thousands_sep() const { return L'+'; }
+   wchar_t do_decimal_point() const { return L'x'; }
+ };
+ 
+ struct Punct2: std::numpunct<wchar_t>
+ {
+   std::string do_grouping() const { return "\1"; }
+   wchar_t do_thousands_sep() const { return L'X'; }
+   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;
+   long l = 1l;
+   long l1 = 0l;
+   long l2 = 10l;
+   long l3 = 1l;
+   long l4 = 63l;
+   double d = 0.0;
+   double d1 = .4;  
+   double d2 = .1;
+ 
+   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'+' );
+ 
+   iss1.str(L"0x1");
+   iss1.clear();
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
+   VERIFY( err == ios_base::goodbit );
+   VERIFY( *end == L'x' );
+   VERIFY( l == l1 );
+ 
+   iss1.str(L"0Xa");
+   iss1.clear();
+   iss1.unsetf(ios::basefield);
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
+   VERIFY( err == ios_base::eofbit );
+   VERIFY( l == l2 );
+ 
+   iss1.str(L"0xa");
+   iss1.clear();
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, l);
+   VERIFY( err == ios_base::goodbit );
+   VERIFY( *end == L'x' );
+   VERIFY( l == l1 );  
+ 
+   iss1.str(L"+5");
+   iss1.clear();
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
+   VERIFY( err == ios_base::failbit );
+   VERIFY( *end == L'+' );
+ 
+   iss1.str(L"x4");
+   iss1.clear();
+   err = ios_base::goodbit;
+   end = ng1.get(iss1.rdbuf(), 0, iss1, err, d);
+   VERIFY( err == ios_base::eofbit );
+   VERIFY( d == d1 );
+ 
+   iss2.str(L"0001-");
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, l);
+   VERIFY( err == ios_base::goodbit );
+   VERIFY( *end == L'-' );
+   VERIFY( l == l3 );
+ 
+   iss2.str(L"-2");
+   iss2.clear();
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, l);
+   VERIFY( err == ios_base::failbit );
+   VERIFY( *end == L'-' );
+ 
+   iss2.str(L"0X1");
+   iss2.clear();
+   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' );
+ 
+   iss2.str(L"000778");
+   iss2.clear();
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, l);
+   VERIFY( err == ios_base::goodbit );
+   VERIFY( *end == L'8' );
+   VERIFY( l == l4 );
+ 
+   iss2.str(L"00X");
+   iss2.clear();
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, d);
+   VERIFY( err == ios_base::failbit );
+   VERIFY( *end == L'X' );
+ 
+   iss2.str(L"-1");
+   iss2.clear();
+   err = ios_base::goodbit;
+   end = ng2.get(iss2.rdbuf(), 0, iss2, err, d);
+   VERIFY( err == ios_base::eofbit );
+   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]