From cde6384093dcf3f9f90babf65aea62ceb64f8755 Mon Sep 17 00:00:00 2001 From: Benjamin Kosnik Date: Thu, 10 Jul 2003 06:21:13 +0000 Subject: [PATCH] locale_facets.tcc: Use function object for __use_cache instead of template function. 2003-07-09 Benjamin Kosnik * include/bits/locale_facets.tcc: Use function object for __use_cache instead of template function. Partially specialize for __numpunct<_CharT>. * include/bits/locale_classes.h: Update friend declaration for __use_cache. (_M_install_cache): No throw exception specs. * src/locale.cc: Remove __use_cache specializations. * include/ext/pod_char_traits.h (length): Tweak. * include/bits/locale_facets.h (__numpunct_cache): Remove char_type typedef. * testsuite/testsuite_hooks.h (pod_unsigned_int): Remove. (pod_long): Remove. * testsuite/22_locale/numpunct/members/char/cache_1.cc: New. * testsuite/22_locale/numpunct/members/char/cache_2.cc: New. * testsuite/22_locale/numpunct/members/wchar_t/cache_1.cc: New. * testsuite/22_locale/numpunct/members/wchar_t/cache_2.cc: New. * testsuite/22_locale/numpunct/members/pod/1.cc: New. * testsuite/22_locale/numpunct/members/pod/2.cc: New. From-SVN: r69177 --- libstdc++-v3/ChangeLog | 21 ++ libstdc++-v3/include/bits/locale_classes.h | 8 +- libstdc++-v3/include/bits/locale_facets.h | 19 +- libstdc++-v3/include/bits/locale_facets.tcc | 74 +++-- libstdc++-v3/include/ext/pod_char_traits.h | 2 +- libstdc++-v3/src/locale.cc | 32 --- .../numpunct/members/char/cache_1.cc | 78 +++++ .../numpunct/members/char/cache_2.cc | 90 ++++++ .../22_locale/numpunct/members/pod/1.cc | 134 +++++++++ .../22_locale/numpunct/members/pod/2.cc | 267 ++++++++++++++++++ .../numpunct/members/wchar_t/cache_1.cc | 78 +++++ .../numpunct/members/wchar_t/cache_2.cc | 90 ++++++ libstdc++-v3/testsuite/testsuite_hooks.h | 10 - 13 files changed, 819 insertions(+), 84 deletions(-) create mode 100644 libstdc++-v3/testsuite/22_locale/numpunct/members/char/cache_1.cc create mode 100644 libstdc++-v3/testsuite/22_locale/numpunct/members/char/cache_2.cc create mode 100644 libstdc++-v3/testsuite/22_locale/numpunct/members/pod/1.cc create mode 100644 libstdc++-v3/testsuite/22_locale/numpunct/members/pod/2.cc create mode 100644 libstdc++-v3/testsuite/22_locale/numpunct/members/wchar_t/cache_1.cc create mode 100644 libstdc++-v3/testsuite/22_locale/numpunct/members/wchar_t/cache_2.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b5c970e50be..885f9b25fb3 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,24 @@ +2003-07-09 Benjamin Kosnik + + * include/bits/locale_facets.tcc: Use function object for + __use_cache instead of template function. Partially specialize for + __numpunct<_CharT>. + * include/bits/locale_classes.h: Update friend declaration for + __use_cache. + (_M_install_cache): No throw exception specs. + * src/locale.cc: Remove __use_cache specializations. + * include/ext/pod_char_traits.h (length): Tweak. + * include/bits/locale_facets.h (__numpunct_cache): Remove + char_type typedef. + * testsuite/testsuite_hooks.h (pod_unsigned_int): Remove. + (pod_long): Remove. + * testsuite/22_locale/numpunct/members/char/cache_1.cc: New. + * testsuite/22_locale/numpunct/members/char/cache_2.cc: New. + * testsuite/22_locale/numpunct/members/wchar_t/cache_1.cc: New. + * testsuite/22_locale/numpunct/members/wchar_t/cache_2.cc: New. + * testsuite/22_locale/numpunct/members/pod/1.cc: New. + * testsuite/22_locale/numpunct/members/pod/2.cc: New. + 2003-07-09 Jerry Quinn * src/ios.cc (_M_grow_words): Fix spelling. diff --git a/libstdc++-v3/include/bits/locale_classes.h b/libstdc++-v3/include/bits/locale_classes.h index 362e38f2767..b93cfb38142 100644 --- a/libstdc++-v3/include/bits/locale_classes.h +++ b/libstdc++-v3/include/bits/locale_classes.h @@ -73,8 +73,7 @@ namespace std use_facet(const locale&); template - friend const _Cache& - __use_cache(const locale& __loc); + friend struct __use_cache; // Category values: // NB: Order must match _S_facet_categories definition in locale.cc @@ -298,8 +297,7 @@ namespace std use_facet(const locale&); template - friend const _Cache& - __use_cache(const locale& __loc); + friend struct __use_cache; private: // Data Members. @@ -370,7 +368,7 @@ namespace std { _M_install_facet(&_Facet::id, __facet); } void - _M_install_cache(const facet* __cache, size_t __index) + _M_install_cache(const facet* __cache, size_t __index) throw() { __cache->_M_add_reference(); _M_caches[__index] = __cache; diff --git a/libstdc++-v3/include/bits/locale_facets.h b/libstdc++-v3/include/bits/locale_facets.h index 6b5a99d4ff0..cda0dcba9df 100644 --- a/libstdc++-v3/include/bits/locale_facets.h +++ b/libstdc++-v3/include/bits/locale_facets.h @@ -577,34 +577,31 @@ namespace std template struct __numpunct_cache : public locale::facet { - // Types: - typedef _CharT char_type; - const char* _M_grouping; bool _M_use_grouping; - const char_type* _M_truename; - const char_type* _M_falsename; - char_type _M_decimal_point; - char_type _M_thousands_sep; + const _CharT* _M_truename; + const _CharT* _M_falsename; + _CharT _M_decimal_point; + _CharT _M_thousands_sep; // A list of valid numeric literals for output: in the standard // "C" locale, this is "-+xX0123456789abcdef0123456789ABCDEF". // This array contains the chars after having been passed // through the current locale's ctype<_CharT>.widen(). - char_type _M_atoms_out[__num_base::_S_oend + 1]; + _CharT _M_atoms_out[__num_base::_S_oend + 1]; // A list of valid numeric literals for output: in the standard // "C" locale, this is "0123456789eEabcdfABCDF" // This array contains the chars after having been passed // through the current locale's ctype<_CharT>.widen(). - char_type _M_atoms_in[__num_base::_S_iend + 1]; + _CharT _M_atoms_in[__num_base::_S_iend + 1]; bool _M_allocated; __numpunct_cache(size_t __refs = 0) : locale::facet(__refs), _M_grouping(NULL), _M_use_grouping(false), _M_truename(NULL), - _M_falsename(NULL), _M_decimal_point(char_type()), - _M_thousands_sep(char_type()), _M_allocated(false) + _M_falsename(NULL), _M_decimal_point(_CharT()), + _M_thousands_sep(_CharT()), _M_allocated(false) { } ~__numpunct_cache(); diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index 97cec3f313d..d41b8aeeaba 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -89,18 +89,38 @@ namespace std // Routine to access a cache for the facet. If the cache didn't // exist before, it gets constructed on the fly. template - const _Facet& - __use_cache(const locale& __loc); + struct __use_cache + { + const _Facet* + operator() (const locale& __loc) const; + }; - template<> - const __numpunct_cache& - __use_cache(const locale& __loc); - -#ifdef _GLIBCXX_USE_WCHAR_T - template<> - const __numpunct_cache& - __use_cache(const locale& __loc); -#endif + template + struct __use_cache<__numpunct_cache<_CharT> > + { + const __numpunct_cache<_CharT>* + operator() (const locale& __loc) const + { + size_t __i = numpunct<_CharT>::id._M_id(); + const locale::facet** __caches = __loc._M_impl->_M_caches; + if (!__caches[__i]) + { + __numpunct_cache<_CharT>* __tmp; + try + { + __tmp = new __numpunct_cache<_CharT>; + __tmp->_M_cache(__loc); + } + catch(...) + { + delete __tmp; + __throw_exception_again; + } + __loc._M_impl->_M_install_cache(__tmp, __i); + } + return static_cast*>(__caches[__i]); + } + }; // Stage 1: Determine a conversion specifier. template @@ -785,9 +805,10 @@ namespace std _ValueT __v) const { typedef typename numpunct<_CharT>::__cache_type __cache_type; + __use_cache<__cache_type> __uc; const locale& __loc = __io._M_getloc(); - const __cache_type& __lc = __use_cache<__cache_type>(__loc); - const _CharT* __lit = __lc._M_atoms_out; + const __cache_type* __lc = __uc(__loc); + const _CharT* __lit = __lc->_M_atoms_out; // Long enough to hold hex, dec, and octal representations. int __ilen = 4 * sizeof(_ValueT); @@ -801,13 +822,13 @@ namespace std // Add grouping, if necessary. _CharT* __cs2; - if (__lc._M_use_grouping) + if (__lc->_M_use_grouping) { // Grouping can add (almost) as many separators as the // number of digits, but no more. __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len * 2)); - _M_group_int(__lc._M_grouping, __lc._M_thousands_sep, __io, + _M_group_int(__lc->_M_grouping, __lc->_M_thousands_sep, __io, __cs2, __cs, __len); __cs = __cs2; } @@ -890,8 +911,9 @@ namespace std __prec = static_cast(6); typedef typename numpunct<_CharT>::__cache_type __cache_type; + __use_cache<__cache_type> __uc; const locale& __loc = __io._M_getloc(); - const __cache_type& __lc = __use_cache<__cache_type>(__loc); + const __cache_type* __lc = __uc(__loc); // [22.2.2.2.2] Stage 1, numeric conversion to character. int __len; @@ -944,20 +966,20 @@ namespace std // Replace decimal point. const _CharT __cdec = __ctype.widen('.'); - const _CharT __dec = __lc._M_decimal_point; + const _CharT __dec = __lc->_M_decimal_point; const _CharT* __p; if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) __ws[__p - __ws] = __dec; // Add grouping, if necessary. _CharT* __ws2; - if (__lc._M_use_grouping) + if (__lc->_M_use_grouping) { // Grouping can add (almost) as many separators as the // number of digits, but no more. __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len * 2)); - _M_group_float(__lc._M_grouping, __lc._M_thousands_sep, __p, + _M_group_float(__lc->_M_grouping, __lc->_M_thousands_sep, __p, __ws2, __ws, __len); __ws = __ws2; } @@ -992,15 +1014,16 @@ namespace std else { typedef typename numpunct<_CharT>::__cache_type __cache_type; + __use_cache<__cache_type> __uc; const locale& __loc = __io._M_getloc(); - const __cache_type& __lc = __use_cache<__cache_type>(__loc); + const __cache_type* __lc = __uc(__loc); typedef basic_string<_CharT> __string_type; __string_type __name; if (__v) - __name = __lc._M_truename; + __name = __lc->_M_truename; else - __name = __lc._M_falsename; + __name = __lc->_M_falsename; const _CharT* __cs = __name.c_str(); int __len = __name.size(); @@ -1339,7 +1362,8 @@ namespace std // decimal digit, '\0'. const int __cs_size = numeric_limits::max_exponent10 + 5; char* __cs = static_cast(__builtin_alloca(__cs_size)); - int __len = std::__convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale); + int __len = std::__convert_from_v(__cs, 0, "%.01Lf", __units, + _S_c_locale); #endif _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size)); @@ -2280,8 +2304,8 @@ namespace std { if (__last - __first > *__gbeg) { - __s = std::__add_grouping(__s, __sep, - (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1), + const bool __bump = __gbeg + 1 != __gend; + __s = std::__add_grouping(__s, __sep, __gbeg + __bump, __gend, __first, __last - *__gbeg); __first = __last - *__gbeg; *__s++ = __sep; diff --git a/libstdc++-v3/include/ext/pod_char_traits.h b/libstdc++-v3/include/ext/pod_char_traits.h index 0de7a0fd1e6..0145a483095 100644 --- a/libstdc++-v3/include/ext/pod_char_traits.h +++ b/libstdc++-v3/include/ext/pod_char_traits.h @@ -98,7 +98,7 @@ namespace std length(const char_type* __s) { const char_type* __p = __s; - while (*__p) + while (__p->value) ++__p; return (__p - __s); } diff --git a/libstdc++-v3/src/locale.cc b/libstdc++-v3/src/locale.cc index 248fdf30293..43f831d9e7a 100644 --- a/libstdc++-v3/src/locale.cc +++ b/libstdc++-v3/src/locale.cc @@ -451,38 +451,6 @@ namespace std locale::facet:: ~facet() { } - template<> - const __numpunct_cache& - __use_cache(const locale& __loc) - { - size_t __i = numpunct::id._M_id(); - const locale::facet** __caches = __loc._M_impl->_M_caches; - if (!__caches[__i]) - { - __numpunct_cache* __tmp = new __numpunct_cache; - __tmp->_M_cache(__loc); - __loc._M_impl->_M_install_cache(__tmp, __i); - } - return static_cast&>(*__caches[__i]); - } - -#ifdef _GLIBCXX_USE_WCHAR_T - template<> - const __numpunct_cache& - __use_cache(const locale& __loc) - { - size_t __i = numpunct::id._M_id(); - const locale::facet** __caches = __loc._M_impl->_M_caches; - if (!__caches[__i]) - { - __numpunct_cache* __tmp = new __numpunct_cache; - __tmp->_M_cache(__loc); - __loc._M_impl->_M_install_cache(__tmp, __i); - } - return static_cast&>(*__caches[__i]); - } -#endif - // Definitions for static const data members of time_base. template<> const char* diff --git a/libstdc++-v3/testsuite/22_locale/numpunct/members/char/cache_1.cc b/libstdc++-v3/testsuite/22_locale/numpunct/members/char/cache_1.cc new file mode 100644 index 00000000000..002b0c47e37 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/numpunct/members/char/cache_1.cc @@ -0,0 +1,78 @@ +// 2003-07-06 Benjamin Kosnik + +// 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. + +#include +#include +#include +#include + +class numpunct_checked : public std::numpunct +{ + typedef std::numpunct base; + +public: + explicit + numpunct_checked(std::size_t refs = 0): base(refs) { } + + string_type + base_truename() const + { return base::do_truename(); } + +protected: + virtual string_type + do_truename() const + { return base::do_truename() + "st"; } +}; + +// Thwart locale caching strategies that incorrectly overwrite base +// class data. +void test01() +{ + using namespace std; + + bool test = true; + const string basestr("true"); + const string derivedstr("truest"); + + const locale loc(locale::classic(), new numpunct_checked); + stringbuf sbuf; + ostream os(&sbuf); + os.setf(ios_base::boolalpha); + + // Pre-cache sanity check. + const numpunct& np = use_facet >(loc); + VERIFY( np.truename() == derivedstr ); + + // Cache. + os.imbue(loc); + os << true; + VERIFY( sbuf.str() == derivedstr ); + + // Post-cache sanity check, make sure that base class is still fine. + VERIFY( np.truename() == derivedstr ); + const numpunct_checked& npd = static_cast(np); + VERIFY( npd.base_truename() == basestr ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/numpunct/members/char/cache_2.cc b/libstdc++-v3/testsuite/22_locale/numpunct/members/char/cache_2.cc new file mode 100644 index 00000000000..729e82a64bd --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/numpunct/members/char/cache_2.cc @@ -0,0 +1,90 @@ +// 2003-07-06 Benjamin Kosnik + +// 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. + +#include +#include +#include +#include + +class numpunct_checked : public std::numpunct +{ + typedef std::numpunct base; + +public: + explicit + numpunct_checked(std::size_t refs = 0): base(refs) { } + + string_type + base_truename() const + { return base::do_truename(); } + +protected: + virtual string_type + do_truename() const + { return base::do_truename() + "st"; } +}; + +// Changing caches deletes old cache, adds new one. +void test01() +{ + using namespace std; + + bool test = true; + const string empty; + const string basestr("true"); + const string derivedstr("truest"); + + const locale loc(locale::classic(), new numpunct_checked); + stringbuf sbuf; + ostream os(&sbuf); + os.setf(ios_base::boolalpha); + + // Pre-cache sanity check. + const numpunct& np = use_facet >(loc); + VERIFY( np.truename() == derivedstr ); + + // Cache. + os.imbue(loc); + os << true; + VERIFY( sbuf.str() == derivedstr ); + + // Re-cache. + sbuf.str(empty); + os.imbue(locale::classic()); + os << true; + VERIFY( sbuf.str() == basestr ); + + // Cache new locale again. + sbuf.str(empty); + os.imbue(loc); + os << true; + VERIFY( sbuf.str() == derivedstr ); + + // Post-cache sanity check, make sure that base class is still fine. + VERIFY( np.truename() == derivedstr ); + const numpunct_checked& npd = static_cast(np); + VERIFY( npd.base_truename() == basestr ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/numpunct/members/pod/1.cc b/libstdc++-v3/testsuite/22_locale/numpunct/members/pod/1.cc new file mode 100644 index 00000000000..c0cf534af7b --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/numpunct/members/pod/1.cc @@ -0,0 +1,134 @@ +// 2003-07-09 Benjamin Kosnik + +// 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. + +#include +#include +#include +#include +#include +#include + +typedef unsigned short value_type; +typedef unsigned int int_type; +typedef __gnu_cxx::character podchar_type; + +// Member specializations for the existing facet classes. +// NB: This isn't especially portable. Perhaps a better way would be +// to just specialize all of numpunct and ctype. +namespace std +{ + template<> + void + numpunct::_M_initialize_numpunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __numpunct_cache; + + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point.value = value_type('.'); + _M_data->_M_thousands_sep.value = value_type(','); + + for (size_t i = 0; i < __num_base::_S_oend; ++i) + { + value_type v = __num_base::_S_atoms_out[i]; + _M_data->_M_atoms_out[i].value = v; + } + _M_data->_M_atoms_out[__num_base::_S_oend] = podchar_type(); + + for (size_t i = 0; i < __num_base::_S_iend; ++i) + _M_data->_M_atoms_in[i].value = value_type(__num_base::_S_atoms_in[i]); + _M_data->_M_atoms_in[__num_base::_S_iend] = podchar_type(); + + // "true" + podchar_type* __truename = new podchar_type[4 + 1]; + __truename[0].value = value_type('t'); + __truename[1].value = value_type('r'); + __truename[2].value = value_type('u'); + __truename[3].value = value_type('e'); + __truename[4] = podchar_type(); + _M_data->_M_truename = __truename; + + // "false" + podchar_type* __falsename = new podchar_type[5 + 1]; + __falsename[0].value = value_type('f'); + __falsename[1].value = value_type('a'); + __falsename[2].value = value_type('l'); + __falsename[3].value = value_type('s'); + __falsename[4].value = value_type('e'); + __falsename[5] = podchar_type(); + _M_data->_M_falsename = __falsename; + } + + template<> + numpunct::~numpunct() + { delete _M_data; } +} + +// Check for numpunct and ctype dependencies. Make sure that numpunct +// can be created without ctype. +void test01() +{ + using namespace std; + typedef numpunct::string_type string_type; + typedef basic_stringbuf stringbuf_type; + typedef basic_ostream ostream_type; + + bool test = true; + + // Pre-cache sanity check. + const locale loc(locale::classic(), new numpunct); + const numpunct& np = use_facet >(loc); + + podchar_type dp = np.decimal_point(); + podchar_type ts = np.thousands_sep(); + string g = np.grouping(); + string_type strue = np.truename(); + string_type sfalse = np.falsename(); + + podchar_type basedp = { value_type('.') }; + podchar_type basets = { value_type(',') }; + + string_type basetrue(4, podchar_type()); + basetrue[0].value = value_type('t'); + basetrue[1].value = value_type('r'); + basetrue[2].value = value_type('u'); + basetrue[3].value = value_type('e'); + + string_type basefalse(5, podchar_type()); + basefalse[0].value = value_type('f'); + basefalse[1].value = value_type('a'); + basefalse[2].value = value_type('l'); + basefalse[3].value = value_type('s'); + basefalse[4].value = value_type('e'); + + VERIFY( char_traits::eq(dp, basedp) ); + VERIFY( char_traits::eq(ts, basets) ); + VERIFY( g == "" ); + VERIFY( strue == basetrue ); + VERIFY( sfalse == basefalse ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/numpunct/members/pod/2.cc b/libstdc++-v3/testsuite/22_locale/numpunct/members/pod/2.cc new file mode 100644 index 00000000000..32b26eda0cd --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/numpunct/members/pod/2.cc @@ -0,0 +1,267 @@ +// 2003-07-09 Benjamin Kosnik + +// 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. + +#include +#include +#include +#include +#include +#include + +typedef unsigned short value_type; +typedef unsigned int int_type; +typedef __gnu_cxx::character podchar_type; + +// Member specializations for the existing facet classes. +// NB: This isn't especially portable. Perhaps a better way would be +// to just specialize all of numpunct and ctype. +namespace std +{ + template<> + bool + ctype:: + do_is(mask __m, char_type __c) const { return true; } + + template<> + const podchar_type* + ctype:: + do_is(const char_type* __lo, const char_type* __hi, mask* __vec) const + { return __lo; } + + template<> + const podchar_type* + ctype:: + do_scan_is(mask __m, const char_type* __lo, const char_type* __hi) const + { return __lo; } + + template<> + const podchar_type* + ctype:: + do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const + { return __lo; } + + template<> + podchar_type + ctype:: + do_toupper(char_type __c) const + { return __c; } + + template<> + const podchar_type* + ctype:: + do_toupper(char_type* __lo, const char_type* __hi) const + { return __hi; } + + template<> + podchar_type + ctype:: + do_tolower(char_type __c) const + { return __c; } + + template<> + const podchar_type* + ctype:: + do_tolower(char_type* __lo, const char_type* __hi) const + { return __hi; } + + template<> + podchar_type + ctype:: + do_widen(char __c) const + { + char_type ret = { value_type(__c) }; + return ret; + } + + template<> + const char* + ctype:: + do_widen(const char* __lo, const char* __hi, char_type* __dest) const + { + while (__lo < __hi) + { + *__dest = this->do_widen(*__lo); + ++__lo; + ++__dest; + } + return __hi; + } + + template<> + char + ctype:: + do_narrow(char_type __wc, char) const + { return static_cast(__wc.value); } + + template<> + const podchar_type* + ctype:: + do_narrow(const podchar_type* __lo, const podchar_type* __hi, + char __dfault, char* __dest) const + { + while (__lo < __hi) + { + *__dest = this->do_narrow(*__lo, char()); + ++__lo; + ++__dest; + } + return __hi; + } + + template<> + ctype::~ctype() { } + + template<> + void + numpunct::_M_initialize_numpunct(__c_locale __cloc) + { + if (!_M_data) + _M_data = new __numpunct_cache; + + _M_data->_M_grouping = ""; + _M_data->_M_use_grouping = false; + + _M_data->_M_decimal_point.value = value_type('.'); + _M_data->_M_thousands_sep.value = value_type(','); + + for (size_t i = 0; i < __num_base::_S_oend; ++i) + { + value_type v = __num_base::_S_atoms_out[i]; + _M_data->_M_atoms_out[i].value = v; + } + _M_data->_M_atoms_out[__num_base::_S_oend] = podchar_type(); + + for (size_t i = 0; i < __num_base::_S_iend; ++i) + _M_data->_M_atoms_in[i].value = value_type(__num_base::_S_atoms_in[i]); + _M_data->_M_atoms_in[__num_base::_S_iend] = podchar_type(); + + // "true" + podchar_type* __truename = new podchar_type[4 + 1]; + __truename[0].value = value_type('t'); + __truename[1].value = value_type('r'); + __truename[2].value = value_type('u'); + __truename[3].value = value_type('e'); + __truename[4] = podchar_type(); + _M_data->_M_truename = __truename; + + // "false" + podchar_type* __falsename = new podchar_type[5 + 1]; + __falsename[0].value = value_type('f'); + __falsename[1].value = value_type('a'); + __falsename[2].value = value_type('l'); + __falsename[3].value = value_type('s'); + __falsename[4].value = value_type('e'); + __falsename[5] = podchar_type(); + _M_data->_M_falsename = __falsename; + } + + template<> + numpunct::~numpunct() + { delete _M_data; } +} + +// Check for numpunct and ctype dependencies. Make sure that numpunct +// can be created without ctype. +void test01() +{ + using namespace std; + typedef numpunct::string_type string_type; + typedef basic_ostringstream ostream_type; + + bool test = true; + + // Test formatted output. + ostream_type os; + const locale loc = locale::classic(); + os.imbue(loc); + os.setf(ios_base::boolalpha); + os.exceptions(ios_base::badbit); + + // 1: fail, no num_put. + try + { + // Calls to num_put.put will fail, as there's no num_put facet. + os << true; + test = false; + } + catch(const bad_cast& obj) + { } + catch(...) + { test = false; } + VERIFY( test ); + + // 2: fail, no ctype + const locale loc2(loc, new num_put); + os.clear(); + os.imbue(loc2); + try + { + // Calls to ctype.widen will fail, as there's no ctype facet. + os << true; + test = false; + } + catch(const bad_cast& obj) + { } + catch(...) + { test = false; } + VERIFY( test ); + + // 3: fail, no numpunct + const locale loc3(loc, new ctype); + os.clear(); + os.imbue(loc3); + try + { + // Formatted output fails as no numpunct. + os << true; + test = false; + } + catch(const bad_cast& obj) + { } + catch(...) + { test = false; } + VERIFY( test ); + + // 4: works. + const locale loc4(loc3, new numpunct); + os.clear(); + os.imbue(loc4); + try + { + os << long(500); + string_type s = os.str(); + VERIFY( s.length() == 3 ); + + VERIFY( os.narrow(s[0], char()) == '5' ); + VERIFY( os.narrow(s[1], char()) == '0' ); + VERIFY( os.narrow(s[2], char()) == '0' ); + } + catch(const bad_cast& obj) + { test = false; } + catch(...) + { test = false; } + VERIFY( test ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/numpunct/members/wchar_t/cache_1.cc b/libstdc++-v3/testsuite/22_locale/numpunct/members/wchar_t/cache_1.cc new file mode 100644 index 00000000000..0b41e963f50 --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/numpunct/members/wchar_t/cache_1.cc @@ -0,0 +1,78 @@ +// 2003-07-06 Benjamin Kosnik + +// 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. + +#include +#include +#include +#include + +class numpunct_checked : public std::numpunct +{ + typedef std::numpunct base; + +public: + explicit + numpunct_checked(std::size_t refs = 0): base(refs) { } + + string_type + base_truename() const + { return base::do_truename(); } + +protected: + virtual string_type + do_truename() const + { return base::do_truename() + L"st"; } +}; + +// Thwart locale caching strategies that incorrectly overwrite base +// class data. +void test01() +{ + using namespace std; + + bool test = true; + const wstring basestr(L"true"); + const wstring derivedstr(L"truest"); + + const locale loc(locale::classic(), new numpunct_checked); + wstringbuf sbuf; + wostream os(&sbuf); + os.setf(ios_base::boolalpha); + + // Pre-cache sanity check. + const numpunct& np = use_facet >(loc); + VERIFY( np.truename() == derivedstr ); + + // Cache. + os.imbue(loc); + os << true; + VERIFY( sbuf.str() == derivedstr ); + + // Post-cache sanity check, make sure that base class is still fine. + VERIFY( np.truename() == derivedstr ); + const numpunct_checked& npd = static_cast(np); + VERIFY( npd.base_truename() == basestr ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/22_locale/numpunct/members/wchar_t/cache_2.cc b/libstdc++-v3/testsuite/22_locale/numpunct/members/wchar_t/cache_2.cc new file mode 100644 index 00000000000..9a3c4872e5c --- /dev/null +++ b/libstdc++-v3/testsuite/22_locale/numpunct/members/wchar_t/cache_2.cc @@ -0,0 +1,90 @@ +// 2003-07-06 Benjamin Kosnik + +// 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. + +#include +#include +#include +#include + +class numpunct_checked : public std::numpunct +{ + typedef std::numpunct base; + +public: + explicit + numpunct_checked(std::size_t refs = 0): base(refs) { } + + string_type + base_truename() const + { return base::do_truename(); } + +protected: + virtual string_type + do_truename() const + { return base::do_truename() + L"st"; } +}; + +// Changing caches deletes old cache, adds new one. +void test01() +{ + using namespace std; + + bool test = true; + const wstring empty; + const wstring basestr(L"true"); + const wstring derivedstr(L"truest"); + + const locale loc(locale::classic(), new numpunct_checked); + wstringbuf sbuf; + wostream os(&sbuf); + os.setf(ios_base::boolalpha); + + // Pre-cache sanity check. + const numpunct& np = use_facet >(loc); + VERIFY( np.truename() == derivedstr ); + + // Cache. + os.imbue(loc); + os << true; + VERIFY( sbuf.str() == derivedstr ); + + // Re-cache. + sbuf.str(empty); + os.imbue(locale::classic()); + os << true; + VERIFY( sbuf.str() == basestr ); + + // Cache new locale again. + sbuf.str(empty); + os.imbue(loc); + os << true; + VERIFY( sbuf.str() == derivedstr ); + + // Post-cache sanity check, make sure that base class is still fine. + VERIFY( np.truename() == derivedstr ); + const numpunct_checked& npd = static_cast(np); + VERIFY( npd.base_truename() == basestr ); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/testsuite_hooks.h b/libstdc++-v3/testsuite/testsuite_hooks.h index 896bf1cbcae..5de881aaa99 100644 --- a/libstdc++-v3/testsuite/testsuite_hooks.h +++ b/libstdc++-v3/testsuite/testsuite_hooks.h @@ -127,16 +127,6 @@ namespace __gnu_cxx_test int i; }; - struct pod_unsigned_int - { - unsigned int i; - }; - - struct pod_long - { - unsigned long i; - }; - struct state { unsigned long l;