1 // Locale support -*- C++ -*- 2 3 // Copyright (C) 1997-2013 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 3, 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 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file bits/locale_facets.tcc 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{locale} 28 */ 29 30 #ifndef _LOCALE_FACETS_TCC 31 #define _LOCALE_FACETS_TCC 1 32 33 #pragma GCC system_header 34 35 namespace std _GLIBCXX_VISIBILITY(default) 36 { 37 _GLIBCXX_BEGIN_NAMESPACE_VERSION 38 39 // Routine to access a cache for the facet. If the cache didn't 40 // exist before, it gets constructed on the fly. 41 template<typename _Facet> 42 struct __use_cache 43 { 44 const _Facet* 45 operator() (const locale& __loc) const; 46 }; 47 48 // Specializations. 49 template<typename _CharT> 50 struct __use_cache<__numpunct_cache<_CharT> > 51 { 52 const __numpunct_cache<_CharT>* 53 operator() (const locale& __loc) const 54 { 55 const size_t __i = numpunct<_CharT>::id._M_id(); 56 const locale::facet** __caches = __loc._M_impl->_M_caches; 57 if (!__caches[__i]) 58 { 59 __numpunct_cache<_CharT>* __tmp = 0; 60 __try 61 { 62 __tmp = new __numpunct_cache<_CharT>; 63 __tmp->_M_cache(__loc); 64 } 65 __catch(...) 66 { 67 delete __tmp; 68 __throw_exception_again; 69 } 70 __loc._M_impl->_M_install_cache(__tmp, __i); 71 } 72 return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]); 73 } 74 }; 75 76 template<typename _CharT> 77 void 78 __numpunct_cache<_CharT>::_M_cache(const locale& __loc) 79 { 80 _M_allocated = true; 81 82 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 83 84 char* __grouping = 0; 85 _CharT* __truename = 0; 86 _CharT* __falsename = 0; 87 __try 88 { 89 _M_grouping_size = __np.grouping().size(); 90 __grouping = new char[_M_grouping_size]; 91 __np.grouping().copy(__grouping, _M_grouping_size); 92 _M_grouping = __grouping; 93 _M_use_grouping = (_M_grouping_size 94 && static_cast<signed char>(_M_grouping[0]) > 0 95 && (_M_grouping[0] 96 != __gnu_cxx::__numeric_traits<char>::__max)); 97 98 _M_truename_size = __np.truename().size(); 99 __truename = new _CharT[_M_truename_size]; 100 __np.truename().copy(__truename, _M_truename_size); 101 _M_truename = __truename; 102 103 _M_falsename_size = __np.falsename().size(); 104 __falsename = new _CharT[_M_falsename_size]; 105 __np.falsename().copy(__falsename, _M_falsename_size); 106 _M_falsename = __falsename; 107 108 _M_decimal_point = __np.decimal_point(); 109 _M_thousands_sep = __np.thousands_sep(); 110 111 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 112 __ct.widen(__num_base::_S_atoms_out, 113 __num_base::_S_atoms_out 114 + __num_base::_S_oend, _M_atoms_out); 115 __ct.widen(__num_base::_S_atoms_in, 116 __num_base::_S_atoms_in 117 + __num_base::_S_iend, _M_atoms_in); 118 } 119 __catch(...) 120 { 121 delete [] __grouping; 122 delete [] __truename; 123 delete [] __falsename; 124 __throw_exception_again; 125 } 126 } 127 128 // Used by both numeric and monetary facets. 129 // Check to make sure that the __grouping_tmp string constructed in 130 // money_get or num_get matches the canonical grouping for a given 131 // locale. 132 // __grouping_tmp is parsed L to R 133 // 1,222,444 == __grouping_tmp of "\1\3\3" 134 // __grouping is parsed R to L 135 // 1,222,444 == __grouping of "\3" == "\3\3\3" 136 _GLIBCXX_PURE bool 137 __verify_grouping(const char* __grouping, size_t __grouping_size, 138 const string& __grouping_tmp) throw (); 139 140 _GLIBCXX_BEGIN_NAMESPACE_LDBL 141 142 template<typename _CharT, typename _InIter> 143 _InIter 144 num_get<_CharT, _InIter>:: 145 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, 146 ios_base::iostate& __err, string& __xtrc) const 147 { 148 typedef char_traits<_CharT> __traits_type; 149 typedef __numpunct_cache<_CharT> __cache_type; 150 __use_cache<__cache_type> __uc; 151 const locale& __loc = __io._M_getloc(); 152 const __cache_type* __lc = __uc(__loc); 153 const _CharT* __lit = __lc->_M_atoms_in; 154 char_type __c = char_type(); 155 156 // True if __beg becomes equal to __end. 157 bool __testeof = __beg == __end; 158 159 // First check for sign. 160 if (!__testeof) 161 { 162 __c = *__beg; 163 const bool __plus = __c == __lit[__num_base::_S_iplus]; 164 if ((__plus || __c == __lit[__num_base::_S_iminus]) 165 && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 166 && !(__c == __lc->_M_decimal_point)) 167 { 168 __xtrc += __plus ? '+' : '-'; 169 if (++__beg != __end) 170 __c = *__beg; 171 else 172 __testeof = true; 173 } 174 } 175 176 // Next, look for leading zeros. 177 bool __found_mantissa = false; 178 int __sep_pos = 0; 179 while (!__testeof) 180 { 181 if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 182 || __c == __lc->_M_decimal_point) 183 break; 184 else if (__c == __lit[__num_base::_S_izero]) 185 { 186 if (!__found_mantissa) 187 { 188 __xtrc += '0'; 189 __found_mantissa = true; 190 } 191 ++__sep_pos; 192 193 if (++__beg != __end) 194 __c = *__beg; 195 else 196 __testeof = true; 197 } 198 else 199 break; 200 } 201 202 // Only need acceptable digits for floating point numbers. 203 bool __found_dec = false; 204 bool __found_sci = false; 205 string __found_grouping; 206 if (__lc->_M_use_grouping) 207 __found_grouping.reserve(32); 208 const char_type* __lit_zero = __lit + __num_base::_S_izero; 209 210 if (!__lc->_M_allocated) 211 // "C" locale 212 while (!__testeof) 213 { 214 const int __digit = _M_find(__lit_zero, 10, __c); 215 if (__digit != -1) 216 { 217 __xtrc += '0' + __digit; 218 __found_mantissa = true; 219 } 220 else if (__c == __lc->_M_decimal_point 221 && !__found_dec && !__found_sci) 222 { 223 __xtrc += '.'; 224 __found_dec = true; 225 } 226 else if ((__c == __lit[__num_base::_S_ie] 227 || __c == __lit[__num_base::_S_iE]) 228 && !__found_sci && __found_mantissa) 229 { 230 // Scientific notation. 231 __xtrc += 'e'; 232 __found_sci = true; 233 234 // Remove optional plus or minus sign, if they exist. 235 if (++__beg != __end) 236 { 237 __c = *__beg; 238 const bool __plus = __c == __lit[__num_base::_S_iplus]; 239 if (__plus || __c == __lit[__num_base::_S_iminus]) 240 __xtrc += __plus ? '+' : '-'; 241 else 242 continue; 243 } 244 else 245 { 246 __testeof = true; 247 break; 248 } 249 } 250 else 251 break; 252 253 if (++__beg != __end) 254 __c = *__beg; 255 else 256 __testeof = true; 257 } 258 else 259 while (!__testeof) 260 { 261 // According to 22.2.2.1.2, p8-9, first look for thousands_sep 262 // and decimal_point. 263 if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 264 { 265 if (!__found_dec && !__found_sci) 266 { 267 // NB: Thousands separator at the beginning of a string 268 // is a no-no, as is two consecutive thousands separators. 269 if (__sep_pos) 270 { 271 __found_grouping += static_cast<char>(__sep_pos); 272 __sep_pos = 0; 273 } 274 else 275 { 276 // NB: __convert_to_v will not assign __v and will 277 // set the failbit. 278 __xtrc.clear(); 279 break; 280 } 281 } 282 else 283 break; 284 } 285 else if (__c == __lc->_M_decimal_point) 286 { 287 if (!__found_dec && !__found_sci) 288 { 289 // If no grouping chars are seen, no grouping check 290 // is applied. Therefore __found_grouping is adjusted 291 // only if decimal_point comes after some thousands_sep. 292 if (__found_grouping.size()) 293 __found_grouping += static_cast<char>(__sep_pos); 294 __xtrc += '.'; 295 __found_dec = true; 296 } 297 else 298 break; 299 } 300 else 301 { 302 const char_type* __q = 303 __traits_type::find(__lit_zero, 10, __c); 304 if (__q) 305 { 306 __xtrc += '0' + (__q - __lit_zero); 307 __found_mantissa = true; 308 ++__sep_pos; 309 } 310 else if ((__c == __lit[__num_base::_S_ie] 311 || __c == __lit[__num_base::_S_iE]) 312 && !__found_sci && __found_mantissa) 313 { 314 // Scientific notation. 315 if (__found_grouping.size() && !__found_dec) 316 __found_grouping += static_cast<char>(__sep_pos); 317 __xtrc += 'e'; 318 __found_sci = true; 319 320 // Remove optional plus or minus sign, if they exist. 321 if (++__beg != __end) 322 { 323 __c = *__beg; 324 const bool __plus = __c == __lit[__num_base::_S_iplus]; 325 if ((__plus || __c == __lit[__num_base::_S_iminus]) 326 && !(__lc->_M_use_grouping 327 && __c == __lc->_M_thousands_sep) 328 && !(__c == __lc->_M_decimal_point)) 329 __xtrc += __plus ? '+' : '-'; 330 else 331 continue; 332 } 333 else 334 { 335 __testeof = true; 336 break; 337 } 338 } 339 else 340 break; 341 } 342 343 if (++__beg != __end) 344 __c = *__beg; 345 else 346 __testeof = true; 347 } 348 349 // Digit grouping is checked. If grouping and found_grouping don't 350 // match, then get very very upset, and set failbit. 351 if (__found_grouping.size()) 352 { 353 // Add the ending grouping if a decimal or 'e'/'E' wasn't found. 354 if (!__found_dec && !__found_sci) 355 __found_grouping += static_cast<char>(__sep_pos); 356 357 if (!std::__verify_grouping(__lc->_M_grouping, 358 __lc->_M_grouping_size, 359 __found_grouping)) 360 __err = ios_base::failbit; 361 } 362 363 return __beg; 364 } 365 366 template<typename _CharT, typename _InIter> 367 template<typename _ValueT> 368 _InIter 369 num_get<_CharT, _InIter>:: 370 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, 371 ios_base::iostate& __err, _ValueT& __v) const 372 { 373 typedef char_traits<_CharT> __traits_type; 374 using __gnu_cxx::__add_unsigned; 375 typedef typename __add_unsigned<_ValueT>::__type __unsigned_type; 376 typedef __numpunct_cache<_CharT> __cache_type; 377 __use_cache<__cache_type> __uc; 378 const locale& __loc = __io._M_getloc(); 379 const __cache_type* __lc = __uc(__loc); 380 const _CharT* __lit = __lc->_M_atoms_in; 381 char_type __c = char_type(); 382 383 // NB: Iff __basefield == 0, __base can change based on contents. 384 const ios_base::fmtflags __basefield = __io.flags() 385 & ios_base::basefield; 386 const bool __oct = __basefield == ios_base::oct; 387 int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10); 388 389 // True if __beg becomes equal to __end. 390 bool __testeof = __beg == __end; 391 392 // First check for sign. 393 bool __negative = false; 394 if (!__testeof) 395 { 396 __c = *__beg; 397 __negative = __c == __lit[__num_base::_S_iminus]; 398 if ((__negative || __c == __lit[__num_base::_S_iplus]) 399 && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 400 && !(__c == __lc->_M_decimal_point)) 401 { 402 if (++__beg != __end) 403 __c = *__beg; 404 else 405 __testeof = true; 406 } 407 } 408 409 // Next, look for leading zeros and check required digits 410 // for base formats. 411 bool __found_zero = false; 412 int __sep_pos = 0; 413 while (!__testeof) 414 { 415 if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 416 || __c == __lc->_M_decimal_point) 417 break; 418 else if (__c == __lit[__num_base::_S_izero] 419 && (!__found_zero || __base == 10)) 420 { 421 __found_zero = true; 422 ++__sep_pos; 423 if (__basefield == 0) 424 __base = 8; 425 if (__base == 8) 426 __sep_pos = 0; 427 } 428 else if (__found_zero 429 && (__c == __lit[__num_base::_S_ix] 430 || __c == __lit[__num_base::_S_iX])) 431 { 432 if (__basefield == 0) 433 __base = 16; 434 if (__base == 16) 435 { 436 __found_zero = false; 437 __sep_pos = 0; 438 } 439 else 440 break; 441 } 442 else 443 break; 444 445 if (++__beg != __end) 446 { 447 __c = *__beg; 448 if (!__found_zero) 449 break; 450 } 451 else 452 __testeof = true; 453 } 454 455 // At this point, base is determined. If not hex, only allow 456 // base digits as valid input. 457 const size_t __len = (__base == 16 ? __num_base::_S_iend 458 - __num_base::_S_izero : __base); 459 460 // Extract. 461 string __found_grouping; 462 if (__lc->_M_use_grouping) 463 __found_grouping.reserve(32); 464 bool __testfail = false; 465 bool __testoverflow = false; 466 const __unsigned_type __max = 467 (__negative && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed) 468 ? -__gnu_cxx::__numeric_traits<_ValueT>::__min 469 : __gnu_cxx::__numeric_traits<_ValueT>::__max; 470 const __unsigned_type __smax = __max / __base; 471 __unsigned_type __result = 0; 472 int __digit = 0; 473 const char_type* __lit_zero = __lit + __num_base::_S_izero; 474 475 if (!__lc->_M_allocated) 476 // "C" locale 477 while (!__testeof) 478 { 479 __digit = _M_find(__lit_zero, __len, __c); 480 if (__digit == -1) 481 break; 482 483 if (__result > __smax) 484 __testoverflow = true; 485 else 486 { 487 __result *= __base; 488 __testoverflow |= __result > __max - __digit; 489 __result += __digit; 490 ++__sep_pos; 491 } 492 493 if (++__beg != __end) 494 __c = *__beg; 495 else 496 __testeof = true; 497 } 498 else 499 while (!__testeof) 500 { 501 // According to 22.2.2.1.2, p8-9, first look for thousands_sep 502 // and decimal_point. 503 if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 504 { 505 // NB: Thousands separator at the beginning of a string 506 // is a no-no, as is two consecutive thousands separators. 507 if (__sep_pos) 508 { 509 __found_grouping += static_cast<char>(__sep_pos); 510 __sep_pos = 0; 511 } 512 else 513 { 514 __testfail = true; 515 break; 516 } 517 } 518 else if (__c == __lc->_M_decimal_point) 519 break; 520 else 521 { 522 const char_type* __q = 523 __traits_type::find(__lit_zero, __len, __c); 524 if (!__q) 525 break; 526 527 __digit = __q - __lit_zero; 528 if (__digit > 15) 529 __digit -= 6; 530 if (__result > __smax) 531 __testoverflow = true; 532 else 533 { 534 __result *= __base; 535 __testoverflow |= __result > __max - __digit; 536 __result += __digit; 537 ++__sep_pos; 538 } 539 } 540 541 if (++__beg != __end) 542 __c = *__beg; 543 else 544 __testeof = true; 545 } 546 547 // Digit grouping is checked. If grouping and found_grouping don't 548 // match, then get very very upset, and set failbit. 549 if (__found_grouping.size()) 550 { 551 // Add the ending grouping. 552 __found_grouping += static_cast<char>(__sep_pos); 553 554 if (!std::__verify_grouping(__lc->_M_grouping, 555 __lc->_M_grouping_size, 556 __found_grouping)) 557 __err = ios_base::failbit; 558 } 559 560 // _GLIBCXX_RESOLVE_LIB_DEFECTS 561 // 23. Num_get overflow result. 562 if ((!__sep_pos && !__found_zero && !__found_grouping.size()) 563 || __testfail) 564 { 565 __v = 0; 566 __err = ios_base::failbit; 567 } 568 else if (__testoverflow) 569 { 570 if (__negative 571 && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed) 572 __v = __gnu_cxx::__numeric_traits<_ValueT>::__min; 573 else 574 __v = __gnu_cxx::__numeric_traits<_ValueT>::__max; 575 __err = ios_base::failbit; 576 } 577 else 578 __v = __negative ? -__result : __result; 579 580 if (__testeof) 581 __err |= ios_base::eofbit; 582 return __beg; 583 } 584 585 // _GLIBCXX_RESOLVE_LIB_DEFECTS 586 // 17. Bad bool parsing 587 template<typename _CharT, typename _InIter> 588 _InIter 589 num_get<_CharT, _InIter>:: 590 do_get(iter_type __beg, iter_type __end, ios_base& __io, 591 ios_base::iostate& __err, bool& __v) const 592 { 593 if (!(__io.flags() & ios_base::boolalpha)) 594 { 595 // Parse bool values as long. 596 // NB: We can't just call do_get(long) here, as it might 597 // refer to a derived class. 598 long __l = -1; 599 __beg = _M_extract_int(__beg, __end, __io, __err, __l); 600 if (__l == 0 || __l == 1) 601 __v = bool(__l); 602 else 603 { 604 // _GLIBCXX_RESOLVE_LIB_DEFECTS 605 // 23. Num_get overflow result. 606 __v = true; 607 __err = ios_base::failbit; 608 if (__beg == __end) 609 __err |= ios_base::eofbit; 610 } 611 } 612 else 613 { 614 // Parse bool values as alphanumeric. 615 typedef __numpunct_cache<_CharT> __cache_type; 616 __use_cache<__cache_type> __uc; 617 const locale& __loc = __io._M_getloc(); 618 const __cache_type* __lc = __uc(__loc); 619 620 bool __testf = true; 621 bool __testt = true; 622 bool __donef = __lc->_M_falsename_size == 0; 623 bool __donet = __lc->_M_truename_size == 0; 624 bool __testeof = false; 625 size_t __n = 0; 626 while (!__donef || !__donet) 627 { 628 if (__beg == __end) 629 { 630 __testeof = true; 631 break; 632 } 633 634 const char_type __c = *__beg; 635 636 if (!__donef) 637 __testf = __c == __lc->_M_falsename[__n]; 638 639 if (!__testf && __donet) 640 break; 641 642 if (!__donet) 643 __testt = __c == __lc->_M_truename[__n]; 644 645 if (!__testt && __donef) 646 break; 647 648 if (!__testt && !__testf) 649 break; 650 651 ++__n; 652 ++__beg; 653 654 __donef = !__testf || __n >= __lc->_M_falsename_size; 655 __donet = !__testt || __n >= __lc->_M_truename_size; 656 } 657 if (__testf && __n == __lc->_M_falsename_size && __n) 658 { 659 __v = false; 660 if (__testt && __n == __lc->_M_truename_size) 661 __err = ios_base::failbit; 662 else 663 __err = __testeof ? ios_base::eofbit : ios_base::goodbit; 664 } 665 else if (__testt && __n == __lc->_M_truename_size && __n) 666 { 667 __v = true; 668 __err = __testeof ? ios_base::eofbit : ios_base::goodbit; 669 } 670 else 671 { 672 // _GLIBCXX_RESOLVE_LIB_DEFECTS 673 // 23. Num_get overflow result. 674 __v = false; 675 __err = ios_base::failbit; 676 if (__testeof) 677 __err |= ios_base::eofbit; 678 } 679 } 680 return __beg; 681 } 682 683 template<typename _CharT, typename _InIter> 684 _InIter 685 num_get<_CharT, _InIter>:: 686 do_get(iter_type __beg, iter_type __end, ios_base& __io, 687 ios_base::iostate& __err, float& __v) const 688 { 689 string __xtrc; 690 __xtrc.reserve(32); 691 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 692 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 693 if (__beg == __end) 694 __err |= ios_base::eofbit; 695 return __beg; 696 } 697 698 template<typename _CharT, typename _InIter> 699 _InIter 700 num_get<_CharT, _InIter>:: 701 do_get(iter_type __beg, iter_type __end, ios_base& __io, 702 ios_base::iostate& __err, double& __v) const 703 { 704 string __xtrc; 705 __xtrc.reserve(32); 706 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 707 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 708 if (__beg == __end) 709 __err |= ios_base::eofbit; 710 return __beg; 711 } 712 713 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ 714 template<typename _CharT, typename _InIter> 715 _InIter 716 num_get<_CharT, _InIter>:: 717 __do_get(iter_type __beg, iter_type __end, ios_base& __io, 718 ios_base::iostate& __err, double& __v) const 719 { 720 string __xtrc; 721 __xtrc.reserve(32); 722 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 723 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 724 if (__beg == __end) 725 __err |= ios_base::eofbit; 726 return __beg; 727 } 728 #endif 729 730 template<typename _CharT, typename _InIter> 731 _InIter 732 num_get<_CharT, _InIter>:: 733 do_get(iter_type __beg, iter_type __end, ios_base& __io, 734 ios_base::iostate& __err, long double& __v) const 735 { 736 string __xtrc; 737 __xtrc.reserve(32); 738 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 739 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 740 if (__beg == __end) 741 __err |= ios_base::eofbit; 742 return __beg; 743 } 744 745 template<typename _CharT, typename _InIter> 746 _InIter 747 num_get<_CharT, _InIter>:: 748 do_get(iter_type __beg, iter_type __end, ios_base& __io, 749 ios_base::iostate& __err, void*& __v) const 750 { 751 // Prepare for hex formatted input. 752 typedef ios_base::fmtflags fmtflags; 753 const fmtflags __fmt = __io.flags(); 754 __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex); 755 756 typedef __gnu_cxx::__conditional_type<(sizeof(void*) 757 <= sizeof(unsigned long)), 758 unsigned long, unsigned long long>::__type _UIntPtrType; 759 760 _UIntPtrType __ul; 761 __beg = _M_extract_int(__beg, __end, __io, __err, __ul); 762 763 // Reset from hex formatted input. 764 __io.flags(__fmt); 765 766 __v = reinterpret_cast<void*>(__ul); 767 return __beg; 768 } 769 770 // For use by integer and floating-point types after they have been 771 // converted into a char_type string. 772 template<typename _CharT, typename _OutIter> 773 void 774 num_put<_CharT, _OutIter>:: 775 _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 776 _CharT* __new, const _CharT* __cs, int& __len) const 777 { 778 // [22.2.2.2.2] Stage 3. 779 // If necessary, pad. 780 __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, 781 __cs, __w, __len); 782 __len = static_cast<int>(__w); 783 } 784 785 _GLIBCXX_END_NAMESPACE_LDBL 786 787 template<typename _CharT, typename _ValueT> 788 int 789 __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit, 790 ios_base::fmtflags __flags, bool __dec) 791 { 792 _CharT* __buf = __bufend; 793 if (__builtin_expect(__dec, true)) 794 { 795 // Decimal. 796 do 797 { 798 *--__buf = __lit[(__v % 10) + __num_base::_S_odigits]; 799 __v /= 10; 800 } 801 while (__v != 0); 802 } 803 else if ((__flags & ios_base::basefield) == ios_base::oct) 804 { 805 // Octal. 806 do 807 { 808 *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits]; 809 __v >>= 3; 810 } 811 while (__v != 0); 812 } 813 else 814 { 815 // Hex. 816 const bool __uppercase = __flags & ios_base::uppercase; 817 const int __case_offset = __uppercase ? __num_base::_S_oudigits 818 : __num_base::_S_odigits; 819 do 820 { 821 *--__buf = __lit[(__v & 0xf) + __case_offset]; 822 __v >>= 4; 823 } 824 while (__v != 0); 825 } 826 return __bufend - __buf; 827 } 828 829 _GLIBCXX_BEGIN_NAMESPACE_LDBL 830 831 template<typename _CharT, typename _OutIter> 832 void 833 num_put<_CharT, _OutIter>:: 834 _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep, 835 ios_base&, _CharT* __new, _CharT* __cs, int& __len) const 836 { 837 _CharT* __p = std::__add_grouping(__new, __sep, __grouping, 838 __grouping_size, __cs, __cs + __len); 839 __len = __p - __new; 840 } 841 842 template<typename _CharT, typename _OutIter> 843 template<typename _ValueT> 844 _OutIter 845 num_put<_CharT, _OutIter>:: 846 _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill, 847 _ValueT __v) const 848 { 849 using __gnu_cxx::__add_unsigned; 850 typedef typename __add_unsigned<_ValueT>::__type __unsigned_type; 851 typedef __numpunct_cache<_CharT> __cache_type; 852 __use_cache<__cache_type> __uc; 853 const locale& __loc = __io._M_getloc(); 854 const __cache_type* __lc = __uc(__loc); 855 const _CharT* __lit = __lc->_M_atoms_out; 856 const ios_base::fmtflags __flags = __io.flags(); 857 858 // Long enough to hold hex, dec, and octal representations. 859 const int __ilen = 5 * sizeof(_ValueT); 860 _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 861 * __ilen)); 862 863 // [22.2.2.2.2] Stage 1, numeric conversion to character. 864 // Result is returned right-justified in the buffer. 865 const ios_base::fmtflags __basefield = __flags & ios_base::basefield; 866 const bool __dec = (__basefield != ios_base::oct 867 && __basefield != ios_base::hex); 868 const __unsigned_type __u = ((__v > 0 || !__dec) 869 ? __unsigned_type(__v) 870 : -__unsigned_type(__v)); 871 int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec); 872 __cs += __ilen - __len; 873 874 // Add grouping, if necessary. 875 if (__lc->_M_use_grouping) 876 { 877 // Grouping can add (almost) as many separators as the number 878 // of digits + space is reserved for numeric base or sign. 879 _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 880 * (__len + 1) 881 * 2)); 882 _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size, 883 __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len); 884 __cs = __cs2 + 2; 885 } 886 887 // Complete Stage 1, prepend numeric base or sign. 888 if (__builtin_expect(__dec, true)) 889 { 890 // Decimal. 891 if (__v >= 0) 892 { 893 if (bool(__flags & ios_base::showpos) 894 && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed) 895 *--__cs = __lit[__num_base::_S_oplus], ++__len; 896 } 897 else 898 *--__cs = __lit[__num_base::_S_ominus], ++__len; 899 } 900 else if (bool(__flags & ios_base::showbase) && __v) 901 { 902 if (__basefield == ios_base::oct) 903 *--__cs = __lit[__num_base::_S_odigits], ++__len; 904 else 905 { 906 // 'x' or 'X' 907 const bool __uppercase = __flags & ios_base::uppercase; 908 *--__cs = __lit[__num_base::_S_ox + __uppercase]; 909 // '0' 910 *--__cs = __lit[__num_base::_S_odigits]; 911 __len += 2; 912 } 913 } 914 915 // Pad. 916 const streamsize __w = __io.width(); 917 if (__w > static_cast<streamsize>(__len)) 918 { 919 _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 920 * __w)); 921 _M_pad(__fill, __w, __io, __cs3, __cs, __len); 922 __cs = __cs3; 923 } 924 __io.width(0); 925 926 // [22.2.2.2.2] Stage 4. 927 // Write resulting, fully-formatted string to output iterator. 928 return std::__write(__s, __cs, __len); 929 } 930 931 template<typename _CharT, typename _OutIter> 932 void 933 num_put<_CharT, _OutIter>:: 934 _M_group_float(const char* __grouping, size_t __grouping_size, 935 _CharT __sep, const _CharT* __p, _CharT* __new, 936 _CharT* __cs, int& __len) const 937 { 938 // _GLIBCXX_RESOLVE_LIB_DEFECTS 939 // 282. What types does numpunct grouping refer to? 940 // Add grouping, if necessary. 941 const int __declen = __p ? __p - __cs : __len; 942 _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping, 943 __grouping_size, 944 __cs, __cs + __declen); 945 946 // Tack on decimal part. 947 int __newlen = __p2 - __new; 948 if (__p) 949 { 950 char_traits<_CharT>::copy(__p2, __p, __len - __declen); 951 __newlen += __len - __declen; 952 } 953 __len = __newlen; 954 } 955 956 // The following code uses vsnprintf (or vsprintf(), when 957 // _GLIBCXX_USE_C99 is not defined) to convert floating point values 958 // for insertion into a stream. An optimization would be to replace 959 // them with code that works directly on a wide buffer and then use 960 // __pad to do the padding. It would be good to replace them anyway 961 // to gain back the efficiency that C++ provides by knowing up front 962 // the type of the values to insert. Also, sprintf is dangerous 963 // since may lead to accidental buffer overruns. This 964 // implementation follows the C++ standard fairly directly as 965 // outlined in 22.2.2.2 [lib.locale.num.put] 966 template<typename _CharT, typename _OutIter> 967 template<typename _ValueT> 968 _OutIter 969 num_put<_CharT, _OutIter>:: 970 _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 971 _ValueT __v) const 972 { 973 typedef __numpunct_cache<_CharT> __cache_type; 974 __use_cache<__cache_type> __uc; 975 const locale& __loc = __io._M_getloc(); 976 const __cache_type* __lc = __uc(__loc); 977 978 // Use default precision if out of range. 979 const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision(); 980 981 const int __max_digits = 982 __gnu_cxx::__numeric_traits<_ValueT>::__digits10; 983 984 // [22.2.2.2.2] Stage 1, numeric conversion to character. 985 int __len; 986 // Long enough for the max format spec. 987 char __fbuf[16]; 988 __num_base::_S_format_float(__io, __fbuf, __mod); 989 990 #ifdef _GLIBCXX_USE_C99 991 // First try a buffer perhaps big enough (most probably sufficient 992 // for non-ios_base::fixed outputs) 993 int __cs_size = __max_digits * 3; 994 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 995 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 996 __fbuf, __prec, __v); 997 998 // If the buffer was not large enough, try again with the correct size. 999 if (__len >= __cs_size) 1000 { 1001 __cs_size = __len + 1; 1002 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1003 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 1004 __fbuf, __prec, __v); 1005 } 1006 #else 1007 // Consider the possibility of long ios_base::fixed outputs 1008 const bool __fixed = __io.flags() & ios_base::fixed; 1009 const int __max_exp = 1010 __gnu_cxx::__numeric_traits<_ValueT>::__max_exponent10; 1011 1012 // The size of the output string is computed as follows. 1013 // ios_base::fixed outputs may need up to __max_exp + 1 chars 1014 // for the integer part + __prec chars for the fractional part 1015 // + 3 chars for sign, decimal point, '\0'. On the other hand, 1016 // for non-fixed outputs __max_digits * 2 + __prec chars are 1017 // largely sufficient. 1018 const int __cs_size = __fixed ? __max_exp + __prec + 4 1019 : __max_digits * 2 + __prec; 1020 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 1021 __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf, 1022 __prec, __v); 1023 #endif 1024 1025 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 1026 // numpunct.decimal_point() values for '.' and adding grouping. 1027 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1028 1029 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1030 * __len)); 1031 __ctype.widen(__cs, __cs + __len, __ws); 1032 1033 // Replace decimal point. 1034 _CharT* __wp = 0; 1035 const char* __p = char_traits<char>::find(__cs, __len, '.'); 1036 if (__p) 1037 { 1038 __wp = __ws + (__p - __cs); 1039 *__wp = __lc->_M_decimal_point; 1040 } 1041 1042 // Add grouping, if necessary. 1043 // N.B. Make sure to not group things like 2e20, i.e., no decimal 1044 // point, scientific notation. 1045 if (__lc->_M_use_grouping 1046 && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9' 1047 && __cs[1] >= '0' && __cs[2] >= '0'))) 1048 { 1049 // Grouping can add (almost) as many separators as the 1050 // number of digits, but no more. 1051 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1052 * __len * 2)); 1053 1054 streamsize __off = 0; 1055 if (__cs[0] == '-' || __cs[0] == '+') 1056 { 1057 __off = 1; 1058 __ws2[0] = __ws[0]; 1059 __len -= 1; 1060 } 1061 1062 _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size, 1063 __lc->_M_thousands_sep, __wp, __ws2 + __off, 1064 __ws + __off, __len); 1065 __len += __off; 1066 1067 __ws = __ws2; 1068 } 1069 1070 // Pad. 1071 const streamsize __w = __io.width(); 1072 if (__w > static_cast<streamsize>(__len)) 1073 { 1074 _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1075 * __w)); 1076 _M_pad(__fill, __w, __io, __ws3, __ws, __len); 1077 __ws = __ws3; 1078 } 1079 __io.width(0); 1080 1081 // [22.2.2.2.2] Stage 4. 1082 // Write resulting, fully-formatted string to output iterator. 1083 return std::__write(__s, __ws, __len); 1084 } 1085 1086 template<typename _CharT, typename _OutIter> 1087 _OutIter 1088 num_put<_CharT, _OutIter>:: 1089 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 1090 { 1091 const ios_base::fmtflags __flags = __io.flags(); 1092 if ((__flags & ios_base::boolalpha) == 0) 1093 { 1094 const long __l = __v; 1095 __s = _M_insert_int(__s, __io, __fill, __l); 1096 } 1097 else 1098 { 1099 typedef __numpunct_cache<_CharT> __cache_type; 1100 __use_cache<__cache_type> __uc; 1101 const locale& __loc = __io._M_getloc(); 1102 const __cache_type* __lc = __uc(__loc); 1103 1104 const _CharT* __name = __v ? __lc->_M_truename 1105 : __lc->_M_falsename; 1106 int __len = __v ? __lc->_M_truename_size 1107 : __lc->_M_falsename_size; 1108 1109 const streamsize __w = __io.width(); 1110 if (__w > static_cast<streamsize>(__len)) 1111 { 1112 const streamsize __plen = __w - __len; 1113 _CharT* __ps 1114 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 1115 * __plen)); 1116 1117 char_traits<_CharT>::assign(__ps, __plen, __fill); 1118 __io.width(0); 1119 1120 if ((__flags & ios_base::adjustfield) == ios_base::left) 1121 { 1122 __s = std::__write(__s, __name, __len); 1123 __s = std::__write(__s, __ps, __plen); 1124 } 1125 else 1126 { 1127 __s = std::__write(__s, __ps, __plen); 1128 __s = std::__write(__s, __name, __len); 1129 } 1130 return __s; 1131 } 1132 __io.width(0); 1133 __s = std::__write(__s, __name, __len); 1134 } 1135 return __s; 1136 } 1137 1138 template<typename _CharT, typename _OutIter> 1139 _OutIter 1140 num_put<_CharT, _OutIter>:: 1141 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 1142 { return _M_insert_float(__s, __io, __fill, char(), __v); } 1143 1144 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ 1145 template<typename _CharT, typename _OutIter> 1146 _OutIter 1147 num_put<_CharT, _OutIter>:: 1148 __do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 1149 { return _M_insert_float(__s, __io, __fill, char(), __v); } 1150 #endif 1151 1152 template<typename _CharT, typename _OutIter> 1153 _OutIter 1154 num_put<_CharT, _OutIter>:: 1155 do_put(iter_type __s, ios_base& __io, char_type __fill, 1156 long double __v) const 1157 { return _M_insert_float(__s, __io, __fill, 'L', __v); } 1158 1159 template<typename _CharT, typename _OutIter> 1160 _OutIter 1161 num_put<_CharT, _OutIter>:: 1162 do_put(iter_type __s, ios_base& __io, char_type __fill, 1163 const void* __v) const 1164 { 1165 const ios_base::fmtflags __flags = __io.flags(); 1166 const ios_base::fmtflags __fmt = ~(ios_base::basefield 1167 | ios_base::uppercase); 1168 __io.flags((__flags & __fmt) | (ios_base::hex | ios_base::showbase)); 1169 1170 typedef __gnu_cxx::__conditional_type<(sizeof(const void*) 1171 <= sizeof(unsigned long)), 1172 unsigned long, unsigned long long>::__type _UIntPtrType; 1173 1174 __s = _M_insert_int(__s, __io, __fill, 1175 reinterpret_cast<_UIntPtrType>(__v)); 1176 __io.flags(__flags); 1177 return __s; 1178 } 1179 1180 _GLIBCXX_END_NAMESPACE_LDBL 1181 1182 // Construct correctly padded string, as per 22.2.2.2.2 1183 // Assumes 1184 // __newlen > __oldlen 1185 // __news is allocated for __newlen size 1186 1187 // NB: Of the two parameters, _CharT can be deduced from the 1188 // function arguments. The other (_Traits) has to be explicitly specified. 1189 template<typename _CharT, typename _Traits> 1190 void 1191 __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 1192 _CharT* __news, const _CharT* __olds, 1193 streamsize __newlen, streamsize __oldlen) 1194 { 1195 const size_t __plen = static_cast<size_t>(__newlen - __oldlen); 1196 const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 1197 1198 // Padding last. 1199 if (__adjust == ios_base::left) 1200 { 1201 _Traits::copy(__news, __olds, __oldlen); 1202 _Traits::assign(__news + __oldlen, __plen, __fill); 1203 return; 1204 } 1205 1206 size_t __mod = 0; 1207 if (__adjust == ios_base::internal) 1208 { 1209 // Pad after the sign, if there is one. 1210 // Pad after 0[xX], if there is one. 1211 // Who came up with these rules, anyway? Jeeze. 1212 const locale& __loc = __io._M_getloc(); 1213 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1214 1215 if (__ctype.widen('-') == __olds[0] 1216 || __ctype.widen('+') == __olds[0]) 1217 { 1218 __news[0] = __olds[0]; 1219 __mod = 1; 1220 ++__news; 1221 } 1222 else if (__ctype.widen('0') == __olds[0] 1223 && __oldlen > 1 1224 && (__ctype.widen('x') == __olds[1] 1225 || __ctype.widen('X') == __olds[1])) 1226 { 1227 __news[0] = __olds[0]; 1228 __news[1] = __olds[1]; 1229 __mod = 2; 1230 __news += 2; 1231 } 1232 // else Padding first. 1233 } 1234 _Traits::assign(__news, __plen, __fill); 1235 _Traits::copy(__news + __plen, __olds + __mod, __oldlen - __mod); 1236 } 1237 1238 template<typename _CharT> 1239 _CharT* 1240 __add_grouping(_CharT* __s, _CharT __sep, 1241 const char* __gbeg, size_t __gsize, 1242 const _CharT* __first, const _CharT* __last) 1243 { 1244 size_t __idx = 0; 1245 size_t __ctr = 0; 1246 1247 while (__last - __first > __gbeg[__idx] 1248 && static_cast<signed char>(__gbeg[__idx]) > 0 1249 && __gbeg[__idx] != __gnu_cxx::__numeric_traits<char>::__max) 1250 { 1251 __last -= __gbeg[__idx]; 1252 __idx < __gsize - 1 ? ++__idx : ++__ctr; 1253 } 1254 1255 while (__first != __last) 1256 *__s++ = *__first++; 1257 1258 while (__ctr--) 1259 { 1260 *__s++ = __sep; 1261 for (char __i = __gbeg[__idx]; __i > 0; --__i) 1262 *__s++ = *__first++; 1263 } 1264 1265 while (__idx--) 1266 { 1267 *__s++ = __sep; 1268 for (char __i = __gbeg[__idx]; __i > 0; --__i) 1269 *__s++ = *__first++; 1270 } 1271 1272 return __s; 1273 } 1274 1275 // Inhibit implicit instantiations for required instantiations, 1276 // which are defined via explicit instantiations elsewhere. 1277 #if _GLIBCXX_EXTERN_TEMPLATE 1278 extern template class numpunct<char>; 1279 extern template class numpunct_byname<char>; 1280 extern template class _GLIBCXX_NAMESPACE_LDBL num_get<char>; 1281 extern template class _GLIBCXX_NAMESPACE_LDBL num_put<char>; 1282 extern template class ctype_byname<char>; 1283 1284 extern template 1285 const ctype<char>& 1286 use_facet<ctype<char> >(const locale&); 1287 1288 extern template 1289 const numpunct<char>& 1290 use_facet<numpunct<char> >(const locale&); 1291 1292 extern template 1293 const num_put<char>& 1294 use_facet<num_put<char> >(const locale&); 1295 1296 extern template 1297 const num_get<char>& 1298 use_facet<num_get<char> >(const locale&); 1299 1300 extern template 1301 bool 1302 has_facet<ctype<char> >(const locale&); 1303 1304 extern template 1305 bool 1306 has_facet<numpunct<char> >(const locale&); 1307 1308 extern template 1309 bool 1310 has_facet<num_put<char> >(const locale&); 1311 1312 extern template 1313 bool 1314 has_facet<num_get<char> >(const locale&); 1315 1316 #ifdef _GLIBCXX_USE_WCHAR_T 1317 extern template class numpunct<wchar_t>; 1318 extern template class numpunct_byname<wchar_t>; 1319 extern template class _GLIBCXX_NAMESPACE_LDBL num_get<wchar_t>; 1320 extern template class _GLIBCXX_NAMESPACE_LDBL num_put<wchar_t>; 1321 extern template class ctype_byname<wchar_t>; 1322 1323 extern template 1324 const ctype<wchar_t>& 1325 use_facet<ctype<wchar_t> >(const locale&); 1326 1327 extern template 1328 const numpunct<wchar_t>& 1329 use_facet<numpunct<wchar_t> >(const locale&); 1330 1331 extern template 1332 const num_put<wchar_t>& 1333 use_facet<num_put<wchar_t> >(const locale&); 1334 1335 extern template 1336 const num_get<wchar_t>& 1337 use_facet<num_get<wchar_t> >(const locale&); 1338 1339 extern template 1340 bool 1341 has_facet<ctype<wchar_t> >(const locale&); 1342 1343 extern template 1344 bool 1345 has_facet<numpunct<wchar_t> >(const locale&); 1346 1347 extern template 1348 bool 1349 has_facet<num_put<wchar_t> >(const locale&); 1350 1351 extern template 1352 bool 1353 has_facet<num_get<wchar_t> >(const locale&); 1354 #endif 1355 #endif 1356 1357 _GLIBCXX_END_NAMESPACE_VERSION 1358 } // namespace 1359 1360 #endif 1361