libstdc++
locale_facets.tcc
Go to the documentation of this file.
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