This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[v3] __use_cache fixes, tests


This adds checking for the locale cache for numpunct. These should
have gone in with the cache code, but I was distracted.

In addition, I added tests for POD character types. This was quite an
undertaking.

tested x86/linux

2003-07-09  Benjamin Kosnik  <bkoz@redhat.com>

	* 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.

Index: include/bits/locale_classes.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/locale_classes.h,v
retrieving revision 1.9
diff -c -p -r1.9 locale_classes.h
*** include/bits/locale_classes.h	6 Jul 2003 09:37:11 -0000	1.9
--- include/bits/locale_classes.h	10 Jul 2003 05:53:20 -0000
*************** namespace std
*** 73,80 ****
        use_facet(const locale&);
  
      template<typename _Cache>
!       friend const _Cache&
!       __use_cache(const locale& __loc);
     
      // Category values:
      // NB: Order must match _S_facet_categories definition in locale.cc
--- 73,79 ----
        use_facet(const locale&);
  
      template<typename _Cache>
!       friend struct __use_cache;
     
      // Category values:
      // NB: Order must match _S_facet_categories definition in locale.cc
*************** namespace std
*** 298,305 ****
        use_facet(const locale&);
  
      template<typename _Cache>
!       friend const _Cache&
!       __use_cache(const locale& __loc);
  
    private:
      // Data Members.
--- 297,303 ----
        use_facet(const locale&);
  
      template<typename _Cache>
!       friend struct __use_cache;
  
    private:
      // Data Members.
*************** namespace std
*** 370,376 ****
        { _M_install_facet(&_Facet::id, __facet); }
  
      void
!     _M_install_cache(const facet* __cache, size_t __index)
      { 
        __cache->_M_add_reference();
        _M_caches[__index] = __cache; 
--- 368,374 ----
        { _M_install_facet(&_Facet::id, __facet); }
  
      void
!     _M_install_cache(const facet* __cache, size_t __index) throw()
      { 
        __cache->_M_add_reference();
        _M_caches[__index] = __cache; 
Index: include/bits/locale_facets.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/locale_facets.h,v
retrieving revision 1.60
diff -c -p -r1.60 locale_facets.h
*** include/bits/locale_facets.h	8 Jul 2003 20:25:39 -0000	1.60
--- include/bits/locale_facets.h	10 Jul 2003 05:53:22 -0000
*************** namespace std
*** 577,610 ****
    template<typename _CharT>
      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;
        
        // 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];
  
        // 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];
  
        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)
        { } 
  
        ~__numpunct_cache();
--- 577,607 ----
    template<typename _CharT>
      struct __numpunct_cache : public locale::facet
      {
        const char* 			_M_grouping;
        bool				_M_use_grouping;
!       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().
!       _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().
!       _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(_CharT()), 
!       _M_thousands_sep(_CharT()), _M_allocated(false)
        { } 
  
        ~__numpunct_cache();
Index: include/bits/locale_facets.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/locale_facets.tcc,v
retrieving revision 1.106
diff -c -p -r1.106 locale_facets.tcc
*** include/bits/locale_facets.tcc	6 Jul 2003 09:37:11 -0000	1.106
--- include/bits/locale_facets.tcc	10 Jul 2003 05:53:24 -0000
*************** namespace std
*** 89,106 ****
    // Routine to access a cache for the facet.  If the cache didn't
    // exist before, it gets constructed on the fly.
    template<typename _Facet>
!     const _Facet&
!     __use_cache(const locale& __loc);
  
!   template<>
!     const __numpunct_cache<char>&
!     __use_cache(const locale& __loc);
! 
! #ifdef _GLIBCXX_USE_WCHAR_T
!   template<>
!     const __numpunct_cache<wchar_t>&
!     __use_cache(const locale& __loc);
! #endif
  
    // Stage 1: Determine a conversion specifier.
    template<typename _CharT, typename _InIter>
--- 89,126 ----
    // Routine to access a cache for the facet.  If the cache didn't
    // exist before, it gets constructed on the fly.
    template<typename _Facet>
!     struct __use_cache
!     {
!       const _Facet*
!       operator() (const locale& __loc) const;
!     };
  
!   template<typename _CharT>
!     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<const __numpunct_cache<_CharT>*>(__caches[__i]);
!       }
!     };
  
    // Stage 1: Determine a conversion specifier.
    template<typename _CharT, typename _InIter>
