+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.
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>::
{
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;
}
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));
}
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
}
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*
#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;
}
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
#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
}
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;
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<>
#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); }
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
--- /dev/null
+// 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;
+}