monetary_members.cc revision 97403
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 { 221 if (__cloc == _S_c_locale) 222 { 223 // "C" locale 224 _M_decimal_point = '.'; 225 _M_thousands_sep = ','; 226 _M_grouping = ""; 227 _M_curr_symbol = ""; 228 _M_positive_sign = ""; 229 _M_negative_sign = ""; 230 _M_frac_digits = 0; 231 _M_pos_format = money_base::_S_default_pattern; 232 _M_neg_format = money_base::_S_default_pattern; 233 } 234 else 235 { 236 // Named locale. 237 _M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, __cloc)); 238 _M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc)); 239 _M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); 240 _M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 241 242 char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 243 if (!__nposn) 244 _M_negative_sign = "()"; 245 else 246 _M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 247 248 // _Intl == true 249 _M_curr_symbol = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 250 _M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc)); 251 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 252 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 253 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 254 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 255 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 256 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 257 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 258 } 259 } 260 261 template<> 262 void 263 moneypunct<char, false>::_M_initialize_moneypunct(__c_locale __cloc) 264 { 265 if (__cloc == _S_c_locale) 266 { 267 // "C" locale 268 _M_decimal_point = '.'; 269 _M_thousands_sep = ','; 270 _M_grouping = ""; 271 _M_curr_symbol = ""; 272 _M_positive_sign = ""; 273 _M_negative_sign = ""; 274 _M_frac_digits = 0; 275 _M_pos_format = money_base::_S_default_pattern; 276 _M_neg_format = money_base::_S_default_pattern; 277 } 278 else 279 { 280 // Named locale. 281 _M_decimal_point = *(__nl_langinfo_l(__MON_DECIMAL_POINT, __cloc)); 282 _M_thousands_sep = *(__nl_langinfo_l(__MON_THOUSANDS_SEP, __cloc)); 283 _M_grouping = __nl_langinfo_l(__MON_GROUPING, __cloc); 284 _M_positive_sign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 285 286 char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 287 if (!__nposn) 288 _M_negative_sign = "()"; 289 else 290 _M_negative_sign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 291 292 // _Intl == false 293 _M_curr_symbol = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 294 _M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); 295 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 296 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 297 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 298 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 299 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 300 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 301 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 302 } 303 } 304 305 template<> 306 moneypunct<char, true>::~moneypunct() 307 { } 308 309 template<> 310 moneypunct<char, false>::~moneypunct() 311 { } 312 313#ifdef _GLIBCPP_USE_WCHAR_T 314 template<> 315 void 316 moneypunct<wchar_t, true>::_M_initialize_moneypunct(__c_locale __cloc) 317 { 318 if (__cloc == _S_c_locale) 319 { 320 // "C" locale 321 _M_decimal_point = L'.'; 322 _M_thousands_sep = L','; 323 _M_grouping = ""; 324 _M_curr_symbol = L""; 325 _M_positive_sign = L""; 326 _M_negative_sign = L""; 327 _M_frac_digits = 0; 328 _M_pos_format = money_base::_S_default_pattern; 329 _M_neg_format = money_base::_S_default_pattern; 330 } 331 else 332 { 333 // Named locale. 334 _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); 335 336 _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); 337 _M_grouping = __nl_langinfo_l(GROUPING, __cloc); 338 339 mbstate_t __state; 340 size_t __len; 341 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 342 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 343 const char* __ccurr = __nl_langinfo_l(__INT_CURR_SYMBOL, __cloc); 344 345 // NB: Should swich to __cloc's ctype info first. 346 __len = strlen(__cpossign); 347 if (__len) 348 { 349 ++__len; 350 memset(&__state, 0, sizeof(mbstate_t)); 351 wchar_t* __wcs = new wchar_t[__len]; 352 mbsrtowcs(__wcs, &__cpossign, __len, &__state); 353 _M_positive_sign = __wcs; 354 } 355 else 356 _M_positive_sign = L""; 357 358 char __nposn = *(__nl_langinfo_l(__INT_N_SIGN_POSN, __cloc)); 359 __len = strlen(__cnegsign); 360 if (!__nposn) 361 _M_negative_sign = L"()"; 362 else if (__len) 363 { 364 ++__len; 365 memset(&__state, 0, sizeof(mbstate_t)); 366 wchar_t* __wcs = new wchar_t[__len]; 367 mbsrtowcs(__wcs, &__cnegsign, __len, &__state); 368 _M_negative_sign = __wcs; 369 } 370 else 371 _M_negative_sign = L""; 372 373 // _Intl == true. 374 __len = strlen(__ccurr); 375 if (__len) 376 { 377 ++__len; 378 memset(&__state, 0, sizeof(mbstate_t)); 379 wchar_t* __wcs = new wchar_t[__len]; 380 mbsrtowcs(__wcs, &__ccurr, __len, &__state); 381 _M_curr_symbol = __wcs; 382 } 383 else 384 _M_curr_symbol = L""; 385 386 _M_frac_digits = *(__nl_langinfo_l(__INT_FRAC_DIGITS, __cloc)); 387 char __pprecedes = *(__nl_langinfo_l(__INT_P_CS_PRECEDES, __cloc)); 388 char __pspace = *(__nl_langinfo_l(__INT_P_SEP_BY_SPACE, __cloc)); 389 char __pposn = *(__nl_langinfo_l(__INT_P_SIGN_POSN, __cloc)); 390 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 391 char __nprecedes = *(__nl_langinfo_l(__INT_N_CS_PRECEDES, __cloc)); 392 char __nspace = *(__nl_langinfo_l(__INT_N_SEP_BY_SPACE, __cloc)); 393 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 394 } 395 } 396 397 template<> 398 void 399 moneypunct<wchar_t, false>::_M_initialize_moneypunct(__c_locale __cloc) 400 { 401 if (__cloc == _S_c_locale) 402 { 403 // "C" locale 404 _M_decimal_point = L'.'; 405 _M_thousands_sep = L','; 406 _M_grouping = ""; 407 _M_curr_symbol = L""; 408 _M_positive_sign = L""; 409 _M_negative_sign = L""; 410 _M_frac_digits = 0; 411 _M_pos_format = money_base::_S_default_pattern; 412 _M_neg_format = money_base::_S_default_pattern; 413 } 414 else 415 { 416 // Named locale. 417 _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); 418 _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); 419 _M_grouping = __nl_langinfo_l(GROUPING, __cloc); 420 421 mbstate_t __state; 422 size_t __len; 423 const char* __cpossign = __nl_langinfo_l(__POSITIVE_SIGN, __cloc); 424 const char* __cnegsign = __nl_langinfo_l(__NEGATIVE_SIGN, __cloc); 425 const char* __ccurr = __nl_langinfo_l(__CURRENCY_SYMBOL, __cloc); 426 427 // NB: Should swich to __cloc's ctype info first. 428 __len = strlen(__cpossign); 429 if (__len) 430 { 431 ++__len; 432 memset(&__state, 0, sizeof(mbstate_t)); 433 wchar_t* __wcs = new wchar_t[__len]; 434 mbsrtowcs(__wcs, &__cpossign, __len, &__state); 435 _M_positive_sign = __wcs; 436 } 437 else 438 _M_positive_sign = L""; 439 440 char __nposn = *(__nl_langinfo_l(__N_SIGN_POSN, __cloc)); 441 __len = strlen(__cnegsign); 442 if (!__nposn) 443 _M_negative_sign = L"()"; 444 else if (__len) 445 { 446 ++__len; 447 memset(&__state, 0, sizeof(mbstate_t)); 448 wchar_t* __wcs = new wchar_t[__len]; 449 mbsrtowcs(__wcs, &__cnegsign, __len, &__state); 450 _M_negative_sign = __wcs; 451 } 452 else 453 _M_negative_sign = L""; 454 455 // _Intl == true. 456 __len = strlen(__ccurr); 457 if (__len) 458 { 459 ++__len; 460 memset(&__state, 0, sizeof(mbstate_t)); 461 wchar_t* __wcs = new wchar_t[__len]; 462 mbsrtowcs(__wcs, &__ccurr, __len, &__state); 463 _M_curr_symbol = __wcs; 464 } 465 else 466 _M_curr_symbol = L""; 467 468 _M_frac_digits = *(__nl_langinfo_l(__FRAC_DIGITS, __cloc)); 469 char __pprecedes = *(__nl_langinfo_l(__P_CS_PRECEDES, __cloc)); 470 char __pspace = *(__nl_langinfo_l(__P_SEP_BY_SPACE, __cloc)); 471 char __pposn = *(__nl_langinfo_l(__P_SIGN_POSN, __cloc)); 472 _M_pos_format = _S_construct_pattern(__pprecedes, __pspace, __pposn); 473 char __nprecedes = *(__nl_langinfo_l(__N_CS_PRECEDES, __cloc)); 474 char __nspace = *(__nl_langinfo_l(__N_SEP_BY_SPACE, __cloc)); 475 _M_neg_format = _S_construct_pattern(__nprecedes, __nspace, __nposn); 476 } 477 } 478 479 template<> 480 moneypunct<wchar_t, true>::~moneypunct() 481 { 482 if (wcslen(_M_positive_sign)) 483 delete [] _M_positive_sign; 484 if (wcslen(_M_negative_sign) && (wcscmp(_M_negative_sign, L"()") != 0)) 485 delete [] _M_negative_sign; 486 if (wcslen(_M_curr_symbol)) 487 delete [] _M_curr_symbol; 488 } 489 490 template<> 491 moneypunct<wchar_t, false>::~moneypunct() 492 { 493 if (wcslen(_M_positive_sign)) 494 delete [] _M_positive_sign; 495 if (wcslen(_M_negative_sign) && (wcscmp(_M_negative_sign, L"()") != 0)) 496 delete [] _M_negative_sign; 497 if (wcslen(_M_curr_symbol)) 498 delete [] _M_curr_symbol; 499 } 500#endif 501} 502