1 // Locale support -*- C++ -*- 2 3 // Copyright (C) 2007-2017 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 case money_base::none: 286 // Only if not at the end of the pattern. 287 if (__i != 3) 288 for (; __beg != __end 289 && __ctype.is(ctype_base::space, *__beg); ++__beg); 290 break; 291 } 292 } 293 294 // Need to get the rest of the sign characters, if they exist. 295 if (__sign_size > 1 && __testvalid) 296 { 297 const char_type* __sign = __negative ? __lc->_M_negative_sign 298 : __lc->_M_positive_sign; 299 size_type __i = 1; 300 for (; __beg != __end && __i < __sign_size 301 && *__beg == __sign[__i]; ++__beg, (void)++__i); 302 303 if (__i != __sign_size) 304 __testvalid = false; 305 } 306 307 if (__testvalid) 308 { 309 // Strip leading zeros. 310 if (__res.size() > 1) 311 { 312 const size_type __first = __res.find_first_not_of('0'); 313 const bool __only_zeros = __first == string::npos; 314 if (__first) 315 __res.erase(0, __only_zeros ? __res.size() - 1 : __first); 316 } 317 318 // 22.2.6.1.2, p4 319 if (__negative && __res[0] != '0') 320 __res.insert(__res.begin(), '-'); 321 322 // Test for grouping fidelity. 323 if (__grouping_tmp.size()) 324 { 325 // Add the ending grouping. 326 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos 327 : __n); 328 if (!std::__verify_grouping(__lc->_M_grouping, 329 __lc->_M_grouping_size, 330 __grouping_tmp)) 331 __err |= ios_base::failbit; 332 } 333 334 // Iff not enough digits were supplied after the decimal-point. 335 if (__testdecfound && __n != __lc->_M_frac_digits) 336 __testvalid = false; 337 } 338 339 // Iff valid sequence is not recognized. 340 if (!__testvalid) 341 __err |= ios_base::failbit; 342 else 343 __units.swap(__res); 344 345 // Iff no more characters are available. 346 if (__beg == __end) 347 __err |= ios_base::eofbit; 348 return __beg; 349 } 350 351 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \ 352 && _GLIBCXX_USE_CXX11_ABI == 0 353 template<typename _CharT, typename _InIter> 354 _InIter 355 money_get<_CharT, _InIter>:: __do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,double & __units) const356 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 357 ios_base::iostate& __err, double& __units) const 358 { 359 string __str; 360 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 361 : _M_extract<false>(__beg, __end, __io, __err, __str); 362 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 363 return __beg; 364 } 365 #endif 366 367 template<typename _CharT, typename _InIter> 368 _InIter 369 money_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,long double & __units) const370 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 371 ios_base::iostate& __err, long double& __units) const 372 { 373 string __str; 374 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 375 : _M_extract<false>(__beg, __end, __io, __err, __str); 376 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 377 return __beg; 378 } 379 380 template<typename _CharT, typename _InIter> 381 _InIter 382 money_get<_CharT, _InIter>:: do_get(iter_type __beg,iter_type __end,bool __intl,ios_base & __io,ios_base::iostate & __err,string_type & __digits) const383 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 384 ios_base::iostate& __err, string_type& __digits) const 385 { 386 typedef typename string::size_type size_type; 387 388 const locale& __loc = __io._M_getloc(); 389 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 390 391 string __str; 392 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 393 : _M_extract<false>(__beg, __end, __io, __err, __str); 394 const size_type __len = __str.size(); 395 if (__len) 396 { 397 __digits.resize(__len); 398 __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]); 399 } 400 return __beg; 401 } 402 403 template<typename _CharT, typename _OutIter> 404 template<bool _Intl> 405 _OutIter 406 money_put<_CharT, _OutIter>:: _M_insert(iter_type __s,ios_base & __io,char_type __fill,const string_type & __digits) const407 _M_insert(iter_type __s, ios_base& __io, char_type __fill, 408 const string_type& __digits) const 409 { 410 typedef typename string_type::size_type size_type; 411 typedef money_base::part part; 412 typedef __moneypunct_cache<_CharT, _Intl> __cache_type; 413 414 const locale& __loc = __io._M_getloc(); 415 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 416 417 __use_cache<__cache_type> __uc; 418 const __cache_type* __lc = __uc(__loc); 419 const char_type* __lit = __lc->_M_atoms; 420 421 // Determine if negative or positive formats are to be used, and 422 // discard leading negative_sign if it is present. 423 const char_type* __beg = __digits.data(); 424 425 money_base::pattern __p; 426 const char_type* __sign; 427 size_type __sign_size; 428 if (!(*__beg == __lit[money_base::_S_minus])) 429 { 430 __p = __lc->_M_pos_format; 431 __sign = __lc->_M_positive_sign; 432 __sign_size = __lc->_M_positive_sign_size; 433 } 434 else 435 { 436 __p = __lc->_M_neg_format; 437 __sign = __lc->_M_negative_sign; 438 __sign_size = __lc->_M_negative_sign_size; 439 if (__digits.size()) 440 ++__beg; 441 } 442 443 // Look for valid numbers in the ctype facet within input digits. 444 size_type __len = __ctype.scan_not(ctype_base::digit, __beg, 445 __beg + __digits.size()) - __beg; 446 if (__len) 447 { 448 // Assume valid input, and attempt to format. 449 // Break down input numbers into base components, as follows: 450 // final_value = grouped units + (decimal point) + (digits) 451 string_type __value; 452 __value.reserve(2 * __len); 453 454 // Add thousands separators to non-decimal digits, per 455 // grouping rules. 456 long __paddec = __len - __lc->_M_frac_digits; 457 if (__paddec > 0) 458 { 459 if (__lc->_M_frac_digits < 0) 460 __paddec = __len; 461 if (__lc->_M_grouping_size) 462 { 463 __value.assign(2 * __paddec, char_type()); 464 _CharT* __vend = 465 std::__add_grouping(&__value[0], __lc->_M_thousands_sep, 466 __lc->_M_grouping, 467 __lc->_M_grouping_size, 468 __beg, __beg + __paddec); 469 __value.erase(__vend - &__value[0]); 470 } 471 else 472 __value.assign(__beg, __paddec); 473 } 474 475 // Deal with decimal point, decimal digits. 476 if (__lc->_M_frac_digits > 0) 477 { 478 __value += __lc->_M_decimal_point; 479 if (__paddec >= 0) 480 __value.append(__beg + __paddec, __lc->_M_frac_digits); 481 else 482 { 483 // Have to pad zeros in the decimal position. 484 __value.append(-__paddec, __lit[money_base::_S_zero]); 485 __value.append(__beg, __len); 486 } 487 } 488 489 // Calculate length of resulting string. 490 const ios_base::fmtflags __f = __io.flags() 491 & ios_base::adjustfield; 492 __len = __value.size() + __sign_size; 493 __len += ((__io.flags() & ios_base::showbase) 494 ? __lc->_M_curr_symbol_size : 0); 495 496 string_type __res; 497 __res.reserve(2 * __len); 498 499 const size_type __width = static_cast<size_type>(__io.width()); 500 const bool __testipad = (__f == ios_base::internal 501 && __len < __width); 502 // Fit formatted digits into the required pattern. 503 for (int __i = 0; __i < 4; ++__i) 504 { 505 const part __which = static_cast<part>(__p.field[__i]); 506 switch (__which) 507 { 508 case money_base::symbol: 509 if (__io.flags() & ios_base::showbase) 510 __res.append(__lc->_M_curr_symbol, 511 __lc->_M_curr_symbol_size); 512 break; 513 case money_base::sign: 514 // Sign might not exist, or be more than one 515 // character long. In that case, add in the rest 516 // below. 517 if (__sign_size) 518 __res += __sign[0]; 519 break; 520 case money_base::value: 521 __res += __value; 522 break; 523 case money_base::space: 524 // At least one space is required, but if internal 525 // formatting is required, an arbitrary number of 526 // fill spaces will be necessary. 527 if (__testipad) 528 __res.append(__width - __len, __fill); 529 else 530 __res += __fill; 531 break; 532 case money_base::none: 533 if (__testipad) 534 __res.append(__width - __len, __fill); 535 break; 536 } 537 } 538 539 // Special case of multi-part sign parts. 540 if (__sign_size > 1) 541 __res.append(__sign + 1, __sign_size - 1); 542 543 // Pad, if still necessary. 544 __len = __res.size(); 545 if (__width > __len) 546 { 547 if (__f == ios_base::left) 548 // After. 549 __res.append(__width - __len, __fill); 550 else 551 // Before. 552 __res.insert(0, __width - __len, __fill); 553 __len = __width; 554 } 555 556 // Write resulting, fully-formatted string to output iterator. 557 __s = std::__write(__s, __res.data(), __len); 558 } 559 __io.width(0); 560 return __s; 561 } 562 563 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \ 564 && _GLIBCXX_USE_CXX11_ABI == 0 565 template<typename _CharT, typename _OutIter> 566 _OutIter 567 money_put<_CharT, _OutIter>:: __do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,double __units) const568 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 569 double __units) const 570 { return this->do_put(__s, __intl, __io, __fill, (long double) __units); } 571 #endif 572 573 template<typename _CharT, typename _OutIter> 574 _OutIter 575 money_put<_CharT, _OutIter>:: do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,long double __units) const576 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 577 long double __units) const 578 { 579 const locale __loc = __io.getloc(); 580 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 581 #if _GLIBCXX_USE_C99_STDIO 582 // First try a buffer perhaps big enough. 583 int __cs_size = 64; 584 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 585 // _GLIBCXX_RESOLVE_LIB_DEFECTS 586 // 328. Bad sprintf format modifier in money_put<>::do_put() 587 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 588 "%.*Lf", 0, __units); 589 // If the buffer was not large enough, try again with the correct size. 590 if (__len >= __cs_size) 591 { 592 __cs_size = __len + 1; 593 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 594 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 595 "%.*Lf", 0, __units); 596 } 597 #else 598 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'. 599 const int __cs_size = 600 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3; 601 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 602 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 603 0, __units); 604 #endif 605 string_type __digits(__len, char_type()); 606 __ctype.widen(__cs, __cs + __len, &__digits[0]); 607 return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 608 : _M_insert<false>(__s, __io, __fill, __digits); 609 } 610 611 template<typename _CharT, typename _OutIter> 612 _OutIter 613 money_put<_CharT, _OutIter>:: do_put(iter_type __s,bool __intl,ios_base & __io,char_type __fill,const string_type & __digits) const614 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 615 const string_type& __digits) const 616 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 617 : _M_insert<false>(__s, __io, __fill, __digits); } 618 619 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 620 621 // NB: Not especially useful. Without an ios_base object or some 622 // kind of locale reference, we are left clawing at the air where 623 // the side of the mountain used to be... 624 template<typename _CharT, typename _InIter> 625 time_base::dateorder do_date_order() const626 time_get<_CharT, _InIter>::do_date_order() const 627 { return time_base::no_order; } 628 629 // Expand a strftime format string and parse it. E.g., do_get_date() may 630 // pass %m/%d/%Y => extracted characters. 631 template<typename _CharT, typename _InIter> 632 _InIter 633 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) const634 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io, 635 ios_base::iostate& __err, tm* __tm, 636 const _CharT* __format) const 637 { 638 const locale& __loc = __io._M_getloc(); 639 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 640 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 641 const size_t __len = char_traits<_CharT>::length(__format); 642 643 ios_base::iostate __tmperr = ios_base::goodbit; 644 size_t __i = 0; 645 for (; __beg != __end && __i < __len && !__tmperr; ++__i) 646 { 647 if (__ctype.narrow(__format[__i], 0) == '%') 648 { 649 // Verify valid formatting code, attempt to extract. 650 char __c = __ctype.narrow(__format[++__i], 0); 651 int __mem = 0; 652 if (__c == 'E' || __c == 'O') 653 __c = __ctype.narrow(__format[++__i], 0); 654 switch (__c) 655 { 656 const char* __cs; 657 _CharT __wcs[10]; 658 case 'a': 659 // Abbreviated weekday name [tm_wday] 660 const char_type* __days1[7]; 661 __tp._M_days_abbreviated(__days1); 662 __beg = _M_extract_name(__beg, __end, __mem, __days1, 663 7, __io, __tmperr); 664 if (!__tmperr) 665 __tm->tm_wday = __mem; 666 break; 667 case 'A': 668 // Weekday name [tm_wday]. 669 const char_type* __days2[7]; 670 __tp._M_days(__days2); 671 __beg = _M_extract_name(__beg, __end, __mem, __days2, 672 7, __io, __tmperr); 673 if (!__tmperr) 674 __tm->tm_wday = __mem; 675 break; 676 case 'h': 677 case 'b': 678 // Abbreviated month name [tm_mon] 679 const char_type* __months1[12]; 680 __tp._M_months_abbreviated(__months1); 681 __beg = _M_extract_name(__beg, __end, __mem, 682 __months1, 12, __io, __tmperr); 683 if (!__tmperr) 684 __tm->tm_mon = __mem; 685 break; 686 case 'B': 687 // Month name [tm_mon]. 688 const char_type* __months2[12]; 689 __tp._M_months(__months2); 690 __beg = _M_extract_name(__beg, __end, __mem, 691 __months2, 12, __io, __tmperr); 692 if (!__tmperr) 693 __tm->tm_mon = __mem; 694 break; 695 case 'c': 696 // Default time and date representation. 697 const char_type* __dt[2]; 698 __tp._M_date_time_formats(__dt); 699 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 700 __tm, __dt[0]); 701 break; 702 case 'd': 703 // Day [01, 31]. [tm_mday] 704 __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2, 705 __io, __tmperr); 706 if (!__tmperr) 707 __tm->tm_mday = __mem; 708 break; 709 case 'e': 710 // Day [1, 31], with single digits preceded by 711 // space. [tm_mday] 712 if (__ctype.is(ctype_base::space, *__beg)) 713 __beg = _M_extract_num(++__beg, __end, __mem, 1, 9, 714 1, __io, __tmperr); 715 else 716 __beg = _M_extract_num(__beg, __end, __mem, 10, 31, 717 2, __io, __tmperr); 718 if (!__tmperr) 719 __tm->tm_mday = __mem; 720 break; 721 case 'D': 722 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 723 __cs = "%m/%d/%y"; 724 __ctype.widen(__cs, __cs + 9, __wcs); 725 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 726 __tm, __wcs); 727 break; 728 case 'H': 729 // Hour [00, 23]. [tm_hour] 730 __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2, 731 __io, __tmperr); 732 if (!__tmperr) 733 __tm->tm_hour = __mem; 734 break; 735 case 'I': 736 // Hour [01, 12]. [tm_hour] 737 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 738 __io, __tmperr); 739 if (!__tmperr) 740 __tm->tm_hour = __mem; 741 break; 742 case 'm': 743 // Month [01, 12]. [tm_mon] 744 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 745 __io, __tmperr); 746 if (!__tmperr) 747 __tm->tm_mon = __mem - 1; 748 break; 749 case 'M': 750 // Minute [00, 59]. [tm_min] 751 __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2, 752 __io, __tmperr); 753 if (!__tmperr) 754 __tm->tm_min = __mem; 755 break; 756 case 'n': 757 if (__ctype.narrow(*__beg, 0) == '\n') 758 ++__beg; 759 else 760 __tmperr |= ios_base::failbit; 761 break; 762 case 'R': 763 // Equivalent to (%H:%M). 764 __cs = "%H:%M"; 765 __ctype.widen(__cs, __cs + 6, __wcs); 766 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 767 __tm, __wcs); 768 break; 769 case 'S': 770 // Seconds. [tm_sec] 771 // [00, 60] in C99 (one leap-second), [00, 61] in C89. 772 #if _GLIBCXX_USE_C99 773 __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2, 774 #else 775 __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2, 776 #endif 777 __io, __tmperr); 778 if (!__tmperr) 779 __tm->tm_sec = __mem; 780 break; 781 case 't': 782 if (__ctype.narrow(*__beg, 0) == '\t') 783 ++__beg; 784 else 785 __tmperr |= ios_base::failbit; 786 break; 787 case 'T': 788 // Equivalent to (%H:%M:%S). 789 __cs = "%H:%M:%S"; 790 __ctype.widen(__cs, __cs + 9, __wcs); 791 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 792 __tm, __wcs); 793 break; 794 case 'x': 795 // Locale's date. 796 const char_type* __dates[2]; 797 __tp._M_date_formats(__dates); 798 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 799 __tm, __dates[0]); 800 break; 801 case 'X': 802 // Locale's time. 803 const char_type* __times[2]; 804 __tp._M_time_formats(__times); 805 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 806 __tm, __times[0]); 807 break; 808 case 'y': 809 case 'C': // C99 810 // Two digit year. 811 case 'Y': 812 // Year [1900). 813 // NB: We parse either two digits, implicitly years since 814 // 1900, or 4 digits, full year. In both cases we can 815 // reconstruct [tm_year]. See also libstdc++/26701. 816 __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4, 817 __io, __tmperr); 818 if (!__tmperr) 819 __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900; 820 break; 821 case 'Z': 822 // Timezone info. 823 if (__ctype.is(ctype_base::upper, *__beg)) 824 { 825 int __tmp; 826 __beg = _M_extract_name(__beg, __end, __tmp, 827 __timepunct_cache<_CharT>::_S_timezones, 828 14, __io, __tmperr); 829 830 // GMT requires special effort. 831 if (__beg != __end && !__tmperr && __tmp == 0 832 && (*__beg == __ctype.widen('-') 833 || *__beg == __ctype.widen('+'))) 834 { 835 __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 836 __io, __tmperr); 837 __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 838 __io, __tmperr); 839 } 840 } 841 else 842 __tmperr |= ios_base::failbit; 843 break; 844 default: 845 // Not recognized. 846 __tmperr |= ios_base::failbit; 847 } 848 } 849 else 850 { 851 // Verify format and input match, extract and discard. 852 if (__format[__i] == *__beg) 853 ++__beg; 854 else 855 __tmperr |= ios_base::failbit; 856 } 857 } 858 859 if (__tmperr || __i != __len) 860 __err |= ios_base::failbit; 861 862 return __beg; 863 } 864 865 template<typename _CharT, typename _InIter> 866 _InIter 867 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) const868 _M_extract_num(iter_type __beg, iter_type __end, int& __member, 869 int __min, int __max, size_t __len, 870 ios_base& __io, ios_base::iostate& __err) const 871 { 872 const locale& __loc = __io._M_getloc(); 873 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 874 875 // As-is works for __len = 1, 2, 4, the values actually used. 876 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1); 877 878 ++__min; 879 size_t __i = 0; 880 int __value = 0; 881 for (; __beg != __end && __i < __len; ++__beg, (void)++__i) 882 { 883 const char __c = __ctype.narrow(*__beg, '*'); 884 if (__c >= '0' && __c <= '9') 885 { 886 __value = __value * 10 + (__c - '0'); 887 const int __valuec = __value * __mult; 888 if (__valuec > __max || __valuec + __mult < __min) 889 break; 890 __mult /= 10; 891 } 892 else 893 break; 894 } 895 if (__i == __len) 896 __member = __value; 897 // Special encoding for do_get_year, 'y', and 'Y' above. 898 else if (__len == 4 && __i == 2) 899 __member = __value - 100; 900 else 901 __err |= ios_base::failbit; 902 903 return __beg; 904 } 905 906 // Assumptions: 907 // All elements in __names are unique. 908 template<typename _CharT, typename _InIter> 909 _InIter 910 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) const911 _M_extract_name(iter_type __beg, iter_type __end, int& __member, 912 const _CharT** __names, size_t __indexlen, 913 ios_base& __io, ios_base::iostate& __err) const 914 { 915 typedef char_traits<_CharT> __traits_type; 916 const locale& __loc = __io._M_getloc(); 917 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 918 919 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 920 * __indexlen)); 921 size_t __nmatches = 0; 922 size_t __pos = 0; 923 bool __testvalid = true; 924 const char_type* __name; 925 926 // Look for initial matches. 927 // NB: Some of the locale data is in the form of all lowercase 928 // names, and some is in the form of initially-capitalized 929 // names. Look for both. 930 if (__beg != __end) 931 { 932 const char_type __c = *__beg; 933 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 934 if (__c == __names[__i1][0] 935 || __c == __ctype.toupper(__names[__i1][0])) 936 __matches[__nmatches++] = __i1; 937 } 938 939 while (__nmatches > 1) 940 { 941 // Find smallest matching string. 942 size_t __minlen = __traits_type::length(__names[__matches[0]]); 943 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2) 944 __minlen = std::min(__minlen, 945 __traits_type::length(__names[__matches[__i2]])); 946 ++__beg; 947 ++__pos; 948 if (__pos < __minlen && __beg != __end) 949 for (size_t __i3 = 0; __i3 < __nmatches;) 950 { 951 __name = __names[__matches[__i3]]; 952 if (!(__name[__pos] == *__beg)) 953 __matches[__i3] = __matches[--__nmatches]; 954 else 955 ++__i3; 956 } 957 else 958 break; 959 } 960 961 if (__nmatches == 1) 962 { 963 // Make sure found name is completely extracted. 964 ++__beg; 965 ++__pos; 966 __name = __names[__matches[0]]; 967 const size_t __len = __traits_type::length(__name); 968 while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 969 ++__beg, (void)++__pos; 970 971 if (__len == __pos) 972 __member = __matches[0]; 973 else 974 __testvalid = false; 975 } 976 else 977 __testvalid = false; 978 if (!__testvalid) 979 __err |= ios_base::failbit; 980 981 return __beg; 982 } 983 984 template<typename _CharT, typename _InIter> 985 _InIter 986 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) const987 _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member, 988 const _CharT** __names, size_t __indexlen, 989 ios_base& __io, ios_base::iostate& __err) const 990 { 991 typedef char_traits<_CharT> __traits_type; 992 const locale& __loc = __io._M_getloc(); 993 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 994 995 int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int) 996 * __indexlen)); 997 size_t __nmatches = 0; 998 size_t* __matches_lengths = 0; 999 size_t __pos = 0; 1000 1001 if (__beg != __end) 1002 { 1003 const char_type __c = *__beg; 1004 for (size_t __i = 0; __i < 2 * __indexlen; ++__i) 1005 if (__c == __names[__i][0] 1006 || __c == __ctype.toupper(__names[__i][0])) 1007 __matches[__nmatches++] = __i; 1008 } 1009 1010 if (__nmatches) 1011 { 1012 ++__beg; 1013 ++__pos; 1014 1015 __matches_lengths 1016 = static_cast<size_t*>(__builtin_alloca(sizeof(size_t) 1017 * __nmatches)); 1018 for (size_t __i = 0; __i < __nmatches; ++__i) 1019 __matches_lengths[__i] 1020 = __traits_type::length(__names[__matches[__i]]); 1021 } 1022 1023 for (; __beg != __end; ++__beg, (void)++__pos) 1024 { 1025 size_t __nskipped = 0; 1026 const char_type __c = *__beg; 1027 for (size_t __i = 0; __i < __nmatches;) 1028 { 1029 const char_type* __name = __names[__matches[__i]]; 1030 if (__pos >= __matches_lengths[__i]) 1031 ++__nskipped, ++__i; 1032 else if (!(__name[__pos] == __c)) 1033 { 1034 --__nmatches; 1035 __matches[__i] = __matches[__nmatches]; 1036 __matches_lengths[__i] = __matches_lengths[__nmatches]; 1037 } 1038 else 1039 ++__i; 1040 } 1041 if (__nskipped == __nmatches) 1042 break; 1043 } 1044 1045 if ((__nmatches == 1 && __matches_lengths[0] == __pos) 1046 || (__nmatches == 2 && (__matches_lengths[0] == __pos 1047 || __matches_lengths[1] == __pos))) 1048 __member = (__matches[0] >= __indexlen 1049 ? __matches[0] - __indexlen : __matches[0]); 1050 else 1051 __err |= ios_base::failbit; 1052 1053 return __beg; 1054 } 1055 1056 template<typename _CharT, typename _InIter> 1057 _InIter 1058 time_get<_CharT, _InIter>:: do_get_time(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1059 do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 1060 ios_base::iostate& __err, tm* __tm) const 1061 { 1062 const locale& __loc = __io._M_getloc(); 1063 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1064 const char_type* __times[2]; 1065 __tp._M_time_formats(__times); 1066 __beg = _M_extract_via_format(__beg, __end, __io, __err, 1067 __tm, __times[0]); 1068 if (__beg == __end) 1069 __err |= ios_base::eofbit; 1070 return __beg; 1071 } 1072 1073 template<typename _CharT, typename _InIter> 1074 _InIter 1075 time_get<_CharT, _InIter>:: do_get_date(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1076 do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 1077 ios_base::iostate& __err, tm* __tm) const 1078 { 1079 const locale& __loc = __io._M_getloc(); 1080 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1081 const char_type* __dates[2]; 1082 __tp._M_date_formats(__dates); 1083 __beg = _M_extract_via_format(__beg, __end, __io, __err, 1084 __tm, __dates[0]); 1085 if (__beg == __end) 1086 __err |= ios_base::eofbit; 1087 return __beg; 1088 } 1089 1090 template<typename _CharT, typename _InIter> 1091 _InIter 1092 time_get<_CharT, _InIter>:: do_get_weekday(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1093 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 1094 ios_base::iostate& __err, tm* __tm) const 1095 { 1096 const locale& __loc = __io._M_getloc(); 1097 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1098 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1099 const char_type* __days[14]; 1100 __tp._M_days_abbreviated(__days); 1101 __tp._M_days(__days + 7); 1102 int __tmpwday; 1103 ios_base::iostate __tmperr = ios_base::goodbit; 1104 1105 __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7, 1106 __io, __tmperr); 1107 if (!__tmperr) 1108 __tm->tm_wday = __tmpwday; 1109 else 1110 __err |= ios_base::failbit; 1111 1112 if (__beg == __end) 1113 __err |= ios_base::eofbit; 1114 return __beg; 1115 } 1116 1117 template<typename _CharT, typename _InIter> 1118 _InIter 1119 time_get<_CharT, _InIter>:: do_get_monthname(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1120 do_get_monthname(iter_type __beg, iter_type __end, 1121 ios_base& __io, ios_base::iostate& __err, tm* __tm) const 1122 { 1123 const locale& __loc = __io._M_getloc(); 1124 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 1125 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1126 const char_type* __months[24]; 1127 __tp._M_months_abbreviated(__months); 1128 __tp._M_months(__months + 12); 1129 int __tmpmon; 1130 ios_base::iostate __tmperr = ios_base::goodbit; 1131 1132 __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12, 1133 __io, __tmperr); 1134 if (!__tmperr) 1135 __tm->tm_mon = __tmpmon; 1136 else 1137 __err |= ios_base::failbit; 1138 1139 if (__beg == __end) 1140 __err |= ios_base::eofbit; 1141 return __beg; 1142 } 1143 1144 template<typename _CharT, typename _InIter> 1145 _InIter 1146 time_get<_CharT, _InIter>:: do_get_year(iter_type __beg,iter_type __end,ios_base & __io,ios_base::iostate & __err,tm * __tm) const1147 do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 1148 ios_base::iostate& __err, tm* __tm) const 1149 { 1150 const locale& __loc = __io._M_getloc(); 1151 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 1152 int __tmpyear; 1153 ios_base::iostate __tmperr = ios_base::goodbit; 1154 1155 __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4, 1156 __io, __tmperr); 1157 if (!__tmperr) 1158 __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900; 1159 else 1160 __err |= ios_base::failbit; 1161 1162 if (__beg == __end) 1163 __err |= ios_base::eofbit; 1164 return __beg; 1165 } 1166 1167 #if __cplusplus >= 201103L 1168 template<typename _CharT, typename _InIter> 1169 inline 1170 _InIter 1171 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) const1172 get(iter_type __s, iter_type __end, ios_base& __io, 1173 ios_base::iostate& __err, tm* __tm, const char_type* __fmt, 1174 const char_type* __fmtend) const 1175 { 1176 const locale& __loc = __io._M_getloc(); 1177 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1178 __err = ios_base::goodbit; 1179 while (__fmt != __fmtend && 1180 __err == ios_base::goodbit) 1181 { 1182 if (__s == __end) 1183 { 1184 __err = ios_base::eofbit | ios_base::failbit; 1185 break; 1186 } 1187 else if (__ctype.narrow(*__fmt, 0) == '%') 1188 { 1189 char __format; 1190 char __mod = 0; 1191 if (++__fmt == __fmtend) 1192 { 1193 __err = ios_base::failbit; 1194 break; 1195 } 1196 const char __c = __ctype.narrow(*__fmt, 0); 1197 if (__c != 'E' && __c != 'O') 1198 __format = __c; 1199 else if (++__fmt != __fmtend) 1200 { 1201 __mod = __c; 1202 __format = __ctype.narrow(*__fmt, 0); 1203 } 1204 else 1205 { 1206 __err = ios_base::failbit; 1207 break; 1208 } 1209 __s = this->do_get(__s, __end, __io, __err, __tm, __format, 1210 __mod); 1211 ++__fmt; 1212 } 1213 else if (__ctype.is(ctype_base::space, *__fmt)) 1214 { 1215 ++__fmt; 1216 while (__fmt != __fmtend && 1217 __ctype.is(ctype_base::space, *__fmt)) 1218 ++__fmt; 1219 1220 while (__s != __end && 1221 __ctype.is(ctype_base::space, *__s)) 1222 ++__s; 1223 } 1224 // TODO real case-insensitive comparison 1225 else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) || 1226 __ctype.toupper(*__s) == __ctype.toupper(*__fmt)) 1227 { 1228 ++__s; 1229 ++__fmt; 1230 } 1231 else 1232 { 1233 __err = ios_base::failbit; 1234 break; 1235 } 1236 } 1237 return __s; 1238 } 1239 1240 template<typename _CharT, typename _InIter> 1241 inline 1242 _InIter 1243 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) const1244 do_get(iter_type __beg, iter_type __end, ios_base& __io, 1245 ios_base::iostate& __err, tm* __tm, 1246 char __format, char __mod) const 1247 { 1248 const locale& __loc = __io._M_getloc(); 1249 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1250 __err = ios_base::goodbit; 1251 1252 char_type __fmt[4]; 1253 __fmt[0] = __ctype.widen('%'); 1254 if (!__mod) 1255 { 1256 __fmt[1] = __format; 1257 __fmt[2] = char_type(); 1258 } 1259 else 1260 { 1261 __fmt[1] = __mod; 1262 __fmt[2] = __format; 1263 __fmt[3] = char_type(); 1264 } 1265 1266 __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt); 1267 if (__beg == __end) 1268 __err |= ios_base::eofbit; 1269 return __beg; 1270 } 1271 1272 #endif // __cplusplus >= 201103L 1273 1274 template<typename _CharT, typename _OutIter> 1275 _OutIter 1276 time_put<_CharT, _OutIter>:: put(iter_type __s,ios_base & __io,char_type __fill,const tm * __tm,const _CharT * __beg,const _CharT * __end) const1277 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, 1278 const _CharT* __beg, const _CharT* __end) const 1279 { 1280 const locale& __loc = __io._M_getloc(); 1281 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1282 for (; __beg != __end; ++__beg) 1283 if (__ctype.narrow(*__beg, 0) != '%') 1284 { 1285 *__s = *__beg; 1286 ++__s; 1287 } 1288 else if (++__beg != __end) 1289 { 1290 char __format; 1291 char __mod = 0; 1292 const char __c = __ctype.narrow(*__beg, 0); 1293 if (__c != 'E' && __c != 'O') 1294 __format = __c; 1295 else if (++__beg != __end) 1296 { 1297 __mod = __c; 1298 __format = __ctype.narrow(*__beg, 0); 1299 } 1300 else 1301 break; 1302 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod); 1303 } 1304 else 1305 break; 1306 return __s; 1307 } 1308 1309 template<typename _CharT, typename _OutIter> 1310 _OutIter 1311 time_put<_CharT, _OutIter>:: do_put(iter_type __s,ios_base & __io,char_type,const tm * __tm,char __format,char __mod) const1312 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 1313 char __format, char __mod) const 1314 { 1315 const locale& __loc = __io._M_getloc(); 1316 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 1317 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 1318 1319 // NB: This size is arbitrary. Should this be a data member, 1320 // initialized at construction? 1321 const size_t __maxlen = 128; 1322 char_type __res[__maxlen]; 1323 1324 // NB: In IEE 1003.1-200x, and perhaps other locale models, it 1325 // is possible that the format character will be longer than one 1326 // character. Possibilities include 'E' or 'O' followed by a 1327 // format character: if __mod is not the default argument, assume 1328 // it's a valid modifier. 1329 char_type __fmt[4]; 1330 __fmt[0] = __ctype.widen('%'); 1331 if (!__mod) 1332 { 1333 __fmt[1] = __format; 1334 __fmt[2] = char_type(); 1335 } 1336 else 1337 { 1338 __fmt[1] = __mod; 1339 __fmt[2] = __format; 1340 __fmt[3] = char_type(); 1341 } 1342 1343 __tp._M_put(__res, __maxlen, __fmt, __tm); 1344 1345 // Write resulting, fully-formatted string to output iterator. 1346 return std::__write(__s, __res, char_traits<char_type>::length(__res)); 1347 } 1348 1349 1350 // Inhibit implicit instantiations for required instantiations, 1351 // which are defined via explicit instantiations elsewhere. 1352 #if _GLIBCXX_EXTERN_TEMPLATE 1353 extern template class moneypunct<char, false>; 1354 extern template class moneypunct<char, true>; 1355 extern template class moneypunct_byname<char, false>; 1356 extern template class moneypunct_byname<char, true>; 1357 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>; 1358 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>; 1359 extern template class __timepunct<char>; 1360 extern template class time_put<char>; 1361 extern template class time_put_byname<char>; 1362 extern template class time_get<char>; 1363 extern template class time_get_byname<char>; 1364 extern template class messages<char>; 1365 extern template class messages_byname<char>; 1366 1367 extern template 1368 const moneypunct<char, true>& 1369 use_facet<moneypunct<char, true> >(const locale&); 1370 1371 extern template 1372 const moneypunct<char, false>& 1373 use_facet<moneypunct<char, false> >(const locale&); 1374 1375 extern template 1376 const money_put<char>& 1377 use_facet<money_put<char> >(const locale&); 1378 1379 extern template 1380 const money_get<char>& 1381 use_facet<money_get<char> >(const locale&); 1382 1383 extern template 1384 const __timepunct<char>& 1385 use_facet<__timepunct<char> >(const locale&); 1386 1387 extern template 1388 const time_put<char>& 1389 use_facet<time_put<char> >(const locale&); 1390 1391 extern template 1392 const time_get<char>& 1393 use_facet<time_get<char> >(const locale&); 1394 1395 extern template 1396 const messages<char>& 1397 use_facet<messages<char> >(const locale&); 1398 1399 extern template 1400 bool 1401 has_facet<moneypunct<char> >(const locale&); 1402 1403 extern template 1404 bool 1405 has_facet<money_put<char> >(const locale&); 1406 1407 extern template 1408 bool 1409 has_facet<money_get<char> >(const locale&); 1410 1411 extern template 1412 bool 1413 has_facet<__timepunct<char> >(const locale&); 1414 1415 extern template 1416 bool 1417 has_facet<time_put<char> >(const locale&); 1418 1419 extern template 1420 bool 1421 has_facet<time_get<char> >(const locale&); 1422 1423 extern template 1424 bool 1425 has_facet<messages<char> >(const locale&); 1426 1427 #ifdef _GLIBCXX_USE_WCHAR_T 1428 extern template class moneypunct<wchar_t, false>; 1429 extern template class moneypunct<wchar_t, true>; 1430 extern template class moneypunct_byname<wchar_t, false>; 1431 extern template class moneypunct_byname<wchar_t, true>; 1432 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>; 1433 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>; 1434 extern template class __timepunct<wchar_t>; 1435 extern template class time_put<wchar_t>; 1436 extern template class time_put_byname<wchar_t>; 1437 extern template class time_get<wchar_t>; 1438 extern template class time_get_byname<wchar_t>; 1439 extern template class messages<wchar_t>; 1440 extern template class messages_byname<wchar_t>; 1441 1442 extern template 1443 const moneypunct<wchar_t, true>& 1444 use_facet<moneypunct<wchar_t, true> >(const locale&); 1445 1446 extern template 1447 const moneypunct<wchar_t, false>& 1448 use_facet<moneypunct<wchar_t, false> >(const locale&); 1449 1450 extern template 1451 const money_put<wchar_t>& 1452 use_facet<money_put<wchar_t> >(const locale&); 1453 1454 extern template 1455 const money_get<wchar_t>& 1456 use_facet<money_get<wchar_t> >(const locale&); 1457 1458 extern template 1459 const __timepunct<wchar_t>& 1460 use_facet<__timepunct<wchar_t> >(const locale&); 1461 1462 extern template 1463 const time_put<wchar_t>& 1464 use_facet<time_put<wchar_t> >(const locale&); 1465 1466 extern template 1467 const time_get<wchar_t>& 1468 use_facet<time_get<wchar_t> >(const locale&); 1469 1470 extern template 1471 const messages<wchar_t>& 1472 use_facet<messages<wchar_t> >(const locale&); 1473 1474 extern template 1475 bool 1476 has_facet<moneypunct<wchar_t> >(const locale&); 1477 1478 extern template 1479 bool 1480 has_facet<money_put<wchar_t> >(const locale&); 1481 1482 extern template 1483 bool 1484 has_facet<money_get<wchar_t> >(const locale&); 1485 1486 extern template 1487 bool 1488 has_facet<__timepunct<wchar_t> >(const locale&); 1489 1490 extern template 1491 bool 1492 has_facet<time_put<wchar_t> >(const locale&); 1493 1494 extern template 1495 bool 1496 has_facet<time_get<wchar_t> >(const locale&); 1497 1498 extern template 1499 bool 1500 has_facet<messages<wchar_t> >(const locale&); 1501 #endif 1502 #endif 1503 1504 _GLIBCXX_END_NAMESPACE_VERSION 1505 } // namespace std 1506 1507 #endif 1508