locale.cc revision 102782
1// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 2// Free Software Foundation, Inc. 3// 4// This file is part of the GNU ISO C++ Library. This library is free 5// software; you can redistribute it and/or modify it under the 6// terms of the GNU General Public License as published by the 7// Free Software Foundation; either version 2, or (at your option) 8// any later version. 9 10// This library is distributed in the hope that it will be useful, 11// but WITHOUT ANY WARRANTY; without even the implied warranty of 12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13// GNU General Public License for more details. 14 15// You should have received a copy of the GNU General Public License along 16// with this library; see the file COPYING. If not, write to the Free 17// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 18// USA. 19 20// As a special exception, you may use this file as part of a free software 21// library without restriction. Specifically, if other files instantiate 22// templates or use macros or inline functions from this file, or you compile 23// this file and link it with other files to produce an executable, this 24// file does not by itself cause the resulting executable to be covered by 25// the GNU General Public License. This exception does not however 26// invalidate any other reasons why the executable file might be covered by 27// the GNU General Public License. 28 29#include <clocale> 30#include <cstring> 31#include <cassert> 32#include <cctype> 33#include <cwctype> // For towupper, etc. 34#include <limits> 35#include <exception> 36#include <locale> 37#include <istream> 38#include <ostream> 39#include <bits/atomicity.h> 40 41namespace std 42{ 43 // Defined in globals.cc. 44 extern locale c_locale; 45 extern locale::_Impl c_locale_impl; 46 extern locale::facet** facet_vec; 47 48 // Definitions for static const data members of locale. 49 const locale::category locale::none; 50 const locale::category locale::ctype; 51 const locale::category locale::numeric; 52 const locale::category locale::collate; 53 const locale::category locale::time; 54 const locale::category locale::monetary; 55 const locale::category locale::messages; 56 const locale::category locale::all; 57 58 locale::_Impl* locale::_S_classic; 59 locale::_Impl* locale::_S_global; 60 const size_t locale::_S_num_categories; 61 62 // Definitions for locale::id of standard facets that are specialized. 63 locale::id ctype<char>::id; 64 locale::id codecvt<char, char, mbstate_t>::id; 65 66#ifdef _GLIBCPP_USE_WCHAR_T 67 locale::id ctype<wchar_t>::id; 68 locale::id codecvt<wchar_t, char, mbstate_t>::id; 69#endif 70 71 // Definitions for static const data members of locale::id 72 _Atomic_word locale::id::_S_highwater; // init'd to 0 by linker 73 74 // Definitions for static const data members of locale::_Impl 75 const locale::id* const 76 locale::_Impl::_S_id_ctype[] = 77 { 78 &std::ctype<char>::id, 79 &codecvt<char, char, mbstate_t>::id, 80#ifdef _GLIBCPP_USE_WCHAR_T 81 &std::ctype<wchar_t>::id, 82 &codecvt<wchar_t, char, mbstate_t>::id, 83#endif 84 0 85 }; 86 87 const locale::id* const 88 locale::_Impl::_S_id_numeric[] = 89 { 90 &num_get<char>::id, 91 &num_put<char>::id, 92 &numpunct<char>::id, 93#ifdef _GLIBCPP_USE_WCHAR_T 94 &num_get<wchar_t>::id, 95 &num_put<wchar_t>::id, 96 &numpunct<wchar_t>::id, 97#endif 98 0 99 }; 100 101 const locale::id* const 102 locale::_Impl::_S_id_collate[] = 103 { 104 &std::collate<char>::id, 105#ifdef _GLIBCPP_USE_WCHAR_T 106 &std::collate<wchar_t>::id, 107#endif 108 0 109 }; 110 111 const locale::id* const 112 locale::_Impl::_S_id_time[] = 113 { 114 &__timepunct<char>::id, 115 &time_get<char>::id, 116 &time_put<char>::id, 117#ifdef _GLIBCPP_USE_WCHAR_T 118 &__timepunct<wchar_t>::id, 119 &time_get<wchar_t>::id, 120 &time_put<wchar_t>::id, 121#endif 122 0 123 }; 124 125 const locale::id* const 126 locale::_Impl::_S_id_monetary[] = 127 { 128 &money_get<char>::id, 129 &money_put<char>::id, 130 &moneypunct<char, false>::id, 131 &moneypunct<char, true >::id, 132#ifdef _GLIBCPP_USE_WCHAR_T 133 &money_get<wchar_t>::id, 134 &money_put<wchar_t>::id, 135 &moneypunct<wchar_t, false>::id, 136 &moneypunct<wchar_t, true >::id, 137#endif 138 0 139 }; 140 141 const locale::id* const 142 locale::_Impl::_S_id_messages[] = 143 { 144 &std::messages<char>::id, 145#ifdef _GLIBCPP_USE_WCHAR_T 146 &std::messages<wchar_t>::id, 147#endif 148 0 149 }; 150 151 const locale::id* const* const 152 locale::_Impl::_S_facet_categories[] = 153 { 154 // Order must match the decl order in class locale. 155 locale::_Impl::_S_id_ctype, 156 locale::_Impl::_S_id_numeric, 157 locale::_Impl::_S_id_collate, 158 locale::_Impl::_S_id_monetary, 159 locale::_Impl::_S_id_time, 160 locale::_Impl::_S_id_messages, 161 0 162 }; 163 164 locale::~locale() throw() 165 { _M_impl->_M_remove_reference(); } 166 167 void 168 locale::_M_coalesce(const locale& __base, const locale& __add, 169 category __cat) 170 { 171 __cat = _S_normalize_category(__cat); 172 _M_impl = new _Impl(*__base._M_impl, 1); 173 174 try 175 { _M_impl->_M_replace_categories(__add._M_impl, __cat); } 176 catch (...) 177 { 178 _M_impl->_M_remove_reference(); 179 __throw_exception_again; 180 } 181 } 182 183 locale::locale() throw() 184 { 185 _S_initialize(); 186 (_M_impl = _S_global)->_M_add_reference(); 187 } 188 189 locale::locale(const locale& __other) throw() 190 { (_M_impl = __other._M_impl)->_M_add_reference(); } 191 192 // This is used to initialize global and classic locales, and 193 // assumes that the _Impl objects are constructed correctly. 194 locale::locale(_Impl* __ip) throw() : _M_impl(__ip) 195 { } 196 197 locale::locale(const char* __s) 198 { 199 if (__s) 200 { 201 _S_initialize(); 202 if (strcmp(__s, "C") == 0 || strcmp(__s, "POSIX") == 0) 203 (_M_impl = _S_classic)->_M_add_reference(); 204 else if (strcmp(__s, "") == 0) 205 _M_impl = new _Impl(setlocale(LC_ALL, NULL), 1); 206 else 207 _M_impl = new _Impl(__s, 1); 208 } 209 else 210 __throw_runtime_error("attempt to create locale from NULL name"); 211 } 212 213 locale::locale(const locale& __base, const char* __s, category __cat) 214 { 215 // NB: There are complicated, yet more efficient ways to do 216 // this. Building up locales on a per-category way is tedious, so 217 // let's do it this way until people complain. 218 locale __add(__s); 219 _M_coalesce(__base, __add, __cat); 220 } 221 222 locale::locale(const locale& __base, const locale& __add, category __cat) 223 { _M_coalesce(__base, __add, __cat); } 224 225 bool 226 locale::operator==(const locale& __rhs) const throw() 227 { 228 string __name = this->name(); 229 return (_M_impl == __rhs._M_impl 230 || (__name != "*" && __name == __rhs.name())); 231 } 232 233 const locale& 234 locale::operator=(const locale& __other) throw() 235 { 236 __other._M_impl->_M_add_reference(); 237 _M_impl->_M_remove_reference(); 238 _M_impl = __other._M_impl; 239 return *this; 240 } 241 242 locale 243 locale::global(const locale& __other) 244 { 245 // XXX MT 246 _S_initialize(); 247 _Impl* __old = _S_global; 248 __other._M_impl->_M_add_reference(); 249 _S_global = __other._M_impl; 250 if (_S_global->_M_check_same_name() 251 && (strcmp(_S_global->_M_names[0], "*") != 0)) 252 setlocale(LC_ALL, __other.name().c_str()); 253 254 // Reference count sanity check: one reference removed for the 255 // subsition of __other locale, one added by return-by-value. Net 256 // difference: zero. When the returned locale object's destrutor 257 // is called, then the reference count is decremented and possibly 258 // destroyed. 259 return locale(__old); 260 } 261 262 string 263 locale::name() const 264 { 265 // Need some kind of separator character. This one was pretty much 266 // arbitrarily chosen as to not conflict with glibc locales: the 267 // exact formatting is not set in stone. 268 const char __separator = '|'; 269 270 string __ret; 271 if (_M_impl->_M_check_same_name()) 272 __ret = _M_impl->_M_names[0]; 273 else 274 { 275 for (size_t i = 0; i < _S_num_categories; ++i) 276 { 277 __ret += __separator; 278 __ret += _M_impl->_M_names[i]; 279 } 280 } 281 return __ret; 282 } 283 284 const locale& 285 locale::classic() 286 { 287 static _STL_mutex_lock __lock __STL_MUTEX_INITIALIZER; 288 _STL_auto_lock __auto(__lock); 289 290 if (!_S_classic) 291 { 292 try 293 { 294 // 26 Standard facets, 2 references. 295 // One reference for _M_classic, one for _M_global 296 facet** f = new(&facet_vec) facet*[_GLIBCPP_NUM_FACETS]; 297 for (size_t __i = 0; __i < _GLIBCPP_NUM_FACETS; ++__i) 298 f[__i] = 0; 299 300 _S_classic = new (&c_locale_impl) _Impl(f, 2, true); 301 _S_global = _S_classic; 302 new (&c_locale) locale(_S_classic); 303 } 304 catch(...) 305 { 306 // Just call destructor, so that locale_impl_c's memory is 307 // not deallocated via a call to delete. 308 if (_S_classic) 309 _S_classic->~_Impl(); 310 _S_classic = _S_global = 0; 311 __throw_exception_again; 312 } 313 } 314 return c_locale; 315 } 316 317 locale::category 318 locale::_S_normalize_category(category __cat) 319 { 320 int __ret = 0; 321 if (__cat == none || (__cat & all) && !(__cat & ~all)) 322 __ret = __cat; 323 else 324 { 325 // NB: May be a C-style "LC_ALL" category; convert. 326 switch (__cat) 327 { 328 case LC_COLLATE: 329 __ret = collate; 330 break; 331 case LC_CTYPE: 332 __ret = ctype; 333 break; 334 case LC_MONETARY: 335 __ret = monetary; 336 break; 337 case LC_NUMERIC: 338 __ret = numeric; 339 break; 340 case LC_TIME: 341 __ret = time; 342 break; 343#ifdef _GLIBCPP_HAVE_LC_MESSAGES 344 case LC_MESSAGES: 345 __ret = messages; 346 break; 347#endif 348 case LC_ALL: 349 __ret = all; 350 break; 351 default: 352 __throw_runtime_error("bad locale category"); 353 } 354 } 355 return __ret; 356 } 357 358 __c_locale 359 locale::facet::_S_c_locale; 360 361 locale::facet:: 362 ~facet() { } 363 364 locale::facet:: 365 facet(size_t __refs) throw() : _M_references(__refs) 366 { 367 if (!_S_c_locale) 368 _S_create_c_locale(_S_c_locale, "C"); 369 } 370 371 void 372 locale::facet:: 373 _M_add_reference() throw() 374 { __atomic_add(&_M_references, 1); } 375 376 void 377 locale::facet:: 378 _M_remove_reference() throw() 379 { 380 if (__exchange_and_add(&_M_references, -1) == 0) 381 { 382 try 383 { delete this; } 384 catch (...) 385 { } 386 } 387 } 388 389 locale::id::id() 390 { } 391 392 // Definitions for static const data members of ctype_base. 393 const ctype_base::mask ctype_base::space; 394 const ctype_base::mask ctype_base::print; 395 const ctype_base::mask ctype_base::cntrl; 396 const ctype_base::mask ctype_base::upper; 397 const ctype_base::mask ctype_base::lower; 398 const ctype_base::mask ctype_base::alpha; 399 const ctype_base::mask ctype_base::digit; 400 const ctype_base::mask ctype_base::punct; 401 const ctype_base::mask ctype_base::xdigit; 402 const ctype_base::mask ctype_base::alnum; 403 const ctype_base::mask ctype_base::graph; 404 405 // Platform-specific initialization code for ctype tables. 406 #include <bits/ctype_noninline.h> 407 408 const size_t ctype<char>::table_size; 409 410 ctype<char>::~ctype() 411 { 412 if (_M_c_locale_ctype != _S_c_locale) 413 _S_destroy_c_locale(_M_c_locale_ctype); 414 if (_M_del) 415 delete[] this->table(); 416 } 417 418 // These are dummy placeholders as these virtual functions are never called. 419 bool 420 ctype<char>::do_is(mask, char_type) const 421 { return false; } 422 423 const char* 424 ctype<char>::do_is(const char_type* __c, const char_type*, mask*) const 425 { return __c; } 426 427 const char* 428 ctype<char>::do_scan_is(mask, const char_type* __c, const char_type*) const 429 { return __c; } 430 431 const char* 432 ctype<char>::do_scan_not(mask, const char_type* __c, const char_type*) const 433 { return __c; } 434 435 char 436 ctype<char>::do_widen(char __c) const 437 { return __c; } 438 439 const char* 440 ctype<char>::do_widen(const char* __lo, const char* __hi, char* __dest) const 441 { 442 memcpy(__dest, __lo, __hi - __lo); 443 return __hi; 444 } 445 446 char 447 ctype<char>::do_narrow(char __c, char /*__dfault*/) const 448 { return __c; } 449 450 const char* 451 ctype<char>::do_narrow(const char* __lo, const char* __hi, 452 char /*__dfault*/, char* __dest) const 453 { 454 memcpy(__dest, __lo, __hi - __lo); 455 return __hi; 456 } 457 458#ifdef _GLIBCPP_USE_WCHAR_T 459 ctype<wchar_t>::ctype(size_t __refs) 460 : __ctype_abstract_base<wchar_t>(__refs) 461 { _M_c_locale_ctype = _S_c_locale; } 462 463 ctype<wchar_t>::ctype(__c_locale __cloc, size_t __refs) 464 : __ctype_abstract_base<wchar_t>(__refs) 465 { _M_c_locale_ctype = _S_clone_c_locale(__cloc); } 466 467 ctype<wchar_t>::~ctype() 468 { 469 if (_M_c_locale_ctype != _S_c_locale) 470 _S_destroy_c_locale(_M_c_locale_ctype); 471 } 472 473 template<> 474 ctype_byname<wchar_t>::ctype_byname(const char* __s, size_t __refs) 475 : ctype<wchar_t>(__refs) 476 { 477 if (_M_c_locale_ctype != _S_c_locale) 478 _S_destroy_c_locale(_M_c_locale_ctype); 479 _S_create_c_locale(_M_c_locale_ctype, __s); 480 } 481#endif 482 483 // Definitions for static const data members of time_base 484 template<> 485 const char* 486 __timepunct<char>::_S_timezones[14] = 487 { 488 "GMT", "HST", "AKST", "PST", "MST", "CST", "EST", "AST", "NST", "CET", 489 "IST", "EET", "CST", "JST" 490 }; 491 492#ifdef _GLIBCPP_USE_WCHAR_T 493 template<> 494 const wchar_t* 495 __timepunct<wchar_t>::_S_timezones[14] = 496 { 497 L"GMT", L"HST", L"AKST", L"PST", L"MST", L"CST", L"EST", L"AST", 498 L"NST", L"CET", L"IST", L"EET", L"CST", L"JST" 499 }; 500#endif 501 502 // Definitions for static const data members of money_base 503 const money_base::pattern 504 money_base::_S_default_pattern = { {symbol, sign, none, value} }; 505 506 template<> 507 const ctype<char>& 508 use_facet<ctype<char> >(const locale& __loc) 509 { 510 size_t __i = ctype<char>::id._M_id(); 511 const locale::_Impl* __tmp = __loc._M_impl; 512 return static_cast<const ctype<char>&>(*(__tmp->_M_facets[__i])); 513 } 514 515#ifdef _GLIBCPP_USE_WCHAR_T 516 template<> 517 const ctype<wchar_t>& 518 use_facet<ctype<wchar_t> >(const locale& __loc) 519 { 520 size_t __i = ctype<wchar_t>::id._M_id(); 521 const locale::_Impl* __tmp = __loc._M_impl; 522 return static_cast<const ctype<wchar_t>&>(*(__tmp->_M_facets[__i])); 523 } 524#endif 525 526 const char __num_base::_S_atoms[] = "0123456789eEabcdfABCDF"; 527 528 bool 529 __num_base::_S_format_float(const ios_base& __io, char* __fptr, char __mod, 530 streamsize __prec) 531 { 532 bool __incl_prec = false; 533 ios_base::fmtflags __flags = __io.flags(); 534 *__fptr++ = '%'; 535 // [22.2.2.2.2] Table 60 536 if (__flags & ios_base::showpos) 537 *__fptr++ = '+'; 538 if (__flags & ios_base::showpoint) 539 *__fptr++ = '#'; 540 // As per [22.2.2.2.2.11] 541 if (__flags & ios_base::fixed || __prec > 0) 542 { 543 *__fptr++ = '.'; 544 *__fptr++ = '*'; 545 __incl_prec = true; 546 } 547 if (__mod) 548 *__fptr++ = __mod; 549 ios_base::fmtflags __fltfield = __flags & ios_base::floatfield; 550 // [22.2.2.2.2] Table 58 551 if (__fltfield == ios_base::fixed) 552 *__fptr++ = 'f'; 553 else if (__fltfield == ios_base::scientific) 554 *__fptr++ = (__flags & ios_base::uppercase) ? 'E' : 'e'; 555 else 556 *__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g'; 557 *__fptr = '\0'; 558 return __incl_prec; 559 } 560 561 void 562 __num_base::_S_format_int(const ios_base& __io, char* __fptr, char __mod, 563 char __modl) 564 { 565 ios_base::fmtflags __flags = __io.flags(); 566 *__fptr++ = '%'; 567 // [22.2.2.2.2] Table 60 568 if (__flags & ios_base::showpos) 569 *__fptr++ = '+'; 570 if (__flags & ios_base::showbase) 571 *__fptr++ = '#'; 572 *__fptr++ = 'l'; 573 574 // For long long types. 575 if (__modl) 576 *__fptr++ = __modl; 577 578 ios_base::fmtflags __bsefield = __flags & ios_base::basefield; 579 if (__bsefield == ios_base::hex) 580 *__fptr++ = (__flags & ios_base::uppercase) ? 'X' : 'x'; 581 else if (__bsefield == ios_base::oct) 582 *__fptr++ = 'o'; 583 else 584 *__fptr++ = __mod; 585 *__fptr = '\0'; 586 } 587} // namespace std 588 589