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