# locale_facets.tcc

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