1 // Locale support -*- C++ -*- 2 3 // Copyright (C) 2007-2021 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 #pragma GCC system_header 34 35 namespace std _GLIBCXX_VISIBILITY(default) 36 { 37 _GLIBCXX_BEGIN_NAMESPACE_VERSION 38 39 template<typename _CharT, bool _Intl> 40 struct __use_cache<__moneypunct_cache<_CharT, _Intl> > 41 { 42 const __moneypunct_cache<_CharT, _Intl>* operator ()std::__use_cache43 operator() (const locale& __loc) const 44 { 45 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id(); 46 const locale::facet** __caches = __loc._M_impl->_M_caches; 47 if (!__caches[__i]) 48 { 49 __moneypunct_cache<_CharT, _Intl>* __tmp = 0; 50 __try 51 { 52 __tmp = new __moneypunct_cache<_CharT, _Intl>; 53 __tmp->_M_cache(__loc); 54 } 55 __catch(...) 56 { 57 delete __tmp; 58 __throw_exception_again; 59 } 60 __loc._M_impl->_M_install_cache(__tmp, __i); 61 } 62 return static_cast< 63 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]); 64 } 65 }; 66 67 template<typename _CharT, bool _Intl> 68 void _M_cache(const locale & __loc)69 __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc) 70 { 71 const moneypunct<_CharT, _Intl>& __mp = 72 use_facet<moneypunct<_CharT, _Intl> >(__loc); 73 74 _M_decimal_point = __mp.decimal_point(); 75 _M_thousands_sep = __mp.thousands_sep(); 76 _M_frac_digits = __mp.frac_digits(); 77 78 char* __grouping = 0; 79 _CharT* __curr_symbol = 0; 80 _CharT* __positive_sign = 0; 81 _CharT* __negative_sign = 0; 82 __try 83 { 84 const string& __g = __mp.grouping(); 85 _M_grouping_size = __g.size(); 86 __grouping = new char[_M_grouping_size]; 87 __g.copy(__grouping, _M_grouping_size); 88 _M_use_grouping = (_M_grouping_size 89 && static_cast<signed char>(__grouping[0]) > 0 90 && (__grouping[0] 91 != __gnu_cxx::__numeric_traits<char>::__max)); 92 93 const basic_string<_CharT>& __cs = __mp.curr_symbol(); 94 _M_curr_symbol_size = __cs.size(); 95 __curr_symbol = new _CharT[_M_curr_symbol_size]; 96 __cs.copy(__curr_symbol, _M_curr_symbol_size); 97 98 const basic_string<_CharT>& __ps = __mp.positive_sign(); 99 _M_positive_sign_size = __ps.size(); 100 __positive_sign = new _CharT[_M_positive_sign_size]; 101 __ps.copy(__positive_sign, _M_positive_sign_size); 102 103 const basic_string<_CharT>& __ns = __mp.negative_sign(); 104 _M_negative_sign_size = __ns.size(); 105 __negative_sign = new _CharT[_M_negative_sign_size]; 106 __ns.copy(__negative_sign, _M_negative_sign_size); 107 108 _M_pos_format = __mp.pos_format(); 109 _M_neg_format = __mp.neg_format(); 110 111 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 112 __ct.widen(money_base::_S_atoms, 113 money_base::_S_atoms + money_base::_S_end, _M_atoms); 114 115 _M_grouping = __grouping; 116 _M_curr_symbol = __curr_symbol; 117 _M_positive_sign = __positive_sign; 118 _M_negative_sign = __negative_sign; 119 _M_allocated = true; 120 } 121 __catch(...) 122 { 123 delete [] __grouping; 124 delete [] __curr_symbol; 125 delete [] __positive_sign; 126 delete [] __negative_sign; 127 __throw_exception_again; 128 } 129 } 130 131 _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 132 133 template<typename _CharT, typename _InIter> 134 template<bool _Intl> 135 _InIter 136 money_get<_CharT, _InIter>:: _M_extract(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,string & __units) const137 _M_extract(iter_type __beg, iter_type __end, ios_base& __io, 138 ios_base::iostate& __err, string& __units) const 139 { 140 typedef char_traits<_CharT> __traits_type; 141 typedef typename string_type::size_type size_type; 142 typedef money_base::part part; 143 typedef __moneypunct_cache<_CharT, _Intl> __cache_type; 144 145 const locale& __loc = __io._M_getloc(); 146 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 147 148 __use_cache<__cache_type> __uc; 149 const __cache_type* __lc = __uc(__loc); 150 const char_type* __lit = __lc->_M_atoms; 151 152 // Deduced sign. 153 bool __negative = false; 154 // Sign size. 155 size_type __sign_size = 0; 156 // True if sign is mandatory. 157 const bool __mandatory_sign = (__lc->_M_positive_sign_size 158 && __lc->_M_negative_sign_size); 159 // String of grouping info from thousands_sep plucked from __units. 160 string __grouping_tmp; 161 if (__lc->_M_use_grouping) 162 __grouping_tmp.reserve(32); 163 // Last position before the decimal point. 164 int __last_pos = 0; 165 // Separator positions, then, possibly, fractional digits. 166 int __n = 0; 167 // If input iterator is in a valid state. 168 bool __testvalid = true; 169 // Flag marking when a decimal point is found. 170 bool __testdecfound = false; 171 172 // The tentative returned string is stored here. 173 string __res; 174 __res.reserve(32); 175 176 const char_type* __lit_zero = __lit + money_base::_S_zero; 177 const money_base::pattern __p = __lc->_M_neg_format; 178 for (int __i = 0; __i < 4 && __testvalid; ++__i) 179 { 180 const part __which = static_cast<part>(__p.field[__i]); 181 switch (__which) 182 { 183 case money_base::symbol: 184 // According to 22.2.6.1.2, p2, symbol is required 185 // if (__io.flags() & ios_base::showbase), otherwise 186 // is optional and consumed only if other characters 187 // are needed to complete the format. 188 if (__io.flags() & ios_base::showbase || __sign_size > 1 189 || __i == 0 190 || (__i == 1 && (__mandatory_sign 191 || (static_cast<part>(__p.field[0]) 192 == money_base::sign) 193 || (static_cast<part>(__p.field[2]) 194 == money_base::space))) 195 || (__i == 2 && ((static_cast<part>(__p.field[3]) 196 == money_base::value) 197 || (__mandatory_sign 198 && (static_cast<part>(__p.field[3]) 199 == money_base::sign))))) 200 { 201 const size_type __len = __lc->_M_curr_symbol_size; 202 size_type __j = 0; 203 for (; __beg != __end && __j < __len 204 && *__beg == __lc->_M_curr_symbol[__j]; 205 ++__beg, (void)++__j); 206 if (__j != __len 207 && (__j || __io.flags() & ios_base::showbase)) 208 __testvalid = false; 209 } 210 break; 211 case money_base::sign: 212 // Sign might not exist, or be more than one character long. 213 if (__lc->_M_positive_sign_size && __beg != __end 214 && *__beg == __lc->_M_positive_sign[0]) 215 { 216 __sign_size = __lc->_M_positive_sign_size; 217 ++__beg; 218 } 219 else if (__lc->_M_negative_sign_size && __beg != __end 220 && *__beg == __lc->_M_negative_sign[0]) 221 { 222 __negative = true; 223 __sign_size = __lc->_M_negative_sign_size; 224 ++__beg; 225 } 226 else if (__lc->_M_positive_sign_size 227 && !__lc->_M_negative_sign_size) 228 // "... if no sign is detected, the result is given the sign 229 // that corresponds to the source of the empty string" 230 __negative = true; 231 else if (__mandatory_sign) 232 __testvalid = false; 233 break; 234 case money_base::value: 235 // Extract digits, remove and stash away the 236 // grouping of found thousands separators. 237 for (; __beg != __end; ++__beg) 238 { 239 const char_type __c = *__beg; 240 const char_type* __q = __traits_type::find(__lit_zero, 241 10, __c); 242 if (__q != 0) 243 { 244 __res += money_base::_S_atoms[__q - __lit]; 245 ++__n; 246 } 247 else if (__c == __lc->_M_decimal_point 248 && !__testdecfound) 249 { 250 if (__lc->_M_frac_digits <= 0) 251 break; 252 253 __last_pos = __n; 254 __n = 0; 255 __testdecfound = true; 256 } 257 else if (__lc->_M_use_grouping 258 && __c == __lc->_M_thousands_sep 259 && !__testdecfound) 260 { 261 if (__n) 262 { 263 // Mark position for later analysis. 264 __grouping_tmp += static_cast<char>(__n); 265 __n = 0; 266 } 267 else 268 { 269 __testvalid = false; 270 break; 271 } 272 } 273 else 274 break; 275 } 276 if (__res.empty()) 277 __testvalid = false; 278 break; 279 case money_base::space: 280 // At least one space is required. 281 if (__beg != __end && __ctype.is(ctype_base::space, *__beg)) 282 ++__beg; 283 else 284 __testvalid = false; 285 // fallthrough 286 case money_base::none: 287 // Only if not at the end of the pattern. 288 if (__i != 3) 289 for (; __beg != __end 290 && __ctype.is(ctype_base::space, *__beg); ++__beg); 291 break; 292 } 293 } 294 295 // Need to get the rest of the sign characters, if they exist. 296 if (__sign_size > 1 && __testvalid) 297 { 298 const char_type* __sign = __negative ? __lc->_M_negative_sign 299 : __lc->_M_positive_sign; 300 size_type __i = 1; 301 for (; __beg != __end && __i < __sign_size 302 && *__beg == __sign[__i]; ++__beg, (void)++__i); 303 304 if (__i != __sign_size) 305 __testvalid = false; 306 } 307 308 if (__testvalid) 309 { 310 // Strip leading zeros. 311 if (__res.size() > 1) 312 { 313 const size_type __first = __res.find_first_not_of('0'); 314 const bool __only_zeros = __first == string::npos; 315 if (__first) 316 __res.erase(0, __only_zeros ? __res.size() - 1 : __first); 317 } 318 319 // 22.2.6.1.2, p4 320 if (__negative && __res[0] != '0') 321 __res.insert(__res.begin(), '-'); 322 323 // Test for grouping fidelity. 324 if (__grouping_tmp.size()) 325 { 326 // Add the ending grouping. 327 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos 328 : __n); 329 if (!std::__verify_grouping(__lc->_M_grouping, 330 __lc->_M_grouping_size, 331 __grouping_tmp)) 332 __err |= ios_base::failbit; 333 } 334 335 // Iff not enough digits were supplied after the decimal-point. 336 if (__testdecfound && __n != __lc->_M_frac_digits) 337 __testvalid = false; 338 } 339 340 // Iff valid sequence is not recognized. 341 if (!__testvalid) 342 __err |= ios_base::failbit; 343 else 344 __units.swap(__res); 345 346 // Iff no more characters are available. 347 if (__beg == __end) 348 __err |= ios_base::eofbit; 349 return __beg; 350 } 351 352 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \ 353 && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__) 354 template<typename _CharT, typename _InIter> 355 _InIter 356 money_get<_CharT, _InIter>:: __do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,double & __units) const357 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 358 ios_base::iostate& __err, double& __units) const 359 { 360 string __str; 361 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 362 : _M_extract<false>(__beg, __end, __io, __err, __str); 363 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 364 return __beg; 365 } 366 #endif 367 368 template<typename _CharT, typename _InIter> 369 _InIter 370 money_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,long double & __units) const371 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 372 ios_base::iostate& __err, long double& __units) const 373 { 374 string __str; 375 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 376 : _M_extract<false>(__beg, __end, __io, __err, __str); 377 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 378 return __beg; 379 } 380 381 template<typename _CharT, typename _InIter> 382 _InIter 383 money_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,string_type & __digits) const384 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 385 ios_base::iostate& __err, string_type& __digits) const 386 { 387 typedef typename string::size_type size_type; 388 389 const locale& __loc = __io._M_getloc(); 390 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 391 392 string __str; 393 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 394 : _M_extract<false>(__beg, __end, __io, __err, __str); 395 const size_type __len = __str.size(); 396 if (__len) 397 { 398 __digits.resize(__len); 399 __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]); 400 } 401 return __beg; 402 } 403 404 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \ 405 && defined __LONG_DOUBLE_IEEE128__ 406 template<typename _CharT, typename _InIter> 407 _InIter 408 money_get<_CharT, _InIter>:: __do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,__ibm128 & __units) const409 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 410 ios_base::iostate& __err, __ibm128& __units) const 411 { 412 string __str; 413 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 414 : _M_extract<false>(__beg, __end, __io, __err, __str); 415 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 416 return __beg; 417 } 418 #endif 419 420 template<typename _CharT, typename _OutIter> 421 template<bool _Intl> 422 _OutIter 423 money_put<_CharT, _OutIter>:: _M_insert(iter_type __s,ios_base & __io,char_type __fill,const string_type & __digits) const424 _M_insert(iter_type __s, ios_base& __io, char_type __fill, 425 const string_type& __digits) const 426 { 427 typedef typename string_type::size_type size_type; 428 typedef money_base::part part; 429 typedef __moneypunct_cache<_CharT, _Intl> __cache_type; 430 431 const locale& __loc = __io._M_getloc(); 432 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 433 434 __use_cache<__cache_type> __uc; 435 const __cache_type* __lc = __uc(__loc); 436 const char_type* __lit = __lc->_M_atoms; 437 438 // Determine if negative or positive formats are to be used, and 439 // discard leading negative_sign if it is present. 440 const char_type* __beg = __digits.data(); 441 442 money_base::pattern __p; 443 const char_type* __sign; 444 size_type __sign_size; 445 if (!(*__beg == __lit[money_base::_S_minus])) 446 { 447 __p = __lc->_M_pos_format; 448 __sign = __lc->_M_positive_sign; 449 __sign_size = __lc->_M_positive_sign_size; 450 } 451 else 452 { 453 __p = __lc->_M_neg_format; 454 __sign = __lc->_M_negative_sign; 455 __sign_size = __lc->_M_negative_sign_size; 456 if (__digits.size()) 457 ++__beg; 458 } 459 460 // Look for valid numbers in the ctype facet within input digits. 461 size_type __len = __ctype.scan_not(ctype_base::digit, __beg, 462 __beg + __digits.size()) - __beg; 463 if (__len) 464 { 465 // Assume valid input, and attempt to format. 466 // Break down input numbers into base components, as follows: 467 // final_value = grouped units + (decimal point) + (digits) 468 string_type __value; 469 __value.reserve(2 * __len); 470 471 // Add thousands separators to non-decimal digits, per 472 // grouping rules. 473 long __paddec = __len - __lc->_M_frac_digits; 474 if (__paddec > 0) 475 { 476 if (__lc->_M_frac_digits < 0) 477 __paddec = __len; 478 if (__lc->_M_grouping_size) 479 { 480 __value.assign(2 * __paddec, char_type()); 481 _CharT* __vend = 482 std::__add_grouping(&__value[0], __lc->_M_thousands_sep, 483 __lc->_M_grouping, 484 __lc->_M_grouping_size, 485 __beg, __beg + __paddec); 486 __value.erase(__vend - &__value[0]); 487 } 488 else 489 __value.assign(__beg, __paddec); 490 } 491 492 // Deal with decimal point, decimal digits. 493 if (__lc->_M_frac_digits > 0) 494 { 495 __value += __lc->_M_decimal_point; 496 if (__paddec >= 0) 497 __value.append(__beg + __paddec, __lc->_M_frac_digits); 498 else 499 { 500 // Have to pad zeros in the decimal position. 501 __value.append(-__paddec, __lit[money_base::_S_zero]); 502 __value.append(__beg, __len); 503 } 504 } 505 506 // Calculate length of resulting string. 507 const ios_base::fmtflags __f = __io.flags() 508 & ios_base::adjustfield; 509 __len = __value.size() + __sign_size; 510 __len += ((__io.flags() & ios_base::showbase) 511 ? __lc->_M_curr_symbol_size : 0); 512 513 string_type __res; 514 __res.reserve(2 * __len); 515 516 const size_type __width = static_cast<size_type>(__io.width()); 517 const bool __testipad = (__f == ios_base::internal 518 && __len < __width); 519 // Fit formatted digits into the required pattern. 520 for (int __i = 0; __i < 4; ++__i) 521 { 522 const part __which = static_cast<part>(__p.field[__i]); 523 switch (__which) 524 { 525 case money_base::symbol: 526 if (__io.flags() & ios_base::showbase) 527 __res.append(__lc->_M_curr_symbol, 528 __lc->_M_curr_symbol_size); 529 break; 530 case money_base::sign: 531 // Sign might not exist, or be more than one 532 // character long. In that case, add in the rest 533 // below. 534 if (__sign_size) 535 __res += __sign[0]; 536 break; 537 case money_base::value: 538 __res += __value; 539 break; 540 case money_base::space: 541 // At least one space is required, but if internal 542 // formatting is required, an arbitrary number of 543 // fill spaces will be necessary. 544 if (__testipad) 545 __res.append(__width - __len, __fill); 546 else 547 __res += __fill; 548 break; 549 case money_base::none: 550 if (__testipad) 551 __res.append(__width - __len, __fill); 552 break; 553 } 554 } 555 556 // Special case of multi-part sign parts. 557 if (__sign_size > 1) 558 __res.append(__sign + 1, __sign_size - 1); 559 560 // Pad, if still necessary. 561 __len = __res.size(); 562 if (__width > __len) 563 { 564 if (__f == ios_base::left) 565 // After. 566 __res.append(__width - __len, __fill); 567 else 568 // Before. 569 __res.insert(0, __width - __len, __fill); 570 __len = __width; 571 } 572 573 // Write resulting, fully-formatted string to output iterator. 574 __s = std::__write(__s, __res.data(), __len); 575 } 576 __io.width(0); 577 return __s; 578 } 579 580 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \ 581 && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__) 582 template<typename _CharT, typename _OutIter> 583 _OutIter 584 money_put<_CharT, _OutIter>:: __do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,double __units) const585 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 586 double __units) const 587 { return this->do_put(__s, __intl, __io, __fill, (long double) __units); } 588 #endif 589 590 template<typename _CharT, typename _OutIter> 591 _OutIter 592 money_put<_CharT, _OutIter>:: do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,long double __units) const593 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 594 long double __units) const 595 { 596 const locale __loc = __io.getloc(); 597 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 598 #if _GLIBCXX_USE_C99_STDIO 599 // First try a buffer perhaps big enough. 600 int __cs_size = 64; 601 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 602 // _GLIBCXX_RESOLVE_LIB_DEFECTS 603 // 328. Bad sprintf format modifier in money_put<>::do_put() 604 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 605 "%.*Lf", 0, __units); 606 // If the buffer was not large enough, try again with the correct size. 607 if (__len >= __cs_size) 608 { 609 __cs_size = __len + 1; 610 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 611 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 612 "%.*Lf", 0, __units); 613 } 614 #else 615 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'. 616 const int __cs_size = 617 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3; 618 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 619 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 620 0, __units); 621 #endif 622 string_type __digits(__len, char_type()); 623 __ctype.widen(__cs, __cs + __len, &__digits[0]); 624 return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 625 : _M_insert<false>(__s, __io, __fill, __digits); 626 } 627 628 template<typename _CharT, typename _OutIter> 629 _OutIter 630 money_put<_CharT, _OutIter>:: do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,const string_type & __digits) const631 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 632 const string_type& __digits) const 633 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 634 : _M_insert<false>(__s, __io, __fill, __digits); } 635 636 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \ 637 && defined __LONG_DOUBLE_IEEE128__ 638 template<typename _CharT, typename _OutIter> 639 _OutIter 640 money_put<_CharT, _OutIter>:: __do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,__ibm128 __units) const641 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 642 __ibm128 __units) const 643 { 644 const locale __loc = __io.getloc(); 645 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 646 #if _GLIBCXX_USE_C99_STDIO 647 // First try a buffer perhaps big enough. 648 int __cs_size = 64; 649 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 650 // _GLIBCXX_RESOLVE_LIB_DEFECTS 651 // 328. Bad sprintf format modifier in money_put<>::do_put() 652 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 653 "%.*Lf", 0, __units); 654 // If the buffer was not large enough, try again with the correct size. 655 if (__len >= __cs_size) 656 { 657 __cs_size = __len + 1; 658 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 659 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 660 "%.*Lf", 0, __units); 661 } 662 #else 663 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'. 664 const int __cs_size = 665 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3; 666 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 667 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 668 0, __units); 669 #endif 670 string_type __digits(__len, char_type()); 671 __ctype.widen(__cs, __cs + __len, &__digits[0]); 672 return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 673 : _M_insert<false>(__s, __io, __fill, __digits); 674 } 675 #endif 676 677 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 678 679 // NB: Not especially useful. Without an ios_base object or some 680 // kind of locale reference, we are left clawing at the air where 681 // the side of the mountain used to be... 682 template<typename _CharT, typename _InIter> 683 time_base::dateorder do_date_order() const684 time_get<_CharT, _InIter>::do_date_order() const 685 { return time_base::no_order; } 686 687 // Expand a strftime format string and parse it. E.g., do_get_date() may 688 // pass %m/%d/%Y => extracted characters. 689 template<typename _CharT, typename _InIter> 690 _InIter 691 time_get<_CharT, _InIter>:: _M_extract_via_format(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm,const _CharT * __format) const692 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io, 693 ios_base::iostate& __err, tm* __tm, 694 const _CharT* __format) const 695 { 696 const locale& __loc = __io._M_getloc(); 697 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 698 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 699 const size_t __len = char_traits<_CharT>::length(__format); 700 701 ios_base::iostate __tmperr = ios_base::goodbit; 702 size_t __i = 0; 703 for (; __beg != __end && __i < __len && !__tmperr; ++__i) 704 { 705 if (__ctype.narrow(__format[__i], 0) == '%') 706 { 707 // Verify valid formatting code, attempt to extract. 708 char __c = __ctype.narrow(__format[++__i], 0); 709 int __mem = 0; 710 if (__c == 'E' || __c == 'O') 711 __c = __ctype.narrow(__format[++__i], 0); 712 switch (__c) 713 { 714 const char* __cs; 715 _CharT __wcs[10]; 716 case 'a': 717 // Abbreviated weekday name [tm_wday] 718 const char_type* __days1[7]; 719 __tp._M_days_abbreviated(__days1); 720 __beg = _M_extract_name(__beg, __end, __mem, __days1, 721 7, __io, __tmperr); 722 if (!__tmperr) 723 __tm->tm_wday = __mem; 724 break; 725 case 'A': 726 // Weekday name [tm_wday]. 727 const char_type* __days2[7]; 728 __tp._M_days(__days2); 729 __beg = _M_extract_name(__beg, __end, __mem, __days2, 730 7, __io, __tmperr); 731 if (!__tmperr) 732 __tm->tm_wday = __mem; 733 break; 734 case 'h': 735 case 'b': 736 // Abbreviated month name [tm_mon] 737 const char_type* __months1[12]; 738 __tp._M_months_abbreviated(__months1); 739 __beg = _M_extract_name(__beg, __end, __mem, 740 __months1, 12, __io, __tmperr); 741 if (!__tmperr) 742 __tm->tm_mon = __mem; 743 break; 744 case 'B': 745 // Month name [tm_mon]. 746 const char_type* __months2[12]; 747 __tp._M_months(__months2); 748 __beg = _M_extract_name(__beg, __end, __mem, 749 __months2, 12, __io, __tmperr); 750 if (!__tmperr) 751 __tm->tm_mon = __mem; 752 break; 753 case 'c': 754 // Default time and date representation. 755 const char_type* __dt[2]; 756 __tp._M_date_time_formats(__dt); 757 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 758 __tm, __dt[0]); 759 break; 760 case 'd': 761 // Day [01, 31]. [tm_mday] 762 __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2, 763 __io, __tmperr); 764 if (!__tmperr) 765 __tm->tm_mday = __mem; 766 break; 767 case 'e': 768 // Day [1, 31], with single digits preceded by 769 // space. [tm_mday] 770 if (__ctype.is(ctype_base::space, *__beg)) 771 __beg = _M_extract_num(++__beg, __end, __mem, 1, 9, 772 1, __io, __tmperr); 773 else 774 __beg = _M_extract_num(__beg, __end, __mem, 10, 31, 775 2, __io, __tmperr); 776 if (!__tmperr) 777 __tm->tm_mday = __mem; 778 break; 779 case 'D': 780 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 781 __cs = "%m/%d/%y"; 782 __ctype.widen(__cs, __cs + 9, __wcs); 783 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 784 __tm, __wcs); 785 break; 786 case 'H': 787 // Hour [00, 23]. [tm_hour] 788 __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2, 789 __io, __tmperr); 790 if (!__tmperr) 791 __tm->tm_hour = __mem; 792 break; 793 case 'I': 794 // Hour [01, 12]. [tm_hour] 795 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 796 __io, __tmperr); 797 if (!__tmperr) 798 __tm->tm_hour = __mem; 799 break; 800 case 'm': 801 // Month [01, 12]. [tm_mon] 802 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 803 __io, __tmperr); 804 if (!__tmperr) 805 __tm->tm_mon = __mem - 1; 806 break; 807 case 'M': 808 // Minute [00, 59]. [tm_min] 809 __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2, 810 __io, __tmperr); 811 if (!__tmperr) 812 __tm->tm_min = __mem; 813 break; 814 case 'n': 815 if (__ctype.narrow(*__beg, 0) == '\n') 816 ++__beg; 817 else 818 __tmperr |= ios_base::failbit; 819 break; 820 case 'R': 821 // Equivalent to (%H:%M). 822 __cs = "%H:%M"; 823 __ctype.widen(__cs, __cs + 6, __wcs); 824 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 825 __tm, __wcs); 826 break; 827 case 'S': 828 // Seconds. [tm_sec] 829 // [00, 60] in C99 (one leap-second), [00, 61] in C89. 830 #if _GLIBCXX_USE_C99 831 __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2, 832 #else 833 __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2, 834 #endif 835 __io, __tmperr); 836 if (!__tmperr) 837 __tm->tm_sec = __mem; 838 break; 839 case 't': 840 if (__ctype.narrow(*__beg, 0) == '\t') 841 ++__beg; 842 else 843 __tmperr |= ios_base::failbit; 844 break; 845 case 'T': 846 // Equivalent to (%H:%M:%S). 847 __cs = "%H:%M:%S"; 848 __ctype.widen(__cs, __cs + 9, __wcs); 849 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 850 __tm, __wcs); 851 break; 852 case 'x': 853 // Locale's date. 854 const char_type* __dates[2]; 855 __tp._M_date_formats(__dates); 856 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 857 __tm, __dates[0]); 858 break; 859 case 'X': 860 // Locale's time. 861 const char_type* __times[2]; 862 __tp._M_time_formats(__times); 863 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 864 __tm, __times[0]); 865 break; 866 case 'y': 867 case 'C': // C99 868 // Two digit year. 869 case 'Y': 870 // Year [1900). 871 // NB: We parse either two digits, implicitly years since 872 // 1900, or 4 digits, full year. In both cases we can 873 // reconstruct [tm_year]. See also libstdc++/26701. 874 __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4, 875 __io, __tmperr); 876 if (!__tmperr) 877 __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900; 878 break; 879 case 'Z': 880 // Timezone info. 881 if (__ctype.is(ctype_base::upper, *__beg)) 882 { 883 int __tmp; 884 __beg = _M_extract_name(__beg, __end, __tmp, 885 __timepunct_cache<_CharT>::_S_timezones, 886 14, __io, __tmperr); 887 888 // GMT requires special effort. 889 if (__beg != __end && !__tmperr && __tmp == 0 890 && (*__beg == __ctype.widen('-') 891 || *__beg == __ctype.widen('+'))) 892 { 893 __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 894 __io, __tmperr); 895 __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 896 __io, __tmperr); 897 } 898 } 899 else 900 __tmperr |= ios_base::failbit; 901 break; 902 default: 903 // Not recognized. 904 __tmperr |= ios_base::failbit; 905 } 906 } 907 else 908 { 909 // Verify format and input match, extract and discard. 910 if (__format[__i] == *__beg) 911 ++__beg; 912 else 913 __tmperr |= ios_base::failbit; 914 } 915 } 916 917 if (__tmperr || __i != __len) 918 __err |= ios_base::failbit; 919 920 return __beg; 921 } 922 923 template<typename _CharT, typename _InIter> 924 _InIter 925 time_get<_CharT, _InIter>:: _M_extract_num(iter_type __beg,iter_type __end,int & __member,int __min,int __max,size_t __len,ios_base & __io,ios_base::iostate & __err) const926 _M_extract_num(iter_type __beg, iter_type __end, int& __member, 927 int __min, int __max, size_t __len, 928 ios_base& __io, ios_base::iostate& __err) const 929 { 930 const locale& __loc = __io._M_getloc(); 931 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 932 933 // As-is works for __len = 1, 2, 4, the values actually used. 934 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1); 935 936 ++__min; 937 size_t __i = 0; 938 int __value = 0; 939 for (; __beg != __end && __i < __len; ++__beg, (void)++__i) 940 { 941 const char __c = __ctype.narrow(*__beg, '*'); 942 if (__c >= '0' && __c <= '9') 943 { 944 __value = __value * 10 + (__c - '0'); 945 const int __valuec = __value * __mult; 946 if (__valuec > __max || __valuec + __mult < __min) 947 break; 948 __mult /= 10; 949 } 950 else 951 break; 952 } 953 if (__i == __len) 954 __member = __value; 955 // Special encoding for do_get_year, 'y', and 'Y' above. 956 else if (__len == 4 && __i == 2) 957 __member = __value - 100; 958 else 959 __err |= ios_base::failbit; 960 961 return __beg; 962 } 963 964 // Assumptions: 965 // All elements in __names are unique. 966 template<typename _CharT, typename _InIter> 967 _InIter 968 time_get<_CharT, _InIter>:: _M_extract_name(iter_type __beg,iter_type __end,int & __member,const _CharT ** __names,size_t __indexlen,ios_base & __io,ios_base::iostate & __err) const969 _M_extract_name(iter_type __beg, iter_type __end, int& __member, 970 const _CharT** __names, size_t __indexlen, 971 ios_base& __io, ios_base::iostate& __err) const 972 { 973 typedef char_traits<_CharT> __traits_type; 974 const locale& __loc = __io._M_getloc(); 975 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 976 977 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 978 * __indexlen)); 979 size_t __nmatches = 0; 980 size_t __pos = 0; 981 bool __testvalid = true; 982 const char_type* __name; 983 984 // Look for initial matches. 985 // NB: Some of the locale data is in the form of all lowercase 986 // names, and some is in the form of initially-capitalized 987 // names. Look for both. 988 if (__beg != __end) 989 { 990 const char_type __c = *__beg; 991 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 992 if (__c == __names[__i1][0] 993 || __c == __ctype.toupper(__names[__i1][0])) 994 __matches[__nmatches++] = __i1; 995 } 996 997 while (__nmatches > 1) 998 { 999 // Find smallest matching string. 1000 size_t __minlen = __traits_type::length(__names[__matches[0]]); 1001 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2) 1002 __minlen = std::min(__minlen, 1003 __traits_type::length(__names[__matches[__i2]])); 1004 ++__beg; 1005 ++__pos; 1006 if (__pos < __minlen && __beg != __end) 1007 for (size_t __i3 = 0; __i3 < __nmatches;) 1008 { 1009 __name = __names[__matches[__i3]]; 1010 if (!(__name[__pos] == *__beg)) 1011 __matches[__i3] = __matches[--__nmatches]; 1012 else 1013 ++__i3; 1014 } 1015 else 1016 break; 1017 } 1018 1019 if (__nmatches == 1) 1020 { 1021 // Make sure found name is completely extracted. 1022 ++__beg; 1023 ++__pos; 1024 __name = __names[__matches[0]]; 1025 const size_t __len = __traits_type::length(__name); 1026 while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 1027 ++__beg, (void)++__pos; 1028 1029 if (__len == __pos) 1030 __member = __matches[0]; 1031 else 1032 __testvalid = false; 1033 } 1034 else 1035 __testvalid = false; 1036 if (!__testvalid) 1037 __err |= ios_base::failbit; 1038 1039 return __beg; 1040 } 1041 1042 template<typename _CharT, typename _InIter> 1043 _InIter 1044 time_get<_CharT, _InIter>:: _M_extract_wday_or_month(iter_type __beg,iter_type __end,int & __member,const _CharT ** __names,size_t __indexlen,ios_base & __io,ios_base::iostate & __err) const1045 _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member, 1046 const _CharT** __names, size_t __indexlen, 1047 ios_base& __io, ios_base::iostate& __err) const 1048 { 1049 typedef char_traits<_CharT> __traits_type; 1050 const locale& __loc = __io._M_getloc(); 1051 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1052 1053 int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int) 1054 * __indexlen)); 1055 size_t __nmatches = 0; 1056 size_t* __matches_lengths = 0; 1057 size_t __pos = 0; 1058 1059 if (__beg != __end) 1060 { 1061 const char_type __c = *__beg; 1062 for (size_t __i = 0; __i < 2 * __indexlen; ++__i) 1063 if (__c == __names[__i][0] 1064 || __c == __ctype.toupper(__names[__i][0])) 1065 __matches[__nmatches++] = __i; 1066 } 1067 1068 if (__nmatches) 1069 { 1070 ++__beg; 1071 ++__pos; 1072 1073 __matches_lengths 1074 = static_cast<size_t*>(__builtin_alloca(sizeof(size_t) 1075 * __nmatches)); 1076 for (size_t __i = 0; __i < __nmatches; ++__i) 1077 __matches_lengths[__i] 1078 = __traits_type::length(__names[__matches[__i]]); 1079 } 1080 1081 for (; __beg != __end; ++__beg, (void)++__pos) 1082 { 1083 size_t __nskipped = 0; 1084 const char_type __c = *__beg; 1085 for (size_t __i = 0; __i < __nmatches;) 1086 { 1087 const char_type* __name = __names[__matches[__i]]; 1088 if (__pos >= __matches_lengths[__i]) 1089 ++__nskipped, ++__i; 1090 else if (!(__name[__pos] == __c)) 1091 { 1092 --__nmatches; 1093 __matches[__i] = __matches[__nmatches]; 1094 __matches_lengths[__i] = __matches_lengths[__nmatches]; 1095 } 1096 else 1097 ++__i; 1098 } 1099 if (__nskipped == __nmatches) 1100 break; 1101 } 1102 1103 if ((__nmatches == 1 && __matches_lengths[0] == __pos) 1104 || (__nmatches == 2 && (__matches_lengths[0] == __pos 1105 || __matches_lengths[1] == __pos))) 1106 __member = (__matches[0] >= (int)__indexlen 1107 ? __matches[0] - (int)__indexlen : __matches[0]); 1108 else 1109 __err |= ios_base::failbit; 1110 1111 return __beg; 1112 } 1113 1114 template<typename _CharT, typename _InIter> 1115 _InIter 1116 time_get<_CharT, _InIter>:: do_get_time(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1117 do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 1118 ios_base::iostate& __err, tm* __tm) const 1119 { 1120 const locale& __loc = __io._M_getloc(); 1121 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1122 const char_type* __times[2]; 1123 __tp._M_time_formats(__times); 1124 __beg = _M_extract_via_format(__beg, __end, __io, __err, 1125 __tm, __times[0]); 1126 if (__beg == __end) 1127 __err |= ios_base::eofbit; 1128 return __beg; 1129 } 1130 1131 template<typename _CharT, typename _InIter> 1132 _InIter 1133 time_get<_CharT, _InIter>:: do_get_date(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1134 do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 1135 ios_base::iostate& __err, tm* __tm) const 1136 { 1137 const locale& __loc = __io._M_getloc(); 1138 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1139 const char_type* __dates[2]; 1140 __tp._M_date_formats(__dates); 1141 __beg = _M_extract_via_format(__beg, __end, __io, __err, 1142 __tm, __dates[0]); 1143 if (__beg == __end) 1144 __err |= ios_base::eofbit; 1145 return __beg; 1146 } 1147 1148 template<typename _CharT, typename _InIter> 1149 _InIter 1150 time_get<_CharT, _InIter>:: do_get_weekday(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1151 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 1152 ios_base::iostate& __err, tm* __tm) const 1153 { 1154 const locale& __loc = __io._M_getloc(); 1155 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1156 const char_type* __days[14]; 1157 __tp._M_days_abbreviated(__days); 1158 __tp._M_days(__days + 7); 1159 int __tmpwday; 1160 ios_base::iostate __tmperr = ios_base::goodbit; 1161 1162 __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7, 1163 __io, __tmperr); 1164 if (!__tmperr) 1165 __tm->tm_wday = __tmpwday; 1166 else 1167 __err |= ios_base::failbit; 1168 1169 if (__beg == __end) 1170 __err |= ios_base::eofbit; 1171 return __beg; 1172 } 1173 1174 template<typename _CharT, typename _InIter> 1175 _InIter 1176 time_get<_CharT, _InIter>:: do_get_monthname(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1177 do_get_monthname(iter_type __beg, iter_type __end, 1178 ios_base& __io, ios_base::iostate& __err, tm* __tm) const 1179 { 1180 const locale& __loc = __io._M_getloc(); 1181 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1182 const char_type* __months[24]; 1183 __tp._M_months_abbreviated(__months); 1184 __tp._M_months(__months + 12); 1185 int __tmpmon; 1186 ios_base::iostate __tmperr = ios_base::goodbit; 1187 1188 __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12, 1189 __io, __tmperr); 1190 if (!__tmperr) 1191 __tm->tm_mon = __tmpmon; 1192 else 1193 __err |= ios_base::failbit; 1194 1195 if (__beg == __end) 1196 __err |= ios_base::eofbit; 1197 return __beg; 1198 } 1199 1200 template<typename _CharT, typename _InIter> 1201 _InIter 1202 time_get<_CharT, _InIter>:: do_get_year(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1203 do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 1204 ios_base::iostate& __err, tm* __tm) const 1205 { 1206 int __tmpyear; 1207 ios_base::iostate __tmperr = ios_base::goodbit; 1208 1209 __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4, 1210 __io, __tmperr); 1211 if (!__tmperr) 1212 __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900; 1213 else 1214 __err |= ios_base::failbit; 1215 1216 if (__beg == __end) 1217 __err |= ios_base::eofbit; 1218 return __beg; 1219 } 1220 1221 #if __cplusplus >= 201103L 1222 template<typename _CharT, typename _InIter> 1223 inline 1224 _InIter 1225 time_get<_CharT, _InIter>:: get(iter_type __s,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm,const char_type * __fmt,const char_type * __fmtend) const1226 get(iter_type __s, iter_type __end, ios_base& __io, 1227 ios_base::iostate& __err, tm* __tm, const char_type* __fmt, 1228 const char_type* __fmtend) const 1229 { 1230 const locale& __loc = __io._M_getloc(); 1231 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1232 __err = ios_base::goodbit; 1233 while (__fmt != __fmtend && 1234 __err == ios_base::goodbit) 1235 { 1236 if (__s == __end) 1237 { 1238 __err = ios_base::eofbit | ios_base::failbit; 1239 break; 1240 } 1241 else if (__ctype.narrow(*__fmt, 0) == '%') 1242 { 1243 char __format; 1244 char __mod = 0; 1245 if (++__fmt == __fmtend) 1246 { 1247 __err = ios_base::failbit; 1248 break; 1249 } 1250 const char __c = __ctype.narrow(*__fmt, 0); 1251 if (__c != 'E' && __c != 'O') 1252 __format = __c; 1253 else if (++__fmt != __fmtend) 1254 { 1255 __mod = __c; 1256 __format = __ctype.narrow(*__fmt, 0); 1257 } 1258 else 1259 { 1260 __err = ios_base::failbit; 1261 break; 1262 } 1263 __s = this->do_get(__s, __end, __io, __err, __tm, __format, 1264 __mod); 1265 ++__fmt; 1266 } 1267 else if (__ctype.is(ctype_base::space, *__fmt)) 1268 { 1269 ++__fmt; 1270 while (__fmt != __fmtend && 1271 __ctype.is(ctype_base::space, *__fmt)) 1272 ++__fmt; 1273 1274 while (__s != __end && 1275 __ctype.is(ctype_base::space, *__s)) 1276 ++__s; 1277 } 1278 // TODO real case-insensitive comparison 1279 else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) || 1280 __ctype.toupper(*__s) == __ctype.toupper(*__fmt)) 1281 { 1282 ++__s; 1283 ++__fmt; 1284 } 1285 else 1286 { 1287 __err = ios_base::failbit; 1288 break; 1289 } 1290 } 1291 return __s; 1292 } 1293 1294 template<typename _CharT, typename _InIter> 1295 inline 1296 _InIter 1297 time_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm,char __format,char __mod) const1298 do_get(iter_type __beg, iter_type __end, ios_base& __io, 1299 ios_base::iostate& __err, tm* __tm, 1300 char __format, char __mod) const 1301 { 1302 const locale& __loc = __io._M_getloc(); 1303 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1304 __err = ios_base::goodbit; 1305 1306 char_type __fmt[4]; 1307 __fmt[0] = __ctype.widen('%'); 1308 if (!__mod) 1309 { 1310 __fmt[1] = __format; 1311 __fmt[2] = char_type(); 1312 } 1313 else 1314 { 1315 __fmt[1] = __mod; 1316 __fmt[2] = __format; 1317 __fmt[3] = char_type(); 1318 } 1319 1320 __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt); 1321 if (__beg == __end) 1322 __err |= ios_base::eofbit; 1323 return __beg; 1324 } 1325 1326 #endif // __cplusplus >= 201103L 1327 1328 template<typename _CharT, typename _OutIter> 1329 _OutIter 1330 time_put<_CharT, _OutIter>:: put(iter_type __s,ios_base & __io,char_type __fill,const tm * __tm,const _CharT * __beg,const _CharT * __end) const1331 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, 1332 const _CharT* __beg, const _CharT* __end) const 1333 { 1334 const locale& __loc = __io._M_getloc(); 1335 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1336 for (; __beg != __end; ++__beg) 1337 if (__ctype.narrow(*__beg, 0) != '%') 1338 { 1339 *__s = *__beg; 1340 ++__s; 1341 } 1342 else if (++__beg != __end) 1343 { 1344 char __format; 1345 char __mod = 0; 1346 const char __c = __ctype.narrow(*__beg, 0); 1347 if (__c != 'E' && __c != 'O') 1348 __format = __c; 1349 else if (++__beg != __end) 1350 { 1351 __mod = __c; 1352 __format = __ctype.narrow(*__beg, 0); 1353 } 1354 else 1355 break; 1356 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod); 1357 } 1358 else 1359 break; 1360 return __s; 1361 } 1362 1363 template<typename _CharT, typename _OutIter> 1364 _OutIter 1365 time_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __io,char_type,const tm * __tm,char __format,char __mod) const1366 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 1367 char __format, char __mod) const 1368 { 1369 const locale& __loc = __io._M_getloc(); 1370 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1371 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1372 1373 // NB: This size is arbitrary. Should this be a data member, 1374 // initialized at construction? 1375 const size_t __maxlen = 128; 1376 char_type __res[__maxlen]; 1377 1378 // NB: In IEE 1003.1-200x, and perhaps other locale models, it 1379 // is possible that the format character will be longer than one 1380 // character. Possibilities include 'E' or 'O' followed by a 1381 // format character: if __mod is not the default argument, assume 1382 // it's a valid modifier. 1383 char_type __fmt[4]; 1384 __fmt[0] = __ctype.widen('%'); 1385 if (!__mod) 1386 { 1387 __fmt[1] = __format; 1388 __fmt[2] = char_type(); 1389 } 1390 else 1391 { 1392 __fmt[1] = __mod; 1393 __fmt[2] = __format; 1394 __fmt[3] = char_type(); 1395 } 1396 1397 __tp._M_put(__res, __maxlen, __fmt, __tm); 1398 1399 // Write resulting, fully-formatted string to output iterator. 1400 return std::__write(__s, __res, char_traits<char_type>::length(__res)); 1401 } 1402 1403 1404 // Inhibit implicit instantiations for required instantiations, 1405 // which are defined via explicit instantiations elsewhere. 1406 #if _GLIBCXX_EXTERN_TEMPLATE 1407 extern template class moneypunct<char, false>; 1408 extern template class moneypunct<char, true>; 1409 extern template class moneypunct_byname<char, false>; 1410 extern template class moneypunct_byname<char, true>; 1411 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>; 1412 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>; 1413 extern template class __timepunct<char>; 1414 extern template class time_put<char>; 1415 extern template class time_put_byname<char>; 1416 extern template class time_get<char>; 1417 extern template class time_get_byname<char>; 1418 extern template class messages<char>; 1419 extern template class messages_byname<char>; 1420 1421 extern template 1422 const moneypunct<char, true>& 1423 use_facet<moneypunct<char, true> >(const locale&); 1424 1425 extern template 1426 const moneypunct<char, false>& 1427 use_facet<moneypunct<char, false> >(const locale&); 1428 1429 extern template 1430 const money_put<char>& 1431 use_facet<money_put<char> >(const locale&); 1432 1433 extern template 1434 const money_get<char>& 1435 use_facet<money_get<char> >(const locale&); 1436 1437 extern template 1438 const __timepunct<char>& 1439 use_facet<__timepunct<char> >(const locale&); 1440 1441 extern template 1442 const time_put<char>& 1443 use_facet<time_put<char> >(const locale&); 1444 1445 extern template 1446 const time_get<char>& 1447 use_facet<time_get<char> >(const locale&); 1448 1449 extern template 1450 const messages<char>& 1451 use_facet<messages<char> >(const locale&); 1452 1453 extern template 1454 bool 1455 has_facet<moneypunct<char> >(const locale&); 1456 1457 extern template 1458 bool 1459 has_facet<money_put<char> >(const locale&); 1460 1461 extern template 1462 bool 1463 has_facet<money_get<char> >(const locale&); 1464 1465 extern template 1466 bool 1467 has_facet<__timepunct<char> >(const locale&); 1468 1469 extern template 1470 bool 1471 has_facet<time_put<char> >(const locale&); 1472 1473 extern template 1474 bool 1475 has_facet<time_get<char> >(const locale&); 1476 1477 extern template 1478 bool 1479 has_facet<messages<char> >(const locale&); 1480 1481 #ifdef _GLIBCXX_USE_WCHAR_T 1482 extern template class moneypunct<wchar_t, false>; 1483 extern template class moneypunct<wchar_t, true>; 1484 extern template class moneypunct_byname<wchar_t, false>; 1485 extern template class moneypunct_byname<wchar_t, true>; 1486 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>; 1487 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>; 1488 extern template class __timepunct<wchar_t>; 1489 extern template class time_put<wchar_t>; 1490 extern template class time_put_byname<wchar_t>; 1491 extern template class time_get<wchar_t>; 1492 extern template class time_get_byname<wchar_t>; 1493 extern template class messages<wchar_t>; 1494 extern template class messages_byname<wchar_t>; 1495 1496 extern template 1497 const moneypunct<wchar_t, true>& 1498 use_facet<moneypunct<wchar_t, true> >(const locale&); 1499 1500 extern template 1501 const moneypunct<wchar_t, false>& 1502 use_facet<moneypunct<wchar_t, false> >(const locale&); 1503 1504 extern template 1505 const money_put<wchar_t>& 1506 use_facet<money_put<wchar_t> >(const locale&); 1507 1508 extern template 1509 const money_get<wchar_t>& 1510 use_facet<money_get<wchar_t> >(const locale&); 1511 1512 extern template 1513 const __timepunct<wchar_t>& 1514 use_facet<__timepunct<wchar_t> >(const locale&); 1515 1516 extern template 1517 const time_put<wchar_t>& 1518 use_facet<time_put<wchar_t> >(const locale&); 1519 1520 extern template 1521 const time_get<wchar_t>& 1522 use_facet<time_get<wchar_t> >(const locale&); 1523 1524 extern template 1525 const messages<wchar_t>& 1526 use_facet<messages<wchar_t> >(const locale&); 1527 1528 extern template 1529 bool 1530 has_facet<moneypunct<wchar_t> >(const locale&); 1531 1532 extern template 1533 bool 1534 has_facet<money_put<wchar_t> >(const locale&); 1535 1536 extern template 1537 bool 1538 has_facet<money_get<wchar_t> >(const locale&); 1539 1540 extern template 1541 bool 1542 has_facet<__timepunct<wchar_t> >(const locale&); 1543 1544 extern template 1545 bool 1546 has_facet<time_put<wchar_t> >(const locale&); 1547 1548 extern template 1549 bool 1550 has_facet<time_get<wchar_t> >(const locale&); 1551 1552 extern template 1553 bool 1554 has_facet<messages<wchar_t> >(const locale&); 1555 #endif 1556 #endif 1557 1558 _GLIBCXX_END_NAMESPACE_VERSION 1559 } // namespace std 1560 1561 #endif 1562