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

Generated on Tue Apr 21 13:13:28 2009 for libstdc++ by  doxygen 1.5.8