From 82ce2a94d9c0782c0e88fabe924e90a050f56ac8 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Tue, 15 Feb 2005 23:29:52 +0000 Subject: [PATCH] re PR libstdc++/19955 (Second std::ctype::narrow() does not call std::ctype::do_narrow()) 2005-02-15 Paolo Carlini Jon Grimm PR libstdc++/19955 * include/bits/locale_facets.h (ctype::_M_narrow_init()): Fix the logic setting _M_narrow_ok: first check whether the transformation is trivial with a dflt == 0, then deal with the special case of zero. * testsuite/22_locale/ctype/narrow/char/19955.cc: New. * include/bits/locale_facets.h (ctype::_M_widen_init()): Tweak consistently to use memcmp; minor formatting fixes. Co-Authored-By: Jon Grimm From-SVN: r95082 --- libstdc++-v3/ChangeLog | 13 +++ libstdc++-v3/include/bits/locale_facets.h | 54 +++++------ .../testsuite/22_locale/ctype/narrow/char/19955.cc | 105 +++++++++++++++++++++ 3 files changed, 143 insertions(+), 29 deletions(-) create mode 100644 libstdc++-v3/testsuite/22_locale/ctype/narrow/char/19955.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index afdac30..0d5155b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2005-02-15 Paolo Carlini + Jon Grimm + + PR libstdc++/19955 + * include/bits/locale_facets.h (ctype::_M_narrow_init()): + Fix the logic setting _M_narrow_ok: first check whether the + transformation is trivial with a dflt == 0, then deal with the + special case of zero. + * testsuite/22_locale/ctype/narrow/char/19955.cc: New. + + * include/bits/locale_facets.h (ctype::_M_widen_init()): + Tweak consistently to use memcmp; minor formatting fixes. + 2005-02-15 Jakub Jelinek PR libstdc++/19946 diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index 922ee21..152170e 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -1,6 +1,6 @@ // Locale support -*- C++ -*- -// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 // Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free @@ -690,7 +690,7 @@ namespace std mutable char _M_widen[1 + static_cast(-1)]; mutable char _M_narrow[1 + static_cast(-1)]; mutable char _M_narrow_ok; // 0 uninitialized, 1 init, - // 2 non-consecutive + // 2 memcpy can't be used public: /// The facet id for ctype @@ -865,7 +865,8 @@ namespace std char_type widen(char __c) const { - if (_M_widen_ok) return _M_widen[static_cast(__c)]; + if (_M_widen_ok) + return _M_widen[static_cast(__c)]; this->_M_widen_init(); return this->do_widen(__c); } @@ -896,7 +897,8 @@ namespace std memcpy(__to, __lo, __hi - __lo); return __hi; } - if (!_M_widen_ok) _M_widen_init(); + if (!_M_widen_ok) + _M_widen_init(); return this->do_widen(__lo, __hi, __to); } @@ -924,7 +926,8 @@ namespace std if (_M_narrow[static_cast(__c)]) return _M_narrow[static_cast(__c)]; const char __t = do_narrow(__c, __dfault); - if (__t != __dfault) _M_narrow[static_cast(__c)] = __t; + if (__t != __dfault) + _M_narrow[static_cast(__c)] = __t; return __t; } @@ -954,7 +957,7 @@ namespace std narrow(const char_type* __lo, const char_type* __hi, char __dfault, char *__to) const { - if (__builtin_expect(_M_narrow_ok == 1,true)) + if (__builtin_expect(_M_narrow_ok == 1, true)) { memcpy(__to, __lo, __hi - __lo); return __hi; @@ -1161,17 +1164,13 @@ namespace std _M_widen_ok = 1; // Set _M_widen_ok to 2 if memcpy can't be used. - for (size_t __j = 0; __j < sizeof(_M_widen); ++__j) - if (__tmp[__j] != _M_widen[__j]) - { - _M_widen_ok = 2; - break; - } + if (memcmp(__tmp, _M_widen, sizeof(_M_widen))) + _M_widen_ok = 2; } // Fill in the narrowing cache and flag whether all values are - // valid or not. _M_narrow_ok is set to 1 if the whole table is - // narrowed, 2 if only some values could be narrowed. + // valid or not. _M_narrow_ok is set to 2 if memcpy can't + // be used. void _M_narrow_init() const { char __tmp[sizeof(_M_narrow)]; @@ -1179,21 +1178,18 @@ namespace std __tmp[__i] = __i; do_narrow(__tmp, __tmp + sizeof(__tmp), 0, _M_narrow); - // Check if any default values were created. Do this by - // renarrowing with a different default value and comparing. - bool __consecutive = true; - for (size_t __j = 0; __j < sizeof(_M_narrow); ++__j) - if (!_M_narrow[__j]) - { - char __c; - do_narrow(__tmp + __j, __tmp + __j + 1, 1, &__c); - if (__c == 1) - { - __consecutive = false; - break; - } - } - _M_narrow_ok = __consecutive ? 1 : 2; + _M_narrow_ok = 1; + if (memcmp(__tmp, _M_narrow, sizeof(_M_narrow))) + _M_narrow_ok = 2; + else + { + // Deal with the special case of zero: renarrow with a + // different default and compare. + char __c; + do_narrow(__tmp, __tmp + 1, 1, &__c); + if (__c == 1) + _M_narrow_ok = 2; + } } }; diff --git a/libstdc++-v3/testsuite/22_locale/ctype/narrow/char/19955.cc b/libstdc++-v3/testsuite/22_locale/ctype/narrow/char/19955.cc new file mode 100644 index 0000000..4ce1da3 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/ctype/narrow/char/19955.cc @@ -0,0 +1,105 @@ +// Copyright (C) 2005 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. + +// 22.2.1.3.2 ctype members + +#include +#include + +class Ctype1 +: public std::ctype +{ +protected: + const char* + do_narrow(const char* lo, const char* hi, + char dflt, char* to) const + { + for (int i = 0; lo != hi; ++lo, ++to, ++i) + *to = *lo + i; + return hi; + } +}; + +class Ctype2 +: public std::ctype +{ +protected: + const char* + do_narrow(const char* lo, const char* hi, + char dflt, char* to) const + { + for (int i = 0; lo != hi; ++lo, ++to, ++i) + if (*lo == '\000') + *to = dflt; + else + *to = *lo; + return hi; + } +}; + +// libstdc++/19955 +void test01() +{ + using namespace std; + bool test __attribute__((unused)) = true; + + const char src[] = "abcd"; + + locale mylocale1(locale::classic(), new Ctype1); + const ctype& mc1 = use_facet >(mylocale1); + + char dst1[sizeof(src)]; + memset(dst1, 0, sizeof(src)); + char dst2[sizeof(src)]; + memset(dst2, 0, sizeof(src)); + + mc1.narrow(src, src + sizeof(src), '*', dst1); + mc1.narrow(src, src + sizeof(src), '*', dst2); + + VERIFY( !memcmp(dst1, "aceg\004", 5) ); + VERIFY( !memcmp(dst1, dst2, 5) ); + + locale mylocale2(locale::classic(), new Ctype2); + const ctype& mc2 = use_facet >(mylocale2); + + char dst3[sizeof(src)]; + memset(dst3, 0, sizeof(src)); + char dst4[sizeof(src)]; + memset(dst4, 0, sizeof(src)); + + mc2.narrow(src, src + sizeof(src), '*', dst3); + mc2.narrow(src, src + sizeof(src), '*', dst4); + + VERIFY( !memcmp(dst3, "abcd*", 5) ); + VERIFY( !memcmp(dst3, dst4, 5) ); +} + +int main() +{ + test01(); + return 0; +} -- 2.7.4