re PR libstdc++/13341 (ctype<wchar_t>::do_narrow(wchar_t, char) is slow)

2003-12-12  Paolo Carlini  <pcarlini@suse.de>
	    Benjamin Kosnik  <bkoz@redhat.com>

	PR libstdc++/13341
	* include/bits/locale_facets.h (ctype<wchar_t>): Declare
	_M_initialize_ctype() and _M_narrow_ok, _M_narrow and _M_widen.
	* src/ctype.cc (ctype<wchar_t>::ctype(size_t),
	ctype<wchar_t>::ctype(__c_locale, size_t)): Use
	_M_initialize_ctype to fill _M_narrow and _M_widen.
	(ctype_byname<wchar_t>::ctype_byname(const char*, size_t)):
	Likewise.
	* config/locale/generic/ctype_members.cc (do_narrow, do_widen)
	Use _M_narrow and _M_widen when possible, instead of calling
	wctob and btowc, respectively.
	(_M_initialize_ctype): Define, it fills at construction time
	_M_narrow and _M_widen.
	* config/locale/gnu/ctype_members.cc: Likewise.
	* testsuite/performance/narrow_widen_wchar_t.cc: New.

Co-Authored-By: Benjamin Kosnik <bkoz@redhat.com>

From-SVN: r74580
This commit is contained in:
Paolo Carlini 2003-12-12 19:44:17 +00:00 committed by Paolo Carlini
parent e00853fd90
commit e3c0c0989b
6 changed files with 212 additions and 24 deletions

View File

@ -1,3 +1,22 @@
2003-12-12 Paolo Carlini <pcarlini@suse.de>
Benjamin Kosnik <bkoz@redhat.com>
PR libstdc++/13341
* include/bits/locale_facets.h (ctype<wchar_t>): Declare
_M_initialize_ctype() and _M_narrow_ok, _M_narrow and _M_widen.
* src/ctype.cc (ctype<wchar_t>::ctype(size_t),
ctype<wchar_t>::ctype(__c_locale, size_t)): Use
_M_initialize_ctype to fill _M_narrow and _M_widen.
(ctype_byname<wchar_t>::ctype_byname(const char*, size_t)):
Likewise.
* config/locale/generic/ctype_members.cc (do_narrow, do_widen)
Use _M_narrow and _M_widen when possible, instead of calling
wctob and btowc, respectively.
(_M_initialize_ctype): Define, it fills at construction time
_M_narrow and _M_widen.
* config/locale/gnu/ctype_members.cc: Likewise.
* testsuite/performance/narrow_widen_wchar_t.cc: New.
2003-12-12 Jonathan Wakely <redi@gcc.gnu.org>
* docs/html/faq/index.txt: Regenerate after adding <link> tags.

View File

@ -185,7 +185,12 @@ namespace std
wchar_t
ctype<wchar_t>::
do_widen(char __c) const
{ return btowc(static_cast<unsigned char>(__c)); }
{
const unsigned char __uc = static_cast<unsigned char>(__c);
if (__uc < 128)
return _M_widen[__uc];
return btowc(__uc);
}
const char*
ctype<wchar_t>::
@ -193,7 +198,11 @@ namespace std
{
while (__lo < __hi)
{
*__dest = btowc(static_cast<unsigned char>(*__lo));
const unsigned char __uc = static_cast<unsigned char>(*__lo);
if (__uc < 128)
*__dest = _M_widen[__uc];
else
*__dest = btowc(__uc);
++__lo;
++__dest;
}
@ -204,7 +213,9 @@ namespace std
ctype<wchar_t>::
do_narrow(wchar_t __wc, char __dfault) const
{
int __c = wctob(__wc);
if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
return _M_narrow[__wc];
const int __c = wctob(__wc);
return (__c == EOF ? __dfault : static_cast<char>(__c));
}
@ -213,14 +224,48 @@ namespace std
do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault,
char* __dest) const
{
while (__lo < __hi)
{
int __c = wctob(*__lo);
*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++__lo;
++__dest;
}
if (_M_narrow_ok)
while (__lo < __hi)
{
if (*__lo >= 0 && *__lo < 128)
*__dest = _M_narrow[*__lo];
else
{
const int __c = wctob(*__lo);
*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
}
++__lo;
++__dest;
}
else
while (__lo < __hi)
{
const int __c = wctob(*__lo);
*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++__lo;
++__dest;
}
return __hi;
}
void
ctype<wchar_t>::_M_initialize_ctype()
{
wint_t __i;
for (__i = 0; __i < 128; ++__i)
{
const int __c = wctob(__i);
if (__c == EOF)
break;
else
_M_narrow[__i] = static_cast<char>(__c);
}
if (__i == 128)
_M_narrow_ok = true;
else
_M_narrow_ok = false;
for (int __i = 0; __i < 128; ++__i)
_M_widen[__i] = btowc(__i);
}
#endif // _GLIBCXX_USE_WCHAR_T
}

View File

