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
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       bool __neg = false;
00857       if (__v < 0)
00858     {
00859       __ul = -__ul;
00860       __neg = true;
00861     }
00862       return __int_to_char(__bufend, __ul, __lit, __flags, __neg);
00863     }
00864 
00865   template<typename _CharT>
00866     inline int
00867     __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
00868           ios_base::fmtflags __flags)
00869     {
00870       // About showpos, see Table 60 and C99 7.19.6.1, p6 (+).
00871       return __int_to_char(__bufend, __v, __lit,
00872                __flags & ~ios_base::showpos, false);
00873     }
00874 
00875 #ifdef _GLIBCXX_USE_LONG_LONG
00876   template<typename _CharT>
00877     inline int
00878     __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
00879           ios_base::fmtflags __flags)
00880     {
00881       unsigned long long __ull = static_cast<unsigned long long>(__v);
00882       bool __neg = false;
00883       if (__v < 0)
00884     {
00885       __ull = -__ull;
00886       __neg = true;
00887     }
00888       return __int_to_char(__bufend, __ull, __lit, __flags, __neg);
00889     }
00890 
00891   template<typename _CharT>
00892     inline int
00893     __int_to_char(_CharT* __bufend, unsigned long long __v, 
00894           const _CharT* __lit, ios_base::fmtflags __flags)
00895     { return __int_to_char(__bufend, __v, __lit,
00896                __flags & ~ios_base::showpos, false); }
00897 #endif
00898 
00899   template<typename _CharT, typename _ValueT>
00900     int
00901     __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
00902           ios_base::fmtflags __flags, bool __neg)
00903     {
00904       // Don't write base if already 0.
00905       const bool __showbase = (__flags & ios_base::showbase) && __v;
00906       const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
00907       _CharT* __buf = __bufend - 1;
00908 
00909       if (__builtin_expect(__basefield != ios_base::oct &&
00910                __basefield != ios_base::hex, true))
00911     {
00912       // Decimal.
00913       do
00914         {
00915           *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits];
00916           __v /= 10;
00917         }
00918       while (__v != 0);
00919       if (__neg)
00920         *__buf-- = __lit[__num_base::_S_ominus];
00921       else if (__flags & ios_base::showpos)
00922         *__buf-- = __lit[__num_base::_S_oplus];
00923     }
00924       else if (__basefield == ios_base::oct)
00925     {
00926       // Octal.
00927       do
00928         {
00929           *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits];
00930           __v >>= 3;
00931         }
00932       while (__v != 0);
00933       if (__showbase)
00934         *__buf-- = __lit[__num_base::_S_odigits];
00935     }
00936       else
00937     {
00938       // Hex.
00939       const bool __uppercase = __flags & ios_base::uppercase;
00940       const int __case_offset = __uppercase ? __num_base::_S_oudigits
00941                                             : __num_base::_S_odigits;
00942       do
00943         {
00944           *__buf-- = __lit[(__v & 0xf) + __case_offset];
00945           __v >>= 4;
00946         }
00947       while (__v != 0);
00948       if (__showbase)
00949         {
00950           // 'x' or 'X'
00951           *__buf-- = __lit[__num_base::_S_ox + __uppercase];
00952           // '0'
00953           *__buf-- = __lit[__num_base::_S_odigits];
00954         }
00955     }
00956       return __bufend - __buf - 1;
00957     }
00958 
00959   template<typename _CharT, typename _OutIter>
00960     void
00961     num_put<_CharT, _OutIter>::
00962     _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
00963          ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const
00964     {
00965       // By itself __add_grouping cannot deal correctly with __cs when
00966       // ios::showbase is set and ios_base::oct || ios_base::hex.
00967       // Therefore we take care "by hand" of the initial 0, 0x or 0X.
00968       // However, remember that the latter do not occur if the number
00969       // printed is '0' (__len == 1).
00970       streamsize __off = 0;
00971       const ios_base::fmtflags __basefield = __io.flags()
00972                                          & ios_base::basefield;
00973       if ((__io.flags() & ios_base::showbase) && __len > 1)
00974     if (__basefield == ios_base::oct)
00975       {
00976         __off = 1;
00977         __new[0] = __cs[0];
00978       }
00979     else if (__basefield == ios_base::hex)
00980       {
00981         __off = 2;
00982         __new[0] = __cs[0];
00983         __new[1] = __cs[1];
00984       }
00985       _CharT* __p = std::__add_grouping(__new + __off, __sep, __grouping,
00986                     __grouping_size, __cs + __off,
00987                     __cs + __len);
00988       __len = __p - __new;
00989     }
00990 
00991   template<typename _CharT, typename _OutIter>
00992     template<typename _ValueT>
00993       _OutIter
00994       num_put<_CharT, _OutIter>::
00995       _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
00996             _ValueT __v) const
00997       {
00998     typedef typename numpunct<_CharT>::__cache_type __cache_type;
00999     __use_cache<__cache_type> __uc;
01000     const locale& __loc = __io._M_getloc();
01001     const __cache_type* __lc = __uc(__loc);
01002     const _CharT* __lit = __lc->_M_atoms_out;
01003 
01004     // Long enough to hold hex, dec, and octal representations.
01005     const int __ilen = 4 * sizeof(_ValueT);
01006     _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01007                                  * __ilen));
01008 
01009     // [22.2.2.2.2] Stage 1, numeric conversion to character.
01010     // Result is returned right-justified in the buffer.
01011     int __len;
01012     __len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags());
01013     __cs += __ilen - __len;
01014 
01015     // Add grouping, if necessary.
01016     if (__lc->_M_use_grouping)
01017       {
01018         // Grouping can add (almost) as many separators as the
01019         // number of digits, but no more.
01020         _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01021                                   * __len * 2));
01022         _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
01023              __lc->_M_thousands_sep, __io, __cs2, __cs, __len);
01024         __cs = __cs2;
01025       }
01026 
01027     // Pad.
01028     const streamsize __w = __io.width();
01029     if (__w > static_cast<streamsize>(__len))
01030       {
01031         _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01032                                   * __w));
01033         _M_pad(__fill, __w, __io, __cs3, __cs, __len);
01034         __cs = __cs3;
01035       }
01036     __io.width(0);
01037 
01038     // [22.2.2.2.2] Stage 4.
01039     // Write resulting, fully-formatted string to output iterator.
01040     return std::__write(__s, __cs, __len);
01041       }
01042 
01043   template<typename _CharT, typename _OutIter>
01044     void
01045     num_put<_CharT, _OutIter>::
01046     _M_group_float(const char* __grouping, size_t __grouping_size,
01047            _CharT __sep, const _CharT* __p, _CharT* __new,
01048            _CharT* __cs, int& __len) const
01049     {
01050       // _GLIBCXX_RESOLVE_LIB_DEFECTS
01051       // 282. What types does numpunct grouping refer to?
01052       // Add grouping, if necessary.
01053       const int __declen = __p ? __p - __cs : __len;
01054       _CharT* __p2 = std::__add_grouping(__new, __sep, __grouping,
01055                      __grouping_size,
01056                      __cs, __cs + __declen);
01057 
01058       // Tack on decimal part.
01059       int __newlen = __p2 - __new;
01060       if (__p)
01061     {
01062       char_traits<_CharT>::copy(__p2, __p, __len - __declen);
01063       __newlen += __len - __declen;
01064     }
01065       __len = __newlen;
01066     }
01067 
01068   // The following code uses snprintf (or sprintf(), when
01069   // _GLIBCXX_USE_C99 is not defined) to convert floating point values
01070   // for insertion into a stream.  An optimization would be to replace
01071   // them with code that works directly on a wide buffer and then use
01072   // __pad to do the padding.  It would be good to replace them anyway
01073   // to gain back the efficiency that C++ provides by knowing up front
01074   // the type of the values to insert.  Also, sprintf is dangerous
01075   // since may lead to accidental buffer overruns.  This
01076   // implementation follows the C++ standard fairly directly as
01077   // outlined in 22.2.2.2 [lib.locale.num.put]
01078   template<typename _CharT, typename _OutIter>
01079     template<typename _ValueT>
01080       _OutIter
01081       num_put<_CharT, _OutIter>::
01082       _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
01083                _ValueT __v) const
01084       {
01085     typedef typename numpunct<_CharT>::__cache_type __cache_type;
01086     __use_cache<__cache_type> __uc;
01087     const locale& __loc = __io._M_getloc();
01088     const __cache_type* __lc = __uc(__loc);
01089 
01090     // Use default precision if out of range.
01091     streamsize __prec = __io.precision();
01092     if (__prec < static_cast<streamsize>(0))
01093       __prec = static_cast<streamsize>(6);
01094 
01095     const int __max_digits = numeric_limits<_ValueT>::digits10;
01096 
01097     // [22.2.2.2.2] Stage 1, numeric conversion to character.
01098     int __len;
01099     // Long enough for the max format spec.
01100     char __fbuf[16];
01101 
01102 #ifdef _GLIBCXX_USE_C99
01103     // First try a buffer perhaps big enough (most probably sufficient
01104     // for non-ios_base::fixed outputs)
01105     int __cs_size = __max_digits * 3;
01106     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01107 
01108     __num_base::_S_format_float(__io, __fbuf, __mod);
01109     __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
01110                       _S_get_c_locale(), __prec);
01111 
01112     // If the buffer was not large enough, try again with the correct size.
01113     if (__len >= __cs_size)
01114       {
01115         __cs_size = __len + 1;
01116         __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01117         __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
01118                       _S_get_c_locale(), __prec);
01119       }
01120 #else
01121     // Consider the possibility of long ios_base::fixed outputs
01122     const bool __fixed = __io.flags() & ios_base::fixed;
01123     const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
01124 
01125     // The size of the output string is computed as follows.
01126     // ios_base::fixed outputs may need up to __max_exp + 1 chars
01127     // for the integer part + __prec chars for the fractional part
01128     // + 3 chars for sign, decimal point, '\0'. On the other hand,
01129     // for non-fixed outputs __max_digits * 2 + __prec chars are
01130     // largely sufficient.
01131     const int __cs_size = __fixed ? __max_exp + __prec + 4
01132                                   : __max_digits * 2 + __prec;
01133     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01134 
01135     __num_base::_S_format_float(__io, __fbuf, __mod);
01136     __len = std::__convert_from_v(__cs, 0, __fbuf, __v,
01137                       _S_get_c_locale(), __prec);
01138 #endif
01139 
01140       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
01141       // numpunct.decimal_point() values for '.' and adding grouping.
01142       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01143 
01144       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01145                                * __len));
01146       __ctype.widen(__cs, __cs + __len, __ws);
01147 
01148       // Replace decimal point.
01149       const _CharT __cdec = __ctype.widen('.');
01150       const _CharT __dec = __lc->_M_decimal_point;
01151       const _CharT* __p = char_traits<_CharT>::find(__ws, __len, __cdec);
01152       if (__p)
01153     __ws[__p - __ws] = __dec;
01154 
01155       // Add grouping, if necessary.
01156       if (__lc->_M_use_grouping)
01157     {
01158       // Grouping can add (almost) as many separators as the
01159       // number of digits, but no more.
01160       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01161                                 * __len * 2));
01162       _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
01163              __lc->_M_thousands_sep, __p, __ws2, __ws, __len);
01164       __ws = __ws2;
01165     }
01166 
01167       // Pad.
01168       const streamsize __w = __io.width();
01169       if (__w > static_cast<streamsize>(__len))
01170     {
01171       _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01172                                 * __w));
01173       _M_pad(__fill, __w, __io, __ws3, __ws, __len);
01174       __ws = __ws3;
01175     }
01176       __io.width(0);
01177 
01178       // [22.2.2.2.2] Stage 4.
01179       // Write resulting, fully-formatted string to output iterator.
01180       return std::__write(__s, __ws, __len);
01181       }
01182 
01183   template<typename _CharT, typename _OutIter>
01184     _OutIter
01185     num_put<_CharT, _OutIter>::
01186     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
01187     {
01188       const ios_base::fmtflags __flags = __io.flags();
01189       if ((__flags & ios_base::boolalpha) == 0)
01190         {
01191           const long __l = __v;
01192           __s = _M_insert_int(__s, __io, __fill, __l);
01193         }
01194       else
01195         {
01196       typedef typename numpunct<_CharT>::__cache_type __cache_type;
01197       __use_cache<__cache_type> __uc;
01198       const locale& __loc = __io._M_getloc();
01199       const __cache_type* __lc = __uc(__loc);
01200 
01201       const _CharT* __name = __v ? __lc->_M_truename
01202                                  : __lc->_M_falsename;
01203       int __len = __v ? __lc->_M_truename_size
01204                       : __lc->_M_falsename_size;
01205 
01206       const streamsize __w = __io.width();
01207       if (__w > static_cast<streamsize>(__len))
01208         {
01209           _CharT* __cs
01210         = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01211                             * __w));
01212           _M_pad(__fill, __w, __io, __cs, __name, __len);
01213           __name = __cs;
01214         }
01215       __io.width(0);
01216       __s = std::__write(__s, __name, __len);
01217     }
01218       return __s;
01219     }
01220 
01221   template<typename _CharT, typename _OutIter>
01222     _OutIter
01223     num_put<_CharT, _OutIter>::
01224     do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
01225     { return _M_insert_int(__s, __io, __fill, __v); }
01226 
01227   template<typename _CharT, typename _OutIter>
01228     _OutIter
01229     num_put<_CharT, _OutIter>::
01230     do_put(iter_type __s, ios_base& __io, char_type __fill,
01231            unsigned long __v) const
01232     { return _M_insert_int(__s, __io, __fill, __v); }
01233 
01234 #ifdef _GLIBCXX_USE_LONG_LONG
01235   template<typename _CharT, typename _OutIter>
01236     _OutIter
01237     num_put<_CharT, _OutIter>::
01238     do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
01239     { return _M_insert_int(__s, __b, __fill, __v); }
01240 
01241   template<typename _CharT, typename _OutIter>
01242     _OutIter
01243     num_put<_CharT, _OutIter>::
01244     do_put(iter_type __s, ios_base& __io, char_type __fill,
01245            unsigned long long __v) const
01246     { return _M_insert_int(__s, __io, __fill, __v); }
01247 #endif
01248 
01249   template<typename _CharT, typename _OutIter>
01250     _OutIter
01251     num_put<_CharT, _OutIter>::
01252     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
01253     { return _M_insert_float(__s, __io, __fill, char(), __v); }
01254 
01255   template<typename _CharT, typename _OutIter>
01256     _OutIter
01257     num_put<_CharT, _OutIter>::
01258     do_put(iter_type __s, ios_base& __io, char_type __fill,
01259        long double __v) const
01260     { return _M_insert_float(__s, __io, __fill, 'L', __v); }
01261 
01262   template<typename _CharT, typename _OutIter>
01263     _OutIter
01264     num_put<_CharT, _OutIter>::
01265     do_put(iter_type __s, ios_base& __io, char_type __fill,
01266            const void* __v) const
01267     {
01268       const ios_base::fmtflags __flags = __io.flags();
01269       const ios_base::fmtflags __fmt = ~(ios_base::basefield
01270                      | ios_base::uppercase
01271                      | ios_base::internal);
01272       __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
01273 
01274       __s = _M_insert_int(__s, __io, __fill,
01275               reinterpret_cast<unsigned long>(__v));
01276       __io.flags(__flags);
01277       return __s;
01278     }
01279 
01280   template<typename _CharT, typename _InIter>
01281     template<bool _Intl>
01282       _InIter
01283       money_get<_CharT, _InIter>::
01284       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
01285          ios_base::iostate& __err, string& __units) const
01286       {
01287     typedef char_traits<_CharT>           __traits_type;
01288     typedef typename string_type::size_type           size_type;    
01289     typedef money_base::part              part;
01290     typedef moneypunct<_CharT, _Intl>         __moneypunct_type;
01291     typedef typename __moneypunct_type::__cache_type  __cache_type;
01292     
01293     const locale& __loc = __io._M_getloc();
01294     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01295 
01296     __use_cache<__cache_type> __uc;
01297     const __cache_type* __lc = __uc(__loc);
01298     const char_type* __lit = __lc->_M_atoms;
01299 
01300     // Deduced sign.
01301     bool __negative = false;
01302     // Sign size.
01303     size_type __sign_size = 0;
01304     // True if sign is mandatory.
01305     const bool __mandatory_sign = (__lc->_M_positive_sign_size
01306                        && __lc->_M_negative_sign_size);
01307     // String of grouping info from thousands_sep plucked from __units.
01308     string __grouping_tmp;
01309     if (__lc->_M_use_grouping)
01310       __grouping_tmp.reserve(32);
01311     // Last position before the decimal point.
01312     int __last_pos = 0;
01313     // Separator positions, then, possibly, fractional digits.
01314     int __n = 0;
01315     // If input iterator is in a valid state.
01316     bool __testvalid = true;
01317     // Flag marking when a decimal point is found.
01318     bool __testdecfound = false;
01319 
01320     // The tentative returned string is stored here.
01321     string __res;
01322     __res.reserve(32);
01323 
01324     const char_type* __lit_zero = __lit + money_base::_S_zero;
01325     const money_base::pattern __p = __lc->_M_neg_format;
01326     for (int __i = 0; __i < 4 && __testvalid; ++__i)
01327       {
01328         const part __which = static_cast<part>(__p.field[__i]);
01329         switch (__which)
01330           {
01331           case money_base::symbol:
01332         // According to 22.2.6.1.2, p2, symbol is required
01333         // if (__io.flags() & ios_base::showbase), otherwise
01334         // is optional and consumed only if other characters
01335         // are needed to complete the format.
01336         if (__io.flags() & ios_base::showbase || __sign_size > 1
01337             || __i == 0
01338             || (__i == 1 && (__mandatory_sign
01339                      || (static_cast<part>(__p.field[0])
01340                      == money_base::sign)
01341                      || (static_cast<part>(__p.field[2])
01342                      == money_base::space)))
01343             || (__i == 2 && ((static_cast<part>(__p.field[3])
01344                       == money_base::value)
01345                      || __mandatory_sign
01346                      && (static_cast<part>(__p.field[3])
01347                      == money_base::sign))))
01348           {
01349             const size_type __len = __lc->_M_curr_symbol_size;
01350             size_type __j = 0;
01351             for (; __beg != __end && __j < __len
01352                && *__beg == __lc->_M_curr_symbol[__j];
01353              ++__beg, ++__j);
01354             if (__j != __len
01355             && (__j || __io.flags() & ios_base::showbase))
01356               __testvalid = false;
01357           }
01358         break;
01359           case money_base::sign:
01360         // Sign might not exist, or be more than one character long.
01361         if (__lc->_M_positive_sign_size && __beg != __end
01362             && *__beg == __lc->_M_positive_sign[0])
01363           {
01364             __sign_size = __lc->_M_positive_sign_size;
01365             ++__beg;
01366           }
01367         else if (__lc->_M_negative_sign_size && __beg != __end
01368              && *__beg == __lc->_M_negative_sign[0])
01369           {
01370             __negative = true;
01371             __sign_size = __lc->_M_negative_sign_size;
01372             ++__beg;
01373           }
01374         else if (__lc->_M_positive_sign_size
01375              && !__lc->_M_negative_sign_size)
01376           // "... if no sign is detected, the result is given the sign
01377           // that corresponds to the source of the empty string"
01378           __negative = true;
01379         else if (__mandatory_sign)
01380           __testvalid = false;
01381         break;
01382           case money_base::value:
01383         // Extract digits, remove and stash away the
01384         // grouping of found thousands separators.
01385         for (; __beg != __end; ++__beg)
01386           {
01387             const char_type __c = *__beg;
01388             const char_type* __q = __traits_type::find(__lit_zero, 
01389                                    10, __c);
01390             if (__q != 0)
01391               {
01392             __res += money_base::_S_atoms[__q - __lit];
01393             ++__n;
01394               }
01395             else if (__c == __lc->_M_decimal_point 
01396                  && !__testdecfound)
01397               {
01398             __last_pos = __n;
01399             __n = 0;
01400             __testdecfound = true;
01401               }
01402             else if (__lc->_M_use_grouping
01403                  && __c == __lc->_M_thousands_sep
01404                  && !__testdecfound)
01405               {
01406             if (__n)
01407               {
01408                 // Mark position for later analysis.
01409                 __grouping_tmp += static_cast<char>(__n);
01410                 __n = 0;
01411               }
01412             else
01413               {
01414                 __testvalid = false;
01415                 break;
01416               }
01417               }
01418             else
01419               break;
01420           }
01421         if (__res.empty())
01422           __testvalid = false;
01423         break;
01424           case money_base::space:
01425         // At least one space is required.
01426         if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
01427           ++__beg;
01428         else
01429           __testvalid = false;
01430           case money_base::none:
01431         // Only if not at the end of the pattern.
01432         if (__i != 3)
01433           for (; __beg != __end
01434              && __ctype.is(ctype_base::space, *__beg); ++__beg);
01435         break;
01436           }
01437       }
01438 
01439     // Need to get the rest of the sign characters, if they exist.
01440     if (__sign_size > 1 && __testvalid)
01441       {
01442         const char_type* __sign = __negative ? __lc->_M_negative_sign
01443                                              : __lc->_M_positive_sign;
01444         size_type __i = 1;
01445         for (; __beg != __end && __i < __sign_size
01446            && *__beg == __sign[__i]; ++__beg, ++__i);
01447         
01448         if (__i != __sign_size)
01449           __testvalid = false;
01450       }
01451 
01452     if (__testvalid)
01453       {
01454         // Strip leading zeros.
01455         if (__res.size() > 1)
01456           {
01457         const size_type __first = __res.find_first_not_of('0');
01458         const bool __only_zeros = __first == string::npos;
01459         if (__first)
01460           __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
01461           }
01462 
01463         // 22.2.6.1.2, p4
01464         if (__negative && __res[0] != '0')
01465           __res.insert(__res.begin(), '-');
01466         
01467         // Test for grouping fidelity.
01468         if (__grouping_tmp.size())
01469           {
01470         // Add the ending grouping.
01471         __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
01472                                            : __n);
01473         if (!std::__verify_grouping(__lc->_M_grouping,
01474                         __lc->_M_grouping_size,
01475                         __grouping_tmp))
01476           __testvalid = false;
01477           }
01478         
01479         // Iff not enough digits were supplied after the decimal-point.
01480         if (__testdecfound && __lc->_M_frac_digits > 0
01481         && __n != __lc->_M_frac_digits)
01482           __testvalid = false;
01483       }
01484     
01485     // Iff valid sequence is not recognized.
01486     if (!__testvalid)
01487       __err |= ios_base::failbit;
01488     else
01489       __units.swap(__res);
01490     
01491     // Iff no more characters are available.
01492     if (__beg == __end)
01493       __err |= ios_base::eofbit;
01494     return __beg;
01495       }
01496 
01497   template<typename _CharT, typename _InIter>
01498     _InIter
01499     money_get<_CharT, _InIter>::
01500     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
01501        ios_base::iostate& __err, long double& __units) const
01502     {
01503       string __str;
01504       if (__intl)
01505     __beg = _M_extract<true>(__beg, __end, __io, __err, __str);
01506       else
01507     __beg = _M_extract<false>(__beg, __end, __io, __err, __str);
01508       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
01509       return __beg;
01510     }
01511 
01512   template<typename _CharT, typename _InIter>
01513     _InIter
01514     money_get<_CharT, _InIter>::
01515     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
01516        ios_base::iostate& __err, string_type& __units) const
01517     {
01518       typedef typename string::size_type                  size_type;
01519 
01520       const locale& __loc = __io._M_getloc();
01521       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01522 
01523       string __str;
01524       const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io,
01525                             __err, __str)
01526                                  : _M_extract<false>(__beg, __end, __io,
01527                              __err, __str);
01528       const size_type __len = __str.size();
01529       if (__len)
01530     {
01531       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01532                                    * __len));
01533       __ctype.widen(__str.data(), __str.data() + __len, __ws);
01534       __units.assign(__ws, __len);
01535     }
01536 
01537       return __ret;
01538     }
01539 
01540   template<typename _CharT, typename _OutIter>
01541     template<bool _Intl>
01542       _OutIter
01543       money_put<_CharT, _OutIter>::
01544       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
01545         const string_type& __digits) const
01546       {
01547     typedef typename string_type::size_type           size_type;
01548     typedef money_base::part                          part;
01549     typedef moneypunct<_CharT, _Intl>                 __moneypunct_type;
01550     typedef typename __moneypunct_type::__cache_type  __cache_type;
01551       
01552     const locale& __loc = __io._M_getloc();
01553     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01554 
01555     __use_cache<__cache_type> __uc;
01556     const __cache_type* __lc = __uc(__loc);
01557     const char_type* __lit = __lc->_M_atoms;
01558 
01559     // Determine if negative or positive formats are to be used, and
01560     // discard leading negative_sign if it is present.
01561     const char_type* __beg = __digits.data();
01562 
01563     money_base::pattern __p;
01564     const char_type* __sign;
01565     size_type __sign_size;
01566     if (*__beg != __lit[money_base::_S_minus])
01567       {
01568         __p = __lc->_M_pos_format;
01569         __sign = __lc->_M_positive_sign;
01570         __sign_size = __lc->_M_positive_sign_size;
01571       }
01572     else
01573       {
01574         __p = __lc->_M_neg_format;
01575         __sign = __lc->_M_negative_sign;
01576         __sign_size = __lc->_M_negative_sign_size;
01577         if (__digits.size())
01578           ++__beg;
01579       }
01580        
01581     // Look for valid numbers in the ctype facet within input digits.
01582     size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
01583                        __beg + __digits.size()) - __beg;
01584     if (__len)
01585       {
01586         // Assume valid input, and attempt to format.
01587         // Break down input numbers into base components, as follows:
01588         //   final_value = grouped units + (decimal point) + (digits)
01589         string_type __value;
01590         __value.reserve(2 * __len);
01591 
01592         // Add thousands separators to non-decimal digits, per
01593         // grouping rules.
01594         int __paddec = __len - __lc->_M_frac_digits;
01595         if (__paddec > 0)
01596           {
01597         if (__lc->_M_frac_digits < 0)
01598           __paddec = __len;
01599         if (__lc->_M_grouping_size)
01600           {
01601             _CharT* __ws =
01602               static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01603                                 * 2 * __len));
01604             _CharT* __ws_end =
01605               std::__add_grouping(__ws, __lc->_M_thousands_sep,
01606                       __lc->_M_grouping,
01607                       __lc->_M_grouping_size,
01608                       __beg, __beg + __paddec);
01609             __value.assign(__ws, __ws_end - __ws);
01610           }
01611         else
01612           __value.assign(__beg, __paddec);
01613           }
01614 
01615         // Deal with decimal point, decimal digits.
01616         if (__lc->_M_frac_digits > 0)
01617           {
01618         __value += __lc->_M_decimal_point;
01619         if (__paddec >= 0)
01620           __value.append(__beg + __paddec, __lc->_M_frac_digits);
01621         else
01622           {
01623             // Have to pad zeros in the decimal position.
01624             __value.append(-__paddec, __lit[money_base::_S_zero]);
01625             __value.append(__beg, __len);
01626           }
01627           }
01628   
01629         // Calculate length of resulting string.
01630         const ios_base::fmtflags __f = __io.flags() 
01631                                        & ios_base::adjustfield;
01632         __len = __value.size() + __sign_size;
01633         __len += ((__io.flags() & ios_base::showbase)
01634               ? __lc->_M_curr_symbol_size : 0);
01635 
01636         string_type __res;
01637         __res.reserve(2 * __len);
01638         
01639         const size_type __width = static_cast<size_type>(__io.width());  
01640         const bool __testipad = (__f == ios_base::internal
01641                      && __len < __width);
01642         // Fit formatted digits into the required pattern.
01643         for (int __i = 0; __i < 4; ++__i)
01644           {
01645         const part __which = static_cast<part>(__p.field[__i]);
01646         switch (__which)
01647           {
01648           case money_base::symbol:
01649             if (__io.flags() & ios_base::showbase)
01650               __res.append(__lc->_M_curr_symbol,
01651                    __lc->_M_curr_symbol_size);
01652             break;
01653           case money_base::sign:
01654             // Sign might not exist, or be more than one
01655             // charater long. In that case, add in the rest
01656             // below.
01657             if (__sign_size)
01658               __res += __sign[0];
01659             break;
01660           case money_base::value:
01661             __res += __value;
01662             break;
01663           case money_base::space:
01664             // At least one space is required, but if internal
01665             // formatting is required, an arbitrary number of
01666             // fill spaces will be necessary.
01667             if (__testipad)
01668               __res.append(__width - __len, __fill);
01669             else
01670               __res += __fill;
01671             break;
01672           case money_base::none:
01673             if (__testipad)
01674               __res.append(__width - __len, __fill);
01675             break;
01676           }
01677           }
01678         
01679         // Special case of multi-part sign parts.
01680         if (__sign_size > 1)
01681           __res.append(__sign + 1, __sign_size - 1);
01682         
01683         // Pad, if still necessary.
01684         __len = __res.size();
01685         if (__width > __len)
01686           {
01687         if (__f == ios_base::left)
01688           // After.
01689           __res.append(__width - __len, __fill);
01690         else
01691           // Before.
01692           __res.insert(0, __width - __len, __fill);
01693         __len = __width;
01694           }
01695         
01696         // Write resulting, fully-formatted string to output iterator.
01697         __s = std::__write(__s, __res.data(), __len);
01698       }
01699     __io.width(0);
01700     return __s;    
01701       }
01702   
01703   template<typename _CharT, typename _OutIter>
01704     _OutIter
01705     money_put<_CharT, _OutIter>::
01706     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01707        long double __units) const
01708     {
01709       const locale __loc = __io.getloc();
01710       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01711 #ifdef _GLIBCXX_USE_C99
01712       // First try a buffer perhaps big enough.
01713       int __cs_size = 64;
01714       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01715       // _GLIBCXX_RESOLVE_LIB_DEFECTS
01716       // 328. Bad sprintf format modifier in money_put<>::do_put()
01717       int __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
01718                     _S_get_c_locale(), 0);
01719       // If the buffer was not large enough, try again with the correct size.
01720       if (__len >= __cs_size)
01721     {
01722       __cs_size = __len + 1;
01723       __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01724       __len = std::__convert_from_v(__cs, __cs_size, "%.*Lf", __units,
01725                     _S_get_c_locale(), 0);
01726     }
01727 #else
01728       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
01729       const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
01730       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
01731       int __len = std::__convert_from_v(__cs, 0, "%.*Lf", __units,
01732                     _S_get_c_locale(), 0);
01733 #endif
01734       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
01735                                * __cs_size));
01736       __ctype.widen(__cs, __cs + __len, __ws);
01737       const string_type __digits(__ws, __len);
01738       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
01739                 : _M_insert<false>(__s, __io, __fill, __digits);
01740     }
01741 
01742   template<typename _CharT, typename _OutIter>
01743     _OutIter
01744     money_put<_CharT, _OutIter>::
01745     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
01746        const string_type& __digits) const
01747     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
01748                 : _M_insert<false>(__s, __io, __fill, __digits); }
01749 
01750 
01751   // NB: Not especially useful. Without an ios_base object or some
01752   // kind of locale reference, we are left clawing at the air where
01753   // the side of the mountain used to be...
01754   template<typename _CharT, typename _InIter>
01755     time_base::dateorder
01756     time_get<_CharT, _InIter>::do_date_order() const
01757     { return time_base::no_order; }
01758 
01759   // Expand a strftime format string and parse it.  E.g., do_get_date() may
01760   // pass %m/%d/%Y => extracted characters.
01761   template<typename _CharT, typename _InIter>
01762     _InIter
01763     time_get<_CharT, _InIter>::
01764     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
01765               ios_base::iostate& __err, tm* __tm,
01766               const _CharT* __format) const
01767     {
01768       const locale& __loc = __io._M_getloc();
01769       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01770       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01771       const size_t __len = char_traits<_CharT>::length(__format);
01772 
01773       for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
01774     {
01775       if (__ctype.narrow(__format[__i], 0) == '%')
01776         {
01777           // Verify valid formatting code, attempt to extract.
01778           char __c = __ctype.narrow(__format[++__i], 0);
01779           int __mem = 0;
01780           if (__c == 'E' || __c == 'O')
01781         __c = __ctype.narrow(__format[++__i], 0);
01782           switch (__c)
01783         {
01784           const char* __cs;
01785           _CharT __wcs[10];
01786         case 'a':
01787           // Abbreviated weekday name [tm_wday]
01788           const char_type*  __days1[7];
01789           __tp._M_days_abbreviated(__days1);
01790           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
01791                       7, __io, __err);
01792           break;
01793         case 'A':
01794           // Weekday name [tm_wday].
01795           const char_type*  __days2[7];
01796           __tp._M_days(__days2);
01797           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
01798                       7, __io, __err);
01799           break;
01800         case 'h':
01801         case 'b':
01802           // Abbreviated month name [tm_mon]
01803           const char_type*  __months1[12];
01804           __tp._M_months_abbreviated(__months1);
01805           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
01806                       __months1, 12, __io, __err);
01807           break;
01808         case 'B':
01809           // Month name [tm_mon].
01810           const char_type*  __months2[12];
01811           __tp._M_months(__months2);
01812           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
01813                       __months2, 12, __io, __err);
01814           break;
01815         case 'c':
01816           // Default time and date representation.
01817           const char_type*  __dt[2];
01818           __tp._M_date_time_formats(__dt);
01819           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01820                         __tm, __dt[0]);
01821           break;
01822         case 'd':
01823           // Day [01, 31]. [tm_mday]
01824           __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
01825                      __io, __err);
01826           break;
01827         case 'e':
01828           // Day [1, 31], with single digits preceded by
01829           // space. [tm_mday]
01830           if (__ctype.is(ctype_base::space, *__beg))
01831             __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
01832                        1, __io, __err);
01833           else
01834             __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
01835                        2, __io, __err);
01836           break;
01837         case 'D':
01838           // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
01839           __cs = "%m/%d/%y";
01840           __ctype.widen(__cs, __cs + 9, __wcs);
01841           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01842                         __tm, __wcs);
01843           break;
01844         case 'H':
01845           // Hour [00, 23]. [tm_hour]
01846           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
01847                      __io, __err);
01848           break;
01849         case 'I':
01850           // Hour [01, 12]. [tm_hour]
01851           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
01852                      __io, __err);
01853           break;
01854         case 'm':
01855           // Month [01, 12]. [tm_mon]
01856           __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
01857                      __io, __err);
01858           if (!__err)
01859             __tm->tm_mon = __mem - 1;
01860           break;
01861         case 'M':
01862           // Minute [00, 59]. [tm_min]
01863           __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
01864                      __io, __err);
01865           break;
01866         case 'n':
01867           if (__ctype.narrow(*__beg, 0) == '\n')
01868             ++__beg;
01869           else
01870             __err |= ios_base::failbit;
01871           break;
01872         case 'R':
01873           // Equivalent to (%H:%M).
01874           __cs = "%H:%M";
01875           __ctype.widen(__cs, __cs + 6, __wcs);
01876           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01877                         __tm, __wcs);
01878           break;
01879         case 'S':
01880           // Seconds. [tm_sec]
01881           // [00, 60] in C99 (one leap-second), [00, 61] in C89.
01882 #ifdef _GLIBCXX_USE_C99
01883           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
01884 #else
01885           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
01886 #endif
01887                      __io, __err);
01888           break;
01889         case 't':
01890           if (__ctype.narrow(*__beg, 0) == '\t')
01891             ++__beg;
01892           else
01893             __err |= ios_base::failbit;
01894           break;
01895         case 'T':
01896           // Equivalent to (%H:%M:%S).
01897           __cs = "%H:%M:%S";
01898           __ctype.widen(__cs, __cs + 9, __wcs);
01899           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01900                         __tm, __wcs);
01901           break;
01902         case 'x':
01903           // Locale's date.
01904           const char_type*  __dates[2];
01905           __tp._M_date_formats(__dates);
01906           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01907                         __tm, __dates[0]);
01908           break;
01909         case 'X':
01910           // Locale's time.
01911           const char_type*  __times[2];
01912           __tp._M_time_formats(__times);
01913           __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01914                         __tm, __times[0]);
01915           break;
01916         case 'y':
01917         case 'C': // C99
01918           // Two digit year. [tm_year]
01919           __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
01920                      __io, __err);
01921           break;
01922         case 'Y':
01923           // Year [1900). [tm_year]
01924           __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
01925                      __io, __err);
01926           if (!__err)
01927             __tm->tm_year = __mem - 1900;
01928           break;
01929         case 'Z':
01930           // Timezone info.
01931           if (__ctype.is(ctype_base::upper, *__beg))
01932             {
01933               int __tmp;
01934               __beg = _M_extract_name(__beg, __end, __tmp,
01935                        __timepunct_cache<_CharT>::_S_timezones,
01936                           14, __io, __err);
01937 
01938               // GMT requires special effort.
01939               if (__beg != __end && !__err && __tmp == 0
01940               && (*__beg == __ctype.widen('-')
01941                   || *__beg == __ctype.widen('+')))
01942             {
01943               __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
01944                          __io, __err);
01945               __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
01946                          __io, __err);
01947             }
01948             }
01949           else
01950             __err |= ios_base::failbit;
01951           break;
01952         default:
01953           // Not recognized.
01954           __err |= ios_base::failbit;
01955         }
01956         }
01957       else
01958         {
01959           // Verify format and input match, extract and discard.
01960           if (__format[__i] == *__beg)
01961         ++__beg;
01962           else
01963         __err |= ios_base::failbit;
01964         }
01965     }
01966       return __beg;
01967     }
01968 
01969   template<typename _CharT, typename _InIter>
01970     _InIter
01971     time_get<_CharT, _InIter>::
01972     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
01973            int __min, int __max, size_t __len,
01974            ios_base& __io, ios_base::iostate& __err) const
01975     {
01976       const locale& __loc = __io._M_getloc();
01977       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01978 
01979       // As-is works for __len = 1, 2, 4, the values actually used.
01980       int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
01981 
01982       ++__min;
01983       size_t __i = 0;
01984       int __value = 0;
01985       for (; __beg != __end && __i < __len; ++__beg, ++__i)
01986     {
01987       const char __c = __ctype.narrow(*__beg, '*');
01988       if (__c >= '0' && __c <= '9')
01989         {
01990           __value = __value * 10 + (__c - '0');
01991           const int __valuec = __value * __mult;
01992           if (__valuec > __max || __valuec + __mult < __min)
01993         break;
01994           __mult /= 10;
01995         }
01996       else
01997         break;
01998     }
01999       if (__i == __len)
02000     __member = __value;
02001       else
02002     __err |= ios_base::failbit;
02003       return __beg;
02004     }
02005 
02006   // Assumptions:
02007   // All elements in __names are unique.
02008   template<typename _CharT, typename _InIter>
02009     _InIter
02010     time_get<_CharT, _InIter>::
02011     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
02012             const _CharT** __names, size_t __indexlen,
02013             ios_base& __io, ios_base::iostate& __err) const
02014     {
02015       typedef char_traits<_CharT>       __traits_type;
02016       const locale& __loc = __io._M_getloc();
02017       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02018 
02019       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
02020                               * __indexlen));
02021       size_t __nmatches = 0;
02022       size_t __pos = 0;
02023       bool __testvalid = true;
02024       const char_type* __name;
02025 
02026       // Look for initial matches.
02027       // NB: Some of the locale data is in the form of all lowercase
02028       // names, and some is in the form of initially-capitalized
02029       // names. Look for both.
02030       if (__beg != __end)
02031     {
02032       const char_type __c = *__beg;
02033       for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
02034         if (__c == __names[__i1][0]
02035         || __c == __ctype.toupper(__names[__i1][0]))
02036           __matches[__nmatches++] = __i1;
02037     }
02038 
02039       while (__nmatches > 1)
02040     {
02041       // Find smallest matching string.
02042       size_t __minlen = __traits_type::length(__names[__matches[0]]);
02043       for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
02044         __minlen = std::min(__minlen,
02045                   __traits_type::length(__names[__matches[__i2]]));
02046       ++__beg, ++__pos;
02047       if (__pos < __minlen && __beg != __end)
02048         for (size_t __i3 = 0; __i3 < __nmatches;)
02049           {
02050         __name = __names[__matches[__i3]];
02051         if (__name[__pos] != *__beg)
02052           __matches[__i3] = __matches[--__nmatches];
02053         else
02054           ++__i3;
02055           }
02056       else
02057         break;
02058     }
02059 
02060       if (__nmatches == 1)
02061     {
02062       // Make sure found name is completely extracted.
02063       ++__beg, ++__pos;
02064       __name = __names[__matches[0]];
02065       const size_t __len = __traits_type::length(__name);
02066       while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
02067         ++__beg, ++__pos;
02068 
02069       if (__len == __pos)
02070         __member = __matches[0];
02071       else
02072         __testvalid = false;
02073     }
02074       else
02075     __testvalid = false;
02076       if (!__testvalid)
02077     __err |= ios_base::failbit;
02078       return __beg;
02079     }
02080 
02081   template<typename _CharT, typename _InIter>
02082     _InIter
02083     time_get<_CharT, _InIter>::
02084     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
02085         ios_base::iostate& __err, tm* __tm) const
02086     {
02087       const locale& __loc = __io._M_getloc();
02088       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02089       const char_type*  __times[2];
02090       __tp._M_time_formats(__times);
02091       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
02092                     __tm, __times[0]);
02093       if (__beg == __end)
02094     __err |= ios_base::eofbit;
02095       return __beg;
02096     }
02097 
02098   template<typename _CharT, typename _InIter>
02099     _InIter
02100     time_get<_CharT, _InIter>::
02101     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
02102         ios_base::iostate& __err, tm* __tm) const
02103     {
02104       const locale& __loc = __io._M_getloc();
02105       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02106       const char_type*  __dates[2];
02107       __tp._M_date_formats(__dates);
02108       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
02109                     __tm, __dates[0]);
02110       if (__beg == __end)
02111     __err |= ios_base::eofbit;
02112       return __beg;
02113     }
02114 
02115   template<typename _CharT, typename _InIter>
02116     _InIter
02117     time_get<_CharT, _InIter>::
02118     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
02119            ios_base::iostate& __err, tm* __tm) const
02120     {
02121       typedef char_traits<_CharT>       __traits_type;
02122       const locale& __loc = __io._M_getloc();
02123       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02124       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02125       const char_type*  __days[7];
02126       __tp._M_days_abbreviated(__days);
02127       int __tmpwday;
02128       __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7, __io, __err);
02129 
02130       // Check to see if non-abbreviated name exists, and extract.
02131       // NB: Assumes both _M_days and _M_days_abbreviated organized in
02132       // exact same order, first to last, such that the resulting
02133       // __days array with the same index points to a day, and that
02134       // day's abbreviated form.
02135       // NB: Also assumes that an abbreviated name is a subset of the name.
02136       if (!__err && __beg != __end)
02137     {
02138       size_t __pos = __traits_type::length(__days[__tmpwday]);
02139       __tp._M_days(__days);
02140       const char_type* __name = __days[__tmpwday];
02141       if (__name[__pos] == *__beg)
02142         {
02143           // Extract the rest of it.
02144           const size_t __len = __traits_type::length(__name);
02145           while (__pos < __len && __beg != __end
02146              && __name[__pos] == *__beg)
02147         ++__beg, ++__pos;
02148           if (__len != __pos)
02149         __err |= ios_base::failbit;
02150         }
02151     }
02152       if (!__err)
02153     __tm->tm_wday = __tmpwday;
02154       
02155       if (__beg == __end)
02156     __err |= ios_base::eofbit;
02157       return __beg;
02158      }
02159 
02160   template<typename _CharT, typename _InIter>
02161     _InIter
02162     time_get<_CharT, _InIter>::
02163     do_get_monthname(iter_type __beg, iter_type __end,
02164                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
02165     {
02166       typedef char_traits<_CharT>       __traits_type;
02167       const locale& __loc = __io._M_getloc();
02168       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
02169       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02170       const char_type*  __months[12];
02171       __tp._M_months_abbreviated(__months);
02172       int __tmpmon;
02173       __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12, 
02174                   __io, __err);
02175 
02176       // Check to see if non-abbreviated name exists, and extract.
02177       // NB: Assumes both _M_months and _M_months_abbreviated organized in
02178       // exact same order, first to last, such that the resulting
02179       // __months array with the same index points to a month, and that
02180       // month's abbreviated form.
02181       // NB: Also assumes that an abbreviated name is a subset of the name.
02182       if (!__err && __beg != __end)
02183     {
02184       size_t __pos = __traits_type::length(__months[__tmpmon]);
02185       __tp._M_months(__months);
02186       const char_type* __name = __months[__tmpmon];
02187       if (__name[__pos] == *__beg)
02188         {
02189           // Extract the rest of it.
02190           const size_t __len = __traits_type::length(__name);
02191           while (__pos < __len && __beg != __end
02192              && __name[__pos] == *__beg)
02193         ++__beg, ++__pos;
02194           if (__len != __pos)
02195         __err |= ios_base::failbit;
02196         }
02197     }
02198       if (!__err)
02199     __tm->tm_mon = __tmpmon;
02200 
02201       if (__beg == __end)
02202     __err |= ios_base::eofbit;
02203       return __beg;
02204     }
02205 
02206   template<typename _CharT, typename _InIter>
02207     _InIter
02208     time_get<_CharT, _InIter>::
02209     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
02210         ios_base::iostate& __err, tm* __tm) const
02211     {
02212       const locale& __loc = __io._M_getloc();
02213       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02214 
02215       size_t __i = 0;
02216       int __value = 0;
02217       for (; __beg != __end && __i < 4; ++__beg, ++__i)
02218     {
02219       const char __c = __ctype.narrow(*__beg, '*');
02220       if (__c >= '0' && __c <= '9')
02221         __value = __value * 10 + (__c - '0');
02222       else
02223         break;
02224     }
02225       if (__i == 2 || __i == 4)
02226     __tm->tm_year = __i == 2 ? __value : __value - 1900;
02227       else
02228     __err |= ios_base::failbit;
02229       if (__beg == __end)
02230     __err |= ios_base::eofbit;
02231       return __beg;
02232     }
02233 
02234   template<typename _CharT, typename _OutIter>
02235     _OutIter
02236     time_put<_CharT, _OutIter>::
02237     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
02238     const _CharT* __beg, const _CharT* __end) const
02239     {
02240       const locale& __loc = __io._M_getloc();
02241       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
02242       for (; __beg != __end; ++__beg)
02243     if (__ctype.narrow(*__beg, 0) != '%')
02244       {
02245         *__s = *__beg;
02246         ++__s;
02247       }
02248     else if (++__beg != __end)
02249       {
02250         char __format;
02251         char __mod = 0;
02252         const char __c = __ctype.narrow(*__beg, 0);
02253         if (__c != 'E' && __c != 'O')
02254           __format = __c;
02255         else if (++__beg != __end)
02256           {
02257         __mod = __c;
02258         __format = __ctype.narrow(*__beg, 0);
02259           }
02260         else
02261           break;
02262         __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
02263       }
02264     else
02265       break;
02266       return __s;
02267     }
02268 
02269   template<typename _CharT, typename _OutIter>
02270     _OutIter
02271     time_put<_CharT, _OutIter>::
02272     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
02273        char __format, char __mod) const
02274     {
02275       const locale& __loc = __io._M_getloc();
02276       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
02277       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
02278 
02279       // NB: This size is arbitrary. Should this be a data member,
02280       // initialized at construction?
02281       const size_t __maxlen = 128;
02282       char_type* __res = 
02283        static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
02284 
02285       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
02286       // is possible that the format character will be longer than one
02287       // character. Possibilities include 'E' or 'O' followed by a
02288       // format character: if __mod is not the default argument, assume
02289       // it's a valid modifier.
02290       char_type __fmt[4];
02291       __fmt[0] = __ctype.widen('%');
02292       if (!__mod)
02293     {
02294       __fmt[1] = __format;
02295       __fmt[2] = char_type();
02296     }
02297       else
02298     {
02299       __fmt[1] = __mod;
02300       __fmt[2] = __format;
02301       __fmt[3] = char_type();
02302     }
02303 
02304       __tp._M_put(__res, __maxlen, __fmt, __tm);
02305 
02306       // Write resulting, fully-formatted string to output iterator.
02307       return std::__write(__s, __res, char_traits<char_type>::length(__res));
02308     }
02309 
02310   // Generic version does nothing.
02311   template<typename _CharT>
02312     int
02313     collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
02314     { return 0; }
02315 
02316   // Generic version does nothing.
02317   template<typename _CharT>
02318     size_t
02319     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
02320     { return 0; }
02321 
02322   template<typename _CharT>
02323     int
02324     collate<_CharT>::
02325     do_compare(const _CharT* __lo1, const _CharT* __hi1,
02326            const _CharT* __lo2, const _CharT* __hi2) const
02327     {
02328       // strcoll assumes zero-terminated strings so we make a copy
02329       // and then put a zero at the end.
02330       const string_type __one(__lo1, __hi1);
02331       const string_type __two(__lo2, __hi2);
02332 
02333       const _CharT* __p = __one.c_str();
02334       const _CharT* __pend = __one.data() + __one.length();
02335       const _CharT* __q = __two.c_str();
02336       const _CharT* __qend = __two.data() + __two.length();
02337 
02338       // strcoll stops when it sees a nul character so we break
02339       // the strings into zero-terminated substrings and pass those
02340       // to strcoll.
02341       for (;;)
02342     {
02343       const int __res = _M_compare(__p, __q);
02344       if (__res)
02345         return __res;
02346 
02347       __p += char_traits<_CharT>::length(__p);
02348       __q += char_traits<_CharT>::length(__q);
02349       if (__p == __pend && __q == __qend)
02350         return 0;
02351       else if (__p == __pend)
02352         return -1;
02353       else if (__q == __qend)
02354         return 1;
02355 
02356       __p++;
02357       __q++;
02358     }
02359     }
02360 
02361   template<typename _CharT>
02362     typename collate<_CharT>::string_type
02363     collate<_CharT>::
02364     do_transform(const _CharT* __lo, const _CharT* __hi) const
02365     {
02366       // strxfrm assumes zero-terminated strings so we make a copy
02367       string_type __str(__lo, __hi);
02368 
02369       const _CharT* __p = __str.c_str();
02370       const _CharT* __pend = __str.data() + __str.length();
02371 
02372       size_t __len = (__hi - __lo) * 2;
02373 
02374       string_type __ret;
02375 
02376       // strxfrm stops when it sees a nul character so we break
02377       // the string into zero-terminated substrings and pass those
02378       // to strxfrm.
02379       for (;;)
02380     {
02381       // First try a buffer perhaps big enough.
02382       _CharT* __c =
02383         static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
02384       size_t __res = _M_transform(__c, __p, __len);
02385       // If the buffer was not large enough, try again with the
02386       // correct size.
02387       if (__res >= __len)
02388         {
02389           __len = __res + 1;
02390           __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
02391                               * __len));
02392           __res = _M_transform(__c, __p, __len);
02393         }
02394 
02395       __ret.append(__c, __res);
02396       __p += char_traits<_CharT>::length(__p);
02397       if (__p == __pend)
02398         return __ret;
02399 
02400       __p++;
02401       __ret.push_back(_CharT());
02402     }
02403     }
02404 
02405   template<typename _CharT>
02406     long
02407     collate<_CharT>::
02408     do_hash(const _CharT* __lo, const _CharT* __hi) const
02409     {
02410       unsigned long __val = 0;
02411       for (; __lo < __hi; ++__lo)
02412     __val = *__lo + ((__val << 7) |
02413                (__val >> (numeric_limits<unsigned long>::digits - 7)));
02414       return static_cast<long>(__val);
02415     }
02416 
02417   // Construct correctly padded string, as per 22.2.2.2.2
02418   // Assumes
02419   // __newlen > __oldlen
02420   // __news is allocated for __newlen size
02421   // Used by both num_put and ostream inserters: if __num,
02422   // internal-adjusted objects are padded according to the rules below
02423   // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
02424   // ones are.
02425 
02426   // NB: Of the two parameters, _CharT can be deduced from the
02427   // function arguments. The other (_Traits) has to be explicitly specified.
02428   template<typename _CharT, typename _Traits>
02429     void
02430     __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
02431                    _CharT* __news, const _CharT* __olds,
02432                    const streamsize __newlen,
02433                    const streamsize __oldlen, const bool __num)
02434     {
02435       const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
02436       const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
02437 
02438       // Padding last.
02439       if (__adjust == ios_base::left)
02440     {
02441       _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen);
02442       _Traits::assign(__news + __oldlen, __plen, __fill);
02443       return;
02444     }
02445 
02446       size_t __mod = 0;
02447       if (__adjust == ios_base::internal && __num)
02448     {
02449       // Pad after the sign, if there is one.
02450       // Pad after 0[xX], if there is one.
02451       // Who came up with these rules, anyway? Jeeze.
02452           const locale& __loc = __io._M_getloc();
02453       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
02454 
02455       const bool __testsign = (__ctype.widen('-') == __olds[0]
02456                    || __ctype.widen('+') == __olds[0]);
02457       const bool __testhex = (__ctype.widen('0') == __olds[0]
02458                   && __oldlen > 1
02459                   && (__ctype.widen('x') == __olds[1]
02460                       || __ctype.widen('X') == __olds[1]));
02461       if (__testhex)
02462         {
02463           __news[0] = __olds[0];
02464           __news[1] = __olds[1];
02465           __mod = 2;
02466           __news += 2;
02467         }
02468       else if (__testsign)
02469         {
02470           __news[0] = __olds[0];
02471           __mod = 1;
02472           ++__news;
02473         }
02474       // else Padding first.
02475     }
02476       _Traits::assign(__news, __plen, __fill);
02477       _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod),
02478             __oldlen - __mod);
02479     }
02480 
02481   bool
02482   __verify_grouping(const char* __grouping, size_t __grouping_size,
02483             const string& __grouping_tmp)
02484   {
02485     const size_t __n = __grouping_tmp.size() - 1;
02486     const size_t __min = std::min(__n, size_t(__grouping_size - 1));
02487     size_t __i = __n;
02488     bool __test = true;
02489     
02490     // Parsed number groupings have to match the
02491     // numpunct::grouping string exactly, starting at the
02492     // right-most point of the parsed sequence of elements ...
02493     for (size_t __j = 0; __j < __min && __test; --__i, ++__j)
02494       __test = __grouping_tmp[__i] == __grouping[__j];
02495     for (; __i && __test; --__i)
02496       __test = __grouping_tmp[__i] == __grouping[__min];
02497     // ... but the last parsed grouping can be <= numpunct
02498     // grouping.
02499     __test &= __grouping_tmp[0] <= __grouping[__min];
02500     return __test;
02501   }
02502 
02503   template<typename _CharT>
02504     _CharT*
02505     __add_grouping(_CharT* __s, _CharT __sep,
02506            const char* __gbeg, size_t __gsize,
02507            const _CharT* __first, const _CharT* __last)
02508     {
02509       if (__last - __first > *__gbeg)
02510     {
02511       const bool __bump = __gsize != 1;
02512       __s = std::__add_grouping(__s,  __sep, __gbeg + __bump,
02513                     __gsize - __bump, __first,
02514                     __last - *__gbeg);
02515       __first = __last - *__gbeg;
02516       *__s++ = __sep;
02517     }
02518       do
02519     *__s++ = *__first++;
02520       while (__first != __last);
02521       return __s;
02522     }
02523 
02524   // Inhibit implicit instantiations for required instantiations,
02525   // which are defined via explicit instantiations elsewhere.
02526   // NB: This syntax is a GNU extension.
02527 #if _GLIBCXX_EXTERN_TEMPLATE
02528   extern template class moneypunct<char, false>;
02529   extern template class moneypunct<char, true>;
02530   extern template class moneypunct_byname<char, false>;
02531   extern template class moneypunct_byname<char, true>;
02532   extern template class money_get<char>;
02533   extern template class money_put<char>;
02534   extern template class numpunct<char>;
02535   extern template class numpunct_byname<char>;
02536   extern template class num_get<char>;
02537   extern template class num_put<char>;
02538   extern template class __timepunct<char>;
02539   extern template class time_put<char>;
02540   extern template class time_put_byname<char>;
02541   extern template class time_get<char>;
02542   extern template class time_get_byname<char>;
02543   extern template class messages<char>;
02544   extern template class messages_byname<char>;
02545   extern template class ctype_byname<char>;
02546   extern template class codecvt_byname<char, char, mbstate_t>;
02547   extern template class collate<char>;
02548   extern template class collate_byname<char>;
02549 
02550   extern template
02551     const codecvt<char, char, mbstate_t>&
02552     use_facet<codecvt<char, char, mbstate_t> >(const locale&);
02553 
02554   extern template
02555     const collate<char>&
02556     use_facet<collate<char> >(const locale&);
02557 
02558   extern template
02559     const numpunct<char>&
02560     use_facet<numpunct<char> >(const locale&);
02561 
02562   extern template
02563     const num_put<char>&
02564     use_facet<num_put<char> >(const locale&);
02565 
02566   extern template
02567     const num_get<char>&
02568     use_facet<num_get<char> >(const locale&);
02569 
02570   extern template
02571     const moneypunct<char, true>&
02572     use_facet<moneypunct<char, true> >(const locale&);
02573 
02574   extern template
02575     const moneypunct<char, false>&
02576     use_facet<moneypunct<char, false> >(const locale&);
02577 
02578   extern template
02579     const money_put<char>&
02580     use_facet<money_put<char> >(const locale&);
02581 
02582   extern template
02583     const money_get<char>&
02584     use_facet<money_get<char> >(const locale&);
02585 
02586   extern template
02587     const __timepunct<char>&
02588     use_facet<__timepunct<char> >(const locale&);
02589 
02590   extern template
02591     const time_put<char>&
02592     use_facet<time_put<char> >(const locale&);
02593 
02594   extern template
02595     const time_get<char>&
02596     use_facet<time_get<char> >(const locale&);
02597 
02598   extern template
02599     const messages<char>&
02600     use_facet<messages<char> >(const locale&);
02601 
02602   extern template
02603     bool
02604     has_facet<ctype<char> >(const locale&);
02605 
02606   extern template
02607     bool
02608     has_facet<codecvt<char, char, mbstate_t> >(const locale&);
02609 
02610   extern template
02611     bool
02612     has_facet<collate<char> >(const locale&);
02613 
02614   extern template
02615     bool
02616     has_facet<numpunct<char> >(const locale&);
02617 
02618   extern template
02619     bool
02620     has_facet<num_put<char> >(const locale&);
02621 
02622   extern template
02623     bool
02624     has_facet<num_get<char> >(const locale&);
02625 
02626   extern template
02627     bool
02628     has_facet<moneypunct<char> >(const locale&);
02629 
02630   extern template
02631     bool
02632     has_facet<money_put<char> >(const locale&);
02633 
02634   extern template
02635     bool
02636     has_facet<money_get<char> >(const locale&);
02637 
02638   extern template
02639     bool
02640     has_facet<__timepunct<char> >(const locale&);
02641 
02642   extern template
02643     bool
02644     has_facet<time_put<char> >(const locale&);
02645 
02646   extern template
02647     bool
02648     has_facet<time_get<char> >(const locale&);
02649 
02650   extern template
02651     bool
02652     has_facet<messages<char> >(const locale&);
02653 
02654 #ifdef _GLIBCXX_USE_WCHAR_T
02655   extern template class moneypunct<wchar_t, false>;
02656   extern template class moneypunct<wchar_t, true>;
02657   extern template class moneypunct_byname<wchar_t, false>;
02658   extern template class moneypunct_byname<wchar_t, true>;
02659   extern template class money_get<wchar_t>;
02660   extern template class money_put<wchar_t>;
02661   extern template class numpunct<wchar_t>;
02662   extern template class numpunct_byname<wchar_t>;
02663   extern template class num_get<wchar_t>;
02664   extern template class num_put<wchar_t>;
02665   extern template class __timepunct<wchar_t>;
02666   extern template class time_put<wchar_t>;
02667   extern template class time_put_byname<wchar_t>;
02668   extern template class time_get<wchar_t>;
02669   extern template class time_get_byname<wchar_t>;
02670   extern template class messages<wchar_t>;
02671   extern template class messages_byname<wchar_t>;
02672   extern template class ctype_byname<wchar_t>;
02673   extern template class codecvt_byname<wchar_t, char, mbstate_t>;
02674   extern template class collate<wchar_t>;
02675   extern template class collate_byname<wchar_t>;
02676 
02677   extern template
02678     const codecvt<wchar_t, char, mbstate_t>&
02679     use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
02680 
02681   extern template
02682     const collate<wchar_t>&
02683     use_facet<collate<wchar_t> >(const locale&);
02684 
02685   extern template
02686     const numpunct<wchar_t>&
02687     use_facet<numpunct<wchar_t> >(const locale&);
02688 
02689   extern template
02690     const num_put<wchar_t>&
02691     use_facet<num_put<wchar_t> >(const locale&);
02692 
02693   extern template
02694     const num_get<wchar_t>&
02695     use_facet<num_get<wchar_t> >(const locale&);
02696 
02697   extern template
02698     const moneypunct<wchar_t, true>&
02699     use_facet<moneypunct<wchar_t, true> >(const locale&);
02700 
02701   extern template
02702     const moneypunct<wchar_t, false>&
02703     use_facet<moneypunct<wchar_t, false> >(const locale&);
02704 
02705   extern template
02706     const money_put<wchar_t>&
02707     use_facet<money_put<wchar_t> >(const locale&);
02708 
02709   extern template
02710     const money_get<wchar_t>&
02711     use_facet<money_get<wchar_t> >(const locale&);
02712 
02713   extern template
02714     const __timepunct<wchar_t>&
02715     use_facet<__timepunct<wchar_t> >(const locale&);
02716 
02717   extern template
02718     const time_put<wchar_t>&
02719     use_facet<time_put<wchar_t> >(const locale&);
02720 
02721   extern template
02722     const time_get<wchar_t>&
02723     use_facet<time_get<wchar_t> >(const locale&);
02724 
02725   extern template
02726     const messages<wchar_t>&
02727     use_facet<messages<wchar_t> >(const locale&);
02728 
02729  extern template
02730     bool
02731     has_facet<ctype<wchar_t> >(const locale&);
02732 
02733   extern template
02734     bool
02735     has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
02736 
02737   extern template
02738     bool
02739     has_facet<collate<wchar_t> >(const locale&);
02740 
02741   extern template
02742     bool
02743     has_facet<numpunct<wchar_t> >(const locale&);
02744 
02745   extern template
02746     bool
02747     has_facet<num_put<wchar_t> >(const locale&);
02748 
02749   extern template
02750     bool
02751     has_facet<num_get<wchar_t> >(const locale&);
02752 
02753   extern template
02754     bool
02755     has_facet<moneypunct<wchar_t> >(const locale&);
02756 
02757   extern template
02758     bool
02759     has_facet<money_put<wchar_t> >(const locale&);
02760 
02761   extern template
02762     bool
02763     has_facet<money_get<wchar_t> >(const locale&);
02764 
02765   extern template
02766     bool
02767     has_facet<__timepunct<wchar_t> >(const locale&);
02768 
02769   extern template
02770     bool
02771     has_facet<time_put<wchar_t> >(const locale&);
02772 
02773   extern template
02774     bool
02775     has_facet<time_get<wchar_t> >(const locale&);
02776 
02777   extern template
02778     bool
02779     has_facet<messages<wchar_t> >(const locale&);
02780 #endif
02781 #endif
02782 } // namespace std
02783 
02784 #endif

Generated on Sat Apr 2 13:54:42 2005 for libstdc++ source by  doxygen 1.4.0