# locale_facets.tcc

Go to the documentation of this file.

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