*************** namespace std
*** 785,793 ****
  		     _ValueT __v) const
        {
  	typedef typename numpunct<_CharT>::__cache_type  __cache_type;
  	const locale& __loc = __io._M_getloc();
! 	const __cache_type& __lc = __use_cache<__cache_type>(__loc);
! 	const _CharT* __lit = __lc._M_atoms_out;
  
   	// Long enough to hold hex, dec, and octal representations.
  	int __ilen = 4 * sizeof(_ValueT);
--- 805,814 ----
  		     _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 = __uc(__loc);
! 	const _CharT* __lit = __lc->_M_atoms_out;
  
   	// Long enough to hold hex, dec, and octal representations.
  	int __ilen = 4 * sizeof(_ValueT);
*************** namespace std
*** 801,813 ****
  	
  	// Add grouping, if necessary. 
  	_CharT* __cs2;
! 	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, 
  			 __cs2, __cs, __len);
  	    __cs = __cs2;
  	  }
--- 822,834 ----
  	
  	// Add grouping, if necessary. 
  	_CharT* __cs2;
! 	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, 
  			 __cs2, __cs, __len);
  	    __cs = __cs2;
  	  }
*************** namespace std
*** 890,897 ****
  	  __prec = static_cast<streamsize>(6);
  
  	typedef typename numpunct<_CharT>::__cache_type  __cache_type;
  	const locale& __loc = __io._M_getloc();
! 	const __cache_type& __lc = __use_cache<__cache_type>(__loc);
  
  	// [22.2.2.2.2] Stage 1, numeric conversion to character.
  	int __len;
--- 911,919 ----
  	  __prec = static_cast<streamsize>(6);
  
  	typedef typename numpunct<_CharT>::__cache_type  __cache_type;
+ 	__use_cache<__cache_type> __uc;
  	const locale& __loc = __io._M_getloc();
! 	const __cache_type* __lc = __uc(__loc);
  
  	// [22.2.2.2.2] Stage 1, numeric conversion to character.
  	int __len;
*************** namespace std
*** 944,963 ****
        
        // Replace decimal point.
        const _CharT __cdec = __ctype.widen('.');
!       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)
  	{
  	    // 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,
  			   __ws2, __ws, __len);
  	    __ws = __ws2;
  	}
--- 966,985 ----
        
        // Replace decimal point.
        const _CharT __cdec = __ctype.widen('.');
!       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)
  	{
  	    // 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,
  			   __ws2, __ws, __len);
  	    __ws = __ws2;
  	}
*************** namespace std
*** 992,1006 ****
        else
          {
  	  typedef typename numpunct<_CharT>::__cache_type  __cache_type;
  	  const locale& __loc = __io._M_getloc();
! 	  const __cache_type& __lc = __use_cache<__cache_type>(__loc);
  
  	  typedef basic_string<_CharT> 	__string_type;
  	  __string_type __name;
            if (__v)
! 	    __name = __lc._M_truename;
            else
! 	    __name = __lc._M_falsename;
  
  	  const _CharT* __cs = __name.c_str();
  	  int __len = __name.size();
--- 1014,1029 ----
        else
          {
  	  typedef typename numpunct<_CharT>::__cache_type  __cache_type;
+ 	  __use_cache<__cache_type> __uc;
  	  const locale& __loc = __io._M_getloc();
! 	  const __cache_type* __lc = __uc(__loc);
  
  	  typedef basic_string<_CharT> 	__string_type;
  	  __string_type __name;
            if (__v)
! 	    __name = __lc->_M_truename;
            else
! 	    __name = __lc->_M_falsename;
  
  	  const _CharT* __cs = __name.c_str();
  	  int __len = __name.size();
*************** namespace std
*** 1339,1345 ****
        // decimal digit, '\0'. 
        const int __cs_size = numeric_limits<long double>::max_exponent10 + 5;
        char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
!       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));
--- 1362,1369 ----
        // decimal digit, '\0'. 
        const int __cs_size = numeric_limits<long double>::max_exponent10 + 5;
        char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
