# locale_facets.tcc

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