monetary_members.cc revision 102782
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 38namespace std 39{ 40 // Construct and return valid pattern consisting of some combination of: 41 // space none symbol sign value 42 money_base::pattern 43 money_base::_S_construct_pattern(char __precedes, char __space, char __posn) 44 { 45 pattern __ret; 46 47 // This insanely complicated routine attempts to construct a valid 48 // pattern for use with monyepunct. A couple of invariants: 49 50 // if (__precedes) symbol -> value 51 // else value -> symbol 52 53 // if (__space) space 54 // else none 55 56 // none == never first 57 // space never first or last 58 59 // Any elegant implementations of this are welcome. 60 switch (__posn) 61 { 62 case 0: 63 case 1: 64 // 1 The sign precedes the value and symbol. 65 if (__space) 66 { 67 // Pattern starts with sign. 68 if (__precedes) 69 { 70 __ret.field[1] = symbol; 71 __ret.field[2] = space; 72 __ret.field[3] = value; 73 } 74 else 75 { 76 __ret.field[1] = value; 77 __ret.field[2] = space; 78 __ret.field[3] = symbol; 79 } 80 __ret.field[0] = sign; 81 } 82 else 83 { 84 // Pattern starts with sign and ends with none. 85 if (__precedes) 86 { 87 __ret.field[1] = symbol; 88 __ret.field[2] = value; 89 } 90 else 91 { 92 __ret.field[1] = value; 93 __ret.field[2] = symbol; 94 } 95 __ret.field[0] = sign; 96 __ret.field[3] = none; 97 } 98 break; 99 case 2: 100 // 2 The sign follows the value and symbol. 101 if (__space) 102 { 103 // Pattern either ends with sign. 104 if (__precedes) 105 { 106 __ret.field[0] = symbol; 107 __ret.field[1] = space; 108 __ret.field[2] = value; 109 } 110 else 111 { 112 __ret.field[0] = value; 113 __ret.field[1] = space; 114 __ret.field[2] = symbol; 115 } 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 (__space) 138 { 139 // Have space. 140 if (__precedes) 141 { 142 __ret.field[0] = sign; 143 __ret.field[1] = symbol; 144 __ret.field[2] = space; 145 __ret.field[3] = value; 146 } 147 else 148 { 149 __ret.field[0] = value; 150 __ret.field[1] = space; 151 __ret.field[2] = sign; 152 __ret.field[3] = symbol; 153 } 154 } 155 else 156 { 157 // Have none. 158 if (__precedes) 159 { 160 __ret.field[0] = sign; 161 __ret.field[1] = symbol; 162 __ret.field[2] = value; 163 } 164 else 165 { 166 __ret.field[0] = value; 167 __ret.field[1] = sign; 168 __ret.field[2] = symbol; 169 } 170 __ret.field[3] = none; 171 } 172 break; 173 case 4: 174 // 4 The sign immediately follows the symbol. 175 if (__space) 176 { 177 // Have space. 178 if (__precedes) 179 { 180 __ret.field[0] = symbol; 181 __ret.field[1] = sign; 182 __ret.field[2] = space; 183 __ret.field[3] = value; 184 } 185 else 186 { 187 __ret.field[0] = value; 188 __ret.field[1] = space; 189 __ret.field[2] = symbol; 190 __ret.field[3] = sign; 191 } 192 } 193 else 194 { 195 // Have none. 196 if (__precedes) 197 { 198 __ret.field[0] = symbol; 199 __ret.field[1] = sign; 200 __ret.field[2] = value; 201 } 202 else 203 { 204 __ret.field[0] = value; 205 __ret.field[1] = symbol; 206 __ret.field[2] = sign; 207 } 208 __ret.field[3] = none; 209 } 210 break; 211 default: 212 ; 213 } 214 return __ret; 215 } 216 217 template<> 218 void 219 moneypunct<char, true>::_M_initialize_moneypunct(__c_locale __cloc, 220 const char*) 221 { 222 if (__cloc == _S_c_locale) 223 { 224 // "C" locale 225 _M_decimal_point = '.'; 226 _M_thousands_sep = ','; 227 _M_grouping = ""; 228 _M_curr_symbol = ""; 229 _M_positive_sign = ""; 230 _M_negative_sign = ""; 231 _M_frac_digits = 0; 232 _M_pos_format = money_base::_S_default_pattern; 233 _M_neg_format = money_base::_S_default_pattern; 234 } 235 else 236 { 237 // Named locale. 238 _M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, __cloc)); 239 _M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc)); 240 _M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); 241 _M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 242 243 char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 244 if (!__nposn) 245 _M_negative_sign = "()"; 246 else 247 _M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 248 249 // _Intl == true 250 _M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 251 _M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc)); 252 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 253 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 254 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 255 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 256 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 257 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 258 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 259 } 260 } 261 262 template<> 263 void 264 moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc, 265 const char*) 266 { 267 if (__cloc == _S_c_locale) 268 { 269 // "C" locale 270 _M_decimal_point = '.'; 271 _M_thousands_sep = ','; 272 _M_grouping = ""; 273 _M_curr_symbol = ""; 274 _M_positive_sign = ""; 275 _M_negative_sign = ""; 276 _M_frac_digits = 0; 277 _M_pos_format = money_base::_S_default_pattern; 278 _M_neg_format = money_base::_S_default_pattern; 279 } 280 else 281 { 282 // Named locale. 283 _M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, __cloc)); 284 _M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc)); 285 _M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); 286 _M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 287 288 char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 289 if (!__nposn) 290 _M_negative_sign = "()"; 291 else 292 _M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 293 294 // _Intl == false 295 _M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 296 _M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); 297 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 298 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 299 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 300 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 301 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 302 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 303 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 304 } 305 } 306 307 template<> 308 moneypunct<char, true>::~moneypunct() 309 { } 310 311 template<> 312 moneypunct<char, false>::~moneypunct() 313 { } 314 315#ifdef _GLIBCPP_USE_WCHAR_T 316 template<> 317 void 318 moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc, 319 const char* __name) 320 { 321 if (__cloc == _S_c_locale) 322 { 323 // "C" locale 324 _M_decimal_point = L'.'; 325 _M_thousands_sep = L','; 326 _M_grouping = ""; 327 _M_curr_symbol = L""; 328 _M_positive_sign = L""; 329 _M_negative_sign = L""; 330 _M_frac_digits = 0; 331 _M_pos_format = money_base::_S_default_pattern; 332 _M_neg_format = money_base::_S_default_pattern; 333 } 334 else 335 { 336 // Named locale. 337 // XXX Fix me. Switch to named locale so that mbsrtowcs will work. 338 char* __old = strdup(setlocale(LC_ALL, NULL)); 339 setlocale(LC_ALL, __name); 340 341 _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); 342 343 _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); 344 _M_grouping = __nl_langinfo_l(GROUPING, __cloc); 345 346 mbstate_t __state; 347 size_t __len; 348 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 349 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 350 const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 351 352 // NB: Should swich to __cloc's ctype info first. 353 __len = strlen(__cpossign); 354 if (__len) 355 { 356 ++__len; 357 memset(&__state, 0, sizeof(mbstate_t)); 358 wchar_t* __wcs = new wchar_t[__len]; 359 mbsrtowcs(__wcs, &__cpossign, __len, &__state); 360 _M_positive_sign = __wcs; 361 } 362 else 363 _M_positive_sign = L""; 364 365 char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 366 __len = strlen(__cnegsign); 367 if (!__nposn) 368 _M_negative_sign = L"()"; 369 else if (__len) 370 { 371 ++__len; 372 memset(&__state, 0, sizeof(mbstate_t)); 373 wchar_t* __wcs = new wchar_t[__len]; 374 mbsrtowcs(__wcs, &__cnegsign, __len, &__state); 375 _M_negative_sign = __wcs; 376 } 377 else 378 _M_negative_sign = L""; 379 380 // _Intl == true. 381 __len = strlen(__ccurr); 382 if (__len) 383 { 384 ++__len; 385 memset(&__state, 0, sizeof(mbstate_t)); 386 wchar_t* __wcs = new wchar_t[__len]; 387 mbsrtowcs(__wcs, &__ccurr, __len, &__state); 388 _M_curr_symbol = __wcs; 389 } 390 else 391 _M_curr_symbol = L""; 392 393 _M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc)); 394 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 395 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 396 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 397 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 398 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 399 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 400 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 401 402 // XXX 403 setlocale(LC_ALL, __old); 404 free(__old); 405 } 406 } 407 408 template<> 409 void 410 moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc, 411 const char* __name) 412 { 413 if (__cloc == _S_c_locale) 414 { 415 // "C" locale 416 _M_decimal_point = L'.'; 417 _M_thousands_sep = L','; 418 _M_grouping = ""; 419 _M_curr_symbol = L""; 420 _M_positive_sign = L""; 421 _M_negative_sign = L""; 422 _M_frac_digits = 0; 423 _M_pos_format = money_base::_S_default_pattern; 424 _M_neg_format = money_base::_S_default_pattern; 425 } 426 else 427 { 428 // Named locale. 429 // XXX Fix me. Switch to named locale so that mbsrtowcs will work. 430 char* __old = strdup(setlocale(LC_ALL, NULL)); 431 setlocale(LC_ALL, __name); 432 433 _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); 434 _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); 435 _M_grouping = __nl_langinfo_l(GROUPING, __cloc); 436 437 mbstate_t __state; 438 size_t __len; 439 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 440 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 441 const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 442 443 // NB: Should swich to __cloc's ctype info first. 444 __len = strlen(__cpossign); 445 if (__len) 446 { 447 ++__len; 448 memset(&__state, 0, sizeof(mbstate_t)); 449 wchar_t* __wcs = new wchar_t[__len]; 450 mbsrtowcs(__wcs, &__cpossign, __len, &__state); 451 _M_positive_sign = __wcs; 452 } 453 else 454 _M_positive_sign = L""; 455 456 char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 457 __len = strlen(__cnegsign); 458 if (!__nposn) 459 _M_negative_sign = L"()"; 460 else if (__len) 461 { 462 ++__len; 463 memset(&__state, 0, sizeof(mbstate_t)); 464 wchar_t* __wcs = new wchar_t[__len]; 465 mbsrtowcs(__wcs, &__cnegsign, __len, &__state); 466 _M_negative_sign = __wcs; 467 } 468 else 469 _M_negative_sign = L""; 470 471 // _Intl == true. 472 __len = strlen(__ccurr); 473 if (__len) 474 { 475 ++__len; 476 memset(&__state, 0, sizeof(mbstate_t)); 477 wchar_t* __wcs = new wchar_t[__len]; 478 mbsrtowcs(__wcs, &__ccurr, __len, &__state); 479 _M_curr_symbol = __wcs; 480 } 481 else 482 _M_curr_symbol = L""; 483 484 _M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); 485 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 486 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 487 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 488 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 489 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 490 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 491 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 492 493 // XXX 494 setlocale(LC_ALL, __old); 495 free(__old); 496 } 497 } 498 499 template<> 500 moneypunct<wchar_t, true>::~moneypunct() 501 { 502 if (wcslen(_M_positive_sign)) 503 delete [] _M_positive_sign; 504 if (wcslen(_M_negative_sign) && (wcscmp(_M_negative_sign, L"()") != 0)) 505 delete [] _M_negative_sign; 506 if (wcslen(_M_curr_symbol)) 507 delete [] _M_curr_symbol; 508 } 509 510 template<> 511 moneypunct<wchar_t, false>::~moneypunct() 512 { 513 if (wcslen(_M_positive_sign)) 514 delete [] _M_positive_sign; 515 if (wcslen(_M_negative_sign) && (wcscmp(_M_negative_sign, L"()") != 0)) 516 delete [] _M_negative_sign; 517 if (wcslen(_M_curr_symbol)) 518 delete [] _M_curr_symbol; 519 } 520#endif 521} 522