monetary_members.cc revision 107606
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 "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 const char* __name) 321 { 322 if (!__cloc) 323 { 324 // "C" locale 325 _M_decimal_point = L'.'; 326 _M_thousands_sep = L','; 327 _M_grouping = ""; 328 _M_curr_symbol = L""; 329 _M_positive_sign = L""; 330 _M_negative_sign = L""; 331 _M_frac_digits = 0; 332 _M_pos_format = money_base::_S_default_pattern; 333 _M_neg_format = money_base::_S_default_pattern; 334 } 335 else 336 { 337 // Named locale. 338#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 339 __c_locale __old = __uselocale(__cloc); 340#else 341 // Switch to named locale so that mbsrtowcs will work. 342 char* __old = strdup(setlocale(LC_ALL, NULL)); 343 setlocale(LC_ALL, __name); 344#endif 345 346 _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); 347 348 _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); 349 _M_grouping = __nl_langinfo_l(GROUPING, __cloc); 350 351 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 352 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 353 const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 354 355 mbstate_t __state; 356 size_t __len = strlen(__cpossign); 357 if (__len) 358 { 359 ++__len; 360 memset(&__state, 0, sizeof(mbstate_t)); 361 wchar_t* __wcs = new wchar_t[__len]; 362 mbsrtowcs(__wcs, &__cpossign, __len, &__state); 363 _M_positive_sign = __wcs; 364 } 365 else 366 _M_positive_sign = L""; 367 368 char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 369 __len = strlen(__cnegsign); 370 if (!__nposn) 371 _M_negative_sign = L"()"; 372 else if (__len) 373 { 374 ++__len; 375 memset(&__state, 0, sizeof(mbstate_t)); 376 wchar_t* __wcs = new wchar_t[__len]; 377 mbsrtowcs(__wcs, &__cnegsign, __len, &__state); 378 _M_negative_sign = __wcs; 379 } 380 else 381 _M_negative_sign = L""; 382 383 // _Intl == true. 384 __len = strlen(__ccurr); 385 if (__len) 386 { 387 ++__len; 388 memset(&__state, 0, sizeof(mbstate_t)); 389 wchar_t* __wcs = new wchar_t[__len]; 390 mbsrtowcs(__wcs, &__ccurr, __len, &__state); 391 _M_curr_symbol = __wcs; 392 } 393 else 394 _M_curr_symbol = L""; 395 396 _M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc)); 397 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 398 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 399 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 400 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 401 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 402 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 403 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 404 405#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 406 __uselocale(__old); 407#else 408 setlocale(LC_ALL, __old); 409 free(__old); 410#endif 411 } 412 } 413 414 template<> 415 void 416 moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc, 417 const char* __name) 418 { 419 if (!__cloc) 420 { 421 // "C" locale 422 _M_decimal_point = L'.'; 423 _M_thousands_sep = L','; 424 _M_grouping = ""; 425 _M_curr_symbol = L""; 426 _M_positive_sign = L""; 427 _M_negative_sign = L""; 428 _M_frac_digits = 0; 429 _M_pos_format = money_base::_S_default_pattern; 430 _M_neg_format = money_base::_S_default_pattern; 431 } 432 else 433 { 434 // Named locale. 435#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 436 __c_locale __old = __uselocale(__cloc); 437#else 438 // Switch to named locale so that mbsrtowcs will work. 439 char* __old = strdup(setlocale(LC_ALL, NULL)); 440 setlocale(LC_ALL, __name); 441#endif 442 443 _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); 444 _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); 445 _M_grouping = __nl_langinfo_l(GROUPING, __cloc); 446 447 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 448 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 449 const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 450 451 mbstate_t __state; 452 size_t __len; 453 __len = strlen(__cpossign); 454 if (__len) 455 { 456 ++__len; 457 memset(&__state, 0, sizeof(mbstate_t)); 458 wchar_t* __wcs = new wchar_t[__len]; 459 mbsrtowcs(__wcs, &__cpossign, __len, &__state); 460 _M_positive_sign = __wcs; 461 } 462 else 463 _M_positive_sign = L""; 464 465 char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 466 __len = strlen(__cnegsign); 467 if (!__nposn) 468 _M_negative_sign = L"()"; 469 else if (__len) 470 { 471 ++__len; 472 memset(&__state, 0, sizeof(mbstate_t)); 473 wchar_t* __wcs = new wchar_t[__len]; 474 mbsrtowcs(__wcs, &__cnegsign, __len, &__state); 475 _M_negative_sign = __wcs; 476 } 477 else 478 _M_negative_sign = L""; 479 480 // _Intl == true. 481 __len = strlen(__ccurr); 482 if (__len) 483 { 484 ++__len; 485 memset(&__state, 0, sizeof(mbstate_t)); 486 wchar_t* __wcs = new wchar_t[__len]; 487 mbsrtowcs(__wcs, &__ccurr, __len, &__state); 488 _M_curr_symbol = __wcs; 489 } 490 else 491 _M_curr_symbol = L""; 492 493 _M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); 494 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 495 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 496 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 497 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 498 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 499 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 500 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 501 502#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) 503 __uselocale(__old); 504#else 505 setlocale(LC_ALL, __old); 506 free(__old); 507#endif 508 } 509 } 510 511 template<> 512 moneypunct<wchar_t, true>::~moneypunct() 513 { 514 if (wcslen(_M_positive_sign)) 515 delete [] _M_positive_sign; 516 if (wcslen(_M_negative_sign) && (wcscmp(_M_negative_sign, L"()") != 0)) 517 delete [] _M_negative_sign; 518 if (wcslen(_M_curr_symbol)) 519 delete [] _M_curr_symbol; 520 } 521 522 template<> 523 moneypunct<wchar_t, false>::~moneypunct() 524 { 525 if (wcslen(_M_positive_sign)) 526 delete [] _M_positive_sign; 527 if (wcslen(_M_negative_sign) && (wcscmp(_M_negative_sign, L"()") != 0)) 528 delete [] _M_negative_sign; 529 if (wcslen(_M_curr_symbol)) 530 delete [] _M_curr_symbol; 531 } 532#endif 533} 534