locale_facets.tcc

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

Generated on Wed Apr 27 18:35:13 2005 for libstdc++ source by  doxygen 1.4.2