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
This commit is contained in:
Paolo Carlini 2006-07-11 11:21:38 +00:00 committed by Paolo Carlini
parent 9d6a4afbc8
commit 36bb088b04
4 changed files with 163 additions and 31 deletions

View File

@ -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.

View File

@ -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);
const _CharT* __p = __str.c_str();
const _CharT* __pend = __str.data() + __str.length();
size_t __len = (__hi - __lo) * 2;
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 (;;)
// 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 = __asize;
_CharT* __c =
static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
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)
break;
__p++;
__ret.push_back(_CharT());
}
__ret.append(__c, __res);
__p += char_traits<_CharT>::length(__p);
if (__p == __pend)
return __ret;
__p++;
__ret.push_back(_CharT());
}
if (__len > __asize)
delete [] __c;
return __ret;
}
template<typename _CharT>

View File

@ -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;
}

View File

@ -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;
}