diff options
author | Paolo Carlini <pcarlini@suse.de> | 2003-12-12 19:44:17 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2003-12-12 19:44:17 +0000 |
commit | e3c0c0989b614b5ce3e968ff49a12eaddebc0d76 (patch) | |
tree | a54b8363ab8d9576e500c8c1d21398142cdd9d19 | |
parent | e00853fd9010af463931114e469875303b7bf876 (diff) | |
download | gcc-e3c0c0989b614b5ce3e968ff49a12eaddebc0d76.zip gcc-e3c0c0989b614b5ce3e968ff49a12eaddebc0d76.tar.gz gcc-e3c0c0989b614b5ce3e968ff49a12eaddebc0d76.tar.bz2 |
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
-rw-r--r-- | libstdc++-v3/ChangeLog | 19 | ||||
-rw-r--r-- | libstdc++-v3/config/locale/generic/ctype_members.cc | 63 | ||||
-rw-r--r-- | libstdc++-v3/config/locale/gnu/ctype_members.cc | 69 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/locale_facets.h | 9 | ||||
-rw-r--r-- | libstdc++-v3/src/ctype.cc | 13 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/performance/narrow_widen_wchar_t.cc | 59 |
6 files changed, 210 insertions, 22 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 8c5a764..27e23bf 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -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. diff --git a/libstdc++-v3/config/locale/generic/ctype_members.cc b/libstdc++-v3/config/locale/generic/ctype_members.cc index 71175f1..517df4c 100644 --- a/libstdc++-v3/config/locale/generic/ctype_members.cc +++ b/libstdc++-v3/config/locale/generic/ctype_members.cc @@ -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) + 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) { - int __c = wctob(*__lo); - *__dest = (__c == EOF ? __dfault : static_cast<char>(__c)); - ++__lo; - ++__dest; + const int __c = wctob(__i); + if (__c == EOF) + break; + else + _M_narrow[__i] = static_cast<char>(__c); } - return __hi; + 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 } diff --git a/libstdc++-v3/config/locale/gnu/ctype_members.cc b/libstdc++-v3/config/locale/gnu/ctype_members.cc index a5394b5..673b511 100644 --- a/libstdc++-v3/config/locale/gnu/ctype_members.cc +++ b/libstdc++-v3/config/locale/gnu/ctype_members.cc @@ -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) + 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) { - int __c = wctob(*__lo); - *__dest = (__c == EOF ? __dfault : static_cast<char>(__c)); - ++__lo; - ++__dest; + 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 - return __hi; } #endif // _GLIBCXX_USE_WCHAR_T } diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index a61ac9f..7a24b9b 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -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<> diff --git a/libstdc++-v3/src/ctype.cc b/libstdc++-v3/src/ctype.cc index 7fb5c2d..b0888c5 100644 --- a/libstdc++-v3/src/ctype.cc +++ b/libstdc++-v3/src/ctype.cc @@ -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 diff --git a/libstdc++-v3/testsuite/performance/narrow_widen_wchar_t.cc b/libstdc++-v3/testsuite/performance/narrow_widen_wchar_t.cc new file mode 100644 index 0000000..1081bf5 --- /dev/null +++ b/libstdc++-v3/testsuite/performance/narrow_widen_wchar_t.cc @@ -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; +} |