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 40 #ifndef _CPP_BITS_LOCALE_CLASSES_H 41 #define _CPP_BITS_LOCALE_CLASSES_H 1 42 43 #pragma GCC system_header 44 45 #include <bits/localefwd.h> 46 #include <cstring> // For strcmp. 47 #include <string> 48 #include <bits/atomicity.h> 49 50 namespace std 51 { 52 class __locale_cache_base; 53 template<typename _Facet> class __locale_cache; 54 55 // 22.1.1 Class locale 56 class locale 57 { 58 public: 59 // Types: 60 typedef unsigned int category; 61 62 // Forward decls and friends: 63 class facet; 64 class id; 65 class _Impl; 66 67 friend class facet; 68 friend class _Impl; 69 70 template<typename _Facet> 71 friend const _Facet& 72 use_facet(const locale&); 73 74 template<typename _Facet> 75 friend bool 76 has_facet(const locale&) throw(); 77 78 template<typename _Facet> 79 friend const __locale_cache<_Facet>& 80 __use_cache(const locale&); 81 82 // Category values: 83 // NB: Order must match _S_facet_categories definition in locale.cc 84 static const category none = 0; 85 static const category ctype = 1L << 0; 86 static const category numeric = 1L << 1; 87 static const category collate = 1L << 2; 88 static const category time = 1L << 3; 89 static const category monetary = 1L << 4; 90 static const category messages = 1L << 5; 91 static const category all = (ctype | numeric | collate | 92 time | monetary | messages); 93 94 // Construct/copy/destroy: 95 locale() throw(); 96 97 locale(const locale& __other) throw(); 98 99 explicit 100 locale(const char* __s); 101 102 locale(const locale& __base, const char* __s, category __cat); 103 104 locale(const locale& __base, const locale& __add, category __cat); 105 106 template<typename _Facet> 107 locale(const locale& __other, _Facet* __f); 108 109 ~locale() throw(); 110 111 const locale& 112 operator=(const locale& __other) throw(); 113 114 template<typename _Facet> 115 locale 116 combine(const locale& __other) const; 117 118 // Locale operations: 119 string 120 name() const; 121 122 bool 123 operator==(const locale& __other) const throw (); 124 125 inline bool 126 operator!=(const locale& __other) const throw () 127 { return !(this->operator==(__other)); } 128 129 template<typename _Char, typename _Traits, typename _Alloc> 130 bool 131 operator()(const basic_string<_Char, _Traits, _Alloc>& __s1, 132 const basic_string<_Char, _Traits, _Alloc>& __s2) const; 133 134 // Global locale objects: 135 static locale 136 global(const locale&); 137 138 static const locale& 139 classic(); 140 141 private: 142 // The (shared) implementation 143 _Impl* _M_impl; 144 145 // The "C" reference locale 146 static _Impl* _S_classic; 147 148 // Current global locale 149 static _Impl* _S_global; 150 151 // Number of standard categories. For C++, these categories are 152 // collate, ctype, monetary, numeric, time, and messages. These 153 // directly correspond to ISO C99 macros LC_COLLATE, LC_CTYPE, 154 // LC_MONETARY, LC_NUMERIC, and LC_TIME. In addition, POSIX (IEEE 155 // 1003.1-2001) specifies LC_MESSAGES. 156 static const size_t _S_categories_size = 6; 157 158 // In addition to the standard categories, the underlying 159 // operating system is allowed to define extra LC_* 160 // macros. For GNU systems, the following are also valid: 161 // LC_PAPER, LC_NAME, LC_ADDRESS, LC_TELEPHONE, LC_MEASUREMENT, 162 // and LC_IDENTIFICATION. 163 static const size_t _S_extra_categories_size = _GLIBCPP_NUM_CATEGORIES; 164 165 // Names of underlying locale categories. 166 // NB: locale::global() has to know how to modify all the 167 // underlying categories, not just the ones required by the C++ 168 // standard. 169 static const char* _S_categories[_S_categories_size 170 + _S_extra_categories_size]; 171 172 explicit 173 locale(_Impl*) throw(); 174 175 static inline void _S_initialize()176 _S_initialize() 177 { 178 if (!_S_classic) 179 classic(); 180 } 181 182 static category 183 _S_normalize_category(category); 184 185 void 186 _M_coalesce(const locale& __base, const locale& __add, category __cat); 187 }; 188 189 190 // Implementation object for locale 191 class locale::_Impl 192 { 193 public: 194 // Friends. 195 friend class locale; 196 friend class locale::facet; 197 198 template<typename _Facet> 199 friend const _Facet& 200 use_facet(const locale&); 201 202 template<typename _Facet> 203 friend bool 204 has_facet(const locale&) throw(); 205 206 template<typename _Facet> 207 friend const __locale_cache<_Facet>& 208 __use_cache(const locale&); 209 210 private: 211 // Data Members. 212 _Atomic_word _M_references; 213 facet** _M_facets; 214 size_t _M_facets_size; 215 216 char* _M_names[_S_categories_size 217 + _S_extra_categories_size]; 218 static const locale::id* const _S_id_ctype[]; 219 static const locale::id* const _S_id_numeric[]; 220 static const locale::id* const _S_id_collate[]; 221 static const locale::id* const _S_id_time[]; 222 static const locale::id* const _S_id_monetary[]; 223 static const locale::id* const _S_id_messages[]; 224 static const locale::id* const* const _S_facet_categories[]; 225 226 inline void _M_add_reference()227 _M_add_reference() throw() 228 { __atomic_add(&_M_references, 1); } 229 230 inline void _M_remove_reference()231 _M_remove_reference() throw() 232 { 233 if (__exchange_and_add(&_M_references, -1) == 1) 234 { 235 try 236 { delete this; } 237 catch(...) 238 { } 239 } 240 } 241 242 _Impl(const _Impl&, size_t); 243 _Impl(const char*, size_t); 244 _Impl(facet**, size_t, bool); 245 246 ~_Impl() throw(); 247 248 _Impl(const _Impl&); // Not defined. 249 250 void 251 operator=(const _Impl&); // Not defined. 252 253 inline bool _M_check_same_name()254 _M_check_same_name() 255 { 256 bool __ret = true; 257 for (size_t __i = 0; 258 __ret && __i < _S_categories_size + _S_extra_categories_size - 1; 259 ++__i) 260 __ret &= (strcmp(_M_names[__i], _M_names[__i + 1]) == 0); 261 return __ret; 262 } 263 264 void 265 _M_replace_categories(const _Impl*, category); 266 267 void 268 _M_replace_category(const _Impl*, const locale::id* const*); 269 270 void 271 _M_replace_facet(const _Impl*, const locale::id*); 272 273 void 274 _M_install_facet(const locale::id*, facet*); 275 276 template<typename _Facet> 277 inline void _M_init_facet(_Facet * __facet)278 _M_init_facet(_Facet* __facet) 279 { _M_install_facet(&_Facet::id, __facet); } 280 281 // Retrieve the cache at __index. 0 is returned if the cache is 282 // missing. Cache is actually located at __index + 283 // _M_facets_size. __index must be < _M_facets_size. 284 inline __locale_cache_base* _M_get_cache(size_t __index)285 _M_get_cache(size_t __index) 286 { 287 return (__locale_cache_base*)_M_facets[__index + _M_facets_size]; 288 } 289 290 // Save the supplied cache at __id. Assumes _M_get_cache has been 291 // called. 292 void _M_install_cache(__locale_cache_base * __cache,int __id)293 _M_install_cache(__locale_cache_base* __cache, int __id) 294 { 295 _M_facets[__id + _M_facets_size] = 296 reinterpret_cast<locale::facet*>(__cache); 297 } 298 299 }; 300 301 template<typename _Facet> locale(const locale & __other,_Facet * __f)302 locale::locale(const locale& __other, _Facet* __f) 303 { 304 _M_impl = new _Impl(*__other._M_impl, 1); 305 306 char* _M_tmp_names[_S_categories_size + _S_extra_categories_size]; 307 size_t __i = 0; 308 try 309 { 310 for (; __i < _S_categories_size 311 + _S_extra_categories_size; ++__i) 312 { 313 _M_tmp_names[__i] = new char[2]; 314 strlcpy(_M_tmp_names[__i], "*", 2); 315 } 316 _M_impl->_M_install_facet(&_Facet::id, __f); 317 } 318 catch(...) 319 { 320 _M_impl->_M_remove_reference(); 321 for (size_t __j = 0; __j < __i; ++__j) 322 delete [] _M_tmp_names[__j]; 323 __throw_exception_again; 324 } 325 326 for (size_t __k = 0; __k < _S_categories_size 327 + _S_extra_categories_size; ++__k) 328 { 329 delete [] _M_impl->_M_names[__k]; 330 _M_impl->_M_names[__k] = _M_tmp_names[__k]; 331 } 332 } 333 334 335 // 22.1.1.1.2 Class locale::facet 336 class locale::facet 337 { 338 private: 339 friend class locale; 340 friend class locale::_Impl; 341 342 _Atomic_word _M_references; 343 344 protected: 345 // Contains data from the underlying "C" library for the classic locale. 346 static __c_locale _S_c_locale; 347 348 // String literal for the name of the classic locale. 349 static char _S_c_name[2]; 350 351 explicit 352 facet(size_t __refs = 0) throw(); 353 354 virtual 355 ~facet(); 356 357 static void 358 _S_create_c_locale(__c_locale& __cloc, const char* __s, 359 __c_locale __old = 0); 360 361 static __c_locale 362 _S_clone_c_locale(__c_locale& __cloc); 363 364 static void 365 _S_destroy_c_locale(__c_locale& __cloc); 366 367 private: 368 void 369 _M_add_reference() throw(); 370 371 void 372 _M_remove_reference() throw(); 373 374 facet(const facet&); // Not defined. 375 376 void 377 operator=(const facet&); // Not defined. 378 }; 379 380 381 // 22.1.1.1.3 Class locale::id 382 class locale::id 383 { 384 private: 385 friend class locale; 386 friend class locale::_Impl; 387 template<typename _Facet> 388 friend const _Facet& 389 use_facet(const locale&); 390 template<typename _Facet> 391 friend bool 392 has_facet(const locale&) throw (); 393 394 // NB: There is no accessor for _M_index because it may be used 395 // before the constructor is run; the effect of calling a member 396 // function (even an inline) would be undefined. 397 mutable size_t _M_index; 398 399 // Last id number assigned. 400 static _Atomic_word _S_highwater; 401 402 void 403 operator=(const id&); // Not defined. 404 405 id(const id&); // Not defined. 406 407 public: 408 // NB: This class is always a static data member, and thus can be 409 // counted on to be zero-initialized. 410 id(); 411 412 inline size_t _M_id()413 _M_id() const 414 { 415 if (!_M_index) 416 _M_index = 1 + __exchange_and_add(&_S_highwater, 1); 417 return _M_index - 1; 418 } 419 }; 420 } // namespace std 421 422 #endif 423