Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
locale_body.h
Go to the documentation of this file.
1
32#ifndef _RWSTD_LOC_RW_LOCALE_H_INCLUDED
33#define _RWSTD_LOC_RW_LOCALE_H_INCLUDED
34
35
36#include <loc/_facet.h>
37#include <loc/_locale.h>
38#include <string.h>
39
40#include "podarray.h"
41
42#include <rw/_defs.h>
43
44
46
47struct _RWSTD_CLASS_EXPORT locale;
48
49} // namespace std
50
51
53
54
55class _RWSTD_EXPORT __rw_locale
56{
57public:
58 // total number of standard facets (char and wchar specializations)
59 // ordinary (unnamed) and byname facets share the same array slot
60 enum { _C_n_std_facets = __rw_facet::_C_last_type / 2 };
61 enum { _C_namebuf_size = 40 };
62
63private:
64 // standard facets are always present, user defined facets (i.e.,
65 // non-standard specializations of standard facets, or user-defined
66 // facets with own id's) are dynamically allocated only if installed
67
68 // each standard facet is stored at an index, inx, computed from its
69 // numeric id, as follows: inx = (Facet::id._C_id - 1) / 2
70 // each slot holds either an ordinary (unnamed) or a byname standard
71 // facet (if the latter exists)
72 __rw_facet *_C_std_facets [_C_n_std_facets];
73 __rw_facet **_C_usr_facets; // array of pointers to user facets
74 _RWSTD_SIZE_T _C_n_usr_facets; // number of user-defined facets
75
76 // name buffer sufficiently large to accommodate 6 basic 5-character
77 // POSIX locale names such as "en_US" (one for each LC_XXX category)
78 char _C_namebuf [_C_namebuf_size];
79 const char *_C_name; // name of locale (!= 0)
80 _RWSTD_SIZE_T _C_ref; // reference count (>= 0)
81
82 // a bit is set for each standard ordinary (unnamed) or byname facet that
83 // is installed in the locale, and clear for each standard facet that has
84 // been replaced with a user-defined (or user-constructed) object (i.e.,
85 // one with the same id) in the locale object
86 _RWSTD_SIZE_T _C_std_facet_bits;
87
88 // a bit is set for each standard byname facet that is installed in
89 // the locale object, and clear for each standard byname facet that
90 // has been replaced with a user-defined (or user-constructed) object
91 // (i.e., one with the same id) in the locale object
92 _RWSTD_SIZE_T _C_byname_facet_bits;
93
94 __rw_mutex _C_mutex;
95
96 friend struct _STD::locale;
97
98public:
99
100 enum {
101
102#define _FACET_BIT(name) (1U << (__rw_facet::_C_##name - 1U) / 2U)
103
104 // bitmaps of standard facet types for each category
105 // used to set and test the value _C_{std,byname}_facet_bits
106 // to quickly determine the composition of a locale object
107
108 _C_collate = _FACET_BIT (collate) | _FACET_BIT (wcollate),
109 _C_ctype = _FACET_BIT (codecvt) | _FACET_BIT (ctype)
110 | _FACET_BIT (wcodecvt) | _FACET_BIT (wctype),
111 _C_monetary = _FACET_BIT (moneypunct) | _FACET_BIT (moneypunct_intl)
112 | _FACET_BIT (wmoneypunct) | _FACET_BIT (wmoneypunct_intl)
113 | _FACET_BIT (money_get) | _FACET_BIT (money_put)
114 | _FACET_BIT (wmoney_get) | _FACET_BIT (wmoney_put),
115 _C_numeric = _FACET_BIT (numpunct) | _FACET_BIT (wnumpunct)
116 | _FACET_BIT (num_get) | _FACET_BIT (num_put)
117 | _FACET_BIT (wnum_get) | _FACET_BIT (wnum_put),
118 _C_time = _FACET_BIT (time_get) | _FACET_BIT (time_put)
119 | _FACET_BIT (wtime_get) | _FACET_BIT (wtime_put),
120 _C_messages = _FACET_BIT (messages) | _FACET_BIT (wmessages),
121 _C_all = _C_collate | _C_ctype | _C_monetary
122 | _C_numeric | _C_time | _C_messages
123
124#undef _FACET_BIT
125
126 };
127
128 // create a locale body from the name of a locale
129 __rw_locale (const char*);
130
131 // create a locale body from the name of a locale combined with a facet
132 __rw_locale (const char *__name, const __rw_facet *__facet) {
133 __rw_locale __tmp (__name);
134 _C_construct (__tmp, __facet);
135 }
136
137 // create a locale body from another locale combined with a facet
138 __rw_locale (const __rw_locale &__rhs, const __rw_facet *__facet) {
139 _C_construct (__rhs, __facet);
140 }
141
142 // create a locale body from two locales taking cats from the named one
143 __rw_locale (const __rw_locale &__rhs, const char *__name, int __cat) {
144 __rw_locale __tmp (__name);
145 _C_construct (__rhs, __tmp, __cat);
146 }
147
148 // create a locale body from two locales taking cats from `l2'
149 __rw_locale (const __rw_locale &__l1, const __rw_locale &__l2, int __cat) {
150 _C_construct (__l1, __l2, __cat);
151 }
152
153 ~__rw_locale ();
154
155 // returns the name of the locale
156 const char* _C_get_name () const {
157 return _C_name;
158 }
159
160 static _RWSTD_SIZE_T _C_add_ref (__rw_facet &__facet) {
161 return _RWSTD_ATOMIC_PREINCREMENT (__facet._C_ref, false);
162 }
163
164 static _RWSTD_SIZE_T _C_remove_ref (__rw_facet &__facet) {
165 return _RWSTD_ATOMIC_PREDECREMENT (__facet._C_ref, false);
166 }
167
168 _RWSTD_SIZE_T _C_add_ref () {
169 return _RWSTD_ATOMIC_PREINCREMENT (_C_ref, _C_mutex);
170 }
171
172 _RWSTD_SIZE_T _C_remove_ref () {
173 return _RWSTD_ATOMIC_PREDECREMENT (_C_ref, _C_mutex);
174 }
175
176 // access private facet name
177 static const char* _C_get_cat_name (const __rw_facet &__facet) {
178 return __facet._C_name;
179 }
180
181 // get a string of locale names, one for each installed standard
182 // facet's category; will dynamically allocate string if buf is 0
183 char* _C_get_cat_names (char*, _RWSTD_SIZE_T) const;
184
185 // returns true iff all categories of facets (given by the bitmap)
186 // in *this are being globally managed, i.e., iff all of *this facets
187 // whose category matches the bitmap are also being globally managed
188 // (when the category is locale::none, the function fails for all
189 // locales that contain any user-defined facets; otherwise only
190 // standard facets are considered)
191 bool _C_is_managed (int) const;
192
193 // converts a LC_XXX constant to a locale::category value
194 static int _C_LC2category (int);
195
196 // converts a LC_XXX constant to an internal bitset of facets
197 static int _C_LC2facet_bits (int);
198
199 static bool _C_check_category (int);
200
201 // returns the type of the standard facet object or `unknown'
202 // if the facet is of a user-defined type
203 static __rw_facet::_C_facet_type _C_get_facet_type (const __rw_facet&);
204
205private:
206
207 // globally manages all named locales; implements default locale
208 // ctor, dtor, and locale::global()
209 static __rw_locale* _C_manage (__rw_locale*, const char*);
210
211 // implements all but the default locale ctor; the function
212 // may construct a new object, return one of its first two
213 // arguments, or return a pointer to a cached locale object
214 static __rw_locale*
215 _C_get_body (__rw_locale*, __rw_locale*,
216 const char*, int, const __rw_facet*);
217
218 // called from ctors (only) to fully construct a combined locale
219 void _C_construct (const __rw_locale&, const __rw_facet*);
220 void _C_construct (const __rw_locale&, const __rw_locale&, int);
221
222 // implements locale template ctor: locale::locale (const locale&, Facet*)
223 __rw_locale* _C_combine (const __rw_facet*) const;
224
225 // implements locale ctor: locale (const locale&, const locale&, category)
226 __rw_locale* _C_combine (const __rw_locale&, int);
227
228 // returns the index into one of the facet arrays
229 // corresponding to the given facet id:
230 // -1 if the facet isn't installed
231 // value < _C_n_std_facets for a standard facet
232 // value >= _C_n_std_facets otherwise (i.e., for user defined facets)
233 _RWSTD_SIZE_T _C_get_facet_inx (_RWSTD_SIZE_T) const;
234};
235
236
237/* static */ inline bool __rw_locale::_C_check_category (int cat)
238{
239 // `cat' is assumed to be a C++ locale category (i.e., not an LC_XXX)
240 _RWSTD_ASSERT (cat == _C_LC2category (cat));
241
242 return __rw_cat_none == cat || !(cat & ~__rw_cat_all);
243}
244
245
246/* static */ inline __rw_facet::_C_facet_type
247__rw_locale::_C_get_facet_type (const __rw_facet &__facet)
248{
249 _RWSTD_ASSERT (0 != __facet._C_pid);
250 _RWSTD_ASSERT (0 != *__facet._C_pid);
251
252 // compute the numeric value of the facet's type
253 const _RWSTD_SIZE_T __numtype =
254 *__facet._C_pid * 2 - 1 + (0 != __facet._C_name);
255
256 // return `unknown' for user-defined facets
257 return __numtype > __rw_facet::_C_last_type ?
258 __rw_facet::_C_unknown : __rw_facet::_C_facet_type (__numtype);
259}
260
261
262// a one-character string to separate LC_XXX categories in locale names
263#ifndef _RWSTD_CAT_SEP
264# define _RWSTD_CAT_SEP ""
265#endif
266
267
268// maps LC_XXX category values to their names
269extern const struct __rw_cats_t
270{
271 int cat; // LC_XXX category
272 const char *name; // LC_XXX name
273 int facet_bits; // bitmap of facet types
274} __rw_cats [6];
275
276static const _RWSTD_SIZE_T __rw_n_cats = 6;
277
278
279// computes LC_XXX category from a numeric facet id, returns the
280// LC_XXX category for standard facets, LC_ALL for all others
281inline int __rw_get_cat (int id)
282{
283#if _RWSTD_LC_MIN >= 0 && _RWSTD_LC_MAX < _RWSTD_UCHAR_MAX
284 typedef unsigned char LC_type;
285#else
286 typedef int LC_type;
287#endif // _RWSTD_LC_MIN >= 0 && _RWSTD_LC_MAX < _RWSTD_UCHAR_MAX
288
289 const LC_type lc_cats[] = {
290 _RWSTD_LC_COLLATE,
291 // _C_codecvt, _C_ctype (all derivatives and specialiations)
292 _RWSTD_LC_CTYPE, _RWSTD_LC_CTYPE,
293 // _C_moneypunct, _C_moneypunct_intl, _C_money_get, _C_money_put
294 _RWSTD_LC_MONETARY, _RWSTD_LC_MONETARY,
295 _RWSTD_LC_MONETARY, _RWSTD_LC_MONETARY,
296 // _C_numpunct, _C_num_get, _C_num_put
297 _RWSTD_LC_NUMERIC, _RWSTD_LC_NUMERIC, _RWSTD_LC_NUMERIC,
298 // _C_time_get, _C_time_put
299 _RWSTD_LC_TIME, _RWSTD_LC_TIME,
300#ifdef _RWSTD_LC_MESSAGES
301 // _C_messages
302 _RWSTD_LC_MESSAGES
303#else
304 _RWSTD_LC_MAX + 1
305#endif
306 };
307
308 return id > 0 && id <= __rw_locale::_C_n_std_facets ?
309 lc_cats [((id - 1) % (sizeof lc_cats / sizeof *lc_cats))]
310 : _RWSTD_LC_ALL;
311}
312
313
314#ifndef _RWSTD_NO_CONDENSED_NAME
315
316static const char __rw_C_locale_name[] = "C";
317
318#else // if defined (_RWSTD_NO_CONDENSED_NAME)
319
320static const char __rw_C_locale_name[] = {
321 'C', *_RWSTD_CAT_SEP, 'C', *_RWSTD_CAT_SEP, 'C', *_RWSTD_CAT_SEP,
322 'C', *_RWSTD_CAT_SEP, 'C', *_RWSTD_CAT_SEP, 'C', '\0'
323};
324
325#endif // _RWSTD_NO_CONDENSED_NAME
326
327
328// returns true iff `name' is a name of the classic C locale
329static inline bool __rw_is_C (const char *name)
330{
331 _RWSTD_ASSERT (0 != name);
332
333 return 'C' == name [0] && '\0' == name [1]
334
335#ifdef _RWSTD_NO_CONDENSED_NAME
336
337 || !strcmp (__rw_C_locale_name, name)
338
339#endif // _RWSTD_NO_CONDENSED_NAME
340
341 ;
342}
343
344
345} // namespace __rw
346
347
348#endif // _RWSTD_LOC_RW_LOCALE_H_INCLUDED
#define _RWSTD_CLASS_EXPORT
Definition _defs.h:486
#define _RWSTD_EXPORT
Definition _defs.h:485
#define _RWSTD_ATOMIC_PREINCREMENT(x, ignore)
Definition _defs.h:699
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_ATOMIC_PREDECREMENT(x, ignore)
Definition _defs.h:700
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
const char * name
Definition codecvt1.cpp:72
#define _FACET_BIT(name)
#define _RWSTD_CAT_SEP
Definition json.h:5363