xref: /openbsd-src/gnu/lib/libstdc++/libstdc++/include/bits/locale_classes.h (revision 534d6ef73a061b07292185cee5cb8230994f382b)
103a78d15Sespie // Locale support -*- C++ -*-
203a78d15Sespie 
303a78d15Sespie // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
403a78d15Sespie // Free Software Foundation, Inc.
503a78d15Sespie //
603a78d15Sespie // This file is part of the GNU ISO C++ Library.  This library is free
703a78d15Sespie // software; you can redistribute it and/or modify it under the
803a78d15Sespie // terms of the GNU General Public License as published by the
903a78d15Sespie // Free Software Foundation; either version 2, or (at your option)
1003a78d15Sespie // any later version.
1103a78d15Sespie 
1203a78d15Sespie // This library is distributed in the hope that it will be useful,
1303a78d15Sespie // but WITHOUT ANY WARRANTY; without even the implied warranty of
1403a78d15Sespie // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1503a78d15Sespie // GNU General Public License for more details.
1603a78d15Sespie 
1703a78d15Sespie // You should have received a copy of the GNU General Public License along
1803a78d15Sespie // with this library; see the file COPYING.  If not, write to the Free
1903a78d15Sespie // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2003a78d15Sespie // USA.
2103a78d15Sespie 
2203a78d15Sespie // As a special exception, you may use this file as part of a free software
2303a78d15Sespie // library without restriction.  Specifically, if other files instantiate
2403a78d15Sespie // templates or use macros or inline functions from this file, or you compile
2503a78d15Sespie // this file and link it with other files to produce an executable, this
2603a78d15Sespie // file does not by itself cause the resulting executable to be covered by
2703a78d15Sespie // the GNU General Public License.  This exception does not however
2803a78d15Sespie // invalidate any other reasons why the executable file might be covered by
2903a78d15Sespie // the GNU General Public License.
3003a78d15Sespie 
3103a78d15Sespie //
3203a78d15Sespie // ISO C++ 14882: 22.1  Locales
3303a78d15Sespie //
3403a78d15Sespie 
3503a78d15Sespie /** @file localefwd.h
3603a78d15Sespie  *  This is an internal header file, included by other library headers.
3703a78d15Sespie  *  You should not attempt to use it directly.
3803a78d15Sespie  */
3903a78d15Sespie 
4003a78d15Sespie #ifndef _CPP_BITS_LOCALE_CLASSES_H
4103a78d15Sespie #define _CPP_BITS_LOCALE_CLASSES_H	1
4203a78d15Sespie 
4303a78d15Sespie #pragma GCC system_header
4403a78d15Sespie 
4503a78d15Sespie #include <bits/localefwd.h>
4603a78d15Sespie #include <cstring>		// For strcmp.
4703a78d15Sespie #include <string>
4803a78d15Sespie #include <bits/atomicity.h>
4903a78d15Sespie 
5003a78d15Sespie namespace std
5103a78d15Sespie {
5203a78d15Sespie   class __locale_cache_base;
5303a78d15Sespie   template<typename _Facet> class __locale_cache;
5403a78d15Sespie 
5503a78d15Sespie   // 22.1.1 Class locale
5603a78d15Sespie   class locale
5703a78d15Sespie   {
5803a78d15Sespie   public:
5903a78d15Sespie     // Types:
6003a78d15Sespie     typedef unsigned int 	category;
6103a78d15Sespie 
6203a78d15Sespie     // Forward decls and friends:
6303a78d15Sespie     class facet;
6403a78d15Sespie     class id;
6503a78d15Sespie     class _Impl;
6603a78d15Sespie 
6703a78d15Sespie     friend class facet;
6803a78d15Sespie     friend class _Impl;
6903a78d15Sespie 
7003a78d15Sespie     template<typename _Facet>
7103a78d15Sespie       friend const _Facet&
7203a78d15Sespie       use_facet(const locale&);
7303a78d15Sespie 
7403a78d15Sespie     template<typename _Facet>
7503a78d15Sespie       friend bool
7603a78d15Sespie       has_facet(const locale&) throw();
7703a78d15Sespie 
7803a78d15Sespie     template<typename _Facet>
7903a78d15Sespie       friend const __locale_cache<_Facet>&
8003a78d15Sespie       __use_cache(const locale&);
8103a78d15Sespie 
8203a78d15Sespie     // Category values:
8303a78d15Sespie     // NB: Order must match _S_facet_categories definition in locale.cc
8403a78d15Sespie     static const category none		= 0;
8503a78d15Sespie     static const category ctype 	= 1L << 0;
8603a78d15Sespie     static const category numeric 	= 1L << 1;
8703a78d15Sespie     static const category collate  	= 1L << 2;
8803a78d15Sespie     static const category time 		= 1L << 3;
8903a78d15Sespie     static const category monetary 	= 1L << 4;
9003a78d15Sespie     static const category messages 	= 1L << 5;
9103a78d15Sespie     static const category all 		= (ctype | numeric | collate |
9203a78d15Sespie 				 	   time  | monetary | messages);
9303a78d15Sespie 
9403a78d15Sespie     // Construct/copy/destroy:
9503a78d15Sespie     locale() throw();
9603a78d15Sespie 
9703a78d15Sespie     locale(const locale& __other) throw();
9803a78d15Sespie 
9903a78d15Sespie     explicit
10003a78d15Sespie     locale(const char* __s);
10103a78d15Sespie 
10203a78d15Sespie     locale(const locale& __base, const char* __s, category __cat);
10303a78d15Sespie 
10403a78d15Sespie     locale(const locale& __base, const locale& __add, category __cat);
10503a78d15Sespie 
10603a78d15Sespie     template<typename _Facet>
10703a78d15Sespie       locale(const locale& __other, _Facet* __f);
10803a78d15Sespie 
10903a78d15Sespie     ~locale() throw();
11003a78d15Sespie 
11103a78d15Sespie     const locale&
11203a78d15Sespie     operator=(const locale& __other) throw();
11303a78d15Sespie 
11403a78d15Sespie     template<typename _Facet>
11503a78d15Sespie       locale
11603a78d15Sespie       combine(const locale& __other) const;
11703a78d15Sespie 
11803a78d15Sespie     // Locale operations:
11903a78d15Sespie     string
12003a78d15Sespie     name() const;
12103a78d15Sespie 
12203a78d15Sespie     bool
12303a78d15Sespie     operator==(const locale& __other) const throw ();
12403a78d15Sespie 
12503a78d15Sespie     inline bool
12603a78d15Sespie     operator!=(const locale& __other) const throw ()
12703a78d15Sespie     { return !(this->operator==(__other));  }
12803a78d15Sespie 
12903a78d15Sespie     template<typename _Char, typename _Traits, typename _Alloc>
13003a78d15Sespie       bool
13103a78d15Sespie       operator()(const basic_string<_Char, _Traits, _Alloc>& __s1,
13203a78d15Sespie 		 const basic_string<_Char, _Traits, _Alloc>& __s2) const;
13303a78d15Sespie 
13403a78d15Sespie     // Global locale objects:
13503a78d15Sespie     static locale
13603a78d15Sespie     global(const locale&);
13703a78d15Sespie 
13803a78d15Sespie     static const locale&
13903a78d15Sespie     classic();
14003a78d15Sespie 
14103a78d15Sespie   private:
14203a78d15Sespie     // The (shared) implementation
14303a78d15Sespie     _Impl* 		_M_impl;
14403a78d15Sespie 
14503a78d15Sespie     // The "C" reference locale
14603a78d15Sespie     static _Impl* 	_S_classic;
14703a78d15Sespie 
14803a78d15Sespie     // Current global locale
14903a78d15Sespie     static _Impl* 	_S_global;
15003a78d15Sespie 
15103a78d15Sespie     // Number of standard categories. For C++, these categories are
15203a78d15Sespie     // collate, ctype, monetary, numeric, time, and messages. These
15303a78d15Sespie     // directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE,
15403a78d15Sespie     // LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE
15503a78d15Sespie     // 1003.1-2001) specifies LC_MESSAGES.
15603a78d15Sespie     static const size_t	_S_categories_size = 6;
15703a78d15Sespie 
15803a78d15Sespie     // In addition to the standard categories, the underlying
15903a78d15Sespie     // operating system is allowed to define extra LC_*
16003a78d15Sespie     // macros. For GNU systems, the following are also valid:
16103a78d15Sespie     // LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT,
16203a78d15Sespie     // and LC_IDENTIFICATION.
16303a78d15Sespie     static const size_t	_S_extra_categories_size = _GLIBCPP_NUM_CATEGORIES;
16403a78d15Sespie 
16503a78d15Sespie     // Names of underlying locale categories.
16603a78d15Sespie     // NB: locale::global() has to know how to modify all the
16703a78d15Sespie     // underlying categories, not just the ones required by the C++
16803a78d15Sespie     // standard.
16903a78d15Sespie     static const char* 	_S_categories[_S_categories_size
17003a78d15Sespie 				      + _S_extra_categories_size];
17103a78d15Sespie 
17203a78d15Sespie     explicit
17303a78d15Sespie     locale(_Impl*) throw();
17403a78d15Sespie 
17503a78d15Sespie     static inline void
_S_initialize()17603a78d15Sespie     _S_initialize()
17703a78d15Sespie     {
17803a78d15Sespie       if (!_S_classic)
17903a78d15Sespie 	classic();
18003a78d15Sespie     }
18103a78d15Sespie 
18203a78d15Sespie     static category
18303a78d15Sespie     _S_normalize_category(category);
18403a78d15Sespie 
18503a78d15Sespie     void
18603a78d15Sespie     _M_coalesce(const locale& __base, const locale& __add, category __cat);
18703a78d15Sespie   };
18803a78d15Sespie 
18903a78d15Sespie 
19003a78d15Sespie   // Implementation object for locale
19103a78d15Sespie   class locale::_Impl
19203a78d15Sespie   {
19303a78d15Sespie   public:
19403a78d15Sespie     // Friends.
19503a78d15Sespie     friend class locale;
19603a78d15Sespie     friend class locale::facet;
19703a78d15Sespie 
19803a78d15Sespie     template<typename _Facet>
19903a78d15Sespie       friend const _Facet&
20003a78d15Sespie       use_facet(const locale&);
20103a78d15Sespie 
20203a78d15Sespie     template<typename _Facet>
20303a78d15Sespie       friend bool
20403a78d15Sespie       has_facet(const locale&) throw();
20503a78d15Sespie 
20603a78d15Sespie     template<typename _Facet>
20703a78d15Sespie       friend const __locale_cache<_Facet>&
20803a78d15Sespie       __use_cache(const locale&);
20903a78d15Sespie 
21003a78d15Sespie   private:
21103a78d15Sespie     // Data Members.
21203a78d15Sespie     _Atomic_word			_M_references;
21303a78d15Sespie     facet** 				_M_facets;
21403a78d15Sespie     size_t 				_M_facets_size;
21503a78d15Sespie 
21603a78d15Sespie     char* 				_M_names[_S_categories_size
21703a78d15Sespie 						 + _S_extra_categories_size];
21803a78d15Sespie     static const locale::id* const 	_S_id_ctype[];
21903a78d15Sespie     static const locale::id* const 	_S_id_numeric[];
22003a78d15Sespie     static const locale::id* const 	_S_id_collate[];
22103a78d15Sespie     static const locale::id* const 	_S_id_time[];
22203a78d15Sespie     static const locale::id* const 	_S_id_monetary[];
22303a78d15Sespie     static const locale::id* const 	_S_id_messages[];
22403a78d15Sespie     static const locale::id* const* const _S_facet_categories[];
22503a78d15Sespie 
22603a78d15Sespie     inline void
_M_add_reference()22703a78d15Sespie     _M_add_reference() throw()
22803a78d15Sespie     { __atomic_add(&_M_references, 1); }
22903a78d15Sespie 
23003a78d15Sespie     inline void
_M_remove_reference()23103a78d15Sespie     _M_remove_reference() throw()
23203a78d15Sespie     {
23303a78d15Sespie       if (__exchange_and_add(&_M_references, -1) == 1)
23403a78d15Sespie 	{
23503a78d15Sespie 	  try
23603a78d15Sespie 	    { delete this; }
23703a78d15Sespie 	  catch(...)
23803a78d15Sespie 	    { }
23903a78d15Sespie 	}
24003a78d15Sespie     }
24103a78d15Sespie 
24203a78d15Sespie     _Impl(const _Impl&, size_t);
24303a78d15Sespie     _Impl(const char*, size_t);
24403a78d15Sespie     _Impl(facet**, size_t, bool);
24503a78d15Sespie 
24603a78d15Sespie    ~_Impl() throw();
24703a78d15Sespie 
24803a78d15Sespie     _Impl(const _Impl&);  // Not defined.
24903a78d15Sespie 
25003a78d15Sespie     void
25103a78d15Sespie     operator=(const _Impl&);  // Not defined.
25203a78d15Sespie 
25303a78d15Sespie     inline bool
_M_check_same_name()25403a78d15Sespie     _M_check_same_name()
25503a78d15Sespie     {
25603a78d15Sespie       bool __ret = true;
25703a78d15Sespie       for (size_t __i = 0;
25803a78d15Sespie 	   __ret && __i < _S_categories_size + _S_extra_categories_size - 1;
25903a78d15Sespie 	   ++__i)
26003a78d15Sespie 	__ret &= (strcmp(_M_names[__i], _M_names[__i + 1]) == 0);
26103a78d15Sespie       return __ret;
26203a78d15Sespie     }
26303a78d15Sespie 
26403a78d15Sespie     void
26503a78d15Sespie     _M_replace_categories(const _Impl*, category);
26603a78d15Sespie 
26703a78d15Sespie     void
26803a78d15Sespie     _M_replace_category(const _Impl*, const locale::id* const*);
26903a78d15Sespie 
27003a78d15Sespie     void
27103a78d15Sespie     _M_replace_facet(const _Impl*, const locale::id*);
27203a78d15Sespie 
27303a78d15Sespie     void
27403a78d15Sespie     _M_install_facet(const locale::id*, facet*);
27503a78d15Sespie 
27603a78d15Sespie     template<typename _Facet>
27703a78d15Sespie       inline void
_M_init_facet(_Facet * __facet)27803a78d15Sespie       _M_init_facet(_Facet* __facet)
27903a78d15Sespie       { _M_install_facet(&_Facet::id, __facet);  }
28003a78d15Sespie 
28103a78d15Sespie     // Retrieve the cache at __index.  0 is returned if the cache is
28203a78d15Sespie     // missing.  Cache is actually located at __index +
28303a78d15Sespie     // _M_facets_size.  __index must be < _M_facets_size.
28403a78d15Sespie     inline __locale_cache_base*
_M_get_cache(size_t __index)28503a78d15Sespie       _M_get_cache(size_t __index)
28603a78d15Sespie       {
28703a78d15Sespie 	return (__locale_cache_base*)_M_facets[__index + _M_facets_size];
28803a78d15Sespie       }
28903a78d15Sespie 
29003a78d15Sespie     // Save the supplied cache at __id.  Assumes _M_get_cache has been
29103a78d15Sespie     // called.
29203a78d15Sespie     void
_M_install_cache(__locale_cache_base * __cache,int __id)29303a78d15Sespie     _M_install_cache(__locale_cache_base* __cache, int __id)
29403a78d15Sespie     {
29503a78d15Sespie       _M_facets[__id + _M_facets_size] =
29603a78d15Sespie 	reinterpret_cast<locale::facet*>(__cache);
29703a78d15Sespie     }
29803a78d15Sespie 
29903a78d15Sespie   };
30003a78d15Sespie 
30103a78d15Sespie   template<typename _Facet>
locale(const locale & __other,_Facet * __f)30203a78d15Sespie     locale::locale(const locale& __other, _Facet* __f)
30303a78d15Sespie     {
30403a78d15Sespie       _M_impl = new _Impl(*__other._M_impl, 1);
30519731d4fSespie 
30619731d4fSespie       char* _M_tmp_names[_S_categories_size + _S_extra_categories_size];
30719731d4fSespie       size_t __i = 0;
30819731d4fSespie       try
30903a78d15Sespie 	{
31019731d4fSespie 	  for (; __i < _S_categories_size
31119731d4fSespie 		       + _S_extra_categories_size; ++__i)
31219731d4fSespie 	    {
31319731d4fSespie 	      _M_tmp_names[__i] = new char[2];
314*534d6ef7Sespie 	      strlcpy(_M_tmp_names[__i], "*", 2);
31519731d4fSespie 	    }
31619731d4fSespie 	  _M_impl->_M_install_facet(&_Facet::id, __f);
31719731d4fSespie 	}
31819731d4fSespie       catch(...)
31919731d4fSespie 	{
32019731d4fSespie 	  _M_impl->_M_remove_reference();
32119731d4fSespie 	  for (size_t __j = 0; __j < __i; ++__j)
32219731d4fSespie 	    delete [] _M_tmp_names[__j];
32319731d4fSespie 	  __throw_exception_again;
32419731d4fSespie 	}
32519731d4fSespie 
32619731d4fSespie       for (size_t __k = 0; __k < _S_categories_size
32719731d4fSespie 	                         + _S_extra_categories_size; ++__k)
32819731d4fSespie 	{
32919731d4fSespie 	  delete [] _M_impl->_M_names[__k];
33019731d4fSespie 	  _M_impl->_M_names[__k] = _M_tmp_names[__k];
33103a78d15Sespie 	}
33203a78d15Sespie     }
33303a78d15Sespie 
33403a78d15Sespie 
33503a78d15Sespie   // 22.1.1.1.2  Class locale::facet
33603a78d15Sespie   class locale::facet
33703a78d15Sespie   {
33803a78d15Sespie   private:
33903a78d15Sespie     friend class locale;
34003a78d15Sespie     friend class locale::_Impl;
34103a78d15Sespie 
34203a78d15Sespie     _Atomic_word 			_M_references;
34303a78d15Sespie 
34403a78d15Sespie   protected:
34503a78d15Sespie     // Contains data from the underlying "C" library for the classic locale.
34603a78d15Sespie     static __c_locale		     	_S_c_locale;
34703a78d15Sespie 
34803a78d15Sespie     // String literal for the name of the classic locale.
34903a78d15Sespie     static char				_S_c_name[2];
35003a78d15Sespie 
35103a78d15Sespie     explicit
35203a78d15Sespie     facet(size_t __refs = 0) throw();
35303a78d15Sespie 
35403a78d15Sespie     virtual
35503a78d15Sespie     ~facet();
35603a78d15Sespie 
35703a78d15Sespie     static void
35803a78d15Sespie     _S_create_c_locale(__c_locale& __cloc, const char* __s,
35903a78d15Sespie 		       __c_locale __old = 0);
36003a78d15Sespie 
36103a78d15Sespie     static __c_locale
36203a78d15Sespie     _S_clone_c_locale(__c_locale& __cloc);
36303a78d15Sespie 
36403a78d15Sespie     static void
36503a78d15Sespie     _S_destroy_c_locale(__c_locale& __cloc);
36603a78d15Sespie 
36703a78d15Sespie   private:
36803a78d15Sespie     void
36903a78d15Sespie     _M_add_reference() throw();
37003a78d15Sespie 
37103a78d15Sespie     void
37203a78d15Sespie     _M_remove_reference() throw();
37303a78d15Sespie 
37403a78d15Sespie     facet(const facet&);  // Not defined.
37503a78d15Sespie 
37603a78d15Sespie     void
37703a78d15Sespie     operator=(const facet&);  // Not defined.
37803a78d15Sespie   };
37903a78d15Sespie 
38003a78d15Sespie 
38103a78d15Sespie   // 22.1.1.1.3 Class locale::id
38203a78d15Sespie   class locale::id
38303a78d15Sespie   {
38403a78d15Sespie   private:
38503a78d15Sespie     friend class locale;
38603a78d15Sespie     friend class locale::_Impl;
38703a78d15Sespie     template<typename _Facet>
38803a78d15Sespie       friend const _Facet&
38903a78d15Sespie       use_facet(const locale&);
39003a78d15Sespie     template<typename _Facet>
39103a78d15Sespie       friend bool
39203a78d15Sespie       has_facet(const locale&) throw ();
39303a78d15Sespie 
39403a78d15Sespie     // NB: There is no accessor for _M_index because it may be used
39503a78d15Sespie     // before the constructor is run; the effect of calling a member
39603a78d15Sespie     // function (even an inline) would be undefined.
39703a78d15Sespie     mutable size_t 		_M_index;
39803a78d15Sespie 
39903a78d15Sespie     // Last id number assigned.
40003a78d15Sespie     static _Atomic_word 	_S_highwater;
40103a78d15Sespie 
40203a78d15Sespie     void
40303a78d15Sespie     operator=(const id&);  // Not defined.
40403a78d15Sespie 
40503a78d15Sespie     id(const id&);  // Not defined.
40603a78d15Sespie 
40703a78d15Sespie   public:
40803a78d15Sespie     // NB: This class is always a static data member, and thus can be
40903a78d15Sespie     // counted on to be zero-initialized.
41003a78d15Sespie     id();
41103a78d15Sespie 
41203a78d15Sespie     inline size_t
_M_id()41303a78d15Sespie     _M_id() const
41403a78d15Sespie     {
41503a78d15Sespie       if (!_M_index)
41603a78d15Sespie 	_M_index = 1 + __exchange_and_add(&_S_highwater, 1);
41703a78d15Sespie       return _M_index - 1;
41803a78d15Sespie     }
41903a78d15Sespie   };
42003a78d15Sespie } // namespace std
42103a78d15Sespie 
42203a78d15Sespie #endif
423