]>
Commit | Line | Data |
---|---|---|
e6686813 BK |
1 | // Locale support -*- C++ -*- |
2 | ||
3 | // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 | |
4 | // Free Software Foundation, Inc. | |
5 | // | |
6 | // This file is part of the GNU ISO C++ Library. This library is free | |
7 | // software; you can redistribute it and/or modify it under the | |
8 | // terms of the GNU General Public License as published by the | |
9 | // Free Software Foundation; either version 2, or (at your option) | |
10 | // any later version. | |
11 | ||
12 | // This library is distributed in the hope that it will be useful, | |
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | // GNU General Public License for more details. | |
16 | ||
17 | // You should have received a copy of the GNU General Public License along | |
18 | // with this library; see the file COPYING. If not, write to the Free | |
19 | // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
20 | // USA. | |
21 | ||
22 | // As a special exception, you may use this file as part of a free software | |
23 | // library without restriction. Specifically, if other files instantiate | |
24 | // templates or use macros or inline functions from this file, or you compile | |
25 | // this file and link it with other files to produce an executable, this | |
26 | // file does not by itself cause the resulting executable to be covered by | |
27 | // the GNU General Public License. This exception does not however | |
28 | // invalidate any other reasons why the executable file might be covered by | |
29 | // the GNU General Public License. | |
30 | ||
31 | // | |
32 | // ISO C++ 14882: 22.1 Locales | |
33 | // | |
34 | ||
35 | /** @file localefwd.h | |
36 | * This is an internal header file, included by other library headers. | |
37 | * You should not attempt to use it directly. | |
38 | */ | |
39 | ||
3d7c150e BK |
40 | #ifndef _LOCALE_CLASSES_H |
41 | #define _LOCALE_CLASSES_H 1 | |
e6686813 BK |
42 | |
43 | #pragma GCC system_header | |
44 | ||
45 | #include <bits/localefwd.h> | |
e6686813 BK |
46 | #include <cstring> // For strcmp. |
47 | #include <string> | |
48 | #include <bits/atomicity.h> | |
8ae81136 | 49 | #include <bits/gthr.h> |
e6686813 BK |
50 | |
51 | namespace std | |
52 | { | |
53 | // 22.1.1 Class locale | |
3101fa3c JQ |
54 | /** |
55 | * @brief Container class for localization functionality. | |
56 | * | |
57 | * The locale class is first a class wrapper for C library locales. It is | |
58 | * also an extensible container for user-defined localization. A locale is | |
59 | * a collection of facets that implement various localization features such | |
60 | * as money, time, and number printing. | |
61 | * | |
62 | * Constructing C++ locales does not change the C library locale. | |
63 | * | |
64 | * This library supports efficient construction and copying of locales | |
65 | * through a reference counting implementation of the locale class. | |
66 | */ | |
e6686813 BK |
67 | class locale |
68 | { | |
69 | public: | |
70 | // Types: | |
3101fa3c | 71 | /// Definition of locale::category. |
b656faa8 | 72 | typedef int category; |
e6686813 BK |
73 | |
74 | // Forward decls and friends: | |
75 | class facet; | |
76 | class id; | |
77 | class _Impl; | |
78 | ||
79 | friend class facet; | |
80 | friend class _Impl; | |
81 | ||
e6686813 BK |
82 | template<typename _Facet> |
83 | friend bool | |
84 | has_facet(const locale&) throw(); | |
0cd1de6f BK |
85 | |
86 | template<typename _Facet> | |
87 | friend const _Facet& | |
88 | use_facet(const locale&); | |
215f9e28 BK |
89 | |
90 | template<typename _Cache> | |
cde63840 | 91 | friend struct __use_cache; |
215f9e28 | 92 | |
3101fa3c JQ |
93 | //@{ |
94 | /** | |
95 | * @brief Category values. | |
96 | * | |
97 | * The standard category values are none, ctype, numeric, collate, time, | |
98 | * monetary, and messages. They form a bitmask that supports union and | |
99 | * intersection. The category all is the union of these values. | |
100 | * | |
101 | * @if maint | |
102 | * NB: Order must match _S_facet_categories definition in locale.cc | |
103 | * @endif | |
104 | */ | |
e6686813 BK |
105 | static const category none = 0; |
106 | static const category ctype = 1L << 0; | |
107 | static const category numeric = 1L << 1; | |
108 | static const category collate = 1L << 2; | |
109 | static const category time = 1L << 3; | |
110 | static const category monetary = 1L << 4; | |
111 | static const category messages = 1L << 5; | |
112 | static const category all = (ctype | numeric | collate | | |
113 | time | monetary | messages); | |
3101fa3c | 114 | //@} |
e6686813 BK |
115 | |
116 | // Construct/copy/destroy: | |
3101fa3c JQ |
117 | |
118 | /** | |
119 | * @brief Default constructor. | |
120 | * | |
121 | * Constructs a copy of the global locale. If no locale has been | |
122 | * explicitly set, this is the "C" locale. | |
123 | */ | |
e6686813 BK |
124 | locale() throw(); |
125 | ||
3101fa3c JQ |
126 | /** |
127 | * @brief Copy constructor. | |
128 | * | |
129 | * Constructs a copy of @a other. | |
130 | * | |
131 | * @param other The locale to copy. | |
132 | */ | |
e6686813 BK |
133 | locale(const locale& __other) throw(); |
134 | ||
3101fa3c JQ |
135 | /** |
136 | * @brief Named locale constructor. | |
137 | * | |
138 | * Constructs a copy of the named C library locale. | |
139 | * | |
140 | * @param s Name of the locale to construct. | |
141 | * @throw std::runtime_error if s is null or an undefined locale. | |
142 | */ | |
e6686813 BK |
143 | explicit |
144 | locale(const char* __s); | |
145 | ||
3101fa3c JQ |
146 | /** |
147 | * @brief Construct locale with facets from another locale. | |
148 | * | |
149 | * Constructs a copy of the locale @a base. The facets specified by @a | |
150 | * cat are replaced with those from the locale named by @a s. If base is | |
151 | * named, this locale instance will also be named. | |
152 | * | |
153 | * @param base The locale to copy. | |
154 | * @param s Name of the locale to use facets from. | |
155 | * @param cat Set of categories defining the facets to use from s. | |
156 | * @throw std::runtime_error if s is null or an undefined locale. | |
157 | */ | |
e6686813 BK |
158 | locale(const locale& __base, const char* __s, category __cat); |
159 | ||
3101fa3c JQ |
160 | /** |
161 | * @brief Construct locale with facets from another locale. | |
162 | * | |
163 | * Constructs a copy of the locale @a base. The facets specified by @a | |
164 | * cat are replaced with those from the locale @a add. If @a base and @a | |
165 | * add are named, this locale instance will also be named. | |
166 | * | |
167 | * @param base The locale to copy. | |
168 | * @param add The locale to use facets from. | |
169 | * @param cat Set of categories defining the facets to use from add. | |
170 | */ | |
e6686813 BK |
171 | locale(const locale& __base, const locale& __add, category __cat); |
172 | ||
3101fa3c JQ |
173 | /** |
174 | * @brief Construct locale with another facet. | |
175 | * | |
176 | * Constructs a copy of the locale @a other. The facet @f is added to | |
177 | * @other, replacing an existing facet of type Facet if there is one. If | |
178 | * @f is null, this locale is a copy of @a other. | |
179 | * | |
180 | * @param other The locale to copy. | |
181 | * @param f The facet to add in. | |
182 | */ | |
e6686813 BK |
183 | template<typename _Facet> |
184 | locale(const locale& __other, _Facet* __f); | |
185 | ||
3101fa3c | 186 | /// Locale destructor. |
e6686813 BK |
187 | ~locale() throw(); |
188 | ||
3101fa3c JQ |
189 | /** |
190 | * @brief Assignment operator. | |
191 | * | |
192 | * Set this locale to be a copy of @a other. | |
193 | * | |
194 | * @param other The locale to copy. | |
195 | * @return A reference to this locale. | |
196 | */ | |
197 | const locale& | |
e6686813 BK |
198 | operator=(const locale& __other) throw(); |
199 | ||
3101fa3c JQ |
200 | /** |
201 | * @brief Construct locale with another facet. | |
202 | * | |
203 | * Constructs and returns a new copy of this locale. Adds or replaces an | |
204 | * existing facet of type Facet from the locale @a other into the new | |
205 | * locale. | |
206 | * | |
207 | * @param Facet The facet type to copy from other | |
208 | * @param other The locale to copy from. | |
209 | * @return Newly constructed locale. | |
210 | * @throw std::runtime_error if other has no facet of type Facet. | |
211 | */ | |
e6686813 BK |
212 | template<typename _Facet> |
213 | locale | |
214 | combine(const locale& __other) const; | |
215 | ||
216 | // Locale operations: | |
3101fa3c JQ |
217 | /** |
218 | * @brief Return locale name. | |
219 | * @return Locale name or "*" if unnamed. | |
220 | */ | |
e6686813 BK |
221 | string |
222 | name() const; | |
223 | ||
3101fa3c JQ |
224 | /** |
225 | * @brief Locale equality. | |
226 | * | |
227 | * @param other The locale to compare against. | |
228 | * @return True if other and this refer to the same locale instance, are | |
229 | * copies, or have the same name. False otherwise. | |
230 | */ | |
e6686813 BK |
231 | bool |
232 | operator==(const locale& __other) const throw (); | |
233 | ||
3101fa3c JQ |
234 | /** |
235 | * @brief Locale inequality. | |
236 | * | |
237 | * @param other The locale to compare against. | |
238 | * @return ! (*this == other) | |
239 | */ | |
e6686813 BK |
240 | inline bool |
241 | operator!=(const locale& __other) const throw () | |
242 | { return !(this->operator==(__other)); } | |
243 | ||
3101fa3c JQ |
244 | /** |
245 | * @brief Compare two strings according to collate. | |
246 | * | |
247 | * Template operator to compare two strings using the compare function of | |
248 | * the collate facet in this locale. One use is to provide the locale to | |
249 | * the sort function. For example, a vector v of strings could be sorted | |
250 | * according to locale loc by doing: | |
251 | * @code | |
252 | * std::sort(v.begin(), v.end(), loc); | |
253 | * @endcode | |
254 | * | |
255 | * @param s1 First string to compare. | |
256 | * @param s2 Second string to compare. | |
257 | * @return True if collate<Char> facet compares s1 < s2, else false. | |
258 | */ | |
e6686813 BK |
259 | template<typename _Char, typename _Traits, typename _Alloc> |
260 | bool | |
261 | operator()(const basic_string<_Char, _Traits, _Alloc>& __s1, | |
262 | const basic_string<_Char, _Traits, _Alloc>& __s2) const; | |
263 | ||
264 | // Global locale objects: | |
3101fa3c JQ |
265 | /** |
266 | * @brief Set global locale | |
267 | * | |
268 | * This function sets the global locale to the argument and returns a | |
269 | * copy of the previous global locale. If the argument has a name, it | |
270 | * will also call std::setlocale(LC_ALL, loc.name()). | |
271 | * | |
272 | * @param locale The new locale to make global. | |
273 | * @return Copy of the old global locale. | |
274 | */ | |
e6686813 BK |
275 | static locale |
276 | global(const locale&); | |
277 | ||
3101fa3c JQ |
278 | /** |
279 | * @brief Return reference to the "C" locale. | |
280 | */ | |
e6686813 BK |
281 | static const locale& |
282 | classic(); | |
283 | ||
284 | private: | |
285 | // The (shared) implementation | |
286 | _Impl* _M_impl; | |
287 | ||
288 | // The "C" reference locale | |
8ae81136 | 289 | static _Impl* _S_classic; |
e6686813 BK |
290 | |
291 | // Current global locale | |
292 | static _Impl* _S_global; | |
293 | ||
215f9e28 BK |
294 | // Names of underlying locale categories. |
295 | // NB: locale::global() has to know how to modify all the | |
296 | // underlying categories, not just the ones required by the C++ | |
297 | // standard. | |
8ae81136 | 298 | static const char* const* const _S_categories; |
215f9e28 | 299 | |
e6686813 BK |
300 | // Number of standard categories. For C++, these categories are |
301 | // collate, ctype, monetary, numeric, time, and messages. These | |
302 | // directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE, | |
303 | // LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE | |
304 | // 1003.1-2001) specifies LC_MESSAGES. | |
e6686813 BK |
305 | // In addition to the standard categories, the underlying |
306 | // operating system is allowed to define extra LC_* | |
307 | // macros. For GNU systems, the following are also valid: | |
308 | // LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT, | |
309 | // and LC_IDENTIFICATION. | |
3d7c150e | 310 | static const size_t _S_categories_size = 6 + _GLIBCXX_NUM_CATEGORIES; |
e6686813 | 311 | |
8ae81136 BK |
312 | #ifdef __GTHREADS |
313 | static __gthread_once_t _S_once; | |
314 | #endif | |
315 | ||
e6686813 BK |
316 | explicit |
317 | locale(_Impl*) throw(); | |
318 | ||
8ae81136 BK |
319 | static void |
320 | _S_initialize(); | |
321 | ||
322 | static void | |
323 | _S_initialize_once(); | |
e6686813 BK |
324 | |
325 | static category | |
326 | _S_normalize_category(category); | |
327 | ||
328 | void | |
329 | _M_coalesce(const locale& __base, const locale& __add, category __cat); | |
330 | }; | |
331 | ||
332 | ||
215f9e28 | 333 | // 22.1.1.1.2 Class locale::facet |
3101fa3c JQ |
334 | /** |
335 | * @brief Localization functionality base class. | |
336 | * | |
337 | * The facet class is the base class for a localization feature, such as | |
338 | * money, time, and number printing. It provides common support for facets | |
339 | * and reference management. | |
340 | * | |
341 | * Facets may not be copied or assigned. | |
342 | */ | |
215f9e28 BK |
343 | class locale::facet |
344 | { | |
345 | private: | |
346 | friend class locale; | |
347 | friend class locale::_Impl; | |
348 | ||
1313d87f | 349 | mutable _Atomic_word _M_refcount; |
215f9e28 | 350 | |
215f9e28 | 351 | // Contains data from the underlying "C" library for the classic locale. |
8ae81136 | 352 | static __c_locale _S_c_locale; |
215f9e28 BK |
353 | |
354 | // String literal for the name of the classic locale. | |
8ae81136 BK |
355 | static const char _S_c_name[2]; |
356 | ||
357 | #ifdef __GTHREADS | |
358 | static __gthread_once_t _S_once; | |
359 | #endif | |
360 | ||
361 | static void | |
362 | _S_initialize_once(); | |
363 | ||
364 | protected: | |
3101fa3c JQ |
365 | /** |
366 | * @brief Facet constructor. | |
367 | * | |
368 | * This is the constructor provided by the standard. If refs is 0, the | |
369 | * facet is destroyed when the last referencing locale is destroyed. | |
370 | * Otherwise the facet will never be destroyed. | |
371 | * | |
372 | * @param refs The initial value for reference count. | |
373 | */ | |
215f9e28 | 374 | explicit |
1313d87f | 375 | facet(size_t __refs = 0) throw() : _M_refcount(__refs ? 1 : 0) |
215f9e28 BK |
376 | { } |
377 | ||
3101fa3c | 378 | /// Facet destructor. |
215f9e28 BK |
379 | virtual |
380 | ~facet(); | |
381 | ||
382 | static void | |
383 | _S_create_c_locale(__c_locale& __cloc, const char* __s, | |
384 | __c_locale __old = 0); | |
385 | ||
386 | static __c_locale | |
387 | _S_clone_c_locale(__c_locale& __cloc); | |
388 | ||
389 | static void | |
390 | _S_destroy_c_locale(__c_locale& __cloc); | |
391 | ||
bb1b12ec BK |
392 | // Returns data from the underlying "C" library data for the |
393 | // classic locale. | |
8ae81136 BK |
394 | static __c_locale |
395 | _S_get_c_locale(); | |
396 | ||
bb1b12ec BK |
397 | static const char* |
398 | _S_get_c_name(); | |
399 | ||
215f9e28 BK |
400 | private: |
401 | inline void | |
402 | _M_add_reference() const throw() | |
1313d87f | 403 | { __atomic_add(&_M_refcount, 1); } |
215f9e28 BK |
404 | |
405 | inline void | |
406 | _M_remove_reference() const throw() | |
407 | { | |
1313d87f | 408 | if (__exchange_and_add(&_M_refcount, -1) == 1) |
215f9e28 BK |
409 | { |
410 | try | |
411 | { delete this; } | |
412 | catch (...) | |
413 | { } | |
414 | } | |
415 | } | |
416 | ||
417 | facet(const facet&); // Not defined. | |
418 | ||
419 | void | |
420 | operator=(const facet&); // Not defined. | |
421 | }; | |
422 | ||
423 | ||
424 | // 22.1.1.1.3 Class locale::id | |
3101fa3c JQ |
425 | /** |
426 | * @brief Facet ID class. | |
427 | * | |
428 | * The ID class provides facets with an index used to identify them. | |
429 | * Every facet class must define a public static member locale::id, or be | |
430 | * derived from a facet that provides this member, otherwise the facet | |
431 | * cannot be used in a locale. The locale::id ensures that each class | |
432 | * type gets a unique identifier. | |
433 | */ | |
215f9e28 BK |
434 | class locale::id |
435 | { | |
436 | private: | |
437 | friend class locale; | |
438 | friend class locale::_Impl; | |
439 | ||
440 | template<typename _Facet> | |
441 | friend const _Facet& | |
442 | use_facet(const locale&); | |
443 | ||
444 | template<typename _Facet> | |
445 | friend bool | |
446 | has_facet(const locale&) throw (); | |
447 | ||
448 | // NB: There is no accessor for _M_index because it may be used | |
449 | // before the constructor is run; the effect of calling a member | |
450 | // function (even an inline) would be undefined. | |
451 | mutable size_t _M_index; | |
452 | ||
453 | // Last id number assigned. | |
1313d87f | 454 | static _Atomic_word _S_refcount; |
215f9e28 BK |
455 | |
456 | void | |
457 | operator=(const id&); // Not defined. | |
458 | ||
459 | id(const id&); // Not defined. | |
460 | ||
461 | public: | |
462 | // NB: This class is always a static data member, and thus can be | |
463 | // counted on to be zero-initialized. | |
3101fa3c | 464 | /// Constructor. |
215f9e28 BK |
465 | id() { } |
466 | ||
5aaa2108 BK |
467 | size_t |
468 | _M_id() const; | |
215f9e28 BK |
469 | }; |
470 | ||
471 | ||
472 | // Implementation object for locale. | |
e6686813 BK |
473 | class locale::_Impl |
474 | { | |
475 | public: | |
476 | // Friends. | |
477 | friend class locale; | |
478 | friend class locale::facet; | |
479 | ||
215f9e28 BK |
480 | template<typename _Facet> |
481 | friend bool | |
482 | has_facet(const locale&) throw(); | |
483 | ||
e6686813 BK |
484 | template<typename _Facet> |
485 | friend const _Facet& | |
486 | use_facet(const locale&); | |
487 | ||
215f9e28 | 488 | template<typename _Cache> |
cde63840 | 489 | friend struct __use_cache; |
e6686813 BK |
490 | |
491 | private: | |
492 | // Data Members. | |
1313d87f | 493 | _Atomic_word _M_refcount; |
064994a3 | 494 | const facet** _M_facets; |
e6686813 | 495 | size_t _M_facets_size; |
215f9e28 | 496 | const facet** _M_caches; |
73c4dcc6 | 497 | char** _M_names; |
e6686813 BK |
498 | static const locale::id* const _S_id_ctype[]; |
499 | static const locale::id* const _S_id_numeric[]; | |
500 | static const locale::id* const _S_id_collate[]; | |
501 | static const locale::id* const _S_id_time[]; | |
502 | static const locale::id* const _S_id_monetary[]; | |
503 | static const locale::id* const _S_id_messages[]; | |
504 | static const locale::id* const* const _S_facet_categories[]; | |
505 | ||
506 | inline void | |
507 | _M_add_reference() throw() | |
1313d87f | 508 | { __atomic_add(&_M_refcount, 1); } |
e6686813 BK |
509 | |
510 | inline void | |
511 | _M_remove_reference() throw() | |
512 | { | |
1313d87f | 513 | if (__exchange_and_add(&_M_refcount, -1) == 1) |
e6686813 BK |
514 | { |
515 | try | |
516 | { delete this; } | |
517 | catch(...) | |
518 | { } | |
519 | } | |
520 | } | |
521 | ||
522 | _Impl(const _Impl&, size_t); | |
523 | _Impl(const char*, size_t); | |
8ae81136 | 524 | _Impl(size_t) throw(); |
e6686813 BK |
525 | |
526 | ~_Impl() throw(); | |
527 | ||
528 | _Impl(const _Impl&); // Not defined. | |
529 | ||
530 | void | |
531 | operator=(const _Impl&); // Not defined. | |
532 | ||
533 | inline bool | |
534 | _M_check_same_name() | |
535 | { | |
536 | bool __ret = true; | |
89e9920b | 537 | for (size_t __i = 0; __ret && __i < _S_categories_size - 1; ++__i) |
91675f9d | 538 | __ret &= (std::strcmp(_M_names[__i], _M_names[__i + 1]) == 0); |
e6686813 BK |
539 | return __ret; |
540 | } | |
541 | ||
542 | void | |
543 | _M_replace_categories(const _Impl*, category); | |
544 | ||
545 | void | |
546 | _M_replace_category(const _Impl*, const locale::id* const*); | |
547 | ||
548 | void | |
549 | _M_replace_facet(const _Impl*, const locale::id*); | |
550 | ||
551 | void | |
064994a3 | 552 | _M_install_facet(const locale::id*, const facet*); |
e6686813 BK |
553 | |
554 | template<typename _Facet> | |
555 | inline void | |
556 | _M_init_facet(_Facet* __facet) | |
215f9e28 BK |
557 | { _M_install_facet(&_Facet::id, __facet); } |
558 | ||
559 | void | |
cde63840 | 560 | _M_install_cache(const facet* __cache, size_t __index) throw() |
215f9e28 BK |
561 | { |
562 | __cache->_M_add_reference(); | |
563 | _M_caches[__index] = __cache; | |
564 | } | |
e6686813 BK |
565 | }; |
566 | ||
567 | template<typename _Facet> | |
568 | locale::locale(const locale& __other, _Facet* __f) | |
569 | { | |
570 | _M_impl = new _Impl(*__other._M_impl, 1); | |
91675f9d PC |
571 | |
572 | char* _M_tmp_names[_S_categories_size]; | |
573 | size_t __i = 0; | |
574 | try | |
575 | { | |
576 | for (; __i < _S_categories_size; ++__i) | |
577 | { | |
578 | _M_tmp_names[__i] = new char[2]; | |
579 | std::strcpy(_M_tmp_names[__i], "*"); | |
580 | } | |
581 | _M_impl->_M_install_facet(&_Facet::id, __f); | |
582 | } | |
583 | catch(...) | |
584 | { | |
155f6fbb | 585 | _M_impl->_M_remove_reference(); |
91675f9d PC |
586 | for (size_t __j = 0; __j < __i; ++__j) |
587 | delete [] _M_tmp_names[__j]; | |
588 | __throw_exception_again; | |
589 | } | |
590 | ||
591 | for (size_t __k = 0; __k < _S_categories_size; ++__k) | |
e6686813 | 592 | { |
91675f9d PC |
593 | delete [] _M_impl->_M_names[__k]; |
594 | _M_impl->_M_names[__k] = _M_tmp_names[__k]; | |
e6686813 BK |
595 | } |
596 | } | |
e6686813 BK |
597 | } // namespace std |
598 | ||
599 | #endif |