| /*************************************************************************** |
| * |
| * locale_body.h - definition of the __rw_locale class |
| * |
| * This is an internal header file used to implement the C++ Standard |
| * Library. It should never be #included directly by a program. |
| * |
| * $Id$ |
| * |
| *************************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed |
| * with this work for additional information regarding copyright |
| * ownership. The ASF licenses this file to you under the Apache |
| * License, Version 2.0 (the "License"); you may not use this file |
| * except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. See the License for the specific language governing |
| * permissions and limitations under the License. |
| * |
| * Copyright 1994-2006 Rogue Wave Software. |
| * |
| **************************************************************************/ |
| |
| #ifndef _RWSTD_LOC_RW_LOCALE_H_INCLUDED |
| #define _RWSTD_LOC_RW_LOCALE_H_INCLUDED |
| |
| |
| #include <loc/_facet.h> |
| #include <loc/_locale.h> |
| #include <string.h> |
| |
| #include "podarray.h" |
| |
| #include <rw/_defs.h> |
| |
| |
| _RWSTD_NAMESPACE (std) { |
| |
| struct _RWSTD_CLASS_EXPORT locale; |
| |
| } // namespace std |
| |
| |
| _RWSTD_NAMESPACE (__rw) { |
| |
| |
| class _RWSTD_EXPORT __rw_locale |
| { |
| public: |
| // total number of standard facets (char and wchar specializations) |
| // ordinary (unnamed) and byname facets share the same array slot |
| enum { _C_n_std_facets = __rw_facet::_C_last_type / 2 }; |
| enum { _C_namebuf_size = 40 }; |
| |
| private: |
| // standard facets are always present, user defined facets (i.e., |
| // non-standard specializations of standard facets, or user-defined |
| // facets with own id's) are dynamically allocated only if installed |
| |
| // each standard facet is stored at an index, inx, computed from its |
| // numeric id, as follows: inx = (Facet::id._C_id - 1) / 2 |
| // each slot holds either an ordinary (unnamed) or a byname standard |
| // facet (if the latter exists) |
| __rw_facet *_C_std_facets [_C_n_std_facets]; |
| __rw_facet **_C_usr_facets; // array of pointers to user facets |
| _RWSTD_SIZE_T _C_n_usr_facets; // number of user-defined facets |
| |
| // name buffer sufficiently large to accommodate 6 basic 5-character |
| // POSIX locale names such as "en_US" (one for each LC_XXX category) |
| char _C_namebuf [_C_namebuf_size]; |
| const char *_C_name; // name of locale (!= 0) |
| _RWSTD_SIZE_T _C_ref; // reference count (>= 0) |
| |
| // a bit is set for each standard ordinary (unnamed) or byname facet that |
| // is installed in the locale, and clear for each standard facet that has |
| // been replaced with a user-defined (or user-constructed) object (i.e., |
| // one with the same id) in the locale object |
| _RWSTD_SIZE_T _C_std_facet_bits; |
| |
| // a bit is set for each standard byname facet that is installed in |
| // the locale object, and clear for each standard byname facet that |
| // has been replaced with a user-defined (or user-constructed) object |
| // (i.e., one with the same id) in the locale object |
| _RWSTD_SIZE_T _C_byname_facet_bits; |
| |
| __rw_mutex _C_mutex; |
| |
| friend struct _STD::locale; |
| |
| public: |
| |
| enum { |
| |
| #define _FACET_BIT(name) (1U << (__rw_facet::_C_##name - 1U) / 2U) |
| |
| // bitmaps of standard facet types for each category |
| // used to set and test the value _C_{std,byname}_facet_bits |
| // to quickly determine the composition of a locale object |
| |
| _C_collate = _FACET_BIT (collate) | _FACET_BIT (wcollate), |
| _C_ctype = _FACET_BIT (codecvt) | _FACET_BIT (ctype) |
| | _FACET_BIT (wcodecvt) | _FACET_BIT (wctype), |
| _C_monetary = _FACET_BIT (moneypunct) | _FACET_BIT (moneypunct_intl) |
| | _FACET_BIT (wmoneypunct) | _FACET_BIT (wmoneypunct_intl) |
| | _FACET_BIT (money_get) | _FACET_BIT (money_put) |
| | _FACET_BIT (wmoney_get) | _FACET_BIT (wmoney_put), |
| _C_numeric = _FACET_BIT (numpunct) | _FACET_BIT (wnumpunct) |
| | _FACET_BIT (num_get) | _FACET_BIT (num_put) |
| | _FACET_BIT (wnum_get) | _FACET_BIT (wnum_put), |
| _C_time = _FACET_BIT (time_get) | _FACET_BIT (time_put) |
| | _FACET_BIT (wtime_get) | _FACET_BIT (wtime_put), |
| _C_messages = _FACET_BIT (messages) | _FACET_BIT (wmessages), |
| _C_all = _C_collate | _C_ctype | _C_monetary |
| | _C_numeric | _C_time | _C_messages |
| |
| #undef _FACET_BIT |
| |
| }; |
| |
| // create a locale body from the name of a locale |
| __rw_locale (const char*); |
| |
| // create a locale body from the name of a locale combined with a facet |
| __rw_locale (const char *__name, const __rw_facet *__facet) { |
| __rw_locale __tmp (__name); |
| _C_construct (__tmp, __facet); |
| } |
| |
| // create a locale body from another locale combined with a facet |
| __rw_locale (const __rw_locale &__rhs, const __rw_facet *__facet) { |
| _C_construct (__rhs, __facet); |
| } |
| |
| // create a locale body from two locales taking cats from the named one |
| __rw_locale (const __rw_locale &__rhs, const char *__name, int __cat) { |
| __rw_locale __tmp (__name); |
| _C_construct (__rhs, __tmp, __cat); |
| } |
| |
| // create a locale body from two locales taking cats from `l2' |
| __rw_locale (const __rw_locale &__l1, const __rw_locale &__l2, int __cat) { |
| _C_construct (__l1, __l2, __cat); |
| } |
| |
| ~__rw_locale (); |
| |
| // returns the name of the locale |
| const char* _C_get_name () const { |
| return _C_name; |
| } |
| |
| static _RWSTD_SIZE_T _C_add_ref (__rw_facet &__facet) { |
| return _RWSTD_ATOMIC_PREINCREMENT (__facet._C_ref, false); |
| } |
| |
| static _RWSTD_SIZE_T _C_remove_ref (__rw_facet &__facet) { |
| return _RWSTD_ATOMIC_PREDECREMENT (__facet._C_ref, false); |
| } |
| |
| _RWSTD_SIZE_T _C_add_ref () { |
| return _RWSTD_ATOMIC_PREINCREMENT (_C_ref, _C_mutex); |
| } |
| |
| _RWSTD_SIZE_T _C_remove_ref () { |
| return _RWSTD_ATOMIC_PREDECREMENT (_C_ref, _C_mutex); |
| } |
| |
| // access private facet name |
| static const char* _C_get_cat_name (const __rw_facet &__facet) { |
| return __facet._C_name; |
| } |
| |
| // get a string of locale names, one for each installed standard |
| // facet's category; will dynamically allocate string if buf is 0 |
| char* _C_get_cat_names (char*, _RWSTD_SIZE_T) const; |
| |
| // returns true iff all categories of facets (given by the bitmap) |
| // in *this are being globally managed, i.e., iff all of *this facets |
| // whose category matches the bitmap are also being globally managed |
| // (when the category is locale::none, the function fails for all |
| // locales that contain any user-defined facets; otherwise only |
| // standard facets are considered) |
| bool _C_is_managed (int) const; |
| |
| // converts a LC_XXX constant to a locale::category value |
| static int _C_LC2category (int); |
| |
| // converts a LC_XXX constant to an internal bitset of facets |
| static int _C_LC2facet_bits (int); |
| |
| static bool _C_check_category (int); |
| |
| // returns the type of the standard facet object or `unknown' |
| // if the facet is of a user-defined type |
| static __rw_facet::_C_facet_type _C_get_facet_type (const __rw_facet&); |
| |
| private: |
| |
| // globally manages all named locales; implements default locale |
| // ctor, dtor, and locale::global() |
| static __rw_locale* _C_manage (__rw_locale*, const char*); |
| |
| // implements all but the default locale ctor; the function |
| // may construct a new object, return one of its first two |
| // arguments, or return a pointer to a cached locale object |
| static __rw_locale* |
| _C_get_body (__rw_locale*, __rw_locale*, |
| const char*, int, const __rw_facet*); |
| |
| // called from ctors (only) to fully construct a combined locale |
| void _C_construct (const __rw_locale&, const __rw_facet*); |
| void _C_construct (const __rw_locale&, const __rw_locale&, int); |
| |
| // implements locale template ctor: locale::locale (const locale&, Facet*) |
| __rw_locale* _C_combine (const __rw_facet*) const; |
| |
| // implements locale ctor: locale (const locale&, const locale&, category) |
| __rw_locale* _C_combine (const __rw_locale&, int); |
| |
| // returns the index into one of the facet arrays |
| // corresponding to the given facet id: |
| // -1 if the facet isn't installed |
| // value < _C_n_std_facets for a standard facet |
| // value >= _C_n_std_facets otherwise (i.e., for user defined facets) |
| _RWSTD_SIZE_T _C_get_facet_inx (_RWSTD_SIZE_T) const; |
| }; |
| |
| |
| /* static */ inline bool __rw_locale::_C_check_category (int cat) |
| { |
| // `cat' is assumed to be a C++ locale category (i.e., not an LC_XXX) |
| _RWSTD_ASSERT (cat == _C_LC2category (cat)); |
| |
| return __rw_cat_none == cat || !(cat & ~__rw_cat_all); |
| } |
| |
| |
| /* static */ inline __rw_facet::_C_facet_type |
| __rw_locale::_C_get_facet_type (const __rw_facet &__facet) |
| { |
| _RWSTD_ASSERT (0 != __facet._C_pid); |
| _RWSTD_ASSERT (0 != *__facet._C_pid); |
| |
| // compute the numeric value of the facet's type |
| const _RWSTD_SIZE_T __numtype = |
| *__facet._C_pid * 2 - 1 + (0 != __facet._C_name); |
| |
| // return `unknown' for user-defined facets |
| return __numtype > __rw_facet::_C_last_type ? |
| __rw_facet::_C_unknown : __rw_facet::_C_facet_type (__numtype); |
| } |
| |
| |
| // a one-character string to separate LC_XXX categories in locale names |
| #ifndef _RWSTD_CAT_SEP |
| # define _RWSTD_CAT_SEP "" |
| #endif |
| |
| |
| // maps LC_XXX category values to their names |
| extern const struct __rw_cats_t |
| { |
| int cat; // LC_XXX category |
| const char *name; // LC_XXX name |
| int facet_bits; // bitmap of facet types |
| } __rw_cats [6]; |
| |
| static const _RWSTD_SIZE_T __rw_n_cats = 6; |
| |
| |
| // computes LC_XXX category from a numeric facet id, returns the |
| // LC_XXX category for standard facets, LC_ALL for all others |
| inline int __rw_get_cat (int id) |
| { |
| #if _RWSTD_LC_MIN >= 0 && _RWSTD_LC_MAX < _RWSTD_UCHAR_MAX |
| typedef unsigned char LC_type; |
| #else |
| typedef int LC_type; |
| #endif // _RWSTD_LC_MIN >= 0 && _RWSTD_LC_MAX < _RWSTD_UCHAR_MAX |
| |
| const LC_type lc_cats[] = { |
| _RWSTD_LC_COLLATE, |
| // _C_codecvt, _C_ctype (all derivatives and specialiations) |
| _RWSTD_LC_CTYPE, _RWSTD_LC_CTYPE, |
| // _C_moneypunct, _C_moneypunct_intl, _C_money_get, _C_money_put |
| _RWSTD_LC_MONETARY, _RWSTD_LC_MONETARY, |
| _RWSTD_LC_MONETARY, _RWSTD_LC_MONETARY, |
| // _C_numpunct, _C_num_get, _C_num_put |
| _RWSTD_LC_NUMERIC, _RWSTD_LC_NUMERIC, _RWSTD_LC_NUMERIC, |
| // _C_time_get, _C_time_put |
| _RWSTD_LC_TIME, _RWSTD_LC_TIME, |
| #ifdef _RWSTD_LC_MESSAGES |
| // _C_messages |
| _RWSTD_LC_MESSAGES |
| #else |
| _RWSTD_LC_MAX + 1 |
| #endif |
| }; |
| |
| return id > 0 && id <= __rw_locale::_C_n_std_facets ? |
| lc_cats [((id - 1) % (sizeof lc_cats / sizeof *lc_cats))] |
| : _RWSTD_LC_ALL; |
| } |
| |
| |
| #ifndef _RWSTD_NO_CONDENSED_NAME |
| |
| static const char __rw_C_locale_name[] = "C"; |
| |
| #else // if defined (_RWSTD_NO_CONDENSED_NAME) |
| |
| static const char __rw_C_locale_name[] = { |
| 'C', *_RWSTD_CAT_SEP, 'C', *_RWSTD_CAT_SEP, 'C', *_RWSTD_CAT_SEP, |
| 'C', *_RWSTD_CAT_SEP, 'C', *_RWSTD_CAT_SEP, 'C', '\0' |
| }; |
| |
| #endif // _RWSTD_NO_CONDENSED_NAME |
| |
| |
| // returns true iff `name' is a name of the classic C locale |
| static inline bool __rw_is_C (const char *name) |
| { |
| _RWSTD_ASSERT (0 != name); |
| |
| return 'C' == name [0] && '\0' == name [1] |
| |
| #ifdef _RWSTD_NO_CONDENSED_NAME |
| |
| || !strcmp (__rw_C_locale_name, name) |
| |
| #endif // _RWSTD_NO_CONDENSED_NAME |
| |
| ; |
| } |
| |
| |
| } // namespace __rw |
| |
| |
| #endif // _RWSTD_LOC_RW_LOCALE_H_INCLUDED |