libstdc++
|
00001 // Locale support -*- C++ -*- 00002 00003 // Copyright (C) 2007-2017 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the 00007 // terms of the GNU General Public License as published by the 00008 // Free Software Foundation; either version 3, or (at your option) 00009 // any later version. 00010 00011 // This library is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file bits/locale_facets_nonio.tcc 00026 * This is an internal header file, included by other library headers. 00027 * Do not attempt to use it directly. @headername{locale} 00028 */ 00029 00030 #ifndef _LOCALE_FACETS_NONIO_TCC 00031 #define _LOCALE_FACETS_NONIO_TCC 1 00032 00033 #pragma GCC system_header 00034 00035 namespace std _GLIBCXX_VISIBILITY(default) 00036 { 00037 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00038 00039 template<typename _CharT, bool _Intl> 00040 struct __use_cache<__moneypunct_cache<_CharT, _Intl> > 00041 { 00042 const __moneypunct_cache<_CharT, _Intl>* 00043 operator() (const locale& __loc) const 00044 { 00045 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id(); 00046 const locale::facet** __caches = __loc._M_impl->_M_caches; 00047 if (!__caches[__i]) 00048 { 00049 __moneypunct_cache<_CharT, _Intl>* __tmp = 0; 00050 __try 00051 { 00052 __tmp = new __moneypunct_cache<_CharT, _Intl>; 00053 __tmp->_M_cache(__loc); 00054 } 00055 __catch(...) 00056 { 00057 delete __tmp; 00058 __throw_exception_again; 00059 } 00060 __loc._M_impl->_M_install_cache(__tmp, __i); 00061 } 00062 return static_cast< 00063 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]); 00064 } 00065 }; 00066 00067 template<typename _CharT, bool _Intl> 00068 void 00069 __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc) 00070 { 00071 const moneypunct<_CharT, _Intl>& __mp = 00072 use_facet<moneypunct<_CharT, _Intl> >(__loc); 00073 00074 _M_decimal_point = __mp.decimal_point(); 00075 _M_thousands_sep = __mp.thousands_sep(); 00076 _M_frac_digits = __mp.frac_digits(); 00077 00078 char* __grouping = 0; 00079 _CharT* __curr_symbol = 0; 00080 _CharT* __positive_sign = 0; 00081 _CharT* __negative_sign = 0; 00082 __try 00083 { 00084 const string& __g = __mp.grouping(); 00085 _M_grouping_size = __g.size(); 00086 __grouping = new char[_M_grouping_size]; 00087 __g.copy(__grouping, _M_grouping_size); 00088 _M_use_grouping = (_M_grouping_size 00089 && static_cast<signed char>(__grouping[0]) > 0 00090 && (__grouping[0] 00091 != __gnu_cxx::__numeric_traits<char>::__max)); 00092 00093 const basic_string<_CharT>& __cs = __mp.curr_symbol(); 00094 _M_curr_symbol_size = __cs.size(); 00095 __curr_symbol = new _CharT[_M_curr_symbol_size]; 00096 __cs.copy(__curr_symbol, _M_curr_symbol_size); 00097 00098 const basic_string<_CharT>& __ps = __mp.positive_sign(); 00099 _M_positive_sign_size = __ps.size(); 00100 __positive_sign = new _CharT[_M_positive_sign_size]; 00101 __ps.copy(__positive_sign, _M_positive_sign_size); 00102 00103 const basic_string<_CharT>& __ns = __mp.negative_sign(); 00104 _M_negative_sign_size = __ns.size(); 00105 __negative_sign = new _CharT[_M_negative_sign_size]; 00106 __ns.copy(__negative_sign, _M_negative_sign_size); 00107 00108 _M_pos_format = __mp.pos_format(); 00109 _M_neg_format = __mp.neg_format(); 00110 00111 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 00112 __ct.widen(money_base::_S_atoms, 00113 money_base::_S_atoms + money_base::_S_end, _M_atoms); 00114 00115 _M_grouping = __grouping; 00116 _M_curr_symbol = __curr_symbol; 00117 _M_positive_sign = __positive_sign; 00118 _M_negative_sign = __negative_sign; 00119 _M_allocated = true; 00120 } 00121 __catch(...) 00122 { 00123 delete [] __grouping; 00124 delete [] __curr_symbol; 00125 delete [] __positive_sign; 00126 delete [] __negative_sign; 00127 __throw_exception_again; 00128 } 00129 } 00130 00131 _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 00132 00133 template<typename _CharT, typename _InIter> 00134 template<bool _Intl> 00135 _InIter 00136 money_get<_CharT, _InIter>:: 00137 _M_extract(iter_type __beg, iter_type __end, ios_base& __io, 00138 ios_base::iostate& __err, string& __units) const 00139 { 00140 typedef char_traits<_CharT> __traits_type; 00141 typedef typename string_type::size_type size_type; 00142 typedef money_base::part part; 00143 typedef __moneypunct_cache<_CharT, _Intl> __cache_type; 00144 00145 const locale& __loc = __io._M_getloc(); 00146 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00147 00148 __use_cache<__cache_type> __uc; 00149 const __cache_type* __lc = __uc(__loc); 00150 const char_type* __lit = __lc->_M_atoms; 00151 00152 // Deduced sign. 00153 bool __negative = false; 00154 // Sign size. 00155 size_type __sign_size = 0; 00156 // True if sign is mandatory. 00157 const bool __mandatory_sign = (__lc->_M_positive_sign_size 00158 && __lc->_M_negative_sign_size); 00159 // String of grouping info from thousands_sep plucked from __units. 00160 string __grouping_tmp; 00161 if (__lc->_M_use_grouping) 00162 __grouping_tmp.reserve(32); 00163 // Last position before the decimal point. 00164 int __last_pos = 0; 00165 // Separator positions, then, possibly, fractional digits. 00166 int __n = 0; 00167 // If input iterator is in a valid state. 00168 bool __testvalid = true; 00169 // Flag marking when a decimal point is found. 00170 bool __testdecfound = false; 00171 00172 // The tentative returned string is stored here. 00173 string __res; 00174 __res.reserve(32); 00175 00176 const char_type* __lit_zero = __lit + money_base::_S_zero; 00177 const money_base::pattern __p = __lc->_M_neg_format; 00178 for (int __i = 0; __i < 4 && __testvalid; ++__i) 00179 { 00180 const part __which = static_cast<part>(__p.field[__i]); 00181 switch (__which) 00182 { 00183 case money_base::symbol: 00184 // According to 22.2.6.1.2, p2, symbol is required 00185 // if (__io.flags() & ios_base::showbase), otherwise 00186 // is optional and consumed only if other characters 00187 // are needed to complete the format. 00188 if (__io.flags() & ios_base::showbase || __sign_size > 1 00189 || __i == 0 00190 || (__i == 1 && (__mandatory_sign 00191 || (static_cast<part>(__p.field[0]) 00192 == money_base::sign) 00193 || (static_cast<part>(__p.field[2]) 00194 == money_base::space))) 00195 || (__i == 2 && ((static_cast<part>(__p.field[3]) 00196 == money_base::value) 00197 || (__mandatory_sign 00198 && (static_cast<part>(__p.field[3]) 00199 == money_base::sign))))) 00200 { 00201 const size_type __len = __lc->_M_curr_symbol_size; 00202 size_type __j = 0; 00203 for (; __beg != __end && __j < __len 00204 && *__beg == __lc->_M_curr_symbol[__j]; 00205 ++__beg, (void)++__j); 00206 if (__j != __len 00207 && (__j || __io.flags() & ios_base::showbase)) 00208 __testvalid = false; 00209 } 00210 break; 00211 case money_base::sign: 00212 // Sign might not exist, or be more than one character long. 00213 if (__lc->_M_positive_sign_size && __beg != __end 00214 && *__beg == __lc->_M_positive_sign[0]) 00215 { 00216 __sign_size = __lc->_M_positive_sign_size; 00217 ++__beg; 00218 } 00219 else if (__lc->_M_negative_sign_size && __beg != __end 00220 && *__beg == __lc->_M_negative_sign[0]) 00221 { 00222 __negative = true; 00223 __sign_size = __lc->_M_negative_sign_size; 00224 ++__beg; 00225 } 00226 else if (__lc->_M_positive_sign_size 00227 && !__lc->_M_negative_sign_size) 00228 // "... if no sign is detected, the result is given the sign 00229 // that corresponds to the source of the empty string" 00230 __negative = true; 00231 else if (__mandatory_sign) 00232 __testvalid = false; 00233 break; 00234 case money_base::value: 00235 // Extract digits, remove and stash away the 00236 // grouping of found thousands separators. 00237 for (; __beg != __end; ++__beg) 00238 { 00239 const char_type __c = *__beg; 00240 const char_type* __q = __traits_type::find(__lit_zero, 00241 10, __c); 00242 if (__q != 0) 00243 { 00244 __res += money_base::_S_atoms[__q - __lit]; 00245 ++__n; 00246 } 00247 else if (__c == __lc->_M_decimal_point 00248 && !__testdecfound) 00249 { 00250 if (__lc->_M_frac_digits <= 0) 00251 break; 00252 00253 __last_pos = __n; 00254 __n = 0; 00255 __testdecfound = true; 00256 } 00257 else if (__lc->_M_use_grouping 00258 && __c == __lc->_M_thousands_sep 00259 && !__testdecfound) 00260 { 00261 if (__n) 00262 { 00263 // Mark position for later analysis. 00264 __grouping_tmp += static_cast<char>(__n); 00265 __n = 0; 00266 } 00267 else 00268 { 00269 __testvalid = false; 00270 break; 00271 } 00272 } 00273 else 00274 break; 00275 } 00276 if (__res.empty()) 00277 __testvalid = false; 00278 break; 00279 case money_base::space: 00280 // At least one space is required. 00281 if (__beg != __end && __ctype.is(ctype_base::space, *__beg)) 00282 ++__beg; 00283 else 00284 __testvalid = false; 00285 case money_base::none: 00286 // Only if not at the end of the pattern. 00287 if (__i != 3) 00288 for (; __beg != __end 00289 && __ctype.is(ctype_base::space, *__beg); ++__beg); 00290 break; 00291 } 00292 } 00293 00294 // Need to get the rest of the sign characters, if they exist. 00295 if (__sign_size > 1 && __testvalid) 00296 { 00297 const char_type* __sign = __negative ? __lc->_M_negative_sign 00298 : __lc->_M_positive_sign; 00299 size_type __i = 1; 00300 for (; __beg != __end && __i < __sign_size 00301 && *__beg == __sign[__i]; ++__beg, (void)++__i); 00302 00303 if (__i != __sign_size) 00304 __testvalid = false; 00305 } 00306 00307 if (__testvalid) 00308 { 00309 // Strip leading zeros. 00310 if (__res.size() > 1) 00311 { 00312 const size_type __first = __res.find_first_not_of('0'); 00313 const bool __only_zeros = __first == string::npos; 00314 if (__first) 00315 __res.erase(0, __only_zeros ? __res.size() - 1 : __first); 00316 } 00317 00318 // 22.2.6.1.2, p4 00319 if (__negative && __res[0] != '0') 00320 __res.insert(__res.begin(), '-'); 00321 00322 // Test for grouping fidelity. 00323 if (__grouping_tmp.size()) 00324 { 00325 // Add the ending grouping. 00326 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos 00327 : __n); 00328 if (!std::__verify_grouping(__lc->_M_grouping, 00329 __lc->_M_grouping_size, 00330 __grouping_tmp)) 00331 __err |= ios_base::failbit; 00332 } 00333 00334 // Iff not enough digits were supplied after the decimal-point. 00335 if (__testdecfound && __n != __lc->_M_frac_digits) 00336 __testvalid = false; 00337 } 00338 00339 // Iff valid sequence is not recognized. 00340 if (!__testvalid) 00341 __err |= ios_base::failbit; 00342 else 00343 __units.swap(__res); 00344 00345 // Iff no more characters are available. 00346 if (__beg == __end) 00347 __err |= ios_base::eofbit; 00348 return __beg; 00349 } 00350 00351 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \ 00352 && _GLIBCXX_USE_CXX11_ABI == 0 00353 template<typename _CharT, typename _InIter> 00354 _InIter 00355 money_get<_CharT, _InIter>:: 00356 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 00357 ios_base::iostate& __err, double& __units) const 00358 { 00359 string __str; 00360 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 00361 : _M_extract<false>(__beg, __end, __io, __err, __str); 00362 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 00363 return __beg; 00364 } 00365 #endif 00366 00367 template<typename _CharT, typename _InIter> 00368 _InIter 00369 money_get<_CharT, _InIter>:: 00370 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 00371 ios_base::iostate& __err, long double& __units) const 00372 { 00373 string __str; 00374 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 00375 : _M_extract<false>(__beg, __end, __io, __err, __str); 00376 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 00377 return __beg; 00378 } 00379 00380 template<typename _CharT, typename _InIter> 00381 _InIter 00382 money_get<_CharT, _InIter>:: 00383 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 00384 ios_base::iostate& __err, string_type& __digits) const 00385 { 00386 typedef typename string::size_type size_type; 00387 00388 const locale& __loc = __io._M_getloc(); 00389 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00390 00391 string __str; 00392 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str) 00393 : _M_extract<false>(__beg, __end, __io, __err, __str); 00394 const size_type __len = __str.size(); 00395 if (__len) 00396 { 00397 __digits.resize(__len); 00398 __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]); 00399 } 00400 return __beg; 00401 } 00402 00403 template<typename _CharT, typename _OutIter> 00404 template<bool _Intl> 00405 _OutIter 00406 money_put<_CharT, _OutIter>:: 00407 _M_insert(iter_type __s, ios_base& __io, char_type __fill, 00408 const string_type& __digits) const 00409 { 00410 typedef typename string_type::size_type size_type; 00411 typedef money_base::part part; 00412 typedef __moneypunct_cache<_CharT, _Intl> __cache_type; 00413 00414 const locale& __loc = __io._M_getloc(); 00415 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00416 00417 __use_cache<__cache_type> __uc; 00418 const __cache_type* __lc = __uc(__loc); 00419 const char_type* __lit = __lc->_M_atoms; 00420 00421 // Determine if negative or positive formats are to be used, and 00422 // discard leading negative_sign if it is present. 00423 const char_type* __beg = __digits.data(); 00424 00425 money_base::pattern __p; 00426 const char_type* __sign; 00427 size_type __sign_size; 00428 if (!(*__beg == __lit[money_base::_S_minus])) 00429 { 00430 __p = __lc->_M_pos_format; 00431 __sign = __lc->_M_positive_sign; 00432 __sign_size = __lc->_M_positive_sign_size; 00433 } 00434 else 00435 { 00436 __p = __lc->_M_neg_format; 00437 __sign = __lc->_M_negative_sign; 00438 __sign_size = __lc->_M_negative_sign_size; 00439 if (__digits.size()) 00440 ++__beg; 00441 } 00442 00443 // Look for valid numbers in the ctype facet within input digits. 00444 size_type __len = __ctype.scan_not(ctype_base::digit, __beg, 00445 __beg + __digits.size()) - __beg; 00446 if (__len) 00447 { 00448 // Assume valid input, and attempt to format. 00449 // Break down input numbers into base components, as follows: 00450 // final_value = grouped units + (decimal point) + (digits) 00451 string_type __value; 00452 __value.reserve(2 * __len); 00453 00454 // Add thousands separators to non-decimal digits, per 00455 // grouping rules. 00456 long __paddec = __len - __lc->_M_frac_digits; 00457 if (__paddec > 0) 00458 { 00459 if (__lc->_M_frac_digits < 0) 00460 __paddec = __len; 00461 if (__lc->_M_grouping_size) 00462 { 00463 __value.assign(2 * __paddec, char_type()); 00464 _CharT* __vend = 00465 std::__add_grouping(&__value[0], __lc->_M_thousands_sep, 00466 __lc->_M_grouping, 00467 __lc->_M_grouping_size, 00468 __beg, __beg + __paddec); 00469 __value.erase(__vend - &__value[0]); 00470 } 00471 else 00472 __value.assign(__beg, __paddec); 00473 } 00474 00475 // Deal with decimal point, decimal digits. 00476 if (__lc->_M_frac_digits > 0) 00477 { 00478 __value += __lc->_M_decimal_point; 00479 if (__paddec >= 0) 00480 __value.append(__beg + __paddec, __lc->_M_frac_digits); 00481 else 00482 { 00483 // Have to pad zeros in the decimal position. 00484 __value.append(-__paddec, __lit[money_base::_S_zero]); 00485 __value.append(__beg, __len); 00486 } 00487 } 00488 00489 // Calculate length of resulting string. 00490 const ios_base::fmtflags __f = __io.flags() 00491 & ios_base::adjustfield; 00492 __len = __value.size() + __sign_size; 00493 __len += ((__io.flags() & ios_base::showbase) 00494 ? __lc->_M_curr_symbol_size : 0); 00495 00496 string_type __res; 00497 __res.reserve(2 * __len); 00498 00499 const size_type __width = static_cast<size_type>(__io.width()); 00500 const bool __testipad = (__f == ios_base::internal 00501 && __len < __width); 00502 // Fit formatted digits into the required pattern. 00503 for (int __i = 0; __i < 4; ++__i) 00504 { 00505 const part __which = static_cast<part>(__p.field[__i]); 00506 switch (__which) 00507 { 00508 case money_base::symbol: 00509 if (__io.flags() & ios_base::showbase) 00510 __res.append(__lc->_M_curr_symbol, 00511 __lc->_M_curr_symbol_size); 00512 break; 00513 case money_base::sign: 00514 // Sign might not exist, or be more than one 00515 // character long. In that case, add in the rest 00516 // below. 00517 if (__sign_size) 00518 __res += __sign[0]; 00519 break; 00520 case money_base::value: 00521 __res += __value; 00522 break; 00523 case money_base::space: 00524 // At least one space is required, but if internal 00525 // formatting is required, an arbitrary number of 00526 // fill spaces will be necessary. 00527 if (__testipad) 00528 __res.append(__width - __len, __fill); 00529 else 00530 __res += __fill; 00531 break; 00532 case money_base::none: 00533 if (__testipad) 00534 __res.append(__width - __len, __fill); 00535 break; 00536 } 00537 } 00538 00539 // Special case of multi-part sign parts. 00540 if (__sign_size > 1) 00541 __res.append(__sign + 1, __sign_size - 1); 00542 00543 // Pad, if still necessary. 00544 __len = __res.size(); 00545 if (__width > __len) 00546 { 00547 if (__f == ios_base::left) 00548 // After. 00549 __res.append(__width - __len, __fill); 00550 else 00551 // Before. 00552 __res.insert(0, __width - __len, __fill); 00553 __len = __width; 00554 } 00555 00556 // Write resulting, fully-formatted string to output iterator. 00557 __s = std::__write(__s, __res.data(), __len); 00558 } 00559 __io.width(0); 00560 return __s; 00561 } 00562 00563 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \ 00564 && _GLIBCXX_USE_CXX11_ABI == 0 00565 template<typename _CharT, typename _OutIter> 00566 _OutIter 00567 money_put<_CharT, _OutIter>:: 00568 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 00569 double __units) const 00570 { return this->do_put(__s, __intl, __io, __fill, (long double) __units); } 00571 #endif 00572 00573 template<typename _CharT, typename _OutIter> 00574 _OutIter 00575 money_put<_CharT, _OutIter>:: 00576 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 00577 long double __units) const 00578 { 00579 const locale __loc = __io.getloc(); 00580 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00581 #if _GLIBCXX_USE_C99_STDIO 00582 // First try a buffer perhaps big enough. 00583 int __cs_size = 64; 00584 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 00585 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00586 // 328. Bad sprintf format modifier in money_put<>::do_put() 00587 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 00588 "%.*Lf", 0, __units); 00589 // If the buffer was not large enough, try again with the correct size. 00590 if (__len >= __cs_size) 00591 { 00592 __cs_size = __len + 1; 00593 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 00594 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 00595 "%.*Lf", 0, __units); 00596 } 00597 #else 00598 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'. 00599 const int __cs_size = 00600 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3; 00601 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 00602 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 00603 0, __units); 00604 #endif 00605 string_type __digits(__len, char_type()); 00606 __ctype.widen(__cs, __cs + __len, &__digits[0]); 00607 return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 00608 : _M_insert<false>(__s, __io, __fill, __digits); 00609 } 00610 00611 template<typename _CharT, typename _OutIter> 00612 _OutIter 00613 money_put<_CharT, _OutIter>:: 00614 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 00615 const string_type& __digits) const 00616 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 00617 : _M_insert<false>(__s, __io, __fill, __digits); } 00618 00619 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 00620 00621 // NB: Not especially useful. Without an ios_base object or some 00622 // kind of locale reference, we are left clawing at the air where 00623 // the side of the mountain used to be... 00624 template<typename _CharT, typename _InIter> 00625 time_base::dateorder 00626 time_get<_CharT, _InIter>::do_date_order() const 00627 { return time_base::no_order; } 00628 00629 // Expand a strftime format string and parse it. E.g., do_get_date() may 00630 // pass %m/%d/%Y => extracted characters. 00631 template<typename _CharT, typename _InIter> 00632 _InIter 00633 time_get<_CharT, _InIter>:: 00634 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io, 00635 ios_base::iostate& __err, tm* __tm, 00636 const _CharT* __format) const 00637 { 00638 const locale& __loc = __io._M_getloc(); 00639 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 00640 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00641 const size_t __len = char_traits<_CharT>::length(__format); 00642 00643 ios_base::iostate __tmperr = ios_base::goodbit; 00644 size_t __i = 0; 00645 for (; __beg != __end && __i < __len && !__tmperr; ++__i) 00646 { 00647 if (__ctype.narrow(__format[__i], 0) == '%') 00648 { 00649 // Verify valid formatting code, attempt to extract. 00650 char __c = __ctype.narrow(__format[++__i], 0); 00651 int __mem = 0; 00652 if (__c == 'E' || __c == 'O') 00653 __c = __ctype.narrow(__format[++__i], 0); 00654 switch (__c) 00655 { 00656 const char* __cs; 00657 _CharT __wcs[10]; 00658 case 'a': 00659 // Abbreviated weekday name [tm_wday] 00660 const char_type* __days1[7]; 00661 __tp._M_days_abbreviated(__days1); 00662 __beg = _M_extract_name(__beg, __end, __mem, __days1, 00663 7, __io, __tmperr); 00664 if (!__tmperr) 00665 __tm->tm_wday = __mem; 00666 break; 00667 case 'A': 00668 // Weekday name [tm_wday]. 00669 const char_type* __days2[7]; 00670 __tp._M_days(__days2); 00671 __beg = _M_extract_name(__beg, __end, __mem, __days2, 00672 7, __io, __tmperr); 00673 if (!__tmperr) 00674 __tm->tm_wday = __mem; 00675 break; 00676 case 'h': 00677 case 'b': 00678 // Abbreviated month name [tm_mon] 00679 const char_type* __months1[12]; 00680 __tp._M_months_abbreviated(__months1); 00681 __beg = _M_extract_name(__beg, __end, __mem, 00682 __months1, 12, __io, __tmperr); 00683 if (!__tmperr) 00684 __tm->tm_mon = __mem; 00685 break; 00686 case 'B': 00687 // Month name [tm_mon]. 00688 const char_type* __months2[12]; 00689 __tp._M_months(__months2); 00690 __beg = _M_extract_name(__beg, __end, __mem, 00691 __months2, 12, __io, __tmperr); 00692 if (!__tmperr) 00693 __tm->tm_mon = __mem; 00694 break; 00695 case 'c': 00696 // Default time and date representation. 00697 const char_type* __dt[2]; 00698 __tp._M_date_time_formats(__dt); 00699 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 00700 __tm, __dt[0]); 00701 break; 00702 case 'd': 00703 // Day [01, 31]. [tm_mday] 00704 __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2, 00705 __io, __tmperr); 00706 if (!__tmperr) 00707 __tm->tm_mday = __mem; 00708 break; 00709 case 'e': 00710 // Day [1, 31], with single digits preceded by 00711 // space. [tm_mday] 00712 if (__ctype.is(ctype_base::space, *__beg)) 00713 __beg = _M_extract_num(++__beg, __end, __mem, 1, 9, 00714 1, __io, __tmperr); 00715 else 00716 __beg = _M_extract_num(__beg, __end, __mem, 10, 31, 00717 2, __io, __tmperr); 00718 if (!__tmperr) 00719 __tm->tm_mday = __mem; 00720 break; 00721 case 'D': 00722 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 00723 __cs = "%m/%d/%y"; 00724 __ctype.widen(__cs, __cs + 9, __wcs); 00725 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 00726 __tm, __wcs); 00727 break; 00728 case 'H': 00729 // Hour [00, 23]. [tm_hour] 00730 __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2, 00731 __io, __tmperr); 00732 if (!__tmperr) 00733 __tm->tm_hour = __mem; 00734 break; 00735 case 'I': 00736 // Hour [01, 12]. [tm_hour] 00737 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 00738 __io, __tmperr); 00739 if (!__tmperr) 00740 __tm->tm_hour = __mem; 00741 break; 00742 case 'm': 00743 // Month [01, 12]. [tm_mon] 00744 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 00745 __io, __tmperr); 00746 if (!__tmperr) 00747 __tm->tm_mon = __mem - 1; 00748 break; 00749 case 'M': 00750 // Minute [00, 59]. [tm_min] 00751 __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2, 00752 __io, __tmperr); 00753 if (!__tmperr) 00754 __tm->tm_min = __mem; 00755 break; 00756 case 'n': 00757 if (__ctype.narrow(*__beg, 0) == '\n') 00758 ++__beg; 00759 else 00760 __tmperr |= ios_base::failbit; 00761 break; 00762 case 'R': 00763 // Equivalent to (%H:%M). 00764 __cs = "%H:%M"; 00765 __ctype.widen(__cs, __cs + 6, __wcs); 00766 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 00767 __tm, __wcs); 00768 break; 00769 case 'S': 00770 // Seconds. [tm_sec] 00771 // [00, 60] in C99 (one leap-second), [00, 61] in C89. 00772 #if _GLIBCXX_USE_C99 00773 __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2, 00774 #else 00775 __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2, 00776 #endif 00777 __io, __tmperr); 00778 if (!__tmperr) 00779 __tm->tm_sec = __mem; 00780 break; 00781 case 't': 00782 if (__ctype.narrow(*__beg, 0) == '\t') 00783 ++__beg; 00784 else 00785 __tmperr |= ios_base::failbit; 00786 break; 00787 case 'T': 00788 // Equivalent to (%H:%M:%S). 00789 __cs = "%H:%M:%S"; 00790 __ctype.widen(__cs, __cs + 9, __wcs); 00791 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 00792 __tm, __wcs); 00793 break; 00794 case 'x': 00795 // Locale's date. 00796 const char_type* __dates[2]; 00797 __tp._M_date_formats(__dates); 00798 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 00799 __tm, __dates[0]); 00800 break; 00801 case 'X': 00802 // Locale's time. 00803 const char_type* __times[2]; 00804 __tp._M_time_formats(__times); 00805 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 00806 __tm, __times[0]); 00807 break; 00808 case 'y': 00809 case 'C': // C99 00810 // Two digit year. 00811 case 'Y': 00812 // Year [1900). 00813 // NB: We parse either two digits, implicitly years since 00814 // 1900, or 4 digits, full year. In both cases we can 00815 // reconstruct [tm_year]. See also libstdc++/26701. 00816 __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4, 00817 __io, __tmperr); 00818 if (!__tmperr) 00819 __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900; 00820 break; 00821 case 'Z': 00822 // Timezone info. 00823 if (__ctype.is(ctype_base::upper, *__beg)) 00824 { 00825 int __tmp; 00826 __beg = _M_extract_name(__beg, __end, __tmp, 00827 __timepunct_cache<_CharT>::_S_timezones, 00828 14, __io, __tmperr); 00829 00830 // GMT requires special effort. 00831 if (__beg != __end && !__tmperr && __tmp == 0 00832 && (*__beg == __ctype.widen('-') 00833 || *__beg == __ctype.widen('+'))) 00834 { 00835 __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 00836 __io, __tmperr); 00837 __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 00838 __io, __tmperr); 00839 } 00840 } 00841 else 00842 __tmperr |= ios_base::failbit; 00843 break; 00844 default: 00845 // Not recognized. 00846 __tmperr |= ios_base::failbit; 00847 } 00848 } 00849 else 00850 { 00851 // Verify format and input match, extract and discard. 00852 if (__format[__i] == *__beg) 00853 ++__beg; 00854 else 00855 __tmperr |= ios_base::failbit; 00856 } 00857 } 00858 00859 if (__tmperr || __i != __len) 00860 __err |= ios_base::failbit; 00861 00862 return __beg; 00863 } 00864 00865 template<typename _CharT, typename _InIter> 00866 _InIter 00867 time_get<_CharT, _InIter>:: 00868 _M_extract_num(iter_type __beg, iter_type __end, int& __member, 00869 int __min, int __max, size_t __len, 00870 ios_base& __io, ios_base::iostate& __err) const 00871 { 00872 const locale& __loc = __io._M_getloc(); 00873 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00874 00875 // As-is works for __len = 1, 2, 4, the values actually used. 00876 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1); 00877 00878 ++__min; 00879 size_t __i = 0; 00880 int __value = 0; 00881 for (; __beg != __end && __i < __len; ++__beg, (void)++__i) 00882 { 00883 const char __c = __ctype.narrow(*__beg, '*'); 00884 if (__c >= '0' && __c <= '9') 00885 { 00886 __value = __value * 10 + (__c - '0'); 00887 const int __valuec = __value * __mult; 00888 if (__valuec > __max || __valuec + __mult < __min) 00889 break; 00890 __mult /= 10; 00891 } 00892 else 00893 break; 00894 } 00895 if (__i == __len) 00896 __member = __value; 00897 // Special encoding for do_get_year, 'y', and 'Y' above. 00898 else if (__len == 4 && __i == 2) 00899 __member = __value - 100; 00900 else 00901 __err |= ios_base::failbit; 00902 00903 return __beg; 00904 } 00905 00906 // Assumptions: 00907 // All elements in __names are unique. 00908 template<typename _CharT, typename _InIter> 00909 _InIter 00910 time_get<_CharT, _InIter>:: 00911 _M_extract_name(iter_type __beg, iter_type __end, int& __member, 00912 const _CharT** __names, size_t __indexlen, 00913 ios_base& __io, ios_base::iostate& __err) const 00914 { 00915 typedef char_traits<_CharT> __traits_type; 00916 const locale& __loc = __io._M_getloc(); 00917 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00918 00919 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 00920 * __indexlen)); 00921 size_t __nmatches = 0; 00922 size_t __pos = 0; 00923 bool __testvalid = true; 00924 const char_type* __name; 00925 00926 // Look for initial matches. 00927 // NB: Some of the locale data is in the form of all lowercase 00928 // names, and some is in the form of initially-capitalized 00929 // names. Look for both. 00930 if (__beg != __end) 00931 { 00932 const char_type __c = *__beg; 00933 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 00934 if (__c == __names[__i1][0] 00935 || __c == __ctype.toupper(__names[__i1][0])) 00936 __matches[__nmatches++] = __i1; 00937 } 00938 00939 while (__nmatches > 1) 00940 { 00941 // Find smallest matching string. 00942 size_t __minlen = __traits_type::length(__names[__matches[0]]); 00943 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2) 00944 __minlen = std::min(__minlen, 00945 __traits_type::length(__names[__matches[__i2]])); 00946 ++__beg; 00947 ++__pos; 00948 if (__pos < __minlen && __beg != __end) 00949 for (size_t __i3 = 0; __i3 < __nmatches;) 00950 { 00951 __name = __names[__matches[__i3]]; 00952 if (!(__name[__pos] == *__beg)) 00953 __matches[__i3] = __matches[--__nmatches]; 00954 else 00955 ++__i3; 00956 } 00957 else 00958 break; 00959 } 00960 00961 if (__nmatches == 1) 00962 { 00963 // Make sure found name is completely extracted. 00964 ++__beg; 00965 ++__pos; 00966 __name = __names[__matches[0]]; 00967 const size_t __len = __traits_type::length(__name); 00968 while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 00969 ++__beg, (void)++__pos; 00970 00971 if (__len == __pos) 00972 __member = __matches[0]; 00973 else 00974 __testvalid = false; 00975 } 00976 else 00977 __testvalid = false; 00978 if (!__testvalid) 00979 __err |= ios_base::failbit; 00980 00981 return __beg; 00982 } 00983 00984 template<typename _CharT, typename _InIter> 00985 _InIter 00986 time_get<_CharT, _InIter>:: 00987 _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member, 00988 const _CharT** __names, size_t __indexlen, 00989 ios_base& __io, ios_base::iostate& __err) const 00990 { 00991 typedef char_traits<_CharT> __traits_type; 00992 const locale& __loc = __io._M_getloc(); 00993 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 00994 00995 int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int) 00996 * __indexlen)); 00997 size_t __nmatches = 0; 00998 size_t* __matches_lengths = 0; 00999 size_t __pos = 0; 01000 01001 if (__beg != __end) 01002 { 01003 const char_type __c = *__beg; 01004 for (size_t __i = 0; __i < 2 * __indexlen; ++__i) 01005 if (__c == __names[__i][0] 01006 || __c == __ctype.toupper(__names[__i][0])) 01007 __matches[__nmatches++] = __i; 01008 } 01009 01010 if (__nmatches) 01011 { 01012 ++__beg; 01013 ++__pos; 01014 01015 __matches_lengths 01016 = static_cast<size_t*>(__builtin_alloca(sizeof(size_t) 01017 * __nmatches)); 01018 for (size_t __i = 0; __i < __nmatches; ++__i) 01019 __matches_lengths[__i] 01020 = __traits_type::length(__names[__matches[__i]]); 01021 } 01022 01023 for (; __beg != __end; ++__beg, (void)++__pos) 01024 { 01025 size_t __nskipped = 0; 01026 const char_type __c = *__beg; 01027 for (size_t __i = 0; __i < __nmatches;) 01028 { 01029 const char_type* __name = __names[__matches[__i]]; 01030 if (__pos >= __matches_lengths[__i]) 01031 ++__nskipped, ++__i; 01032 else if (!(__name[__pos] == __c)) 01033 { 01034 --__nmatches; 01035 __matches[__i] = __matches[__nmatches]; 01036 __matches_lengths[__i] = __matches_lengths[__nmatches]; 01037 } 01038 else 01039 ++__i; 01040 } 01041 if (__nskipped == __nmatches) 01042 break; 01043 } 01044 01045 if ((__nmatches == 1 && __matches_lengths[0] == __pos) 01046 || (__nmatches == 2 && (__matches_lengths[0] == __pos 01047 || __matches_lengths[1] == __pos))) 01048 __member = (__matches[0] >= __indexlen 01049 ? __matches[0] - __indexlen : __matches[0]); 01050 else 01051 __err |= ios_base::failbit; 01052 01053 return __beg; 01054 } 01055 01056 template<typename _CharT, typename _InIter> 01057 _InIter 01058 time_get<_CharT, _InIter>:: 01059 do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 01060 ios_base::iostate& __err, tm* __tm) const 01061 { 01062 const locale& __loc = __io._M_getloc(); 01063 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 01064 const char_type* __times[2]; 01065 __tp._M_time_formats(__times); 01066 __beg = _M_extract_via_format(__beg, __end, __io, __err, 01067 __tm, __times[0]); 01068 if (__beg == __end) 01069 __err |= ios_base::eofbit; 01070 return __beg; 01071 } 01072 01073 template<typename _CharT, typename _InIter> 01074 _InIter 01075 time_get<_CharT, _InIter>:: 01076 do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 01077 ios_base::iostate& __err, tm* __tm) const 01078 { 01079 const locale& __loc = __io._M_getloc(); 01080 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 01081 const char_type* __dates[2]; 01082 __tp._M_date_formats(__dates); 01083 __beg = _M_extract_via_format(__beg, __end, __io, __err, 01084 __tm, __dates[0]); 01085 if (__beg == __end) 01086 __err |= ios_base::eofbit; 01087 return __beg; 01088 } 01089 01090 template<typename _CharT, typename _InIter> 01091 _InIter 01092 time_get<_CharT, _InIter>:: 01093 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 01094 ios_base::iostate& __err, tm* __tm) const 01095 { 01096 const locale& __loc = __io._M_getloc(); 01097 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 01098 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01099 const char_type* __days[14]; 01100 __tp._M_days_abbreviated(__days); 01101 __tp._M_days(__days + 7); 01102 int __tmpwday; 01103 ios_base::iostate __tmperr = ios_base::goodbit; 01104 01105 __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7, 01106 __io, __tmperr); 01107 if (!__tmperr) 01108 __tm->tm_wday = __tmpwday; 01109 else 01110 __err |= ios_base::failbit; 01111 01112 if (__beg == __end) 01113 __err |= ios_base::eofbit; 01114 return __beg; 01115 } 01116 01117 template<typename _CharT, typename _InIter> 01118 _InIter 01119 time_get<_CharT, _InIter>:: 01120 do_get_monthname(iter_type __beg, iter_type __end, 01121 ios_base& __io, ios_base::iostate& __err, tm* __tm) const 01122 { 01123 const locale& __loc = __io._M_getloc(); 01124 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 01125 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01126 const char_type* __months[24]; 01127 __tp._M_months_abbreviated(__months); 01128 __tp._M_months(__months + 12); 01129 int __tmpmon; 01130 ios_base::iostate __tmperr = ios_base::goodbit; 01131 01132 __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12, 01133 __io, __tmperr); 01134 if (!__tmperr) 01135 __tm->tm_mon = __tmpmon; 01136 else 01137 __err |= ios_base::failbit; 01138 01139 if (__beg == __end) 01140 __err |= ios_base::eofbit; 01141 return __beg; 01142 } 01143 01144 template<typename _CharT, typename _InIter> 01145 _InIter 01146 time_get<_CharT, _InIter>:: 01147 do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 01148 ios_base::iostate& __err, tm* __tm) const 01149 { 01150 const locale& __loc = __io._M_getloc(); 01151 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01152 int __tmpyear; 01153 ios_base::iostate __tmperr = ios_base::goodbit; 01154 01155 __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4, 01156 __io, __tmperr); 01157 if (!__tmperr) 01158 __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900; 01159 else 01160 __err |= ios_base::failbit; 01161 01162 if (__beg == __end) 01163 __err |= ios_base::eofbit; 01164 return __beg; 01165 } 01166 01167 #if __cplusplus >= 201103L 01168 template<typename _CharT, typename _InIter> 01169 inline 01170 _InIter 01171 time_get<_CharT, _InIter>:: 01172 get(iter_type __s, iter_type __end, ios_base& __io, 01173 ios_base::iostate& __err, tm* __tm, const char_type* __fmt, 01174 const char_type* __fmtend) const 01175 { 01176 const locale& __loc = __io._M_getloc(); 01177 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 01178 __err = ios_base::goodbit; 01179 while (__fmt != __fmtend && 01180 __err == ios_base::goodbit) 01181 { 01182 if (__s == __end) 01183 { 01184 __err = ios_base::eofbit | ios_base::failbit; 01185 break; 01186 } 01187 else if (__ctype.narrow(*__fmt, 0) == '%') 01188 { 01189 char __format; 01190 char __mod = 0; 01191 if (++__fmt == __fmtend) 01192 { 01193 __err = ios_base::failbit; 01194 break; 01195 } 01196 const char __c = __ctype.narrow(*__fmt, 0); 01197 if (__c != 'E' && __c != 'O') 01198 __format = __c; 01199 else if (++__fmt != __fmtend) 01200 { 01201 __mod = __c; 01202 __format = __ctype.narrow(*__fmt, 0); 01203 } 01204 else 01205 { 01206 __err = ios_base::failbit; 01207 break; 01208 } 01209 __s = this->do_get(__s, __end, __io, __err, __tm, __format, 01210 __mod); 01211 ++__fmt; 01212 } 01213 else if (__ctype.is(ctype_base::space, *__fmt)) 01214 { 01215 ++__fmt; 01216 while (__fmt != __fmtend && 01217 __ctype.is(ctype_base::space, *__fmt)) 01218 ++__fmt; 01219 01220 while (__s != __end && 01221 __ctype.is(ctype_base::space, *__s)) 01222 ++__s; 01223 } 01224 // TODO real case-insensitive comparison 01225 else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) || 01226 __ctype.toupper(*__s) == __ctype.toupper(*__fmt)) 01227 { 01228 ++__s; 01229 ++__fmt; 01230 } 01231 else 01232 { 01233 __err = ios_base::failbit; 01234 break; 01235 } 01236 } 01237 return __s; 01238 } 01239 01240 template<typename _CharT, typename _InIter> 01241 inline 01242 _InIter 01243 time_get<_CharT, _InIter>:: 01244 do_get(iter_type __beg, iter_type __end, ios_base& __io, 01245 ios_base::iostate& __err, tm* __tm, 01246 char __format, char __mod) const 01247 { 01248 const locale& __loc = __io._M_getloc(); 01249 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 01250 __err = ios_base::goodbit; 01251 01252 char_type __fmt[4]; 01253 __fmt[0] = __ctype.widen('%'); 01254 if (!__mod) 01255 { 01256 __fmt[1] = __format; 01257 __fmt[2] = char_type(); 01258 } 01259 else 01260 { 01261 __fmt[1] = __mod; 01262 __fmt[2] = __format; 01263 __fmt[3] = char_type(); 01264 } 01265 01266 __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt); 01267 if (__beg == __end) 01268 __err |= ios_base::eofbit; 01269 return __beg; 01270 } 01271 01272 #endif // __cplusplus >= 201103L 01273 01274 template<typename _CharT, typename _OutIter> 01275 _OutIter 01276 time_put<_CharT, _OutIter>:: 01277 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, 01278 const _CharT* __beg, const _CharT* __end) const 01279 { 01280 const locale& __loc = __io._M_getloc(); 01281 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 01282 for (; __beg != __end; ++__beg) 01283 if (__ctype.narrow(*__beg, 0) != '%') 01284 { 01285 *__s = *__beg; 01286 ++__s; 01287 } 01288 else if (++__beg != __end) 01289 { 01290 char __format; 01291 char __mod = 0; 01292 const char __c = __ctype.narrow(*__beg, 0); 01293 if (__c != 'E' && __c != 'O') 01294 __format = __c; 01295 else if (++__beg != __end) 01296 { 01297 __mod = __c; 01298 __format = __ctype.narrow(*__beg, 0); 01299 } 01300 else 01301 break; 01302 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod); 01303 } 01304 else 01305 break; 01306 return __s; 01307 } 01308 01309 template<typename _CharT, typename _OutIter> 01310 _OutIter 01311 time_put<_CharT, _OutIter>:: 01312 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 01313 char __format, char __mod) const 01314 { 01315 const locale& __loc = __io._M_getloc(); 01316 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 01317 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 01318 01319 // NB: This size is arbitrary. Should this be a data member, 01320 // initialized at construction? 01321 const size_t __maxlen = 128; 01322 char_type __res[__maxlen]; 01323 01324 // NB: In IEE 1003.1-200x, and perhaps other locale models, it 01325 // is possible that the format character will be longer than one 01326 // character. Possibilities include 'E' or 'O' followed by a 01327 // format character: if __mod is not the default argument, assume 01328 // it's a valid modifier. 01329 char_type __fmt[4]; 01330 __fmt[0] = __ctype.widen('%'); 01331 if (!__mod) 01332 { 01333 __fmt[1] = __format; 01334 __fmt[2] = char_type(); 01335 } 01336 else 01337 { 01338 __fmt[1] = __mod; 01339 __fmt[2] = __format; 01340 __fmt[3] = char_type(); 01341 } 01342 01343 __tp._M_put(__res, __maxlen, __fmt, __tm); 01344 01345 // Write resulting, fully-formatted string to output iterator. 01346 return std::__write(__s, __res, char_traits<char_type>::length(__res)); 01347 } 01348 01349 01350 // Inhibit implicit instantiations for required instantiations, 01351 // which are defined via explicit instantiations elsewhere. 01352 #if _GLIBCXX_EXTERN_TEMPLATE 01353 extern template class moneypunct<char, false>; 01354 extern template class moneypunct<char, true>; 01355 extern template class moneypunct_byname<char, false>; 01356 extern template class moneypunct_byname<char, true>; 01357 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>; 01358 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>; 01359 extern template class __timepunct<char>; 01360 extern template class time_put<char>; 01361 extern template class time_put_byname<char>; 01362 extern template class time_get<char>; 01363 extern template class time_get_byname<char>; 01364 extern template class messages<char>; 01365 extern template class messages_byname<char>; 01366 01367 extern template 01368 const moneypunct<char, true>& 01369 use_facet<moneypunct<char, true> >(const locale&); 01370 01371 extern template 01372 const moneypunct<char, false>& 01373 use_facet<moneypunct<char, false> >(const locale&); 01374 01375 extern template 01376 const money_put<char>& 01377 use_facet<money_put<char> >(const locale&); 01378 01379 extern template 01380 const money_get<char>& 01381 use_facet<money_get<char> >(const locale&); 01382 01383 extern template 01384 const __timepunct<char>& 01385 use_facet<__timepunct<char> >(const locale&); 01386 01387 extern template 01388 const time_put<char>& 01389 use_facet<time_put<char> >(const locale&); 01390 01391 extern template 01392 const time_get<char>& 01393 use_facet<time_get<char> >(const locale&); 01394 01395 extern template 01396 const messages<char>& 01397 use_facet<messages<char> >(const locale&); 01398 01399 extern template 01400 bool 01401 has_facet<moneypunct<char> >(const locale&); 01402 01403 extern template 01404 bool 01405 has_facet<money_put<char> >(const locale&); 01406 01407 extern template 01408 bool 01409 has_facet<money_get<char> >(const locale&); 01410 01411 extern template 01412 bool 01413 has_facet<__timepunct<char> >(const locale&); 01414 01415 extern template 01416 bool 01417 has_facet<time_put<char> >(const locale&); 01418 01419 extern template 01420 bool 01421 has_facet<time_get<char> >(const locale&); 01422 01423 extern template 01424 bool 01425 has_facet<messages<char> >(const locale&); 01426 01427 #ifdef _GLIBCXX_USE_WCHAR_T 01428 extern template class moneypunct<wchar_t, false>; 01429 extern template class moneypunct<wchar_t, true>; 01430 extern template class moneypunct_byname<wchar_t, false>; 01431 extern template class moneypunct_byname<wchar_t, true>; 01432 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>; 01433 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>; 01434 extern template class __timepunct<wchar_t>; 01435 extern template class time_put<wchar_t>; 01436 extern template class time_put_byname<wchar_t>; 01437 extern template class time_get<wchar_t>; 01438 extern template class time_get_byname<wchar_t>; 01439 extern template class messages<wchar_t>; 01440 extern template class messages_byname<wchar_t>; 01441 01442 extern template 01443 const moneypunct<wchar_t, true>& 01444 use_facet<moneypunct<wchar_t, true> >(const locale&); 01445 01446 extern template 01447 const moneypunct<wchar_t, false>& 01448 use_facet<moneypunct<wchar_t, false> >(const locale&); 01449 01450 extern template 01451 const money_put<wchar_t>& 01452 use_facet<money_put<wchar_t> >(const locale&); 01453 01454 extern template 01455 const money_get<wchar_t>& 01456 use_facet<money_get<wchar_t> >(const locale&); 01457 01458 extern template 01459 const __timepunct<wchar_t>& 01460 use_facet<__timepunct<wchar_t> >(const locale&); 01461 01462 extern template 01463 const time_put<wchar_t>& 01464 use_facet<time_put<wchar_t> >(const locale&); 01465 01466 extern template 01467 const time_get<wchar_t>& 01468 use_facet<time_get<wchar_t> >(const locale&); 01469 01470 extern template 01471 const messages<wchar_t>& 01472 use_facet<messages<wchar_t> >(const locale&); 01473 01474 extern template 01475 bool 01476 has_facet<moneypunct<wchar_t> >(const locale&); 01477 01478 extern template 01479 bool 01480 has_facet<money_put<wchar_t> >(const locale&); 01481 01482 extern template 01483 bool 01484 has_facet<money_get<wchar_t> >(const locale&); 01485 01486 extern template 01487 bool 01488 has_facet<__timepunct<wchar_t> >(const locale&); 01489 01490 extern template 01491 bool 01492 has_facet<time_put<wchar_t> >(const locale&); 01493 01494 extern template 01495 bool 01496 has_facet<time_get<wchar_t> >(const locale&); 01497 01498 extern template 01499 bool 01500 has_facet<messages<wchar_t> >(const locale&); 01501 #endif 01502 #endif 01503 01504 _GLIBCXX_END_NAMESPACE_VERSION 01505 } // namespace std 01506 01507 #endif