monetary_members.cc revision 117397
1// std::moneypunct implementation details, GNU version -*- C++ -*- 2 3// Copyright (C) 2001, 2002 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 2, 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// You should have received a copy of the GNU General Public License along 17// with this library; see the file COPYING. If not, write to the Free 18// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19// USA. 20 21// As a special exception, you may use this file as part of a free software 22// library without restriction. Specifically, if other files instantiate 23// templates or use macros or inline functions from this file, or you compile 24// this file and link it with other files to produce an executable, this 25// file does not by itself cause the resulting executable to be covered by 26// the GNU General Public License. This exception does not however 27// invalidate any other reasons why the executable file might be covered by 28// the GNU General Public License. 29 30// 31// ISO C++ 14882: 22.2.6.3.2 moneypunct virtual functions 32// 33 34// Written by Benjamin Kosnik <bkoz@redhat.com> 35 36#include <locale> 37#include <bits/c++locale_internal.h> 38 39namespace std 40{ 41 // Construct and return valid pattern consisting of some combination of: 42 // space none symbol sign value 43 money_base::pattern 44 money_base::_S_construct_pattern(char __precedes, char __space, char __posn) 45 { 46 pattern __ret; 47 48 // This insanely complicated routine attempts to construct a valid 49 // pattern for use with monyepunct. A couple of invariants: 50 51 // if (__precedes) symbol -> value 52 // else value -> symbol 53 54 // if (__space) space 55 // else none 56 57 // none == never first 58 // space never first or last 59 60 // Any elegant implementations of this are welcome. 61 switch (__posn) 62 { 63 case 0: 64 case 1: 65 // 1 The sign precedes the value and symbol. 66 if (__space) 67 { 68 // Pattern starts with sign. 69 if (__precedes) 70 { 71 __ret.field[1] = symbol; 72 __ret.field[2] = space; 73 __ret.field[3] = value; 74 } 75 else 76 { 77 __ret.field[1] = value; 78 __ret.field[2] = space; 79 __ret.field[3] = symbol; 80 } 81 __ret.field[0] = sign; 82 } 83 else 84 { 85 // Pattern starts with sign and ends with none. 86 if (__precedes) 87 { 88 __ret.field[1] = symbol; 89 __ret.field[2] = value; 90 } 91 else 92 { 93 __ret.field[1] = value; 94 __ret.field[2] = symbol; 95 } 96 __ret.field[0] = sign; 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[1] = space; 109 __ret.field[2] = value; 110 } 111 else 112 { 113 __ret.field[0] = value; 114 __ret.field[1] = space; 115 __ret.field[2] = symbol; 116 } 117 __ret.field[3] = sign; 118 } 119 else 120 { 121 // Pattern ends with sign then none. 122 if (__precedes) 123 { 124 __ret.field[0] = symbol; 125 __ret.field[1] = value; 126 } 127 else 128 { 129 __ret.field[0] = value; 130 __ret.field[1] = symbol; 131 } 132 __ret.field[2] = sign; 133 __ret.field[3] = none; 134 } 135 break; 136 case 3: 137 // 3 The sign immediately precedes the symbol. 138 if (__space) 139 { 140 // Have space. 141 if (__precedes) 142 { 143 __ret.field[0] = sign; 144 __ret.field[1] = symbol; 145 __ret.field[2] = space; 146 __ret.field[3] = value; 147 } 148 else 149 { 150 __ret.field[0] = value; 151 __ret.field[1] = space; 152 __ret.field[2] = sign; 153 __ret.field[3] = symbol; 154 } 155 } 156 else 157 { 158 // Have none. 159 if (__precedes) 160 { 161 __ret.field[0] = sign; 162 __ret.field[1] = symbol; 163 __ret.field[2] = value; 164 } 165 else 166 { 167 __ret.field[0] = value; 168 __ret.field[1] = sign; 169 __ret.field[2] = symbol; 170 } 171 __ret.field[3] = none; 172 } 173 break; 174 case 4: 175 // 4 The sign immediately follows the symbol. 176 if (__space) 177 { 178 // Have space. 179 if (__precedes) 180 { 181 __ret.field[0] = symbol; 182 __ret.field[1] = sign; 183 __ret.field[2] = space; 184 __ret.field[3] = value; 185 } 186 else 187 { 188 __ret.field[0] = value; 189 __ret.field[1] = space; 190 __ret.field[2] = symbol; 191 __ret.field[3] = sign; 192 } 193 } 194 else 195 { 196 // Have none. 197 if (__precedes) 198 { 199 __ret.field[0] = symbol; 200 __ret.field[1] = sign; 201 __ret.field[2] = value; 202 } 203 else 204 { 205 __ret.field[0] = value; 206 __ret.field[1] = symbol; 207 __ret.field[2] = sign; 208 } 209 __ret.field[3] = none; 210 } 211 break; 212 default: 213 ; 214 } 215 return __ret; 216 } 217 218 template<> 219 void 220 moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc, 221 const char*) 222 { 223 if (!__cloc) 224 { 225 // "C" locale 226 _M_decimal_point = '.'; 227 _M_thousands_sep = ','; 228 _M_grouping = ""; 229 _M_curr_symbol = ""; 230 _M_positive_sign = ""; 231 _M_negative_sign = ""; 232 _M_frac_digits = 0; 233 _M_pos_format = money_base::_S_default_pattern; 234 _M_neg_format = money_base::_S_default_pattern; 235 } 236 else 237 { 238 // Named locale. 239 _M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, __cloc)); 240 _M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc)); 241 _M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); 242 _M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 243 244 char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 245 if (!__nposn) 246 _M_negative_sign = "()"; 247 else 248 _M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 249 250 // _Intl == true 251 _M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 252 _M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc)); 253 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 254 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 255 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 256 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 257 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 258 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 259 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 260 } 261 } 262 263 template<> 264 void 265 moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc, 266 const char*) 267 { 268 if (!__cloc) 269 { 270 // "C" locale 271 _M_decimal_point = '.'; 272 _M_thousands_sep = ','; 273 _M_grouping = ""; 274 _M_curr_symbol = ""; 275 _M_positive_sign = ""; 276 _M_negative_sign = ""; 277 _M_frac_digits = 0; 278 _M_pos_format = money_base::_S_default_pattern; 279 _M_neg_format = money_base::_S_default_pattern; 280 } 281 else 282 { 283 // Named locale. 284 _M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, __cloc)); 285 _M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc)); 286 _M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); 287 _M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 288 289 char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 290 if (!__nposn) 291 _M_negative_sign = "()"; 292 else 293 _M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 294 295 // _Intl == false 296 _M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 297 _M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); 298 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 299 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 300 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 301 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 302 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 303 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 304 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 305 } 306 } 307 308 template<> 309 moneypunct<char, true>::~moneypunct() 310 { } 311 312 template<> 313 moneypunct<char, false>::~moneypunct() 314 { } 315 316#ifdef _GLIBCPP_USE_WCHAR_T 317 template<> 318 void 319 moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc, 320#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 321 const char*) 322#else 323 const char* __name) 324#endif 325 { 326 if (!__cloc) 327 { 328 // "C" locale 329 _M_decimal_point = L'.'; 330 _M_thousands_sep = L','; 331 _M_grouping = ""; 332 _M_curr_symbol = L""; 333 _M_positive_sign = L""; 334 _M_negative_sign = L""; 335 _M_frac_digits = 0; 336 _M_pos_format = money_base::_S_default_pattern; 337 _M_neg_format = money_base::_S_default_pattern; 338 } 339 else 340 { 341 // Named locale. 342#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 343 __c_locale __old = __uselocale(__cloc); 344#else 345 // Switch to named locale so that mbsrtowcs will work. 346 char* __old = strdup(setlocale(LC_ALL, NULL)); 347 setlocale(LC_ALL, __name); 348#endif 349 350 _M_decimal_point = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc)}).__w); 351 352 _M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w); 353 _M_grouping = __nl_langinfo_l(GROUPING, __cloc); 354 355 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 356 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 357 const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 358 359 mbstate_t __state; 360 size_t __len = strlen(__cpossign); 361 if (__len) 362 { 363 ++__len; 364 memset(&__state, 0, sizeof(mbstate_t)); 365 wchar_t* __wcs = new wchar_t[__len]; 366 mbsrtowcs(__wcs, &__cpossign, __len, &__state); 367 _M_positive_sign = __wcs; 368 } 369 else 370 _M_positive_sign = L""; 371 372 char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 373 __len = strlen(__cnegsign); 374 if (!__nposn) 375 _M_negative_sign = L"()"; 376 else if (__len) 377 { 378 ++__len; 379 memset(&__state, 0, sizeof(mbstate_t)); 380 wchar_t* __wcs = new wchar_t[__len]; 381 mbsrtowcs(__wcs, &__cnegsign, __len, &__state); 382 _M_negative_sign = __wcs; 383 } 384 else 385 _M_negative_sign = L""; 386 387 // _Intl == true. 388 __len = strlen(__ccurr); 389 if (__len) 390 { 391 ++__len; 392 memset(&__state, 0, sizeof(mbstate_t)); 393 wchar_t* __wcs = new wchar_t[__len]; 394 mbsrtowcs(__wcs, &__ccurr, __len, &__state); 395 _M_curr_symbol = __wcs; 396 } 397 else 398 _M_curr_symbol = L""; 399 400 _M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc)); 401 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 402 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 403 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 404 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 405 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 406 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 407 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 408 409#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 410 __uselocale(__old); 411#else 412 setlocale(LC_ALL, __old); 413 free(__old); 414#endif 415 } 416 } 417 418 template<> 419 void 420 moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc, 421#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 422 const char*) 423#else 424 const char* __name) 425#endif 426 { 427 if (!__cloc) 428 { 429 // "C" locale 430 _M_decimal_point = L'.'; 431 _M_thousands_sep = L','; 432 _M_grouping = ""; 433 _M_curr_symbol = L""; 434 _M_positive_sign = L""; 435 _M_negative_sign = L""; 436 _M_frac_digits = 0; 437 _M_pos_format = money_base::_S_default_pattern; 438 _M_neg_format = money_base::_S_default_pattern; 439 } 440 else 441 { 442 // Named locale. 443#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 444 __c_locale __old = __uselocale(__cloc); 445#else 446 // Switch to named locale so that mbsrtowcs will work. 447 char* __old = strdup(setlocale(LC_ALL, NULL)); 448 setlocale(LC_ALL, __name); 449#endif 450 451 _M_decimal_point = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_DECIMAL_POINT_WC, __cloc)}).__w); 452 _M_thousands_sep = static_cast<wchar_t>(((union { const char *__s; unsigned int __w; }){ __s: __nl_langinfo_l(_NL_NUMERIC_THOUSANDS_SEP_WC, __cloc)}).__w); 453 _M_grouping = __nl_langinfo_l(GROUPING, __cloc); 454 455 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 456 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 457 const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 458 459 mbstate_t __state; 460 size_t __len; 461 __len = strlen(__cpossign); 462 if (__len) 463 { 464 ++__len; 465 memset(&__state, 0, sizeof(mbstate_t)); 466 wchar_t* __wcs = new wchar_t[__len]; 467 mbsrtowcs(__wcs, &__cpossign, __len, &__state); 468 _M_positive_sign = __wcs; 469 } 470 else 471 _M_positive_sign = L""; 472 473 char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 474 __len = strlen(__cnegsign); 475 if (!__nposn) 476 _M_negative_sign = L"()"; 477 else if (__len) 478 { 479 ++__len; 480 memset(&__state, 0, sizeof(mbstate_t)); 481 wchar_t* __wcs = new wchar_t[__len]; 482 mbsrtowcs(__wcs, &__cnegsign, __len, &__state); 483 _M_negative_sign = __wcs; 484 } 485 else 486 _M_negative_sign = L""; 487 488 // _Intl == true. 489 __len = strlen(__ccurr); 490 if (__len) 491 { 492 ++__len; 493 memset(&__state, 0, sizeof(mbstate_t)); 494 wchar_t* __wcs = new wchar_t[__len]; 495 mbsrtowcs(__wcs, &__ccurr, __len, &__state); 496 _M_curr_symbol = __wcs; 497 } 498 else 499 _M_curr_symbol = L""; 500 501 _M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); 502 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 503 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 504 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 505 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 506 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 507 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 508 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 509 510#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 511 __uselocale(__old); 512#else 513 setlocale(LC_ALL, __old); 514 free(__old); 515#endif 516 } 517 } 518 519 template<> 520 moneypunct<wchar_t, true>::~moneypunct() 521 { 522 if (wcslen(_M_positive_sign)) 523 delete [] _M_positive_sign; 524 if (wcslen(_M_negative_sign) && (wcscmp(_M_negative_sign, L"()") != 0)) 525 delete [] _M_negative_sign; 526 if (wcslen(_M_curr_symbol)) 527 delete [] _M_curr_symbol; 528 } 529 530 template<> 531 moneypunct<wchar_t, false>::~moneypunct() 532 { 533 if (wcslen(_M_positive_sign)) 534 delete [] _M_positive_sign; 535 if (wcslen(_M_negative_sign) && (wcscmp(_M_negative_sign, L"()") != 0)) 536 delete [] _M_negative_sign; 537 if (wcslen(_M_curr_symbol)) 538 delete [] _M_curr_symbol; 539 } 540#endif 541} 542