1 // std::moneypunct implementation details, GNU version -*- C++ -*- 2 3 // Copyright (C) 2001-2020 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 _S_construct_pattern(char __precedes,char __space,char __posn)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 extern char __narrow_multibyte_chars(const char* s, __locale_t cloc); 211 212 template<> 213 void _M_initialize_moneypunct(__c_locale __cloc,const char *)214 moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc, 215 const char*) 216 { 217 if (!_M_data) 218 _M_data = new __moneypunct_cache<char, true>; 219 220 if (!__cloc) 221 { 222 // "C" locale 223 _M_data->_M_decimal_point = '.'; 224 _M_data->_M_thousands_sep = ','; 225 _M_data->_M_grouping = ""; 226 _M_data->_M_grouping_size = 0; 227 _M_data->_M_use_grouping = false; 228 _M_data->_M_curr_symbol = ""; 229 _M_data->_M_curr_symbol_size = 0; 230 _M_data->_M_positive_sign = ""; 231 _M_data->_M_positive_sign_size = 0; 232 _M_data->_M_negative_sign = ""; 233 _M_data->_M_negative_sign_size = 0; 234 _M_data->_M_frac_digits = 0; 235 _M_data->_M_pos_format = money_base::_S_default_pattern; 236 _M_data->_M_neg_format = money_base::_S_default_pattern; 237 238 for (size_t __i = 0; __i < money_base::_S_end; ++__i) 239 _M_data->_M_atoms[__i] = money_base::_S_atoms[__i]; 240 } 241 else 242 { 243 // Named locale. 244 _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, 245 __cloc)); 246 const char* thousands_sep = __nl_langinfo_l(__MON_THOUSANDS_SEP, 247 __cloc); 248 if (thousands_sep[0] != '\0' && thousands_sep[1] != '\0') 249 _M_data->_M_thousands_sep = __narrow_multibyte_chars(thousands_sep, 250 __cloc); 251 else 252 _M_data->_M_thousands_sep = *thousands_sep; 253 254 // Check for NULL, which implies no fractional digits. 255 if (_M_data->_M_decimal_point == '\0') 256 { 257 // Like in "C" locale. 258 _M_data->_M_frac_digits = 0; 259 _M_data->_M_decimal_point = '.'; 260 } 261 else 262 _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, 263 __cloc)); 264 265 const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); 266 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 267 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 268 // _Intl == true 269 const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 270 271 char* __group = 0; 272 char* __ps = 0; 273 char* __ns = 0; 274 const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 275 __try 276 { 277 size_t __len; 278 279 // Check for NULL, which implies no grouping. 280 if (_M_data->_M_thousands_sep == '\0') 281 { 282 // Like in "C" locale. 283 _M_data->_M_grouping = ""; 284 _M_data->_M_grouping_size = 0; 285 _M_data->_M_use_grouping = false; 286 _M_data->_M_thousands_sep = ','; 287 } 288 else 289 { 290 __len = strlen(__cgroup); 291 if (__len) 292 { 293 __group = new char[__len + 1]; 294 memcpy(__group, __cgroup, __len + 1); 295 _M_data->_M_grouping = __group; 296 } 297 else 298 { 299 _M_data->_M_grouping = ""; 300 _M_data->_M_use_grouping = false; 301 } 302 _M_data->_M_grouping_size = __len; 303 } 304 305 __len = strlen(__cpossign); 306 if (__len) 307 { 308 __ps = new char[__len + 1]; 309 memcpy(__ps, __cpossign, __len + 1); 310 _M_data->_M_positive_sign = __ps; 311 } 312 else 313 _M_data->_M_positive_sign = ""; 314 _M_data->_M_positive_sign_size = __len; 315 316 if (!__nposn) 317 { 318 _M_data->_M_negative_sign = "()"; 319 _M_data->_M_negative_sign_size = 2; 320 } 321 else 322 { 323 __len = strlen(__cnegsign); 324 if (__len) 325 { 326 __ns = new char[__len + 1]; 327 memcpy(__ns, __cnegsign, __len + 1); 328 _M_data->_M_negative_sign = __ns; 329 } 330 else 331 _M_data->_M_negative_sign = ""; 332 _M_data->_M_negative_sign_size = __len; 333 } 334 335 __len = strlen(__ccurr); 336 if (__len) 337 { 338 char* __curr = new char[__len + 1]; 339 memcpy(__curr, __ccurr, __len + 1); 340 _M_data->_M_curr_symbol = __curr; 341 } 342 else 343 _M_data->_M_curr_symbol = ""; 344 _M_data->_M_curr_symbol_size = __len; 345 } 346 __catch(...) 347 { 348 delete _M_data; 349 _M_data = 0; 350 delete [] __group; 351 delete [] __ps; 352 delete [] __ns; 353 __throw_exception_again; 354 } 355 356 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 357 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 358 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 359 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 360 __pposn); 361 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 362 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 363 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 364 __nposn); 365 } 366 } 367 368 template<> 369 void _M_initialize_moneypunct(__c_locale __cloc,const char *)370 moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc, 371 const char*) 372 { 373 if (!_M_data) 374 _M_data = new __moneypunct_cache<char, false>; 375 376 if (!__cloc) 377 { 378 // "C" locale 379 _M_data->_M_decimal_point = '.'; 380 _M_data->_M_thousands_sep = ','; 381 _M_data->_M_grouping = ""; 382 _M_data->_M_grouping_size = 0; 383 _M_data->_M_use_grouping = false; 384 _M_data->_M_curr_symbol = ""; 385 _M_data->_M_curr_symbol_size = 0; 386 _M_data->_M_positive_sign = ""; 387 _M_data->_M_positive_sign_size = 0; 388 _M_data->_M_negative_sign = ""; 389 _M_data->_M_negative_sign_size = 0; 390 _M_data->_M_frac_digits = 0; 391 _M_data->_M_pos_format = money_base::_S_default_pattern; 392 _M_data->_M_neg_format = money_base::_S_default_pattern; 393 394 for (size_t __i = 0; __i < money_base::_S_end; ++__i) 395 _M_data->_M_atoms[__i] = money_base::_S_atoms[__i]; 396 } 397 else 398 { 399 // Named locale. 400 _M_data->_M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, 401 __cloc)); 402 _M_data->_M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, 403 __cloc)); 404 405 // Check for NULL, which implies no fractional digits. 406 if (_M_data->_M_decimal_point == '\0') 407 { 408 // Like in "C" locale. 409 _M_data->_M_frac_digits = 0; 410 _M_data->_M_decimal_point = '.'; 411 } 412 else 413 _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, 414 __cloc)); 415 416 const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); 417 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 418 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 419 // _Intl == false 420 const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 421 422 char* __group = 0; 423 char* __ps = 0; 424 char* __ns = 0; 425 const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 426 __try 427 { 428 size_t __len; 429 430 // Check for NULL, which implies no grouping. 431 if (_M_data->_M_thousands_sep == '\0') 432 { 433 // Like in "C" locale. 434 _M_data->_M_grouping = ""; 435 _M_data->_M_grouping_size = 0; 436 _M_data->_M_use_grouping = false; 437 _M_data->_M_thousands_sep = ','; 438 } 439 else 440 { 441 __len = strlen(__cgroup); 442 if (__len) 443 { 444 __group = new char[__len + 1]; 445 memcpy(__group, __cgroup, __len + 1); 446 _M_data->_M_grouping = __group; 447 } 448 else 449 { 450 _M_data->_M_grouping = ""; 451 _M_data->_M_use_grouping = false; 452 } 453 _M_data->_M_grouping_size = __len; 454 } 455 456 __len = strlen(__cpossign); 457 if (__len) 458 { 459 __ps = new char[__len + 1]; 460 memcpy(__ps, __cpossign, __len + 1); 461 _M_data->_M_positive_sign = __ps; 462 } 463 else 464 _M_data->_M_positive_sign = ""; 465 _M_data->_M_positive_sign_size = __len; 466 467 if (!__nposn) 468 { 469 _M_data->_M_negative_sign = "()"; 470 _M_data->_M_negative_sign_size = 2; 471 } 472 else 473 { 474 __len = strlen(__cnegsign); 475 if (__len) 476 { 477 __ns = new char[__len + 1]; 478 memcpy(__ns, __cnegsign, __len + 1); 479 _M_data->_M_negative_sign = __ns; 480 } 481 else 482 _M_data->_M_negative_sign = ""; 483 _M_data->_M_negative_sign_size = __len; 484 } 485 486 __len = strlen(__ccurr); 487 if (__len) 488 { 489 char* __curr = new char[__len + 1]; 490 memcpy(__curr, __ccurr, __len + 1); 491 _M_data->_M_curr_symbol = __curr; 492 } 493 else 494 _M_data->_M_curr_symbol = ""; 495 _M_data->_M_curr_symbol_size = __len; 496 } 497 __catch(...) 498 { 499 delete _M_data; 500 _M_data = 0; 501 delete [] __group; 502 delete [] __ps; 503 delete [] __ns; 504 __throw_exception_again; 505 } 506 507 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 508 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 509 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 510 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 511 __pposn); 512 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 513 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 514 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 515 __nposn); 516 } 517 } 518 519 template<> ~moneypunct()520 moneypunct<char, true>::~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 template<> ~moneypunct()535 moneypunct<char, false>::~moneypunct() 536 { 537 if (_M_data->_M_grouping_size) 538 delete [] _M_data->_M_grouping; 539 if (_M_data->_M_positive_sign_size) 540 delete [] _M_data->_M_positive_sign; 541 if (_M_data->_M_negative_sign_size 542 && strcmp(_M_data->_M_negative_sign, "()") != 0) 543 delete [] _M_data->_M_negative_sign; 544 if (_M_data->_M_curr_symbol_size) 545 delete [] _M_data->_M_curr_symbol; 546 delete _M_data; 547 } 548 549 #ifdef _GLIBCXX_USE_WCHAR_T 550 template<> 551 void _M_initialize_moneypunct(__c_locale __cloc,const char *)552 moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc, 553 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 554 const char*) 555 #else 556 const char* __name) 557 #endif 558 { 559 if (!_M_data) 560 _M_data = new __moneypunct_cache<wchar_t, true>; 561 562 if (!__cloc) 563 { 564 // "C" locale 565 _M_data->_M_decimal_point = L'.'; 566 _M_data->_M_thousands_sep = L','; 567 _M_data->_M_grouping = ""; 568 _M_data->_M_grouping_size = 0; 569 _M_data->_M_use_grouping = false; 570 _M_data->_M_curr_symbol = L""; 571 _M_data->_M_curr_symbol_size = 0; 572 _M_data->_M_positive_sign = L""; 573 _M_data->_M_positive_sign_size = 0; 574 _M_data->_M_negative_sign = L""; 575 _M_data->_M_negative_sign_size = 0; 576 _M_data->_M_frac_digits = 0; 577 _M_data->_M_pos_format = money_base::_S_default_pattern; 578 _M_data->_M_neg_format = money_base::_S_default_pattern; 579 580 // Use ctype::widen code without the facet... 581 for (size_t __i = 0; __i < money_base::_S_end; ++__i) 582 _M_data->_M_atoms[__i] = 583 static_cast<wchar_t>(money_base::_S_atoms[__i]); 584 } 585 else 586 { 587 // Named locale. 588 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 589 __c_locale __old = __uselocale(__cloc); 590 #else 591 // Switch to named locale so that mbsrtowcs will work. 592 char* __old = setlocale(LC_ALL, 0); 593 const size_t __llen = strlen(__old) + 1; 594 char* __sav = new char[__llen]; 595 memcpy(__sav, __old, __llen); 596 setlocale(LC_ALL, __name); 597 #endif 598 599 union { char *__s; wchar_t __w; } __u; 600 __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc); 601 _M_data->_M_decimal_point = __u.__w; 602 603 __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc); 604 _M_data->_M_thousands_sep = __u.__w; 605 606 // Check for NULL, which implies no fractional digits. 607 if (_M_data->_M_decimal_point == L'\0') 608 { 609 // Like in "C" locale. 610 _M_data->_M_frac_digits = 0; 611 _M_data->_M_decimal_point = L'.'; 612 } 613 else 614 _M_data->_M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, 615 __cloc)); 616 617 const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); 618 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 619 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 620 const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 621 622 char* __group = 0; 623 wchar_t* __wcs_ps = 0; 624 wchar_t* __wcs_ns = 0; 625 const char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 626 __try 627 { 628 size_t __len; 629 630 // Check for NULL, which implies no grouping. 631 if (_M_data->_M_thousands_sep == L'\0') 632 { 633 // Like in "C" locale. 634 _M_data->_M_grouping = ""; 635 _M_data->_M_grouping_size = 0; 636 _M_data->_M_use_grouping = false; 637 _M_data->_M_thousands_sep = L','; 638 } 639 else 640 { 641 __len = strlen(__cgroup); 642 if (__len) 643 { 644 __group = new char[__len + 1]; 645 memcpy(__group, __cgroup, __len + 1); 646 _M_data->_M_grouping = __group; 647 } 648 else 649 { 650 _M_data->_M_grouping = ""; 651 _M_data->_M_use_grouping = false; 652 } 653 _M_data->_M_grouping_size = __len; 654 } 655 656 mbstate_t __state; 657 __len = strlen(__cpossign); 658 if (__len) 659 { 660 memset(&__state, 0, sizeof(mbstate_t)); 661 __wcs_ps = new wchar_t[__len + 1]; 662 mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); 663 _M_data->_M_positive_sign = __wcs_ps; 664 } 665 else 666 _M_data->_M_positive_sign = L""; 667 _M_data->_M_positive_sign_size = 668 wcslen(_M_data->_M_positive_sign); 669 670 __len = strlen(__cnegsign); 671 if (!__nposn) 672 _M_data->_M_negative_sign = L"()"; 673 else if (__len) 674 { 675 memset(&__state, 0, sizeof(mbstate_t)); 676 __wcs_ns = new wchar_t[__len + 1]; 677 mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); 678 _M_data->_M_negative_sign = __wcs_ns; 679 } 680 else 681 _M_data->_M_negative_sign = L""; 682 _M_data->_M_negative_sign_size = 683 wcslen(_M_data->_M_negative_sign); 684 685 // _Intl == true. 686 __len = strlen(__ccurr); 687 if (__len) 688 { 689 memset(&__state, 0, sizeof(mbstate_t)); 690 wchar_t* __wcs = new wchar_t[__len + 1]; 691 mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); 692 _M_data->_M_curr_symbol = __wcs; 693 } 694 else 695 _M_data->_M_curr_symbol = L""; 696 _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol); 697 } 698 __catch(...) 699 { 700 delete _M_data; 701 _M_data = 0; 702 delete [] __group; 703 delete [] __wcs_ps; 704 delete [] __wcs_ns; 705 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 706 __uselocale(__old); 707 #else 708 setlocale(LC_ALL, __sav); 709 delete [] __sav; 710 #endif 711 __throw_exception_again; 712 } 713 714 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 715 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 716 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 717 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 718 __pposn); 719 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 720 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 721 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 722 __nposn); 723 724 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 725 __uselocale(__old); 726 #else 727 setlocale(LC_ALL, __sav); 728 delete [] __sav; 729 #endif 730 } 731 } 732 733 template<> 734 void _M_initialize_moneypunct(__c_locale __cloc,const char *)735 moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc, 736 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 737 const char*) 738 #else 739 const char* __name) 740 #endif 741 { 742 if (!_M_data) 743 _M_data = new __moneypunct_cache<wchar_t, false>; 744 745 if (!__cloc) 746 { 747 // "C" locale 748 _M_data->_M_decimal_point = L'.'; 749 _M_data->_M_thousands_sep = L','; 750 _M_data->_M_grouping = ""; 751 _M_data->_M_grouping_size = 0; 752 _M_data->_M_use_grouping = false; 753 _M_data->_M_curr_symbol = L""; 754 _M_data->_M_curr_symbol_size = 0; 755 _M_data->_M_positive_sign = L""; 756 _M_data->_M_positive_sign_size = 0; 757 _M_data->_M_negative_sign = L""; 758 _M_data->_M_negative_sign_size = 0; 759 _M_data->_M_frac_digits = 0; 760 _M_data->_M_pos_format = money_base::_S_default_pattern; 761 _M_data->_M_neg_format = money_base::_S_default_pattern; 762 763 // Use ctype::widen code without the facet... 764 for (size_t __i = 0; __i < money_base::_S_end; ++__i) 765 _M_data->_M_atoms[__i] = 766 static_cast<wchar_t>(money_base::_S_atoms[__i]); 767 } 768 else 769 { 770 // Named locale. 771 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 772 __c_locale __old = __uselocale(__cloc); 773 #else 774 // Switch to named locale so that mbsrtowcs will work. 775 char* __old = setlocale(LC_ALL, 0); 776 const size_t __llen = strlen(__old) + 1; 777 char* __sav = new char[__llen]; 778 memcpy(__sav, __old, __llen); 779 setlocale(LC_ALL, __name); 780 #endif 781 782 union { char *__s; wchar_t __w; } __u; 783 __u.__s = __nl_langinfo_l(_NL_MONETARY_DECIMAL_POINT_WC, __cloc); 784 _M_data->_M_decimal_point = __u.__w; 785 786 __u.__s = __nl_langinfo_l(_NL_MONETARY_THOUSANDS_SEP_WC, __cloc); 787 _M_data->_M_thousands_sep = __u.__w; 788 789 // Check for NULL, which implies no fractional digits. 790 if (_M_data->_M_decimal_point == L'\0') 791 { 792 // Like in "C" locale. 793 _M_data->_M_frac_digits = 0; 794 _M_data->_M_decimal_point = L'.'; 795 } 796 else 797 _M_data->_M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, 798 __cloc)); 799 800 const char* __cgroup = __nl_langinfo_l(__MON_GROUPING, __cloc); 801 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 802 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 803 const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 804 805 char* __group = 0; 806 wchar_t* __wcs_ps = 0; 807 wchar_t* __wcs_ns = 0; 808 const char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 809 __try 810 { 811 size_t __len; 812 813 // Check for NULL, which implies no grouping. 814 if (_M_data->_M_thousands_sep == L'\0') 815 { 816 // Like in "C" locale. 817 _M_data->_M_grouping = ""; 818 _M_data->_M_grouping_size = 0; 819 _M_data->_M_use_grouping = false; 820 _M_data->_M_thousands_sep = L','; 821 } 822 else 823 { 824 __len = strlen(__cgroup); 825 if (__len) 826 { 827 __group = new char[__len + 1]; 828 memcpy(__group, __cgroup, __len + 1); 829 _M_data->_M_grouping = __group; 830 } 831 else 832 { 833 _M_data->_M_grouping = ""; 834 _M_data->_M_use_grouping = false; 835 } 836 _M_data->_M_grouping_size = __len; 837 } 838 839 mbstate_t __state; 840 __len = strlen(__cpossign); 841 if (__len) 842 { 843 memset(&__state, 0, sizeof(mbstate_t)); 844 __wcs_ps = new wchar_t[__len + 1]; 845 mbsrtowcs(__wcs_ps, &__cpossign, __len + 1, &__state); 846 _M_data->_M_positive_sign = __wcs_ps; 847 } 848 else 849 _M_data->_M_positive_sign = L""; 850 _M_data->_M_positive_sign_size = 851 wcslen(_M_data->_M_positive_sign); 852 853 __len = strlen(__cnegsign); 854 if (!__nposn) 855 _M_data->_M_negative_sign = L"()"; 856 else if (__len) 857 { 858 memset(&__state, 0, sizeof(mbstate_t)); 859 __wcs_ns = new wchar_t[__len + 1]; 860 mbsrtowcs(__wcs_ns, &__cnegsign, __len + 1, &__state); 861 _M_data->_M_negative_sign = __wcs_ns; 862 } 863 else 864 _M_data->_M_negative_sign = L""; 865 _M_data->_M_negative_sign_size = 866 wcslen(_M_data->_M_negative_sign); 867 868 // _Intl == true. 869 __len = strlen(__ccurr); 870 if (__len) 871 { 872 memset(&__state, 0, sizeof(mbstate_t)); 873 wchar_t* __wcs = new wchar_t[__len + 1]; 874 mbsrtowcs(__wcs, &__ccurr, __len + 1, &__state); 875 _M_data->_M_curr_symbol = __wcs; 876 } 877 else 878 _M_data->_M_curr_symbol = L""; 879 _M_data->_M_curr_symbol_size = wcslen(_M_data->_M_curr_symbol); 880 } 881 __catch(...) 882 { 883 delete _M_data; 884 _M_data = 0; 885 delete [] __group; 886 delete [] __wcs_ps; 887 delete [] __wcs_ns; 888 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 889 __uselocale(__old); 890 #else 891 setlocale(LC_ALL, __sav); 892 delete [] __sav; 893 #endif 894 __throw_exception_again; 895 } 896 897 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 898 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 899 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 900 _M_data->_M_pos_format = _S_construct_pattern(__pprecedes, __pspace, 901 __pposn); 902 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 903 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 904 _M_data->_M_neg_format = _S_construct_pattern(__nprecedes, __nspace, 905 __nposn); 906 907 #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 908 __uselocale(__old); 909 #else 910 setlocale(LC_ALL, __sav); 911 delete [] __sav; 912 #endif 913 } 914 } 915 916 template<> ~moneypunct()917 moneypunct<wchar_t, true>::~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 931 template<> ~moneypunct()932 moneypunct<wchar_t, false>::~moneypunct() 933 { 934 if (_M_data->_M_grouping_size) 935 delete [] _M_data->_M_grouping; 936 if (_M_data->_M_positive_sign_size) 937 delete [] _M_data->_M_positive_sign; 938 if (_M_data->_M_negative_sign_size 939 && wcscmp(_M_data->_M_negative_sign, L"()") != 0) 940 delete [] _M_data->_M_negative_sign; 941 if (_M_data->_M_curr_symbol_size) 942 delete [] _M_data->_M_curr_symbol; 943 delete _M_data; 944 } 945 #endif 946 947 _GLIBCXX_END_NAMESPACE_VERSION 948 } // namespace 949