!       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));
*************** namespace std
*** 2280,2287 ****
      {
        if (__last - __first > *__gbeg)
          {
!           __s = std::__add_grouping(__s,  __sep, 
! 				    (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
  				    __gend, __first, __last - *__gbeg);
            __first = __last - *__gbeg;
            *__s++ = __sep;
--- 2304,2311 ----
      {
        if (__last - __first > *__gbeg)
          {
! 	  const bool __bump = __gbeg + 1 != __gend;
!           __s = std::__add_grouping(__s,  __sep, __gbeg + __bump,
  				    __gend, __first, __last - *__gbeg);
            __first = __last - *__gbeg;
            *__s++ = __sep;
Index: include/ext/pod_char_traits.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/ext/pod_char_traits.h,v
retrieving revision 1.1
diff -c -p -r1.1 pod_char_traits.h
*** include/ext/pod_char_traits.h	9 Jul 2003 00:40:29 -0000	1.1
--- include/ext/pod_char_traits.h	10 Jul 2003 05:53:26 -0000
*************** namespace std
*** 98,104 ****
        length(const char_type* __s)
        { 
  	const char_type* __p = __s; 
! 	while (*__p) 
  	  ++__p; 
  	return (__p - __s); 
        }
--- 98,104 ----
        length(const char_type* __s)
        { 
  	const char_type* __p = __s; 
! 	while (__p->value) 
  	  ++__p; 
  	return (__p - __s); 
        }
Index: src/locale.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/locale.cc,v
retrieving revision 1.88
diff -c -p -r1.88 locale.cc
*** src/locale.cc	8 Jul 2003 20:25:39 -0000	1.88
--- src/locale.cc	10 Jul 2003 05:53:26 -0000
*************** namespace std 
*** 451,488 ****
    locale::facet::
    ~facet() { }
  
-   template<>
-     const __numpunct_cache<char>&
-     __use_cache(const locale& __loc)
-     {
-       size_t __i = numpunct<char>::id._M_id();
-       const locale::facet** __caches = __loc._M_impl->_M_caches;
-       if (!__caches[__i])
- 	{
- 	  __numpunct_cache<char>* __tmp = new __numpunct_cache<char>;
- 	  __tmp->_M_cache(__loc);
- 	  __loc._M_impl->_M_install_cache(__tmp, __i);
- 	}
-       return static_cast<const __numpunct_cache<char>&>(*__caches[__i]);
-     }
- 
- #ifdef _GLIBCXX_USE_WCHAR_T
-   template<>
-     const __numpunct_cache<wchar_t>&
-     __use_cache(const locale& __loc)
-     {
-       size_t __i = numpunct<wchar_t>::id._M_id();
-       const locale::facet** __caches = __loc._M_impl->_M_caches;
-       if (!__caches[__i])
- 	{
- 	  __numpunct_cache<wchar_t>* __tmp = new __numpunct_cache<wchar_t>;
- 	  __tmp->_M_cache(__loc);
- 	  __loc._M_impl->_M_install_cache(__tmp, __i);
- 	}
-       return static_cast<const __numpunct_cache<wchar_t>&>(*__caches[__i]);
-     }
- #endif
- 
    // Definitions for static const data members of time_base.
    template<> 
      const char*
--- 451,456 ----
Index: testsuite/testsuite_hooks.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/testsuite_hooks.h,v
retrieving revision 1.19
diff -c -p -r1.19 testsuite_hooks.h
*** testsuite/testsuite_hooks.h	6 Jul 2003 04:30:10 -0000	1.19
--- testsuite/testsuite_hooks.h	10 Jul 2003 05:53:26 -0000
*************** namespace __gnu_cxx_test
*** 127,142 ****
      int i;
    };
    
-   struct pod_unsigned_int
-   {
-     unsigned int i;
-   };
-   
-   struct pod_long
-   {
-     unsigned long i;
-   };
-   
    struct state
    {
      unsigned long l;
--- 127,132 ----
Index: testsuite/22_locale/numpunct/members/char/cache_1.cc
===================================================================
RCS file: testsuite/22_locale/numpunct/members/char/cache_1.cc
diff -N testsuite/22_locale/numpunct/members/char/cache_1.cc
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/22_locale/numpunct/members/char/cache_1.cc	10 Jul 2003 05:53:27 -0000
***************
*** 0 ****
--- 1,78 ----
+ // 2003-07-06  Benjamin Kosnik  <bkoz@redhat.com>
+ 
+ // 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 <locale>
+ #include <sstream>
+ #include <ostream>
+ #include <testsuite_hooks.h>
+ 
+ class numpunct_checked : public std::numpunct<char>
+ {
+   typedef std::numpunct<char> 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<char>& np = use_facet<numpunct<char> >(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<const numpunct_checked&>(np);
+   VERIFY( npd.base_truename() == basestr );
+ }
+ 
+ int main()
+ {
+   test01();
+   return 0;
+ }
Index: testsuite/22_locale/numpunct/members/char/cache_2.cc
===================================================================
RCS file: testsuite/22_locale/numpunct/members/char/cache_2.cc
diff -N testsuite/22_locale/numpunct/members/char/cache_2.cc
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/22_locale/numpunct/members/char/cache_2.cc	10 Jul 2003 05:53:27 -0000
***************
*** 0 ****
--- 1,90 ----
+ // 2003-07-06  Benjamin Kosnik  <bkoz@redhat.com>
+ 
+ // 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 <locale>
+ #include <sstream>
+ #include <ostream>
+ #include <testsuite_hooks.h>
+ 
+ class numpunct_checked : public std::numpunct<char>
+ {
+   typedef std::numpunct<char> 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<char>& np = use_facet<numpunct<char> >(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<const numpunct_checked&>(np);
+   VERIFY( npd.base_truename() == basestr );
+ }
+ 
+ int main()
+ {
+   test01();
+   return 0;
+ }
Index: testsuite/22_locale/numpunct/members/pod/1.cc
===================================================================
RCS file: testsuite/22_locale/numpunct/members/pod/1.cc
diff -N testsuite/22_locale/numpunct/members/pod/1.cc
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/22_locale/numpunct/members/pod/1.cc	10 Jul 2003 05:53:28 -0000
***************
*** 0 ****
--- 1,134 ----
+ // 2003-07-09  Benjamin Kosnik  <bkoz@redhat.com>
+ 
+ // 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 <locale>
+ #include <sstream>
+ #include <ostream>
+ #include <stdexcept>
+ #include <ext/pod_char_traits.h>
+ #include <testsuite_hooks.h>
+ 
+ typedef unsigned short					value_type;
+ typedef unsigned int					int_type;
+ typedef __gnu_cxx::character<value_type, int_type>	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<podchar_type>::_M_initialize_numpunct(__c_locale __cloc)
+     {
+       if (!_M_data)
+ 	_M_data = new __numpunct_cache<podchar_type>;
+ 
+       _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<podchar_type>::~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<podchar_type>::string_type 	string_type;
+   typedef basic_stringbuf<podchar_type> 	stringbuf_type;
+   typedef basic_ostream<podchar_type> 		ostream_type;
+   
+   bool 		test = true;
+ 
+   // Pre-cache sanity check.
+   const locale 	loc(locale::classic(), new numpunct<podchar_type>);
+   const numpunct<podchar_type>& np = use_facet<numpunct<podchar_type> >(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<podchar_type>::eq(dp, basedp) );
+   VERIFY( char_traits<podchar_type>::eq(ts, basets) );
+   VERIFY( g == "" );
+   VERIFY( strue == basetrue );
+   VERIFY( sfalse == basefalse );
+ }
+ 
+ int main()
+ {
+   test01();
+   return 0;
+ }
Index: testsuite/22_locale/numpunct/members/pod/2.cc
===================================================================
RCS file: testsuite/22_locale/numpunct/members/pod/2.cc
diff -N testsuite/22_locale/numpunct/members/pod/2.cc
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/22_locale/numpunct/members/pod/2.cc	10 Jul 2003 05:53:28 -0000
***************
*** 0 ****
--- 1,267 ----
+ // 2003-07-09  Benjamin Kosnik  <bkoz@redhat.com>
+ 
+ // 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 <locale>
+ #include <sstream>
+ #include <ostream>
+ #include <stdexcept>
+ #include <ext/pod_char_traits.h>
+ #include <testsuite_hooks.h>
+ 
+ typedef unsigned short					value_type;
+ typedef unsigned int					int_type;
+ typedef __gnu_cxx::character<value_type, int_type>	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<podchar_type>::
+     do_is(mask __m, char_type __c) const { return true; }
+ 
+   template<>
+     const podchar_type*
+     ctype<podchar_type>::
+     do_is(const char_type* __lo, const char_type* __hi, mask* __vec) const
+     { return __lo; }
+ 
+   template<>
+     const podchar_type*
+     ctype<podchar_type>::
+     do_scan_is(mask __m, const char_type* __lo, const char_type* __hi) const
+     { return __lo; }
+ 
+   template<>
+     const podchar_type*
+     ctype<podchar_type>::
+     do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
+     { return __lo; }
+ 
+   template<>
+     podchar_type 
+     ctype<podchar_type>::
+     do_toupper(char_type __c) const
+     { return __c; }
+ 
+   template<>
+     const podchar_type*
+     ctype<podchar_type>::
+     do_toupper(char_type* __lo, const char_type* __hi) const
+     { return __hi; }
+ 
+   template<>
+     podchar_type 
+     ctype<podchar_type>::
+     do_tolower(char_type __c) const
+     { return __c; }
+ 
+   template<>
+     const podchar_type*
+     ctype<podchar_type>::
+     do_tolower(char_type* __lo, const char_type* __hi) const
+     { return __hi; }
+ 
+   template<>
+     podchar_type
+     ctype<podchar_type>::
+     do_widen(char __c) const
+     { 
+       char_type ret = { value_type(__c) };
+       return ret;
+     }
+ 
+   template<>
+     const char*
+     ctype<podchar_type>::
+     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<podchar_type>::
+     do_narrow(char_type __wc, char) const
+     { return static_cast<char>(__wc.value); }
+ 
+   template<>
+     const podchar_type*
+     ctype<podchar_type>::
+     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<podchar_type>::~ctype() { }
+ 
+   template<>
+     void
+     numpunct<podchar_type>::_M_initialize_numpunct(__c_locale __cloc)
+     {
+       if (!_M_data)
+ 	_M_data = new __numpunct_cache<podchar_type>;
+ 
+       _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<podchar_type>::~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<podchar_type>::string_type 	string_type;
+   typedef basic_ostringstream<podchar_type> 		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<podchar_type>);
+   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<podchar_type>);
+   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<podchar_type>);
+   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;
+ }
Index: testsuite/22_locale/numpunct/members/wchar_t/cache_1.cc
===================================================================
RCS file: testsuite/22_locale/numpunct/members/wchar_t/cache_1.cc
diff -N testsuite/22_locale/numpunct/members/wchar_t/cache_1.cc
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/22_locale/numpunct/members/wchar_t/cache_1.cc	10 Jul 2003 05:53:28 -0000
***************
*** 0 ****
--- 1,78 ----
+ // 2003-07-06  Benjamin Kosnik  <bkoz@redhat.com>
+ 
+ // 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 <locale>
+ #include <sstream>
+ #include <ostream>
+ #include <testsuite_hooks.h>
+ 
+ class numpunct_checked : public std::numpunct<wchar_t>
+ {
+   typedef std::numpunct<wchar_t> 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<wchar_t>& np = use_facet<numpunct<wchar_t> >(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<const numpunct_checked&>(np);
+   VERIFY( npd.base_truename() == basestr );
+ }
+ 
+ int main()
+ {
+   test01();
+   return 0;
+ }
Index: testsuite/22_locale/numpunct/members/wchar_t/cache_2.cc
===================================================================
RCS file: testsuite/22_locale/numpunct/members/wchar_t/cache_2.cc
diff -N testsuite/22_locale/numpunct/members/wchar_t/cache_2.cc
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/22_locale/numpunct/members/wchar_t/cache_2.cc	10 Jul 2003 05:53:28 -0000
***************
*** 0 ****
--- 1,90 ----
+ // 2003-07-06  Benjamin Kosnik  <bkoz@redhat.com>
+ 
+ // 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 <locale>
+ #include <sstream>
+ #include <ostream>
+ #include <testsuite_hooks.h>
+ 
+ class numpunct_checked : public std::numpunct<wchar_t>
+ {
+   typedef std::numpunct<wchar_t> 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<wchar_t>& np = use_facet<numpunct<wchar_t> >(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<const numpunct_checked&>(np);
+   VERIFY( npd.base_truename() == basestr );
+ }
+ 
+ int main()
+ {
+   test01();
+   return 0;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]