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