libstdc++
|
00001 // Locale support -*- C++ -*- 00002 00003 // Copyright (C) 1997-2013 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.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_TCC 00031 #define _LOCALE_FACETS_TCC 1 00032 00033 #pragma GCC system_header 00034 00035 namespace std _GLIBCXX_VISIBILITY(default) 00036 { 00037 _GLIBCXX_BEGIN_NAMESPACE_VERSION 00038 00039 // Routine to access a cache for the facet. If the cache didn't 00040 // exist before, it gets constructed on the fly. 00041 template<typename _Facet> 00042 struct __use_cache 00043 { 00044 const _Facet* 00045 operator() (const locale& __loc) const; 00046 }; 00047 00048 // Specializations. 00049 template<typename _CharT> 00050 struct __use_cache<__numpunct_cache<_CharT> > 00051 { 00052 const __numpunct_cache<_CharT>* 00053 operator() (const locale& __loc) const 00054 { 00055 const size_t __i = numpunct<_CharT>::id._M_id(); 00056 const locale::facet** __caches = __loc._M_impl->_M_caches; 00057 if (!__caches[__i]) 00058 { 00059 __numpunct_cache<_CharT>* __tmp = 0; 00060 __try 00061 { 00062 __tmp = new __numpunct_cache<_CharT>; 00063 __tmp->_M_cache(__loc); 00064 } 00065 __catch(...) 00066 { 00067 delete __tmp; 00068 __throw_exception_again; 00069 } 00070 __loc._M_impl->_M_install_cache(__tmp, __i); 00071 } 00072 return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]); 00073 } 00074 }; 00075 00076 template<typename _CharT> 00077 void 00078 __numpunct_cache<_CharT>::_M_cache(const locale& __loc) 00079 { 00080 _M_allocated = true; 00081 00082 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 00083 00084 char* __grouping = 0; 00085 _CharT* __truename = 0; 00086 _CharT* __falsename = 0; 00087 __try 00088 { 00089 _M_grouping_size = __np.grouping().size(); 00090 __grouping = new char[_M_grouping_size]; 00091 __np.grouping().copy(__grouping, _M_grouping_size); 00092 _M_grouping = __grouping; 00093 _M_use_grouping = (_M_grouping_size 00094 && static_cast<signed char>(_M_grouping[0]) > 0 00095 && (_M_grouping[0] 00096 != __gnu_cxx::__numeric_traits<char>::__max)); 00097 00098 _M_truename_size = __np.truename().size(); 00099 __truename = new _CharT[_M_truename_size]; 00100 __np.truename().copy(__truename, _M_truename_size); 00101 _M_truename = __truename; 00102 00103 _M_falsename_size = __np.falsename().size(); 00104 __falsename = new _CharT[_M_falsename_size]; 00105 __np.falsename().copy(__falsename, _M_falsename_size); 00106 _M_falsename = __falsename; 00107 00108 _M_decimal_point = __np.decimal_point(); 00109 _M_thousands_sep = __np.thousands_sep(); 00110 00111 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc); 00112 __ct.widen(__num_base::_S_atoms_out, 00113 __num_base::_S_atoms_out 00114 + __num_base::_S_oend, _M_atoms_out); 00115 __ct.widen(__num_base::_S_atoms_in, 00116 __num_base::_S_atoms_in 00117 + __num_base::_S_iend, _M_atoms_in); 00118 } 00119 __catch(...) 00120 { 00121 delete [] __grouping; 00122 delete [] __truename; 00123 delete [] __falsename; 00124 __throw_exception_again; 00125 } 00126 } 00127 00128 // Used by both numeric and monetary facets. 00129 // Check to make sure that the __grouping_tmp string constructed in 00130 // money_get or num_get matches the canonical grouping for a given 00131 // locale. 00132 // __grouping_tmp is parsed L to R 00133 // 1,222,444 == __grouping_tmp of "\1\3\3" 00134 // __grouping is parsed R to L 00135 // 1,222,444 == __grouping of "\3" == "\3\3\3" 00136 _GLIBCXX_PURE bool 00137 __verify_grouping(const char* __grouping, size_t __grouping_size, 00138 const string& __grouping_tmp) throw (); 00139 00140 _GLIBCXX_BEGIN_NAMESPACE_LDBL 00141 00142 template<typename _CharT, typename _InIter> 00143 _InIter 00144 num_get<_CharT, _InIter>:: 00145 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io, 00146 ios_base::iostate& __err, string& __xtrc) const 00147 { 00148 typedef char_traits<_CharT> __traits_type; 00149 typedef __numpunct_cache<_CharT> __cache_type; 00150 __use_cache<__cache_type> __uc; 00151 const locale& __loc = __io._M_getloc(); 00152 const __cache_type* __lc = __uc(__loc); 00153 const _CharT* __lit = __lc->_M_atoms_in; 00154 char_type __c = char_type(); 00155 00156 // True if __beg becomes equal to __end. 00157 bool __testeof = __beg == __end; 00158 00159 // First check for sign. 00160 if (!__testeof) 00161 { 00162 __c = *__beg; 00163 const bool __plus = __c == __lit[__num_base::_S_iplus]; 00164 if ((__plus || __c == __lit[__num_base::_S_iminus]) 00165 && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00166 && !(__c == __lc->_M_decimal_point)) 00167 { 00168 __xtrc += __plus ? '+' : '-'; 00169 if (++__beg != __end) 00170 __c = *__beg; 00171 else 00172 __testeof = true; 00173 } 00174 } 00175 00176 // Next, look for leading zeros. 00177 bool __found_mantissa = false; 00178 int __sep_pos = 0; 00179 while (!__testeof) 00180 { 00181 if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00182 || __c == __lc->_M_decimal_point) 00183 break; 00184 else if (__c == __lit[__num_base::_S_izero]) 00185 { 00186 if (!__found_mantissa) 00187 { 00188 __xtrc += '0'; 00189 __found_mantissa = true; 00190 } 00191 ++__sep_pos; 00192 00193 if (++__beg != __end) 00194 __c = *__beg; 00195 else 00196 __testeof = true; 00197 } 00198 else 00199 break; 00200 } 00201 00202 // Only need acceptable digits for floating point numbers. 00203 bool __found_dec = false; 00204 bool __found_sci = false; 00205 string __found_grouping; 00206 if (__lc->_M_use_grouping) 00207 __found_grouping.reserve(32); 00208 const char_type* __lit_zero = __lit + __num_base::_S_izero; 00209 00210 if (!__lc->_M_allocated) 00211 // "C" locale 00212 while (!__testeof) 00213 { 00214 const int __digit = _M_find(__lit_zero, 10, __c); 00215 if (__digit != -1) 00216 { 00217 __xtrc += '0' + __digit; 00218 __found_mantissa = true; 00219 } 00220 else if (__c == __lc->_M_decimal_point 00221 && !__found_dec && !__found_sci) 00222 { 00223 __xtrc += '.'; 00224 __found_dec = true; 00225 } 00226 else if ((__c == __lit[__num_base::_S_ie] 00227 || __c == __lit[__num_base::_S_iE]) 00228 && !__found_sci && __found_mantissa) 00229 { 00230 // Scientific notation. 00231 __xtrc += 'e'; 00232 __found_sci = true; 00233 00234 // Remove optional plus or minus sign, if they exist. 00235 if (++__beg != __end) 00236 { 00237 __c = *__beg; 00238 const bool __plus = __c == __lit[__num_base::_S_iplus]; 00239 if (__plus || __c == __lit[__num_base::_S_iminus]) 00240 __xtrc += __plus ? '+' : '-'; 00241 else 00242 continue; 00243 } 00244 else 00245 { 00246 __testeof = true; 00247 break; 00248 } 00249 } 00250 else 00251 break; 00252 00253 if (++__beg != __end) 00254 __c = *__beg; 00255 else 00256 __testeof = true; 00257 } 00258 else 00259 while (!__testeof) 00260 { 00261 // According to 22.2.2.1.2, p8-9, first look for thousands_sep 00262 // and decimal_point. 00263 if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00264 { 00265 if (!__found_dec && !__found_sci) 00266 { 00267 // NB: Thousands separator at the beginning of a string 00268 // is a no-no, as is two consecutive thousands separators. 00269 if (__sep_pos) 00270 { 00271 __found_grouping += static_cast<char>(__sep_pos); 00272 __sep_pos = 0; 00273 } 00274 else 00275 { 00276 // NB: __convert_to_v will not assign __v and will 00277 // set the failbit. 00278 __xtrc.clear(); 00279 break; 00280 } 00281 } 00282 else 00283 break; 00284 } 00285 else if (__c == __lc->_M_decimal_point) 00286 { 00287 if (!__found_dec && !__found_sci) 00288 { 00289 // If no grouping chars are seen, no grouping check 00290 // is applied. Therefore __found_grouping is adjusted 00291 // only if decimal_point comes after some thousands_sep. 00292 if (__found_grouping.size()) 00293 __found_grouping += static_cast<char>(__sep_pos); 00294 __xtrc += '.'; 00295 __found_dec = true; 00296 } 00297 else 00298 break; 00299 } 00300 else 00301 { 00302 const char_type* __q = 00303 __traits_type::find(__lit_zero, 10, __c); 00304 if (__q) 00305 { 00306 __xtrc += '0' + (__q - __lit_zero); 00307 __found_mantissa = true; 00308 ++__sep_pos; 00309 } 00310 else if ((__c == __lit[__num_base::_S_ie] 00311 || __c == __lit[__num_base::_S_iE]) 00312 && !__found_sci && __found_mantissa) 00313 { 00314 // Scientific notation. 00315 if (__found_grouping.size() && !__found_dec) 00316 __found_grouping += static_cast<char>(__sep_pos); 00317 __xtrc += 'e'; 00318 __found_sci = true; 00319 00320 // Remove optional plus or minus sign, if they exist. 00321 if (++__beg != __end) 00322 { 00323 __c = *__beg; 00324 const bool __plus = __c == __lit[__num_base::_S_iplus]; 00325 if ((__plus || __c == __lit[__num_base::_S_iminus]) 00326 && !(__lc->_M_use_grouping 00327 && __c == __lc->_M_thousands_sep) 00328 && !(__c == __lc->_M_decimal_point)) 00329 __xtrc += __plus ? '+' : '-'; 00330 else 00331 continue; 00332 } 00333 else 00334 { 00335 __testeof = true; 00336 break; 00337 } 00338 } 00339 else 00340 break; 00341 } 00342 00343 if (++__beg != __end) 00344 __c = *__beg; 00345 else 00346 __testeof = true; 00347 } 00348 00349 // Digit grouping is checked. If grouping and found_grouping don't 00350 // match, then get very very upset, and set failbit. 00351 if (__found_grouping.size()) 00352 { 00353 // Add the ending grouping if a decimal or 'e'/'E' wasn't found. 00354 if (!__found_dec && !__found_sci) 00355 __found_grouping += static_cast<char>(__sep_pos); 00356 00357 if (!std::__verify_grouping(__lc->_M_grouping, 00358 __lc->_M_grouping_size, 00359 __found_grouping)) 00360 __err = ios_base::failbit; 00361 } 00362 00363 return __beg; 00364 } 00365 00366 template<typename _CharT, typename _InIter> 00367 template<typename _ValueT> 00368 _InIter 00369 num_get<_CharT, _InIter>:: 00370 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io, 00371 ios_base::iostate& __err, _ValueT& __v) const 00372 { 00373 typedef char_traits<_CharT> __traits_type; 00374 using __gnu_cxx::__add_unsigned; 00375 typedef typename __add_unsigned<_ValueT>::__type __unsigned_type; 00376 typedef __numpunct_cache<_CharT> __cache_type; 00377 __use_cache<__cache_type> __uc; 00378 const locale& __loc = __io._M_getloc(); 00379 const __cache_type* __lc = __uc(__loc); 00380 const _CharT* __lit = __lc->_M_atoms_in; 00381 char_type __c = char_type(); 00382 00383 // NB: Iff __basefield == 0, __base can change based on contents. 00384 const ios_base::fmtflags __basefield = __io.flags() 00385 & ios_base::basefield; 00386 const bool __oct = __basefield == ios_base::oct; 00387 int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10); 00388 00389 // True if __beg becomes equal to __end. 00390 bool __testeof = __beg == __end; 00391 00392 // First check for sign. 00393 bool __negative = false; 00394 if (!__testeof) 00395 { 00396 __c = *__beg; 00397 __negative = __c == __lit[__num_base::_S_iminus]; 00398 if ((__negative || __c == __lit[__num_base::_S_iplus]) 00399 && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00400 && !(__c == __lc->_M_decimal_point)) 00401 { 00402 if (++__beg != __end) 00403 __c = *__beg; 00404 else 00405 __testeof = true; 00406 } 00407 } 00408 00409 // Next, look for leading zeros and check required digits 00410 // for base formats. 00411 bool __found_zero = false; 00412 int __sep_pos = 0; 00413 while (!__testeof) 00414 { 00415 if ((__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00416 || __c == __lc->_M_decimal_point) 00417 break; 00418 else if (__c == __lit[__num_base::_S_izero] 00419 && (!__found_zero || __base == 10)) 00420 { 00421 __found_zero = true; 00422 ++__sep_pos; 00423 if (__basefield == 0) 00424 __base = 8; 00425 if (__base == 8) 00426 __sep_pos = 0; 00427 } 00428 else if (__found_zero 00429 && (__c == __lit[__num_base::_S_ix] 00430 || __c == __lit[__num_base::_S_iX])) 00431 { 00432 if (__basefield == 0) 00433 __base = 16; 00434 if (__base == 16) 00435 { 00436 __found_zero = false; 00437 __sep_pos = 0; 00438 } 00439 else 00440 break; 00441 } 00442 else 00443 break; 00444 00445 if (++__beg != __end) 00446 { 00447 __c = *__beg; 00448 if (!__found_zero) 00449 break; 00450 } 00451 else 00452 __testeof = true; 00453 } 00454 00455 // At this point, base is determined. If not hex, only allow 00456 // base digits as valid input. 00457 const size_t __len = (__base == 16 ? __num_base::_S_iend 00458 - __num_base::_S_izero : __base); 00459 00460 // Extract. 00461 string __found_grouping; 00462 if (__lc->_M_use_grouping) 00463 __found_grouping.reserve(32); 00464 bool __testfail = false; 00465 bool __testoverflow = false; 00466 const __unsigned_type __max = 00467 (__negative && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed) 00468 ? -__gnu_cxx::__numeric_traits<_ValueT>::__min 00469 : __gnu_cxx::__numeric_traits<_ValueT>::__max; 00470 const __unsigned_type __smax = __max / __base; 00471 __unsigned_type __result = 0; 00472 int __digit = 0; 00473 const char_type* __lit_zero = __lit + __num_base::_S_izero; 00474 00475 if (!__lc->_M_allocated) 00476 // "C" locale 00477 while (!__testeof) 00478 { 00479 __digit = _M_find(__lit_zero, __len, __c); 00480 if (__digit == -1) 00481 break; 00482 00483 if (__result > __smax) 00484 __testoverflow = true; 00485 else 00486 { 00487 __result *= __base; 00488 __testoverflow |= __result > __max - __digit; 00489 __result += __digit; 00490 ++__sep_pos; 00491 } 00492 00493 if (++__beg != __end) 00494 __c = *__beg; 00495 else 00496 __testeof = true; 00497 } 00498 else 00499 while (!__testeof) 00500 { 00501 // According to 22.2.2.1.2, p8-9, first look for thousands_sep 00502 // and decimal_point. 00503 if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep) 00504 { 00505 // NB: Thousands separator at the beginning of a string 00506 // is a no-no, as is two consecutive thousands separators. 00507 if (__sep_pos) 00508 { 00509 __found_grouping += static_cast<char>(__sep_pos); 00510 __sep_pos = 0; 00511 } 00512 else 00513 { 00514 __testfail = true; 00515 break; 00516 } 00517 } 00518 else if (__c == __lc->_M_decimal_point) 00519 break; 00520 else 00521 { 00522 const char_type* __q = 00523 __traits_type::find(__lit_zero, __len, __c); 00524 if (!__q) 00525 break; 00526 00527 __digit = __q - __lit_zero; 00528 if (__digit > 15) 00529 __digit -= 6; 00530 if (__result > __smax) 00531 __testoverflow = true; 00532 else 00533 { 00534 __result *= __base; 00535 __testoverflow |= __result > __max - __digit; 00536 __result += __digit; 00537 ++__sep_pos; 00538 } 00539 } 00540 00541 if (++__beg != __end) 00542 __c = *__beg; 00543 else 00544 __testeof = true; 00545 } 00546 00547 // Digit grouping is checked. If grouping and found_grouping don't 00548 // match, then get very very upset, and set failbit. 00549 if (__found_grouping.size()) 00550 { 00551 // Add the ending grouping. 00552 __found_grouping += static_cast<char>(__sep_pos); 00553 00554 if (!std::__verify_grouping(__lc->_M_grouping, 00555 __lc->_M_grouping_size, 00556 __found_grouping)) 00557 __err = ios_base::failbit; 00558 } 00559 00560 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00561 // 23. Num_get overflow result. 00562 if ((!__sep_pos && !__found_zero && !__found_grouping.size()) 00563 || __testfail) 00564 { 00565 __v = 0; 00566 __err = ios_base::failbit; 00567 } 00568 else if (__testoverflow) 00569 { 00570 if (__negative 00571 && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed) 00572 __v = __gnu_cxx::__numeric_traits<_ValueT>::__min; 00573 else 00574 __v = __gnu_cxx::__numeric_traits<_ValueT>::__max; 00575 __err = ios_base::failbit; 00576 } 00577 else 00578 __v = __negative ? -__result : __result; 00579 00580 if (__testeof) 00581 __err |= ios_base::eofbit; 00582 return __beg; 00583 } 00584 00585 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00586 // 17. Bad bool parsing 00587 template<typename _CharT, typename _InIter> 00588 _InIter 00589 num_get<_CharT, _InIter>:: 00590 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00591 ios_base::iostate& __err, bool& __v) const 00592 { 00593 if (!(__io.flags() & ios_base::boolalpha)) 00594 { 00595 // Parse bool values as long. 00596 // NB: We can't just call do_get(long) here, as it might 00597 // refer to a derived class. 00598 long __l = -1; 00599 __beg = _M_extract_int(__beg, __end, __io, __err, __l); 00600 if (__l == 0 || __l == 1) 00601 __v = bool(__l); 00602 else 00603 { 00604 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00605 // 23. Num_get overflow result. 00606 __v = true; 00607 __err = ios_base::failbit; 00608 if (__beg == __end) 00609 __err |= ios_base::eofbit; 00610 } 00611 } 00612 else 00613 { 00614 // Parse bool values as alphanumeric. 00615 typedef __numpunct_cache<_CharT> __cache_type; 00616 __use_cache<__cache_type> __uc; 00617 const locale& __loc = __io._M_getloc(); 00618 const __cache_type* __lc = __uc(__loc); 00619 00620 bool __testf = true; 00621 bool __testt = true; 00622 bool __donef = __lc->_M_falsename_size == 0; 00623 bool __donet = __lc->_M_truename_size == 0; 00624 bool __testeof = false; 00625 size_t __n = 0; 00626 while (!__donef || !__donet) 00627 { 00628 if (__beg == __end) 00629 { 00630 __testeof = true; 00631 break; 00632 } 00633 00634 const char_type __c = *__beg; 00635 00636 if (!__donef) 00637 __testf = __c == __lc->_M_falsename[__n]; 00638 00639 if (!__testf && __donet) 00640 break; 00641 00642 if (!__donet) 00643 __testt = __c == __lc->_M_truename[__n]; 00644 00645 if (!__testt && __donef) 00646 break; 00647 00648 if (!__testt && !__testf) 00649 break; 00650 00651 ++__n; 00652 ++__beg; 00653 00654 __donef = !__testf || __n >= __lc->_M_falsename_size; 00655 __donet = !__testt || __n >= __lc->_M_truename_size; 00656 } 00657 if (__testf && __n == __lc->_M_falsename_size && __n) 00658 { 00659 __v = false; 00660 if (__testt && __n == __lc->_M_truename_size) 00661 __err = ios_base::failbit; 00662 else 00663 __err = __testeof ? ios_base::eofbit : ios_base::goodbit; 00664 } 00665 else if (__testt && __n == __lc->_M_truename_size && __n) 00666 { 00667 __v = true; 00668 __err = __testeof ? ios_base::eofbit : ios_base::goodbit; 00669 } 00670 else 00671 { 00672 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00673 // 23. Num_get overflow result. 00674 __v = false; 00675 __err = ios_base::failbit; 00676 if (__testeof) 00677 __err |= ios_base::eofbit; 00678 } 00679 } 00680 return __beg; 00681 } 00682 00683 template<typename _CharT, typename _InIter> 00684 _InIter 00685 num_get<_CharT, _InIter>:: 00686 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00687 ios_base::iostate& __err, float& __v) const 00688 { 00689 string __xtrc; 00690 __xtrc.reserve(32); 00691 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 00692 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 00693 if (__beg == __end) 00694 __err |= ios_base::eofbit; 00695 return __beg; 00696 } 00697 00698 template<typename _CharT, typename _InIter> 00699 _InIter 00700 num_get<_CharT, _InIter>:: 00701 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00702 ios_base::iostate& __err, double& __v) const 00703 { 00704 string __xtrc; 00705 __xtrc.reserve(32); 00706 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 00707 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 00708 if (__beg == __end) 00709 __err |= ios_base::eofbit; 00710 return __beg; 00711 } 00712 00713 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ 00714 template<typename _CharT, typename _InIter> 00715 _InIter 00716 num_get<_CharT, _InIter>:: 00717 __do_get(iter_type __beg, iter_type __end, ios_base& __io, 00718 ios_base::iostate& __err, double& __v) const 00719 { 00720 string __xtrc; 00721 __xtrc.reserve(32); 00722 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 00723 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 00724 if (__beg == __end) 00725 __err |= ios_base::eofbit; 00726 return __beg; 00727 } 00728 #endif 00729 00730 template<typename _CharT, typename _InIter> 00731 _InIter 00732 num_get<_CharT, _InIter>:: 00733 do_get(iter_type __beg, iter_type __end, ios_base& __io, 00734 ios_base::iostate& __err, long double& __v) const 00735 { 00736 string __xtrc; 00737 __xtrc.reserve(32); 00738 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); 00739 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); 00740 if (__beg == __end) 00741 __err |= ios_base::eofbit; 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, void*& __v) const 00750 { 00751 // Prepare for hex formatted input. 00752 typedef ios_base::fmtflags fmtflags; 00753 const fmtflags __fmt = __io.flags(); 00754 __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex); 00755 00756 typedef __gnu_cxx::__conditional_type<(sizeof(void*) 00757 <= sizeof(unsigned long)), 00758 unsigned long, unsigned long long>::__type _UIntPtrType; 00759 00760 _UIntPtrType __ul; 00761 __beg = _M_extract_int(__beg, __end, __io, __err, __ul); 00762 00763 // Reset from hex formatted input. 00764 __io.flags(__fmt); 00765 00766 __v = reinterpret_cast<void*>(__ul); 00767 return __beg; 00768 } 00769 00770 // For use by integer and floating-point types after they have been 00771 // converted into a char_type string. 00772 template<typename _CharT, typename _OutIter> 00773 void 00774 num_put<_CharT, _OutIter>:: 00775 _M_pad(_CharT __fill, streamsize __w, ios_base& __io, 00776 _CharT* __new, const _CharT* __cs, int& __len) const 00777 { 00778 // [22.2.2.2.2] Stage 3. 00779 // If necessary, pad. 00780 __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, 00781 __cs, __w, __len); 00782 __len = static_cast<int>(__w); 00783 } 00784 00785 _GLIBCXX_END_NAMESPACE_LDBL 00786 00787 template<typename _CharT, typename _ValueT> 00788 int 00789 __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit, 00790 ios_base::fmtflags __flags, bool __dec) 00791 { 00792 _CharT* __buf = __bufend; 00793 if (__builtin_expect(__dec, true)) 00794 { 00795 // Decimal. 00796 do 00797 { 00798 *--__buf = __lit[(__v % 10) + __num_base::_S_odigits]; 00799 __v /= 10; 00800 } 00801 while (__v != 0); 00802 } 00803 else if ((__flags & ios_base::basefield) == ios_base::oct) 00804 { 00805 // Octal. 00806 do 00807 { 00808 *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits]; 00809 __v >>= 3; 00810 } 00811 while (__v != 0); 00812 } 00813 else 00814 { 00815 // Hex. 00816 const bool __uppercase = __flags & ios_base::uppercase; 00817 const int __case_offset = __uppercase ? __num_base::_S_oudigits 00818 : __num_base::_S_odigits; 00819 do 00820 { 00821 *--__buf = __lit[(__v & 0xf) + __case_offset]; 00822 __v >>= 4; 00823 } 00824 while (__v != 0); 00825 } 00826 return __bufend - __buf; 00827 } 00828 00829 _GLIBCXX_BEGIN_NAMESPACE_LDBL 00830 00831 template<typename _CharT, typename _OutIter> 00832 void 00833 num_put<_CharT, _OutIter>:: 00834 _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep, 00835 ios_base&, _CharT* __new, _CharT* __cs, int& __len) const 00836 { 00837 _CharT* __p = std::__add_grouping(__new, __sep, __grouping, 00838 __grouping_size, __cs, __cs + __len); 00839 __len = __p - __new; 00840 } 00841 00842 template<typename _CharT, typename _OutIter> 00843 template<typename _ValueT> 00844 _OutIter 00845 num_put<_CharT, _OutIter>:: 00846 _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill, 00847 _ValueT __v) const 00848 { 00849 using __gnu_cxx::__add_unsigned; 00850 typedef typename __add_unsigned<_ValueT>::__type __unsigned_type; 00851 typedef __numpunct_cache<_CharT> __cache_type; 00852 __use_cache<__cache_type> __uc; 00853 const locale& __loc = __io._M_getloc(); 00854 const __cache_type* __lc = __uc(__loc); 00855 const _CharT* __lit = __lc->_M_atoms_out; 00856 const ios_base::fmtflags __flags = __io.flags(); 00857 00858 // Long enough to hold hex, dec, and octal representations. 00859 const int __ilen = 5 * sizeof(_ValueT); 00860 _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00861 * __ilen)); 00862 00863 // [22.2.2.2.2] Stage 1, numeric conversion to character. 00864 // Result is returned right-justified in the buffer. 00865 const ios_base::fmtflags __basefield = __flags & ios_base::basefield; 00866 const bool __dec = (__basefield != ios_base::oct 00867 && __basefield != ios_base::hex); 00868 const __unsigned_type __u = ((__v > 0 || !__dec) 00869 ? __unsigned_type(__v) 00870 : -__unsigned_type(__v)); 00871 int __len = __int_to_char(__cs + __ilen, __u, __lit, __flags, __dec); 00872 __cs += __ilen - __len; 00873 00874 // Add grouping, if necessary. 00875 if (__lc->_M_use_grouping) 00876 { 00877 // Grouping can add (almost) as many separators as the number 00878 // of digits + space is reserved for numeric base or sign. 00879 _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00880 * (__len + 1) 00881 * 2)); 00882 _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size, 00883 __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len); 00884 __cs = __cs2 + 2; 00885 } 00886 00887 // Complete Stage 1, prepend numeric base or sign. 00888 if (__builtin_expect(__dec, true)) 00889 { 00890 // Decimal. 00891 if (__v >= 0) 00892 { 00893 if (bool(__flags & ios_base::showpos) 00894 && __gnu_cxx::__numeric_traits<_ValueT>::__is_signed) 00895 *--__cs = __lit[__num_base::_S_oplus], ++__len; 00896 } 00897 else 00898 *--__cs = __lit[__num_base::_S_ominus], ++__len; 00899 } 00900 else if (bool(__flags & ios_base::showbase) && __v) 00901 { 00902 if (__basefield == ios_base::oct) 00903 *--__cs = __lit[__num_base::_S_odigits], ++__len; 00904 else 00905 { 00906 // 'x' or 'X' 00907 const bool __uppercase = __flags & ios_base::uppercase; 00908 *--__cs = __lit[__num_base::_S_ox + __uppercase]; 00909 // '0' 00910 *--__cs = __lit[__num_base::_S_odigits]; 00911 __len += 2; 00912 } 00913 } 00914 00915 // Pad. 00916 const streamsize __w = __io.width(); 00917 if (__w > static_cast<streamsize>(__len)) 00918 { 00919 _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 00920 * __w)); 00921 _M_pad(__fill, __w, __io, __cs3, __cs, __len); 00922 __cs = __cs3; 00923 } 00924 __io.width(0); 00925 00926 // [22.2.2.2.2] Stage 4. 00927 // Write resulting, fully-formatted string to output iterator. 00928 return std::__write(__s, __cs, __len); 00929 } 00930 00931 template<typename _CharT, typename _OutIter> 00932 void 00933 num_put<_CharT, _OutIter>:: 00934 _M_group_float(const char* __grouping, size_t __grouping_size, 00935 _CharT __sep, const _CharT* __p, _CharT* __new, 00936 _CharT* __cs, int& __len) const 00937 { 00938 // _GLIBCXX_RESOLVE_LIB_DEFECTS 00939 // 282. What types does numpunct grouping refer to? 00940 // Add grouping, if necessary. 00941 const int __declen = __p ? __p - __cs : __len; 00942 _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping, 00943 __grouping_size, 00944 __cs, __cs + __declen); 00945 00946 // Tack on decimal part. 00947 int __newlen = __p2 - __new; 00948 if (__p) 00949 { 00950 char_traits<_CharT>::copy(__p2, __p, __len - __declen); 00951 __newlen += __len - __declen; 00952 } 00953 __len = __newlen; 00954 } 00955 00956 // The following code uses vsnprintf (or vsprintf(), when 00957 // _GLIBCXX_USE_C99 is not defined) to convert floating point values 00958 // for insertion into a stream. An optimization would be to replace 00959 // them with code that works directly on a wide buffer and then use 00960 // __pad to do the padding. It would be good to replace them anyway 00961 // to gain back the efficiency that C++ provides by knowing up front 00962 // the type of the values to insert. Also, sprintf is dangerous 00963 // since may lead to accidental buffer overruns. This 00964 // implementation follows the C++ standard fairly directly as 00965 // outlined in 22.2.2.2 [lib.locale.num.put] 00966 template<typename _CharT, typename _OutIter> 00967 template<typename _ValueT> 00968 _OutIter 00969 num_put<_CharT, _OutIter>:: 00970 _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod, 00971 _ValueT __v) const 00972 { 00973 typedef __numpunct_cache<_CharT> __cache_type; 00974 __use_cache<__cache_type> __uc; 00975 const locale& __loc = __io._M_getloc(); 00976 const __cache_type* __lc = __uc(__loc); 00977 00978 // Use default precision if out of range. 00979 const streamsize __prec = __io.precision() < 0 ? 6 : __io.precision(); 00980 00981 const int __max_digits = 00982 __gnu_cxx::__numeric_traits<_ValueT>::__digits10; 00983 00984 // [22.2.2.2.2] Stage 1, numeric conversion to character. 00985 int __len; 00986 // Long enough for the max format spec. 00987 char __fbuf[16]; 00988 __num_base::_S_format_float(__io, __fbuf, __mod); 00989 00990 #ifdef _GLIBCXX_USE_C99 00991 // First try a buffer perhaps big enough (most probably sufficient 00992 // for non-ios_base::fixed outputs) 00993 int __cs_size = __max_digits * 3; 00994 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 00995 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 00996 __fbuf, __prec, __v); 00997 00998 // If the buffer was not large enough, try again with the correct size. 00999 if (__len >= __cs_size) 01000 { 01001 __cs_size = __len + 1; 01002 __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01003 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size, 01004 __fbuf, __prec, __v); 01005 } 01006 #else 01007 // Consider the possibility of long ios_base::fixed outputs 01008 const bool __fixed = __io.flags() & ios_base::fixed; 01009 const int __max_exp = 01010 __gnu_cxx::__numeric_traits<_ValueT>::__max_exponent10; 01011 01012 // The size of the output string is computed as follows. 01013 // ios_base::fixed outputs may need up to __max_exp + 1 chars 01014 // for the integer part + __prec chars for the fractional part 01015 // + 3 chars for sign, decimal point, '\0'. On the other hand, 01016 // for non-fixed outputs __max_digits * 2 + __prec chars are 01017 // largely sufficient. 01018 const int __cs_size = __fixed ? __max_exp + __prec + 4 01019 : __max_digits * 2 + __prec; 01020 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size)); 01021 __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, __fbuf, 01022 __prec, __v); 01023 #endif 01024 01025 // [22.2.2.2.2] Stage 2, convert to char_type, using correct 01026 // numpunct.decimal_point() values for '.' and adding grouping. 01027 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01028 01029 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01030 * __len)); 01031 __ctype.widen(__cs, __cs + __len, __ws); 01032 01033 // Replace decimal point. 01034 _CharT* __wp = 0; 01035 const char* __p = char_traits<char>::find(__cs, __len, '.'); 01036 if (__p) 01037 { 01038 __wp = __ws + (__p - __cs); 01039 *__wp = __lc->_M_decimal_point; 01040 } 01041 01042 // Add grouping, if necessary. 01043 // N.B. Make sure to not group things like 2e20, i.e., no decimal 01044 // point, scientific notation. 01045 if (__lc->_M_use_grouping 01046 && (__wp || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9' 01047 && __cs[1] >= '0' && __cs[2] >= '0'))) 01048 { 01049 // Grouping can add (almost) as many separators as the 01050 // number of digits, but no more. 01051 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01052 * __len * 2)); 01053 01054 streamsize __off = 0; 01055 if (__cs[0] == '-' || __cs[0] == '+') 01056 { 01057 __off = 1; 01058 __ws2[0] = __ws[0]; 01059 __len -= 1; 01060 } 01061 01062 _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size, 01063 __lc->_M_thousands_sep, __wp, __ws2 + __off, 01064 __ws + __off, __len); 01065 __len += __off; 01066 01067 __ws = __ws2; 01068 } 01069 01070 // Pad. 01071 const streamsize __w = __io.width(); 01072 if (__w > static_cast<streamsize>(__len)) 01073 { 01074 _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01075 * __w)); 01076 _M_pad(__fill, __w, __io, __ws3, __ws, __len); 01077 __ws = __ws3; 01078 } 01079 __io.width(0); 01080 01081 // [22.2.2.2.2] Stage 4. 01082 // Write resulting, fully-formatted string to output iterator. 01083 return std::__write(__s, __ws, __len); 01084 } 01085 01086 template<typename _CharT, typename _OutIter> 01087 _OutIter 01088 num_put<_CharT, _OutIter>:: 01089 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const 01090 { 01091 const ios_base::fmtflags __flags = __io.flags(); 01092 if ((__flags & ios_base::boolalpha) == 0) 01093 { 01094 const long __l = __v; 01095 __s = _M_insert_int(__s, __io, __fill, __l); 01096 } 01097 else 01098 { 01099 typedef __numpunct_cache<_CharT> __cache_type; 01100 __use_cache<__cache_type> __uc; 01101 const locale& __loc = __io._M_getloc(); 01102 const __cache_type* __lc = __uc(__loc); 01103 01104 const _CharT* __name = __v ? __lc->_M_truename 01105 : __lc->_M_falsename; 01106 int __len = __v ? __lc->_M_truename_size 01107 : __lc->_M_falsename_size; 01108 01109 const streamsize __w = __io.width(); 01110 if (__w > static_cast<streamsize>(__len)) 01111 { 01112 const streamsize __plen = __w - __len; 01113 _CharT* __ps 01114 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 01115 * __plen)); 01116 01117 char_traits<_CharT>::assign(__ps, __plen, __fill); 01118 __io.width(0); 01119 01120 if ((__flags & ios_base::adjustfield) == ios_base::left) 01121 { 01122 __s = std::__write(__s, __name, __len); 01123 __s = std::__write(__s, __ps, __plen); 01124 } 01125 else 01126 { 01127 __s = std::__write(__s, __ps, __plen); 01128 __s = std::__write(__s, __name, __len); 01129 } 01130 return __s; 01131 } 01132 __io.width(0); 01133 __s = std::__write(__s, __name, __len); 01134 } 01135 return __s; 01136 } 01137 01138 template<typename _CharT, typename _OutIter> 01139 _OutIter 01140 num_put<_CharT, _OutIter>:: 01141 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 01142 { return _M_insert_float(__s, __io, __fill, char(), __v); } 01143 01144 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ 01145 template<typename _CharT, typename _OutIter> 01146 _OutIter 01147 num_put<_CharT, _OutIter>:: 01148 __do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const 01149 { return _M_insert_float(__s, __io, __fill, char(), __v); } 01150 #endif 01151 01152 template<typename _CharT, typename _OutIter> 01153 _OutIter 01154 num_put<_CharT, _OutIter>:: 01155 do_put(iter_type __s, ios_base& __io, char_type __fill, 01156 long double __v) const 01157 { return _M_insert_float(__s, __io, __fill, 'L', __v); } 01158 01159 template<typename _CharT, typename _OutIter> 01160 _OutIter 01161 num_put<_CharT, _OutIter>:: 01162 do_put(iter_type __s, ios_base& __io, char_type __fill, 01163 const void* __v) const 01164 { 01165 const ios_base::fmtflags __flags = __io.flags(); 01166 const ios_base::fmtflags __fmt = ~(ios_base::basefield 01167 | ios_base::uppercase); 01168 __io.flags((__flags & __fmt) | (ios_base::hex | ios_base::showbase)); 01169 01170 typedef __gnu_cxx::__conditional_type<(sizeof(const void*) 01171 <= sizeof(unsigned long)), 01172 unsigned long, unsigned long long>::__type _UIntPtrType; 01173 01174 __s = _M_insert_int(__s, __io, __fill, 01175 reinterpret_cast<_UIntPtrType>(__v)); 01176 __io.flags(__flags); 01177 return __s; 01178 } 01179 01180 _GLIBCXX_END_NAMESPACE_LDBL 01181 01182 // Construct correctly padded string, as per 22.2.2.2.2 01183 // Assumes 01184 // __newlen > __oldlen 01185 // __news is allocated for __newlen size 01186 01187 // NB: Of the two parameters, _CharT can be deduced from the 01188 // function arguments. The other (_Traits) has to be explicitly specified. 01189 template<typename _CharT, typename _Traits> 01190 void 01191 __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 01192 _CharT* __news, const _CharT* __olds, 01193 streamsize __newlen, streamsize __oldlen) 01194 { 01195 const size_t __plen = static_cast<size_t>(__newlen - __oldlen); 01196 const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield; 01197 01198 // Padding last. 01199 if (__adjust == ios_base::left) 01200 { 01201 _Traits::copy(__news, __olds, __oldlen); 01202 _Traits::assign(__news + __oldlen, __plen, __fill); 01203 return; 01204 } 01205 01206 size_t __mod = 0; 01207 if (__adjust == ios_base::internal) 01208 { 01209 // Pad after the sign, if there is one. 01210 // Pad after 0[xX], if there is one. 01211 // Who came up with these rules, anyway? Jeeze. 01212 const locale& __loc = __io._M_getloc(); 01213 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 01214 01215 if (__ctype.widen('-') == __olds[0] 01216 || __ctype.widen('+') == __olds[0]) 01217 { 01218 __news[0] = __olds[0]; 01219 __mod = 1; 01220 ++__news; 01221 } 01222 else if (__ctype.widen('0') == __olds[0] 01223 && __oldlen > 1 01224 && (__ctype.widen('x') == __olds[1] 01225 || __ctype.widen('X') == __olds[1])) 01226 { 01227 __news[0] = __olds[0]; 01228 __news[1] = __olds[1]; 01229 __mod = 2; 01230 __news += 2; 01231 } 01232 // else Padding first. 01233 } 01234 _Traits::assign(__news, __plen, __fill); 01235 _Traits::copy(__news + __plen, __olds + __mod, __oldlen - __mod); 01236 } 01237 01238 template<typename _CharT> 01239 _CharT* 01240 __add_grouping(_CharT* __s, _CharT __sep, 01241 const char* __gbeg, size_t __gsize, 01242 const _CharT* __first, const _CharT* __last) 01243 { 01244 size_t __idx = 0; 01245 size_t __ctr = 0; 01246 01247 while (__last - __first > __gbeg[__idx] 01248 && static_cast<signed char>(__gbeg[__idx]) > 0 01249 && __gbeg[__idx] != __gnu_cxx::__numeric_traits<char>::__max) 01250 { 01251 __last -= __gbeg[__idx]; 01252 __idx < __gsize - 1 ? ++__idx : ++__ctr; 01253 } 01254 01255 while (__first != __last) 01256 *__s++ = *__first++; 01257 01258 while (__ctr--) 01259 { 01260 *__s++ = __sep; 01261 for (char __i = __gbeg[__idx]; __i > 0; --__i) 01262 *__s++ = *__first++; 01263 } 01264 01265 while (__idx--) 01266 { 01267 *__s++ = __sep; 01268 for (char __i = __gbeg[__idx]; __i > 0; --__i) 01269 *__s++ = *__first++; 01270 } 01271 01272 return __s; 01273 } 01274 01275 // Inhibit implicit instantiations for required instantiations, 01276 // which are defined via explicit instantiations elsewhere. 01277 #if _GLIBCXX_EXTERN_TEMPLATE 01278 extern template class numpunct<char>; 01279 extern template class numpunct_byname<char>; 01280 extern template class _GLIBCXX_NAMESPACE_LDBL num_get<char>; 01281 extern template class _GLIBCXX_NAMESPACE_LDBL num_put<char>; 01282 extern template class ctype_byname<char>; 01283 01284 extern template 01285 const ctype<char>& 01286 use_facet<ctype<char> >(const locale&); 01287 01288 extern template 01289 const numpunct<char>& 01290 use_facet<numpunct<char> >(const locale&); 01291 01292 extern template 01293 const num_put<char>& 01294 use_facet<num_put<char> >(const locale&); 01295 01296 extern template 01297 const num_get<char>& 01298 use_facet<num_get<char> >(const locale&); 01299 01300 extern template 01301 bool 01302 has_facet<ctype<char> >(const locale&); 01303 01304 extern template 01305 bool 01306 has_facet<numpunct<char> >(const locale&); 01307 01308 extern template 01309 bool 01310 has_facet<num_put<char> >(const locale&); 01311 01312 extern template 01313 bool 01314 has_facet<num_get<char> >(const locale&); 01315 01316 #ifdef _GLIBCXX_USE_WCHAR_T 01317 extern template class numpunct<wchar_t>; 01318 extern template class numpunct_byname<wchar_t>; 01319 extern template class _GLIBCXX_NAMESPACE_LDBL num_get<wchar_t>; 01320 extern template class _GLIBCXX_NAMESPACE_LDBL num_put<wchar_t>; 01321 extern template class ctype_byname<wchar_t>; 01322 01323 extern template 01324 const ctype<wchar_t>& 01325 use_facet<ctype<wchar_t> >(const locale&); 01326 01327 extern template 01328 const numpunct<wchar_t>& 01329 use_facet<numpunct<wchar_t> >(const locale&); 01330 01331 extern template 01332 const num_put<wchar_t>& 01333 use_facet<num_put<wchar_t> >(const locale&); 01334 01335 extern template 01336 const num_get<wchar_t>& 01337 use_facet<num_get<wchar_t> >(const locale&); 01338 01339 extern template 01340 bool 01341 has_facet<ctype<wchar_t> >(const locale&); 01342 01343 extern template 01344 bool 01345 has_facet<numpunct<wchar_t> >(const locale&); 01346 01347 extern template 01348 bool 01349 has_facet<num_put<wchar_t> >(const locale&); 01350 01351 extern template 01352 bool 01353 has_facet<num_get<wchar_t> >(const locale&); 01354 #endif 01355 #endif 01356 01357 _GLIBCXX_END_NAMESPACE_VERSION 01358 } // namespace 01359 01360 #endif