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