1 /* 2 * Copyright (c) 1999 3 * Silicon Graphics Computer Systems, Inc. 4 * 5 * Copyright (c) 1999 6 * Boris Fomitchev 7 * 8 * This material is provided "as is", with absolutely no warranty expressed 9 * or implied. Any use is at your own risk. 10 * 11 * Permission to use or copy this software for any purpose is hereby granted 12 * without fee, provided the above notices are retained on all copies. 13 * Permission to modify the code and to distribute modified code is granted, 14 * provided the above notices are retained, and a notice that the code was 15 * modified is included with the above copyright notice. 16 * 17 */ 18 #include "stlport_prefix.h" 19 20 #include <hash_map> 21 #include <vector> 22 23 #include <locale> 24 #include <istream> 25 26 #include <algorithm> 27 #include <functional> 28 29 #include "c_locale.h" 30 #include "locale_impl.h" 31 #include "acquire_release.h" 32 33 _STLP_BEGIN_NAMESPACE 34 35 //---------------------------------------------------------------------- 36 // ctype_byname<char> 37 38 #if defined (__DMC__) 39 _STLP_DECLSPEC 40 #endif 41 ctype_byname<char>::ctype_byname(const char* name, size_t refs) 42 : ctype<char>( 0, false, refs) { 43 if (!name) 44 locale::_M_throw_on_null_name(); 45 46 int __err_code; 47 char buf[_Locale_MAX_SIMPLE_NAME]; 48 _M_ctype = _STLP_PRIV __acquire_ctype(name, buf, 0, &__err_code); 49 if (!_M_ctype) 50 locale::_M_throw_on_creation_failure(__err_code, name, "ctype"); 51 52 _M_init(); 53 } 54 55 void ctype_byname<char>::_M_init() { 56 _M_ctype_table = _M_byname_table; 57 58 // We have to do this, instead of just pointer twiddling, because 59 // ctype_base::mask isn't the same type as _Locale_mask_t. 60 const _Locale_mask_t* p = _Locale_ctype_table(_M_ctype); 61 for (size_t i = 0; i != table_size; ++i) { 62 _M_byname_table[i] = ctype_base::mask(p[i]); 63 } 64 } 65 66 ctype_byname<char>::~ctype_byname() 67 { _STLP_PRIV __release_ctype(_M_ctype); } 68 69 char ctype_byname<char>::do_toupper(char c) const 70 { return (char)_Locale_toupper(_M_ctype, c); } 71 72 char ctype_byname<char>::do_tolower(char c) const 73 { return (char)_Locale_tolower(_M_ctype, c); } 74 75 const char* 76 ctype_byname<char>::do_toupper(char* first, const char* last) const { 77 for ( ; first != last ; ++first) 78 *first = (char)_Locale_toupper(_M_ctype, *first); 79 return last; 80 } 81 82 const char* 83 ctype_byname<char>::do_tolower(char* first, const char* last) const { 84 for ( ; first != last ; ++first) 85 *first = (char)_Locale_tolower(_M_ctype, *first); 86 return last; 87 } 88 89 90 // Some helper functions used in ctype<>::scan_is and scan_is_not. 91 #if !defined (_STLP_NO_WCHAR_T) 92 93 _STLP_MOVE_TO_PRIV_NAMESPACE 94 95 // ctype_byname<wchar_t> 96 97 struct _Ctype_byname_w_is_mask : public unary_function<wchar_t, bool> { 98 _Locale_mask_t M; 99 _Locale_ctype* M_ctp; 100 101 _Ctype_byname_w_is_mask(_Locale_mask_t m, _Locale_ctype* c) 102 : M(m), M_ctp(c) {} 103 bool operator()(wchar_t c) const 104 { return _WLocale_ctype(M_ctp, c, M) != 0; } 105 }; 106 107 _STLP_MOVE_TO_STD_NAMESPACE 108 109 #if defined (__DMC__) 110 _STLP_DECLSPEC 111 #endif 112 ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs) 113 : ctype<wchar_t>(refs) { 114 if (!name) 115 locale::_M_throw_on_null_name(); 116 117 int __err_code; 118 char buf[_Locale_MAX_SIMPLE_NAME]; 119 _M_ctype = _STLP_PRIV __acquire_ctype(name, buf, 0, &__err_code); 120 if (!_M_ctype) 121 locale::_M_throw_on_creation_failure(__err_code, name, "ctype"); 122 } 123 124 ctype_byname<wchar_t>::~ctype_byname() 125 { _STLP_PRIV __release_ctype(_M_ctype); } 126 127 bool ctype_byname<wchar_t>::do_is(ctype_base::mask m, wchar_t c) const 128 { return _WLocale_ctype(_M_ctype, c, (_Locale_mask_t)m) != 0; } 129 130 const wchar_t* 131 ctype_byname<wchar_t>::do_is(const wchar_t* low, const wchar_t* high, 132 ctype_base::mask * m) const { 133 _Locale_mask_t all_bits = _Locale_mask_t(ctype_base::space | 134 ctype_base::print | 135 ctype_base::cntrl | 136 ctype_base::upper | 137 ctype_base::lower | 138 ctype_base::alpha | 139 ctype_base::digit | 140 ctype_base::punct | 141 ctype_base::xdigit); 142 143 for ( ; low < high; ++low, ++m) 144 *m = ctype_base::mask (_WLocale_ctype(_M_ctype, *low, all_bits)); 145 return high; 146 } 147 148 const wchar_t* 149 ctype_byname<wchar_t> 150 ::do_scan_is(ctype_base::mask m, const wchar_t* low, const wchar_t* high) const 151 { return find_if(low, high, _STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype)); } 152 153 const wchar_t* 154 ctype_byname<wchar_t> 155 ::do_scan_not(ctype_base::mask m, const wchar_t* low, const wchar_t* high) const 156 { return find_if(low, high, not1(_STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype))); } 157 158 wchar_t ctype_byname<wchar_t>::do_toupper(wchar_t c) const 159 { return _WLocale_toupper(_M_ctype, c); } 160 161 const wchar_t* 162 ctype_byname<wchar_t>::do_toupper(wchar_t* low, const wchar_t* high) const { 163 for ( ; low < high; ++low) 164 *low = _WLocale_toupper(_M_ctype, *low); 165 return high; 166 } 167 168 wchar_t ctype_byname<wchar_t>::do_tolower(wchar_t c) const 169 { return _WLocale_tolower(_M_ctype, c); } 170 171 const wchar_t* 172 ctype_byname<wchar_t>::do_tolower(wchar_t* low, const wchar_t* high) const { 173 for ( ; low < high; ++low) 174 *low = _WLocale_tolower(_M_ctype, *low); 175 return high; 176 } 177 178 #endif /* WCHAR_T */ 179 180 // collate_byname<char> 181 #if defined (__DMC__) 182 _STLP_DECLSPEC 183 #endif 184 collate_byname<char>::collate_byname(const char* name, size_t refs) 185 : collate<char>(refs) { 186 if (!name) 187 locale::_M_throw_on_null_name(); 188 189 int __err_code; 190 char buf[_Locale_MAX_SIMPLE_NAME]; 191 _M_collate = _STLP_PRIV __acquire_collate(name, buf, 0, &__err_code); 192 if (!_M_collate) 193 locale::_M_throw_on_creation_failure(__err_code, name, "collate"); 194 } 195 196 collate_byname<char>::~collate_byname() 197 { _STLP_PRIV __release_collate(_M_collate); } 198 199 int collate_byname<char>::do_compare(const char* __low1, 200 const char* __high1, 201 const char* __low2, 202 const char* __high2) const { 203 return _Locale_strcmp(_M_collate, 204 __low1, __high1 - __low1, 205 __low2, __high2 - __low2); 206 } 207 208 collate_byname<char>::string_type 209 collate_byname<char>::do_transform(const char* low, const char* high) const { 210 if (low == high) 211 return string_type(); 212 213 size_t n = _Locale_strxfrm(_M_collate, NULL, 0, low, high - low); 214 215 // NOT PORTABLE. What we're doing relies on internal details of the 216 // string implementation. (Contiguity of string elements and presence 217 // of trailing zero.) 218 string_type buf(n, 0); 219 _Locale_strxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low); 220 return buf; 221 } 222 223 224 #if !defined (_STLP_NO_WCHAR_T) 225 226 // collate_byname<wchar_t> 227 228 #if defined (__DMC__) 229 _STLP_DECLSPEC 230 #endif 231 collate_byname<wchar_t>::collate_byname(const char* name, size_t refs) 232 : collate<wchar_t>(refs) { 233 if (!name) 234 locale::_M_throw_on_null_name(); 235 236 int __err_code; 237 char buf[_Locale_MAX_SIMPLE_NAME]; 238 _M_collate = _STLP_PRIV __acquire_collate(name, buf, 0, &__err_code); 239 if (!_M_collate) 240 locale::_M_throw_on_creation_failure(__err_code, name, "collate"); 241 } 242 243 collate_byname<wchar_t>::~collate_byname() 244 { _STLP_PRIV __release_collate(_M_collate); } 245 246 int collate_byname<wchar_t>::do_compare(const wchar_t* low1, 247 const wchar_t* high1, 248 const wchar_t* low2, 249 const wchar_t* high2) const { 250 return _WLocale_strcmp(_M_collate, 251 low1, high1 - low1, 252 low2, high2 - low2); 253 } 254 255 collate_byname<wchar_t>::string_type 256 collate_byname<wchar_t>::do_transform(const wchar_t* low, 257 const wchar_t* high) const { 258 if (low == high) 259 return string_type(); 260 261 size_t n = _WLocale_strxfrm(_M_collate, NULL, 0, low, high - low); 262 263 // NOT PORTABLE. What we're doing relies on internal details of the 264 // string implementation. (Contiguity of string elements and presence 265 // of trailing zero.) 266 string_type buf(n, 0); 267 _WLocale_strxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low); 268 return buf; 269 } 270 271 #endif /* _STLP_NO_WCHAR_T */ 272 273 //---------------------------------------------------------------------- 274 // codecvt_byname<char> 275 276 codecvt_byname<char, char, mbstate_t> 277 ::codecvt_byname(const char* name, size_t refs) 278 : codecvt<char, char, mbstate_t>(refs) { 279 if (!name) 280 locale::_M_throw_on_null_name(); 281 } 282 283 codecvt_byname<char, char, mbstate_t>::~codecvt_byname() {} 284 285 286 #if !defined (_STLP_NO_WCHAR_T) 287 288 //---------------------------------------------------------------------- 289 // codecvt_byname<wchar_t> 290 codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname(const char* name, size_t refs) 291 : codecvt<wchar_t, char, mbstate_t>(refs) { 292 if (!name) 293 locale::_M_throw_on_null_name(); 294 295 int __err_code; 296 char buf[_Locale_MAX_SIMPLE_NAME]; 297 _M_codecvt = _STLP_PRIV __acquire_codecvt(name, buf, 0, &__err_code); 298 if (!_M_codecvt) 299 locale::_M_throw_on_creation_failure(__err_code, name, "ctype"); 300 } 301 302 codecvt_byname<wchar_t, char, mbstate_t>::~codecvt_byname() 303 { _STLP_PRIV __release_codecvt(_M_codecvt); } 304 305 codecvt<wchar_t, char, mbstate_t>::result 306 codecvt_byname<wchar_t, char, mbstate_t>::do_out(state_type& state, 307 const intern_type* from, 308 const intern_type* from_end, 309 const intern_type*& from_next, 310 extern_type* to, 311 extern_type* to_limit, 312 extern_type*& to_next) const { 313 while (from != from_end && to != to_limit) { 314 size_t chars_stored = _WLocale_wctomb(_M_codecvt, 315 to, to_limit - to, *from, 316 &state); 317 if (chars_stored == (size_t) -1) { 318 from_next = from; 319 to_next = to; 320 return error; 321 } 322 else if (chars_stored == (size_t) -2) { 323 from_next = from; 324 to_next = to; 325 return partial; 326 } 327 328 ++from; 329 to += chars_stored; 330 } 331 332 from_next = from; 333 to_next = to; 334 return ok; 335 } 336 337 codecvt<wchar_t, char, mbstate_t>::result 338 codecvt_byname<wchar_t, char, mbstate_t>::do_in(state_type& state, 339 const extern_type* from, 340 const extern_type* from_end, 341 const extern_type*& from_next, 342 intern_type* to, 343 intern_type* to_end, 344 intern_type*& to_next) const { 345 while (from != from_end && to != to_end) { 346 size_t chars_read = _WLocale_mbtowc(_M_codecvt, 347 to, from, from_end - from, 348 &state); 349 if (chars_read == (size_t) -1) { 350 from_next = from; 351 to_next = to; 352 return error; 353 } 354 355 if (chars_read == (size_t) -2) { 356 from_next = from; 357 to_next = to; 358 return partial; 359 } 360 361 from += chars_read; 362 to++; 363 } 364 365 from_next = from; 366 to_next = to; 367 return ok; 368 } 369 370 codecvt<wchar_t, char, mbstate_t>::result 371 codecvt_byname<wchar_t, char, mbstate_t>::do_unshift(state_type& state, 372 extern_type* to, 373 extern_type* to_limit, 374 extern_type*& to_next) const { 375 to_next = to; 376 size_t result = _WLocale_unshift(_M_codecvt, &state, 377 to, to_limit - to, &to_next); 378 if (result == (size_t) -1) 379 return error; 380 else if (result == (size_t) -2) 381 return partial; 382 else 383 # if defined (__ISCPP__) 384 return /*to_next == to ? noconv :*/ ok; 385 # else 386 return to_next == to ? noconv : ok; 387 # endif 388 } 389 390 int 391 codecvt_byname<wchar_t, char, mbstate_t>::do_encoding() const _STLP_NOTHROW { 392 if (_WLocale_is_stateless(_M_codecvt)) { 393 int max_width = _WLocale_mb_cur_max(_M_codecvt); 394 int min_width = _WLocale_mb_cur_min(_M_codecvt); 395 return min_width == max_width ? min_width : 0; 396 } 397 else 398 return -1; 399 } 400 401 bool 402 codecvt_byname<wchar_t, char, mbstate_t>::do_always_noconv() const _STLP_NOTHROW 403 { return false; } 404 405 int 406 codecvt_byname<wchar_t, char, mbstate_t>::do_length(state_type& state, 407 const extern_type* from, 408 const extern_type* end, 409 size_t mx) const { 410 size_t __count = 0; 411 while (from != end && mx--) { 412 intern_type __dummy; 413 size_t chars_read = _WLocale_mbtowc(_M_codecvt, 414 &__dummy, from, end - from, 415 &state); 416 if ((chars_read == (size_t) -1) || (chars_read == (size_t) -2)) // error or partial 417 break; 418 __count += chars_read; 419 from += chars_read; 420 } 421 return int(__count); 422 } 423 424 int 425 codecvt_byname<wchar_t, char, mbstate_t>::do_max_length() const _STLP_NOTHROW 426 { return _WLocale_mb_cur_max(_M_codecvt); } 427 #endif 428 429 // numpunct_byname<char> 430 numpunct_byname<char>::numpunct_byname(const char* name, size_t refs) 431 : numpunct<char>(refs) { 432 if (!name) 433 locale::_M_throw_on_null_name(); 434 435 int __err_code; 436 char buf[_Locale_MAX_SIMPLE_NAME]; 437 _M_numeric = _STLP_PRIV __acquire_numeric(name, buf, 0, &__err_code); 438 if (!_M_numeric) 439 locale::_M_throw_on_creation_failure(__err_code, name, "numpunct"); 440 } 441 442 numpunct_byname<char>::~numpunct_byname() 443 { _STLP_PRIV __release_numeric(_M_numeric); } 444 445 char numpunct_byname<char>::do_decimal_point() const 446 { return _Locale_decimal_point(_M_numeric); } 447 448 char numpunct_byname<char>::do_thousands_sep() const 449 { return _Locale_thousands_sep(_M_numeric); } 450 451 string numpunct_byname<char>::do_grouping() const { 452 const char * __grouping = _Locale_grouping(_M_numeric); 453 if (__grouping != NULL && __grouping[0] == CHAR_MAX) 454 __grouping = ""; 455 return __grouping; 456 } 457 458 string numpunct_byname<char>::do_truename() const 459 { return _Locale_true(_M_numeric); } 460 461 string numpunct_byname<char>::do_falsename() const 462 { return _Locale_false(_M_numeric); } 463 464 //---------------------------------------------------------------------- 465 // numpunct<wchar_t> 466 467 #if !defined (_STLP_NO_WCHAR_T) 468 469 // numpunct_byname<wchar_t> 470 471 numpunct_byname<wchar_t>::numpunct_byname(const char* name, size_t refs) 472 : numpunct<wchar_t>(refs) { 473 if (!name) 474 locale::_M_throw_on_null_name(); 475 476 int __err_code; 477 char buf[_Locale_MAX_SIMPLE_NAME]; 478 _M_numeric = _STLP_PRIV __acquire_numeric(name, buf, 0, &__err_code); 479 if (!_M_numeric) 480 locale::_M_throw_on_creation_failure(__err_code, name, "numpunct"); 481 } 482 483 numpunct_byname<wchar_t>::~numpunct_byname() 484 { _STLP_PRIV __release_numeric(_M_numeric); } 485 486 wchar_t numpunct_byname<wchar_t>::do_decimal_point() const 487 { return _WLocale_decimal_point(_M_numeric); } 488 489 wchar_t numpunct_byname<wchar_t>::do_thousands_sep() const 490 { return _WLocale_thousands_sep(_M_numeric); } 491 492 string numpunct_byname<wchar_t>::do_grouping() const { 493 const char * __grouping = _Locale_grouping(_M_numeric); 494 if (__grouping != NULL && __grouping[0] == CHAR_MAX) 495 __grouping = ""; 496 return __grouping; 497 } 498 499 wstring numpunct_byname<wchar_t>::do_truename() const { 500 wchar_t buf[16]; 501 return _WLocale_true(_M_numeric, _STLP_ARRAY_AND_SIZE(buf)); 502 } 503 504 wstring numpunct_byname<wchar_t>::do_falsename() const { 505 wchar_t buf[16]; 506 return _WLocale_false(_M_numeric, _STLP_ARRAY_AND_SIZE(buf)); 507 } 508 509 #endif 510 511 _STLP_MOVE_TO_PRIV_NAMESPACE 512 513 static void _Init_monetary_formats(money_base::pattern& pos_format, 514 money_base::pattern& neg_format, 515 _Locale_monetary * monetary) { 516 switch (_Locale_p_sign_posn(monetary)) { 517 case 0: // Parentheses surround the quantity and currency symbol 518 case 1: // The sign string precedes the quantity and currency symbol 519 pos_format.field[0] = (char) money_base::sign; 520 if (_Locale_p_cs_precedes(monetary)) { 521 // 1 if currency symbol precedes a positive value 522 pos_format.field[1] = (char) money_base::symbol; 523 if (_Locale_p_sep_by_space(monetary)) { 524 // a space separates currency symbol from a positive value. 525 pos_format.field[2] = (char) money_base::space; 526 pos_format.field[3] = (char) money_base::value; 527 } else { 528 // a space not separates currency symbol from a positive value. 529 pos_format.field[2] = (char) money_base::value; 530 pos_format.field[3] = (char) money_base::none; 531 } 532 } else { 533 // 0 if currency symbol succeeds a positive value 534 pos_format.field[1] = (char) money_base::value; 535 if (_Locale_p_sep_by_space(monetary)) { 536 // a space separates currency symbol from a positive value. 537 pos_format.field[2] = (char) money_base::space; 538 pos_format.field[3] = (char) money_base::symbol; 539 } else { 540 // a space not separates currency symbol from a positive value. 541 pos_format.field[2] = (char) money_base::symbol; 542 pos_format.field[3] = (char) money_base::none; 543 } 544 } 545 break; 546 case 2: // The sign string succeeds the quantity and currency symbol. 547 if (_Locale_p_cs_precedes(monetary)) { 548 // 1 if currency symbol precedes a positive value 549 pos_format.field[0] = (char) money_base::symbol; 550 if (_Locale_p_sep_by_space(monetary)) { 551 // a space separates currency symbol from a positive value. 552 pos_format.field[1] = (char) money_base::space; 553 pos_format.field[2] = (char) money_base::value; 554 pos_format.field[3] = (char) money_base::sign; 555 } else { 556 // a space not separates currency symbol from a positive value. 557 pos_format.field[1] = (char) money_base::value; 558 pos_format.field[2] = (char) money_base::sign; 559 pos_format.field[3] = (char) money_base::none; 560 } 561 } else { 562 // 0 if currency symbol succeeds a positive value 563 pos_format.field[0] = (char) money_base::value; 564 if (_Locale_p_sep_by_space(monetary)) { 565 // a space separates currency symbol from a positive value. 566 pos_format.field[1] = (char) money_base::space; 567 pos_format.field[2] = (char) money_base::symbol; 568 pos_format.field[3] = (char) money_base::sign; 569 } else { 570 // a space not separates currency symbol from a positive value. 571 pos_format.field[1] = (char) money_base::symbol; 572 pos_format.field[2] = (char) money_base::sign; 573 pos_format.field[3] = (char) money_base::none; 574 } 575 } 576 break; 577 case 3: // The sign string immediately precedes the currency symbol. 578 if (_Locale_p_cs_precedes(monetary)) { 579 // 1 if currency symbol precedes a positive value 580 pos_format.field[0] = (char) money_base::sign; 581 pos_format.field[1] = (char) money_base::symbol; 582 if (_Locale_p_sep_by_space(monetary)) { 583 // a space separates currency symbol from a positive value. 584 pos_format.field[2] = (char) money_base::space; 585 pos_format.field[3] = (char) money_base::value; 586 } else { 587 // a space not separates currency symbol from a positive value. 588 pos_format.field[2] = (char) money_base::value; 589 pos_format.field[3] = (char) money_base::none; 590 } 591 } else { 592 // 0 if currency symbol succeeds a positive value 593 pos_format.field[0] = (char) money_base::value; 594 pos_format.field[1] = (char) money_base::sign; 595 pos_format.field[2] = (char) money_base::symbol; 596 pos_format.field[3] = (char) money_base::none; 597 } 598 break; 599 case 4: // The sign string immediately succeeds the currency symbol. 600 if (_Locale_p_cs_precedes(monetary)) { 601 // 1 if currency symbol precedes a positive value 602 pos_format.field[0] = (char) money_base::symbol; 603 pos_format.field[1] = (char) money_base::sign; 604 pos_format.field[2] = (char) money_base::value; 605 pos_format.field[3] = (char) money_base::none; 606 } else { 607 // 0 if currency symbol succeeds a positive value 608 pos_format.field[0] = (char) money_base::value; 609 if (_Locale_p_sep_by_space(monetary)) { 610 // a space separates currency symbol from a positive value. 611 pos_format.field[1] = (char) money_base::space; 612 pos_format.field[2] = (char) money_base::symbol; 613 pos_format.field[3] = (char) money_base::sign; 614 } else { 615 // a space not separates currency symbol from a positive value. 616 pos_format.field[1] = (char) money_base::symbol; 617 pos_format.field[2] = (char) money_base::sign; 618 pos_format.field[3] = (char) money_base::none; 619 } 620 } 621 break; 622 default: // Default C++ Standard format 623 pos_format.field[0] = (char) money_base::symbol; 624 pos_format.field[1] = (char) money_base::sign; 625 pos_format.field[2] = (char) money_base::none; 626 pos_format.field[3] = (char) money_base::value; 627 break; 628 } 629 630 switch (_Locale_n_sign_posn(monetary)) { 631 case 0: // Parentheses surround the quantity and currency symbol 632 case 1: // The sign string precedes the quantity and currency symbol 633 neg_format.field[0] = (char) money_base::sign; 634 if (_Locale_n_cs_precedes(monetary)) { 635 // 1 if currency symbol precedes a negative value 636 neg_format.field[1] = (char) money_base::symbol; 637 if (_Locale_n_sep_by_space(monetary)) { 638 // a space separates currency symbol from a negative value. 639 neg_format.field[2] = (char) money_base::space; 640 neg_format.field[3] = (char) money_base::value; 641 } else { 642 // a space not separates currency symbol from a negative value. 643 neg_format.field[2] = (char) money_base::value; 644 neg_format.field[3] = (char) money_base::none; 645 } 646 } else { 647 // 0 if currency symbol succeeds a negative value 648 neg_format.field[1] = (char) money_base::value; 649 if (_Locale_n_sep_by_space(monetary)) { 650 // a space separates currency symbol from a negative value. 651 neg_format.field[2] = (char) money_base::space; 652 neg_format.field[3] = (char) money_base::symbol; 653 } else { 654 // a space not separates currency symbol from a negative value. 655 neg_format.field[2] = (char) money_base::symbol; 656 neg_format.field[3] = (char) money_base::none; 657 } 658 } 659 break; 660 case 2: // The sign string succeeds the quantity and currency symbol. 661 if (_Locale_n_cs_precedes(monetary)) { 662 // 1 if currency symbol precedes a negative value 663 neg_format.field[0] = (char) money_base::symbol; 664 if (_Locale_n_sep_by_space(monetary)) { 665 // a space separates currency symbol from a negative value. 666 neg_format.field[1] = (char) money_base::space; 667 neg_format.field[2] = (char) money_base::value; 668 neg_format.field[3] = (char) money_base::sign; 669 } else { 670 // a space not separates currency symbol from a negative value. 671 neg_format.field[1] = (char) money_base::value; 672 neg_format.field[2] = (char) money_base::sign; 673 neg_format.field[3] = (char) money_base::none; 674 } 675 } else { 676 // 0 if currency symbol succeeds a negative value 677 neg_format.field[0] = (char) money_base::value; 678 if (_Locale_n_sep_by_space(monetary)) { 679 // a space separates currency symbol from a negative value. 680 neg_format.field[1] = (char) money_base::space; 681 neg_format.field[2] = (char) money_base::symbol; 682 neg_format.field[3] = (char) money_base::sign; 683 } else { 684 // a space not separates currency symbol from a negative value. 685 neg_format.field[1] = (char) money_base::symbol; 686 neg_format.field[2] = (char) money_base::sign; 687 neg_format.field[3] = (char) money_base::none; 688 } 689 } 690 break; 691 case 3: // The sign string immediately precedes the currency symbol. 692 if (_Locale_n_cs_precedes(monetary)) { 693 // 1 if currency symbol precedes a negative value 694 neg_format.field[0] = (char) money_base::sign; 695 neg_format.field[1] = (char) money_base::symbol; 696 if (_Locale_n_sep_by_space(monetary)) { 697 // a space separates currency symbol from a negative value. 698 neg_format.field[2] = (char) money_base::space; 699 neg_format.field[3] = (char) money_base::value; 700 } else { 701 // a space not separates currency symbol from a negative value. 702 neg_format.field[2] = (char) money_base::value; 703 neg_format.field[3] = (char) money_base::none; 704 } 705 } else { 706 // 0 if currency symbol succeeds a negative value 707 neg_format.field[0] = (char) money_base::value; 708 neg_format.field[1] = (char) money_base::sign; 709 neg_format.field[2] = (char) money_base::symbol; 710 neg_format.field[3] = (char) money_base::none; 711 } 712 break; 713 case 4: // The sign string immediately succeeds the currency symbol. 714 if (_Locale_n_cs_precedes(monetary)) { 715 // 1 if currency symbol precedes a negative value 716 neg_format.field[0] = (char) money_base::symbol; 717 neg_format.field[1] = (char) money_base::sign; 718 neg_format.field[2] = (char) money_base::none; 719 neg_format.field[3] = (char) money_base::value; 720 } else { 721 // 0 if currency symbol succeeds a negative value 722 neg_format.field[0] = (char) money_base::value; 723 if (_Locale_n_sep_by_space(monetary)) { 724 // a space separates currency symbol from a negative value. 725 neg_format.field[1] = (char) money_base::space; 726 neg_format.field[2] = (char) money_base::symbol; 727 neg_format.field[3] = (char) money_base::sign; 728 } else { 729 // a space not separates currency symbol from a negative value. 730 neg_format.field[1] = (char) money_base::symbol; 731 neg_format.field[2] = (char) money_base::sign; 732 neg_format.field[3] = (char) money_base::none; 733 } 734 } 735 break; 736 default: // Default C++ Standard format 737 neg_format.field[0] = (char) money_base::symbol; 738 neg_format.field[1] = (char) money_base::sign; 739 neg_format.field[2] = (char) money_base::none; 740 neg_format.field[3] = (char) money_base::value; 741 break; 742 } 743 } 744 745 // international variant of monetary 746 747 /* 748 * int_curr_symbol 749 * 750 * The international currency symbol. The operand is a four-character 751 * string, with the first three characters containing the alphabetic 752 * international currency symbol in accordance with those specified 753 * in the ISO 4217 specification. The fourth character is the character used 754 * to separate the international currency symbol from the monetary quantity. 755 * 756 * (http://www.opengroup.org/onlinepubs/7990989775/xbd/locale.html) 757 */ 758 759 /* 760 * Standards are unclear in the usage of international currency 761 * and monetary formats. 762 * But I am expect that international currency symbol should be the first 763 * (not depends upon where currency symbol situated in the national 764 * format). 765 * 766 * If this isn't so, let's see: 767 * 1 234.56 RUR 768 * GBP 1,234.56 769 * USD 1,234.56 770 * The situation really is worse than you see above: 771 * RUR typed wrong here---it prints '1 234.56 RUR ' (see space after RUR). 772 * This is due to intl_fmp.curr_symbol() == "RUR ". (see reference in comments 773 * above). 774 * 775 */ 776 777 static void _Init_monetary_formats_int(money_base::pattern& pos_format, 778 money_base::pattern& neg_format, 779 _Locale_monetary * monetary) 780 { 781 782 switch (_Locale_p_sign_posn(monetary)) { 783 case 0: // Parentheses surround the quantity and currency symbol 784 case 1: // The sign string precedes the quantity and currency symbol 785 pos_format.field[0] = (char) money_base::symbol; 786 pos_format.field[1] = (char) money_base::sign; 787 pos_format.field[2] = (char) money_base::value; 788 pos_format.field[3] = (char) money_base::none; 789 break; 790 case 2: // The sign string succeeds the quantity and currency symbol. 791 pos_format.field[0] = (char) money_base::symbol; 792 pos_format.field[1] = (char) money_base::value; 793 pos_format.field[2] = (char) money_base::sign; 794 pos_format.field[3] = (char) money_base::none; 795 break; 796 case 3: // The sign string immediately precedes the currency symbol. 797 case 4: // The sign string immediately succeeds the currency symbol. 798 pos_format.field[0] = (char) money_base::symbol; 799 if (_Locale_p_cs_precedes(monetary)) { 800 // 1 if currency symbol precedes a positive value 801 pos_format.field[1] = (char) money_base::sign; 802 pos_format.field[2] = (char) money_base::value; 803 } else { 804 // 0 if currency symbol succeeds a positive value 805 pos_format.field[1] = (char) money_base::value; 806 pos_format.field[2] = (char) money_base::sign; 807 } 808 pos_format.field[3] = (char) money_base::none; 809 break; 810 default: // Default C++ Standard format 811 pos_format.field[0] = (char) money_base::symbol; 812 pos_format.field[1] = (char) money_base::sign; 813 pos_format.field[2] = (char) money_base::none; 814 pos_format.field[3] = (char) money_base::value; 815 break; 816 } 817 818 819 switch (_Locale_n_sign_posn(monetary)) { 820 case 0: // Parentheses surround the quantity and currency symbol 821 case 1: // The sign string precedes the quantity and currency symbol 822 neg_format.field[0] = (char) money_base::symbol; 823 neg_format.field[1] = (char) money_base::sign; 824 neg_format.field[2] = (char) money_base::value; 825 neg_format.field[3] = (char) money_base::none; 826 break; 827 case 2: // The sign string succeeds the quantity and currency symbol. 828 neg_format.field[0] = (char) money_base::symbol; 829 neg_format.field[1] = (char) money_base::value; 830 neg_format.field[2] = (char) money_base::sign; 831 neg_format.field[3] = (char) money_base::none; 832 break; 833 case 3: // The sign string immediately precedes the currency symbol. 834 case 4: // The sign string immediately succeeds the currency symbol. 835 neg_format.field[0] = (char) money_base::symbol; 836 if (_Locale_n_cs_precedes(monetary)) { 837 // 1 if currency symbol precedes a negative value 838 neg_format.field[1] = (char) money_base::sign; 839 neg_format.field[2] = (char) money_base::value; 840 } else { 841 // 0 if currency symbol succeeds a negative value 842 neg_format.field[1] = (char) money_base::value; 843 neg_format.field[2] = (char) money_base::sign; 844 } 845 neg_format.field[3] = (char) money_base::none; 846 break; 847 default: // Default C++ Standard format 848 neg_format.field[0] = (char) money_base::symbol; 849 neg_format.field[1] = (char) money_base::sign; 850 neg_format.field[2] = (char) money_base::none; 851 neg_format.field[3] = (char) money_base::value; 852 break; 853 } 854 } 855 856 _STLP_MOVE_TO_STD_NAMESPACE 857 858 // 859 // moneypunct_byname<> 860 // 861 moneypunct_byname<char, true>::moneypunct_byname(const char * name, 862 size_t refs) 863 : moneypunct<char, true>(refs) { 864 if (!name) 865 locale::_M_throw_on_null_name(); 866 867 int __err_code; 868 char buf[_Locale_MAX_SIMPLE_NAME]; 869 _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code); 870 if (!_M_monetary) 871 locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct"); 872 873 _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary); 874 } 875 876 moneypunct_byname<char, true>::moneypunct_byname(_Locale_monetary *__mon) 877 : _M_monetary(__mon) { 878 _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary); 879 } 880 881 moneypunct_byname<char, true>::~moneypunct_byname() 882 { _STLP_PRIV __release_monetary(_M_monetary); } 883 884 char moneypunct_byname<char, true>::do_decimal_point() const 885 { return _Locale_mon_decimal_point(_M_monetary); } 886 887 char moneypunct_byname<char, true>::do_thousands_sep() const 888 { return _Locale_mon_thousands_sep(_M_monetary); } 889 890 string moneypunct_byname<char, true>::do_grouping() const 891 { return _Locale_mon_grouping(_M_monetary); } 892 893 string moneypunct_byname<char, true>::do_curr_symbol() const 894 { return _Locale_int_curr_symbol(_M_monetary); } 895 896 string moneypunct_byname<char, true>::do_positive_sign() const 897 { return _Locale_positive_sign(_M_monetary); } 898 899 string moneypunct_byname<char, true>::do_negative_sign() const 900 { return _Locale_negative_sign(_M_monetary); } 901 902 int moneypunct_byname<char, true>::do_frac_digits() const 903 { return _Locale_int_frac_digits(_M_monetary); } 904 905 moneypunct_byname<char, false>::moneypunct_byname(const char * name, 906 size_t refs) 907 : moneypunct<char, false>(refs) { 908 if (!name) 909 locale::_M_throw_on_null_name(); 910 911 int __err_code; 912 char buf[_Locale_MAX_SIMPLE_NAME]; 913 _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code); 914 if (!_M_monetary) 915 locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct"); 916 917 _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary); 918 } 919 920 moneypunct_byname<char, false>::moneypunct_byname(_Locale_monetary *__mon) 921 : _M_monetary(__mon) { 922 _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary); 923 } 924 925 moneypunct_byname<char, false>::~moneypunct_byname() 926 { _STLP_PRIV __release_monetary(_M_monetary); } 927 928 char moneypunct_byname<char, false>::do_decimal_point() const 929 { return _Locale_mon_decimal_point(_M_monetary); } 930 931 char moneypunct_byname<char, false>::do_thousands_sep() const 932 { return _Locale_mon_thousands_sep(_M_monetary); } 933 934 string moneypunct_byname<char, false>::do_grouping() const 935 { return _Locale_mon_grouping(_M_monetary); } 936 937 string moneypunct_byname<char, false>::do_curr_symbol() const 938 { return _Locale_currency_symbol(_M_monetary); } 939 940 string moneypunct_byname<char, false>::do_positive_sign() const 941 { return _Locale_positive_sign(_M_monetary); } 942 943 string moneypunct_byname<char, false>::do_negative_sign() const 944 { return _Locale_negative_sign(_M_monetary); } 945 946 int moneypunct_byname<char, false>::do_frac_digits() const 947 { return _Locale_frac_digits(_M_monetary); } 948 949 // 950 // moneypunct_byname<wchar_t> 951 // 952 #if !defined (_STLP_NO_WCHAR_T) 953 954 moneypunct_byname<wchar_t, true>::moneypunct_byname(const char * name, 955 size_t refs) 956 : moneypunct<wchar_t, true>(refs) { 957 if (!name) 958 locale::_M_throw_on_null_name(); 959 960 int __err_code; 961 char buf[_Locale_MAX_SIMPLE_NAME]; 962 _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code); 963 if (!_M_monetary) 964 locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct"); 965 966 _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary); 967 } 968 969 moneypunct_byname<wchar_t, true>::moneypunct_byname(_Locale_monetary *__mon) 970 : _M_monetary(__mon) { 971 _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary); 972 } 973 974 moneypunct_byname<wchar_t, true>::~moneypunct_byname() 975 { _STLP_PRIV __release_monetary(_M_monetary); } 976 977 wchar_t moneypunct_byname<wchar_t, true>::do_decimal_point() const 978 { return _Locale_mon_decimal_point(_M_monetary); } 979 980 wchar_t moneypunct_byname<wchar_t, true>::do_thousands_sep() const 981 { return _Locale_mon_thousands_sep(_M_monetary); } 982 983 string moneypunct_byname<wchar_t, true>::do_grouping() const 984 { return _Locale_mon_grouping(_M_monetary); } 985 986 inline wstring __do_widen (string const& str) { 987 #if defined (_STLP_NO_MEMBER_TEMPLATES) || defined (_STLP_MSVC) 988 wstring::_Reserve_t __Reserve; 989 size_t __size = str.size(); 990 wstring result(__Reserve, __size); 991 copy(str.begin(), str.end(), result.begin()); 992 #else 993 wstring result(str.begin(), str.end()); 994 #endif 995 return result; 996 } 997 998 wstring moneypunct_byname<wchar_t, true>::do_curr_symbol() const 999 { wchar_t buf[16]; return _WLocale_int_curr_symbol(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); } 1000 1001 wstring moneypunct_byname<wchar_t, true>::do_positive_sign() const 1002 { wchar_t buf[16]; return _WLocale_positive_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); } 1003 1004 wstring moneypunct_byname<wchar_t, true>::do_negative_sign() const 1005 { wchar_t buf[16]; return _WLocale_negative_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); } 1006 1007 int moneypunct_byname<wchar_t, true>::do_frac_digits() const 1008 { return _Locale_int_frac_digits(_M_monetary); } 1009 1010 moneypunct_byname<wchar_t, false>::moneypunct_byname(const char * name, 1011 size_t refs) 1012 : moneypunct<wchar_t, false>(refs) { 1013 if (!name) 1014 locale::_M_throw_on_null_name() ; 1015 1016 int __err_code; 1017 char buf[_Locale_MAX_SIMPLE_NAME]; 1018 _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code); 1019 if (!_M_monetary) 1020 locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct"); 1021 1022 _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary); 1023 } 1024 1025 moneypunct_byname<wchar_t, false>::moneypunct_byname(_Locale_monetary *__mon) 1026 : _M_monetary(__mon) { 1027 _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary); 1028 } 1029 1030 moneypunct_byname<wchar_t, false>::~moneypunct_byname() 1031 { _STLP_PRIV __release_monetary(_M_monetary); } 1032 1033 wchar_t moneypunct_byname<wchar_t, false>::do_decimal_point() const 1034 { return _Locale_mon_decimal_point(_M_monetary); } 1035 1036 wchar_t moneypunct_byname<wchar_t, false>::do_thousands_sep() const 1037 { return _Locale_mon_thousands_sep(_M_monetary); } 1038 1039 string moneypunct_byname<wchar_t, false>::do_grouping() const 1040 { return _Locale_mon_grouping(_M_monetary); } 1041 1042 wstring moneypunct_byname<wchar_t, false>::do_curr_symbol() const 1043 { wchar_t buf[16]; return _WLocale_currency_symbol(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); } 1044 1045 wstring moneypunct_byname<wchar_t, false>::do_positive_sign() const 1046 { wchar_t buf[16]; return _WLocale_positive_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); } 1047 1048 wstring moneypunct_byname<wchar_t, false>::do_negative_sign() const 1049 { wchar_t buf[16]; return _WLocale_negative_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); } 1050 1051 int moneypunct_byname<wchar_t, false>::do_frac_digits() const 1052 { return _Locale_frac_digits(_M_monetary); } 1053 1054 #endif 1055 1056 _STLP_END_NAMESPACE 1057 1058