From 22831f13fa47bc74d80462cd0fc5bdb904dc3679 Mon Sep 17 00:00:00 2001 From: paolo Date: Mon, 22 Dec 2003 11:00:43 +0000 Subject: [PATCH] 2003-12-22 Paolo Carlini * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@74932 138bc75d-0d04-0410-961f-82ee72b054a4 --- libstdc++-v3/ChangeLog | 12 ++ libstdc++-v3/include/bits/locale_facets.tcc | 96 ++++++++----- .../testsuite/22_locale/num_get/get/char/11.cc | 1 + .../testsuite/22_locale/num_get/get/char/12.cc | 160 +++++++++++++++++++++ .../testsuite/22_locale/num_get/get/wchar_t/11.cc | 1 + .../testsuite/22_locale/num_get/get/wchar_t/12.cc | 160 +++++++++++++++++++++ 6 files changed, 391 insertions(+), 39 deletions(-) create mode 100644 libstdc++-v3/testsuite/22_locale/num_get/get/char/12.cc create mode 100644 libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/12.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4c981a5..d8ca538 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,15 @@ +2003-12-22 Paolo Carlini + + * 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. + 2003-12-20 Jason Merrill * config/cpu/powerpc/atomicity.h: Fix oversight in previous diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index b934482..265c143 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -163,12 +163,18 @@ namespace std 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])) + 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]; @@ -176,16 +182,25 @@ namespace std } } - // Next, look for a zero... - bool __found_mantissa = false; - if (__beg != __end && __traits_type::eq(*__beg, __lit[_S_izero])) + // Next, look for leading zeros. + while (__beg != __end) { - __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); + 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. @@ -307,48 +322,51 @@ namespace std // 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(*__beg, __lit[_S_iminus]); - if (__negative || __traits_type::eq(*__beg, __lit[_S_iplus])) + __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. - if (__beg != __end && __traits_type::eq(*__beg, __lit[_S_izero])) + while (__beg != __end) { - __found_num = true; - ++__beg; - if (__builtin_expect(__base == 10, true)) + 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)) { - // 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; - } + __found_num = true; + ++__beg; } - else if (__base == 16 && __beg != __end) + else if (__found_num) { - const bool __x = __traits_type::eq(*__beg, __lit[_S_ix]); - if (__x || __traits_type::eq(*__beg, __lit[_S_iX])) + if (__traits_type::eq(__c, __lit[_S_ix]) + || __traits_type::eq(__c, __lit[_S_iX])) { - ++__beg; - __found_num = false; + 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 --git a/libstdc++-v3/testsuite/22_locale/num_get/get/char/11.cc b/libstdc++-v3/testsuite/22_locale/num_get/get/char/11.cc index fde63c4..138f10d 100644 --- a/libstdc++-v3/testsuite/22_locale/num_get/get/char/11.cc +++ b/libstdc++-v3/testsuite/22_locale/num_get/get/char/11.cc @@ -29,6 +29,7 @@ struct Punct: std::numpunct char do_decimal_point() const { return '4'; } }; +// http://gcc.gnu.org/ml/libstdc++/2003-12/msg00201.html void test01() { using namespace std; diff --git a/libstdc++-v3/testsuite/22_locale/num_get/get/char/12.cc b/libstdc++-v3/testsuite/22_locale/num_get/get/char/12.cc new file mode 100644 index 0000000..1898867 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_get/get/char/12.cc @@ -0,0 +1,160 @@ +// 2003-12-22 Paolo Carlini + +// 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 +#include +#include + +struct Punct1: std::numpunct +{ + std::string do_grouping() const { return "\1"; } + char do_thousands_sep() const { return '+'; } + char do_decimal_point() const { return 'x'; } +}; + +struct Punct2: std::numpunct +{ + 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 iterator_type; + + bool test __attribute__((unused)) = true; + + istringstream iss1, iss2; + iss1.imbue(locale(iss1.getloc(), static_cast*>(new Punct1))); + iss2.imbue(locale(iss2.getloc(), static_cast*>(new Punct2))); + const num_get& ng1 = use_facet >(iss1.getloc()); + const num_get& ng2 = use_facet >(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 --git a/libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/11.cc b/libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/11.cc index e438fbe..d478209 100644 --- a/libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/11.cc +++ b/libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/11.cc @@ -29,6 +29,7 @@ struct Punct: std::numpunct 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 --git a/libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/12.cc b/libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/12.cc new file mode 100644 index 0000000..fa9cb15 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/12.cc @@ -0,0 +1,160 @@ +// 2003-12-22 Paolo Carlini + +// 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 +#include +#include + +struct Punct1: std::numpunct +{ + 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 +{ + 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 iterator_type; + + bool test __attribute__((unused)) = true; + + wistringstream iss1, iss2; + iss1.imbue(locale(iss1.getloc(), static_cast*>(new Punct1))); + iss2.imbue(locale(iss2.getloc(), static_cast*>(new Punct2))); + const num_get& ng1 = use_facet >(iss1.getloc()); + const num_get& ng2 = use_facet >(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; +} -- 2.7.4