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