locale_classes.h revision 117397
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 50namespace 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 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 227 _M_add_reference() throw() 228 { __atomic_add(&_M_references, 1); } 229 230 inline void 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 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 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* 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 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> 302 locale::locale(const locale& __other, _Facet* __f) 303 { 304 _M_impl = new _Impl(*__other._M_impl, 1); 305 _M_impl->_M_install_facet(&_Facet::id, __f); 306 for (size_t __i = 0; 307 __i < _S_categories_size + _S_extra_categories_size; ++__i) 308 { 309 delete [] _M_impl->_M_names[__i]; 310 char* __new = new char[2]; 311 strcpy(__new, "*"); 312 _M_impl->_M_names[__i] = __new; 313 } 314 } 315 316 317 // 22.1.1.1.2 Class locale::facet 318 class locale::facet 319 { 320 private: 321 friend class locale; 322 friend class locale::_Impl; 323 324 _Atomic_word _M_references; 325 326 protected: 327 // Contains data from the underlying "C" library for the classic locale. 328 static __c_locale _S_c_locale; 329 330 // String literal for the name of the classic locale. 331 static char _S_c_name[2]; 332 333 explicit 334 facet(size_t __refs = 0) throw(); 335 336 virtual 337 ~facet(); 338 339 static void 340 _S_create_c_locale(__c_locale& __cloc, const char* __s, 341 __c_locale __old = 0); 342 343 static __c_locale 344 _S_clone_c_locale(__c_locale& __cloc); 345 346 static void 347 _S_destroy_c_locale(__c_locale& __cloc); 348 349 private: 350 void 351 _M_add_reference() throw(); 352 353 void 354 _M_remove_reference() throw(); 355 356 facet(const facet&); // Not defined. 357 358 void 359 operator=(const facet&); // Not defined. 360 }; 361 362 363 // 22.1.1.1.3 Class locale::id 364 class locale::id 365 { 366 private: 367 friend class locale; 368 friend class locale::_Impl; 369 template<typename _Facet> 370 friend const _Facet& 371 use_facet(const locale&); 372 template<typename _Facet> 373 friend bool 374 has_facet(const locale&) throw (); 375 376 // NB: There is no accessor for _M_index because it may be used 377 // before the constructor is run; the effect of calling a member 378 // function (even an inline) would be undefined. 379 mutable size_t _M_index; 380 381 // Last id number assigned. 382 static _Atomic_word _S_highwater; 383 384 void 385 operator=(const id&); // Not defined. 386 387 id(const id&); // Not defined. 388 389 public: 390 // NB: This class is always a static data member, and thus can be 391 // counted on to be zero-initialized. 392 id(); 393 394 inline size_t 395 _M_id() const 396 { 397 if (!_M_index) 398 _M_index = 1 + __exchange_and_add(&_S_highwater, 1); 399 return _M_index - 1; 400 } 401 }; 402} // namespace std 403 404#endif 405