re PR libstdc++/9817 (collate::compare doesn't handle nul characters.)
authorPetur Runolfsson <peturr02@ru.is>
Fri, 7 Mar 2003 17:24:47 +0000 (17:24 +0000)
committerBenjamin Kosnik <bkoz@gcc.gnu.org>
Fri, 7 Mar 2003 17:24:47 +0000 (17:24 +0000)
2003-03-07  Petur Runolfsson  <peturr02@ru.is>

PR libstdc++/9817
* include/bits/locale_facets.tcc
(collate::do_compare, collate::do_transform):
Handle nul characters in input.
* testsuite/22_locale/collate/compare/char/3.cc:  New test.
* testsuite/22_locale/collate/compare/wchar_t/3.cc:  New test.
* testsuite/22_locale/collate/transform/char/3.cc:  New test.
* testsuite/22_locale/collate/transform/wchar_t/3.cc:  New test.

From-SVN: r63946

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/locale_facets.tcc
libstdc++-v3/testsuite/22_locale/collate/compare/char/3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/22_locale/collate/compare/wchar_t/3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/22_locale/collate/transform/char/3.cc [new file with mode: 0644]
libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/3.cc [new file with mode: 0644]

index 2162fc8e70a1619b69404bd4f78e5b36afb30196..763b5739e51afcd7aa6e7d07465a70ca49972d60 100644 (file)
@@ -1,3 +1,14 @@
+2003-03-07  Petur Runolfsson  <peturr02@ru.is>
+
+       PR libstdc++/9817
+       * include/bits/locale_facets.tcc
+       (collate::do_compare, collate::do_transform):
+       Handle nul characters in input.
+       * testsuite/22_locale/collate/compare/char/3.cc:  New test.
+       * testsuite/22_locale/collate/compare/wchar_t/3.cc:  New test.
+       * testsuite/22_locale/collate/transform/char/3.cc:  New test.
+       * testsuite/22_locale/collate/transform/wchar_t/3.cc:  New test.
+
 2003-03-07  Jerry Quinn  <jlquinn@optonline.net>
 
        * include/bits/streambuf_iterator.h (_M_put): Set _M_failed if
index cb6dccd19e674df28d2248bea1058070d7f62fc5..b5b1f5c2e1e79688920e746e80a01d789dd32346 100644 (file)
@@ -2038,9 +2038,37 @@ namespace std
     do_compare(const _CharT* __lo1, const _CharT* __hi1, 
               const _CharT* __lo2, const _CharT* __hi2) const
     { 
+      // strcoll assumes zero-terminated strings so we make a copy
+      // and then put a zero at the end.
       const string_type __one(__lo1, __hi1);
       const string_type __two(__lo2, __hi2);
-      return _M_compare(__one.c_str(), __two.c_str());
+
+      const _CharT* __p = __one.c_str();
+      const _CharT* __pend = __one.c_str() + __one.length();
+      const _CharT* __q = __two.c_str();
+      const _CharT* __qend = __two.c_str() + __two.length();
+
+      // strcoll stops when it sees a nul character so we break
+      // the strings into zero-terminated substrings and pass those
+      // to strcoll.
+      for (;;)
+       {
+         int __res = _M_compare(__p, __q);
+         if (__res)
+           return __res;
+
+         __p += char_traits<_CharT>::length(__p);
+         __q += char_traits<_CharT>::length(__q);
+         if (__p == __pend && __q == __qend)
+           return 0;
+         else if (__p == __pend)
+           return -1;
+         else if (__q == __qend)
+           return 1;
+
+         __p++;
+         __q++;
+       }
     }
 
  template<typename _CharT>
@@ -2048,19 +2076,43 @@ namespace std
     collate<_CharT>::
     do_transform(const _CharT* __lo, const _CharT* __hi) const
     {
+      // strxfrm assumes zero-terminated strings so we make a copy
+      string_type __str(__lo, __hi);
+
+      const _CharT* __p = __str.c_str();
+      const _CharT* __pend = __str.c_str() + __str.length();
+
       size_t __len = (__hi - __lo) * 2;
-      // First try a buffer perhaps big enough.
-      _CharT* __c =
-       static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
-      size_t __res = _M_transform(__c, __lo, __len);
-      // If the buffer was not large enough, try again with the correct size.
-      if (__res >= __len)
+
+      string_type __ret;
+
+      // strxfrm stops when it sees a nul character so we break
+      // the string into zero-terminated substrings and pass those
+      // to strxfrm.
+      for (;;)
        {
-         __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
-                                                     * (__res + 1)));
-         _M_transform(__c, __lo, __res + 1);
+         // First try a buffer perhaps big enough.
+         _CharT* __c =
+           static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
+         size_t __res = _M_transform(__c, __p, __len);
+         // If the buffer was not large enough, try again with the
+         // correct size.
+         if (__res >= __len)
+           {
+             __len = __res + 1;
+             __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
+                                                         * __len));
+             __res = _M_transform(__c, __p, __res + 1);
+           }
+
+         __ret.append(__c, __res);
+         __p += char_traits<_CharT>::length(__p);
+         if (__p == __pend)
+           return __ret;
+
+         __p++;
+         __ret.push_back(_CharT());
        }
