This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] Last bits for Martin's issue
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Tue, 30 Dec 2003 11:01:13 +0100
- Subject: [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()
{