1 // std::moneypunct implementation details, GNU version -*- C++ -*- 2 3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 3, 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 // Under Section 7 of GPL version 3, you are granted additional 18 // permissions described in the GCC Runtime Library Exception, version 19 // 3.1, as published by the Free Software Foundation. 20 21 // You should have received a copy of the GNU General Public License and 22 // a copy of the GCC Runtime Library Exception along with this program; 23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 // <http://www.gnu.org/licenses/>. 25 26 // 27 // ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions 28 // 29 30 // Written by Benjamin Kosnik <bkoz@redhat.com> 31 32 #include <locale> 33 #include <bits/c++locale_internal.h> 34 35 _GLIBCXX_BEGIN_NAMESPACE(std) 36 37 // Construct and return valid pattern consisting of some combination of: 38 // space none symbol sign value 39 money_base::pattern 40 money_base::_S_construct_pattern(char __precedes, char __space, 41 char __posn) throw() 42 { 43 pattern __ret; 44 45 // This insanely complicated routine attempts to construct a valid 46 // pattern for use with monyepunct. A couple of invariants: 47 48 // if (__precedes) symbol -> value 49 // else value -> symbol 50 51 // if (__space) space 52 // else none 53 54 // none == never first 55 // space never first or last 56 57 // Any elegant implementations of this are welcome. 58 switch (__posn) 59 { 60 case 0: 61 case 1: 62 // 1 The sign precedes the value and symbol. 63 __ret.field[0] = sign; 64 if (__space) 65 { 66 // Pattern starts with sign. 67 if (__precedes) 68 { 69 __ret.field[1] = symbol; 70 __ret.field[3] = value; 71 } 72 else 73 { 74 __ret.field[1] = value; 75 __ret.field[3] = symbol; 76 } 77 __ret.field[2] = space; 78 } 79 else 80 { 81 // Pattern starts with sign and ends with none. 82 if (__precedes) 83 { 84 __ret.field[1] = symbol; 85 __ret.field[2] = value; 86 } 87 else 88 { 89 __ret.field[1] = value; 90 __ret.field[2] = symbol; 91 } 92 __ret.field[3] = none; 93 } 94 break; 95 case 2: 96 // 2 The sign follows the value and symbol. 97 if (__space) 98 { 99 // Pattern either ends with sign. 100 if (__precedes) 101 { 102 __ret.field[0] = symbol; 103 __ret.field[2] = value; 104 } 105 else 106 { 107 __ret.field[0] = value; 108 __ret.field[2] = symbol; 109 } 110 __ret.field[1] = space; 111 __ret.field[3] = sign; 112 } 113 else 114 { 115 // Pattern ends with sign then none. 116 if (__precedes) 117 { 118 __ret.field[0] = symbol; 119 __ret.field[1] = value; 120 } 121 else 122 { 123 __ret.field[0] = value; 124 __ret.field[1] = symbol; 125 } 126 __ret.field[2] = sign; 127 __ret.field[3] = none; 128 } 129 break; 130 case 3: 131 // 3 The sign immediately precedes the symbol. 132 if (__precedes) 133 { 134 __ret.field[0] = sign; 135 __ret.field[1] = symbol; 136 if (__space) 137 { 138 __ret.field[2] = space; 139 __ret.field[3] = value; 140 } 141 else 142 { 143 __ret.field[2] = value; 144 __ret.field[3] = none; 145 } 146 } 147 else 148 { 149 __ret.field[0] = value; 150 if (__space) 151 { 152 __ret.field[1] = space; 153 __ret.field[2] = sign; 154 __ret.field[3] = symbol; 155 } 156 else 157 { 158 __ret.field[1] = sign; 159 __ret.field[2] = symbol; 160 __ret.field[3] = none; 161 } 162 } 163 break; 164 case 4: 165 // 4 The sign immediately follows the symbol. 166 if (__precedes) 167 { 168 __ret.field[0] = symbol; 169 __ret.field[1] = sign; 170 if (__space) 171 { 172 __ret.field[2] = space; 173 __ret.field[3] = value; 174 } 175 else 176 { 177 __ret.field[2] = value; 178 __ret.field[3] = none; 179 } 180 } 181 else 182 { 183 __ret.field[0] = value; 184 if (__space) 185 { 186 __ret.field[1] = space; 187 __ret.field[2] = symbol; 188 __ret.field[3] = sign; 189 } 190 else 191 { 192 __ret.field[1] = symbol; 193 __ret.field[2] = sign; 194 __ret.field[3] = none; 195 } 196 } 197 break; 198 default: 199 __ret = pattern(); 200 } 201 return __ret; 202 } 203 204 template<> 205 void 206 moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc, 207 const char*) 208 { 209 if (!_M_data) 210 _M_data = new __moneypunct_cache<char, true>; 211 212 if (!__cloc) 213 { 214 // "C" locale 215 _M_data->_M_decimal_point = '.'; 216 _M_data->_M_thousands_sep = ','; 217 _M_data->_M_grouping = ""; 218 _M_data->_M_grouping_size = 0; 219 _M_data->_M_use_grouping = false; 220 _M_data->_M_curr_symbol = ""; 221 _M_data->_M_curr_symbol_size = 0; 222 _M_data->_M_positive_sign = ""; 223 _M_data->_M_positive_sign_size = 0; 224 _M_data->_M_negative_sign = ""; 225 _M_data->_M_negative_sign_size = 0; 226 _M_data->_M_frac_digits = 0; 227 _M_data->_M_pos_format = money_base::_S_default_pattern; 228 _M_data->_M_neg_format = money_base::_S_default_pattern; 229 230 for (size_t __i = 0; __i < money_base::_S_end; ++__i) 231 _M_data->_M_atoms[__i] = money_base::_S_atoms[__i]; 232 } 233 else 234 { 235 // Named locale. 236 _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, 237 __cloc)); 238 _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, 239 __cloc)); 240 241 // Check for NULL, which implies no fractional digits. 242 if (_M_data->_M_decimal_point == '\0') 243 { 244 // Like in "C" locale. 245 _M_data->_M_frac_digits = 0; 246 _M_data->_M_decimal_point = '.'; 247 } 248 else 249 _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, 250 __cloc)); 251 252 const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); 253 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 254 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 255 // _Intl == true 256 const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 257 258 char* __group = 0; 259 char* __ps = 0; 260 char* __ns = 0; 261 const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 262 __try 263 { 264 size_t __len; 265 266 // Check for NULL, which implies no grouping. 267 if (_M_data->_M_thousands_sep == '\0') 268 { 269 // Like in "C" locale. 270 _M_data->_M_grouping = ""; 271 _M_data->_M_grouping_size = 0; 272 _M_data->_M_use_grouping = false; 273 _M_data->_M_thousands_sep = ','; 274 } 275 else 276 { 277 __len = strlen(__cgroup); 278 if (__len) 279 { 280 __group = new char[__len + 1]; 281 memcpy(__group, __cgroup, __len + 1); 282 _M_data->_M_grouping = __group; 283 } 284 else 285 { 286 _M_data->_M_grouping = ""; 287 _M_data->_M_use_grouping = false; 288 } 289 _M_data->_M_grouping_size = __len; 290 } 291 292 __len = strlen(__cpossign); 293 if (__len) 294 { 295 __ps = new char[__len + 1]; 296 memcpy(__ps, __cpossign, __len + 1); 297 _M_data->_M_positive_sign = __ps; 298 } 299 else 300 _M_data->_M_positive_sign = ""; 301 _M_data->_M_positive_sign_size = __len; 302 303 if (!__nposn) 304 { 305 _M_data->_M_negative_sign = "()"; 306 _M_data->_M_negative_sign_size = 2; 307 } 308 else 309 { 310 __len = strlen(__cnegsign); 311 if (__len) 312 { 313 __ns = new char[__len + 1]; 314 memcpy(__ns, __cnegsign, __len + 1); 315 _M_data->_M_negative_sign = __ns; 316 } 317 else 318 _M_data->_M_negative_sign = ""; 319 _M_data->_M_negative_sign_size = __len; 320 } 321 322 __len = strlen(__ccurr); 323 if (__len) 324 { 325 char* __curr = new char[__len + 1]; 326 memcpy(__curr, __ccurr, __len + 1); 327 _M_data->_M_curr_symbol = __curr; 328 } 329 else 330 _M_data->_M_curr_symbol = ""; 331 _M_data->_M_curr_symbol_size = __len; 332 } 333 __catch(...) 334 { 335 delete _M_data; 336 _M_data = 0; 337 delete [] __group; 338 delete [] __ps; 339 delete [] __ns; 340 } 341 342 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 343 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 344 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 345 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 346 __pposn); 347 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 348 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 349 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 350 __nposn); 351 } 352 } 353 354 template<> 355 void 356 moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc, 357 const char*) 358 { 359 if (!_M_data) 360 _M_data = new __moneypunct_cache<char, false>; 361 362 if (!__cloc) 363 { 364 // "C" locale 365 _M_data->_M_decimal_point = '.'; 366 _M_data->_M_thousands_sep = ','; 367 _M_data->_M_grouping = ""; 368 _M_data->_M_grouping_size = 0; 369 _M_data->_M_use_grouping = false; 370 _M_data->_M_curr_symbol = ""; 371 _M_data->_M_curr_symbol_size = 0; 372 _M_data->_M_positive_sign = ""; 373 _M_data->_M_positive_sign_size = 0; 374 _M_data->_M_negative_sign = ""; 375 _M_data->_M_negative_sign_size = 0; 376 _M_data->_M_frac_digits = 0; 377 _M_data->_M_pos_format = money_base::_S_default_pattern; 378 _M_data->_M_neg_format = money_base::_S_default_pattern; 379 380 for (size_t __i = 0; __i < money_base::_S_end; ++__i) 381 _M_data->_M_atoms[__i] = money_base::_S_atoms[__i]; 382 } 383 else 384 { 385 // Named locale. 386 _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, 387 __cloc)); 388 _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, 389 __cloc)); 390 391 // Check for NULL, which implies no fractional digits. 392 if (_M_data->_M_decimal_point == '\0') 393 { 394 // Like in "C" locale. 395 _M_data->_M_frac_digits = 0; 396 _M_data->_M_decimal_point = '.'; 397 } 398 else 399 _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, 400 __cloc)); 401 402 const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); 403 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 404 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 405 // _Intl == false 406 const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 407 408 char* __group = 0; 409 char* __ps = 0; 410 char* __ns = 0; 411 const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 412 __try 413 { 414 size_t __len; 415 416 // Check for NULL, which implies no grouping. 417 if (_M_data->_M_thousands_sep == '\0') 418 { 419 // Like in "C" locale. 420 _M_data->_M_grouping = ""; 421 _M_data->_M_grouping_size = 0; 422 _M_data->_M_use_grouping = false; 423 _M_data->_M_thousands_sep = ','; 424 } 425 else 426 { 427 __len = strlen(__cgroup); 428 if (__len) 429 { 430 __group = new char[__len + 1]; 431 memcpy(__group, __cgroup, __len + 1); 432 _M_data->_M_grouping = __group; 433 } 434 else 435 { 436 _M_data->_M_grouping = ""; 437 _M_data->_M_use_grouping = false; 438 } 439 _M_data->_M_grouping_size = __len; 440 } 441 442 __len = strlen(__cpossign); 443 if (__len) 444 { 445 __ps = new char[__len + 1]; 446 memcpy(__ps, __cpossign, __len + 1); 447 _M_data->_M_positive_sign = __ps; 448 } 449 else 450 _M_data->_M_positive_sign = ""; 451 _M_data->_M_positive_sign_size = __len; 452 453 if (!__nposn) 454 { 455 _M_data->_M_negative_sign = "()"; 456 _M_data->_M_negative_sign_size = 2; 457 } 458 else 459 { 460 __len = strlen(__cnegsign); 461 if (__len) 462 { 463 __ns = new char[__len + 1]; 464 memcpy(__ns, __cnegsign, __len + 1); 465 _M_data->_M_negative_sign = __ns; 466 } 467 else 468 _M_data->_M_negative_sign = ""; 469 _M_data->_M_negative_sign_size = __len; 470 } 471 472 __len = strlen(__ccurr); 473 if (__len) 474 { 475 char* __curr = new char[__len + 1]; 476 memcpy(__curr, __ccurr, __len + 1); 477 _M_data->_M_curr_symbol = __curr; 478 } 479 else 480 _M_data->_M_curr_symbol = ""; 481 _M_data->_M_curr_symbol_size = __len; 482 } 483 __catch(...) 484 { 485 delete _M_data; 486 _M_data = 0; 487 delete [] __group; 488 delete [] __ps; 489 delete [] __ns; 490 } 491 492 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 493 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 494 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 495 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 496 __pposn); 497 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 498 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 499 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 500 __nposn); 501 } 502 } 503 504 template<> 505 moneypunct<char, true>::~moneypunct() 506 { 507 if (_M_data->_M_grouping_size) 508 delete [] _M_data->_M_grouping; 509 if (_M_data->_M_positive_sign_size) 510 delete [] _M_data->_M_positive_sign; 511 if (_M_data->_M_negative_sign_size 512 && strcmp(_M_data->_M_negative_sign, "()") != 0) 513 delete [] _M_data->_M_negative_sign; 514 if (_M_data->_M_curr_symbol_size) 515 delete [] _M_data->_M_curr_symbol; 516 delete _M_data; 517 } 518 519 template<> 520 moneypunct<char, false>::~moneypunct() 521 { 522 if (_M_data->_M_grouping_size) 523 delete [] _M_data->_M_grouping; 524 if (_M_data->_M_positive_sign_size) 525 delete [] _M_data->_M_positive_sign; 526 if (_M_data->_M_negative_sign_size 527 && strcmp(_M_data->_M_negative_sign, "()") != 0) 528 delete [] _M_data->_M_negative_sign; 529 if (_M_data->_M_curr_symbol_size) 530 delete [] _M_data->_M_curr_symbol; 531 delete _M_data; 532 } 533 534 #ifdef _GLIBCXX_USE_WCHAR_T 535 template<> 536 void 537 moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc, 538 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 539 const char*) 540 #else 541 const char* __name) 542 #endif 543 { 544 if (!_M_data) 545 _M_data = new __moneypunct_cache<wchar_t, true>; 546 547 if (!__cloc) 548 { 549 // "C" locale 550 _M_data->_M_decimal_point = L'.'; 551 _M_data->_M_thousands_sep = L','; 552 _M_data->_M_grouping = ""; 553 _M_data->_M_grouping_size = 0; 554 _M_data->_M_use_grouping = false; 555 _M_data->_M_curr_symbol = L""; 556 _M_data->_M_curr_symbol_size = 0; 557 _M_data->_M_positive_sign = L""; 558 _M_data->_M_positive_sign_size = 0; 559 _M_data->_M_negative_sign = L""; 560 _M_data->_M_negative_sign_size = 0; 561 _M_data->_M_frac_digits = 0; 562 _M_data->_M_pos_format = money_base::_S_default_pattern; 563 _M_data->_M_neg_format = money_base::_S_default_pattern; 564 565 // Use ctype::widen code without the facet... 566 for (size_t __i = 0; __i < money_base::_S_end; ++__i) 567 _M_data->_M_atoms[__i] = 568 static_cast<wchar_t>(money_base::_S_atoms[__i]); 569 } 570 else 571 { 572 // Named locale. 573 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 574 __c_locale __old = __uselocale(__cloc); 575 #else 576 // Switch to named locale so that mbsrtowcs will work. 577 char* __old = setlocale(LC_ALL, NULL); 578 const size_t __llen = strlen(__old) + 1; 579 char* __sav = new char[__llen]; 580 memcpy(__sav, __old, __llen); 581 setlocale(LC_ALL, __name); 582 #endif 583 584 union { char *__s; wchar_t __w; } __u; 585 __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc); 586 _M_data->_M_decimal_point = __u.__w; 587 588 __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc); 589 _M_data->_M_thousands_sep = __u.__w; 590 591 // Check for NULL, which implies no fractional digits. 592 if (_M_data->_M_decimal_point == L'\0') 593 { 594 // Like in "C" locale. 595 _M_data->_M_frac_digits = 0; 596 _M_data->_M_decimal_point = L'.'; 597 } 598 else 599 _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, 600 __cloc)); 601 602 const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); 603 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 604 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 605 const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 606 607 char* __group = 0; 608 wchar_t* __wcs_ps = 0; 609 wchar_t* __wcs_ns = 0; 610 const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 611 __try 612 { 613 size_t __len; 614 615 // Check for NULL, which implies no grouping. 616 if (_M_data->_M_thousands_sep == L'\0') 617 { 618 // Like in "C" locale. 619 _M_data->_M_grouping = ""; 620 _M_data->_M_grouping_size = 0; 621 _M_data->_M_use_grouping = false; 622 _M_data->_M_thousands_sep = L','; 623 } 624 else 625 { 626 __len = strlen(__cgroup); 627 if (__len) 628 { 629 __group = new char[__len + 1]; 630 memcpy(__group, __cgroup, __len + 1); 631 _M_data->_M_grouping = __group; 632 } 633 else 634 { 635 _M_data->_M_grouping = ""; 636 _M_data->_M_use_grouping = false; 637 } 638 _M_data->_M_grouping_size = __len; 639 } 640 641 mbstate_t __state; 642 __len = strlen(__cpossign); 643 if (__len) 644 { 645 memset(&__state, 0, sizeof(mbstate_t)); 646 __wcs_ps = new wchar_t[__len + 1]; 647 mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); 648 _M_data->_M_positive_sign = __wcs_ps; 649 } 650 else 651 _M_data->_M_positive_sign = L""; 652 _M_data->_M_positive_sign_size = 653 wcslen(_M_data->_M_positive_sign); 654 655 __len = strlen(__cnegsign); 656 if (!__nposn) 657 _M_data->_M_negative_sign = L"()"; 658 else if (__len) 659 { 660 memset(&__state, 0, sizeof(mbstate_t)); 661 __wcs_ns = new wchar_t[__len + 1]; 662 mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); 663 _M_data->_M_negative_sign = __wcs_ns; 664 } 665 else 666 _M_data->_M_negative_sign = L""; 667 _M_data->_M_negative_sign_size = 668 wcslen(_M_data->_M_negative_sign); 669 670 // _Intl == true. 671 __len = strlen(__ccurr); 672 if (__len) 673 { 674 memset(&__state, 0, sizeof(mbstate_t)); 675 wchar_t* __wcs = new wchar_t[__len + 1]; 676 mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); 677 _M_data->_M_curr_symbol = __wcs; 678 } 679 else 680 _M_data->_M_curr_symbol = L""; 681 _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol); 682 } 683 __catch(...) 684 { 685 delete _M_data; 686 _M_data = 0; 687 delete [] __group; 688 delete [] __wcs_ps; 689 delete [] __wcs_ns; 690 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 691 __uselocale(__old); 692 #else 693 setlocale(LC_ALL, __sav); 694 delete [] __sav; 695 #endif 696 __throw_exception_again; 697 } 698 699 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 700 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 701 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 702 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 703 __pposn); 704 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 705 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 706 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 707 __nposn); 708 709 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 710 __uselocale(__old); 711 #else 712 setlocale(LC_ALL, __sav); 713 delete [] __sav; 714 #endif 715 } 716 } 717 718 template<> 719 void 720 moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc, 721 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 722 const char*) 723 #else 724 const char* __name) 725 #endif 726 { 727 if (!_M_data) 728 _M_data = new __moneypunct_cache<wchar_t, false>; 729 730 if (!__cloc) 731 { 732 // "C" locale 733 _M_data->_M_decimal_point = L'.'; 734 _M_data->_M_thousands_sep = L','; 735 _M_data->_M_grouping = ""; 736 _M_data->_M_grouping_size = 0; 737 _M_data->_M_use_grouping = false; 738 _M_data->_M_curr_symbol = L""; 739 _M_data->_M_curr_symbol_size = 0; 740 _M_data->_M_positive_sign = L""; 741 _M_data->_M_positive_sign_size = 0; 742 _M_data->_M_negative_sign = L""; 743 _M_data->_M_negative_sign_size = 0; 744 _M_data->_M_frac_digits = 0; 745 _M_data->_M_pos_format = money_base::_S_default_pattern; 746 _M_data->_M_neg_format = money_base::_S_default_pattern; 747 748 // Use ctype::widen code without the facet... 749 for (size_t __i = 0; __i < money_base::_S_end; ++__i) 750 _M_data->_M_atoms[__i] = 751 static_cast<wchar_t>(money_base::_S_atoms[__i]); 752 } 753 else 754 { 755 // Named locale. 756 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 757 __c_locale __old = __uselocale(__cloc); 758 #else 759 // Switch to named locale so that mbsrtowcs will work. 760 char* __old = setlocale(LC_ALL, NULL); 761 const size_t __llen = strlen(__old) + 1; 762 char* __sav = new char[__llen]; 763 memcpy(__sav, __old, __llen); 764 setlocale(LC_ALL, __name); 765 #endif 766 767 union { char *__s; wchar_t __w; } __u; 768 __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc); 769 _M_data->_M_decimal_point = __u.__w; 770 771 __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc); 772 _M_data->_M_thousands_sep = __u.__w; 773 774 // Check for NULL, which implies no fractional digits. 775 if (_M_data->_M_decimal_point == L'\0') 776 { 777 // Like in "C" locale. 778 _M_data->_M_frac_digits = 0; 779 _M_data->_M_decimal_point = L'.'; 780 } 781 else 782 _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, 783 __cloc)); 784 785 const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); 786 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 787 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 788 const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 789 790 char* __group = 0; 791 wchar_t* __wcs_ps = 0; 792 wchar_t* __wcs_ns = 0; 793 const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 794 __try 795 { 796 size_t __len; 797 798 // Check for NULL, which implies no grouping. 799 if (_M_data->_M_thousands_sep == L'\0') 800 { 801 // Like in "C" locale. 802 _M_data->_M_grouping = ""; 803 _M_data->_M_grouping_size = 0; 804 _M_data->_M_use_grouping = false; 805 _M_data->_M_thousands_sep = L','; 806 } 807 else 808 { 809 __len = strlen(__cgroup); 810 if (__len) 811 { 812 __group = new char[__len + 1]; 813 memcpy(__group, __cgroup, __len + 1); 814 _M_data->_M_grouping = __group; 815 } 816 else 817 { 818 _M_data->_M_grouping = ""; 819 _M_data->_M_use_grouping = false; 820 } 821 _M_data->_M_grouping_size = __len; 822 } 823 824 mbstate_t __state; 825 __len = strlen(__cpossign); 826 if (__len) 827 { 828 memset(&__state, 0, sizeof(mbstate_t)); 829 __wcs_ps = new wchar_t[__len + 1]; 830 mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); 831 _M_data->_M_positive_sign = __wcs_ps; 832 } 833 else 834 _M_data->_M_positive_sign = L""; 835 _M_data->_M_positive_sign_size = 836 wcslen(_M_data->_M_positive_sign); 837 838 __len = strlen(__cnegsign); 839 if (!__nposn) 840 _M_data->_M_negative_sign = L"()"; 841 else if (__len) 842 { 843 memset(&__state, 0, sizeof(mbstate_t)); 844 __wcs_ns = new wchar_t[__len + 1]; 845 mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); 846 _M_data->_M_negative_sign = __wcs_ns; 847 } 848 else 849 _M_data->_M_negative_sign = L""; 850 _M_data->_M_negative_sign_size = 851 wcslen(_M_data->_M_negative_sign); 852 853 // _Intl == true. 854 __len = strlen(__ccurr); 855 if (__len) 856 { 857 memset(&__state, 0, sizeof(mbstate_t)); 858 wchar_t* __wcs = new wchar_t[__len + 1]; 859 mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); 860 _M_data->_M_curr_symbol = __wcs; 861 } 862 else 863 _M_data->_M_curr_symbol = L""; 864 _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol); 865 } 866 __catch(...) 867 { 868 delete _M_data; 869 _M_data = 0; 870 delete [] __group; 871 delete [] __wcs_ps; 872 delete [] __wcs_ns; 873 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 874 __uselocale(__old); 875 #else 876 setlocale(LC_ALL, __sav); 877 delete [] __sav; 878 #endif 879 __throw_exception_again; 880 } 881 882 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 883 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 884 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 885 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 886 __pposn); 887 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 888 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 889 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 890 __nposn); 891 892 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 893 __uselocale(__old); 894 #else 895 setlocale(LC_ALL, __sav); 896 delete [] __sav; 897 #endif 898 } 899 } 900 901 template<> 902 moneypunct<wchar_t, true>::~moneypunct() 903 { 904 if (_M_data->_M_grouping_size) 905 delete [] _M_data->_M_grouping; 906 if (_M_data->_M_positive_sign_size) 907 delete [] _M_data->_M_positive_sign; 908 if (_M_data->_M_negative_sign_size 909 && wcscmp(_M_data->_M_negative_sign, L"()") != 0) 910 delete [] _M_data->_M_negative_sign; 911 if (_M_data->_M_curr_symbol_size) 912 delete [] _M_data->_M_curr_symbol; 913 delete _M_data; 914 } 915 916 template<> 917 moneypunct<wchar_t, false>::~moneypunct() 918 { 919 if (_M_data->_M_grouping_size) 920 delete [] _M_data->_M_grouping; 921 if (_M_data->_M_positive_sign_size) 922 delete [] _M_data->_M_positive_sign; 923 if (_M_data->_M_negative_sign_size 924 && wcscmp(_M_data->_M_negative_sign, L"()") != 0) 925 delete [] _M_data->_M_negative_sign; 926 if (_M_data->_M_curr_symbol_size) 927 delete [] _M_data->_M_curr_symbol; 928 delete _M_data; 929 } 930 #endif 931 932 _GLIBCXX_END_NAMESPACE 933