-      return string_type(__c);
     }
 
  template<typename _CharT>
diff --git a/libstdc++-v3/testsuite/22_locale/collate/compare/char/3.cc b/libstdc++-v3/testsuite/22_locale/collate/compare/char/3.cc
new file mode 100644 (file)
index 0000000..0cce392
--- /dev/null
@@ -0,0 +1,90 @@
+// 2003-02-24 Petur Runolfsson <peturr02@ru.is>
+
+// 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.4.1.1 collate members
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+// Test handling of strings containing nul characters
+void test03()
+{
+  using namespace std;
+  typedef std::collate<char>::string_type string_type;
+
+  bool test = true;
+
+  // basic construction
+  locale loc_c = locale::classic();
+  locale loc_de("de_DE");
+  VERIFY( loc_c != loc_de );
+
+  // cache the collate facets
+  const collate<char>& coll_c = use_facet<collate<char> >(loc_c); 
+  const collate<char>& coll_de = use_facet<collate<char> >(loc_de); 
+
+  // int compare(const charT*, const charT*, const charT*, const charT*) const
+  const char* strlit1 = "a\0a\0";
+  const char* strlit2 = "a\0b\0";
+  const char* strlit3 = "a\0\xc4\0";
+  const char* strlit4 = "a\0B\0";
+  const char* strlit5 = "aa\0";
+  const char* strlit6 = "b\0a\0";
+
+  int i;
+  i = coll_c.compare(strlit1, strlit1 + 3, strlit2, strlit2 + 3);
+  VERIFY( i == -1 );
+
+  i = coll_de.compare(strlit1, strlit1 + 3, strlit2, strlit2 + 3);
+  VERIFY( i == -1 );
+
+  i = coll_c.compare(strlit3, strlit3 + 3, strlit4, strlit4 + 3);
+  VERIFY( i == 1 );
+
+  i = coll_de.compare(strlit3, strlit3 + 3, strlit4, strlit4 + 3);
+  VERIFY( i == -1 );
+
+  i = coll_c.compare(strlit1, strlit1 + 3, strlit1, strlit1 + 4);
+  VERIFY( i == -1 );
+
+  i = coll_de.compare(strlit3, strlit3 + 4, strlit3, strlit3 + 3);
+  VERIFY( i == 1 );
+
+  i = coll_c.compare(strlit1, strlit1 + 4, strlit4, strlit4 + 1);
+  VERIFY( i == 1 );
+
+  i = coll_de.compare(strlit3, strlit3 + 3, strlit3, strlit3 + 3);
+  VERIFY( i == 0 );
+
+  i = coll_c.compare(strlit1, strlit1 + 2, strlit1, strlit1 + 4);
+  VERIFY( i == -1 );
+
+  i = coll_de.compare(strlit1, strlit1 + 3, strlit5, strlit5 + 3);
+  VERIFY( i == -1 );
+
+  i = coll_c.compare(strlit6, strlit6 + 3, strlit1, strlit1 + 3);
+  VERIFY( i == 1 );
+}
+
+int main()
+{
+  test03();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/22_locale/collate/compare/wchar_t/3.cc b/libstdc++-v3/testsuite/22_locale/collate/compare/wchar_t/3.cc
new file mode 100644 (file)
index 0000000..0f9ee64
--- /dev/null
@@ -0,0 +1,90 @@
+// 2003-02-24 Petur Runolfsson <peturr02@ru.is>
+
+// 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.4.1.1 collate members
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+// Test handling of strings containing nul characters
+void test03()
+{
+  using namespace std;
+  typedef std::collate<wchar_t>::string_type string_type;
+
+  bool test = true;
+
+  // basic construction
+  locale loc_c = locale::classic();
+  locale loc_de("de_DE");
+  VERIFY( loc_c != loc_de );
+
+  // cache the collate facets
+  const collate<wchar_t>& coll_c = use_facet<collate<wchar_t> >(loc_c); 
+  const collate<wchar_t>& coll_de = use_facet<collate<wchar_t> >(loc_de); 
+
+  // int compare(const charT*, const charT*, const charT*, const charT*) const
+  const wchar_t* strlit1 = L"a\0a\0";
+  const wchar_t* strlit2 = L"a\0b\0";
+  const wchar_t* strlit3 = L"a\0\xc4\0";
+  const wchar_t* strlit4 = L"a\0B\0";
+  const wchar_t* strlit5 = L"aa\0";
+  const wchar_t* strlit6 = L"b\0a\0";
+
+  int i;
+  i = coll_c.compare(strlit1, strlit1 + 3, strlit2, strlit2 + 3);
+  VERIFY( i == -1 );
+
+  i = coll_de.compare(strlit1, strlit1 + 3, strlit2, strlit2 + 3);
+  VERIFY( i == -1 );
+
+  i = coll_c.compare(strlit3, strlit3 + 3, strlit4, strlit4 + 3);
+  VERIFY( i == 1 );
+
+  i = coll_de.compare(strlit3, strlit3 + 3, strlit4, strlit4 + 3);
+  VERIFY( i == -1 );
+
+  i = coll_c.compare(strlit1, strlit1 + 3, strlit1, strlit1 + 4);
+  VERIFY( i == -1 );
+
+  i = coll_de.compare(strlit3, strlit3 + 4, strlit3, strlit3 + 3);
+  VERIFY( i == 1 );
+
+  i = coll_c.compare(strlit1, strlit1 + 4, strlit4, strlit4 + 1);
+  VERIFY( i == 1 );
+
+  i = coll_de.compare(strlit3, strlit3 + 3, strlit3, strlit3 + 3);
+  VERIFY( i == 0 );
+
+  i = coll_c.compare(strlit1, strlit1 + 2, strlit1, strlit1 + 4);
+  VERIFY( i == -1 );
+
+  i = coll_de.compare(strlit1, strlit1 + 3, strlit5, strlit5 + 3);
+  VERIFY( i == -1 );
+
+  i = coll_c.compare(strlit6, strlit6 + 3, strlit1, strlit1 + 3);
+  VERIFY( i == 1 );
+}
+
+int main()
+{
+  test03();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/22_locale/collate/transform/char/3.cc b/libstdc++-v3/testsuite/22_locale/collate/transform/char/3.cc
new file mode 100644 (file)
index 0000000..a6255af
--- /dev/null
@@ -0,0 +1,93 @@
+// 2003-02-24 Petur Runolfsson <peturr02@ru.is>
+
+// 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.4.1.1 collate members
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+void test03()
+{
+  using namespace std;
+  typedef std::collate<char>::string_type string_type;
+
+  bool test = true;
+
+  // basic construction
+  locale loc_c = locale::classic();
+  locale loc_de("de_DE");
+  VERIFY( loc_c != loc_de );
+
+  // cache the collate facets
+  const collate<char>& coll_c = use_facet<collate<char> >(loc_c); 
+  const collate<char>& coll_de = use_facet<collate<char> >(loc_de); 
+
+  const char* strlit1 = "a\0a\0";
+  const char* strlit2 = "a\0b\0";
+  const char* strlit3 = "a\0\xc4\0";
+  const char* strlit4 = "a\0B\0";
+  const char* strlit5 = "aa\0";
+  const char* strlit6 = "b\0a\0";
+
+  int i;
+  string_type str1;
+  string_type str2;
+
+  str1 = coll_c.transform(strlit1, strlit1 + 3);
+  str2 = coll_c.transform(strlit2, strlit2 + 3);
+  i = str1.compare(str2);
+  VERIFY( i < 0 );
+
+  str1 = coll_de.transform(strlit1, strlit1 + 3);
+  str2 = coll_de.transform(strlit2, strlit2 + 3);
+  i = str1.compare(str2);
+  VERIFY( i < 0 );
+
+  str1 = coll_c.transform(strlit3, strlit3 + 3);
+  str2 = coll_c.transform(strlit4, strlit4 + 3);
+  i = str1.compare(str2);
+  VERIFY( i > 0 );
+
+  str1 = coll_de.transform(strlit3, strlit3 + 3);
+  str2 = coll_de.transform(strlit4, strlit4 + 3);
+  i = str1.compare(str2);
+  VERIFY( i < 0 );
+
+  str1 = coll_c.transform(strlit1, strlit1 + 1);
+  str2 = coll_c.transform(strlit5, strlit5 + 1);
+  i = str1.compare(str2);
+  VERIFY( i == 0 );
+
+  str1 = coll_de.transform(strlit6, strlit6 + 3);
+  str2 = coll_de.transform(strlit1, strlit1 + 3);
+  i = str1.compare(str2);
+  VERIFY( i > 0 );
+
+  str1 = coll_c.transform(strlit1, strlit1 + 3);
+  str2 = coll_c.transform(strlit5, strlit5 + 3);
+  i = str1.compare(str2);
+  VERIFY( i < 0 );
+}
+
+int main()
+{
+  test03();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/3.cc b/libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/3.cc
new file mode 100644 (file)
index 0000000..108c0a4
--- /dev/null
@@ -0,0 +1,93 @@
+// 2003-02-24 Petur Runolfsson <peturr02@ru.is>
+
+// 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.4.1.1 collate members
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+void test03()
+{
+  using namespace std;
+  typedef std::collate<wchar_t>::string_type string_type;
+
+  bool test = true;
+
+  // basic construction
+  locale loc_c = locale::classic();
+  locale loc_de("de_DE");
+  VERIFY( loc_c != loc_de );
+
+  // cache the collate facets
+  const collate<wchar_t>& coll_c = use_facet<collate<wchar_t> >(loc_c); 
+  const collate<wchar_t>& coll_de = use_facet<collate<wchar_t> >(loc_de); 
+
+  const wchar_t* strlit1 = L"a\0a\0";
+  const wchar_t* strlit2 = L"a\0b\0";
+  const wchar_t* strlit3 = L"a\0\xc4\0";
+  const wchar_t* strlit4 = L"a\0B\0";
+  const wchar_t* strlit5 = L"aa\0";
+  const wchar_t* strlit6 = L"b\0a\0";
+
+  int i;
+  string_type str1;
+  string_type str2;
+
+  str1 = coll_c.transform(strlit1, strlit1 + 3);
+  str2 = coll_c.transform(strlit2, strlit2 + 3);
+  i = str1.compare(str2);
+  VERIFY( i < 0 );
+
+  str1 = coll_de.transform(strlit1, strlit1 + 3);
+  str2 = coll_de.transform(strlit2, strlit2 + 3);
+  i = str1.compare(str2);
+  VERIFY( i < 0 );
+
+  str1 = coll_c.transform(strlit3, strlit3 + 3);
+  str2 = coll_c.transform(strlit4, strlit4 + 3);
+  i = str1.compare(str2);
+  VERIFY( i > 0 );
+
+  str1 = coll_de.transform(strlit3, strlit3 + 3);
+  str2 = coll_de.transform(strlit4, strlit4 + 3);
+  i = str1.compare(str2);
+  VERIFY( i < 0 );
+
+  str1 = coll_c.transform(strlit1, strlit1 + 1);
+  str2 = coll_c.transform(strlit5, strlit5 + 1);
+  i = str1.compare(str2);
+  VERIFY( i == 0 );
+
+  str1 = coll_de.transform(strlit6, strlit6 + 3);
+  str2 = coll_de.transform(strlit1, strlit1 + 3);
+  i = str1.compare(str2);
+  VERIFY( i > 0 );
+
+  str1 = coll_c.transform(strlit1, strlit1 + 3);
+  str2 = coll_c.transform(strlit5, strlit5 + 3);
+  i = str1.compare(str2);
+  VERIFY( i < 0 );
+}
+
+int main()
+{
+  test03();
+  return 0;
+}