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 // Free Software Foundation, Inc.
00005 //
00006 // This file is part of the GNU ISO C++ Library.  This library is free
00007 // software; you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the
00009 // Free Software Foundation; either version 2, or (at your option)
00010 // any later version.
00011 
00012 // This library is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 
00017 // You should have received a copy of the GNU General Public License along
00018 // with this library; see the file COPYING.  If not, write to the Free
00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00020 // USA.
00021 
00022 // As a special exception, you may use this file as part of a free software
00023 // library without restriction.  Specifically, if other files instantiate
00024 // templates or use macros or inline functions from this file, or you compile
00025 // this file and link it with other files to produce an executable, this
00026 // file does not by itself cause the resulting executable to be covered by
00027 // the GNU General Public License.  This exception does not however
00028 // invalidate any other reasons why the executable file might be covered by
00029 // the GNU General Public License.
00030 
00031 /** @file locale_facets.tcc
00032  *  This is an internal header file, included by other library headers.
00033  *  You should not attempt to use it directly.
00034  */
00035 
00036 #ifndef _LOCALE_FACETS_TCC
00037 #define _LOCALE_FACETS_TCC 1
00038 
00039 #pragma GCC system_header
00040 
00041 #include <limits>       // For numeric_limits
00042 #include <typeinfo>     // For bad_cast.
00043 #include <bits/streambuf_iterator.h>
00044 
00045 namespace std
00046 {
00047   template<typename _Facet>
00048     locale
00049     locale::combine(const locale& __other) const
00050     {
00051       _Impl* __tmp = new _Impl(*_M_impl, 1);
00052       try
00053     {
00054       __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
00055     }
00056       catch(...)
00057     {
00058       __tmp->_M_remove_reference();
00059       __throw_exception_again;
00060     }
00061       return locale(__tmp);
00062     }
00063 
00064   template<typename _CharT, typename _Traits, typename _Alloc>
00065     bool
00066     locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
00067                        const basic_string<_CharT, _Traits, _Alloc>& __s2) const
00068     {
00069       typedef std::collate<_CharT> __collate_type;
00070       const __collate_type& __collate = use_facet<__collate_type>(*this);
00071       return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
00072                 __s2.data(), __s2.data() + __s2.length()) < 0);
00073     }
00074 
00075   /**
00076    *  @brief  Test for the presence of a facet.
00077    *
00078    *  has_facet tests the locale argument for the presence of the facet type
00079    *  provided as the template parameter.  Facets derived from the facet
00080    *  parameter will also return true.
00081    *
00082    *  @param  Facet  The facet type to test the presence of.
00083    *  @param  locale  The locale to test.
00084    *  @return  true if locale contains a facet of type Facet, else false.
00085   */
00086   template<typename _Facet>
00087     inline bool
00088     has_facet(const locale& __loc) throw()
00089     {
00090       const size_t __i = _Facet::id._M_id();
00091       const locale::facet** __facets = __loc._M_impl->_M_facets;
00092       return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
00093     }
00094 
00095   /**
00096    *  @brief  Return a facet.
00097    *
00098    *  use_facet looks for and returns a reference to a facet of type Facet
00099    *  where Facet is the template parameter.  If has_facet(locale) is true,
00100    *  there is a suitable facet to return.  It throws std::bad_cast if the
00101    *  locale doesn't contain a facet of type Facet.
00102    *
00103    *  @param  Facet  The facet type to access.
00104    *  @param  locale  The locale to use.
00105    *  @return  Reference to facet of type Facet.
00106    *  @throw  std::bad_cast if locale doesn't contain a facet of type Facet.
00107   */
00108   template<typename _Facet>
00109     inline const _Facet&
00110     use_facet(const locale& __loc)
00111     {
00112       const size_t __i = _Facet::id._M_id();
00113       const locale::facet** __facets = __loc._M_impl->_M_facets;
00114       if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
00115         __throw_bad_cast();
00116       return static_cast<const _Facet&>(*__facets[__i]);
00117     }
00118 
00119   // Routine to access a cache for the facet.  If the cache didn't
00120   // exist before, it gets constructed on the fly.
00121   template<typename _Facet>
00122     struct __use_cache
00123     {
00124       const _Facet*
00125       operator() (const locale& __loc) const;
00126     };
00127 
00128   // Specializations.
00129   template<typename _CharT>
00130     struct __use_cache<__numpunct_cache<_CharT> >
00131     {
00132       const __numpunct_cache<_CharT>*
00133       operator() (const locale& __loc) const
00134       {
00135     const size_t __i = numpunct<_CharT>::id._M_id();
00136     const locale::facet** __caches = __loc._M_impl->_M_caches;
00137     if (!__caches[__i])
00138       {
00139         __numpunct_cache<_CharT>* __tmp = NULL;
00140         try
00141           {
00142         __tmp = new __numpunct_cache<_CharT>;
00143         __tmp->_M_cache(__loc);
00144           }
00145         catch(...)
00146           {
00147         delete __tmp;
00148         __throw_exception_again;
00149           }
00150         __loc._M_impl->_M_install_cache(__tmp, __i);
00151       }
00152     return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
00153       }
00154     };
00155 
00156   template<typename _CharT, bool _Intl>
00157     struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
00158     {
00159       const __moneypunct_cache<_CharT, _Intl>*
00160       operator() (const locale& __loc) const
00161       {
00162     const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
00163     const locale::facet** __caches = __loc._M_impl->_M_caches;
00164     if (!__caches[__i])
00165       {
00166         __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
00167         try
00168           {
00169         __tmp = new __moneypunct_cache<_CharT, _Intl>;
00170         __tmp->_M_cache(__loc);
00171           }
00172         catch(...)
00173           {
00174         delete __tmp;
00175         __throw_exception_again;
00176           }
00177         __loc._M_impl->_M_install_cache(__tmp, __i);
00178       }
00179     return static_cast<
00180       const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
00181       }
00182     };
00183 
00184   template<typename _CharT>
00185     void
00186     __numpunct_cache<_CharT>::_M_cache(const locale& __loc)
00187     {
00188       _M_allocated = true;
00189 
00190       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
00191 
00192       _M_grouping_size = __np.grouping().size();
00193       char* __grouping = new char[_M_grouping_size];
00194       __np.grouping().copy(__grouping, _M_grouping_size);
00195       _M_grouping = __grouping;
00196       _M_use_grouping = _M_grouping_size && __np.grouping()[0] != 0;
00197 
00198       _M_truename_size = __np.truename().size();
00199       _CharT* __truename = new _CharT[_M_truename_size];
00200       __np.truename().copy(__truename, _M_truename_size);
00201       _M_truename = __truename;
00202 
00203       _M_falsename_size = __np.falsename().size();
00204       _CharT* __falsename = new _CharT[_M_falsename_size];
00205       __np.falsename().copy(__falsename, _M_falsename_size);
00206       _M_falsename = __falsename;
00207 
00208       _M_decimal_point = __np.decimal_point();
00209       _M_thousands_sep = __np.thousands_sep();
00210 
00211       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
00212       __ct.widen(__num_base::_S_atoms_out,
00213          __num_base::_S_atoms_out + __num_base::_S_oend, _M_atoms_out);
00214       __ct.widen(__num_base::_S_atoms_in,
00215          __num_base::_S_atoms_in + __num_base::_S_iend, _M_atoms_in);
00216     }
00217 
00218   template<typename _CharT, bool _Intl>
00219     void
00220     __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
00221     {
00222       _M_allocated = true;
00223 
00224       const moneypunct<_CharT, _Intl>& __mp =
00225     use_facet<moneypunct<_CharT, _Intl> >(__loc);
00226 
00227       _M_grouping_size = __mp.grouping().size();
00228       char* __grouping = new char[_M_grouping_size];
00229       __mp.grouping().copy(__grouping, _M_grouping_size);
00230       _M_grouping = __grouping;
00231       _M_use_grouping = _M_grouping_size && __mp.grouping()[0] != 0;
00232       
00233       _M_decimal_point = __mp.decimal_point();
00234       _M_thousands_sep = __mp.thousands_sep();
00235       _M_frac_digits = __mp.frac_digits();
00236       
00237       _M_curr_symbol_size = __mp.curr_symbol().size();
00238       _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size];
00239       __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
00240       _M_curr_symbol = __curr_symbol;
00241       
00242       _M_positive_sign_size = __mp.positive_sign().size();
00243       _CharT* __positive_sign = new _CharT[_M_positive_sign_size];
00244       __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
00245       _M_positive_sign = __positive_sign;
00246 
00247       _M_negative_sign_size = __mp.negative_sign().size();
00248       _CharT* __negative_sign = new _CharT[_M_negative_sign_size];
00249       __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
00250       _M_negative_sign = __negative_sign;
00251       
00252       _M_pos_format = __mp.pos_format();
00253       _M_neg_format = __mp.neg_format();
00254 
00255       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
00256       __ct.widen(money_base::_S_atoms,
00257          money_base::_S_atoms + money_base::_S_end, _M_atoms);
00258     }
00259 
00260 
00261   // Used by both numeric and monetary facets.
00262   // Check to make sure that the __grouping_tmp string constructed in
00263   // money_get or num_get matches the canonical grouping for a given
00264   // locale.
00265   // __grouping_tmp is parsed L to R
00266   // 1,222,444 == __grouping_tmp of "\1\3\3"
00267   // __grouping is parsed R to L
00268   // 1,222,444 == __grouping of "\3" == "\3\3\3"
00269   static bool
00270   __verify_grouping(const char* __grouping, size_t __grouping_size,
00271             const string& __grouping_tmp);
00272 
00273   template<typename _CharT, typename _InIter>
00274     _InIter
00275     num_get<_CharT, _InIter>::
00276     _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
00277              ios_base::iostate& __err, string& __xtrc) const
00278     {
00279       typedef char_traits<_CharT>           __traits_type;
00280       typedef __numpunct_cache<_CharT>                  __cache_type;
00281       __use_cache<__cache_type> __uc;
00282       const locale& __loc = __io._M_getloc();
00283       const __cache_type* __lc = __uc(__loc);
00284       const _CharT* __lit = __lc->_M_atoms_in;
00285       char_type __c = char_type();
00286 
00287       // True if __beg becomes equal to __end.
00288       bool __testeof = __beg == __end;
00289 
00290       // First check for sign.
00291       if (!__testeof)
00292     {
00293       __c = *__beg;
00294       const bool __plus = __c == __lit[__num_base::_S_iplus];
00295       if ((__plus || __c == __lit[__num_base::_S_iminus])
00296           && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00297           && !(__c == __lc->_M_decimal_point))
00298         {
00299           __xtrc += __plus ? '+' : '-';
00300           if (++__beg != __end)
00301         __c = *__beg;
00302           else
00303         __testeof = true;
00304         }
00305     }
00306 
00307       // Next, look for leading zeros.
00308       bool __found_mantissa = false;
00309       while (!__testeof)
00310     {
00311       if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
00312           || __c == __lc->_M_decimal_point)
00313         break;
00314       else if (__c == __lit[__num_base::_S_izero])
00315         {
00316           if (!__found_mantissa)
00317         {
00318           __xtrc += '0';
00319           __found_mantissa = true;
00320         }
00321           if (++__beg != __end)
00322         __c = *__beg;
00323           else
00324         __testeof = true;
00325         }
00326       else
00327         break;
00328     }
00329 
00330       // Only need acceptable digits for floating point numbers.
00331       bool __found_dec = false;
00332       bool __found_sci = false;
00333       string __found_grouping;
00334       if (__lc->_M_use_grouping)
00335     __found_grouping.reserve(32);
00336       int __sep_pos = 0;
00337       const char_type* __q;
00338       const char_type* __lit_zero = __lit + __num_base::_S_izero;
00339       while (!__testeof)
00340         {
00341       // According to 22.2.2.1.2, p8-9, first look for thousands_sep
00342       // and decimal_point.
00343           if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00344         {
00345           if (!__found_dec && !__found_sci)
00346         {
00347           // NB: Thousands separator at the beginning of a string
00348           // is a no-no, as is two consecutive thousands separators.
00349           if (__sep_pos)
00350             {
00351               __found_grouping += static_cast<char>(__sep_pos);
00352               __sep_pos = 0;
00353             }
00354           else
00355             {
00356               __err |= ios_base::failbit;
00357               break;
00358             }
00359         }
00360           else
00361         break;
00362             }
00363       else if (__c == __lc->_M_decimal_point)
00364         {
00365           if (!__found_dec && !__found_sci)
00366         {
00367           // If no grouping chars are seen, no grouping check
00368           // is applied. Therefore __found_grouping is adjusted
00369           // only if decimal_point comes after some thousands_sep.
00370           if (__found_grouping.size())
00371             __found_grouping += static_cast<char>(__sep_pos);
00372           __xtrc += '.';
00373           __found_dec = true;
00374         }
00375           else
00376         break;
00377         }
00378           else if ((__q = __traits_type::find(__lit_zero, 10, __c)))
00379         {
00380           __xtrc += __num_base::_S_atoms_in[__q - __lit];
00381           __found_mantissa = true;
00382           ++__sep_pos;
00383         }
00384       else if ((__c == __lit[__num_base::_S_ie] 
00385             || __c == __lit[__num_base::_S_iE])
00386            && __found_mantissa && !__found_sci)
00387         {
00388           // Scientific notation.
00389           if (__found_grouping.size() && !__found_dec)
00390         __found_grouping += static_cast<char>(__sep_pos);
00391           __xtrc += 'e';
00392           __found_sci = true;
00393 
00394           // Remove optional plus or minus sign, if they exist.
00395           if (++__beg != __end)
00396         {
00397           __c = *__beg;
00398           const bool __plus = __c == __lit[__num_base::_S_iplus];
00399           if ((__plus || __c == __lit[__num_base::_S_iminus])
00400               && !(__lc->_M_use_grouping
00401                && __c == __lc->_M_thousands_sep)
00402               && !(__c == __lc->_M_decimal_point))
00403             __xtrc += __plus ? '+' : '-';
00404           else
00405             continue;
00406         }
00407           else
00408         {
00409           __testeof = true;
00410           break;
00411         }
00412         }
00413       else
00414         // Not a valid input item.
00415         break;
00416 
00417       if (++__beg != __end)
00418         __c = *__beg;
00419       else
00420         __testeof = true;
00421         }
00422 
00423       // Digit grouping is checked. If grouping and found_grouping don't
00424       // match, then get very very upset, and set failbit.
00425       if (__found_grouping.size())
00426         {
00427           // Add the ending grouping if a decimal or 'e'/'E' wasn't found.
00428       if (!__found_dec && !__found_sci)
00429         __found_grouping += static_cast<char>(__sep_pos);
00430 
00431           if (!std::__verify_grouping(__lc->_M_grouping, 
00432                       __lc->_M_grouping_size,
00433                       __found_grouping))
00434         __err |= ios_base::failbit;
00435         }
00436 
00437       // Finish up.
00438       if (__testeof)
00439         __err |= ios_base::eofbit;
00440       return __beg;
00441     }
00442 
00443   template<typename _ValueT>
00444     struct __to_unsigned_type
00445     { typedef _ValueT __type; };
00446 
00447   template<>
00448     struct __to_unsigned_type<long>
00449     { typedef unsigned long __type; };
00450 
00451 #ifdef _GLIBCXX_USE_LONG_LONG
00452   template<>
00453     struct __to_unsigned_type<long long>
00454     { typedef unsigned long long __type; };
00455 #endif
00456 
00457   template<typename _CharT, typename _InIter>
00458     template<typename _ValueT>
00459       _InIter
00460       num_get<_CharT, _InIter>::
00461       _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
00462              ios_base::iostate& __err, _ValueT& __v) const
00463       {
00464         typedef char_traits<_CharT>              __traits_type;
00465     typedef typename __to_unsigned_type<_ValueT>::__type __unsigned_type;
00466     typedef __numpunct_cache<_CharT>                     __cache_type;
00467     __use_cache<__cache_type> __uc;
00468     const locale& __loc = __io._M_getloc();
00469     const __cache_type* __lc = __uc(__loc);
00470     const _CharT* __lit = __lc->_M_atoms_in;
00471     char_type __c = char_type();
00472 
00473     // NB: Iff __basefield == 0, __base can change based on contents.
00474     const ios_base::fmtflags __basefield = __io.flags()
00475                                            & ios_base::basefield;
00476     const bool __oct = __basefield == ios_base::oct;
00477     int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
00478 
00479     // True if __beg becomes equal to __end.
00480     bool __testeof = __beg == __end;
00481 
00482     // First check for sign.
00483     bool __negative = false;
00484     if (!__testeof)
00485       {
00486         __c = *__beg;
00487         if (numeric_limits<_ValueT>::is_signed)
00488           __negative = __c == __lit[__num_base::_S_iminus];
00489         if ((__negative || __c == __lit[__num_base::_S_iplus])
00490         && !(__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00491         && !(__c == __lc->_M_decimal_point))
00492           {
00493         if (++__beg != __end)
00494           __c = *__beg;
00495         else
00496           __testeof = true;
00497           }
00498       }
00499 
00500     // Next, look for leading zeros and check required digits
00501     // for base formats.
00502     bool __found_zero = false;
00503     while (!__testeof)
00504       {
00505         if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep
00506         || __c == __lc->_M_decimal_point)
00507           break;
00508         else if (__c == __lit[__num_base::_S_izero] 
00509              && (!__found_zero || __base == 10))
00510           __found_zero = true;
00511         else if (__found_zero)
00512           {
00513         if (__c == __lit[__num_base::_S_ix] 
00514             || __c == __lit[__num_base::_S_iX])
00515           {
00516             if (__basefield == 0)
00517               __base = 16;
00518             if (__base == 16)
00519               __found_zero = false;
00520             else
00521               break;
00522           }
00523         else
00524           {
00525             if (__basefield == 0)
00526               __base = 8;
00527             break;
00528           }
00529           }
00530         else
00531           break;
00532 
00533         if (++__beg != __end)
00534           {
00535         __c = *__beg;
00536         if (!__found_zero)
00537           break;
00538           }
00539         else
00540           __testeof = true;
00541       }
00542     
00543     // At this point, base is determined. If not hex, only allow
00544     // base digits as valid input.
00545     const size_t __len = (__base == 16 ? __num_base::_S_iend
00546                   - __num_base::_S_izero : __base);
00547 
00548     // Extract.
00549     string __found_grouping;
00550     if (__lc->_M_use_grouping)
00551       __found_grouping.reserve(32);
00552     int __sep_pos = 0;
00553     bool __overflow = false;
00554     const __unsigned_type __max = __negative ?
00555       -numeric_limits<_ValueT>::min() : numeric_limits<_ValueT>::max();
00556     const __unsigned_type __smax = __max / __base;
00557     __unsigned_type __result = 0;
00558     const char_type* __q;
00559     const char_type* __lit_zero = __lit + __num_base::_S_izero;
00560     while (!__testeof)
00561       {
00562         // According to 22.2.2.1.2, p8-9, first look for thousands_sep
00563         // and decimal_point.
00564         if (__lc->_M_use_grouping && __c == __lc->_M_thousands_sep)
00565           {
00566         // NB: Thousands separator at the beginning of a string
00567         // is a no-no, as is two consecutive thousands separators.
00568         if (__sep_pos)
00569           {
00570             __found_grouping += static_cast<char>(__sep_pos);
00571             __sep_pos = 0;
00572           }
00573         else
00574           {
00575             __err |= ios_base::failbit;
00576             break;
00577           }
00578           }
00579         else if (__c == __lc->_M_decimal_point)
00580           break;
00581         else if ((__q = __traits_type::find(__lit_zero, __len, __c)))
00582           {
00583         int __digit = __q - __lit_zero;
00584         if (__digit > 15)
00585           __digit -= 6;
00586         if (__result > __smax)
00587           __overflow = true;
00588         else
00589           {
00590             __result *= __base;
00591             __overflow |= __result > __max - __digit;
00592             __result += __digit;
00593             ++__sep_pos;
00594           }
00595           }
00596         else
00597           // Not a valid input item.          
00598           break;
00599         
00600         if (++__beg != __end)
00601           __c = *__beg;
00602         else
00603           __testeof = true;
00604       }
00605 
00606     // Digit grouping is checked. If grouping and found_grouping don't
00607     // match, then get very very upset, and set failbit.
00608     if (__found_grouping.size())
00609       {
00610         // Add the ending grouping.
00611         __found_grouping += static_cast<char>(__sep_pos);
00612 
00613         if (!std::__verify_grouping(__lc->_M_grouping,
00614                     __lc->_M_grouping_size,
00615                     __found_grouping))
00616           __err |= ios_base::failbit;
00617       }
00618 
00619     if (!(__err & ios_base::failbit) && !__overflow
00620         && (__sep_pos || __found_zero || __found_grouping.size()))
00621       __v = __negative ? -__result : __result;
00622     else
00623       __err |= ios_base::failbit;
00624 
00625     if (__testeof)
00626       __err |= ios_base::eofbit;
00627     return __beg;
00628       }
00629 
00630   // _GLIBCXX_RESOLVE_LIB_DEFECTS
00631   // 17.  Bad bool parsing
00632   template<typename _CharT, typename _InIter>
00633     _InIter
00634     num_get<_CharT, _InIter>::
00635     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00636            ios_base::iostate& __err, bool& __v) const
00637     {
00638       if (!(__io.flags() & ios_base::boolalpha))
00639         {
00640       // Parse bool values as long.
00641           // NB: We can't just call do_get(long) here, as it might
00642           // refer to a derived class.
00643       long __l = -1;
00644           __beg = _M_extract_int(__beg, __end, __io, __err, __l);
00645       if (__l == 0 || __l == 1)
00646         __v = __l;
00647       else
00648             __err |= ios_base::failbit;
00649         }
00650       else
00651         {
00652       // Parse bool values as alphanumeric.
00653       typedef __numpunct_cache<_CharT>              __cache_type;
00654       __use_cache<__cache_type> __uc;
00655       const locale& __loc = __io._M_getloc();
00656       const __cache_type* __lc = __uc(__loc);
00657 
00658       bool __testf = true;
00659       bool __testt = true;
00660       size_t __n;
00661       bool __testeof = __beg == __end;
00662           for (__n = 0; !__testeof; ++__n)
00663             {
00664           const char_type __c = *__beg;
00665 
00666           if (__testf)
00667         if (__n < __lc->_M_falsename_size)
00668           __testf = __c == __lc->_M_falsename[__n];
00669         else
00670           break;
00671 
00672           if (__testt)
00673         if (__n < __lc->_M_truename_size)
00674           __testt = __c == __lc->_M_truename[__n];
00675         else
00676           break;
00677 
00678           if (!__testf && !__testt)
00679         break;
00680           
00681           if (++__beg == __end)
00682         __testeof = true;
00683             }
00684       if (__testf && __n == __lc->_M_falsename_size)
00685         __v = 0;
00686       else if (__testt && __n == __lc->_M_truename_size)
00687         __v = 1;
00688       else
00689         __err |= ios_base::failbit;
00690 
00691           if (__testeof)
00692             __err |= ios_base::eofbit;
00693         }
00694       return __beg;
00695     }
00696 
00697   template<typename _CharT, typename _InIter>
00698     _InIter
00699     num_get<_CharT, _InIter>::
00700     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00701            ios_base::iostate& __err, long& __v) const
00702     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00703 
00704   template<typename _CharT, typename _InIter>
00705     _InIter
00706     num_get<_CharT, _InIter>::
00707     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00708            ios_base::iostate& __err, unsigned short& __v) const
00709     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00710 
00711   template<typename _CharT, typename _InIter>
00712     _InIter
00713     num_get<_CharT, _InIter>::
00714     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00715            ios_base::iostate& __err, unsigned int& __v) const
00716     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00717 
00718   template<typename _CharT, typename _InIter>
00719     _InIter
00720     num_get<_CharT, _InIter>::
00721     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00722            ios_base::iostate& __err, unsigned long& __v) const
00723     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00724 
00725 #ifdef _GLIBCXX_USE_LONG_LONG
00726   template<typename _CharT, typename _InIter>
00727     _InIter
00728     num_get<_CharT, _InIter>::
00729     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00730            ios_base::iostate& __err, long long& __v) const
00731     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00732 
00733   template<typename _CharT, typename _InIter>
00734     _InIter
00735     num_get<_CharT, _InIter>::
00736     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00737            ios_base::iostate& __err, unsigned long long& __v) const
00738     { return _M_extract_int(__beg, __end, __io, __err, __v); }
00739 #endif
00740 
00741   template<typename _CharT, typename _InIter>
00742     _InIter
00743     num_get<_CharT, _InIter>::
00744     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00745        ios_base::iostate& __err, float& __v) const
00746     {
00747       string __xtrc;
00748       __xtrc.reserve(32);
00749       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00750       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
00751       return __beg;
00752     }
00753 
00754   template<typename _CharT, typename _InIter>
00755     _InIter
00756     num_get<_CharT, _InIter>::
00757     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00758            ios_base::iostate& __err, double& __v) const
00759     {
00760       string __xtrc;
00761       __xtrc.reserve(32);
00762       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00763       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
00764       return __beg;
00765     }
00766 
00767   template<typename _CharT, typename _InIter>
00768     _InIter
00769     num_get<_CharT, _InIter>::
00770     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00771            ios_base::iostate& __err, long double& __v) const
00772     {
00773       string __xtrc;
00774       __xtrc.reserve(32);
00775       __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
00776       std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
00777       return __beg;
00778     }
00779 
00780   template<typename _CharT, typename _InIter>
00781     _InIter
00782     num_get<_CharT, _InIter>::
00783     do_get(iter_type __beg, iter_type __end, ios_base& __io,
00784            ios_base::iostate& __err, void*& __v) const
00785     {
00786       // Prepare for hex formatted input.
00787       typedef ios_base::fmtflags        fmtflags;
00788       const fmtflags __fmt = __io.flags();
00789       __io.flags(__fmt & ~ios_base::basefield | ios_base::hex);
00790 
00791       unsigned long __ul;
00792       __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
00793 
00794       // Reset from hex formatted input.
00795       __io.flags(__fmt);
00796 
00797       if (!(__err & ios_base::failbit))
00798     __v = reinterpret_cast<void*>(__ul);
00799       return __beg;
00800     }
00801 
00802   // For use by integer and floating-point types after they have been
00803   // converted into a char_type string.
00804   template<typename _CharT, typename _OutIter>
00805     void
00806     num_put<_CharT, _OutIter>::
00807     _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
00808        _CharT* __new, const _CharT* __cs, int& __len) const
00809     {
00810       // [22.2.2.2.2] Stage 3.
00811       // If necessary, pad.
00812       __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs,
00813                           __w, __len, true);
00814       __len = static_cast<int>(__w);
00815     }
00816 
00817   // Forwarding functions to peel signed from unsigned integer types.
00818   template<typename _CharT>
00819     inline int
00820     __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit,
00821           ios_base::fmtflags __flags)
00822     {
00823       unsigned long __ul = static_cast<unsigned long>(__v);
00824       if (__v < 0)
00825     __ul = -__ul;
00826       return __int_to_char(__bufend, __ul, __lit, __flags, false);
00827     }
00828 
00829   template<typename _CharT>
00830     inline int
00831     __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
00832           ios_base::fmtflags __flags)
00833     { return __int_to_char(__bufend, __v, __lit, __flags, false); }
00834 
00835 #ifdef _GLIBCXX_USE_LONG_LONG
00836   template<typename _CharT>
00837     inline int
00838     __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
00839           ios_base::fmtflags __flags)
00840     {
00841       unsigned long long __ull = static_cast<unsigned long long>(__v);
00842       if (__v < 0)
00843     __ull = -__ull;
00844       return __int_to_char(__bufend, __ull, __lit, __flags, false);
00845     }
00846 
00847   template<typename _CharT>
00848     inline int
00849     __int_to_char(_CharT* __bufend, unsigned long long __v, 
00850           const _CharT* __lit, ios_base::fmtflags __flags)
00851     { return __int_to_char(__bufend, __v, __lit, __flags, false); }
00852 #endif
00853 
00854   // N.B. The last argument is currently unused (see libstdc++/20914).
00855   template<typename _CharT, typename _ValueT>
00856     int
00857     __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
00858           ios_base::fmtflags __flags, bool)
00859     {
00860       const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
00861       _CharT* __buf = __bufend;
00862 
00863       if (__builtin_expect(__basefield != ios_base::oct
00864                && __basefield != ios_base::hex, true))
00865     {
00866       // Decimal.
00867       do
00868         {
00869           *--__buf = __lit[(__v % 10) + __num_base::_S_odigits];
00870           __v /= 10;
00871         }
00872       while (__v != 0);
00873     }
00874       else if (__basefield == ios_base::oct)
00875     {
00876       // Octal.
00877       do
00878         {
00879           *--__buf = __lit[(__v & 0x7) + __num_base::_S_odigits];
00880           __v >>= 3;
00881         }
00882       while (__v != 0);
00883     }
00884       else
00885     {
00886       // Hex.
00887       const bool __uppercase = __flags & ios_base::uppercase;
00888       const int __case_offset = __uppercase ? __num_base::_S_oudigits
00889                                             : __num_base::_S_odigits;
00890       do
00891         {
00892           *--__buf = __lit[(__v & 0xf) + __case_offset];
00893           __v >>= 4;
00894         }
00895       while (__v != 0);
00896     }
00897       return __bufend - __buf;
00898     }
00899 
00900   template<typename _CharT, typename _OutIter>
00901     void
00902     num_put<_CharT, _OutIter>::
00903     _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
00904          ios_base&, _CharT* __new, _CharT* __cs, int& __len) const
00905     {
00906       _CharT* __p = std::__add_grouping(__new, __sep, __grouping,
00907                     __grouping_size, __cs, __cs + __len);
00908       __len = __p - __new;
00909     }
00910   
00911   template<typename _CharT, typename _OutIter>
00912     template<typename _ValueT>
00913       _OutIter
00914       num_put<_CharT, _OutIter>::
00915       _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
00916             _ValueT __v) const
00917       {
00918     typedef __numpunct_cache<_CharT>            __cache_type;
00919     __use_cache<__cache_type> __uc;
00920     const locale& __loc = __io._M_getloc();
00921     const __cache_type* __lc = __uc(__loc);
00922     const _CharT* __lit = __lc->_M_atoms_out;
00923     const ios_base::fmtflags __flags = __io.flags();
00924 
00925     // Long enough to hold hex, dec, and octal representations.
00926     const int __ilen = 5 * sizeof(_ValueT);
00927     _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
00928                                  * __ilen));
00929 
00930     // [22.2.2.2.2] Stage 1, numeric conversion to character.
00931     // Result is returned right-justified in the buffer.
00932     int __len = __int_to_char(__cs + __ilen, __v, __lit, __flags);
00933     __cs += __ilen - __len;
00934 
00935     // Add grouping, if necessary.
00936     if (__lc->_M_use_grouping)
00937       {
00938         // Grouping can add (almost) as many separators as the number
00939         // of digits + space is reserved for numeric base or sign.
00940         _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
00941                                   * (__len + 1)
00942                                   * 2));
00943         _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
00944              __lc->_M_thousands_sep, __io, __cs2 + 2, __cs, __len);
00945         __cs = __cs2 + 2;
00946       }
00947 
00948     // Complete Stage 1, prepend numeric base or sign.
00949     const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
00950     if (__builtin_expect(__basefield != ios_base::oct
00951                  && __basefield != ios_base::hex, true))
00952       {
00953         // Decimal.
00954         if (__v > 0)
00955           {
00956         if (__flags & ios_base::showpos
00957             && numeric_limits<_ValueT>::is_signed)
00958           *--__cs = __lit[__num_base::_S_oplus], ++__len;
00959           }
00960         else if (__v)
00961           *--__cs = __lit[__num_base::_S_ominus], ++__len;
00962       }
00963     else if (__basefield == ios_base::oct)
00964       {
00965         // Octal.
00966         if (__flags & ios_base::showbase && __v)
00967           *--__cs = __lit[__num_base::_S_odigits], ++__len;
00968       }
00969     else
00970       {
00971         // Hex.
00972         if (__flags & ios_base::showbase && __v)
00973           {
00974         // 'x' or 'X'
00975         const bool __uppercase = __flags & ios_base::uppercase;
00976         *--__cs = __lit[__num_base::_S_ox + __uppercase];
00977         // '0'
00978         *--__cs = __lit[__num_base::_S_odigits];
00979         __len += 2;
00980           }
00981       }
00982 
00983     // Pad.
00984     const streamsize __w = __io.width();
00985     if (__w > static_cast<streamsize>(__len))
00986       {
00987         _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
00988                                   * __w));
00989         _M_pad(__fill, __w, __io, __cs3, __cs, __len);
00990         __cs = __cs3;
00991       }
00992     __io.width(0);
00993 
00994     // [22.2.2.2.2] Stage 4.
00995     // Write resulting, fully-formatted string to output iterator.
00996     return std::__write(__s, __cs, __len);
00997       }
00998 
00999   template<typename _CharT, typename _OutIter>
01000     void
01001     num_put<_CharT, _OutIter>::
01002     _M_group_float(const char* __grouping, size_t __grouping_size,
01003            _CharT __sep, const _CharT* __p, _CharT* __new,
01004            _CharT* __cs, int& __len) const
01005     {
01006       // _GLIBCXX_RESOLVE_LIB_DEFECTS
01007       // 282. What types does numpunct grouping refer to?
01008       // Add grouping, if necessary.
01009       const int __declen = __p ? __p - __cs : __len;
01010       _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping,
01011                      __grouping_size,
01012                      __cs, __cs + __declen);
01013 
01014       // Tack on decimal part.
01015       int __newlen = __p2 - __new;
01016       if (__p)
01017     {
01018       char_traits<_CharT>::copy(__p2, __p, __len - __declen);
01019       __newlen += __len - __declen;
01020     }
01021       __len = __newlen;
01022     }
01023 
01024   // The following code uses snprintf (or sprintf(), when
01025   // _GLIBCXX_USE_C99 is not defined) to convert floating point values
01026   // for insertion into a stream.  An optimization would be to replace
01027   // them with code that works directly on a wide buffer and then use
01028   // __pad to do the padding.  It would be good to replace them anyway
01029   // to gain back the efficiency that C++ provides by knowing up front
01030   // the type of the values to insert.  Also, sprintf is dangerous
01031   // since may lead to accidental buffer overruns.  This
01032   // implementation follows the C++ standard fairly directly as
01033   // outlined in 22.2.2.2 [lib.locale.num.put]
01034   template<typename _CharT, typename _OutIter>
01035     template<typename _ValueT>
01036       _OutIter
01037       num_put<_CharT, _OutIter>::
01038       _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
01039                _ValueT __v) const
01040       {
01041     typedef __numpunct_cache<_CharT>                __cache_type;
01042     __use_cache<__cache_type> __uc;
01043     const locale& __loc = __io._M_getloc();
01044     const __cache_type* __lc = __uc(__loc);
01045 
01046     // Use default precision if out of range.
01047     streamsize __prec = __io.precision();
01048     if (__prec < static_cast<streamsize>(0))
01049       __prec = static_cast<streamsize>(6);
01050 
01051     const int __max_digits = numeric_limits<_ValueT>::digits10;
01052 
01053     // [22.2.2.2.2] Stage 1, numeric conversion to character.
01054     int __len;
01055     // Long enough for the max format spec.
01056     char __fbuf[16];
01057 
01058 #ifdef _GLIBCXX_USE_C99
01059     // First try a buffer perhaps big enough (most probably sufficient
01060     // for non-ios_base::fixed outputs)
01061     int __cs_size = __max_digits * 3;
01062     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01063 
01064     __num_base::_S_format_float(__io, __fbuf, __mod);
01065     __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
01066                       _S_get_c_locale(), __prec);
01067 
01068     // If the buffer was not large enough, try again with the correct size.
01069     if (__len >= __cs_size)
01070       {
01071         __cs_size = __len + 1;
01072         __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01073         __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
01074                       _S_get_c_locale(), __prec);
01075       }
01076 #else
01077     // Consider the possibility of long ios_base::fixed outputs
01078     const bool __fixed = __io.flags() & ios_base::fixed;
01079     const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
01080 
01081     // The size of the output string is computed as follows.
01082     // ios_base::fixed outputs may need up to __max_exp + 1 chars
01083     // for the integer part + __prec chars for the fractional part
01084     // + 3 chars for sign, decimal point, '\0'. On the other hand,
01085     // for non-fixed outputs __max_digits * 2 + __prec chars are
01086     // largely sufficient.
01087     const int __cs_size = __fixed ? __max_exp + __prec + 4
01088                                   : __max_digits * 2 + __prec;
01089     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01090 
01091     __num_base::_S_format_float(__io, __fbuf, __mod);
01092     __len = std::__convert_from_v(__cs, 0, __fbuf, __v,
01093                       _S_get_c_locale(), __prec);
01094 #endif
01095 
01096     // [22.2.2.2.2] Stage 2, convert to char_type, using correct
01097     // numpunct.decimal_point() values for '.' and adding grouping.
01098     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01099     
01100     _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01101                                  * __len));
01102     __ctype.widen(__cs, __cs + __len, __ws);
01103     
01104     // Replace decimal point.
01105     const _CharT __cdec = __ctype.widen('.');
01106     const _CharT __dec = __lc->_M_decimal_point;
01107     const _CharT* __p = char_traits<_CharT>::find(__ws, __len, __cdec);
01108     if (__p)
01109       __ws[__p - __ws] = __dec;
01110     
01111     // Add grouping, if necessary.
01112     // N.B. Make sure to not group things like 2e20, i.e., no decimal
01113     // point, scientific notation.
01114     if (__lc->_M_use_grouping
01115         && (__p || __len < 3 || (__cs[1] <= '9' && __cs[2] <= '9'
01116                      && __cs[1] >= '0' && __cs[2] >= '0')))
01117       {
01118         // Grouping can add (almost) as many separators as the
01119         // number of digits, but no more.
01120         _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01121                                   * __len * 2));
01122         
01123         streamsize __off = 0;
01124         if (__cs[0] == '-' || __cs[0] == '+')
01125           {
01126         __off = 1;
01127         __ws2[0] = __ws[0];
01128         __len -= 1;
01129           }
01130         
01131         _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
01132                __lc->_M_thousands_sep, __p, __ws2 + __off,
01133                __ws + __off, __len);
01134         __len += __off;
01135         
01136         __ws = __ws2;
01137       }
01138 
01139     // Pad.
01140     const streamsize __w = __io.width();
01141     if (__w > static_cast<streamsize>(__len))
01142       {
01143         _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01144                                   * __w));
01145         _M_pad(__fill, __w, __io, __ws3, __ws, __len);
01146         __ws = __ws3;
01147       }
01148     __io.width(0);
01149     
01150     // [22.2.2.2.2] Stage 4.
01151     // Write resulting, fully-formatted string to output iterator.
01152     return std::__write(__s, __ws, __len);
01153       }
01154   
01155   template<typename _CharT, typename _OutIter>
01156     _OutIter
01157     num_put<_CharT, _OutIter>::
01158     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
01159     {
01160       const ios_base::fmtflags __flags = __io.flags();
01161       if ((__flags & ios_base::boolalpha) == 0)
01162         {
01163           const long __l = __v;
01164           __s = _M_insert_int(__s, __io, __fill, __l);
01165         }
01166       else
01167         {
01168       typedef __numpunct_cache<_CharT>              __cache_type;
01169       __use_cache<__cache_type> __uc;
01170       const locale& __loc = __io._M_getloc();
01171       const __cache_type* __lc = __uc(__loc);
01172 
01173       const _CharT* __name = __v ? __lc->_M_truename
01174                                  : __lc->_M_falsename;
01175       int __len = __v ? __lc->_M_truename_size
01176                       : __lc->_M_falsename_size;
01177 
01178       const streamsize __w = __io.width();
01179       if (__w > static_cast<streamsize>(__len))
01180         {
01181           _CharT* __cs
01182         = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01183                             * __w));
01184           _M_pad(__fill, __w, __io, __cs, __name, __len);
01185           __name = __cs;
01186         }
01187       __io.width(0);
01188       __s = std::__write(__s, __name, __len);
01189     }
01190       return __s;
01191     }
01192 
01193   template<typename _CharT, typename _OutIter>
01194     _OutIter
01195     num_put<_CharT, _OutIter>::
01196     do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
01197     { return _M_insert_int(__s, __io, __fill, __v); }
01198 
01199   template<typename _CharT, typename _OutIter>
01200     _OutIter
01201     num_put<_CharT, _OutIter>::
01202     do_put(iter_type __s, ios_base& __io, char_type __fill,
01203            unsigned long __v) const
01204     { return _M_insert_int(__s, __io, __fill, __v); }
01205 
01206 #ifdef _GLIBCXX_USE_LONG_LONG
01207   template<typename _CharT, typename _OutIter>
01208     _OutIter
01209     num_put<_CharT, _OutIter>::
01210     do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
01211     { return _M_insert_int(__s, __b, __fill, __v); }
01212 
01213   template<typename _CharT, typename _OutIter>
01214     _OutIter
01215     num_put<_CharT, _OutIter>::
01216     do_put(iter_type __s, ios_base& __io, char_type __fill,
01217            unsigned long long __v) const
01218     { return _M_insert_int(__s, __io, __fill, __v); }
01219 #endif
01220 
01221   template<typename _CharT, typename _OutIter>
01222     _OutIter
01223     num_put<_CharT, _OutIter>::
01224     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
01225     { return _M_insert_float(__s, __io, __fill, char(), __v); }
01226 
01227   template<typename _CharT, typename _OutIter>
01228     _OutIter
01229     num_put<_CharT, _OutIter>::
01230     do_put(iter_type __s, ios_base& __io, char_type __fill,
01231        long double __v) const
01232     { return _M_insert_float(__s, __io, __fill, 'L', __v); }
01233 
01234   template<typename _CharT, typename _OutIter>
01235     _OutIter
01236     num_put<_CharT, _OutIter>::
01237     do_put(iter_type __s, ios_base& __io, char_type __fill,
01238            const void* __v) const
01239     {
01240       const ios_base::fmtflags __flags = __io.flags();
01241       const ios_base::fmtflags __fmt = ~(ios_base::basefield
01242                      | ios_base::uppercase
01243                      | ios_base::internal);
01244       __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
01245 
01246       __s = _M_insert_int(__s, __io, __fill,
01247               reinterpret_cast<unsigned long>(__v));
01248       __io.flags(__flags);
01249       return __s;
01250     }
01251 
01252   template<typename _CharT, typename _InIter>
01253     template<bool _Intl>
01254       _InIter
01255       money_get<_CharT, _InIter>::
01256       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
01257          ios_base::iostate& __err, string& __units) const
01258       {
01259     typedef char_traits<_CharT>           __traits_type;
01260     typedef typename string_type::size_type           size_type;    
01261     typedef money_base::part              part;
01262     typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
01263     
01264     const locale& __loc = __io._M_getloc();
01265     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01266 
01267     __use_cache<__cache_type> __uc;
01268     const __cache_type* __lc = __uc(__loc);
01269     const char_type* __lit = __lc->_M_atoms;
01270 
01271     // Deduced sign.
01272     bool __negative = false;
01273     // Sign size.
01274     size_type __sign_size = 0;
01275     // True if sign is mandatory.
01276     const bool __mandatory_sign = (__lc->_M_positive_sign_size
01277                        && __lc->_M_negative_sign_size);
01278     // String of grouping info from thousands_sep plucked from __units.
01279     string __grouping_tmp;
01280     if (__lc->_M_use_grouping)
01281       __grouping_tmp.reserve(32);
01282     // Last position before the decimal point.
01283     int __last_pos = 0;
01284     // Separator positions, then, possibly, fractional digits.
01285     int __n = 0;
01286     // If input iterator is in a valid state.
01287     bool __testvalid = true;
01288     // Flag marking when a decimal point is found.
01289     bool __testdecfound = false;
01290 
01291     // The tentative returned string is stored here.
01292     string __res;
01293     __res.reserve(32);
01294 
01295     const char_type* __lit_zero = __lit + money_base::_S_zero;
01296     const money_base::pattern __p = __lc->_M_neg_format;
01297     for (int __i = 0; __i < 4 && __testvalid; ++__i)
01298       {
01299         const part __which = static_cast<part>(__p.field[__i]);
01300         switch (__which)
01301           {
01302           case money_base::symbol:
01303         // According to 22.2.6.1.2, p2, symbol is required
01304         // if (__io.flags() & ios_base::showbase), otherwise
01305         // is optional and consumed only if other characters
01306         // are needed to complete the format.
01307         if (__io.flags() & ios_base::showbase || __sign_size > 1
01308             || __i == 0
01309             || (__i == 1 && (__mandatory_sign
01310                      || (static_cast<part>(__p.field[0])
01311                      == money_base::sign)
01312                      || (static_cast<part>(__p.field[2])
01313                      == money_base::space)))
01314             || (__i == 2 && ((static_cast<part>(__p.field[3])
01315                       == money_base::value)
01316                      || __mandatory_sign
01317                      && (static_cast<part>(__p.field[3])
01318                      == money_base::sign))))
01319           {
01320             const size_type __len = __lc->_M_curr_symbol_size;
01321             size_type __j = 0;
01322             for (; __beg != __end && __j < __len
01323                && *__beg == __lc->_M_curr_symbol[__j];
01324              ++__beg, ++__j);
01325             if (__j != __len
01326             && (__j || __io.flags() & ios_base::showbase))
01327               __testvalid = false;
01328           }
01329         break;
01330           case money_base::sign:
01331         // Sign might not exist, or be more than one character long.
01332         if (__lc->_M_positive_sign_size && __beg != __end
01333             && *__beg == __lc->_M_positive_sign[0])
01334           {
01335             __sign_size = __lc->_M_positive_sign_size;
01336             ++__beg;
01337           }
01338         else if (__lc->_M_negative_sign_size && __beg != __end
01339              && *__beg == __lc->_M_negative_sign[0])
01340           {
01341             __negative = true;
01342             __sign_size = __lc->_M_negative_sign_size;
01343             ++__beg;
01344           }
01345         else if (__lc->_M_positive_sign_size
01346              && !__lc->_M_negative_sign_size)
01347           // "... if no sign is detected, the result is given the sign
01348           // that corresponds to the source of the empty string"
01349           __negative = true;
01350         else if (__mandatory_sign)
01351           __testvalid = false;
01352         break;
01353           case money_base::value:
01354         // Extract digits, remove and stash away the
01355         // grouping of found thousands separators.
01356         for (; __beg != __end; ++__beg)
01357           {
01358             const char_type __c = *__beg;
01359             const char_type* __q = __traits_type::find(__lit_zero, 
01360                                    10, __c);
01361             if (__q != 0)
01362               {
01363             __res += money_base::_S_atoms[__q - __lit];
01364             ++__n;
01365               }
01366             else if (__c == __lc->_M_decimal_point 
01367                  && !__testdecfound)
01368               {
01369             __last_pos = __n;
01370             __n = 0;
01371             __testdecfound = true;
01372               }
01373             else if (__lc->_M_use_grouping
01374                  && __c == __lc->_M_thousands_sep
01375                  && !__testdecfound)
01376               {
01377             if (__n)
01378               {
01379                 // Mark position for later analysis.
01380                 __grouping_tmp += static_cast<char>(__n);
01381                 __n = 0;
01382               }
01383             else
01384               {
01385                 __testvalid = false;
01386                 break;
01387               }
01388               }
01389             else
01390               break;
01391           }
01392         if (__res.empty())
01393           __testvalid = false;
01394         break;
01395           case money_base::space:
01396         // At least one space is required.
01397         if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
01398           ++__beg;
01399         else
01400           __testvalid = false;
01401           case money_base::none:
01402         // Only if not at the end of the pattern.
01403         if (__i != 3)
01404           for (; __beg != __end
01405              && __ctype.is(ctype_base::space, *__beg); ++__beg);
01406         break;
01407           }
01408       }
01409 
01410     // Need to get the rest of the sign characters, if they exist.
01411     if (__sign_size > 1 && __testvalid)
01412       {
01413         const char_type* __sign = __negative ? __lc->_M_negative_sign
01414                                              : __lc->_M_positive_sign;
01415         size_type __i = 1;
01416         for (; __beg != __end && __i < __sign_size
01417            && *__beg == __sign[__i]; ++__beg, ++__i);
01418         
01419         if (__i != __sign_size)
01420           __testvalid = false;
01421       }
01422 
01423     if (__testvalid)
01424       {
01425         // Strip leading zeros.
01426         if (__res.size() > 1)
01427           {
01428         const size_type __first = __res.find_first_not_of('0');
01429         const bool __only_zeros = __first == string::npos;
01430         if (__first)
01431           __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
01432           }
01433 
01434         // 22.2.6.1.2, p4
01435         if (__negative && __res[0] != '0')
01436           __res.insert(__res.begin(), '-');
01437         
01438         // Test for grouping fidelity.
01439         if (__grouping_tmp.size())
01440           {
01441         // Add the ending grouping.
01442         __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
01443                                            : __n);
01444         if (!std::__verify_grouping(__lc->_M_grouping,
01445                         __lc->_M_grouping_size,
01446                         __grouping_tmp))
01447           __testvalid = false;
01448           }
01449         
01450         // Iff not enough digits were supplied after the decimal-point.
01451         if (__testdecfound && __lc->_M_frac_digits > 0
01452         && __n != __lc->_M_frac_digits)
01453           __testvalid = false;
01454       }
01455     
01456     // Iff valid sequence is not recognized.
01457     if (!__testvalid)
01458       __err |= ios_base::failbit;
01459     else
01460       __units.swap(__res);
01461     
01462     // Iff no more characters are available.
01463     if (__beg == __end)
01464       __err |= ios_base::eofbit;
01465     return __beg;
01466       }
01467 
01468   template<typename _CharT, typename _InIter>
01469     _InIter
01470     money_get<_CharT, _InIter>::
01471     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
01472        ios_base::iostate& __err, long double& __units) const
01473     {
01474       string __str;
01475       if (__intl)
01476     __beg = _M_extract<true>(__beg, __end, __io, __err, __str);
01477       else
01478     __beg = _M_extract<false>(__beg, __end, __io, __err, __str);
01479       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
01480       return __beg;
01481     }
01482 
01483   template<typename _CharT, typename _InIter>
01484     _InIter
01485     money_get<_CharT, _InIter>::
01486     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
01487        ios_base::iostate& __err, string_type& __units) const
01488     {
01489       typedef typename string::size_type                  size_type;
01490 
01491       const locale& __loc = __io._M_getloc();
01492       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01493 
01494       string __str;
01495       const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io,
01496                             __err, __str)
01497                                  : _M_extract<false>(__beg, __end, __io,
01498                              __err, __str);
01499       const size_type __len = __str.size();
01500       if (__len)
01501     {
01502       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01503                                    * __len));
01504       __ctype.widen(__str.data(), __str.data() + __len, __ws);
01505       __units.assign(__ws, __len);
01506     }
01507 
01508       return __ret;
01509     }
01510 
01511   template<typename _CharT, typename _OutIter>
01512     template<bool _Intl>
01513       _OutIter
01514       money_put<_CharT, _OutIter>::
01515       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
01516         const string_type& __digits) const
01517       {
01518     typedef typename string_type::size_type           size_type;
01519     typedef money_base::part                          part;
01520     typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
01521       
01522     const locale& __loc = __io._M_getloc();
01523     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01524 
01525     __use_cache<__cache_type> __uc;
01526     const __cache_type* __lc = __uc(__loc);
01527     const char_type* __lit = __lc->_M_atoms;
01528 
01529     // Determine if negative or positive formats are to be used, and
01530     // discard leading negative_sign if it is present.
01531     const char_type* __beg = __digits.data();
01532 
01533     money_base::pattern __p;
01534     const char_type* __sign;
01535     size_type __sign_size;
01536     if (!(*__beg == __lit[money_base::_S_minus]))
01537       {
01538         __p = __lc->_M_pos_format;
01539         __sign = __lc->_M_positive_sign;
01540         __sign_size = __lc->_M_positive_sign_size;
01541       }
01542     else
01543       {
01544         __p = __lc->_M_neg_format;
01545         __sign = __lc->_M_negative_sign;
01546         __sign_size = __lc->_M_negative_sign_size;
01547         if (__digits.size())
01548           ++__beg;
01549       }
01550        
01551     // Look for valid numbers in the ctype facet within input digits.
01552     size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
01553                        __beg + __digits.size()) - __beg;
01554     if (__len)
01555       {
01556         // Assume valid input, and attempt to format.
01557         // Break down input numbers into base components, as follows:
01558         //   final_value = grouped units + (decimal point) + (digits)
01559         string_type __value;
01560         __value.reserve(2 * __len);
01561 
01562         // Add thousands separators to non-decimal digits, per
01563         // grouping rules.
01564         int __paddec = __len - __lc->_M_frac_digits;
01565         if (__paddec > 0)
01566           {
01567         if (__lc->_M_frac_digits < 0)
01568           __paddec = __len;
01569         if (__lc->_M_grouping_size)
01570           {
01571             _CharT* __ws =
01572               static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01573                                 * 2 * __len));
01574             _CharT* __ws_end =
01575               std::__add_grouping(__ws, __lc->_M_thousands_sep,
01576                       __lc->_M_grouping,
01577                       __lc->_M_grouping_size,
01578                       __beg, __beg + __paddec);
01579             __value.assign(__ws, __ws_end - __ws);
01580           }
01581         else
01582           __value.assign(__beg, __paddec);
01583           }
01584 
01585         // Deal with decimal point, decimal digits.
01586         if (__lc->_M_frac_digits > 0)
01587           {
01588         __value += __lc->_M_decimal_point;
01589         if (__paddec >= 0)
01590           __value.append(__beg + __paddec, __lc->_M_frac_digits);
01591         else
01592           {
01593             // Have to pad zeros in the decimal position.
01594             __value.append(-__paddec, __lit[money_base::_S_zero]);
01595             __value.append(__beg, __len);
01596           }
01597           }
01598   
01599         // Calculate length of resulting string.
01600         const ios_base::fmtflags __f = __io.flags() 
01601                                        & ios_base::adjustfield;
01602         __len = __value.size() + __sign_size;
01603         __len += ((__io.flags() & ios_base::showbase)
01604               ? __lc->_M_curr_symbol_size : 0);
01605 
01606         string_type __res;
01607         __res.reserve(2 * __len);
01608         
01609         const size_type __width = static_cast<size_type>(__io.width());  
01610         const bool __testipad = (__f == ios_base::internal
01611                      && __len < __width);
01612         // Fit formatted digits into the required pattern.
01613         for (int __i = 0; __i < 4; ++__i)
01614           {
01615         const part __which = static_cast<part>(__p.field[__i]);
01616         switch (__which)
01617           {
01618           case money_base::symbol:
01619             if (__io.flags() & ios_base::showbase)
01620               __res.append(__lc->_M_curr_symbol,
01621                    __lc->_M_curr_symbol_size);
01622             break;
01623           case money_base::sign:
01624             // Sign might not exist, or be more than one
01625             // charater long. In that case, add in the rest
01626             // below.
01627             if (__sign_size)
01628               __res += __sign[0];
01629             break;
01630           case money_base::value:
01631             __res += __value;
01632             break;
01633           case money_base::space:
01634             // At least one space is required, but if internal
01635             // formatting is required, an arbitrary number of
01636             // fill spaces will be necessary.
01637             if (__testipad)
01638               __res.append(__width - __len, __fill);
01639             else
01640               __res += __fill;
01641             break;
01642           case money_base::none:
01643             if (__testipad)
01644               __res.append(__width - __len, __fill);
01645             break;
01646           }
01647           }
01648         
01649         // Special case of multi-part sign parts.
01650         if (__sign_size > 1)
01651           __res.append(__sign + 1, __sign_size - 1);
01652         
01653         // Pad, if still necessary.
01654         __len = __res.size();
01655         if (__width > __len)
01656           {
01657         if (__f == ios_base::left)
01658           // After.
01659           __res.append(__width - __len, __fill);
01660         else
01661           // Before.
01662           __res.insert(0, __width - __len, __fill);
01663         __len = __width;
01664           }
01665         
01666         // Write resulting, fully-formatted string to output iterator.
01667         __s = std::__write(__s, __res.data(), __len);
01668       }
01669     __io.width(0);
01670     return __s;    
01671       }
01672   
01673   template<typename _CharT, typename _OutIter>
01674     _OutIter
01675     money_put<_CharT, _OutIter>::
01676     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01677        long double __units) const
01678     {
01679       const locale __loc = __io.getloc();
01680       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01681 #ifdef _GLIBCXX_USE_C99
01682       // First try a buffer perhaps big enough.
01683       int __cs_size = 64;
01684       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01685       // _GLIBCXX_RESOLVE_LIB_DEFECTS
01686       // 328. Bad sprintf format modifier in money_put<>::do_put()
01687       int __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
01688                     _S_get_c_locale(), 0);
01689       // If the buffer was not large enough, try again with the correct size.
01690       if (__len >= __cs_size)
01691     {
01692       __cs_size = __len + 1;
01693       __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01694       __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
01695                     _S_get_c_locale(), 0);
01696     }
01697 #else
01698       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
01699       const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
01700       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01701       int __len = std::__convert_from_v(__cs, 0, "%.*Lf", __units,
01702                     _S_get_c_locale(), 0);
01703 #endif
01704       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01705                                * __cs_size));
01706       __ctype.widen(__cs, __cs + __len, __ws);
01707       const string_type __digits(__ws, __len);
01708       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
01709                 : _M_insert<false>(__s, __io, __fill, __digits);
01710     }
01711 
01712   template<typename _CharT, typename _OutIter>
01713     _OutIter
01714     money_put<_CharT, _OutIter>::
01715     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01716        const string_type& __digits) const
01717     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
01718                 : _M_insert<false>(__s, __io, __fill, __digits); }
01719 
01720 
01721   // NB: Not especially useful. Without an ios_base object or some
01722   // kind of locale reference, we are left clawing at the air where
01723   // the side of the mountain used to be...
01724   template<typename _CharT, typename _InIter>
01725     time_base::dateorder
01726     time_get<_CharT, _InIter>::do_date_order() const
01727     { return time_base::no_order; }
01728 
01729   // Expand a strftime format string and parse it.  E.g., do_get_date() may
01730   // pass %m/%d/%Y => extracted characters.
01731   template<typename _CharT, typename _InIter>
01732     _InIter
01733     time_get<_CharT, _InIter>::
01734     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
01735               ios_base::iostate& __err, tm* __tm,
01736               const _CharT* __format) const
01737     {
01738       const locale& __loc = __io._M_getloc();
01739       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01740       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01741       const size_t __len = char_traits<_CharT>::length(__format);
01742 
01743       for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
01744     {
01745       if (__ctype.narrow(__format[__i], 0) == '%')
01746         {
01747           // Verify valid formatting code, attempt to extract.
01748           char __c = __ctype.narrow(__format[++__i], 0);
01749           int __mem = 0;
01750           if (__c == 'E' || __c == 'O')
01751         __c = __ctype.narrow(__format[++__i], 0);
01752           switch (__c)
01753         {
01754           const char* __cs;
01755           _CharT __wcs[10];
01756         case 'a':
01757           // Abbreviated weekday name [tm_wday]
01758           const char_type*  __days1[7];
01759           __tp._M_days_abbreviated(__days1);
01760           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
01761                       7, __io, __err);
01762           break;
01763         case 'A':
01764           // Weekday name [tm_wday].
01765           const char_type*  __days2[7];
01766           __tp._M_days(__days2);
01767           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
01768                       7, __io, __err);
01769           break;
01770         case 'h':
01771         case 'b':
01772           // Abbreviated month name [tm_mon]
01773           const char_type*  __months1[12];
01774           __tp._M_months_abbreviated(__months1);
01775           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
01776                       __months1, 12, __io, __err);
01777           break;
01778         case 'B':
01779           // Month name [tm_mon].
01780           const char_type*  __months2[12];
01781           __tp._M_months(__months2);
01782           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
01783                       __months2, 12, __io, __err);
01784           break;
01785         case 'c':
01786           // Default time and date representation.
01787           const char_type*  __dt[2];
01788           __tp._M_date_time_formats(__dt);
01789           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01790                         __tm, __dt[0]);
01791           break;
01792         case 'd':
01793           // Day [01, 31]. [tm_mday]
01794           __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
01795                      __io, __err);
01796           break;
01797         case 'e':
01798           // Day [1, 31], with single digits preceded by
01799           // space. [tm_mday]
01800           if (__ctype.is(ctype_base::space, *__beg))
01801             __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
01802                        1, __io, __err);
01803           else
01804             __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
01805                        2, __io, __err);
01806           break;
01807         case 'D':
01808           // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
01809           __cs = "%m/%d/%y";
01810           __ctype.widen(__cs, __cs + 9, __wcs);
01811           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01812                         __tm, __wcs);
01813           break;
01814         case 'H':
01815           // Hour [00, 23]. [tm_hour]
01816           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
01817                      __io, __err);
01818           break;
01819         case 'I':
01820           // Hour [01, 12]. [tm_hour]
01821           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
01822                      __io, __err);
01823           break;
01824         case 'm':
01825           // Month [01, 12]. [tm_mon]
01826           __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
01827                      __io, __err);
01828           if (!__err)
01829             __tm->tm_mon = __mem - 1;
01830           break;
01831         case 'M':
01832           // Minute [00, 59]. [tm_min]
01833           __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
01834                      __io, __err);
01835           break;
01836         case 'n':
01837           if (__ctype.narrow(*__beg, 0) == '\n')
01838             ++__beg;
01839           else
01840             __err |= ios_base::failbit;
01841           break;
01842         case 'R':
01843           // Equivalent to (%H:%M).
01844           __cs = "%H:%M";
01845           __ctype.widen(__cs, __cs + 6, __wcs);
01846           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01847                         __tm, __wcs);
01848           break;
01849         case 'S':
01850           // Seconds. [tm_sec]
01851           // [00, 60] in C99 (one leap-second), [00, 61] in C89.
01852 #ifdef _GLIBCXX_USE_C99
01853           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
01854 #else
01855           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
01856 #endif
01857                      __io, __err);
01858           break;
01859         case 't':
01860           if (__ctype.narrow(*__beg, 0) == '\t')
01861             ++__beg;
01862           else
01863             __err |= ios_base::failbit;
01864           break;
01865         case 'T':
01866           // Equivalent to (%H:%M:%S).
01867           __cs = "%H:%M:%S";
01868           __ctype.widen(__cs, __cs + 9, __wcs);
01869           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01870                         __tm, __wcs);
01871           break;
01872         case 'x':
01873           // Locale's date.
01874           const char_type*  __dates[2];
01875           __tp._M_date_formats(__dates);
01876           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01877                         __tm, __dates[0]);
01878           break;
01879         case 'X':
01880           // Locale's time.
01881           const char_type*  __times[2];
01882           __tp._M_time_formats(__times);
01883           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01884                         __tm, __times[0]);
01885           break;
01886         case 'y':
01887         case 'C': // C99
01888           // Two digit year. [tm_year]
01889           __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
01890                      __io, __err);
01891           break;
01892         case 'Y':
01893           // Year [1900). [tm_year]
01894           __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
01895                      __io, __err);
01896           if (!__err)
01897             __tm->tm_year = __mem - 1900;
01898           break;
01899         case 'Z':
01900           // Timezone info.
01901           if (__ctype.is(ctype_base::upper, *__beg))
01902             {
01903               int __tmp;
01904               __beg = _M_extract_name(__beg, __end, __tmp,
01905                        __timepunct_cache<_CharT>::_S_timezones,
01906                           14, __io, __err);
01907 
01908               // GMT requires special effort.
01909               if (__beg != __end && !__err && __tmp == 0
01910               && (*__beg == __ctype.widen('-')
01911                   || *__beg == __ctype.widen('+')))
01912             {
01913               __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
01914                          __io, __err);
01915               __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
01916                          __io, __err);
01917             }
01918             }
01919           else
01920             __err |= ios_base::failbit;
01921           break;
01922         default:
01923           // Not recognized.
01924           __err |= ios_base::failbit;
01925         }
01926         }
01927       else
01928         {
01929           // Verify format and input match, extract and discard.
01930           if (__format[__i] == *__beg)
01931         ++__beg;
01932           else
01933         __err |= ios_base::failbit;
01934         }
01935     }
01936       return __beg;
01937     }
01938 
01939   template<typename _CharT, typename _InIter>
01940     _InIter
01941     time_get<_CharT, _InIter>::
01942     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
01943            int __min, int __max, size_t __len,
01944            ios_base& __io, ios_base::iostate& __err) const
01945     {
01946       const locale& __loc = __io._M_getloc();
01947       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01948 
01949       // As-is works for __len = 1, 2, 4, the values actually used.
01950       int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
01951 
01952       ++__min;
01953       size_t __i = 0;
01954       int __value = 0;
01955       for (; __beg != __end && __i < __len; ++__beg, ++__i)
01956     {
01957       const char __c = __ctype.narrow(*__beg, '*');
01958       if (__c >= '0' && __c <= '9')
01959         {
01960           __value = __value * 10 + (__c - '0');
01961           const int __valuec = __value * __mult;
01962           if (__valuec > __max || __valuec + __mult < __min)
01963         break;
01964           __mult /= 10;
01965         }
01966       else
01967         break;
01968     }
01969       if (__i == __len)
01970     __member = __value;
01971       else
01972     __err |= ios_base::failbit;
01973       return __beg;
01974     }
01975 
01976   // Assumptions:
01977   // All elements in __names are unique.
01978   template<typename _CharT, typename _InIter>
01979     _InIter
01980     time_get<_CharT, _InIter>::
01981     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
01982             const _CharT** __names, size_t __indexlen,
01983             ios_base& __io, ios_base::iostate& __err) const
01984     {
01985       typedef char_traits<_CharT>       __traits_type;
01986       const locale& __loc = __io._M_getloc();
01987       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01988 
01989       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
01990                               * __indexlen));
01991       size_t __nmatches = 0;
01992       size_t __pos = 0;
01993       bool __testvalid = true;
01994       const char_type* __name;
01995 
01996       // Look for initial matches.
01997       // NB: Some of the locale data is in the form of all lowercase
01998       // names, and some is in the form of initially-capitalized
01999       // names. Look for both.
02000       if (__beg != __end)
02001     {
02002       const char_type __c = *__beg;
02003       for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
02004         if (__c == __names[__i1][0]
02005         || __c == __ctype.toupper(__names[__i1][0]))
02006           __matches[__nmatches++] = __i1;
02007     }
02008 
02009       while (__nmatches > 1)
02010     {
02011       // Find smallest matching string.
02012       size_t __minlen = __traits_type::length(__names[__matches[0]]);
02013       for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
02014         __minlen = std::min(__minlen,
02015                   __traits_type::length(__names[__matches[__i2]]));
02016       ++__beg, ++__pos;
02017       if (__pos < __minlen && __beg != __end)
02018         for (size_t __i3 = 0; __i3 < __nmatches;)
02019           {
02020         __name = __names[__matches[__i3]];
02021         if (!(__name[__pos] == *__beg))
02022           __matches[__i3] = __matches[--__nmatches];
02023         else
02024           ++__i3;
02025           }
02026       else
02027         break;
02028     }
02029 
02030       if (__nmatches == 1)
02031     {
02032       // Make sure found name is completely extracted.
02033       ++__beg, ++__pos;
02034       __name = __names[__matches[0]];
02035       const size_t __len = __traits_type::length(__name);
02036       while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
02037         ++__beg, ++__pos;
02038 
02039       if (__len == __pos)
02040         __member = __matches[0];
02041       else
02042         __testvalid = false;
02043     }
02044       else
02045     __testvalid = false;
02046       if (!__testvalid)
02047     __err |= ios_base::failbit;
02048       return __beg;
02049     }
02050 
02051   template<typename _CharT, typename _InIter>
02052     _InIter
02053     time_get<_CharT, _InIter>::
02054     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
02055         ios_base::iostate& __err, tm* __tm) const
02056     {
02057       const locale& __loc = __io._M_getloc();
02058       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02059       const char_type*  __times[2];
02060       __tp._M_time_formats(__times);
02061       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
02062                     __tm, __times[0]);
02063       if (__beg == __end)
02064     __err |= ios_base::eofbit;
02065       return __beg;
02066     }
02067 
02068   template<typename _CharT, typename _InIter>
02069     _InIter
02070     time_get<_CharT, _InIter>::
02071     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
02072         ios_base::iostate& __err, tm* __tm) const
02073     {
02074       const locale& __loc = __io._M_getloc();
02075       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02076       const char_type*  __dates[2];
02077       __tp._M_date_formats(__dates);
02078       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
02079                     __tm, __dates[0]);
02080       if (__beg == __end)
02081     __err |= ios_base::eofbit;
02082       return __beg;
02083     }
02084 
02085   template<typename _CharT, typename _InIter>
02086     _InIter
02087     time_get<_CharT, _InIter>::
02088     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
02089            ios_base::iostate& __err, tm* __tm) const
02090     {
02091       typedef char_traits<_CharT>       __traits_type;
02092       const locale& __loc = __io._M_getloc();
02093       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02094       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02095       const char_type*  __days[7];
02096       __tp._M_days_abbreviated(__days);
02097       int __tmpwday;
02098       __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, __io, __err);
02099 
02100       // Check to see if non-abbreviated name exists, and extract.
02101       // NB: Assumes both _M_days and _M_days_abbreviated organized in
02102       // exact same order, first to last, such that the resulting
02103       // __days array with the same index points to a day, and that
02104       // day's abbreviated form.
02105       // NB: Also assumes that an abbreviated name is a subset of the name.
02106       if (!__err && __beg != __end)
02107     {
02108       size_t __pos = __traits_type::length(__days[__tmpwday]);
02109       __tp._M_days(__days);
02110       const char_type* __name = __days[__tmpwday];
02111       if (__name[__pos] == *__beg)
02112         {
02113           // Extract the rest of it.
02114           const size_t __len = __traits_type::length(__name);
02115           while (__pos < __len && __beg != __end
02116              && __name[__pos] == *__beg)
02117         ++__beg, ++__pos;
02118           if (__len != __pos)
02119         __err |= ios_base::failbit;
02120         }
02121     }
02122       if (!__err)
02123     __tm->tm_wday = __tmpwday;
02124       
02125       if (__beg == __end)
02126     __err |= ios_base::eofbit;
02127       return __beg;
02128      }
02129 
02130   template<typename _CharT, typename _InIter>
02131     _InIter
02132     time_get<_CharT, _InIter>::
02133     do_get_monthname(iter_type __beg, iter_type __end,
02134                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
02135     {
02136       typedef char_traits<_CharT>       __traits_type;
02137       const locale& __loc = __io._M_getloc();
02138       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02139       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02140       const char_type*  __months[12];
02141       __tp._M_months_abbreviated(__months);
02142       int __tmpmon;
02143       __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 
02144                   __io, __err);
02145 
02146       // Check to see if non-abbreviated name exists, and extract.
02147       // NB: Assumes both _M_months and _M_months_abbreviated organized in
02148       // exact same order, first to last, such that the resulting
02149       // __months array with the same index points to a month, and that
02150       // month's abbreviated form.
02151       // NB: Also assumes that an abbreviated name is a subset of the name.
02152       if (!__err && __beg != __end)
02153     {
02154       size_t __pos = __traits_type::length(__months[__tmpmon]);
02155       __tp._M_months(__months);
02156       const char_type* __name = __months[__tmpmon];
02157       if (__name[__pos] == *__beg)
02158         {
02159           // Extract the rest of it.
02160           const size_t __len = __traits_type::length(__name);
02161           while (__pos < __len && __beg != __end
02162              && __name[__pos] == *__beg)
02163         ++__beg, ++__pos;
02164           if (__len != __pos)
02165         __err |= ios_base::failbit;
02166         }
02167     }
02168       if (!__err)
02169     __tm->tm_mon = __tmpmon;
02170 
02171       if (__beg == __end)
02172     __err |= ios_base::eofbit;
02173       return __beg;
02174     }
02175 
02176   template<typename _CharT, typename _InIter>
02177     _InIter
02178     time_get<_CharT, _InIter>::
02179     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
02180         ios_base::iostate& __err, tm* __tm) const
02181     {
02182       const locale& __loc = __io._M_getloc();
02183       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02184 
02185       size_t __i = 0;
02186       int __value = 0;
02187       for (; __beg != __end && __i < 4; ++__beg, ++__i)
02188     {
02189       const char __c = __ctype.narrow(*__beg, '*');
02190       if (__c >= '0' && __c <= '9')
02191         __value = __value * 10 + (__c - '0');
02192       else
02193         break;
02194     }
02195       if (__i == 2 || __i == 4)
02196     __tm->tm_year = __i == 2 ? __value : __value - 1900;
02197       else
02198     __err |= ios_base::failbit;
02199       if (__beg == __end)
02200     __err |= ios_base::eofbit;
02201       return __beg;
02202     }
02203 
02204   template<typename _CharT, typename _OutIter>
02205     _OutIter
02206     time_put<_CharT, _OutIter>::
02207     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
02208     const _CharT* __beg, const _CharT* __end) const
02209     {
02210       const locale& __loc = __io._M_getloc();
02211       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
02212       for (; __beg != __end; ++__beg)
02213     if (__ctype.narrow(*__beg, 0) != '%')
02214       {
02215         *__s = *__beg;
02216         ++__s;
02217       }
02218     else if (++__beg != __end)
02219       {
02220         char __format;
02221         char __mod = 0;
02222         const char __c = __ctype.narrow(*__beg, 0);
02223         if (__c != 'E' && __c != 'O')
02224           __format = __c;
02225         else if (++__beg != __end)
02226           {
02227         __mod = __c;
02228         __format = __ctype.narrow(*__beg, 0);
02229           }
02230         else
02231           break;
02232         __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
02233       }
02234     else
02235       break;
02236       return __s;
02237     }
02238 
02239   template<typename _CharT, typename _OutIter>
02240     _OutIter
02241     time_put<_CharT, _OutIter>::
02242     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
02243        char __format, char __mod) const
02244     {
02245       const locale& __loc = __io._M_getloc();
02246       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
02247       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
02248 
02249       // NB: This size is arbitrary. Should this be a data member,
02250       // initialized at construction?
02251       const size_t __maxlen = 128;
02252       char_type* __res = 
02253        static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
02254 
02255       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
02256       // is possible that the format character will be longer than one
02257       // character. Possibilities include 'E' or 'O' followed by a
02258       // format character: if __mod is not the default argument, assume
02259       // it's a valid modifier.
02260       char_type __fmt[4];
02261       __fmt[0] = __ctype.widen('%');
02262       if (!__mod)
02263     {
02264       __fmt[1] = __format;
02265       __fmt[2] = char_type();
02266     }
02267       else
02268     {
02269       __fmt[1] = __mod;
02270       __fmt[2] = __format;
02271       __fmt[3] = char_type();
02272     }
02273 
02274       __tp._M_put(__res, __maxlen, __fmt, __tm);
02275 
02276       // Write resulting, fully-formatted string to output iterator.
02277       return std::__write(__s, __res, char_traits<char_type>::length(__res));
02278     }
02279 
02280   // Generic version does nothing.
02281   template<typename _CharT>
02282     int
02283     collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
02284     { return 0; }
02285 
02286   // Generic version does nothing.
02287   template<typename _CharT>
02288     size_t
02289     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
02290     { return 0; }
02291 
02292   template<typename _CharT>
02293     int
02294     collate<_CharT>::
02295     do_compare(const _CharT* __lo1, const _CharT* __hi1,
02296            const _CharT* __lo2, const _CharT* __hi2) const
02297     {
02298       // strcoll assumes zero-terminated strings so we make a copy
02299       // and then put a zero at the end.
02300       const string_type __one(__lo1, __hi1);
02301       const string_type __two(__lo2, __hi2);
02302 
02303       const _CharT* __p = __one.c_str();
02304       const _CharT* __pend = __one.data() + __one.length();
02305       const _CharT* __q = __two.c_str();
02306       const _CharT* __qend = __two.data() + __two.length();
02307 
02308       // strcoll stops when it sees a nul character so we break
02309       // the strings into zero-terminated substrings and pass those
02310       // to strcoll.
02311       for (;;)
02312     {
02313       const int __res = _M_compare(__p, __q);
02314       if (__res)
02315         return __res;
02316 
02317       __p += char_traits<_CharT>::length(__p);
02318       __q += char_traits<_CharT>::length(__q);
02319       if (__p == __pend && __q == __qend)
02320         return 0;
02321       else if (__p == __pend)
02322         return -1;
02323       else if (__q == __qend)
02324         return 1;
02325 
02326       __p++;
02327       __q++;
02328     }
02329     }
02330 
02331   template<typename _CharT>
02332     typename collate<_CharT>::string_type
02333     collate<_CharT>::
02334     do_transform(const _CharT* __lo, const _CharT* __hi) const
02335     {
02336       // strxfrm assumes zero-terminated strings so we make a copy
02337       string_type __str(__lo, __hi);
02338 
02339       const _CharT* __p = __str.c_str();
02340       const _CharT* __pend = __str.data() + __str.length();
02341 
02342       size_t __len = (__hi - __lo) * 2;
02343 
02344       string_type __ret;
02345 
02346       // strxfrm stops when it sees a nul character so we break
02347       // the string into zero-terminated substrings and pass those
02348       // to strxfrm.
02349       for (;;)
02350     {
02351       // First try a buffer perhaps big enough.
02352       _CharT* __c =
02353         static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
02354       size_t __res = _M_transform(__c, __p, __len);
02355       // If the buffer was not large enough, try again with the
02356       // correct size.
02357       if (__res >= __len)
02358         {
02359           __len = __res + 1;
02360           __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
02361                               * __len));
02362           __res = _M_transform(__c, __p, __len);
02363         }
02364 
02365       __ret.append(__c, __res);
02366       __p += char_traits<_CharT>::length(__p);
02367       if (__p == __pend)
02368         return __ret;
02369 
02370       __p++;
02371       __ret.push_back(_CharT());
02372     }
02373     }
02374 
02375   template<typename _CharT>
02376     long
02377     collate<_CharT>::
02378     do_hash(const _CharT* __lo, const _CharT* __hi) const
02379     {
02380       unsigned long __val = 0;
02381       for (; __lo < __hi; ++__lo)
02382     __val = *__lo + ((__val << 7) |
02383                (__val >> (numeric_limits<unsigned long>::digits - 7)));
02384       return static_cast<long>(__val);
02385     }
02386 
02387   // Construct correctly padded string, as per 22.2.2.2.2
02388   // Assumes
02389   // __newlen > __oldlen
02390   // __news is allocated for __newlen size
02391   // Used by both num_put and ostream inserters: if __num,
02392   // internal-adjusted objects are padded according to the rules below
02393   // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
02394   // ones are.
02395 
02396   // NB: Of the two parameters, _CharT can be deduced from the
02397   // function arguments. The other (_Traits) has to be explicitly specified.
02398   template<typename _CharT, typename _Traits>
02399     void
02400     __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
02401                    _CharT* __news, const _CharT* __olds,
02402                    const streamsize __newlen,
02403                    const streamsize __oldlen, const bool __num)
02404     {
02405       const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
02406       const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
02407 
02408       // Padding last.
02409       if (__adjust == ios_base::left)
02410     {
02411       _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen);
02412       _Traits::assign(__news + __oldlen, __plen, __fill);
02413       return;
02414     }
02415 
02416       size_t __mod = 0;
02417       if (__adjust == ios_base::internal && __num)
02418     {
02419       // Pad after the sign, if there is one.
02420       // Pad after 0[xX], if there is one.
02421       // Who came up with these rules, anyway? Jeeze.
02422           const locale& __loc = __io._M_getloc();
02423       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02424 
02425       const bool __testsign = (__ctype.widen('-') == __olds[0]
02426                    || __ctype.widen('+') == __olds[0]);
02427       const bool __testhex = (__ctype.widen('0') == __olds[0]
02428                   && __oldlen > 1
02429                   && (__ctype.widen('x') == __olds[1]
02430                       || __ctype.widen('X') == __olds[1]));
02431       if (__testhex)
02432         {
02433           __news[0] = __olds[0];
02434           __news[1] = __olds[1];
02435           __mod = 2;
02436           __news += 2;
02437         }
02438       else if (__testsign)
02439         {
02440           __news[0] = __olds[0];
02441           __mod = 1;
02442           ++__news;
02443         }
02444       // else Padding first.
02445     }
02446       _Traits::assign(__news, __plen, __fill);
02447       _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod),
02448             __oldlen - __mod);
02449     }
02450 
02451   bool
02452   __verify_grouping(const char* __grouping, size_t __grouping_size,
02453             const string& __grouping_tmp)
02454   {
02455     const size_t __n = __grouping_tmp.size() - 1;
02456     const size_t __min = std::min(__n, size_t(__grouping_size - 1));
02457     size_t __i = __n;
02458     bool __test = true;
02459     
02460     // Parsed number groupings have to match the
02461     // numpunct::grouping string exactly, starting at the
02462     // right-most point of the parsed sequence of elements ...
02463     for (size_t __j = 0; __j < __min && __test; --__i, ++__j)
02464       __test = __grouping_tmp[__i] == __grouping[__j];
02465     for (; __i && __test; --__i)
02466       __test = __grouping_tmp[__i] == __grouping[__min];
02467     // ... but the last parsed grouping can be <= numpunct
02468     // grouping.
02469     __test &= __grouping_tmp[0] <= __grouping[__min];
02470     return __test;
02471   }
02472 
02473   template<typename _CharT>
02474     _CharT*
02475     __add_grouping(_CharT* __s, _CharT __sep,
02476            const char* __gbeg, size_t __gsize,
02477            const _CharT* __first, const _CharT* __last)
02478     {
02479       if (__last - __first > *__gbeg)
02480     {
02481       const bool __bump = __gsize != 1;
02482       __s = std::__add_grouping(__s,  __sep, __gbeg + __bump,
02483                     __gsize - __bump, __first,
02484                     __last - *__gbeg);
02485       __first = __last - *__gbeg;
02486       *__s++ = __sep;
02487     }
02488       do
02489     *__s++ = *__first++;
02490       while (__first != __last);
02491       return __s;
02492     }
02493 
02494   // Inhibit implicit instantiations for required instantiations,
02495   // which are defined via explicit instantiations elsewhere.
02496   // NB: This syntax is a GNU extension.
02497 #if _GLIBCXX_EXTERN_TEMPLATE
02498   extern template class moneypunct<char, false>;
02499   extern template class moneypunct<char, true>;
02500   extern template class moneypunct_byname<char, false>;
02501   extern template class moneypunct_byname<char, true>;
02502   extern template class money_get<char>;
02503   extern template class money_put<char>;
02504   extern template class numpunct<char>;
02505   extern template class numpunct_byname<char>;
02506   extern template class num_get<char>;
02507   extern template class num_put<char>;
02508   extern template class __timepunct<char>;
02509   extern template class time_put<char>;
02510   extern template class time_put_byname<char>;
02511   extern template class time_get<char>;
02512   extern template class time_get_byname<char>;
02513   extern template class messages<char>;
02514   extern template class messages_byname<char>;
02515   extern template class ctype_byname<char>;
02516   extern template class codecvt_byname<char, char, mbstate_t>;
02517   extern template class collate<char>;
02518   extern template class collate_byname<char>;
02519 
02520   extern template
02521     const codecvt<char, char, mbstate_t>&
02522     use_facet<codecvt<char, char, mbstate_t> >(const locale&);
02523 
02524   extern template
02525     const collate<char>&
02526     use_facet<collate<char> >(const locale&);
02527 
02528   extern template
02529     const numpunct<char>&
02530     use_facet<numpunct<char> >(const locale&);
02531 
02532   extern template
02533     const num_put<char>&
02534     use_facet<num_put<char> >(const locale&);
02535 
02536   extern template
02537     const num_get<char>&
02538     use_facet<num_get<char> >(const locale&);
02539 
02540   extern template
02541     const moneypunct<char, true>&
02542     use_facet<moneypunct<char, true> >(const locale&);
02543 
02544   extern template
02545     const moneypunct<char, false>&
02546     use_facet<moneypunct<char, false> >(const locale&);
02547 
02548   extern template
02549     const money_put<char>&
02550     use_facet<money_put<char> >(const locale&);
02551 
02552   extern template
02553     const money_get<char>&
02554     use_facet<money_get<char> >(const locale&);
02555 
02556   extern template
02557     const __timepunct<char>&
02558     use_facet<__timepunct<char> >(const locale&);
02559 
02560   extern template
02561     const time_put<char>&
02562     use_facet<time_put<char> >(const locale&);
02563 
02564   extern template
02565     const time_get<char>&
02566     use_facet<time_get<char> >(const locale&);
02567 
02568   extern template
02569     const messages<char>&
02570     use_facet<messages<char> >(const locale&);
02571 
02572   extern template
02573     bool
02574     has_facet<ctype<char> >(const locale&);
02575 
02576   extern template
02577     bool
02578     has_facet<codecvt<char, char, mbstate_t> >(const locale&);
02579 
02580   extern template
02581     bool
02582     has_facet<collate<char> >(const locale&);
02583 
02584   extern template
02585     bool
02586     has_facet<numpunct<char> >(const locale&);
02587 
02588   extern template
02589     bool
02590     has_facet<num_put<char> >(const locale&);
02591 
02592   extern template
02593     bool
02594     has_facet<num_get<char> >(const locale&);
02595 
02596   extern template
02597     bool
02598     has_facet<moneypunct<char> >(const locale&);
02599 
02600   extern template
02601     bool
02602     has_facet<money_put<char> >(const locale&);
02603 
02604   extern template
02605     bool
02606     has_facet<money_get<char> >(const locale&);
02607 
02608   extern template
02609     bool
02610     has_facet<__timepunct<char> >(const locale&);
02611 
02612   extern template
02613     bool
02614     has_facet<time_put<char> >(const locale&);
02615 
02616   extern template
02617     bool
02618     has_facet<time_get<char> >(const locale&);
02619 
02620   extern template
02621     bool
02622     has_facet<messages<char> >(const locale&);
02623 
02624 #ifdef _GLIBCXX_USE_WCHAR_T
02625   extern template class moneypunct<wchar_t, false>;
02626   extern template class moneypunct<wchar_t, true>;
02627   extern template class moneypunct_byname<wchar_t, false>;
02628   extern template class moneypunct_byname<wchar_t, true>;
02629   extern template class money_get<wchar_t>;
02630   extern template class money_put<wchar_t>;
02631   extern template class numpunct<wchar_t>;
02632   extern template class numpunct_byname<wchar_t>;
02633   extern template class num_get<wchar_t>;
02634   extern template class num_put<wchar_t>;
02635   extern template class __timepunct<wchar_t>;
02636   extern template class time_put<wchar_t>;
02637   extern template class time_put_byname<wchar_t>;
02638   extern template class time_get<wchar_t>;
02639   extern template class time_get_byname<wchar_t>;
02640   extern template class messages<wchar_t>;
02641   extern template class messages_byname<wchar_t>;
02642   extern template class ctype_byname<wchar_t>;
02643   extern template class codecvt_byname<wchar_t, char, mbstate_t>;
02644   extern template class collate<wchar_t>;
02645   extern template class collate_byname<wchar_t>;
02646 
02647   extern template
02648     const codecvt<wchar_t, char, mbstate_t>&
02649     use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
02650 
02651   extern template
02652     const collate<wchar_t>&
02653     use_facet<collate<wchar_t> >(const locale&);
02654 
02655   extern template
02656     const numpunct<wchar_t>&
02657     use_facet<numpunct<wchar_t> >(const locale&);
02658 
02659   extern template
02660     const num_put<wchar_t>&
02661     use_facet<num_put<wchar_t> >(const locale&);
02662 
02663   extern template
02664     const num_get<wchar_t>&
02665     use_facet<num_get<wchar_t> >(const locale&);
02666 
02667   extern template
02668     const moneypunct<wchar_t, true>&
02669     use_facet<moneypunct<wchar_t, true> >(const locale&);
02670 
02671   extern template
02672     const moneypunct<wchar_t, false>&
02673     use_facet<moneypunct<wchar_t, false> >(const locale&);
02674 
02675   extern template
02676     const money_put<wchar_t>&
02677     use_facet<money_put<wchar_t> >(const locale&);
02678 
02679   extern template
02680     const money_get<wchar_t>&
02681     use_facet<money_get<wchar_t> >(const locale&);
02682 
02683   extern template
02684     const __timepunct<wchar_t>&
02685     use_facet<__timepunct<wchar_t> >(const locale&);
02686 
02687   extern template
02688     const time_put<wchar_t>&
02689     use_facet<time_put<wchar_t> >(const locale&);
02690 
02691   extern template
02692     const time_get<wchar_t>&
02693     use_facet<time_get<wchar_t> >(const locale&);
02694 
02695   extern template
02696     const messages<wchar_t>&
02697     use_facet<messages<wchar_t> >(const locale&);
02698 
02699  extern template
02700     bool
02701     has_facet<ctype<wchar_t> >(const locale&);
02702 
02703   extern template
02704     bool
02705     has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
02706 
02707   extern template
02708     bool
02709     has_facet<collate<wchar_t> >(const locale&);
02710 
02711   extern template
02712     bool
02713     has_facet<numpunct<wchar_t> >(const locale&);
02714 
02715   extern template
02716     bool
02717     has_facet<num_put<wchar_t> >(const locale&);
02718 
02719   extern template
02720     bool
02721     has_facet<num_get<wchar_t> >(const locale&);
02722 
02723   extern template
02724     bool
02725     has_facet<moneypunct<wchar_t> >(const locale&);
02726 
02727   extern template
02728     bool
02729     has_facet<money_put<wchar_t> >(const locale&);
02730 
02731   extern template
02732     bool
02733     has_facet<money_get<wchar_t> >(const locale&);
02734 
02735   extern template
02736     bool
02737     has_facet<__timepunct<wchar_t> >(const locale&);
02738 
02739   extern template
02740     bool
02741     has_facet<time_put<wchar_t> >(const locale&);
02742 
02743   extern template
02744     bool
02745     has_facet<time_get<wchar_t> >(const locale&);
02746 
02747   extern template
02748     bool
02749     has_facet<messages<wchar_t> >(const locale&);
02750 #endif
02751 #endif
02752 } // namespace std
02753 
02754 #endif

Generated on Sat Oct 1 15:08:53 2005 for libstdc++ source by  doxygen 1.4.4