locale_facets.tcc (num_get::_M_extract_int, [...]): According to 22.2.2.1.2...
authorPaolo Carlini <pcarlini@suse.de>
Mon, 22 Dec 2003 11:00:43 +0000 (11:00 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Mon, 22 Dec 2003 11:00:43 +0000 (11:00 +0000)
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.

From-SVN: r74932

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/locale_facets.tcc
libstdc++-v3/testsuite/22_locale/num_get/get/char/11.cc
libstdc++-v3/testsuite/22_locale/num_get/get/char/12.cc [new file with mode: 0644]
libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/11.cc
libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/12.cc [new file with mode: 0644]

index 4c981a5920fcc7d103205a19f1ca3c9dfa013ba4..d8ca538327a409eeca927dced1f7802746de5f42 100644 (file)
@@ -1,3 +1,15 @@
+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.
+       
 2003-12-20  Jason Merrill  <jason@redhat.com>
 
        * config/cpu/powerpc/atomicity.h: Fix oversight in previous
index b934482251114eefbe627510f3d3932cbfa7f44a..265c1437ebae111a47cc9b649fdd475bcdbbeb10 100644 (file)
@@ -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
index fde63c4ae1d7dc6f50874073224fc15438e4a567..138f10d0a0c5752e4f34189483be7e062227a1b6 100644 (file)
@@ -29,6 +29,7 @@ struct Punct: std::numpunct<char>
   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 (file)
index 0000000..1898867
--- /dev/null
@@ -0,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;
+}
index e438fbe61a1d5bf5ea27f2effc77cd96853103fc..d478209f49dec6055477c8b2fb6b0016ba7d23f5 100644 (file)
@@ -29,6 +29,7 @@ struct Punct: std::numpunct<wchar_t>
   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 (file)
index 0000000..fa9cb15
--- /dev/null
@@ -0,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;
+}