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