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