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

Generated on Tue Feb 2 16:56:13 2010 for GNU C++ STL by  doxygen 1.4.7