Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/bits/locale_facets_nonio.tcc
1 // Locale support -*- C++ -*- 2 3 // Copyright (C) 2007-2025 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_nonio.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_NONIO_TCC 31 #define _LOCALE_FACETS_NONIO_TCC 1 32 33 #ifdef _GLIBCXX_SYSHDR 34 #pragma GCC system_header 35 #endif 36 37 namespace std _GLIBCXX_VISIBILITY(default) 38 { 39 _GLIBCXX_BEGIN_NAMESPACE_VERSION 40 41 template<typename _CharT, bool _Intl> 42 struct __use_cache<__moneypunct_cache<_CharT, _Intl> > 43 { 44 const __moneypunct_cache<_CharT, _Intl>* 45 operator() (const locale& __loc) const 46 { 47 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id(); 48 const locale::facet** __caches = __loc._M_impl->_M_caches; 49 if (!__caches[__i]) 50 { 51 __moneypunct_cache<_CharT, _Intl>* __tmp = 0; 52 __try 53 { 54 __tmp = new __moneypunct_cache<_CharT, _Intl>; 55 __tmp->_M_cache(__loc); 56 } 57 __catch(...) 58 { 59 delete __tmp; 60 __throw_exception_again; 61 } 62 __loc._M_impl->_M_install_cache(__tmp, __i); 63 } 64 return static_cast< 65 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]); 66 } 67 }; 68 69 template<typename _CharT, bool _Intl> 70 void 71 __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc) 72 { 73 const moneypunct<_CharT, _Intl>& __mp = 74 use_facet<moneypunct<_CharT, _Intl> >(__loc); 75 76 struct _Scoped_str 77 { 78 size_t _M_len; 79 _CharT* _M_str; 80 81 explicit 82 _Scoped_str(const basic_string<_CharT>& __str) 83 : _M_len(__str.size()), _M_str(new _CharT[_M_len]) 84 { __str.copy(_M_str, _M_len); } 85 86 ~_Scoped_str() { delete[] _M_str; } 87 88 void 89 _M_release(const _CharT*& __p, size_t& __n) 90 { 91 __p = _M_str; 92 __n = _M_len; 93 _M_str = 0; 94 } 95 }; 96 97 _Scoped_str __curr_symbol(__mp.curr_symbol()); 98 _Scoped_str __positive_sign(__mp.positive_sign()); 99 _Scoped_str __negative_sign(__mp.negative_sign()); 100 101 const string& __g = __mp.grouping(); 102 const size_t __g_size = __g.size(); 103 char* const __grouping = new char[__g_size]; 104 __g.copy(__grouping, __g_size); 105 106 // All allocations succeeded without throwing, OK to modify *this now. 107 108 _M_grouping = __grouping; 109 _M_grouping_size = __g_size; 110 _M_use_grouping = (__g_size 111 && static_cast<signed char>(__grouping[0]) > 0 112 && (__grouping[0] 113 != __gnu_cxx::__numeric_traits<char>::__max)); 114 115 _M_decimal_point = __mp.decimal_point(); 116 _M_thousands_sep = __mp.thousands_sep(); 117 118 __curr_symbol._M_release(_M_curr_symbol, _M_curr_symbol_size); 119 __positive_sign._M_release(_M_positive_sign, _M_positive_sign_size); 120 __negative_sign._M_release(_M_negative_sign, _M_negative_sign_size); 121 122 _M_frac_digits = __mp.frac_digits(); 123 _M_pos_format = __mp.pos_format(); 124 _M_neg_format = __mp.neg_format(); 125 126 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 127 __ct.widen(money_base::_S_atoms, 128 money_base::_S_atoms + money_base::_S_end, _M_atoms); 129 130 _M_allocated = true; 131 } 132 133 _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 134 135 template<typename _CharT, typename _InIter> 136 template<bool _Intl> 137 _InIter 138 money_get<_CharT, _InIter>:: 139 _M_extract(iter_type __beg, iter_type __end, ios_base& __io, 140 ios_base::iostate& __err, string& __units) const 141 { 142 typedef char_traits<_CharT> __traits_type; 143 typedef typename string_type::size_type size_type; 144 typedef money_base::part part; 145 typedef __moneypunct_cache<_CharT, _Intl> __cache_type; 146 147 const locale& __loc = __io._M_getloc(); 148 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 149 150 __use_cache<__cache_type> __uc; 151 const __cache_type* __lc = __uc(__loc); 152 const char_type* __lit = __lc->_M_atoms; 153 154 // Deduced sign. 155 bool __negative = false; 156 // Sign size. 157 size_type __sign_size = 0; 158 // True if sign is mandatory. 159 const bool __mandatory_sign = (__lc->_M_positive_sign_size 160 && __lc->_M_negative_sign_size); 161 // String of grouping info from thousands_sep plucked from __units. 162 string __grouping_tmp; 163 if (__lc->_M_use_grouping) 164 __grouping_tmp.reserve(32); 165 // Last position before the decimal point. 166 int __last_pos = 0; 167 // Separator positions, then, possibly, fractional digits. 168 int __n = 0; 169 // If input iterator is in a valid state. 170 bool __testvalid = true; 171 // Flag marking when a decimal point is found. 172 bool __testdecfound = false; 173 174 // The tentative returned string is stored here. 175 string __res; 176 __res.reserve(32); 177 178 const char_type* __lit_zero = __lit + money_base::_S_zero; 179 const money_base::pattern __p = __lc->_M_neg_format; 180 for (int __i = 0; __i < 4 && __testvalid; ++__i) 181 { 182 const part __which = static_cast<part>(__p.field[__i]); 183 switch (__which) 184 { 185 case money_base::symbol: 186 // According to 22.2.6.1.2, p2, symbol is required 187 // if (__io.flags() & ios_base::showbase), otherwise 188 // is optional and consumed only if other characters 189 // are needed to complete the format. 190 if (__io.flags() & ios_base::showbase || __sign_size > 1 191 || __i == 0 192 || (__i == 1 && (__mandatory_sign 193 || (static_cast<part>(__p.field[0]) 194 == money_base::sign) 195 || (static_cast<part>(__p.field[2]) 196 == money_base::space))) 197 || (__i == 2 && ((static_cast<part>(__p.field[3]) 198 == money_base::value) 199 || (__mandatory_sign 200 && (static_cast<part>(__p.field[3]) 201 == money_base::sign))))) 202 { 203 const size_type __len = __lc->_M_curr_symbol_size; 204 size_type __j = 0; 205 for (; __beg != __end && __j < __len 206 && *__beg == __lc->_M_curr_symbol[__j]; 207 ++__beg, (void)++__j); 208 if (__j != __len 209 && (__j || __io.flags() & ios_base::showbase)) 210 __testvalid = false; 211 } 212 break; 213 case money_base::sign: 214 // Sign might not exist, or be more than one character long. 215 if (__lc->_M_positive_sign_size && __beg != __end 216 && *__beg == __lc->_M_positive_sign[0]) 217 { 218 __sign_size = __lc->_M_positive_sign_size; 219 ++__beg; 220 } 221 else if (__lc->_M_negative_sign_size && __beg != __end 222 && *__beg == __lc->_M_negative_sign[0]) 223 { 224 __negative = true; 225 __sign_size = __lc->_M_negative_sign_size; 226 ++__beg; 227 } 228 else if (__lc->_M_positive_sign_size 229 && !__lc->_M_negative_sign_size) 230 // "... if no sign is detected, the result is given the sign 231 // that corresponds to the source of the empty string" 232 __negative = true; 233 else if (__mandatory_sign) 234 __testvalid = false; 235 break; 236 case money_base::value: 237 // Extract digits, remove and stash away the 238 // grouping of found thousands separators. 239 for (; __beg != __end; ++__beg) 240 { 241 const char_type __c = *__beg; 242 const char_type* __q = __traits_type::find(__lit_zero, 243 10, __c); 244 if (__q != 0) 245 { 246 __res += money_base::_S_atoms[__q - __lit]; 247 ++__n; 248 } 249 else if (__c == __lc->_M_decimal_point 250 && !__testdecfound) 251 { 252 if (__lc->_M_frac_digits <= 0) 253 break; 254 255 __last_pos = __n; 256 __n = 0; 257 __testdecfound = true; 258 } 259 else if (__lc->_M_use_grouping 260 && __c == __lc->_M_thousands_sep 261 && !__testdecfound) 262 { 263 if (__n) 264 { 265 // Mark position for later analysis. 266 __grouping_tmp += static_cast<char>(__n); 267 __n = 0; 268 } 269 else 270 { 271 __testvalid = false; 272 break; 273 } 274 } 275 else 276 break; 277 } 278 if (__res.empty()) 279 __testvalid = false; 280 break; 281 case money_base::space: 282 // At least one space is required. 283 if (__beg != __end && __ctype.is(ctype_base::space, *__beg)) 284 ++__beg; 285 else 286 __testvalid = false; 287 // fallthrough 288 case money_base::none: 289 // Only if not at the end of the pattern. 290 if (__i != 3) 291 for (; __beg != __end 292 && __ctype.is(ctype_base::space, *__beg); ++__beg); 293 break; 294 } 295 } 296 297 // Need to get the rest of the sign characters, if they exist. 298 if (__sign_size > 1 && __testvalid) 299 { 300 const char_type* __sign = __negative ? __lc->_M_negative_sign 301 : __lc->_M_positive_sign; 302 size_type __i = 1; 303 for (; __beg != __end && __i < __sign_size 304 && *__beg == __sign[__i]; ++__beg, (void)++__i); 305 306 if (__i != __sign_size) 307 __testvalid = false; 308 } 309 310 if (__testvalid) 311 { 312 // Strip leading zeros. 313 if (__res.size() > 1) 314 { 315 const size_type __first = __res.find_first_not_of('0'); 316 const bool __only_zeros = __first == string::npos; 317 if (__first) 318 __res.erase(0, __only_zeros ? __res.size() - 1 : __first); 319 } 320 321 // 22.2.6.1.2, p4 322 if (__negative && __res[0] != '0') 323 __res.insert(__res.begin(), '-'); 324 325 // Test for grouping fidelity. 326 if (__grouping_tmp.size()) 327 { 328 // Add the ending grouping. 329 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos 330 : __n); 331 if (!std::__verify_grouping(__lc->_M_grouping, 332 __lc->_M_grouping_size, 333 __grouping_tmp)) 334 __err |= ios_base::failbit; 335 } 336 337 // Iff not enough digits were supplied after the decimal-point. 338 if (__testdecfound && __n != __lc->_M_frac_digits) 339 __testvalid = false; 340 } 341 342 // Iff valid sequence is not recognized. 343 if (!__testvalid) 344 __err |= ios_base::failbit; 345 else 346 __units.swap(__res); 347 348 // Iff no more characters are available. 349 if (__beg == __end) 350 __err |= ios_base::eofbit; 351 return __beg; 352 } 353 354 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \ 355 && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__) 356 template<typename _CharT, typename _InIter> 357 _InIter 358 money_get<_CharT, _InIter>:: 359 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 360 ios_base::iostate& __err, double& __units) const 361 { 362 string __str; 363 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 364 : _M_extract<false>(__beg, __end, __io, __err, __str); 365 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 366 return __beg; 367 } 368 #endif 369 370 template<typename _CharT, typename _InIter> 371 _InIter 372 money_get<_CharT, _InIter>:: 373 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 374 ios_base::iostate& __err, long double& __units) const 375 { 376 string __str; 377 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 378 : _M_extract<false>(__beg, __end, __io, __err, __str); 379 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 380 return __beg; 381 } 382 383 template<typename _CharT, typename _InIter> 384 _InIter 385 money_get<_CharT, _InIter>:: 386 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 387 ios_base::iostate& __err, string_type& __digits) const 388 { 389 typedef typename string::size_type size_type; 390 391 const locale& __loc = __io._M_getloc(); 392 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 393 394 string __str; 395 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 396 : _M_extract<false>(__beg, __end, __io, __err, __str); 397 const size_type __len = __str.size(); 398 if (__len) 399 { 400 __digits.resize(__len); 401 __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]); 402 } 403 return __beg; 404 } 405 406 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \ 407 && defined __LONG_DOUBLE_IEEE128__ 408 template<typename _CharT, typename _InIter> 409 _InIter 410 money_get<_CharT, _InIter>:: 411 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 412 ios_base::iostate& __err, __ibm128& __units) const 413 { 414 string __str; 415 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 416 : _M_extract<false>(__beg, __end, __io, __err, __str); 417 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 418 return __beg; 419 } 420 #endif 421 422 template<typename _CharT, typename _OutIter> 423 template<bool _Intl> 424 _OutIter 425 money_put<_CharT, _OutIter>:: 426 _M_insert(iter_type __s, ios_base& __io, char_type __fill, 427 const string_type& __digits) const 428 { 429 typedef typename string_type::size_type size_type; 430 typedef money_base::part part; 431 typedef __moneypunct_cache<_CharT, _Intl> __cache_type; 432 433 const locale& __loc = __io._M_getloc(); 434 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 435 436 __use_cache<__cache_type> __uc; 437 const __cache_type* __lc = __uc(__loc); 438 const char_type* __lit = __lc->_M_atoms; 439 440 // Determine if negative or positive formats are to be used, and 441 // discard leading negative_sign if it is present. 442 const char_type* __beg = __digits.data(); 443 444 money_base::pattern __p; 445 const char_type* __sign; 446 size_type __sign_size; 447 if (!(*__beg == __lit[money_base::_S_minus])) 448 { 449 __p = __lc->_M_pos_format; 450 __sign = __lc->_M_positive_sign; 451 __sign_size = __lc->_M_positive_sign_size; 452 } 453 else 454 { 455 __p = __lc->_M_neg_format; 456 __sign = __lc->_M_negative_sign; 457 __sign_size = __lc->_M_negative_sign_size; 458 if (__digits.size()) 459 ++__beg; 460 } 461 462 // Look for valid numbers in the ctype facet within input digits. 463 size_type __len = __ctype.scan_not(ctype_base::digit, __beg, 464 __beg + __digits.size()) - __beg; 465 if (__len) 466 { 467 // Assume valid input, and attempt to format. 468 // Break down input numbers into base components, as follows: 469 // final_value = grouped units + (decimal point) + (digits) 470 string_type __value; 471 __value.reserve(2 * __len); 472 473 // Add thousands separators to non-decimal digits, per 474 // grouping rules. 475 long __paddec = __len - __lc->_M_frac_digits; 476 if (__paddec > 0) 477 { 478 if (__lc->_M_frac_digits < 0) 479 __paddec = __len; 480 if (__lc->_M_grouping_size) 481 { 482 __value.assign(2 * __paddec, char_type()); 483 _CharT* __vend = 484 std::__add_grouping(&__value[0], __lc->_M_thousands_sep, 485 __lc->_M_grouping, 486 __lc->_M_grouping_size, 487 __beg, __beg + __paddec); 488 __value.erase(__vend - &__value[0]); 489 } 490 else 491 __value.assign(__beg, __paddec); 492 } 493 494 // Deal with decimal point, decimal digits. 495 if (__lc->_M_frac_digits > 0) 496 { 497 __value += __lc->_M_decimal_point; 498 if (__paddec >= 0) 499 __value.append(__beg + __paddec, __lc->_M_frac_digits); 500 else 501 { 502 // Have to pad zeros in the decimal position. 503 __value.append(-__paddec, __lit[money_base::_S_zero]); 504 __value.append(__beg, __len); 505 } 506 } 507 508 // Calculate length of resulting string. 509 const ios_base::fmtflags __f = __io.flags() 510 & ios_base::adjustfield; 511 __len = __value.size() + __sign_size; 512 __len += ((__io.flags() & ios_base::showbase) 513 ? __lc->_M_curr_symbol_size : 0); 514 515 string_type __res; 516 __res.reserve(2 * __len); 517 518 const size_type __width = static_cast<size_type>(__io.width()); 519 const bool __testipad = (__f == ios_base::internal 520 && __len < __width); 521 // Fit formatted digits into the required pattern. 522 for (int __i = 0; __i < 4; ++__i) 523 { 524 const part __which = static_cast<part>(__p.field[__i]); 525 switch (__which) 526 { 527 case money_base::symbol: 528 if (__io.flags() & ios_base::showbase) 529 __res.append(__lc->_M_curr_symbol, 530 __lc->_M_curr_symbol_size); 531 break; 532 case money_base::sign: 533 // Sign might not exist, or be more than one 534 // character long. In that case, add in the rest 535 // below. 536 if (__sign_size) 537 __res += __sign[0]; 538 break; 539 case money_base::value: 540 __res += __value; 541 break; 542 case money_base::space: 543 // At least one space is required, but if internal 544 // formatting is required, an arbitrary number of 545 // fill spaces will be necessary. 546 if (__testipad) 547 __res.append(__width - __len, __fill); 548 else 549 __res += __fill; 550 break; 551 case money_base::none: 552 if (__testipad) 553 __res.append(__width - __len, __fill); 554 break; 555 } 556 } 557 558 // Special case of multi-part sign parts. 559 if (__sign_size > 1) 560 __res.append(__sign + 1, __sign_size - 1); 561 562 // Pad, if still necessary. 563 __len = __res.size(); 564 if (__width > __len) 565 { 566 if (__f == ios_base::left) 567 // After. 568 __res.append(__width - __len, __fill); 569 else 570 // Before. 571 __res.insert(0, __width - __len, __fill); 572 __len = __width; 573 } 574 575 // Write resulting, fully-formatted string to output iterator. 576 __s = std::__write(__s, __res.data(), __len); 577 } 578 __io.width(0); 579 return __s; 580 } 581 582 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \ 583 && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__) 584 template<typename _CharT, typename _OutIter> 585 _OutIter 586 money_put<_CharT, _OutIter>:: 587 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 588 double __units) const 589 { return this->do_put(__s, __intl, __io, __fill, (long double) __units); } 590 #endif 591 592 template<typename _CharT, typename _OutIter> 593 _OutIter 594 money_put<_CharT, _OutIter>:: 595 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 596 long double __units) const 597 { 598 const locale __loc = __io.getloc(); 599 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 600 #if _GLIBCXX_USE_C99_STDIO 601 // First try a buffer perhaps big enough. 602 int __cs_size = 64; 603 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 604 // _GLIBCXX_RESOLVE_LIB_DEFECTS 605 // 328. Bad sprintf format modifier in money_put<>::do_put() 606 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 607 "%.*Lf", 0, __units); 608 // If the buffer was not large enough, try again with the correct size. 609 if (__len >= __cs_size) 610 { 611 __cs_size = __len + 1; 612 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 613 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 614 "%.*Lf", 0, __units); 615 } 616 #else 617 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'. 618 const int __cs_size = 619 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3; 620 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 621 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 622 0, __units); 623 #endif 624 string_type __digits(__len, char_type()); 625 __ctype.widen(__cs, __cs + __len, &__digits[0]); 626 return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 627 : _M_insert<false>(__s, __io, __fill, __digits); 628 } 629 630 template<typename _CharT, typename _OutIter> 631 _OutIter 632 money_put<_CharT, _OutIter>:: 633 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 634 const string_type& __digits) const 635 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 636 : _M_insert<false>(__s, __io, __fill, __digits); } 637 638 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \ 639 && defined __LONG_DOUBLE_IEEE128__ 640 // The snprintf symbol in glibc that works with __ibm128 format is not visible 641 // when compiling with -mabi=ieeelongdouble so we use this name for it instead. 642 // N.B. we don't use __typeof__(__builtin_snprintf) for the type because that 643 // would inherit __attribute__((format(printf, 3, 4))) and give a warning for 644 // passing __ibm128 to %Lf instead of long double. The warning would be wrong 645 // because long double in this TU is __ieee128 and snprintf expects __ibm128. 646 extern "C" int 647 __glibcxx_snprintfibm128(char*, size_t, const char*, ...) __asm__("snprintf"); 648 649 template<typename _CharT, typename _OutIter> 650 _OutIter 651 money_put<_CharT, _OutIter>:: 652 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 653 __ibm128 __units) const 654 { 655 const locale __loc = __io.getloc(); 656 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 657 // First try a buffer perhaps big enough. 658 int __cs_size = 64; 659 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 660 const __c_locale __old = __gnu_cxx::__uselocale(_S_get_c_locale()); 661 662 // _GLIBCXX_RESOLVE_LIB_DEFECTS 663 // 328. Bad sprintf format modifier in money_put<>::do_put() 664 int __len = __glibcxx_snprintfibm128(__cs, __cs_size, "%.*Lf", 0, 665 __units); 666 // If the buffer was not large enough, try again with the correct size. 667 if (__len >= __cs_size) 668 { 669 __cs_size = __len + 1; 670 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 671 __len = __glibcxx_snprintfibm128(__cs, __cs_size, "%.*Lf", 0, 672 __units); 673 } 674 __gnu_cxx::__uselocale(__old); 675 string_type __digits(__len, char_type()); 676 __ctype.widen(__cs, __cs + __len, &__digits[0]); 677 return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 678 : _M_insert<false>(__s, __io, __fill, __digits); 679 } 680 #endif 681 682 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 683 684 // NB: Not especially useful. Without an ios_base object or some 685 // kind of locale reference, we are left clawing at the air where 686 // the side of the mountain used to be... 687 template<typename _CharT, typename _InIter> 688 time_base::dateorder 689 time_get<_CharT, _InIter>::do_date_order() const 690 { return time_base::no_order; } 691 692 // Expand a strptime format string and parse it. E.g., do_get_date() may 693 // pass %m/%d/%Y => extracted characters. 694 template<typename _CharT, typename _InIter> 695 _InIter 696 time_get<_CharT, _InIter>:: 697 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io, 698 ios_base::iostate& __err, tm* __tm, 699 const _CharT* __format, 700 __time_get_state &__state) const 701 { 702 const locale& __loc = __io._M_getloc(); 703 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 704 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 705 const size_t __len = char_traits<_CharT>::length(__format); 706 707 ios_base::iostate __tmperr = ios_base::goodbit; 708 size_t __i = 0; 709 for (; __beg != __end && __i < __len && !__tmperr; ++__i) 710 { 711 if (__ctype.narrow(__format[__i], 0) == '%') 712 { 713 // Verify valid formatting code, attempt to extract. 714 char __c = __ctype.narrow(__format[++__i], 0); 715 int __mem = 0; 716 if (__c == 'E' || __c == 'O') 717 __c = __ctype.narrow(__format[++__i], 0); 718 switch (__c) 719 { 720 const char* __cs; 721 _CharT __wcs[10]; 722 case 'a': 723 case 'A': 724 // Weekday name (possibly abbreviated) [tm_wday] 725 const char_type* __days[14]; 726 __tp._M_days(&__days[0]); 727 __tp._M_days_abbreviated(&__days[7]); 728 __beg = _M_extract_name(__beg, __end, __mem, __days, 729 14, __io, __tmperr); 730 if (!__tmperr) 731 { 732 __tm->tm_wday = __mem % 7; 733 __state._M_have_wday = 1; 734 } 735 break; 736 case 'h': 737 case 'b': 738 case 'B': 739 // Month name (possibly abbreviated) [tm_mon] 740 const char_type* __months[24]; 741 __tp._M_months(&__months[0]); 742 __tp._M_months_abbreviated(&__months[12]); 743 __beg = _M_extract_name(__beg, __end, __mem, 744 __months, 24, __io, __tmperr); 745 if (!__tmperr) 746 { 747 __tm->tm_mon = __mem % 12; 748 __state._M_have_mon = 1; 749 __state._M_want_xday = 1; 750 } 751 break; 752 case 'c': 753 // Default time and date representation. 754 const char_type* __dt[2]; 755 __tp._M_date_time_formats(__dt); 756 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 757 __tm, __dt[0], __state); 758 if (!__tmperr) 759 __state._M_want_xday = 1; 760 break; 761 case 'C': 762 // Century. 763 __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2, 764 __io, __tmperr); 765 if (!__tmperr) 766 { 767 __state._M_century = __mem; 768 __state._M_have_century = 1; 769 __state._M_want_xday = 1; 770 } 771 break; 772 case 'd': 773 case 'e': 774 // Day [1, 31]. [tm_mday] 775 if (__ctype.is(ctype_base::space, *__beg)) 776 ++__beg; 777 __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2, 778 __io, __tmperr); 779 if (!__tmperr) 780 { 781 __tm->tm_mday = __mem; 782 __state._M_have_mday = 1; 783 __state._M_want_xday = 1; 784 } 785 break; 786 case 'D': 787 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 788 __cs = "%m/%d/%y"; 789 __ctype.widen(__cs, __cs + 9, __wcs); 790 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 791 __tm, __wcs, __state); 792 if (!__tmperr) 793 __state._M_want_xday = 1; 794 break; 795 case 'H': 796 // Hour [00, 23]. [tm_hour] 797 __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2, 798 __io, __tmperr); 799 if (!__tmperr) 800 { 801 __tm->tm_hour = __mem; 802 __state._M_have_I = 0; 803 } 804 break; 805 case 'I': 806 // Hour [01, 12]. [tm_hour] 807 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 808 __io, __tmperr); 809 if (!__tmperr) 810 { 811 __tm->tm_hour = __mem % 12; 812 __state._M_have_I = 1; 813 } 814 break; 815 case 'j': 816 // Day number of year. 817 __beg = _M_extract_num(__beg, __end, __mem, 1, 366, 3, 818 __io, __tmperr); 819 if (!__tmperr) 820 { 821 __tm->tm_yday = __mem - 1; 822 __state._M_have_yday = 1; 823 } 824 break; 825 case 'm': 826 // Month [01, 12]. [tm_mon] 827 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 828 __io, __tmperr); 829 if (!__tmperr) 830 { 831 __tm->tm_mon = __mem - 1; 832 __state._M_have_mon = 1; 833 } 834 break; 835 case 'M': 836 // Minute [00, 59]. [tm_min] 837 __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2, 838 __io, __tmperr); 839 if (!__tmperr) 840 __tm->tm_min = __mem; 841 break; 842 case 'n': 843 case 't': 844 while (__beg != __end 845 && __ctype.is(ctype_base::space, *__beg)) 846 ++__beg; 847 break; 848 case 'p': 849 // Locale's a.m. or p.m. 850 const char_type* __ampm[2]; 851 __tp._M_am_pm(&__ampm[0]); 852 if (!__ampm[0][0] || !__ampm[1][0]) 853 break; 854 __beg = _M_extract_name(__beg, __end, __mem, __ampm, 855 2, __io, __tmperr); 856 if (!__tmperr && __mem) 857 __state._M_is_pm = 1; 858 break; 859 case 'r': 860 // Locale's 12-hour clock time format (in C %I:%M:%S %p). 861 const char_type* __ampm_format; 862 __tp._M_am_pm_format(&__ampm_format); 863 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 864 __tm, __ampm_format, __state); 865 break; 866 case 'R': 867 // Equivalent to (%H:%M). 868 __cs = "%H:%M"; 869 __ctype.widen(__cs, __cs + 6, __wcs); 870 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 871 __tm, __wcs, __state); 872 break; 873 case 'S': 874 // Seconds. [tm_sec] 875 // [00, 60] in C99 (one leap-second), [00, 61] in C89. 876 #if _GLIBCXX_USE_C99 877 __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2, 878 #else 879 __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2, 880 #endif 881 __io, __tmperr); 882 if (!__tmperr) 883 __tm->tm_sec = __mem; 884 break; 885 case 'T': 886 // Equivalent to (%H:%M:%S). 887 __cs = "%H:%M:%S"; 888 __ctype.widen(__cs, __cs + 9, __wcs); 889 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 890 __tm, __wcs, __state); 891 break; 892 case 'U': 893 // Week number of the year (Sunday as first day of week). 894 __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2, 895 __io, __tmperr); 896 if (!__tmperr) 897 { 898 __state._M_week_no = __mem; 899 __state._M_have_uweek = 1; 900 } 901 break; 902 case 'w': 903 // Weekday [tm_wday] 904 __beg = _M_extract_num(__beg, __end, __mem, 0, 6, 1, 905 __io, __tmperr); 906 if (!__tmperr) 907 { 908 __tm->tm_wday = __mem; 909 __state._M_have_wday = 1; 910 } 911 break; 912 case 'W': 913 // Week number of the year (Monday as first day of week). 914 __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2, 915 __io, __tmperr); 916 if (!__tmperr) 917 { 918 __state._M_week_no = __mem; 919 __state._M_have_wweek = 1; 920 } 921 break; 922 case 'x': 923 // Locale's date. 924 const char_type* __dates[2]; 925 __tp._M_date_formats(__dates); 926 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 927 __tm, __dates[0], __state); 928 break; 929 case 'X': 930 // Locale's time. 931 const char_type* __times[2]; 932 __tp._M_time_formats(__times); 933 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 934 __tm, __times[0], __state); 935 break; 936 case 'y': 937 // The last 2 digits of year. 938 __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2, 939 __io, __tmperr); 940 if (!__tmperr) 941 { 942 __state._M_want_century = 1; 943 __state._M_want_xday = 1; 944 // As an extension, if the 2 digits are followed by 945 // 1-2 further digits, treat it like %Y. 946 __c = 0; 947 if (__beg != __end) 948 __c = __ctype.narrow(*__beg, '*'); 949 if (__c >= '0' && __c <= '9') 950 { 951 ++__beg; 952 __mem = __mem * 10 + (__c - '0'); 953 if (__beg != __end) 954 { 955 __c = __ctype.narrow(*__beg, '*'); 956 if (__c >= '0' && __c <= '9') 957 { 958 ++__beg; 959 __mem = __mem * 10 + (__c - '0'); 960 } 961 } 962 __mem -= 1900; 963 __state._M_want_century = 0; 964 } 965 // Otherwise, as per POSIX 2008, 00-68 is 2000-2068, 966 // while 69-99 is 1969-1999. 967 else if (__mem < 69) 968 __mem += 100; 969 __tm->tm_year = __mem; 970 } 971 break; 972 case 'Y': 973 // Year. 974 __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4, 975 __io, __tmperr); 976 if (!__tmperr) 977 { 978 __tm->tm_year = __mem - 1900; 979 __state._M_want_century = 0; 980 __state._M_want_xday = 1; 981 } 982 break; 983 case 'Z': 984 // Timezone info. 985 if (__ctype.is(ctype_base::upper, *__beg)) 986 { 987 int __tmp; 988 __beg = _M_extract_name(__beg, __end, __tmp, 989 __timepunct_cache<_CharT>::_S_timezones, 990 14, __io, __tmperr); 991 992 // GMT requires special effort. 993 if (__beg != __end && !__tmperr && __tmp == 0 994 && (*__beg == __ctype.widen('-') 995 || *__beg == __ctype.widen('+'))) 996 { 997 __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 998 __io, __tmperr); 999 __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 1000 __io, __tmperr); 1001 } 1002 } 1003 else 1004 __tmperr |= ios_base::failbit; 1005 break; 1006 case '%': 1007 if (*__beg == __ctype.widen('%')) 1008 ++__beg; 1009 else 1010 __tmperr |= ios_base::failbit; 1011 break; 1012 default: 1013 // Not recognized. 1014 __tmperr |= ios_base::failbit; 1015 } 1016 } 1017 else if (__ctype.is(ctype_base::space, __format[__i])) 1018 { 1019 // Skip any whitespace. 1020 while (__beg != __end 1021 && __ctype.is(ctype_base::space, *__beg)) 1022 ++__beg; 1023 } 1024 else 1025 { 1026 // Verify format and input match, extract and discard. 1027 // TODO real case-insensitive comparison 1028 if (__ctype.tolower(__format[__i]) == __ctype.tolower(*__beg) 1029 || __ctype.toupper(__format[__i]) == __ctype.toupper(*__beg)) 1030 ++__beg; 1031 else 1032 __tmperr |= ios_base::failbit; 1033 } 1034 } 1035 1036 if (__tmperr || __i != __len) 1037 __err |= ios_base::failbit; 1038 1039 return __beg; 1040 } 1041 1042 template<typename _CharT, typename _InIter> 1043 _InIter 1044 time_get<_CharT, _InIter>:: 1045 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io, 1046 ios_base::iostate& __err, tm* __tm, 1047 const _CharT* __format) const 1048 { 1049 __time_get_state __state = __time_get_state(); 1050 return _M_extract_via_format(__beg, __end, __io, __err, __tm, 1051 __format, __state); 1052 } 1053 1054 template<typename _CharT, typename _InIter> 1055 _InIter 1056 time_get<_CharT, _InIter>:: 1057 _M_extract_num(iter_type __beg, iter_type __end, int& __member, 1058 int __min, int __max, size_t __len, 1059 ios_base& __io, ios_base::iostate& __err) const 1060 { 1061 const locale& __loc = __io._M_getloc(); 1062 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1063 1064 size_t __i = 0; 1065 int __value = 0; 1066 for (; __beg != __end && __i < __len; ++__beg, (void)++__i) 1067 { 1068 const char __c = __ctype.narrow(*__beg, '*'); 1069 if (__c >= '0' && __c <= '9') 1070 { 1071 __value = __value * 10 + (__c - '0'); 1072 if (__value > __max) 1073 break; 1074 } 1075 else 1076 break; 1077 } 1078 if (__i && __value >= __min && __value <= __max) 1079 __member = __value; 1080 else 1081 __err |= ios_base::failbit; 1082 1083 return __beg; 1084 } 1085 1086 // Assumptions: 1087 // All elements in __names are unique, except if __indexlen is 1088 // even __names in the first half could be the same as corresponding 1089 // __names in the second half (May is abbreviated as May). Some __names 1090 // elements could be prefixes of other __names elements. 1091 template<typename _CharT, typename _InIter> 1092 _InIter 1093 time_get<_CharT, _InIter>:: 1094 _M_extract_name(iter_type __beg, iter_type __end, int& __member, 1095 const _CharT** __names, size_t __indexlen, 1096 ios_base& __io, ios_base::iostate& __err) const 1097 { 1098 typedef char_traits<_CharT> __traits_type; 1099 const locale& __loc = __io._M_getloc(); 1100 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1101 1102 size_t* __matches 1103 = static_cast<size_t*>(__builtin_alloca(2 * sizeof(size_t) 1104 * __indexlen)); 1105 size_t* __lengths = __matches + __indexlen; 1106 size_t __nmatches = 0; 1107 size_t __pos = 0; 1108 bool __testvalid = true; 1109 const char_type* __name; 1110 bool __begupdated = false; 1111 1112 // Look for initial matches. 1113 if (__beg != __end) 1114 { 1115 const char_type __c = *__beg; 1116 // TODO real case-insensitive comparison 1117 const char_type __cl = __ctype.tolower(__c); 1118 const char_type __cu = __ctype.toupper(__c); 1119 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 1120 if (__cl == __ctype.tolower(__names[__i1][0]) 1121 || __cu == __ctype.toupper(__names[__i1][0])) 1122 { 1123 __lengths[__nmatches] 1124 = __traits_type::length(__names[__i1]); 1125 __matches[__nmatches++] = __i1; 1126 } 1127 } 1128 1129 while (__nmatches > 1) 1130 { 1131 // Find smallest matching string. 1132 size_t __minlen = __lengths[0]; 1133 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2) 1134 __minlen = std::min(__minlen, __lengths[__i2]); 1135 ++__pos; 1136 ++__beg; 1137 if (__pos == __minlen) 1138 { 1139 // If some match has remaining length of 0, 1140 // need to decide if any match with remaining 1141 // length non-zero matches the next character. 1142 // If so, remove all matches with remaining length 1143 // 0 from consideration, otherwise keep only matches 1144 // with remaining length 0. 1145 bool __match_longer = false; 1146 1147 if (__beg != __end) 1148 { 1149 // TODO real case-insensitive comparison 1150 const char_type __cl = __ctype.tolower(*__beg); 1151 const char_type __cu = __ctype.toupper(*__beg); 1152 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) 1153 { 1154 __name = __names[__matches[__i3]]; 1155 if (__lengths[__i3] > __pos 1156 && (__ctype.tolower(__name[__pos]) == __cl 1157 || __ctype.toupper(__name[__pos]) == __cu)) 1158 { 1159 __match_longer = true; 1160 break; 1161 } 1162 } 1163 } 1164 for (size_t __i4 = 0; __i4 < __nmatches;) 1165 if (__match_longer == (__lengths[__i4] == __pos)) 1166 { 1167 __matches[__i4] = __matches[--__nmatches]; 1168 __lengths[__i4] = __lengths[__nmatches]; 1169 } 1170 else 1171 ++__i4; 1172 if (__match_longer) 1173 { 1174 __minlen = __lengths[0]; 1175 for (size_t __i5 = 1; __i5 < __nmatches; ++__i5) 1176 __minlen = std::min(__minlen, __lengths[__i5]); 1177 } 1178 else 1179 { 1180 // Deal with May being full as well as abbreviated month 1181 // name. Pick the smaller index. 1182 if (__nmatches == 2 && (__indexlen & 1) == 0) 1183 { 1184 if (__matches[0] < __indexlen / 2) 1185 { 1186 if (__matches[1] == __matches[0] + __indexlen / 2) 1187 __nmatches = 1; 1188 } 1189 else if (__matches[1] == __matches[0] - __indexlen / 2) 1190 { 1191 __matches[0] = __matches[1]; 1192 __lengths[0] = __lengths[1]; 1193 __nmatches = 1; 1194 } 1195 } 1196 __begupdated = true; 1197 break; 1198 } 1199 } 1200 if (__pos < __minlen && __beg != __end) 1201 { 1202 // TODO real case-insensitive comparison 1203 const char_type __cl = __ctype.tolower(*__beg); 1204 const char_type __cu = __ctype.toupper(*__beg); 1205 for (size_t __i6 = 0; __i6 < __nmatches;) 1206 { 1207 __name = __names[__matches[__i6]]; 1208 if (__ctype.tolower(__name[__pos]) != __cl 1209 && __ctype.toupper(__name[__pos]) != __cu) 1210 { 1211 __matches[__i6] = __matches[--__nmatches]; 1212 __lengths[__i6] = __lengths[__nmatches]; 1213 } 1214 else 1215 ++__i6; 1216 } 1217 } 1218 else 1219 break; 1220 } 1221 1222 if (__nmatches == 1) 1223 { 1224 // Make sure found name is completely extracted. 1225 if (!__begupdated) 1226 { 1227 ++__beg; 1228 ++__pos; 1229 } 1230 __name = __names[__matches[0]]; 1231 const size_t __len = __lengths[0]; 1232 while (__pos < __len 1233 && __beg != __end 1234 // TODO real case-insensitive comparison 1235 && (__ctype.tolower(__name[__pos]) == __ctype.tolower(*__beg) 1236 || (__ctype.toupper(__name[__pos]) 1237 == __ctype.toupper(*__beg)))) 1238 ++__beg, (void)++__pos; 1239 1240 if (__len == __pos) 1241 __member = __matches[0]; 1242 else 1243 __testvalid = false; 1244 } 1245 else 1246 __testvalid = false; 1247 if (!__testvalid) 1248 __err |= ios_base::failbit; 1249 1250 return __beg; 1251 } 1252 1253 template<typename _CharT, typename _InIter> 1254 _InIter 1255 time_get<_CharT, _InIter>:: 1256 _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member, 1257 const _CharT** __names, size_t __indexlen, 1258 ios_base& __io, ios_base::iostate& __err) const 1259 { 1260 typedef char_traits<_CharT> __traits_type; 1261 const locale& __loc = __io._M_getloc(); 1262 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1263 1264 int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int) 1265 * __indexlen)); 1266 size_t __nmatches = 0; 1267 size_t* __matches_lengths = 0; 1268 size_t __pos = 0; 1269 1270 if (__beg != __end) 1271 { 1272 const char_type __c = *__beg; 1273 for (size_t __i = 0; __i < 2 * __indexlen; ++__i) 1274 if (__c == __names[__i][0] 1275 || __c == __ctype.toupper(__names[__i][0])) 1276 __matches[__nmatches++] = __i; 1277 } 1278 1279 if (__nmatches) 1280 { 1281 ++__beg; 1282 ++__pos; 1283 1284 __matches_lengths 1285 = static_cast<size_t*>(__builtin_alloca(sizeof(size_t) 1286 * __nmatches)); 1287 for (size_t __i = 0; __i < __nmatches; ++__i) 1288 __matches_lengths[__i] 1289 = __traits_type::length(__names[__matches[__i]]); 1290 } 1291 1292 for (; __beg != __end; ++__beg, (void)++__pos) 1293 { 1294 size_t __nskipped = 0; 1295 const char_type __c = *__beg; 1296 for (size_t __i = 0; __i < __nmatches;) 1297 { 1298 const char_type* __name = __names[__matches[__i]]; 1299 if (__pos >= __matches_lengths[__i]) 1300 ++__nskipped, ++__i; 1301 else if (!(__name[__pos] == __c)) 1302 { 1303 --__nmatches; 1304 __matches[__i] = __matches[__nmatches]; 1305 __matches_lengths[__i] = __matches_lengths[__nmatches]; 1306 } 1307 else 1308 ++__i; 1309 } 1310 if (__nskipped == __nmatches) 1311 break; 1312 } 1313 1314 if ((__nmatches == 1 && __matches_lengths[0] == __pos) 1315 || (__nmatches == 2 && (__matches_lengths[0] == __pos 1316 || __matches_lengths[1] == __pos))) 1317 __member = (__matches[0] >= (int)__indexlen 1318 ? __matches[0] - (int)__indexlen : __matches[0]); 1319 else 1320 __err |= ios_base::failbit; 1321 1322 return __beg; 1323 } 1324 1325 template<typename _CharT, typename _InIter> 1326 _InIter 1327 time_get<_CharT, _InIter>:: 1328 do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 1329 ios_base::iostate& __err, tm* __tm) const 1330 { 1331 const locale& __loc = __io._M_getloc(); 1332 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1333 const char_type* __times[2]; 1334 __tp._M_time_formats(__times); 1335 __time_get_state __state = __time_get_state(); 1336 __beg = _M_extract_via_format(__beg, __end, __io, __err, 1337 __tm, __times[0], __state); 1338 __state._M_finalize_state(__tm); 1339 if (__beg == __end) 1340 __err |= ios_base::eofbit; 1341 return __beg; 1342 } 1343 1344 template<typename _CharT, typename _InIter> 1345 _InIter 1346 time_get<_CharT, _InIter>:: 1347 do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 1348 ios_base::iostate& __err, tm* __tm) const 1349 { 1350 const locale& __loc = __io._M_getloc(); 1351 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1352 const char_type* __dates[2]; 1353 __tp._M_date_formats(__dates); 1354 __time_get_state __state = __time_get_state(); 1355 __beg = _M_extract_via_format(__beg, __end, __io, __err, 1356 __tm, __dates[0], __state); 1357 __state._M_finalize_state(__tm); 1358 if (__beg == __end) 1359 __err |= ios_base::eofbit; 1360 return __beg; 1361 } 1362 1363 template<typename _CharT, typename _InIter> 1364 _InIter 1365 time_get<_CharT, _InIter>:: 1366 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 1367 ios_base::iostate& __err, tm* __tm) const 1368 { 1369 const locale& __loc = __io._M_getloc(); 1370 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1371 const char_type* __days[14]; 1372 __tp._M_days_abbreviated(__days); 1373 __tp._M_days(__days + 7); 1374 int __tmpwday; 1375 ios_base::iostate __tmperr = ios_base::goodbit; 1376 1377 __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7, 1378 __io, __tmperr); 1379 if (!__tmperr) 1380 __tm->tm_wday = __tmpwday; 1381 else 1382 __err |= ios_base::failbit; 1383 1384 if (__beg == __end) 1385 __err |= ios_base::eofbit; 1386 return __beg; 1387 } 1388 1389 template<typename _CharT, typename _InIter> 1390 _InIter 1391 time_get<_CharT, _InIter>:: 1392 do_get_monthname(iter_type __beg, iter_type __end, 1393 ios_base& __io, ios_base::iostate& __err, tm* __tm) const 1394 { 1395 const locale& __loc = __io._M_getloc(); 1396 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1397 const char_type* __months[24]; 1398 __tp._M_months_abbreviated(__months); 1399 __tp._M_months(__months + 12); 1400 int __tmpmon; 1401 ios_base::iostate __tmperr = ios_base::goodbit; 1402 1403 __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12, 1404 __io, __tmperr); 1405 if (!__tmperr) 1406 __tm->tm_mon = __tmpmon; 1407 else 1408 __err |= ios_base::failbit; 1409 1410 if (__beg == __end) 1411 __err |= ios_base::eofbit; 1412 return __beg; 1413 } 1414 1415 template<typename _CharT, typename _InIter> 1416 _InIter 1417 time_get<_CharT, _InIter>:: 1418 do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 1419 ios_base::iostate& __err, tm* __tm) const 1420 { 1421 int __tmpyear; 1422 ios_base::iostate __tmperr = ios_base::goodbit; 1423 const locale& __loc = __io._M_getloc(); 1424 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1425 1426 __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 99, 2, 1427 __io, __tmperr); 1428 if (!__tmperr) 1429 { 1430 char __c = 0; 1431 if (__beg != __end) 1432 __c = __ctype.narrow(*__beg, '*'); 1433 // For 1-2 digit year, assume 69-99 is 1969-1999, 0-68 is 2000-2068. 1434 // For 3-4 digit year, use it as year. 1435 // __tm->tm_year needs year - 1900 though. 1436 if (__c >= '0' && __c <= '9') 1437 { 1438 ++__beg; 1439 __tmpyear = __tmpyear * 10 + (__c - '0'); 1440 if (__beg != __end) 1441 { 1442 __c = __ctype.narrow(*__beg, '*'); 1443 if (__c >= '0' && __c <= '9') 1444 { 1445 ++__beg; 1446 __tmpyear = __tmpyear * 10 + (__c - '0'); 1447 } 1448 } 1449 __tmpyear -= 1900; 1450 } 1451 else if (__tmpyear < 69) 1452 __tmpyear += 100; 1453 __tm->tm_year = __tmpyear; 1454 } 1455 else 1456 __err |= ios_base::failbit; 1457 1458 if (__beg == __end) 1459 __err |= ios_base::eofbit; 1460 return __beg; 1461 } 1462 1463 #if __cplusplus >= 201103L 1464 template<typename _CharT, typename _InIter> 1465 inline 1466 _InIter 1467 time_get<_CharT, _InIter>:: 1468 get(iter_type __s, iter_type __end, ios_base& __io, 1469 ios_base::iostate& __err, tm* __tm, const char_type* __fmt, 1470 const char_type* __fmtend) const 1471 { 1472 const locale& __loc = __io._M_getloc(); 1473 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1474 __err = ios_base::goodbit; 1475 bool __use_state = false; 1476 #if __GNUC__ >= 5 && !defined(_GLIBCXX_CLANG) 1477 #pragma GCC diagnostic push 1478 #pragma GCC diagnostic ignored "-Wpmf-conversions" 1479 // Nasty hack. The C++ standard mandates that get invokes the do_get 1480 // virtual method, but unfortunately at least without an ABI change 1481 // for the facets we can't keep state across the different do_get 1482 // calls. So e.g. if __fmt is "%p %I:%M:%S", we can't handle it 1483 // properly, because we first handle the %p am/pm specifier and only 1484 // later the 12-hour format specifier. 1485 if ((void*)(this->*(&time_get::do_get)) == (void*)(&time_get::do_get)) 1486 __use_state = true; 1487 #pragma GCC diagnostic pop 1488 #endif 1489 __time_get_state __state = __time_get_state(); 1490 while (__fmt != __fmtend && 1491 __err == ios_base::goodbit) 1492 { 1493 if (__s == __end) 1494 { 1495 __err = ios_base::eofbit | ios_base::failbit; 1496 break; 1497 } 1498 else if (__ctype.narrow(*__fmt, 0) == '%') 1499 { 1500 const char_type* __fmt_start = __fmt; 1501 char __format; 1502 char __mod = 0; 1503 if (++__fmt == __fmtend) 1504 { 1505 __err = ios_base::failbit; 1506 break; 1507 } 1508 const char __c = __ctype.narrow(*__fmt, 0); 1509 if (__c != 'E' && __c != 'O') 1510 __format = __c; 1511 else if (++__fmt != __fmtend) 1512 { 1513 __mod = __c; 1514 __format = __ctype.narrow(*__fmt, 0); 1515 } 1516 else 1517 { 1518 __err = ios_base::failbit; 1519 break; 1520 } 1521 if (__use_state) 1522 { 1523 char_type __new_fmt[4]; 1524 __new_fmt[0] = __fmt_start[0]; 1525 __new_fmt[1] = __fmt_start[1]; 1526 if (__mod) 1527 { 1528 __new_fmt[2] = __fmt_start[2]; 1529 __new_fmt[3] = char_type(); 1530 } 1531 else 1532 __new_fmt[2] = char_type(); 1533 __s = _M_extract_via_format(__s, __end, __io, __err, __tm, 1534 __new_fmt, __state); 1535 if (__s == __end) 1536 __err |= ios_base::eofbit; 1537 } 1538 else 1539 __s = this->do_get(__s, __end, __io, __err, __tm, __format, 1540 __mod); 1541 ++__fmt; 1542 } 1543 else if (__ctype.is(ctype_base::space, *__fmt)) 1544 { 1545 ++__fmt; 1546 while (__fmt != __fmtend && 1547 __ctype.is(ctype_base::space, *__fmt)) 1548 ++__fmt; 1549 1550 while (__s != __end && 1551 __ctype.is(ctype_base::space, *__s)) 1552 ++__s; 1553 } 1554 // TODO real case-insensitive comparison 1555 else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) || 1556 __ctype.toupper(*__s) == __ctype.toupper(*__fmt)) 1557 { 1558 ++__s; 1559 ++__fmt; 1560 } 1561 else 1562 { 1563 __err = ios_base::failbit; 1564 break; 1565 } 1566 } 1567 if (__use_state) 1568 __state._M_finalize_state(__tm); 1569 return __s; 1570 } 1571 1572 template<typename _CharT, typename _InIter> 1573 inline 1574 _InIter 1575 time_get<_CharT, _InIter>:: 1576 do_get(iter_type __beg, iter_type __end, ios_base& __io, 1577 ios_base::iostate& __err, tm* __tm, 1578 char __format, char __mod) const 1579 { 1580 const locale& __loc = __io._M_getloc(); 1581 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1582 __err = ios_base::goodbit; 1583 1584 char_type __fmt[4]; 1585 __fmt[0] = __ctype.widen('%'); 1586 if (!__mod) 1587 { 1588 __fmt[1] = __format; 1589 __fmt[2] = char_type(); 1590 } 1591 else 1592 { 1593 __fmt[1] = __mod; 1594 __fmt[2] = __format; 1595 __fmt[3] = char_type(); 1596 } 1597 1598 __time_get_state __state = __time_get_state(); 1599 __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt, 1600 __state); 1601 __state._M_finalize_state(__tm); 1602 if (__beg == __end) 1603 __err |= ios_base::eofbit; 1604 return __beg; 1605 } 1606 1607 #endif // __cplusplus >= 201103L 1608 1609 template<typename _CharT, typename _OutIter> 1610 _OutIter 1611 time_put<_CharT, _OutIter>:: 1612 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, 1613 const _CharT* __beg, const _CharT* __end) const 1614 { 1615 const locale& __loc = __io._M_getloc(); 1616 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1617 for (; __beg != __end; ++__beg) 1618 if (__ctype.narrow(*__beg, 0) != '%') 1619 { 1620 *__s = *__beg; 1621 ++__s; 1622 } 1623 else if (++__beg != __end) 1624 { 1625 char __format; 1626 char __mod = 0; 1627 const char __c = __ctype.narrow(*__beg, 0); 1628 if (__c != 'E' && __c != 'O') 1629 __format = __c; 1630 else if (++__beg != __end) 1631 { 1632 __mod = __c; 1633 __format = __ctype.narrow(*__beg, 0); 1634 } 1635 else 1636 break; 1637 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod); 1638 } 1639 else 1640 break; 1641 return __s; 1642 } 1643 1644 template<typename _CharT, typename _OutIter> 1645 _OutIter 1646 time_put<_CharT, _OutIter>:: 1647 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 1648 char __format, char __mod) const 1649 { 1650 const locale& __loc = __io._M_getloc(); 1651 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1652 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1653 1654 // NB: This size is arbitrary. Should this be a data member, 1655 // initialized at construction? 1656 const size_t __maxlen = 128; 1657 char_type __res[__maxlen]; 1658 1659 // NB: In IEEE 1003.1-200x, and perhaps other locale models, it 1660 // is possible that the format character will be longer than one 1661 // character. Possibilities include 'E' or 'O' followed by a 1662 // format character: if __mod is not the default argument, assume 1663 // it's a valid modifier. 1664 char_type __fmt[4]; 1665 __fmt[0] = __ctype.widen('%'); 1666 if (!__mod) 1667 { 1668 __fmt[1] = __format; 1669 __fmt[2] = char_type(); 1670 } 1671 else 1672 { 1673 __fmt[1] = __mod; 1674 __fmt[2] = __format; 1675 __fmt[3] = char_type(); 1676 } 1677 1678 __tp._M_put(__res, __maxlen, __fmt, __tm); 1679 1680 // Write resulting, fully-formatted string to output iterator. 1681 return std::__write(__s, __res, char_traits<char_type>::length(__res)); 1682 } 1683 1684 1685 // Inhibit implicit instantiations for required instantiations, 1686 // which are defined via explicit instantiations elsewhere. 1687 #if _GLIBCXX_EXTERN_TEMPLATE 1688 #pragma GCC diagnostic push 1689 #pragma GCC diagnostic ignored "-Wc++11-extensions" // extern template 1690 #pragma GCC diagnostic ignored "-Wlong-long" 1691 extern template class moneypunct<char, false>; 1692 extern template class moneypunct<char, true>; 1693 extern template class moneypunct_byname<char, false>; 1694 extern template class moneypunct_byname<char, true>; 1695 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>; 1696 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>; 1697 extern template class __timepunct<char>; 1698 extern template class time_put<char>; 1699 extern template class time_put_byname<char>; 1700 extern template class time_get<char>; 1701 extern template class time_get_byname<char>; 1702 extern template class messages<char>; 1703 extern template class messages_byname<char>; 1704 1705 extern template 1706 const moneypunct<char, true>* 1707 __try_use_facet<moneypunct<char, true> >(const locale&) _GLIBCXX_NOTHROW; 1708 1709 extern template 1710 const moneypunct<char, false>* 1711 __try_use_facet<moneypunct<char, false> >(const locale&) _GLIBCXX_NOTHROW; 1712 1713 extern template 1714 const money_put<char>* 1715 __try_use_facet<money_put<char> >(const locale&) _GLIBCXX_NOTHROW; 1716 1717 extern template 1718 const money_get<char>* 1719 __try_use_facet<money_get<char> >(const locale&) _GLIBCXX_NOTHROW; 1720 1721 extern template 1722 const __timepunct<char>* 1723 __try_use_facet<__timepunct<char> >(const locale&) _GLIBCXX_NOTHROW; 1724 1725 extern template 1726 const time_put<char>* 1727 __try_use_facet<time_put<char> >(const locale&) _GLIBCXX_NOTHROW; 1728 1729 extern template 1730 const time_get<char>* 1731 __try_use_facet<time_get<char> >(const locale&) _GLIBCXX_NOTHROW; 1732 1733 extern template 1734 const messages<char>* 1735 __try_use_facet<messages<char> >(const locale&) _GLIBCXX_NOTHROW; 1736 1737 extern template 1738 const moneypunct<char, true>& 1739 use_facet<moneypunct<char, true> >(const locale&); 1740 1741 extern template 1742 const moneypunct<char, false>& 1743 use_facet<moneypunct<char, false> >(const locale&); 1744 1745 extern template 1746 const money_put<char>& 1747 use_facet<money_put<char> >(const locale&); 1748 1749 extern template 1750 const money_get<char>& 1751 use_facet<money_get<char> >(const locale&); 1752 1753 extern template 1754 const __timepunct<char>& 1755 use_facet<__timepunct<char> >(const locale&); 1756 1757 extern template 1758 const time_put<char>& 1759 use_facet<time_put<char> >(const locale&); 1760 1761 extern template 1762 const time_get<char>& 1763 use_facet<time_get<char> >(const locale&); 1764 1765 extern template 1766 const messages<char>& 1767 use_facet<messages<char> >(const locale&); 1768 1769 extern template 1770 bool 1771 has_facet<moneypunct<char> >(const locale&); 1772 1773 extern template 1774 bool 1775 has_facet<money_put<char> >(const locale&); 1776 1777 extern template 1778 bool 1779 has_facet<money_get<char> >(const locale&); 1780 1781 extern template 1782 bool 1783 has_facet<__timepunct<char> >(const locale&); 1784 1785 extern template 1786 bool 1787 has_facet<time_put<char> >(const locale&); 1788 1789 extern template 1790 bool 1791 has_facet<time_get<char> >(const locale&); 1792 1793 extern template 1794 bool 1795 has_facet<messages<char> >(const locale&); 1796 1797 #ifdef _GLIBCXX_USE_WCHAR_T 1798 extern template class moneypunct<wchar_t, false>; 1799 extern template class moneypunct<wchar_t, true>; 1800 extern template class moneypunct_byname<wchar_t, false>; 1801 extern template class moneypunct_byname<wchar_t, true>; 1802 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>; 1803 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>; 1804 extern template class __timepunct<wchar_t>; 1805 extern template class time_put<wchar_t>; 1806 extern template class time_put_byname<wchar_t>; 1807 extern template class time_get<wchar_t>; 1808 extern template class time_get_byname<wchar_t>; 1809 extern template class messages<wchar_t>; 1810 extern template class messages_byname<wchar_t>; 1811 1812 extern template 1813 const moneypunct<wchar_t, true>* 1814 __try_use_facet<moneypunct<wchar_t, true> >(const locale&) _GLIBCXX_NOTHROW; 1815 1816 extern template 1817 const moneypunct<wchar_t, false>* 1818 __try_use_facet<moneypunct<wchar_t, false> >(const locale&) _GLIBCXX_NOTHROW; 1819 1820 extern template 1821 const money_put<wchar_t>* 1822 __try_use_facet<money_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW; 1823 1824 extern template 1825 const money_get<wchar_t>* 1826 __try_use_facet<money_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW; 1827 1828 extern template 1829 const __timepunct<wchar_t>* 1830 __try_use_facet<__timepunct<wchar_t> >(const locale&) _GLIBCXX_NOTHROW; 1831 1832 extern template 1833 const time_put<wchar_t>* 1834 __try_use_facet<time_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW; 1835 1836 extern template 1837 const time_get<wchar_t>* 1838 __try_use_facet<time_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW; 1839 1840 extern template 1841 const messages<wchar_t>* 1842 __try_use_facet<messages<wchar_t> >(const locale&) _GLIBCXX_NOTHROW; 1843 1844 extern template 1845 const moneypunct<wchar_t, true>& 1846 use_facet<moneypunct<wchar_t, true> >(const locale&); 1847 1848 extern template 1849 const moneypunct<wchar_t, false>& 1850 use_facet<moneypunct<wchar_t, false> >(const locale&); 1851 1852 extern template 1853 const money_put<wchar_t>& 1854 use_facet<money_put<wchar_t> >(const locale&); 1855 1856 extern template 1857 const money_get<wchar_t>& 1858 use_facet<money_get<wchar_t> >(const locale&); 1859 1860 extern template 1861 const __timepunct<wchar_t>& 1862 use_facet<__timepunct<wchar_t> >(const locale&); 1863 1864 extern template 1865 const time_put<wchar_t>& 1866 use_facet<time_put<wchar_t> >(const locale&); 1867 1868 extern template 1869 const time_get<wchar_t>& 1870 use_facet<time_get<wchar_t> >(const locale&); 1871 1872 extern template 1873 const messages<wchar_t>& 1874 use_facet<messages<wchar_t> >(const locale&); 1875 1876 extern template 1877 bool 1878 has_facet<moneypunct<wchar_t> >(const locale&); 1879 1880 extern template 1881 bool 1882 has_facet<money_put<wchar_t> >(const locale&); 1883 1884 extern template 1885 bool 1886 has_facet<money_get<wchar_t> >(const locale&); 1887 1888 extern template 1889 bool 1890 has_facet<__timepunct<wchar_t> >(const locale&); 1891 1892 extern template 1893 bool 1894 has_facet<time_put<wchar_t> >(const locale&); 1895 1896 extern template 1897 bool 1898 has_facet<time_get<wchar_t> >(const locale&); 1899 1900 extern template 1901 bool 1902 has_facet<messages<wchar_t> >(const locale&); 1903 #endif 1904 #pragma GCC diagnostic pop 1905 #endif 1906 1907 _GLIBCXX_END_NAMESPACE_VERSION 1908 } // namespace std 1909 1910 #endif