locale_facets.tcc

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

Generated on Thu Nov 1 17:35:59 2007 for libstdc++ by  doxygen 1.5.1