@ -192,14 +192,17 @@ namespace std
ctype<wchar_t>::
do_widen(char __c) const
{
const unsigned char __uc = static_cast<unsigned char>(__c);
if (__uc < 128)
return _M_widen[__uc];
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__c_locale __old = __uselocale(_M_c_locale_ctype);
#endif
wchar_t __ret = btowc(static_cast<unsigned char>(__c));
const wchar_t __wc = btowc(__uc);
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__uselocale(__old);
#endif
return __ret;
return __wc;
}
const char*
@ -211,7 +214,11 @@ namespace std
#endif
while (__lo < __hi)
{
*__dest = btowc(static_cast<unsigned char>(*__lo));
const unsigned char __uc = static_cast<unsigned char>(*__lo);
if (__uc < 128)
*__dest = _M_widen[__uc];
else
*__dest = btowc(__uc);
++__lo;
++__dest;
}
@ -225,10 +232,12 @@ namespace std
ctype<wchar_t>::
do_narrow(wchar_t __wc, char __dfault) const
{
if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
return _M_narrow[__wc];
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__c_locale __old = __uselocale(_M_c_locale_ctype);
#endif
int __c = wctob(__wc);
const int __c = wctob(__wc);
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__uselocale(__old);
#endif
@ -243,17 +252,57 @@ namespace std
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__c_locale __old = __uselocale(_M_c_locale_ctype);
#endif
while (__lo < __hi)
{
int __c = wctob(*__lo);
*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++__lo;
++__dest;
}
if (_M_narrow_ok)
while (__lo < __hi)
{
if (*__lo >= 0 && *__lo < 128)
*__dest = _M_narrow[*__lo];
else
{
const int __c = wctob(*__lo);
*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
}
++__lo;
++__dest;
}
else
while (__lo < __hi)
{
const int __c = wctob(*__lo);
*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++__lo;
++__dest;
}
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__uselocale(__old);
#endif
return __hi;
}
void
ctype<wchar_t>::_M_initialize_ctype()
{
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__c_locale __old = __uselocale(_M_c_locale_ctype);
#endif
wint_t __i;
for (__i = 0; __i < 128; ++__i)
{
const int __c = wctob(__i);
if (__c == EOF)
break;
else
_M_narrow[__i] = static_cast<char>(__c);
}
if (__i == 128)
_M_narrow_ok = true;
else
_M_narrow_ok = false;
for (int __i = 0; __i < 128; ++__i)
_M_widen[__i] = btowc(__i);
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
__uselocale(__old);
#endif
}
#endif // _GLIBCXX_USE_WCHAR_T
}

View File

@ -446,6 +446,11 @@ namespace std
protected:
__c_locale _M_c_locale_ctype;
// Pre-computed narrowed and widened chars in the range 0-127.
bool _M_narrow_ok;
char _M_narrow[128];
wint_t _M_widen[128];
public:
// Data Members:
static locale::id id;
@ -500,6 +505,10 @@ namespace std
virtual const char_type*
do_narrow(const char_type* __lo, const char_type* __hi,
char __dfault, char* __dest) const;
// For use at construction time only.
void
_M_initialize_ctype();
};
template<>

View File

@ -87,11 +87,17 @@ namespace std
#ifdef _GLIBCXX_USE_WCHAR_T
ctype<wchar_t>::ctype(size_t __refs)
: __ctype_abstract_base<wchar_t>(__refs)
{ _M_c_locale_ctype = _S_get_c_locale(); }
{
_M_c_locale_ctype = _S_get_c_locale();
_M_initialize_ctype();
}
ctype<wchar_t>::ctype(__c_locale __cloc, size_t __refs)
: __ctype_abstract_base<wchar_t>(__refs)
{ _M_c_locale_ctype = _S_clone_c_locale(__cloc); }
{
_M_c_locale_ctype = _S_clone_c_locale(__cloc);
_M_initialize_ctype();
}
ctype<wchar_t>::~ctype()
{ _S_destroy_c_locale(_M_c_locale_ctype); }
@ -103,7 +109,8 @@ namespace std
if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
{
_S_destroy_c_locale(_M_c_locale_ctype);
_S_create_c_locale(_M_c_locale_ctype, __s);
_S_create_c_locale(_M_c_locale_ctype, __s);
_M_initialize_ctype();
}
}
#endif

View File

@ -0,0 +1,59 @@
// Copyright (C) 2003 Free Software Foundation, Inc.
//
// 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.
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
#include <locale>
#include <testsuite_performance.h>
int main()
{
using namespace std;
using namespace __gnu_test;
time_counter time;
resource_counter resource;
const long iters = 200000000;
locale loc;
const ctype<wchar_t>& ct = use_facet<ctype<wchar_t> >(loc);
// narrow
start_counters(time, resource);
for (long i = 0; i < iters; ++i)
ct.narrow(i % 128, '*');
stop_counters(time, resource);
report_performance(__FILE__, "narrow", time, resource);
clear_counters(time, resource);
// widen
start_counters(time, resource);
for (long i = 0; i < iters; ++i)
ct.widen(i % 128);
stop_counters(time, resource);
report_performance(__FILE__, "widen", time, resource);
return 0;
}