diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 27e23bf5482..e0f17c36b83 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,23 @@ +2003-12-15 Paolo Carlini + + * include/bits/locale_facets.tcc (num_get::do_get(bool&)): + Fail as soon as the begins of both truename and falsename + stop to match; always leave __beg one position beyond the + last char successfully matched. + * testsuite/22_locale/num_get/get/char/8.cc: New. + * testsuite/22_locale/num_get/get/wchar_t/8.cc: Likewise. + +2003-12-15 Paolo Carlini + + * include/bits/locale_facets.h (_M_widen): Reserve space + for all the possible widened chars. + * config/locale/generic/ctype_members.cc (_M_initialize_ctype): + Compute at construction time all the possible widened chars. + (do_widen): Tweak, simplify. + * config/locale/gnu/ctype_members.cc: Likewise. + * testsuite/performance/narrow_widen_wchar_t.cc: Add tests + for the array versions. + 2003-12-12 Paolo Carlini Benjamin Kosnik diff --git a/libstdc++-v3/config/locale/generic/ctype_members.cc b/libstdc++-v3/config/locale/generic/ctype_members.cc index 517df4c2187..e94d447a251 100644 --- a/libstdc++-v3/config/locale/generic/ctype_members.cc +++ b/libstdc++-v3/config/locale/generic/ctype_members.cc @@ -185,12 +185,7 @@ namespace std wchar_t ctype:: do_widen(char __c) const - { - const unsigned char __uc = static_cast(__c); - if (__uc < 128) - return _M_widen[__uc]; - return btowc(__uc); - } + { return _M_widen[static_cast(__c)]; } const char* ctype:: @@ -198,11 +193,7 @@ namespace std { while (__lo < __hi) { - const unsigned char __uc = static_cast(*__lo); - if (__uc < 128) - *__dest = _M_widen[__uc]; - else - *__dest = btowc(__uc); + *__dest = _M_widen[static_cast(*__lo)]; ++__lo; ++__dest; } @@ -264,7 +255,8 @@ namespace std _M_narrow_ok = true; else _M_narrow_ok = false; - for (int __i = 0; __i < 128; ++__i) + for (size_t __i = 0; + __i < sizeof(_M_widen) / sizeof(wint_t); ++__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 673b511e5cd..998737b273d 100644 --- a/libstdc++-v3/config/locale/gnu/ctype_members.cc +++ b/libstdc++-v3/config/locale/gnu/ctype_members.cc @@ -191,47 +191,25 @@ namespace std wchar_t ctype:: do_widen(char __c) const - { - const unsigned char __uc = static_cast(__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 - const wchar_t __wc = btowc(__uc); -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) - __uselocale(__old); -#endif - return __wc; - } + { return _M_widen[static_cast(__c)]; } const char* ctype:: do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const { -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) - __c_locale __old = __uselocale(_M_c_locale_ctype); -#endif while (__lo < __hi) { - const unsigned char __uc = static_cast(*__lo); - if (__uc < 128) - *__dest = _M_widen[__uc]; - else - *__dest = btowc(__uc); + *__dest = _M_widen[static_cast(*__lo)]; ++__lo; ++__dest; } -#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) - __uselocale(__old); -#endif return __hi; } char ctype:: 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) @@ -298,7 +276,8 @@ namespace std _M_narrow_ok = true; else _M_narrow_ok = false; - for (int __i = 0; __i < 128; ++__i) + for (size_t __i = 0; + __i < sizeof(_M_widen) / sizeof(wint_t); ++__i) _M_widen[__i] = btowc(__i); #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) __uselocale(__old); diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index 7a24b9b30fe..83d77c81119 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -446,10 +446,10 @@ namespace std protected: __c_locale _M_c_locale_ctype; - // Pre-computed narrowed and widened chars in the range 0-127. - bool _M_narrow_ok; + // Pre-computed narrowed and widened chars. + bool _M_narrow_ok; char _M_narrow[128]; - wint_t _M_widen[128]; + wint_t _M_widen[1 + static_cast(-1)]; public: // Data Members: diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index a583e0e07ba..84f0b887852 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -473,38 +473,36 @@ namespace std __use_cache<__cache_type> __uc; const locale& __loc = __io._M_getloc(); const __cache_type* __lc = __uc(__loc); - const size_t __tn = __traits_type::length(__lc->_M_truename) - 1; - const size_t __fn = __traits_type::length(__lc->_M_falsename) - 1; + const size_t __tn = __traits_type::length(__lc->_M_truename); + const size_t __fn = __traits_type::length(__lc->_M_falsename); - bool __testf = false; - bool __testt = false; - for (size_t __n = 0; __beg != __end; ++__n) + bool __testf = true; + bool __testt = true; + size_t __n; + for (__n = 0; __beg != __end; ++__n, ++__beg) { - const char_type __c = *__beg; - ++__beg; + if (__testf) + if (__n < __fn) + __testf = __traits_type::eq(*__beg, __lc->_M_falsename[__n]); + else + break; - if (__n <= __fn) - __testf = __traits_type::eq(__c, __lc->_M_falsename[__n]); + if (__testt) + if (__n < __tn) + __testt = __traits_type::eq(*__beg, __lc->_M_truename[__n]); + else + break; - if (__n <= __tn) - __testt = __traits_type::eq(__c, __lc->_M_truename[__n]); - - if (!(__testf || __testt)) - { - __err |= ios_base::failbit; - break; - } - else if (__testf && __n == __fn) - { - __v = 0; - break; - } - else if (__testt && __n == __tn) - { - __v = 1; - break; - } + if (!__testf && !__testt) + break; } + if (__testf && __n == __fn) + __v = 0; + else if (__testt && __n == __tn) + __v = 1; + else + __err |= ios_base::failbit; + if (__beg == __end) __err |= ios_base::eofbit; } diff --git a/libstdc++-v3/testsuite/22_locale/num_get/get/char/8.cc b/libstdc++-v3/testsuite/22_locale/num_get/get/char/8.cc new file mode 100644 index 00000000000..d3f24f972de --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_get/get/char/8.cc @@ -0,0 +1,70 @@ +// 2003-12-15 Paolo Carlini + +// Copyright (C) 2003 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 22.2.2.1.1 num_get members + +#include +#include +#include + +void test01() +{ + using namespace std; + typedef istreambuf_iterator iterator_type; + + bool test __attribute__((unused)) = true; + + bool b; + + // cache the num_get facet + istringstream iss; + const num_get& ng = use_facet >(iss.getloc()); + const ios_base::iostate goodbit = ios_base::goodbit; + const ios_base::iostate failbit = ios_base::failbit; + ios_base::iostate err; + iterator_type end; + + iss.setf(ios_base::boolalpha); + iss.str("faLse"); + err = goodbit; + end = ng.get(iss.rdbuf(), 0, iss, err, b); + VERIFY( *end == 'L' ); + VERIFY( err == failbit ); + + iss.str("falsr"); + iss.clear(); + err = goodbit; + end = ng.get(iss.rdbuf(), 0, iss, err, b); + VERIFY( *end == 'r' ); + VERIFY( err == failbit ); + + iss.str("trus"); + iss.clear(); + err = goodbit; + end = ng.get(iss.rdbuf(), 0, iss, err, b); + VERIFY( *end == 's' ); + VERIFY( err == failbit ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/8.cc b/libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/8.cc new file mode 100644 index 00000000000..fbba3a5553a --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/num_get/get/wchar_t/8.cc @@ -0,0 +1,70 @@ +// 2003-12-15 Paolo Carlini + +// Copyright (C) 2003 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, +// USA. + +// 22.2.2.1.1 num_get members + +#include +#include +#include + +void test01() +{ + using namespace std; + typedef istreambuf_iterator iterator_type; + + bool test __attribute__((unused)) = true; + + bool b; + + // cache the num_get facet + wistringstream iss; + const num_get& ng = use_facet >(iss.getloc()); + const ios_base::iostate goodbit = ios_base::goodbit; + const ios_base::iostate failbit = ios_base::failbit; + ios_base::iostate err; + iterator_type end; + + iss.setf(ios_base::boolalpha); + iss.str(L"faLse"); + err = goodbit; + end = ng.get(iss.rdbuf(), 0, iss, err, b); + VERIFY( *end == L'L' ); + VERIFY( err == failbit ); + + iss.str(L"falsr"); + iss.clear(); + err = goodbit; + end = ng.get(iss.rdbuf(), 0, iss, err, b); + VERIFY( *end == L'r' ); + VERIFY( err == failbit ); + + iss.str(L"trus"); + iss.clear(); + err = goodbit; + end = ng.get(iss.rdbuf(), 0, iss, err, b); + VERIFY( *end == L's' ); + VERIFY( err == failbit ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/performance/narrow_widen_wchar_t.cc b/libstdc++-v3/testsuite/performance/narrow_widen_wchar_t.cc index 1081bf56452..053f8072610 100644 --- a/libstdc++-v3/testsuite/performance/narrow_widen_wchar_t.cc +++ b/libstdc++-v3/testsuite/performance/narrow_widen_wchar_t.cc @@ -35,25 +35,41 @@ int main() time_counter time; resource_counter resource; - const long iters = 200000000; + wchar_t bufwc[] = L"M'innamoravo di tutto (Fabrizio De Andre')"; + char bufc[sizeof(bufwc) / sizeof(wchar_t)]; locale loc; const ctype& ct = use_facet >(loc); // narrow start_counters(time, resource); - for (long i = 0; i < iters; ++i) + for (long i = 0; i < 200000000; ++i) ct.narrow(i % 128, '*'); stop_counters(time, resource); report_performance(__FILE__, "narrow", time, resource); clear_counters(time, resource); + // narrow array + start_counters(time, resource); + for (long i = 0; i < 20000000; ++i) + ct.narrow(bufwc, bufwc + sizeof(bufwc) / sizeof(wchar_t), '*', bufc); + stop_counters(time, resource); + report_performance(__FILE__, "narrow array", time, resource); + clear_counters(time, resource); + // widen start_counters(time, resource); - for (long i = 0; i < iters; ++i) + for (long i = 0; i < 200000000; ++i) ct.widen(i % 128); stop_counters(time, resource); report_performance(__FILE__, "widen", time, resource); + // widen array + start_counters(time, resource); + for (long i = 0; i < 20000000; ++i) + ct.widen(bufc, bufc + sizeof(bufc), bufwc); + stop_counters(time, resource); + report_performance(__FILE__, "widen array", time, resource); + return 0; }