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