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

Generated on Tue May 23 12:55:27 2006 for libstdc++ source by  doxygen 1.4.4