aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorPaolo Carlini <pcarlini@suse.de>2006-07-11 11:21:38 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2006-07-11 11:21:38 +0000
commit36bb088b048126eb29c92a5def5c2f7fe65b2700 (patch)
tree252b02320f7138f79ec6e29074172cb3a0442ce6 /libstdc++-v3
parent9d6a4afbc8eac608855512c43de5dd939efc06b3 (diff)
downloadgcc-36bb088b048126eb29c92a5def5c2f7fe65b2700.zip
gcc-36bb088b048126eb29c92a5def5c2f7fe65b2700.tar.gz
gcc-36bb088b048126eb29c92a5def5c2f7fe65b2700.tar.bz2
PR libstdc++/28277 (partial: collate bits)
2006-07-11 Paolo Carlini <pcarlini@suse.de> PR libstdc++/28277 (partial: collate bits) * include/bits/locale_facets.tcc (collate<>::do_transform( const _CharT*, const _CharT*)): Avoid __builtin_alloca with no limit; also avoid multiple calls (in a loop). * testsuite/22_locale/collate/transform/char/28277.cc: New. * testsuite/22_locale/collate/transform/wchar_t/28277.cc: Likewise. From-SVN: r115332
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog9
-rw-r--r--libstdc++-v3/include/bits/locale_facets.tcc75
-rw-r--r--libstdc++-v3/testsuite/22_locale/collate/transform/char/28277.cc52
-rw-r--r--libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/28277.cc52
4 files changed, 160 insertions, 28 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 774b3df..249e6ac 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,12 @@
+2006-07-11 Paolo Carlini <pcarlini@suse.de>
+
+ PR libstdc++/28277 (partial: collate bits)
+ * include/bits/locale_facets.tcc (collate<>::do_transform(
+ const _CharT*, const _CharT*)): Avoid __builtin_alloca with no
+ limit; also avoid multiple calls (in a loop).
+ * testsuite/22_locale/collate/transform/char/28277.cc: New.
+ * testsuite/22_locale/collate/transform/wchar_t/28277.cc: Likewise.
+
2006-07-10 Mike Stump <mrs@apple.com>
* libsupc++/eh_globals.cc (~__eh_globals_init): Unset _M_init.
diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
index a889e01..ad45863 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -2455,43 +2455,62 @@ _GLIBCXX_END_LDBL_NAMESPACE
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);
+ string_type __ret;
- const _CharT* __p = __str.c_str();
- const _CharT* __pend = __str.data() + __str.length();
+ // Use alloca for an _M_transform temporary buffer up to an arbitrary,
+ // but limited, asize, to avoid abusing the stack. Otherwise fall back
+ // to dynamic memory allocation. This means splitting the computation
+ // itself in hunks: a size <= 8k (thus <= 16k asize) appear sufficient
+ // for optimal performance.
+ const size_t __size = std::min(size_t(__hi - __lo), size_t(8192));
+ const size_t __asize = 2 * __size;
- size_t __len = (__hi - __lo) * 2;
+ size_t __len = __asize;
- string_type __ret;
+ _CharT* __c =
+ static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
- // strxfrm stops when it sees a nul character so we break
- // the string into zero-terminated substrings and pass those
- // to strxfrm.
- for (;;)
+ for (size_t __hunk = __size; __lo < __hi;
+ __lo += __hunk, __hunk = std::min(size_t(__hi - __lo), __hunk))
{
- // 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)
+ // strxfrm assumes zero-terminated strings so we make a copy
+ const string_type __str(__lo, __lo + __hunk);
+
+ const _CharT* __p = __str.c_str();
+ const _CharT* __pend = __str.data() + __hunk;
+
+ // strxfrm stops when it sees a nul character so we break
+ // the string into zero-terminated substrings and pass those
+ // to strxfrm.
+ for (;;)
{
- __len = __res + 1;
- __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
- * __len));
- __res = _M_transform(__c, __p, __len);
- }
+ // First try a buffer perhaps big enough.
+ size_t __res = _M_transform(__c, __p, __len);
+ // If the buffer was not large enough, try again with the
+ // correct size.
+ if (__res >= __len)
+ {
+ if (__len > __asize)
+ delete [] __c;
+ __len = __res + 1;
+ __c = new _CharT[__len];
+ __res = _M_transform(__c, __p, __len);
+ }
- __ret.append(__c, __res);
- __p += char_traits<_CharT>::length(__p);
- if (__p == __pend)
- return __ret;
+ __ret.append(__c, __res);
+ __p += char_traits<_CharT>::length(__p);
+ if (__p == __pend)
+ break;
- __p++;
- __ret.push_back(_CharT());
+ __p++;
+ __ret.push_back(_CharT());
+ }
}
+
+ if (__len > __asize)
+ delete [] __c;
+
+ return __ret;
}
template<typename _CharT>
diff --git a/libstdc++-v3/testsuite/22_locale/collate/transform/char/28277.cc b/libstdc++-v3/testsuite/22_locale/collate/transform/char/28277.cc
new file mode 100644
index 0000000..c81cdaa
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/collate/transform/char/28277.cc
@@ -0,0 +1,52 @@
+// 2006-07-11 Paolo Carlini <pcarlini@suse.de>
+
+// Copyright (C) 2006 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 22.2.4.1.1 collate members
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+// libstdc++/28277
+void test01()
+{
+ using namespace std;
+ typedef collate<char>::string_type string_type;
+
+ bool test __attribute__((unused)) = true;
+
+ // basic construction
+ locale loc_c = locale::classic();
+
+ // cache the collate facets
+ const collate<char>& coll_c = use_facet<collate<char> >(loc_c);
+
+ const string_type sstr(10000000, 'a');
+
+ const string_type dstr = coll_c.transform(sstr.data(),
+ sstr.data() + sstr.size());
+
+ VERIFY( dstr == sstr );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/28277.cc b/libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/28277.cc
new file mode 100644
index 0000000..3a9fbb9
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/collate/transform/wchar_t/28277.cc
@@ -0,0 +1,52 @@
+// 2006-07-11 Paolo Carlini <pcarlini@suse.de>
+
+// Copyright (C) 2006 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 22.2.4.1.1 collate members
+
+#include <locale>
+#include <testsuite_hooks.h>
+
+// libstdc++/28277
+void test01()
+{
+ using namespace std;
+ typedef collate<wchar_t>::string_type string_type;
+
+ bool test __attribute__((unused)) = true;
+
+ // basic construction
+ locale loc_c = locale::classic();
+
+ // cache the collate facets
+ const collate<wchar_t>& coll_c = use_facet<collate<wchar_t> >(loc_c);
+
+ const string_type sstr(10000000, L'a');
+
+ const string_type dstr = coll_c.transform(sstr.data(),
+ sstr.data() + sstr.size());
+
+ VERIFY( dstr == sstr );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}