# locale_facets.tcc

Go to the documentation of this file.

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