locale_facets.tcc

00001 // Locale support -*- C++ -*- 00002 00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 00004 // Free Software Foundation, Inc. 00005 // 00006 // This file is part of the GNU ISO C++ Library. This library is free 00007 // software; you can redistribute it and/or modify it under the 00008 // terms of the GNU General Public License as published by the 00009 // Free Software Foundation; either version 2, or (at your option) 00010 // any later version. 00011 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 00017 // You should have received a copy of the GNU General Public License along 00018 // with this library; see the file COPYING. If not, write to the Free 00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 00020 // USA. 00021 00022 // As a special exception, you may use this file as part of a free software 00023 // library without restriction. Specifically, if other files instantiate 00024 // templates or use macros or inline functions from this file, or you compile 00025 // this file and link it with other files to produce an executable, this 00026 // file does not by itself cause the resulting executable to be covered by 00027 // the GNU General Public License. This exception does not however 00028 // invalidate any other reasons why the executable file might be covered by 00029 // the GNU General Public License. 00030 00031 // Warning: this file is not meant for user inclusion. Use <locale>. 00032 00033 #ifndef _LOCALE_FACETS_TCC 00034 #define _LOCALE_FACETS_TCC 1 00035 00036 #pragma GCC system_header 00037 00038 #include <limits> // For numeric_limits 00039 #include <typeinfo> // For bad_cast. 00040 #include <bits/streambuf_iterator.h> 00041 00042 namespace std 00043 { 00044 template<typename _Facet> 00045 locale 00046 locale::combine(const locale& __other) const 00047 { 00048 _Impl* __tmp = new _Impl(*_M_impl, 1); 00049 try 00050 { 00051 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id); 00052 } 00053 catch(...) 00054 { 00055 __tmp->_M_remove_reference(); 00056 __throw_exception_again; 00057 } 00058 return locale(__tmp); 00059 } 00060 00061 template<typename _CharT, typename _Traits, typename _Alloc> 00062 bool 00063 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1, 00064 const basic_string<_CharT, _Traits, _Alloc>& __s2) const 00065 { 00066 typedef std::collate<_CharT> __collate_type; 00067 const __collate_type& __collate = use_facet<__collate_type>(*this); 00068 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(), 00069 __s2.data(), __s2.data() + __s2.length()) < 0); 00070 } 00071 00072 /** 00073 * @brief Test for the presence of a facet. 00074 * 00075 * has_facet tests the locale argument for the presence of the facet type 00076 * provided as the template parameter. Facets derived from the facet 00077 * parameter will also return true. 00078 * 00079 * @param Facet The facet type to test the presence of. 00080 * @param locale The locale to test. 00081 * @return true if locale contains a facet of type Facet, else false. 00082 */ 00083 template<typename _Facet> 00084 inline bool 00085 has_facet(const locale& __loc) throw() 00086 { 00087 const size_t __i = _Facet::id._M_id(); 00088 const locale::facet** __facets = __loc._M_impl->_M_facets; 00089 return (__i < __loc._M_impl->_M_facets_size && __facets[__i]); 00090 } 00091 00092 /** 00093 * @brief Return a facet. 00094 * 00095 * use_facet looks for and returns a reference to a facet of type Facet 00096 * where Facet is the template parameter. If has_facet(locale) is true, 00097 * there is a suitable facet to return. It throws std::bad_cast if the 00098 * locale doesn't contain a facet of type Facet. 00099 * 00100 * @param Facet The facet type to access. 00101 * @param locale The locale to use. 00102 * @return Reference to facet of type Facet. 00103 * @throw std::bad_cast if locale doesn't contain a facet of type Facet. 00104 */ 00105 template<typename _Facet> 00106 inline const _Facet& 00107 use_facet(const locale& __loc) 00108 { 00109 const size_t __i = _Facet::id._M_id(); 00110 const locale::facet** __facets = __loc._M_impl->_M_facets; 00111 if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i])) 00112 __throw_bad_cast(); 00113 return static_cast<const _Facet&>(*__facets[__i]); 00114 } 00115 00116 // Routine to access a cache for the facet. If the cache didn't 00117 // exist before, it gets constructed on the fly. 00118 template<typename _Facet> 00119 struct __use_cache 00120 { 00121 const _Facet* 00122 operator() (const locale& __loc) const; 00123 }; 00124 00125 // Specializations. 00126 template<typename _CharT> 00127 struct __use_cache<__numpunct_cache<_CharT> > 00128 { 00129 const __numpunct_cache<_CharT>* 00130 operator() (const locale& __loc) const 00131 { 00132 const size_t __i = numpunct<_CharT>::id._M_id(); 00133 const locale::facet** __caches = __loc._M_impl->_M_caches; 00134 if (!__caches[__i]) 00135 { 00136 __numpunct_cache<_CharT>* __tmp = NULL; 00137 try 00138 { 00139 __tmp = new __numpunct_cache<_CharT>; 00140 __tmp->_M_cache(__loc); 00141 } 00142 catch(...) 00143 { 00144 delete __tmp; 00145 __throw_exception_again; 00146 } 00147 __loc._M_impl->_M_install_cache(__tmp, __i); 00148 } 00149 return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]); 00150 } 00151 }; 00152 00153 template<typename _CharT, bool _Intl> 00154 struct __use_cache<__moneypunct_cache<_CharT, _Intl> > 00155 { 00156 const __moneypunct_cache<_CharT, _Intl>* 00157 operator() (const locale& __loc) const 00158 { 00159 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id(); 00160 const locale::facet** __caches = __loc._M_impl->_M_caches; 00161 if (!__caches[__i]) 00162 { 00163 __moneypunct_cache<_CharT, _Intl>* __tmp = NULL; 00164 try 00165 { 00166 __tmp = new __moneypunct_cache<_CharT, _Intl>; 00167 __tmp->_M_cache(__loc); 00168 } 00169 catch(...) 00170 { 00171 delete __tmp; 00172 __throw_exception_again; 00173 } 00174 __loc._M_impl->_M_install_cache(__tmp, __i); 00175 } 00176 return static_cast< 00177 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]); 00178 } 00179 }; 00180 00181 template<typename _CharT> 00182 void 00183 __numpunct_cache<_CharT>::_M_cache(const locale& __loc) 00184 { 00185 _M_allocated = true; 00186 00187 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 00188 00189 _M_grouping_size = __np.grouping().size(); 00190 char* __grouping = new char[_M_grouping_size]; 00191 __np.grouping().copy(__grouping, _M_grouping_size); 00192 _M_grouping = __grouping; 00193 _M_use_grouping = _M_grouping_size && __np.grouping()[0] != 0; 00194 00195 _M_truename_size = __np.truename().size(); 00196 _CharT* __truename = new _CharT[_M_truename_size]; 00197 __np.truename().copy(__truename, _M_truename_size); 00198 _M_truename = __truename; 00199 00200 _M_falsename_size = __np.falsename().size(); 00201 _CharT* __falsename = new _CharT[_M_falsename_size]; 00202 __np.falsename().copy(__falsename, _M_falsename_size); 00203 _M_falsename = __falsename; 00204 00205 _M_decimal_point = __np.decimal_point(); 00206 _M_thousands_sep = __np.thousands_sep(); 00207 00208 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 00209 __ct.widen(__num_base::_S_atoms_out, 00210 __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out); 00211 __ct.widen(__num_base::_S_atoms_in, 00212 __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in); 00213 } 00214 00215 template<typename _CharT, bool _Intl> 00216 void 00217 __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc) 00218 { 00219 _M_allocated = true; 00220 00221 const moneypunct<_CharT, _Intl>& __mp = 00222 use_facet<moneypunct<_CharT, _Intl> >(__loc); 00223 00224 _M_grouping_size = __mp.grouping().size(); 00225 char* __grouping = new char[_M_grouping_size]; 00226 __mp.grouping().copy(__grouping, _M_grouping_size); 00227 _M_grouping = __grouping; 00228 _M_use_grouping = _M_grouping_size && __mp.grouping()[0] != 0; 00229 00230 _M_decimal_point = __mp.decimal_point(); 00231 _M_thousands_sep = __mp.thousands_sep(); 00232 _M_frac_digits = __mp.frac_digits(); 00233 00234 _M_curr_symbol_size = __mp.curr_symbol().size(); 00235 _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size]; 00236 __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size); 00237 _M_curr_symbol = __curr_symbol; 00238 00239 _M_positive_sign_size = __mp.positive_sign().size(); 00240 _CharT* __positive_sign = new _CharT[_M_positive_sign_size]; 00241 __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size); 00242 _M_positive_sign = __positive_sign; 00243 00244 _M_negative_sign_size = __mp.negative_sign().size(); 00245 _CharT* __negative_sign = new _CharT[_M_negative_sign_size]; 00246 __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size); 00247 _M_negative_sign = __negative_sign; 00248 00249 _M_pos_format = __mp.pos_format(); 00250 _M_neg_format = __mp.neg_format(); 00251 00252 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 00253 __ct.widen(money_base::_S_atoms, 00254 money_base::_S_atoms + money_base::_S_end, _M_atoms); 00255 } 00256 00257 00258 // Used by both numeric and monetary facets. 00259 // Check to make sure that the __grouping_tmp string constructed in 00260 // money_get or num_get matches the canonical grouping for a given 00261 // locale. 00262 // __grouping_tmp is parsed L to R 00263 // 1,222,444 == __grouping_tmp of "\1\3\3" 00264 // __grouping is parsed R to L 00265 // 1,222,444 == __grouping of "\3" == "\3\3\3" 00266 static bool 00267 __verify_grouping(const char* __grouping, size_t __grouping_size, 00268 const string& __grouping_tmp); 00269 00270 template<typename _CharT, typename _InIter> 00271 _InIter 00272 num_get<_CharT, _InIter>:: 00273 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, 00274 ios_base::iostate& __err, string& __xtrc) const 00275 { 00276 typedef char_traits<_CharT> __traits_type; 00277 typedef typename numpunct<_CharT>::__cache_type __cache_type; 00278 __use_cache<__cache_type> __uc; 00279 const locale& __loc = __io._M_getloc(); 00280 const __cache_type* __lc = __uc(__loc); 00281 const _CharT* __lit = __lc->_M_atoms_in; 00282 00283 // True if a mantissa is found. 00284 bool __found_mantissa = false; 00285 00286 // First check for sign. 00287 if (__beg != __end) 00288 { 00289 const char_type __c = *__beg; 00290 const bool __plus = __c == __lit[__num_base::_S_iplus]; 00291 if ((__plus || __c == __lit[__num_base::_S_iminus]) 00292 && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00293 && !(__c == __lc->_M_decimal_point)) 00294 { 00295 __xtrc += __plus ? '+' : '-'; 00296 ++__beg; 00297 } 00298 } 00299 00300 // Next, look for leading zeros. 00301 while (__beg != __end) 00302 { 00303 const char_type __c = *__beg; 00304 if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep 00305 || __c == __lc->_M_decimal_point) 00306 break; 00307 else if (__c == __lit[__num_base::_S_izero]) 00308 { 00309 if (!__found_mantissa) 00310 { 00311 __xtrc += '0'; 00312 __found_mantissa = true; 00313 } 00314 ++__beg; 00315 } 00316 else 00317 break; 00318 } 00319 00320 // Only need acceptable digits for floating point numbers. 00321 bool __found_dec = false; 00322 bool __found_sci = false; 00323 string __found_grouping; 00324 if (__lc->_M_use_grouping) 00325 __found_grouping.reserve(32); 00326 int __sep_pos = 0; 00327 const char_type* __lit_zero = __lit + __num_base::_S_izero; 00328 const char_type* __q; 00329 while (__beg != __end) 00330 { 00331 // According to 22.2.2.1.2, p8-9, first look for thousands_sep 00332 // and decimal_point. 00333 const char_type __c = *__beg; 00334 if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00335 { 00336 if (!__found_dec && !__found_sci) 00337 { 00338 // NB: Thousands separator at the beginning of a string 00339 // is a no-no, as is two consecutive thousands separators. 00340 if (__sep_pos) 00341 { 00342 __found_grouping += static_cast<char>(__sep_pos); 00343 __sep_pos = 0; 00344 ++__beg; 00345 } 00346 else 00347 { 00348 __err |= ios_base::failbit; 00349 break; 00350 } 00351 } 00352 else 00353 break; 00354 } 00355 else if (__c == __lc->_M_decimal_point) 00356 { 00357 if (!__found_dec && !__found_sci) 00358 { 00359 // If no grouping chars are seen, no grouping check 00360 // is applied. Therefore __found_grouping is adjusted 00361 // only if decimal_point comes after some thousands_sep. 00362 if (__found_grouping.size()) 00363 __found_grouping += static_cast<char>(__sep_pos); 00364 __xtrc += '.'; 00365 __found_dec = true; 00366 ++__beg; 00367 } 00368 else 00369 break; 00370 } 00371 else if (__q = __traits_type::find(__lit_zero, 10, __c)) 00372 { 00373 __xtrc += __num_base::_S_atoms_in[__q - __lit]; 00374 __found_mantissa = true; 00375 ++__sep_pos; 00376 ++__beg; 00377 } 00378 else if ((__c == __lit[__num_base::_S_ie] 00379 || __c == __lit[__num_base::_S_iE]) 00380 && __found_mantissa && !__found_sci) 00381 { 00382 // Scientific notation. 00383 if (__found_grouping.size() && !__found_dec) 00384 __found_grouping += static_cast<char>(__sep_pos); 00385 __xtrc += 'e'; 00386 __found_sci = true; 00387 00388 // Remove optional plus or minus sign, if they exist. 00389 if (++__beg != __end) 00390 { 00391 const bool __plus = *__beg == __lit[__num_base::_S_iplus]; 00392 if ((__plus || *__beg == __lit[__num_base::_S_iminus]) 00393 && !(__lc->_M_use_grouping 00394 && *__beg == __lc->_M_thousands_sep) 00395 && !(*__beg == __lc->_M_decimal_point)) 00396 { 00397 __xtrc += __plus ? '+' : '-'; 00398 ++__beg; 00399 } 00400 } 00401 } 00402 else 00403 // Not a valid input item. 00404 break; 00405 } 00406 00407 // Digit grouping is checked. If grouping and found_grouping don't 00408 // match, then get very very upset, and set failbit. 00409 if (__found_grouping.size()) 00410 { 00411 // Add the ending grouping if a decimal or 'e'/'E' wasn't found. 00412 if (!__found_dec && !__found_sci) 00413 __found_grouping += static_cast<char>(__sep_pos); 00414 00415 if (!std::__verify_grouping(__lc->_M_grouping, 00416 __lc->_M_grouping_size, 00417 __found_grouping)) 00418 __err |= ios_base::failbit; 00419 } 00420 00421 // Finish up. 00422 if (__beg == __end) 00423 __err |= ios_base::eofbit; 00424 return __beg; 00425 } 00426 00427 template<typename _CharT, typename _InIter> 00428 template<typename _ValueT> 00429 _InIter 00430 num_get<_CharT, _InIter>:: 00431 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, 00432 ios_base::iostate& __err, _ValueT& __v) const 00433 { 00434 typedef char_traits<_CharT> __traits_type; 00435 typedef typename numpunct<_CharT>::__cache_type __cache_type; 00436 __use_cache<__cache_type> __uc; 00437 const locale& __loc = __io._M_getloc(); 00438 const __cache_type* __lc = __uc(__loc); 00439 const _CharT* __lit = __lc->_M_atoms_in; 00440 00441 // NB: Iff __basefield == 0, __base can change based on contents. 00442 const ios_base::fmtflags __basefield = __io.flags() 00443 & ios_base::basefield; 00444 const bool __oct = __basefield == ios_base::oct; 00445 int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10); 00446 00447 // True if numeric digits are found. 00448 bool __found_num = false; 00449 00450 // First check for sign. 00451 bool __negative = false; 00452 if (__beg != __end) 00453 { 00454 const char_type __c = *__beg; 00455 if (numeric_limits<_ValueT>::is_signed) 00456 __negative = __c == __lit[__num_base::_S_iminus]; 00457 if ((__negative || __c == __lit[__num_base::_S_iplus]) 00458 && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00459 && !(__c == __lc->_M_decimal_point)) 00460 ++__beg; 00461 } 00462 00463 // Next, look for leading zeros and check required digits 00464 // for base formats. 00465 while (__beg != __end) 00466 { 00467 const char_type __c = *__beg; 00468 if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep 00469 || __c == __lc->_M_decimal_point) 00470 break; 00471 else if (__c == __lit[__num_base::_S_izero] 00472 && (!__found_num || __base == 10)) 00473 { 00474 __found_num = true; 00475 ++__beg; 00476 } 00477 else if (__found_num) 00478 { 00479 if (__c == __lit[__num_base::_S_ix] 00480 || __c == __lit[__num_base::_S_iX]) 00481 { 00482 if (__basefield == 0) 00483 __base = 16; 00484 if (__base == 16) 00485 { 00486 __found_num = false; 00487 ++__beg; 00488 } 00489 } 00490 else if (__basefield == 0) 00491 __base = 8; 00492 break; 00493 } 00494 else 00495 break; 00496 } 00497 00498 // At this point, base is determined. If not hex, only allow 00499 // base digits as valid input. 00500 const size_t __len = (__base == 16 ? __num_base::_S_iend 00501 - __num_base::_S_izero : __base); 00502 00503 // Extract. 00504 string __found_grouping; 00505 if (__lc->_M_use_grouping) 00506 __found_grouping.reserve(32); 00507 int __sep_pos = 0; 00508 bool __overflow = false; 00509 _ValueT __result = 0; 00510 const char_type* __lit_zero = __lit + __num_base::_S_izero; 00511 const char_type* __q; 00512 if (__negative) 00513 { 00514 const _ValueT __min = numeric_limits<_ValueT>::min() / __base; 00515 for (; __beg != __end; ++__beg) 00516 { 00517 // According to 22.2.2.1.2, p8-9, first look for thousands_sep 00518 // and decimal_point. 00519 const char_type __c = *__beg; 00520 if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00521 { 00522 // NB: Thousands separator at the beginning of a string 00523 // is a no-no, as is two consecutive thousands separators. 00524 if (__sep_pos) 00525 { 00526 __found_grouping += static_cast<char>(__sep_pos); 00527 __sep_pos = 0; 00528 } 00529 else 00530 { 00531 __err |= ios_base::failbit; 00532 break; 00533 } 00534 } 00535 else if (__c == __lc->_M_decimal_point) 00536 break; 00537 else if (__q = __traits_type::find(__lit_zero, __len, __c)) 00538 { 00539 int __digit = __q - __lit_zero; 00540 if (__digit > 15) 00541 __digit -= 6; 00542 if (__result < __min) 00543 __overflow = true; 00544 else 00545 { 00546 const _ValueT __new_result = __result * __base 00547 - __digit; 00548 __overflow |= __new_result > __result; 00549 __result = __new_result; 00550 ++__sep_pos; 00551 __found_num = true; 00552 } 00553 } 00554 else 00555 // Not a valid input item. 00556 break; 00557 } 00558 } 00559 else 00560 { 00561 const _ValueT __max = numeric_limits<_ValueT>::max() / __base; 00562 for (; __beg != __end; ++__beg) 00563 { 00564 const char_type __c = *__beg; 00565 if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00566 { 00567 if (__sep_pos) 00568 { 00569 __found_grouping += static_cast<char>(__sep_pos); 00570 __sep_pos = 0; 00571 } 00572 else 00573 { 00574 __err |= ios_base::failbit; 00575 break; 00576 } 00577 } 00578 else if (__c == __lc->_M_decimal_point) 00579 break; 00580 else if (__q = __traits_type::find(__lit_zero, __len, __c)) 00581 { 00582 int __digit = __q - __lit_zero; 00583 if (__digit > 15) 00584 __digit -= 6; 00585 if (__result > __max) 00586 __overflow = true; 00587 else 00588 { 00589 const _ValueT __new_result = __result * __base 00590 + __digit; 00591 __overflow |= __new_result < __result; 00592 __result = __new_result; 00593 ++__sep_pos; 00594 __found_num = true; 00595 } 00596 } 00597 else 00598 break; 00599 } 00600 } 00601 00602 // Digit grouping is checked. If grouping and found_grouping don't 00603 // match, then get very very upset, and set failbit. 00604 if (__found_grouping.size()) 00605 { 00606 // Add the ending grouping. 00607 __found_grouping += static_cast<char>(__sep_pos); 00608 00609 if (!std::__verify_grouping(__lc->_M_grouping, 00610 __lc->_M_grouping_size, 00611 __found_grouping)) 00612 __err |= ios_base::failbit; 00613 } 00614 00615 if (!(__err & ios_base::failbit) && !__overflow 00616 && __found_num) 00617 __v = __result; 00618 else 00619 __err |= ios_base::failbit; 00620 00621 if (__beg == __end) 00622 __err |= ios_base::eofbit; 00623 return __beg; 00624 } 00625 00626 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00627 // 17. Bad bool parsing 00628 template<typename _CharT, typename _InIter> 00629 _InIter 00630 num_get<_CharT, _InIter>:: 00631 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00632 ios_base::iostate& __err, bool& __v) const 00633 { 00634 if (!(__io.flags() & ios_base::boolalpha)) 00635 { 00636 // Parse bool values as long. 00637 // NB: We can't just call do_get(long) here, as it might 00638 // refer to a derived class. 00639 long __l = -1; 00640 __beg = _M_extract_int(__beg, __end, __io, __err, __l); 00641 if (__l == 0 || __l == 1) 00642 __v = __l; 00643 else 00644 __err |= ios_base::failbit; 00645 } 00646 else 00647 { 00648 // Parse bool values as alphanumeric. 00649 typedef char_traits<_CharT> __traits_type; 00650 typedef typename numpunct<_CharT>::__cache_type __cache_type; 00651 __use_cache<__cache_type> __uc; 00652 const locale& __loc = __io._M_getloc(); 00653 const __cache_type* __lc = __uc(__loc); 00654 00655 bool __testf = true; 00656 bool __testt = true; 00657 size_t __n; 00658 for (__n = 0; __beg != __end; ++__n, ++__beg) 00659 { 00660 if (__testf) 00661 if (__n < __lc->_M_falsename_size) 00662 __testf = *__beg == __lc->_M_falsename[__n]; 00663 else 00664 break; 00665 00666 if (__testt) 00667 if (__n < __lc->_M_truename_size) 00668 __testt = *__beg == __lc->_M_truename[__n]; 00669 else 00670 break; 00671 00672 if (!__testf && !__testt) 00673 break; 00674 } 00675 if (__testf && __n == __lc->_M_falsename_size) 00676 __v = 0; 00677 else if (__testt && __n == __lc->_M_truename_size) 00678 __v = 1; 00679 else 00680 __err |= ios_base::failbit; 00681 00682 if (__beg == __end) 00683 __err |= ios_base::eofbit; 00684 } 00685 return __beg; 00686 } 00687 00688 template<typename _CharT, typename _InIter> 00689 _InIter 00690 num_get<_CharT, _InIter>:: 00691 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00692 ios_base::iostate& __err, long& __v) const 00693 { return _M_extract_int(__beg, __end, __io, __err, __v); } 00694 00695 template<typename _CharT, typename _InIter> 00696 _InIter 00697 num_get<_CharT, _InIter>:: 00698 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00699 ios_base::iostate& __err, unsigned short& __v) const 00700 { return _M_extract_int(__beg, __end, __io, __err, __v); } 00701 00702 template<typename _CharT, typename _InIter> 00703 _InIter 00704 num_get<_CharT, _InIter>:: 00705 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00706 ios_base::iostate& __err, unsigned int& __v) const 00707 { return _M_extract_int(__beg, __end, __io, __err, __v); } 00708 00709 template<typename _CharT, typename _InIter> 00710 _InIter 00711 num_get<_CharT, _InIter>:: 00712 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00713 ios_base::iostate& __err, unsigned long& __v) const 00714 { return _M_extract_int(__beg, __end, __io, __err, __v); } 00715 00716 #ifdef _GLIBCXX_USE_LONG_LONG 00717 template<typename _CharT, typename _InIter> 00718 _InIter 00719 num_get<_CharT, _InIter>:: 00720 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00721 ios_base::iostate& __err, long long& __v) const 00722 { return _M_extract_int(__beg, __end, __io, __err, __v); } 00723 00724 template<typename _CharT, typename _InIter> 00725 _InIter 00726 num_get<_CharT, _InIter>:: 00727 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00728 ios_base::iostate& __err, unsigned long long& __v) const 00729 { return _M_extract_int(__beg, __end, __io, __err, __v); } 00730 #endif 00731 00732 template<typename _CharT, typename _InIter> 00733 _InIter 00734 num_get<_CharT, _InIter>:: 00735 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00736 ios_base::iostate& __err, float& __v) const 00737 { 00738 string __xtrc; 00739 __xtrc.reserve(32); 00740 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 00741 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 00742 return __beg; 00743 } 00744 00745 template<typename _CharT, typename _InIter> 00746 _InIter 00747 num_get<_CharT, _InIter>:: 00748 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00749 ios_base::iostate& __err, double& __v) const 00750 { 00751 string __xtrc; 00752 __xtrc.reserve(32); 00753 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 00754 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 00755 return __beg; 00756 } 00757 00758 template<typename _CharT, typename _InIter> 00759 _InIter 00760 num_get<_CharT, _InIter>:: 00761 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00762 ios_base::iostate& __err, long double& __v) const 00763 { 00764 string __xtrc; 00765 __xtrc.reserve(32); 00766 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 00767 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 00768 return __beg; 00769 } 00770 00771 template<typename _CharT, typename _InIter> 00772 _InIter 00773 num_get<_CharT, _InIter>:: 00774 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00775 ios_base::iostate& __err, void*& __v) const 00776 { 00777 // Prepare for hex formatted input. 00778 typedef ios_base::fmtflags fmtflags; 00779 const fmtflags __fmt = __io.flags(); 00780 __io.flags(__fmt & ~ios_base::basefield | ios_base::hex); 00781 00782 unsigned long __ul; 00783 __beg = _M_extract_int(__beg, __end, __io, __err, __ul); 00784 00785 // Reset from hex formatted input. 00786 __io.flags(__fmt); 00787 00788 if (!(__err & ios_base::failbit)) 00789 __v = reinterpret_cast<void*>(__ul); 00790 else 00791 __err |= ios_base::failbit; 00792 return __beg; 00793 } 00794 00795 // For use by integer and floating-point types after they have been 00796 // converted into a char_type string. 00797 template<typename _CharT, typename _OutIter> 00798 void 00799 num_put<_CharT, _OutIter>:: 00800 _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 00801 _CharT* __new, const _CharT* __cs, int& __len) const 00802 { 00803 // [22.2.2.2.2] Stage 3. 00804 // If necessary, pad. 00805 __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs, 00806 __w, __len, true); 00807 __len = static_cast<int>(__w); 00808 } 00809 00810 // Forwarding functions to peel signed from unsigned integer types. 00811 template<typename _CharT> 00812 inline int 00813 __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit, 00814 ios_base::fmtflags __flags) 00815 { 00816 unsigned long __ul = static_cast<unsigned long>(__v); 00817 bool __neg = false; 00818 if (__v < 0) 00819 { 00820 __ul = -__ul; 00821 __neg = true; 00822 } 00823 return __int_to_char(__bufend, __ul, __lit, __flags, __neg); 00824 } 00825 00826 template<typename _CharT> 00827 inline int 00828 __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit, 00829 ios_base::fmtflags __flags) 00830 { 00831 // About showpos, see Table 60 and C99 7.19.6.1, p6 (+). 00832 return __int_to_char(__bufend, __v, __lit, 00833 __flags & ~ios_base::showpos, false); 00834 } 00835 00836 #ifdef _GLIBCXX_USE_LONG_LONG 00837 template<typename _CharT> 00838 inline int 00839 __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit, 00840 ios_base::fmtflags __flags) 00841 { 00842 unsigned long long __ull = static_cast<unsigned long long>(__v); 00843 bool __neg = false; 00844 if (__v < 0) 00845 { 00846 __ull = -__ull; 00847 __neg = true; 00848 } 00849 return __int_to_char(__bufend, __ull, __lit, __flags, __neg); 00850 } 00851 00852 template<typename _CharT> 00853 inline int 00854 __int_to_char(_CharT* __bufend, unsigned long long __v, 00855 const _CharT* __lit, ios_base::fmtflags __flags) 00856 { return __int_to_char(__bufend, __v, __lit, 00857 __flags & ~ios_base::showpos, false); } 00858 #endif 00859 00860 template<typename _CharT, typename _ValueT> 00861 int 00862 __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit, 00863 ios_base::fmtflags __flags, bool __neg) 00864 { 00865 // Don't write base if already 0. 00866 const bool __showbase = (__flags & ios_base::showbase) && __v; 00867 const ios_base::fmtflags __basefield = __flags & ios_base::basefield; 00868 _CharT* __buf = __bufend - 1; 00869 00870 if (__builtin_expect(__basefield != ios_base::oct && 00871 __basefield != ios_base::hex, true)) 00872 { 00873 // Decimal. 00874 do 00875 { 00876 *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits]; 00877 __v /= 10; 00878 } 00879 while (__v != 0); 00880 if (__neg) 00881 *__buf-- = __lit[__num_base::_S_ominus]; 00882 else if (__flags & ios_base::showpos) 00883 *__buf-- = __lit[__num_base::_S_oplus]; 00884 } 00885 else if (__basefield == ios_base::oct) 00886 { 00887 // Octal. 00888 do 00889 { 00890 *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits]; 00891 __v >>= 3; 00892 } 00893 while (__v != 0); 00894 if (__showbase) 00895 *__buf-- = __lit[__num_base::_S_odigits]; 00896 } 00897 else 00898 { 00899 // Hex. 00900 const bool __uppercase = __flags & ios_base::uppercase; 00901 const int __case_offset = __uppercase ? __num_base::_S_oudigits 00902 : __num_base::_S_odigits; 00903 do 00904 { 00905 *__buf-- = __lit[(__v & 0xf) + __case_offset]; 00906 __v >>= 4; 00907 } 00908 while (__v != 0); 00909 if (__showbase) 00910 { 00911 // 'x' or 'X' 00912 *__buf-- = __lit[__num_base::_S_ox + __uppercase]; 00913 // '0' 00914 *__buf-- = __lit[__num_base::_S_odigits]; 00915 } 00916 } 00917 return __bufend - __buf - 1; 00918 } 00919 00920 template<typename _CharT, typename _OutIter> 00921 void 00922 num_put<_CharT, _OutIter>:: 00923 _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep, 00924 ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const 00925 { 00926 // By itself __add_grouping cannot deal correctly with __cs when 00927 // ios::showbase is set and ios_base::oct || ios_base::hex. 00928 // Therefore we take care "by hand" of the initial 0, 0x or 0X. 00929 // However, remember that the latter do not occur if the number 00930 // printed is '0' (__len == 1). 00931 streamsize __off = 0; 00932 const ios_base::fmtflags __basefield = __io.flags() 00933 & ios_base::basefield; 00934 if ((__io.flags() & ios_base::showbase) && __len > 1) 00935 if (__basefield == ios_base::oct) 00936 { 00937 __off = 1; 00938 __new[0] = __cs[0]; 00939 } 00940 else if (__basefield == ios_base::hex) 00941 { 00942 __off = 2; 00943 __new[0] = __cs[0]; 00944 __new[1] = __cs[1]; 00945 } 00946 _CharT* __p; 00947 __p = std::__add_grouping(__new + __off, __sep, __grouping, 00948 __grouping_size, __cs + __off, 00949 __cs + __len); 00950 __len = __p - __new; 00951 } 00952 00953 template<typename _CharT, typename _OutIter> 00954 template<typename _ValueT> 00955 _OutIter 00956 num_put<_CharT, _OutIter>:: 00957 _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill, 00958 _ValueT __v) const 00959 { 00960 typedef typename numpunct<_CharT>::__cache_type __cache_type; 00961 __use_cache<__cache_type> __uc; 00962 const locale& __loc = __io._M_getloc(); 00963 const __cache_type* __lc = __uc(__loc); 00964 const _CharT* __lit = __lc->_M_atoms_out; 00965 00966 // Long enough to hold hex, dec, and octal representations. 00967 const int __ilen = 4 * sizeof(_ValueT); 00968 _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00969 * __ilen)); 00970 00971 // [22.2.2.2.2] Stage 1, numeric conversion to character. 00972 // Result is returned right-justified in the buffer. 00973 int __len; 00974 __len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags()); 00975 __cs += __ilen - __len; 00976 00977 // Add grouping, if necessary. 00978 if (__lc->_M_use_grouping) 00979 { 00980 // Grouping can add (almost) as many separators as the 00981 // number of digits, but no more. 00982 _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00983 * __len * 2)); 00984 _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size, 00985 __lc->_M_thousands_sep, __io, __cs2, __cs, __len); 00986 __cs = __cs2; 00987 } 00988 00989 // Pad. 00990 const streamsize __w = __io.width(); 00991 if (__w > static_cast<streamsize>(__len)) 00992 { 00993 _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00994 * __w)); 00995 _M_pad(__fill, __w, __io, __cs3, __cs, __len); 00996 __cs = __cs3; 00997 } 00998 __io.width(0); 00999 01000 // [22.2.2.2.2] Stage 4. 01001 // Write resulting, fully-formatted string to output iterator. 01002 return std::__write(__s, __cs, __len); 01003 } 01004 01005 template<typename _CharT, typename _OutIter> 01006 void 01007 num_put<_CharT, _OutIter>:: 01008 _M_group_float(const char* __grouping, size_t __grouping_size, 01009 _CharT __sep, const _CharT* __p, _CharT* __new, 01010 _CharT* __cs, int& __len) const 01011 { 01012 // _GLIBCXX_RESOLVE_LIB_DEFECTS 01013 // 282. What types does numpunct grouping refer to? 01014 // Add grouping, if necessary. 01015 _CharT* __p2; 01016 const int __declen = __p ? __p - __cs : __len; 01017 __p2 = std::__add_grouping(__new, __sep, __grouping, __grouping_size, 01018 __cs, __cs + __declen); 01019 01020 // Tack on decimal part. 01021 int __newlen = __p2 - __new; 01022 if (__p) 01023 { 01024 char_traits<_CharT>::copy(__p2, __p, __len - __declen); 01025 __newlen += __len - __declen; 01026 } 01027 __len = __newlen; 01028 } 01029 01030 // The following code uses snprintf (or sprintf(), when 01031 // _GLIBCXX_USE_C99 is not defined) to convert floating point values 01032 // for insertion into a stream. An optimization would be to replace 01033 // them with code that works directly on a wide buffer and then use 01034 // __pad to do the padding. It would be good to replace them anyway 01035 // to gain back the efficiency that C++ provides by knowing up front 01036 // the type of the values to insert. Also, sprintf is dangerous 01037 // since may lead to accidental buffer overruns. This 01038 // implementation follows the C++ standard fairly directly as 01039 // outlined in 22.2.2.2 [lib.locale.num.put] 01040 template<typename _CharT, typename _OutIter> 01041 template<typename _ValueT> 01042 _OutIter 01043 num_put<_CharT, _OutIter>:: 01044 _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 01045 _ValueT __v) const 01046 { 01047 typedef typename numpunct<_CharT>::__cache_type __cache_type; 01048 __use_cache<__cache_type> __uc; 01049 const locale& __loc = __io._M_getloc(); 01050 const __cache_type* __lc = __uc(__loc); 01051 01052 // Note: digits10 is rounded down: add 1 to ensure the maximum 01053 // available precision. Then, in general, one more 1 needs to 01054 // be added since, when the %{g,G} conversion specifiers are 01055 // chosen inside _S_format_float, the precision field is "the 01056 // maximum number of significant digits", *not* the "number of 01057 // digits to appear after the decimal point", as happens for 01058 // %{e,E,f,F} (C99, 7.19.6.1,4). 01059 const int __max_digits = numeric_limits<_ValueT>::digits10 + 2; 01060 01061 // Use default precision if out of range. 01062 streamsize __prec = __io.precision(); 01063 if (__prec > static_cast<streamsize>(__max_digits)) 01064 __prec = static_cast<streamsize>(__max_digits); 01065 else if (__prec < static_cast<streamsize>(0)) 01066 __prec = static_cast<streamsize>(6); 01067 01068 // [22.2.2.2.2] Stage 1, numeric conversion to character. 01069 int __len; 01070 // Long enough for the max format spec. 01071 char __fbuf[16]; 01072 01073 #ifdef _GLIBCXX_USE_C99 01074 // First try a buffer perhaps big enough (for sure sufficient 01075 // for non-ios_base::fixed outputs) 01076 int __cs_size = __max_digits * 3; 01077 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01078 01079 __num_base::_S_format_float(__io, __fbuf, __mod); 01080 __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v, 01081 _S_get_c_locale(), __prec); 01082 01083 // If the buffer was not large enough, try again with the correct size. 01084 if (__len >= __cs_size) 01085 { 01086 __cs_size = __len + 1; 01087 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01088 __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v, 01089 _S_get_c_locale(), __prec); 01090 } 01091 #else 01092 // Consider the possibility of long ios_base::fixed outputs 01093 const bool __fixed = __io.flags() & ios_base::fixed; 01094 const int __max_exp = numeric_limits<_ValueT>::max_exponent10; 01095 01096 // The size of the output string is computed as follows. 01097 // ios_base::fixed outputs may need up to __max_exp+1 chars 01098 // for the integer part + up to __max_digits chars for the 01099 // fractional part + 3 chars for sign, decimal point, '\0'. On 01100 // the other hand, for non-fixed outputs __max_digits*3 chars 01101 // are largely sufficient. 01102 const int __cs_size = __fixed ? __max_exp + __max_digits + 4 01103 : __max_digits * 3; 01104 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01105 01106 __num_base::_S_format_float(__io, __fbuf, __mod); 01107 __len = std::__convert_from_v(__cs, 0, __fbuf, __v, 01108 _S_get_c_locale(), __prec); 01109 #endif 01110 01111 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 01112 // numpunct.decimal_point() values for '.' and adding grouping. 01113 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01114 01115 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01116 * __len)); 01117 __ctype.widen(__cs, __cs + __len, __ws); 01118 01119 // Replace decimal point. 01120 const _CharT __cdec = __ctype.widen('.'); 01121 const _CharT __dec = __lc->_M_decimal_point; 01122 const _CharT* __p; 01123 if (__p = char_traits<_CharT>::find(__ws, __len, __cdec)) 01124 __ws[__p - __ws] = __dec; 01125 01126 // Add grouping, if necessary. 01127 if (__lc->_M_use_grouping) 01128 { 01129 // Grouping can add (almost) as many separators as the 01130 // number of digits, but no more. 01131 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01132 * __len * 2)); 01133 _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size, 01134 __lc->_M_thousands_sep, __p, __ws2, __ws, __len); 01135 __ws = __ws2; 01136 } 01137 01138 // Pad. 01139 const streamsize __w = __io.width(); 01140 if (__w > static_cast<streamsize>(__len)) 01141 { 01142 _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01143 * __w)); 01144 _M_pad(__fill, __w, __io, __ws3, __ws, __len); 01145 __ws = __ws3; 01146 } 01147 __io.width(0); 01148 01149 // [22.2.2.2.2] Stage 4. 01150 // Write resulting, fully-formatted string to output iterator. 01151 return std::__write(__s, __ws, __len); 01152 } 01153 01154 template<typename _CharT, typename _OutIter> 01155 _OutIter 01156 num_put<_CharT, _OutIter>:: 01157 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 01158 { 01159 const ios_base::fmtflags __flags = __io.flags(); 01160 if ((__flags & ios_base::boolalpha) == 0) 01161 { 01162 unsigned long __uv = __v; 01163 __s = _M_insert_int(__s, __io, __fill, __uv); 01164 } 01165 else 01166 { 01167 typedef typename numpunct<_CharT>::__cache_type __cache_type; 01168 __use_cache<__cache_type> __uc; 01169 const locale& __loc = __io._M_getloc(); 01170 const __cache_type* __lc = __uc(__loc); 01171 01172 const _CharT* __name = __v ? __lc->_M_truename 01173 : __lc->_M_falsename; 01174 int __len = __v ? __lc->_M_truename_size 01175 : __lc->_M_falsename_size; 01176 01177 const streamsize __w = __io.width(); 01178 if (__w > static_cast<streamsize>(__len)) 01179 { 01180 _CharT* __cs 01181 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01182 * __w)); 01183 _M_pad(__fill, __w, __io, __cs, __name, __len); 01184 __name = __cs; 01185 } 01186 __io.width(0); 01187 __s = std::__write(__s, __name, __len); 01188 } 01189 return __s; 01190 } 01191 01192 template<typename _CharT, typename _OutIter> 01193 _OutIter 01194 num_put<_CharT, _OutIter>:: 01195 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const 01196 { return _M_insert_int(__s, __io, __fill, __v); } 01197 01198 template<typename _CharT, typename _OutIter> 01199 _OutIter 01200 num_put<_CharT, _OutIter>:: 01201 do_put(iter_type __s, ios_base& __io, char_type __fill, 01202 unsigned long __v) const 01203 { return _M_insert_int(__s, __io, __fill, __v); } 01204 01205 #ifdef _GLIBCXX_USE_LONG_LONG 01206 template<typename _CharT, typename _OutIter> 01207 _OutIter 01208 num_put<_CharT, _OutIter>:: 01209 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const 01210 { return _M_insert_int(__s, __b, __fill, __v); } 01211 01212 template<typename _CharT, typename _OutIter> 01213 _OutIter 01214 num_put<_CharT, _OutIter>:: 01215 do_put(iter_type __s, ios_base& __io, char_type __fill, 01216 unsigned long long __v) const 01217 { return _M_insert_int(__s, __io, __fill, __v); } 01218 #endif 01219 01220 template<typename _CharT, typename _OutIter> 01221 _OutIter 01222 num_put<_CharT, _OutIter>:: 01223 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 01224 { return _M_insert_float(__s, __io, __fill, char(), __v); } 01225 01226 template<typename _CharT, typename _OutIter> 01227 _OutIter 01228 num_put<_CharT, _OutIter>:: 01229 do_put(iter_type __s, ios_base& __io, char_type __fill, 01230 long double __v) const 01231 { return _M_insert_float(__s, __io, __fill, 'L', __v); } 01232 01233 template<typename _CharT, typename _OutIter> 01234 _OutIter 01235 num_put<_CharT, _OutIter>:: 01236 do_put(iter_type __s, ios_base& __io, char_type __fill, 01237 const void* __v) const 01238 { 01239 const ios_base::fmtflags __flags = __io.flags(); 01240 const ios_base::fmtflags __fmt = ~(ios_base::showpos 01241 | ios_base::basefield 01242 | ios_base::uppercase 01243 | ios_base::internal); 01244 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase)); 01245 01246 __s = _M_insert_int(__s, __io, __fill, 01247 reinterpret_cast<unsigned long>(__v)); 01248 __io.flags(__flags); 01249 return __s; 01250 } 01251 01252 template<typename _CharT, typename _InIter> 01253 template<bool _Intl> 01254 _InIter 01255 money_get<_CharT, _InIter>:: 01256 _M_extract(iter_type __beg, iter_type __end, ios_base& __io, 01257 ios_base::iostate& __err, string& __units) const 01258 { 01259 typedef char_traits<_CharT> __traits_type; 01260 typedef typename string_type::size_type size_type; 01261 typedef money_base::part part; 01262 typedef moneypunct<_CharT, _Intl> __moneypunct_type; 01263 typedef typename __moneypunct_type::__cache_type __cache_type; 01264 01265 const locale& __loc = __io._M_getloc(); 01266 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01267 01268 __use_cache<__cache_type> __uc; 01269 const __cache_type* __lc = __uc(__loc); 01270 const char_type* __lit = __lc->_M_atoms; 01271 01272 // Deduced sign. 01273 bool __negative = false; 01274 // Sign size. 01275 size_type __sign_size = 0; 01276 // True if sign is mandatory. 01277 const bool __mandatory_sign = (__lc->_M_positive_sign_size 01278 && __lc->_M_negative_sign_size); 01279 // String of grouping info from thousands_sep plucked from __units. 01280 string __grouping_tmp; 01281 if (__lc->_M_use_grouping) 01282 __grouping_tmp.reserve(32); 01283 // Last position before the decimal point. 01284 int __last_pos = 0; 01285 // Separator positions, then, possibly, fractional digits. 01286 int __n = 0; 01287 // If input iterator is in a valid state. 01288 bool __testvalid = true; 01289 // Flag marking when a decimal point is found. 01290 bool __testdecfound = false; 01291 01292 // The tentative returned string is stored here. 01293 string __res; 01294 __res.reserve(32); 01295 01296 const char_type* __lit_zero = __lit + money_base::_S_zero; 01297 const char_type* __q; 01298 const money_base::pattern __p = __lc->_M_neg_format; 01299 for (int __i = 0; __i < 4 && __testvalid; ++__i) 01300 { 01301 const part __which = static_cast<part>(__p.field[__i]); 01302 switch (__which) 01303 { 01304 case money_base::symbol: 01305 // According to 22.2.6.1.2, p2, symbol is required 01306 // if (__io.flags() & ios_base::showbase), otherwise 01307 // is optional and consumed only if other characters 01308 // are needed to complete the format. 01309 if (__io.flags() & ios_base::showbase || __sign_size > 1 01310 || __i == 0 01311 || (__i == 1 && (__mandatory_sign 01312 || (static_cast<part>(__p.field[0]) 01313 == money_base::sign) 01314 || (static_cast<part>(__p.field[2]) 01315 == money_base::space))) 01316 || (__i == 2 && ((static_cast<part>(__p.field[3]) 01317 == money_base::value) 01318 || __mandatory_sign 01319 && (static_cast<part>(__p.field[3]) 01320 == money_base::sign)))) 01321 { 01322 const size_type __len = __lc->_M_curr_symbol_size; 01323 size_type __j = 0; 01324 for (; __beg != __end && __j < __len 01325 && *__beg == __lc->_M_curr_symbol[__j]; 01326 ++__beg, ++__j); 01327 if (__j != __len 01328 && (__j || __io.flags() & ios_base::showbase)) 01329 __testvalid = false; 01330 } 01331 break; 01332 case money_base::sign: 01333 // Sign might not exist, or be more than one character long. 01334 if (__lc->_M_positive_sign_size && __beg != __end 01335 && *__beg == __lc->_M_positive_sign[0]) 01336 { 01337 __sign_size = __lc->_M_positive_sign_size; 01338 ++__beg; 01339 } 01340 else if (__lc->_M_negative_sign_size && __beg != __end 01341 && *__beg == __lc->_M_negative_sign[0]) 01342 { 01343 __negative = true; 01344 __sign_size = __lc->_M_negative_sign_size; 01345 ++__beg; 01346 } 01347 else if (__lc->_M_positive_sign_size 01348 && !__lc->_M_negative_sign_size) 01349 // "... if no sign is detected, the result is given the sign 01350 // that corresponds to the source of the empty string" 01351 __negative = true; 01352 else if (__mandatory_sign) 01353 __testvalid = false; 01354 break; 01355 case money_base::value: 01356 // Extract digits, remove and stash away the 01357 // grouping of found thousands separators. 01358 for (; __beg != __end; ++__beg) 01359 if (__q = __traits_type::find(__lit_zero, 10, *__beg)) 01360 { 01361 __res += money_base::_S_atoms[__q - __lit]; 01362 ++__n; 01363 } 01364 else if (*__beg == __lc->_M_decimal_point && !__testdecfound) 01365 { 01366 __last_pos = __n; 01367 __n = 0; 01368 __testdecfound = true; 01369 } 01370 else if (__lc->_M_use_grouping 01371 && *__beg == __lc->_M_thousands_sep 01372 && !__testdecfound) 01373 { 01374 if (__n) 01375 { 01376 // Mark position for later analysis. 01377 __grouping_tmp += static_cast<char>(__n); 01378 __n = 0; 01379 } 01380 else 01381 { 01382 __testvalid = false; 01383 break; 01384 } 01385 } 01386 else 01387 break; 01388 if (__res.empty()) 01389 __testvalid = false; 01390 break; 01391 case money_base::space: 01392 // At least one space is required. 01393 if (__beg != __end && __ctype.is(ctype_base::space, *__beg)) 01394 ++__beg; 01395 else 01396 __testvalid = false; 01397 case money_base::none: 01398 // Only if not at the end of the pattern. 01399 if (__i != 3) 01400 for (; __beg != __end 01401 && __ctype.is(ctype_base::space, *__beg); ++__beg); 01402 break; 01403 } 01404 } 01405 01406 // Need to get the rest of the sign characters, if they exist. 01407 if (__sign_size > 1 && __testvalid) 01408 { 01409 const char_type* __sign = __negative ? __lc->_M_negative_sign 01410 : __lc->_M_positive_sign; 01411 size_type __i = 1; 01412 for (; __beg != __end && __i < __sign_size 01413 && *__beg == __sign[__i]; ++__beg, ++__i); 01414 01415 if (__i != __sign_size) 01416 __testvalid = false; 01417 } 01418 01419 if (__testvalid) 01420 { 01421 // Strip leading zeros. 01422 if (__res.size() > 1) 01423 { 01424 const size_type __first = __res.find_first_not_of('0'); 01425 const bool __only_zeros = __first == string::npos; 01426 if (__first) 01427 __res.erase(0, __only_zeros ? __res.size() - 1 : __first); 01428 } 01429 01430 // 22.2.6.1.2, p4 01431 if (__negative && __res[0] != '0') 01432 __res.insert(__res.begin(), '-'); 01433 01434 // Test for grouping fidelity. 01435 if (__grouping_tmp.size()) 01436 { 01437 // Add the ending grouping. 01438 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos 01439 : __n); 01440 if (!std::__verify_grouping(__lc->_M_grouping, 01441 __lc->_M_grouping_size, 01442 __grouping_tmp)) 01443 __testvalid = false; 01444 } 01445 01446 // Iff not enough digits were supplied after the decimal-point. 01447 if (__testdecfound && __lc->_M_frac_digits > 0 01448 && __n != __lc->_M_frac_digits) 01449 __testvalid = false; 01450 } 01451 01452 // Iff no more characters are available. 01453 if (__beg == __end) 01454 __err |= ios_base::eofbit; 01455 01456 // Iff valid sequence is not recognized. 01457 if (!__testvalid) 01458 __err |= ios_base::failbit; 01459 else 01460 __units.swap(__res); 01461 01462 return __beg; 01463 } 01464 01465 template<typename _CharT, typename _InIter> 01466 _InIter 01467 money_get<_CharT, _InIter>:: 01468 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 01469 ios_base::iostate& __err, long double& __units) const 01470 { 01471 string __str; 01472 if (__intl) 01473 __beg = _M_extract<true>(__beg, __end, __io, __err, __str); 01474 else 01475 __beg = _M_extract<false>(__beg, __end, __io, __err, __str); 01476 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale()); 01477 return __beg; 01478 } 01479 01480 template<typename _CharT, typename _InIter> 01481 _InIter 01482 money_get<_CharT, _InIter>:: 01483 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 01484 ios_base::iostate& __err, string_type& __units) const 01485 { 01486 typedef typename string::size_type size_type; 01487 01488 const locale& __loc = __io._M_getloc(); 01489 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01490 01491 string __str; 01492 const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io, 01493 __err, __str) 01494 : _M_extract<false>(__beg, __end, __io, 01495 __err, __str); 01496 const size_type __len = __str.size(); 01497 if (__len) 01498 { 01499 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01500 * __len)); 01501 __ctype.widen(__str.data(), __str.data() + __len, __ws); 01502 __units.assign(__ws, __len); 01503 } 01504 01505 return __ret; 01506 } 01507 01508 template<typename _CharT, typename _OutIter> 01509 template<bool _Intl> 01510 _OutIter 01511 money_put<_CharT, _OutIter>:: 01512 _M_insert(iter_type __s, ios_base& __io, char_type __fill, 01513 const string_type& __digits) const 01514 { 01515 typedef typename string_type::size_type size_type; 01516 typedef money_base::part part; 01517 typedef moneypunct<_CharT, _Intl> __moneypunct_type; 01518 typedef typename __moneypunct_type::__cache_type __cache_type; 01519 01520 const locale& __loc = __io._M_getloc(); 01521 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01522 01523 __use_cache<__cache_type> __uc; 01524 const __cache_type* __lc = __uc(__loc); 01525 const char_type* __lit = __lc->_M_atoms; 01526 01527 // Determine if negative or positive formats are to be used, and 01528 // discard leading negative_sign if it is present. 01529 const char_type* __beg = __digits.data(); 01530 01531 money_base::pattern __p; 01532 const char_type* __sign; 01533 size_type __sign_size; 01534 if (*__beg != __lit[money_base::_S_minus]) 01535 { 01536 __p = __lc->_M_pos_format; 01537 __sign = __lc->_M_positive_sign; 01538 __sign_size = __lc->_M_positive_sign_size; 01539 } 01540 else 01541 { 01542 __p = __lc->_M_neg_format; 01543 __sign = __lc->_M_negative_sign; 01544 __sign_size = __lc->_M_negative_sign_size; 01545 if (__digits.size()) 01546 ++__beg; 01547 } 01548 01549 // Look for valid numbers in the ctype facet within input digits. 01550 size_type __len = __ctype.scan_not(ctype_base::digit, __beg, 01551 __beg + __digits.size()) - __beg; 01552 if (__len) 01553 { 01554 // Assume valid input, and attempt to format. 01555 // Break down input numbers into base components, as follows: 01556 // final_value = grouped units + (decimal point) + (digits) 01557 string_type __value; 01558 __value.reserve(2 * __len); 01559 01560 // Add thousands separators to non-decimal digits, per 01561 // grouping rules. 01562 int __paddec = __len - __lc->_M_frac_digits; 01563 if (__paddec > 0) 01564 { 01565 if (__lc->_M_frac_digits < 0) 01566 __paddec = __len; 01567 if (__lc->_M_grouping_size) 01568 { 01569 _CharT* __ws = 01570 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01571 * 2 * __len)); 01572 _CharT* __ws_end = 01573 std::__add_grouping(__ws, __lc->_M_thousands_sep, 01574 __lc->_M_grouping, 01575 __lc->_M_grouping_size, 01576 __beg, __beg + __paddec); 01577 __value.assign(__ws, __ws_end - __ws); 01578 } 01579 else 01580 __value.assign(__beg, __paddec); 01581 } 01582 01583 // Deal with decimal point, decimal digits. 01584 if (__lc->_M_frac_digits > 0) 01585 { 01586 __value += __lc->_M_decimal_point; 01587 if (__paddec >= 0) 01588 __value.append(__beg + __paddec, __lc->_M_frac_digits); 01589 else 01590 { 01591 // Have to pad zeros in the decimal position. 01592 __value.append(-__paddec, __lit[money_base::_S_zero]); 01593 __value.append(__beg, __len); 01594 } 01595 } 01596 01597 // Calculate length of resulting string. 01598 const ios_base::fmtflags __f = __io.flags() 01599 & ios_base::adjustfield; 01600 __len = __value.size() + __sign_size; 01601 __len += ((__io.flags() & ios_base::showbase) 01602 ? __lc->_M_curr_symbol_size : 0); 01603 01604 string_type __res; 01605 __res.reserve(2 * __len); 01606 01607 const size_type __width = static_cast<size_type>(__io.width()); 01608 const bool __testipad = (__f == ios_base::internal 01609 && __len < __width); 01610 // Fit formatted digits into the required pattern. 01611 for (int __i = 0; __i < 4; ++__i) 01612 { 01613 const part __which = static_cast<part>(__p.field[__i]); 01614 switch (__which) 01615 { 01616 case money_base::symbol: 01617 if (__io.flags() & ios_base::showbase) 01618 __res.append(__lc->_M_curr_symbol, 01619 __lc->_M_curr_symbol_size); 01620 break; 01621 case money_base::sign: 01622 // Sign might not exist, or be more than one 01623 // charater long. In that case, add in the rest 01624 // below. 01625 if (__sign_size) 01626 __res += __sign[0]; 01627 break; 01628 case money_base::value: 01629 __res += __value; 01630 break; 01631 case money_base::space: 01632 // At least one space is required, but if internal 01633 // formatting is required, an arbitrary number of 01634 // fill spaces will be necessary. 01635 if (__testipad) 01636 __res.append(__width - __len, __fill); 01637 else 01638 __res += __fill; 01639 break; 01640 case money_base::none: 01641 if (__testipad) 01642 __res.append(__width - __len, __fill); 01643 break; 01644 } 01645 } 01646 01647 // Special case of multi-part sign parts. 01648 if (__sign_size > 1) 01649 __res.append(__sign + 1, __sign_size - 1); 01650 01651 // Pad, if still necessary. 01652 __len = __res.size(); 01653 if (__width > __len) 01654 { 01655 if (__f == ios_base::left) 01656 // After. 01657 __res.append(__width - __len, __fill); 01658 else 01659 // Before. 01660 __res.insert(0, __width - __len, __fill); 01661 __len = __width; 01662 } 01663 01664 // Write resulting, fully-formatted string to output iterator. 01665 __s = std::__write(__s, __res.data(), __len); 01666 } 01667 __io.width(0); 01668 return __s; 01669 } 01670 01671 template<typename _CharT, typename _OutIter> 01672 _OutIter 01673 money_put<_CharT, _OutIter>:: 01674 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 01675 long double __units) const 01676 { 01677 const locale __loc = __io.getloc(); 01678 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01679 #ifdef _GLIBCXX_USE_C99 01680 // First try a buffer perhaps big enough. 01681 int __cs_size = 64; 01682 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01683 // _GLIBCXX_RESOLVE_LIB_DEFECTS 01684 // 328. Bad sprintf format modifier in money_put<>::do_put() 01685 int __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units, 01686 _S_get_c_locale()); 01687 // If the buffer was not large enough, try again with the correct size. 01688 if (__len >= __cs_size) 01689 { 01690 __cs_size = __len + 1; 01691 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01692 __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units, 01693 _S_get_c_locale()); 01694 } 01695 #else 01696 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'. 01697 const int __cs_size = numeric_limits<long double>::max_exponent10 + 3; 01698 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01699 int __len = std::__convert_from_v(__cs, 0, "%.0Lf", __units, 01700 _S_get_c_locale()); 01701 #endif 01702 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01703 * __cs_size)); 01704 __ctype.widen(__cs, __cs + __len, __ws); 01705 const string_type __digits(__ws, __len); 01706 return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 01707 : _M_insert<false>(__s, __io, __fill, __digits); 01708 } 01709 01710 template<typename _CharT, typename _OutIter> 01711 _OutIter 01712 money_put<_CharT, _OutIter>:: 01713 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill, 01714 const string_type& __digits) const 01715 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits) 01716 : _M_insert<false>(__s, __io, __fill, __digits); } 01717 01718 01719 // NB: Not especially useful. Without an ios_base object or some 01720 // kind of locale reference, we are left clawing at the air where 01721 // the side of the mountain used to be... 01722 template<typename _CharT, typename _InIter> 01723 time_base::dateorder 01724 time_get<_CharT, _InIter>::do_date_order() const 01725 { return time_base::no_order; } 01726 01727 // Recursively expand a strftime format string and parse it. Starts w/ %x 01728 // and %X from do_get_time() and do_get_date(), which translate to a more 01729 // specific string, which may contain yet more strings. I.e. %x => %r => 01730 // %H:%M:%S => extracted characters. 01731 template<typename _CharT, typename _InIter> 01732 _InIter 01733 time_get<_CharT, _InIter>:: 01734 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io, 01735 ios_base::iostate& __err, tm* __tm, 01736 const _CharT* __format) const 01737 { 01738 const locale& __loc = __io._M_getloc(); 01739 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 01740 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01741 const size_t __len = char_traits<_CharT>::length(__format); 01742 01743 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i) 01744 { 01745 if (__ctype.narrow(__format[__i], 0) == '%') 01746 { 01747 // Verify valid formatting code, attempt to extract. 01748 char __c = __ctype.narrow(__format[++__i], 0); 01749 int __mem = 0; 01750 if (__c == 'E' || __c == 'O') 01751 __c = __ctype.narrow(__format[++__i], 0); 01752 switch (__c) 01753 { 01754 const char* __cs; 01755 _CharT __wcs[10]; 01756 case 'a': 01757 // Abbreviated weekday name [tm_wday] 01758 const char_type* __days1[7]; 01759 __tp._M_days_abbreviated(__days1); 01760 __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 01761 7, __io, __err); 01762 break; 01763 case 'A': 01764 // Weekday name [tm_wday]. 01765 const char_type* __days2[7]; 01766 __tp._M_days(__days2); 01767 __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 01768 7, __io, __err); 01769 break; 01770 case 'h': 01771 case 'b': 01772 // Abbreviated month name [tm_mon] 01773 const char_type* __months1[12]; 01774 __tp._M_months_abbreviated(__months1); 01775 __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 01776 __months1, 12, __io, __err); 01777 break; 01778 case 'B': 01779 // Month name [tm_mon]. 01780 const char_type* __months2[12]; 01781 __tp._M_months(__months2); 01782 __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 01783 __months2, 12, __io, __err); 01784 break; 01785 case 'c': 01786 // Default time and date representation. 01787 const char_type* __dt[2]; 01788 __tp._M_date_time_formats(__dt); 01789 __beg = _M_extract_via_format(__beg, __end, __io, __err, 01790 __tm, __dt[0]); 01791 break; 01792 case 'd': 01793 // Day [01, 31]. [tm_mday] 01794 __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 01795 __io, __err); 01796 break; 01797 case 'e': 01798 // Day [1, 31], with single digits preceded by 01799 // space. [tm_mday] 01800 if (__ctype.is(ctype_base::space, *__beg)) 01801 __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9, 01802 1, __io, __err); 01803 else 01804 __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31, 01805 2, __io, __err); 01806 break; 01807 case 'D': 01808 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] 01809 __cs = "%m/%d/%y"; 01810 __ctype.widen(__cs, __cs + 9, __wcs); 01811 __beg = _M_extract_via_format(__beg, __end, __io, __err, 01812 __tm, __wcs); 01813 break; 01814 case 'H': 01815 // Hour [00, 23]. [tm_hour] 01816 __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, 01817 __io, __err); 01818 break; 01819 case 'I': 01820 // Hour [01, 12]. [tm_hour] 01821 __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 01822 __io, __err); 01823 break; 01824 case 'm': 01825 // Month [01, 12]. [tm_mon] 01826 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 01827 __io, __err); 01828 if (!__err) 01829 __tm->tm_mon = __mem - 1; 01830 break; 01831 case 'M': 01832 // Minute [00, 59]. [tm_min] 01833 __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, 01834 __io, __err); 01835 break; 01836 case 'n': 01837 if (__ctype.narrow(*__beg, 0) == '\n') 01838 ++__beg; 01839 else 01840 __err |= ios_base::failbit; 01841 break; 01842 case 'R': 01843 // Equivalent to (%H:%M). 01844 __cs = "%H:%M"; 01845 __ctype.widen(__cs, __cs + 6, __wcs); 01846 __beg = _M_extract_via_format(__beg, __end, __io, __err, 01847 __tm, __wcs); 01848 break; 01849 case 'S': 01850 // Seconds. 01851 __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2, 01852 __io, __err); 01853 break; 01854 case 't': 01855 if (__ctype.narrow(*__beg, 0) == '\t') 01856 ++__beg; 01857 else 01858 __err |= ios_base::failbit; 01859 break; 01860 case 'T': 01861 // Equivalent to (%H:%M:%S). 01862 __cs = "%H:%M:%S"; 01863 __ctype.widen(__cs, __cs + 9, __wcs); 01864 __beg = _M_extract_via_format(__beg, __end, __io, __err, 01865 __tm, __wcs); 01866 break; 01867 case 'x': 01868 // Locale's date. 01869 const char_type* __dates[2]; 01870 __tp._M_date_formats(__dates); 01871 __beg = _M_extract_via_format(__beg, __end, __io, __err, 01872 __tm, __dates[0]); 01873 break; 01874 case 'X': 01875 // Locale's time. 01876 const char_type* __times[2]; 01877 __tp._M_time_formats(__times); 01878 __beg = _M_extract_via_format(__beg, __end, __io, __err, 01879 __tm, __times[0]); 01880 break; 01881 case 'y': 01882 case 'C': // C99 01883 // Two digit year. [tm_year] 01884 __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 01885 __io, __err); 01886 break; 01887 case 'Y': 01888 // Year [1900). [tm_year] 01889 __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4, 01890 __io, __err); 01891 if (!__err) 01892 __tm->tm_year = __mem - 1900; 01893 break; 01894 case 'Z': 01895 // Timezone info. 01896 if (__ctype.is(ctype_base::upper, *__beg)) 01897 { 01898 int __tmp; 01899 __beg = _M_extract_name(__beg, __end, __tmp, 01900 __timepunct_cache<_CharT>::_S_timezones, 01901 14, __io, __err); 01902 01903 // GMT requires special effort. 01904 if (__beg != __end && !__err && __tmp == 0 01905 && (*__beg == __ctype.widen('-') 01906 || *__beg == __ctype.widen('+'))) 01907 { 01908 __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2, 01909 __io, __err); 01910 __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2, 01911 __io, __err); 01912 } 01913 } 01914 else 01915 __err |= ios_base::failbit; 01916 break; 01917 default: 01918 // Not recognized. 01919 __err |= ios_base::failbit; 01920 } 01921 } 01922 else 01923 { 01924 // Verify format and input match, extract and discard. 01925 if (__format[__i] == *__beg) 01926 ++__beg; 01927 else 01928 __err |= ios_base::failbit; 01929 } 01930 } 01931 return __beg; 01932 } 01933 01934 template<typename _CharT, typename _InIter> 01935 _InIter 01936 time_get<_CharT, _InIter>:: 01937 _M_extract_num(iter_type __beg, iter_type __end, int& __member, 01938 int __min, int __max, size_t __len, 01939 ios_base& __io, ios_base::iostate& __err) const 01940 { 01941 const locale& __loc = __io._M_getloc(); 01942 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01943 01944 // As-is works for __len = 1, 2, 4, the values actually used. 01945 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1); 01946 01947 ++__min; 01948 size_t __i = 0; 01949 int __value = 0; 01950 for (; __beg != __end && __i < __len; ++__beg, ++__i) 01951 { 01952 const char __c = __ctype.narrow(*__beg, '*'); 01953 if (__c >= '0' && __c <= '9') 01954 { 01955 __value = __value * 10 + (__c - '0'); 01956 const int __valuec = __value * __mult; 01957 if (__valuec > __max || __valuec + __mult < __min) 01958 break; 01959 __mult /= 10; 01960 } 01961 else 01962 break; 01963 } 01964 if (__i == __len) 01965 __member = __value; 01966 else 01967 __err |= ios_base::failbit; 01968 return __beg; 01969 } 01970 01971 // Assumptions: 01972 // All elements in __names are unique. 01973 template<typename _CharT, typename _InIter> 01974 _InIter 01975 time_get<_CharT, _InIter>:: 01976 _M_extract_name(iter_type __beg, iter_type __end, int& __member, 01977 const _CharT** __names, size_t __indexlen, 01978 ios_base& __io, ios_base::iostate& __err) const 01979 { 01980 typedef char_traits<_CharT> __traits_type; 01981 const locale& __loc = __io._M_getloc(); 01982 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01983 01984 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) 01985 * __indexlen)); 01986 size_t __nmatches = 0; 01987 size_t __pos = 0; 01988 bool __testvalid = true; 01989 const char_type* __name; 01990 01991 // Look for initial matches. 01992 // NB: Some of the locale data is in the form of all lowercase 01993 // names, and some is in the form of initially-capitalized 01994 // names. Look for both. 01995 if (__beg != __end) 01996 { 01997 const char_type __c = *__beg; 01998 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1) 01999 if (__c == __names[__i1][0] 02000 || __c == __ctype.toupper(__names[__i1][0])) 02001 __matches[__nmatches++] = __i1; 02002 } 02003 02004 while (__nmatches > 1) 02005 { 02006 // Find smallest matching string. 02007 size_t __minlen = 10; 02008 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2) 02009 __minlen = std::min(__minlen, 02010 __traits_type::length(__names[__matches[__i2]])); 02011 ++__beg; 02012 if (__pos < __minlen && __beg != __end) 02013 { 02014 ++__pos; 02015 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3) 02016 { 02017 __name = __names[__matches[__i3]]; 02018 if (__name[__pos] != *__beg) 02019 __matches[__i3] = __matches[--__nmatches]; 02020 } 02021 } 02022 else 02023 break; 02024 } 02025 02026 if (__nmatches == 1) 02027 { 02028 // If there was only one match, the first compare is redundant. 02029 if (__pos == 0) 02030 { 02031 ++__pos; 02032 ++__beg; 02033 } 02034 02035 // Make sure found name is completely extracted. 02036 __name = __names[__matches[0]]; 02037 const size_t __len = __traits_type::length(__name); 02038 while (__pos < __len && __beg != __end && __name[__pos] == *__beg) 02039 ++__beg, ++__pos; 02040 02041 if (__len == __pos) 02042 __member = __matches[0]; 02043 else 02044 __testvalid = false; 02045 } 02046 else 02047 __testvalid = false; 02048 if (!__testvalid) 02049 __err |= ios_base::failbit; 02050 return __beg; 02051 } 02052 02053 template<typename _CharT, typename _InIter> 02054 _InIter 02055 time_get<_CharT, _InIter>:: 02056 do_get_time(iter_type __beg, iter_type __end, ios_base& __io, 02057 ios_base::iostate& __err, tm* __tm) const 02058 { 02059 _CharT __wcs[3]; 02060 const char* __cs = "%X"; 02061 const locale& __loc = __io._M_getloc(); 02062 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 02063 __ctype.widen(__cs, __cs + 3, __wcs); 02064 __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 02065 if (__beg == __end) 02066 __err |= ios_base::eofbit; 02067 return __beg; 02068 } 02069 02070 template<typename _CharT, typename _InIter> 02071 _InIter 02072 time_get<_CharT, _InIter>:: 02073 do_get_date(iter_type __beg, iter_type __end, ios_base& __io, 02074 ios_base::iostate& __err, tm* __tm) const 02075 { 02076 _CharT __wcs[3]; 02077 const char* __cs = "%x"; 02078 const locale& __loc = __io._M_getloc(); 02079 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 02080 __ctype.widen(__cs, __cs + 3, __wcs); 02081 __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs); 02082 if (__beg == __end) 02083 __err |= ios_base::eofbit; 02084 return __beg; 02085 } 02086 02087 template<typename _CharT, typename _InIter> 02088 _InIter 02089 time_get<_CharT, _InIter>:: 02090 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 02091 ios_base::iostate& __err, tm* __tm) const 02092 { 02093 typedef char_traits<_CharT> __traits_type; 02094 const locale& __loc = __io._M_getloc(); 02095 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 02096 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 02097 const char_type* __days[7]; 02098 __tp._M_days_abbreviated(__days); 02099 int __tmpwday; 02100 __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, __io, __err); 02101 02102 // Check to see if non-abbreviated name exists, and extract. 02103 // NB: Assumes both _M_days and _M_days_abbreviated organized in 02104 // exact same order, first to last, such that the resulting 02105 // __days array with the same index points to a day, and that 02106 // day's abbreviated form. 02107 // NB: Also assumes that an abbreviated name is a subset of the name. 02108 if (!__err) 02109 { 02110 size_t __pos = __traits_type::length(__days[__tmpwday]); 02111 __tp._M_days(__days); 02112 const char_type* __name = __days[__tmpwday]; 02113 if (__name[__pos] == *__beg) 02114 { 02115 // Extract the rest of it. 02116 const size_t __len = __traits_type::length(__name); 02117 while (__pos < __len && __beg != __end 02118 && __name[__pos] == *__beg) 02119 ++__beg, ++__pos; 02120 if (__len != __pos) 02121 __err |= ios_base::failbit; 02122 } 02123 if (!__err) 02124 __tm->tm_wday = __tmpwday; 02125 } 02126 if (__beg == __end) 02127 __err |= ios_base::eofbit; 02128 return __beg; 02129 } 02130 02131 template<typename _CharT, typename _InIter> 02132 _InIter 02133 time_get<_CharT, _InIter>:: 02134 do_get_monthname(iter_type __beg, iter_type __end, 02135 ios_base& __io, ios_base::iostate& __err, tm* __tm) const 02136 { 02137 typedef char_traits<_CharT> __traits_type; 02138 const locale& __loc = __io._M_getloc(); 02139 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc); 02140 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 02141 const char_type* __months[12]; 02142 __tp._M_months_abbreviated(__months); 02143 int __tmpmon; 02144 __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 02145 __io, __err); 02146 02147 // Check to see if non-abbreviated name exists, and extract. 02148 // NB: Assumes both _M_months and _M_months_abbreviated organized in 02149 // exact same order, first to last, such that the resulting 02150 // __months array with the same index points to a month, and that 02151 // month's abbreviated form. 02152 // NB: Also assumes that an abbreviated name is a subset of the name. 02153 if (!__err) 02154 { 02155 size_t __pos = __traits_type::length(__months[__tmpmon]); 02156 __tp._M_months(__months); 02157 const char_type* __name = __months[__tmpmon]; 02158 if (__name[__pos] == *__beg) 02159 { 02160 // Extract the rest of it. 02161 const size_t __len = __traits_type::length(__name); 02162 while (__pos < __len && __beg != __end 02163 && __name[__pos] == *__beg) 02164 ++__beg, ++__pos; 02165 if (__len != __pos) 02166 __err |= ios_base::failbit; 02167 } 02168 if (!__err) 02169 __tm->tm_mon = __tmpmon; 02170 } 02171 02172 if (__beg == __end) 02173 __err |= ios_base::eofbit; 02174 return __beg; 02175 } 02176 02177 template<typename _CharT, typename _InIter> 02178 _InIter 02179 time_get<_CharT, _InIter>:: 02180 do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 02181 ios_base::iostate& __err, tm* __tm) const 02182 { 02183 const locale& __loc = __io._M_getloc(); 02184 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 02185 02186 size_t __i = 0; 02187 int __value = 0; 02188 for (; __beg != __end && __i < 4; ++__beg, ++__i) 02189 { 02190 const char __c = __ctype.narrow(*__beg, '*'); 02191 if (__c >= '0' && __c <= '9') 02192 __value = __value * 10 + (__c - '0'); 02193 else 02194 break; 02195 } 02196 if (__i == 2 || __i == 4) 02197 __tm->tm_year = __i == 2 ? __value : __value - 1900; 02198 else 02199 __err |= ios_base::failbit; 02200 if (__beg == __end) 02201 __err |= ios_base::eofbit; 02202 return __beg; 02203 } 02204 02205 template<typename _CharT, typename _OutIter> 02206 _OutIter 02207 time_put<_CharT, _OutIter>:: 02208 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm, 02209 const _CharT* __beg, const _CharT* __end) const 02210 { 02211 const locale& __loc = __io._M_getloc(); 02212 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 02213 for (; __beg != __end; ++__beg) 02214 if (__ctype.narrow(*__beg, 0) != '%') 02215 { 02216 *__s = *__beg; 02217 ++__s; 02218 } 02219 else if (++__beg != __end) 02220 { 02221 char __format; 02222 char __mod = 0; 02223 const char __c = __ctype.narrow(*__beg, 0); 02224 if (__c != 'E' && __c != 'O') 02225 __format = __c; 02226 else if (++__beg != __end) 02227 { 02228 __mod = __c; 02229 __format = __ctype.narrow(*__beg, 0); 02230 } 02231 else 02232 break; 02233 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod); 02234 } 02235 else 02236 break; 02237 return __s; 02238 } 02239 02240 template<typename _CharT, typename _OutIter> 02241 _OutIter 02242 time_put<_CharT, _OutIter>:: 02243 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 02244 char __format, char __mod) const 02245 { 02246 const locale& __loc = __io._M_getloc(); 02247 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc); 02248 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc); 02249 02250 // NB: This size is arbitrary. Should this be a data member, 02251 // initialized at construction? 02252 const size_t __maxlen = 64; 02253 char_type* __res = 02254 static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen)); 02255 02256 // NB: In IEE 1003.1-200x, and perhaps other locale models, it 02257 // is possible that the format character will be longer than one 02258 // character. Possibilities include 'E' or 'O' followed by a 02259 // format character: if __mod is not the default argument, assume 02260 // it's a valid modifier. 02261 char_type __fmt[4]; 02262 __fmt[0] = __ctype.widen('%'); 02263 if (!__mod) 02264 { 02265 __fmt[1] = __format; 02266 __fmt[2] = char_type(); 02267 } 02268 else 02269 { 02270 __fmt[1] = __mod; 02271 __fmt[2] = __format; 02272 __fmt[3] = char_type(); 02273 } 02274 02275 __tp._M_put(__res, __maxlen, __fmt, __tm); 02276 02277 // Write resulting, fully-formatted string to output iterator. 02278 return std::__write(__s, __res, char_traits<char_type>::length(__res)); 02279 } 02280 02281 02282 // Generic version does nothing. 02283 template<typename _CharT> 02284 int 02285 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const 02286 { return 0; } 02287 02288 // Generic version does nothing. 02289 template<typename _CharT> 02290 size_t 02291 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const 02292 { return 0; } 02293 02294 template<typename _CharT> 02295 int 02296 collate<_CharT>:: 02297 do_compare(const _CharT* __lo1, const _CharT* __hi1, 02298 const _CharT* __lo2, const _CharT* __hi2) const 02299 { 02300 // strcoll assumes zero-terminated strings so we make a copy 02301 // and then put a zero at the end. 02302 const string_type __one(__lo1, __hi1); 02303 const string_type __two(__lo2, __hi2); 02304 02305 const _CharT* __p = __one.c_str(); 02306 const _CharT* __pend = __one.data() + __one.length(); 02307 const _CharT* __q = __two.c_str(); 02308 const _CharT* __qend = __two.data() + __two.length(); 02309 02310 // strcoll stops when it sees a nul character so we break 02311 // the strings into zero-terminated substrings and pass those 02312 // to strcoll. 02313 for (;;) 02314 { 02315 const int __res = _M_compare(__p, __q); 02316 if (__res) 02317 return __res; 02318 02319 __p += char_traits<_CharT>::length(__p); 02320 __q += char_traits<_CharT>::length(__q); 02321 if (__p == __pend && __q == __qend) 02322 return 0; 02323 else if (__p == __pend) 02324 return -1; 02325 else if (__q == __qend) 02326 return 1; 02327 02328 __p++; 02329 __q++; 02330 } 02331 } 02332 02333 template<typename _CharT> 02334 typename collate<_CharT>::string_type 02335 collate<_CharT>:: 02336 do_transform(const _CharT* __lo, const _CharT* __hi) const 02337 { 02338 // strxfrm assumes zero-terminated strings so we make a copy 02339 string_type __str(__lo, __hi); 02340 02341 const _CharT* __p = __str.c_str(); 02342 const _CharT* __pend = __str.data() + __str.length(); 02343 02344 size_t __len = (__hi - __lo) * 2; 02345 02346 string_type __ret; 02347 02348 // strxfrm stops when it sees a nul character so we break 02349 // the string into zero-terminated substrings and pass those 02350 // to strxfrm. 02351 for (;;) 02352 { 02353 // First try a buffer perhaps big enough. 02354 _CharT* __c = 02355 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len)); 02356 size_t __res = _M_transform(__c, __p, __len); 02357 // If the buffer was not large enough, try again with the 02358 // correct size. 02359 if (__res >= __len) 02360 { 02361 __len = __res + 1; 02362 __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 02363 * __len)); 02364 __res = _M_transform(__c, __p, __res + 1); 02365 } 02366 02367 __ret.append(__c, __res); 02368 __p += char_traits<_CharT>::length(__p); 02369 if (__p == __pend) 02370 return __ret; 02371 02372 __p++; 02373 __ret.push_back(_CharT()); 02374 } 02375 } 02376 02377 template<typename _CharT> 02378 long 02379 collate<_CharT>:: 02380 do_hash(const _CharT* __lo, const _CharT* __hi) const 02381 { 02382 unsigned long __val = 0; 02383 for (; __lo < __hi; ++__lo) 02384 __val = *__lo + ((__val << 7) | 02385 (__val >> (numeric_limits<unsigned long>::digits - 7))); 02386 return static_cast<long>(__val); 02387 } 02388 02389 // Construct correctly padded string, as per 22.2.2.2.2 02390 // Assumes 02391 // __newlen > __oldlen 02392 // __news is allocated for __newlen size 02393 // Used by both num_put and ostream inserters: if __num, 02394 // internal-adjusted objects are padded according to the rules below 02395 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted 02396 // ones are. 02397 02398 // NB: Of the two parameters, _CharT can be deduced from the 02399 // function arguments. The other (_Traits) has to be explicitly specified. 02400 template<typename _CharT, typename _Traits> 02401 void 02402 __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 02403 _CharT* __news, const _CharT* __olds, 02404 const streamsize __newlen, 02405 const streamsize __oldlen, const bool __num) 02406 { 02407 const size_t __plen = static_cast<size_t>(__newlen - __oldlen); 02408 const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 02409 02410 // Padding last. 02411 if (__adjust == ios_base::left) 02412 { 02413 _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen); 02414 _Traits::assign(__news + __oldlen, __plen, __fill); 02415 return; 02416 } 02417 02418 size_t __mod = 0; 02419 if (__adjust == ios_base::internal && __num) 02420 { 02421 // Pad after the sign, if there is one. 02422 // Pad after 0[xX], if there is one. 02423 // Who came up with these rules, anyway? Jeeze. 02424 const locale& __loc = __io._M_getloc(); 02425 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 02426 02427 const bool __testsign = (__ctype.widen('-') == __olds[0] 02428 || __ctype.widen('+') == __olds[0]); 02429 const bool __testhex = (__ctype.widen('0') == __olds[0] 02430 && __oldlen > 1 02431 && (__ctype.widen('x') == __olds[1] 02432 || __ctype.widen('X') == __olds[1])); 02433 if (__testhex) 02434 { 02435 __news[0] = __olds[0]; 02436 __news[1] = __olds[1]; 02437 __mod = 2; 02438 __news += 2; 02439 } 02440 else if (__testsign) 02441 { 02442 __news[0] = __olds[0]; 02443 __mod = 1; 02444 ++__news; 02445 } 02446 // else Padding first. 02447 } 02448 _Traits::assign(__news, __plen, __fill); 02449 _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod), 02450 __oldlen - __mod); 02451 } 02452 02453 bool 02454 __verify_grouping(const char* __grouping, size_t __grouping_size, 02455 const string& __grouping_tmp) 02456 { 02457 const size_t __n = __grouping_tmp.size() - 1; 02458 const size_t __min = std::min(__n, __grouping_size - 1); 02459 size_t __i = __n; 02460 bool __test = true; 02461 02462 // Parsed number groupings have to match the 02463 // numpunct::grouping string exactly, starting at the 02464 // right-most point of the parsed sequence of elements ... 02465 for (size_t __j = 0; __j < __min && __test; --__i, ++__j) 02466 __test = __grouping_tmp[__i] == __grouping[__j]; 02467 for (; __i && __test; --__i) 02468 __test = __grouping_tmp[__i] == __grouping[__min]; 02469 // ... but the last parsed grouping can be <= numpunct 02470 // grouping. 02471 __test &= __grouping_tmp[0] <= __grouping[__min]; 02472 return __test; 02473 } 02474 02475 template<typename _CharT> 02476 _CharT* 02477 __add_grouping(_CharT* __s, _CharT __sep, 02478 const char* __gbeg, size_t __gsize, 02479 const _CharT* __first, const _CharT* __last) 02480 { 02481 if (__last - __first > *__gbeg) 02482 { 02483 const bool __bump = __gsize != 1; 02484 __s = std::__add_grouping(__s, __sep, __gbeg + __bump, 02485 __gsize - __bump, __first, 02486 __last - *__gbeg); 02487 __first = __last - *__gbeg; 02488 *__s++ = __sep; 02489 } 02490 do 02491 *__s++ = *__first++; 02492 while (__first != __last); 02493 return __s; 02494 } 02495 02496 // Inhibit implicit instantiations for required instantiations, 02497 // which are defined via explicit instantiations elsewhere. 02498 // NB: This syntax is a GNU extension. 02499 #if _GLIBCXX_EXTERN_TEMPLATE 02500 extern template class moneypunct<char, false>; 02501 extern template class moneypunct<char, true>; 02502 extern template class moneypunct_byname<char, false>; 02503 extern template class moneypunct_byname<char, true>; 02504 extern template class money_get<char>; 02505 extern template class money_put<char>; 02506 extern template class numpunct<char>; 02507 extern template class numpunct_byname<char>; 02508 extern template class num_get<char>; 02509 extern template class num_put<char>; 02510 extern template class __timepunct<char>; 02511 extern template class time_put<char>; 02512 extern template class time_put_byname<char>; 02513 extern template class time_get<char>; 02514 extern template class time_get_byname<char>; 02515 extern template class messages<char>; 02516 extern template class messages_byname<char>; 02517 extern template class ctype_byname<char>; 02518 extern template class codecvt_byname<char, char, mbstate_t>; 02519 extern template class collate<char>; 02520 extern template class collate_byname<char>; 02521 02522 extern template 02523 const codecvt<char, char, mbstate_t>& 02524 use_facet<codecvt<char, char, mbstate_t> >(const locale&); 02525 02526 extern template 02527 const collate<char>& 02528 use_facet<collate<char> >(const locale&); 02529 02530 extern template 02531 const numpunct<char>& 02532 use_facet<numpunct<char> >(const locale&); 02533 02534 extern template 02535 const num_put<char>& 02536 use_facet<num_put<char> >(const locale&); 02537 02538 extern template 02539 const num_get<char>& 02540 use_facet<num_get<char> >(const locale&); 02541 02542 extern template 02543 const moneypunct<char, true>& 02544 use_facet<moneypunct<char, true> >(const locale&); 02545 02546 extern template 02547 const moneypunct<char, false>& 02548 use_facet<moneypunct<char, false> >(const locale&); 02549 02550 extern template 02551 const money_put<char>& 02552 use_facet<money_put<char> >(const locale&); 02553 02554 extern template 02555 const money_get<char>& 02556 use_facet<money_get<char> >(const locale&); 02557 02558 extern template 02559 const __timepunct<char>& 02560 use_facet<__timepunct<char> >(const locale&); 02561 02562 extern template 02563 const time_put<char>& 02564 use_facet<time_put<char> >(const locale&); 02565 02566 extern template 02567 const time_get<char>& 02568 use_facet<time_get<char> >(const locale&); 02569 02570 extern template 02571 const messages<char>& 02572 use_facet<messages<char> >(const locale&); 02573 02574 extern template 02575 bool 02576 has_facet<ctype<char> >(const locale&); 02577 02578 extern template 02579 bool 02580 has_facet<codecvt<char, char, mbstate_t> >(const locale&); 02581 02582 extern template 02583 bool 02584 has_facet<collate<char> >(const locale&); 02585 02586 extern template 02587 bool 02588 has_facet<numpunct<char> >(const locale&); 02589 02590 extern template 02591 bool 02592 has_facet<num_put<char> >(const locale&); 02593 02594 extern template 02595 bool 02596 has_facet<num_get<char> >(const locale&); 02597 02598 extern template 02599 bool 02600 has_facet<moneypunct<char> >(const locale&); 02601 02602 extern template 02603 bool 02604 has_facet<money_put<char> >(const locale&); 02605 02606 extern template 02607 bool 02608 has_facet<money_get<char> >(const locale&); 02609 02610 extern template 02611 bool 02612 has_facet<__timepunct<char> >(const locale&); 02613 02614 extern template 02615 bool 02616 has_facet<time_put<char> >(const locale&); 02617 02618 extern template 02619 bool 02620 has_facet<time_get<char> >(const locale&); 02621 02622 extern template 02623 bool 02624 has_facet<messages<char> >(const locale&); 02625 02626 #ifdef _GLIBCXX_USE_WCHAR_T 02627 extern template class moneypunct<wchar_t, false>; 02628 extern template class moneypunct<wchar_t, true>; 02629 extern template class moneypunct_byname<wchar_t, false>; 02630 extern template class moneypunct_byname<wchar_t, true>; 02631 extern template class money_get<wchar_t>; 02632 extern template class money_put<wchar_t>; 02633 extern template class numpunct<wchar_t>; 02634 extern template class numpunct_byname<wchar_t>; 02635 extern template class num_get<wchar_t>; 02636 extern template class num_put<wchar_t>; 02637 extern template class __timepunct<wchar_t>; 02638 extern template class time_put<wchar_t>; 02639 extern template class time_put_byname<wchar_t>; 02640 extern template class time_get<wchar_t>; 02641 extern template class time_get_byname<wchar_t>; 02642 extern template class messages<wchar_t>; 02643 extern template class messages_byname<wchar_t>; 02644 extern template class ctype_byname<wchar_t>; 02645 extern template class codecvt_byname<wchar_t, char, mbstate_t>; 02646 extern template class collate<wchar_t>; 02647 extern template class collate_byname<wchar_t>; 02648 02649 extern template 02650 const codecvt<wchar_t, char, mbstate_t>& 02651 use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&); 02652 02653 extern template 02654 const collate<wchar_t>& 02655 use_facet<collate<wchar_t> >(const locale&); 02656 02657 extern template 02658 const numpunct<wchar_t>& 02659 use_facet<numpunct<wchar_t> >(const locale&); 02660 02661 extern template 02662 const num_put<wchar_t>& 02663 use_facet<num_put<wchar_t> >(const locale&); 02664 02665 extern template 02666 const num_get<wchar_t>& 02667 use_facet<num_get<wchar_t> >(const locale&); 02668 02669 extern template 02670 const moneypunct<wchar_t, true>& 02671 use_facet<moneypunct<wchar_t, true> >(const locale&); 02672 02673 extern template 02674 const moneypunct<wchar_t, false>& 02675 use_facet<moneypunct<wchar_t, false> >(const locale&); 02676 02677 extern template 02678 const money_put<wchar_t>& 02679 use_facet<money_put<wchar_t> >(const locale&); 02680 02681 extern template 02682 const money_get<wchar_t>& 02683 use_facet<money_get<wchar_t> >(const locale&); 02684 02685 extern template 02686 const __timepunct<wchar_t>& 02687 use_facet<__timepunct<wchar_t> >(const locale&); 02688 02689 extern template 02690 const time_put<wchar_t>& 02691 use_facet<time_put<wchar_t> >(const locale&); 02692 02693 extern template 02694 const time_get<wchar_t>& 02695 use_facet<time_get<wchar_t> >(const locale&); 02696 02697 extern template 02698 const messages<wchar_t>& 02699 use_facet<messages<wchar_t> >(const locale&); 02700 02701 extern template 02702 bool 02703 has_facet<ctype<wchar_t> >(const locale&); 02704 02705 extern template 02706 bool 02707 has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&); 02708 02709 extern template 02710 bool 02711 has_facet<collate<wchar_t> >(const locale&); 02712 02713 extern template 02714 bool 02715 has_facet<numpunct<wchar_t> >(const locale&); 02716 02717 extern template 02718 bool 02719 has_facet<num_put<wchar_t> >(const locale&); 02720 02721 extern template 02722 bool 02723 has_facet<num_get<wchar_t> >(const locale&); 02724 02725 extern template 02726 bool 02727 has_facet<moneypunct<wchar_t> >(const locale&); 02728 02729 extern template 02730 bool 02731 has_facet<money_put<wchar_t> >(const locale&); 02732 02733 extern template 02734 bool 02735 has_facet<money_get<wchar_t> >(const locale&); 02736 02737 extern template 02738 bool 02739 has_facet<__timepunct<wchar_t> >(const locale&); 02740 02741 extern template 02742 bool 02743 has_facet<time_put<wchar_t> >(const locale&); 02744 02745 extern template 02746 bool 02747 has_facet<time_get<wchar_t> >(const locale&); 02748 02749 extern template 02750 bool 02751 has_facet<messages<wchar_t> >(const locale&); 02752 #endif 02753 #endif 02754 } // namespace std 02755 02756 #endif

Generated on Wed Jun 9 11:18:40 2004 for libstdc++-v3 Source by doxygen 1.3.7