# locale_facets.tcc

    00001 // Locale support -*- C++ -*-
    00002
    00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
    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 <bits/streambuf_iterator.h>
    00045 #include <typeinfo>  // For bad_cast.
    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[_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[_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, _S_atoms + __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[__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[_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[_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[_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, _S_atoms + __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[__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   // The following code uses snprintf (or sprintf(), when _GLIBCPP_USE_C99
    00610   // is not defined) to convert floating point values for insertion into a
    00611   // stream.  An optimization would be to replace them with code that works
    00612   // directly on a wide buffer and then use __pad to do the padding.
    00613   // It would be good to replace them anyway to gain back the efficiency
    00614   // that C++ provides by knowing up front the type of the values to insert.
    00615   // Also, sprintf is dangerous since may lead to accidental buffer overruns.
    00616   // This implementation follows the C++ standard fairly directly as
    00617   // outlined in 22.2.2.2 [lib.locale.num.put]
    00618   template<typename _CharT, typename _OutIter>
    00619     template<typename _ValueT>
    00620       _OutIter
    00621       num_put<_CharT, _OutIter>::
    00622       _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
    00623                _ValueT __v) const
    00624       {
    00625     // Note: digits10 is rounded down.  We need to add 1 to ensure
    00626     // we get the full available precision.
    00627     const int __max_digits = numeric_limits<_ValueT>::digits10 + 1;
    00628     streamsize __prec = __io.precision();
    00629
    00630     if (__prec > static_cast<streamsize>(__max_digits))
    00631       __prec = static_cast<streamsize>(__max_digits);
    00632
    00633     // Long enough for the max format spec.
    00634     char __fbuf[16];
    00635
    00636     // [22.2.2.2.2] Stage 1, numeric conversion to character.
    00637     int __len;
    00638 #ifdef _GLIBCPP_USE_C99
    00639     // First try a buffer perhaps big enough (for sure sufficient for
    00640     // non-ios_base::fixed outputs)
    00641     int __cs_size = __max_digits * 3;
    00642     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    00643
    00644     const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec);
    00645     if (__fp)
    00646       __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
    00647                    _S_c_locale, __prec);
    00648     else
    00649       __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
    00650
    00651     // If the buffer was not large enough, try again with the correct size.
    00652     if (__len >= __cs_size)
    00653       {
    00654         __cs_size = __len + 1;
    00655         __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    00656         if (__fp)
    00657           __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
    00658                        _S_c_locale, __prec);
    00659         else
    00660           __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
    00661                        _S_c_locale);
    00662       }
    00663 #else
    00664     // Consider the possibility of long ios_base::fixed outputs
    00665     const bool __fixed = __io.flags() & ios_base::fixed;
    00666     const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
    00667     // ios_base::fixed outputs may need up to __max_exp+1 chars
    00668     // for the integer part + up to __max_digits chars for the
    00669     // fractional part + 3 chars for sign, decimal point, '\0'. On
    00670     // the other hand, for non-fixed outputs __max_digits*3 chars
    00671     // are largely sufficient.
    00672     const int __cs_size = __fixed ? __max_exp + __max_digits + 4
    00673                                   : __max_digits * 3;
    00674     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    00675
    00676     if (_S_format_float(__io, __fbuf, __mod, __prec))
    00677       __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
    00678     else
    00679       __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
    00680 #endif
    00681     return _M_widen_float(__s, __io, __fill, __cs, __len);
    00682       }
    00683
    00684   template<typename _CharT, typename _OutIter>
    00685     template<typename _ValueT>
    00686       _OutIter
    00687       num_put<_CharT, _OutIter>::
    00688       _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
    00689              char __modl, _ValueT __v) const
    00690       {
    00691     // [22.2.2.2.2] Stage 1, numeric conversion to character.
    00692
    00693     // Long enough for the max format spec.
    00694     char __fbuf[16];
    00695     _S_format_int(__io, __fbuf, __mod, __modl);
    00696 #ifdef _GLIBCPP_USE_C99
    00697     // First try a buffer perhaps big enough.
    00698     int __cs_size = 64;
    00699     char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    00700     int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
    00701                      _S_c_locale);
    00702     // If the buffer was not large enough, try again with the correct size.
    00703     if (__len >= __cs_size)
    00704       {
    00705         __cs_size = __len + 1;
    00706         __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    00707         __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
    00708                      _S_c_locale);
    00709       }
    00710 #else
    00711     // Leave room for "+/-," "0x," and commas. This size is
    00712     // arbitrary, but should be largely sufficient.
    00713     char __cs[128];
    00714     int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
    00715 #endif
    00716     return _M_widen_int(__s, __io, __fill, __cs, __len);
    00717       }
    00718
    00719   template<typename _CharT, typename _OutIter>
    00720     _OutIter
    00721     num_put<_CharT, _OutIter>::
    00722     _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
    00723            int __len) const
    00724     {
    00725       typedef char_traits<_CharT>       __traits_type;
    00726       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
    00727       // numpunct.decimal_point() values for '.' and adding grouping.
    00728       const locale __loc = __io.getloc();
    00729       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00730       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    00731                                * __len));
    00732       // Grouping can add (almost) as many separators as the number of
    00733       // digits, but no more.
    00734       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    00735                                 * __len * 2));
    00736       __ctype.widen(__cs, __cs + __len, __ws);
    00737
    00738       // Replace decimal point.
    00739       const _CharT* __p;
    00740       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
    00741       if (__p = __traits_type::find(__ws, __len, __ctype.widen('.')))
    00742     __ws[__p - __ws] = __np.decimal_point();
    00743
    00744 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
    00745 //282. What types does numpunct grouping refer to?
    00746       // Add grouping, if necessary.
    00747       const string __grouping = __np.grouping();
    00748       ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
    00749       if (__grouping.size())
    00750     {
    00751       _CharT* __p2;
    00752       int __declen = __p ? __p - __ws : __len;
    00753       __p2 = __add_grouping(__ws2, __np.thousands_sep(),
    00754                 __grouping.c_str(),
    00755                 __grouping.c_str() + __grouping.size(),
    00756                 __ws, __ws + __declen);
    00757       int __newlen = __p2 - __ws2;
    00758
    00759       // Tack on decimal part.
    00760       if (__p)
    00761         {
    00762           __traits_type::copy(__p2, __p, __len - __declen);
    00763           __newlen += __len - __declen;
    00764         }
    00765
    00766       // Switch strings, establish correct new length.
    00767       __ws = __ws2;
    00768       __len = __newlen;
    00769     }
    00770 #endif
    00771       return _M_insert(__s, __io, __fill, __ws, __len);
    00772     }
    00773
    00774   template<typename _CharT, typename _OutIter>
    00775     _OutIter
    00776     num_put<_CharT, _OutIter>::
    00777     _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
    00778          int __len) const
    00779     {
    00780       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
    00781       // numpunct.decimal_point() values for '.' and adding grouping.
    00782       const locale __loc = __io.getloc();
    00783       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00784       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    00785                                * __len));
    00786       // Grouping can add (almost) as many separators as the number of
    00787       // digits, but no more.
    00788       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    00789                                 * __len * 2));
    00790       __ctype.widen(__cs, __cs + __len, __ws);
    00791
    00792       // Add grouping, if necessary.
    00793       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
    00794       const string __grouping = __np.grouping();
    00795       const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
    00796       if (__grouping.size())
    00797     {
    00798       // By itself __add_grouping cannot deal correctly with __ws when
    00799       // ios::showbase is set and ios_base::oct || ios_base::hex.
    00800       // Therefore we take care "by hand" of the initial 0, 0x or 0X.
    00801       // However, remember that the latter do not occur if the number
    00802       // printed is '0' (__len == 1).
    00803       streamsize __off = 0;
    00804       if ((__io.flags() & ios_base::showbase) && __len > 1)
    00805         if (__basefield == ios_base::oct)
    00806           {
    00807         __off = 1;
    00808         *__ws2 = *__ws;
    00809           }
    00810         else if (__basefield == ios_base::hex)
    00811           {
    00812         __off = 2;
    00813         *__ws2 = *__ws;
    00814         *(__ws2 + 1) = *(__ws + 1);
    00815           }
    00816       _CharT* __p;
    00817       __p = __add_grouping(__ws2 + __off, __np.thousands_sep(),
    00818                    __grouping.c_str(),
    00819                    __grouping.c_str() + __grouping.size(),
    00820                    __ws + __off, __ws + __len);
    00821       __len = __p - __ws2;
    00822       // Switch strings.
    00823       __ws = __ws2;
    00824     }
    00825       return _M_insert(__s, __io, __fill, __ws, __len);
    00826     }
    00827
    00828   // For use by integer and floating-point types after they have been
    00829   // converted into a char_type string.
    00830   template<typename _CharT, typename _OutIter>
    00831     _OutIter
    00832     num_put<_CharT, _OutIter>::
    00833     _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws,
    00834           int __len) const
    00835     {
    00836       typedef char_traits<_CharT>       __traits_type;
    00837       // [22.2.2.2.2] Stage 3.
    00838       streamsize __w = __io.width();
    00839       _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    00840                                 * __w));
    00841       if (__w > static_cast<streamsize>(__len))
    00842     {
    00843       __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws,
    00844                            __w, __len, true);
    00845       __len = static_cast<int>(__w);
    00846       // Switch strings.
    00847       __ws = __ws2;
    00848     }
    00849       __io.width(0);
    00850
    00851       // [22.2.2.2.2] Stage 4.
    00852       // Write resulting, fully-formatted string to output iterator.
    00853       for (int __j = 0; __j < __len; ++__j, ++__s)
    00854     *__s = __ws[__j];
    00855       return __s;
    00856     }
    00857
    00858   template<typename _CharT, typename _OutIter>
    00859     _OutIter
    00860     num_put<_CharT, _OutIter>::
    00861     do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
    00862     {
    00863       ios_base::fmtflags __flags = __io.flags();
    00864       if ((__flags & ios_base::boolalpha) == 0)
    00865         {
    00866           unsigned long __uv = __v;
    00867           __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv);
    00868         }
    00869       else
    00870         {
    00871       typedef basic_string<_CharT> __string_type;
    00872           locale __loc = __io.getloc();
    00873       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
    00874       __string_type __name;
    00875           if (__v)
    00876         __name = __np.truename();
    00877           else
    00878         __name = __np.falsename();
    00879       __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size());
    00880     }
    00881       return __s;
    00882     }
    00883
    00884   template<typename _CharT, typename _OutIter>
    00885     _OutIter
    00886     num_put<_CharT, _OutIter>::
    00887     do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
    00888     { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); }
    00889
    00890   template<typename _CharT, typename _OutIter>
    00891     _OutIter
    00892     num_put<_CharT, _OutIter>::
    00893     do_put(iter_type __s, ios_base& __io, char_type __fill,
    00894            unsigned long __v) const
    00895     { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); }
    00896
    00897 #ifdef _GLIBCPP_USE_LONG_LONG
    00898   template<typename _CharT, typename _OutIter>
    00899     _OutIter
    00900     num_put<_CharT, _OutIter>::
    00901     do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
    00902     { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); }
    00903
    00904   template<typename _CharT, typename _OutIter>
    00905     _OutIter
    00906     num_put<_CharT, _OutIter>::
    00907     do_put(iter_type __s, ios_base& __io, char_type __fill,
    00908            unsigned long long __v) const
    00909     { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); }
    00910 #endif
    00911
    00912   template<typename _CharT, typename _OutIter>
    00913     _OutIter
    00914     num_put<_CharT, _OutIter>::
    00915     do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
    00916     { return _M_convert_float(__s, __io, __fill, char(), __v); }
    00917
    00918   template<typename _CharT, typename _OutIter>
    00919     _OutIter
    00920     num_put<_CharT, _OutIter>::
    00921     do_put(iter_type __s, ios_base& __io, char_type __fill,
    00922        long double __v) const
    00923     { return _M_convert_float(__s, __io, __fill, 'L', __v); }
    00924
    00925   template<typename _CharT, typename _OutIter>
    00926     _OutIter
    00927     num_put<_CharT, _OutIter>::
    00928     do_put(iter_type __s, ios_base& __io, char_type __fill,
    00929            const void* __v) const
    00930     {
    00931       ios_base::fmtflags __flags = __io.flags();
    00932       ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
    00933                    | ios_base::uppercase | ios_base::internal);
    00934       __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
    00935       try
    00936     {
    00937       __s = _M_convert_int(__s, __io, __fill, 'u', char(),
    00938                    reinterpret_cast<unsigned long>(__v));
    00939       __io.flags(__flags);
    00940     }
    00941       catch (...)
    00942     {
    00943       __io.flags(__flags);
    00944       __throw_exception_again;
    00945     }
    00946       return __s;
    00947     }
    00948
    00949
    00950   template<typename _CharT, typename _InIter>
    00951     _InIter
    00952     money_get<_CharT, _InIter>::
    00953     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
    00954        ios_base::iostate& __err, long double& __units) const
    00955     {
    00956       string_type __str;
    00957       __beg = this->do_get(__beg, __end, __intl, __io, __err, __str);
    00958
    00959       const int __n = numeric_limits<long double>::digits10;
    00960       char* __cs = static_cast<char*>(__builtin_alloca(__n));
    00961       const locale __loc = __io.getloc();
    00962       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00963       const _CharT* __wcs = __str.c_str();
    00964       __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);
    00965       __convert_to_v(__cs, __units, __err, _S_c_locale);
    00966       return __beg;
    00967     }
    00968
    00969   template<typename _CharT, typename _InIter>
    00970     _InIter
    00971     money_get<_CharT, _InIter>::
    00972     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
    00973        ios_base::iostate& __err, string_type& __units) const
    00974     {
    00975       // These contortions are quite unfortunate.
    00976       typedef moneypunct<_CharT, true>      __money_true;
    00977       typedef moneypunct<_CharT, false>     __money_false;
    00978       typedef money_base::part          part;
    00979       typedef typename string_type::size_type   size_type;
    00980
    00981       const locale __loc = __io.getloc();
    00982       const __money_true& __mpt = use_facet<__money_true>(__loc);
    00983       const __money_false& __mpf = use_facet<__money_false>(__loc);
    00984       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00985
    00986       const money_base::pattern __p = __intl ? __mpt.neg_format()
    00987                          : __mpf.neg_format();
    00988
    00989       const string_type __pos_sign =__intl ? __mpt.positive_sign()
    00990                        : __mpf.positive_sign();
    00991       const string_type __neg_sign =__intl ? __mpt.negative_sign()
    00992                        : __mpf.negative_sign();
    00993       const char_type __d = __intl ? __mpt.decimal_point()
    00994                            : __mpf.decimal_point();
    00995       const char_type __sep = __intl ? __mpt.thousands_sep()
    00996                          : __mpf.thousands_sep();
    00997
    00998       const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
    00999
    01000       // Set to deduced positive or negative sign, depending.
    01001       string_type __sign;
    01002       // String of grouping info from thousands_sep plucked from __units.
    01003       string __grouping_tmp;
    01004       // Marker for thousands_sep position.
    01005       int __sep_pos = 0;
    01006       // If input iterator is in a valid state.
    01007       bool __testvalid = true;
    01008       // Flag marking when a decimal point is found.
    01009       bool __testdecfound = false;
    01010
    01011       // The tentative returned string is stored here.
    01012       string_type __temp_units;
    01013
    01014       char_type __c = *__beg;
    01015       char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
    01016       for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
    01017     {
    01018       part __which = static_cast<part>(__p.field[__i]);
    01019       switch (__which)
    01020         {
    01021         case money_base::symbol:
    01022           if (__io.flags() & ios_base::showbase
    01023               || __i < 2 || __sign.size() > 1
    01024               || ((static_cast<part>(__p.field[3]) != money_base::none)
    01025               && __i == 2))
    01026             {
    01027               // According to 22.2.6.1.2.2, symbol is required
    01028               // if (__io.flags() & ios_base::showbase),
    01029               // otherwise is optional and consumed only if
    01030               // other characters are needed to complete the
    01031               // format.
    01032               const string_type __symbol = __intl ? __mpt.curr_symbol()
    01033                                  : __mpf.curr_symbol();
    01034               size_type __len = __symbol.size();
    01035               size_type __j = 0;
    01036               while (__beg != __end
    01037                  && __j < __len && __symbol[__j] == __c)
    01038             {
    01039               __c = *(++__beg);
    01040               ++__j;
    01041             }
    01042               // When (__io.flags() & ios_base::showbase)
    01043               // symbol is required.
    01044               if (__j != __len && (__io.flags() & ios_base::showbase))
    01045             __testvalid = false;
    01046             }
    01047           break;
    01048         case money_base::sign:
    01049           // Sign might not exist, or be more than one character long.
    01050           if (__pos_sign.size() && __neg_sign.size())
    01051           {
    01052             // Sign is mandatory.
    01053             if (__c == __pos_sign[0])
    01054               {
    01055             __sign = __pos_sign;
    01056             __c = *(++__beg);
    01057               }
    01058             else if (__c == __neg_sign[0])
    01059               {
    01060             __sign = __neg_sign;
    01061             __c = *(++__beg);
    01062               }
    01063             else
    01064               __testvalid = false;
    01065           }
    01066           else if (__pos_sign.size() && __c == __pos_sign[0])
    01067             {
    01068               __sign = __pos_sign;
    01069               __c = *(++__beg);
    01070             }
    01071           else if (__neg_sign.size() && __c == __neg_sign[0])
    01072             {
    01073               __sign = __neg_sign;
    01074               __c = *(++__beg);
    01075             }
    01076           break;
    01077         case money_base::value:
    01078           // Extract digits, remove and stash away the
    01079           // grouping of found thousands separators.
    01080           while (__beg != __end
    01081              && (__ctype.is(ctype_base::digit, __c)
    01082                  || (__c == __d && !__testdecfound)
    01083                  || __c == __sep))
    01084             {
    01085               if (__c == __d)
    01086             {
    01087               __grouping_tmp += static_cast<char>(__sep_pos);
    01088               __sep_pos = 0;
    01089               __testdecfound = true;
    01090             }
    01091               else if (__c == __sep)
    01092             {
    01093               if (__grouping.size())
    01094                 {
    01095                   // Mark position for later analysis.
    01096                   __grouping_tmp += static_cast<char>(__sep_pos);
    01097                   __sep_pos = 0;
    01098                 }
    01099               else
    01100                 {
    01101                   __testvalid = false;
    01102                   break;
    01103                 }
    01104             }
    01105               else
    01106             {
    01107               __temp_units += __c;
    01108               ++__sep_pos;
    01109             }
    01110               __c = *(++__beg);
    01111             }
    01112           break;
    01113         case money_base::space:
    01114         case money_base::none:
    01115           // Only if not at the end of the pattern.
    01116           if (__i != 3)
    01117             while (__beg != __end
    01118                && __ctype.is(ctype_base::space, __c))
    01119               __c = *(++__beg);
    01120           break;
    01121         }
    01122     }
    01123
    01124       // Need to get the rest of the sign characters, if they exist.
    01125       if (__sign.size() > 1)
    01126     {
    01127       size_type __len = __sign.size();
    01128       size_type __i = 1;
    01129       for (; __c != __eof && __i < __len; ++__i)
    01130         while (__beg != __end && __c != __sign[__i])
    01131           __c = *(++__beg);
    01132
    01133       if (__i != __len)
    01134         __testvalid = false;
    01135     }
    01136
    01137       // Strip leading zeros.
    01138       while (__temp_units[0] == __ctype.widen('0'))
    01139     __temp_units.erase(__temp_units.begin());
    01140
    01141       if (__sign.size() && __sign == __neg_sign)
    01142     __temp_units.insert(__temp_units.begin(), __ctype.widen('-'));
    01143
    01144       // Test for grouping fidelity.
    01145       if (__grouping.size() && __grouping_tmp.size())
    01146     {
    01147       if (!__verify_grouping(__grouping, __grouping_tmp))
    01148         __testvalid = false;
    01149     }
    01150
    01151       // Iff no more characters are available.
    01152       if (__c == __eof)
    01153     __err |= ios_base::eofbit;
    01154
    01155       // Iff valid sequence is not recognized.
    01156       if (!__testvalid || !__temp_units.size())
    01157     __err |= ios_base::failbit;
    01158       else
    01159     // Use the "swap trick" to copy __temp_units into __units.
    01160     __temp_units.swap(__units);
    01161
    01162       return __beg;
    01163     }
    01164
    01165   template<typename _CharT, typename _OutIter>
    01166     _OutIter
    01167     money_put<_CharT, _OutIter>::
    01168     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
    01169        long double __units) const
    01170     {
    01171       const locale __loc = __io.getloc();
    01172       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    01173 #ifdef _GLIBCPP_USE_C99
    01174       // First try a buffer perhaps big enough.
    01175       int __cs_size = 64;
    01176       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    01177       int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units,
    01178                    _S_c_locale);
    01179       // If the buffer was not large enough, try again with the correct size.
    01180       if (__len >= __cs_size)
    01181     {
    01182       __cs_size = __len + 1;
    01183       __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    01184       __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units,
    01185                    _S_c_locale);
    01186     }
    01187 #else
    01188       // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point,
    01189       // decimal digit, '\0'.
    01190       const int __cs_size = numeric_limits<long double>::max_exponent10 + 5;
    01191       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    01192       int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale);
    01193 #endif
    01194       _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size));
    01195       __ctype.widen(__cs, __cs + __len, __ws);
    01196       string_type __digits(__ws);
    01197       return this->do_put(__s, __intl, __io, __fill, __digits);
    01198     }
    01199
    01200   template<typename _CharT, typename _OutIter>
    01201     _OutIter
    01202     money_put<_CharT, _OutIter>::
    01203     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
    01204        const string_type& __digits) const
    01205     {
    01206       typedef typename string_type::size_type   size_type;
    01207       typedef money_base::part          part;
    01208
    01209       const locale __loc = __io.getloc();
    01210       const size_type __width = static_cast<size_type>(__io.width());
    01211
    01212       // These contortions are quite unfortunate.
    01213       typedef moneypunct<_CharT, true> __money_true;
    01214       typedef moneypunct<_CharT, false> __money_false;
    01215       const __money_true& __mpt = use_facet<__money_true>(__loc);
    01216       const __money_false& __mpf = use_facet<__money_false>(__loc);
    01217       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    01218
    01219       // Determine if negative or positive formats are to be used, and
    01220       // discard leading negative_sign if it is present.
    01221       const char_type* __beg = __digits.data();
    01222       const char_type* __end = __beg + __digits.size();
    01223       money_base::pattern __p;
    01224       string_type __sign;
    01225       if (*__beg != __ctype.widen('-'))
    01226     {
    01227       __p = __intl ? __mpt.pos_format() : __mpf.pos_format();
    01228       __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
    01229     }
    01230       else
    01231     {
    01232       __p = __intl ? __mpt.neg_format() : __mpf.neg_format();
    01233       __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
    01234       ++__beg;
    01235     }
    01236
    01237       // Look for valid numbers in the current ctype facet within input digits.
    01238       __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
    01239       if (__beg != __end)
    01240     {
    01241       // Assume valid input, and attempt to format.
    01242       // Break down input numbers into base components, as follows:
    01243       //   final_value = grouped units + (decimal point) + (digits)
    01244       string_type __res;
    01245       string_type __value;
    01246       const string_type __symbol = __intl ? __mpt.curr_symbol()
    01247                               : __mpf.curr_symbol();
    01248
    01249       // Deal with decimal point, decimal digits.
    01250       const int __frac = __intl ? __mpt.frac_digits()
    01251                         : __mpf.frac_digits();
    01252       if (__frac > 0)
    01253         {
    01254           const char_type __d = __intl ? __mpt.decimal_point()
    01255                        : __mpf.decimal_point();
    01256           if (__end - __beg >= __frac)
    01257         {
    01258           __value = string_type(__end - __frac, __end);
    01259           __value.insert(__value.begin(), __d);
    01260           __end -= __frac;
    01261         }
    01262           else
    01263         {
    01264           // Have to pad zeros in the decimal position.
    01265           __value = string_type(__beg, __end);
    01266           int __paddec = __frac - (__end - __beg);
    01267           char_type __zero = __ctype.widen('0');
    01268           __value.insert(__value.begin(), __paddec, __zero);
    01269           __value.insert(__value.begin(), __d);
    01270           __beg = __end;
    01271         }
    01272         }
    01273
    01274       // Add thousands separators to non-decimal digits, per
    01275       // grouping rules.
    01276       if (__beg != __end)
    01277         {
    01278           const string __grouping = __intl ? __mpt.grouping()
    01279                            : __mpf.grouping();
    01280           if (__grouping.size())
    01281         {
    01282           const char_type __sep = __intl ? __mpt.thousands_sep()
    01283                                  : __mpf.thousands_sep();
    01284           const char* __gbeg = __grouping.c_str();
    01285           const char* __gend = __gbeg + __grouping.size();
    01286           const int __n = (__end - __beg) * 2;
    01287           _CharT* __ws2 =
    01288             static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
    01289           _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg,
    01290                             __gend, __beg, __end);
    01291           __value.insert(0, __ws2, __ws_end - __ws2);
    01292         }
    01293           else
    01294         __value.insert(0, string_type(__beg, __end));
    01295         }
    01296
    01297       // Calculate length of resulting string.
    01298       ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
    01299       size_type __len = __value.size() + __sign.size();
    01300       __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
    01301       bool __testipad = __f == ios_base::internal && __len < __width;
    01302
    01303       // Fit formatted digits into the required pattern.
    01304       for (int __i = 0; __i < 4; ++__i)
    01305         {
    01306           part __which = static_cast<part>(__p.field[__i]);
    01307           switch (__which)
    01308         {
    01309         case money_base::symbol:
    01310           if (__io.flags() & ios_base::showbase)
    01311             __res += __symbol;
    01312           break;
    01313         case money_base::sign:
    01314           // Sign might not exist, or be more than one
    01315           // charater long. In that case, add in the rest
    01316           // below.
    01317           if (__sign.size())
    01318             __res += __sign[0];
    01319           break;
    01320         case money_base::value:
    01321           __res += __value;
    01322           break;
    01323         case money_base::space:
    01324           // At least one space is required, but if internal
    01325           // formatting is required, an arbitrary number of
    01326           // fill spaces will be necessary.
    01327           if (__testipad)
    01328             __res += string_type(__width - __len, __fill);
    01329           else
    01330             __res += __ctype.widen(__fill);
    01331           break;
    01332         case money_base::none:
    01333           if (__testipad)
    01334             __res += string_type(__width - __len, __fill);
    01335           break;
    01336         }
    01337         }
    01338
    01339       // Special case of multi-part sign parts.
    01340       if (__sign.size() > 1)
    01341         __res += string_type(__sign.begin() + 1, __sign.end());
    01342
    01343       // Pad, if still necessary.
    01344       __len = __res.size();
    01345       if (__width > __len)
    01346         {
    01347           if (__f == ios_base::left)
    01348         // After.
    01349         __res.append(__width - __len, __fill);
    01350           else
    01351         // Before.
    01352         __res.insert(0, string_type(__width - __len, __fill));
    01353           __len = __width;
    01354         }
    01355
    01356       // Write resulting, fully-formatted string to output iterator.
    01357       for (size_type __j = 0; __j < __len; ++__j, ++__s)
    01358         *__s = __res[__j];
    01359     }
    01360       __io.width(0);
    01361       return __s;
    01362     }
    01363
    01364
    01365   // NB: Not especially useful. Without an ios_base object or some
    01366   // kind of locale reference, we are left clawing at the air where
    01367   // the side of the mountain used to be...
    01368   template<typename _CharT, typename _InIter>
    01369     time_base::dateorder
    01370     time_get<_CharT, _InIter>::do_date_order() const
    01371     { return time_base::no_order; }
    01372
    01373   template<typename _CharT, typename _InIter>
    01374     void
    01375     time_get<_CharT, _InIter>::
    01376     _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
    01377               ios_base::iostate& __err, tm* __tm,
    01378               const _CharT* __format) const
    01379     {
    01380       locale __loc = __io.getloc();
    01381       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
    01382       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    01383       size_t __len = char_traits<_CharT>::length(__format);
    01384
    01385       for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
    01386     {
    01387       char __c = __format[__i];
    01388       if (__c == '%')
    01389         {
    01390           // Verify valid formatting code, attempt to extract.
    01391           __c = __format[++__i];
    01392           char __mod = 0;
    01393           int __mem = 0;
    01394           if (__c == 'E' || __c == 'O')
    01395         {
    01396           __mod = __c;
    01397           __c = __format[++__i];
    01398         }
    01399           switch (__c)
    01400         {
    01401           const char* __cs;
    01402           _CharT __wcs[10];
    01403         case 'a':
    01404           // Abbreviated weekday name [tm_wday]
    01405           const char_type*  __days1[7];
    01406           __tp._M_days_abbreviated(__days1);
    01407           _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7,
    01408                   __err);
    01409           break;
    01410         case 'A':
    01411           // Weekday name [tm_wday].
    01412           const char_type*  __days2[7];
    01413           __tp._M_days(__days2);
    01414           _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7,
    01415                   __err);
    01416           break;
    01417         case 'h':
    01418         case 'b':
    01419           // Abbreviated month name [tm_mon]
    01420           const char_type*  __months1[12];
    01421           __tp._M_months_abbreviated(__months1);
    01422           _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12,
    01423                   __err);
    01424           break;
    01425         case 'B':
    01426           // Month name [tm_mon].
    01427           const char_type*  __months2[12];
    01428           __tp._M_months(__months2);
    01429           _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12,
    01430                   __err);
    01431           break;
    01432         case 'c':
    01433           // Default time and date representation.
    01434           const char_type*  __dt[2];
    01435           __tp._M_date_time_formats(__dt);
    01436           _M_extract_via_format(__beg, __end, __io, __err, __tm,
    01437                     __dt[0]);
    01438           break;
    01439         case 'd':
    01440           // Day [01, 31]. [tm_mday]
    01441           _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
    01442                  __ctype, __err);
    01443           break;
    01444         case 'D':
    01445           // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
    01446           __cs = "%m/%d/%y";
    01447           __ctype.widen(__cs, __cs + 9, __wcs);
    01448           _M_extract_via_format(__beg, __end, __io, __err, __tm,
    01449                     __wcs);
    01450           break;
    01451         case 'H':
    01452           // Hour [00, 23]. [tm_hour]
    01453           _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
    01454                  __ctype, __err);
    01455           break;
    01456         case 'I':
    01457           // Hour [01, 12]. [tm_hour]
    01458           _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
    01459                  __ctype, __err);
    01460           break;
    01461         case 'm':
    01462           // Month [01, 12]. [tm_mon]
    01463           _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype,
    01464                  __err);
    01465           if (!__err)
    01466             __tm->tm_mon = __mem - 1;
    01467           break;
    01468         case 'M':
    01469           // Minute [00, 59]. [tm_min]
    01470           _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
    01471                  __ctype, __err);
    01472           break;
    01473         case 'n':
    01474           if (__ctype.narrow(*__beg, 0) == '\n')
    01475             ++__beg;
    01476           else
    01477             __err |= ios_base::failbit;
    01478           break;
    01479         case 'R':
    01480           // Equivalent to (%H:%M).
    01481           __cs = "%H:%M";
    01482           __ctype.widen(__cs, __cs + 6, __wcs);
    01483           _M_extract_via_format(__beg, __end, __io, __err, __tm,
    01484                     __wcs);
    01485           break;
    01486         case 'S':
    01487           // Seconds.
    01488           _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
    01489                  __ctype, __err);
    01490           break;
    01491         case 't':
    01492           if (__ctype.narrow(*__beg, 0) == '\t')
    01493             ++__beg;
    01494           else
    01495         __err |= ios_base::failbit;
    01496           break;
    01497         case 'T':
    01498           // Equivalent to (%H:%M:%S).
    01499           __cs = "%H:%M:%S";
    01500           __ctype.widen(__cs, __cs + 9, __wcs);
    01501           _M_extract_via_format(__beg, __end, __io, __err, __tm,
    01502                     __wcs);
    01503           break;
    01504         case 'x':
    01505           // Locale's date.
    01506           const char_type*  __dates[2];
    01507           __tp._M_date_formats(__dates);
    01508           _M_extract_via_format(__beg, __end, __io, __err, __tm,
    01509                     __dates[0]);
    01510           break;
    01511         case 'X':
    01512           // Locale's time.
    01513           const char_type*  __times[2];
    01514           __tp._M_time_formats(__times);
    01515           _M_extract_via_format(__beg, __end, __io, __err, __tm,
    01516                     __times[0]);
    01517           break;
    01518         case 'y':
    01519           // Two digit year. [tm_year]
    01520           _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
    01521                  __ctype, __err);
    01522           break;
    01523         case 'Y':
    01524           // Year [1900). [tm_year]
    01525           _M_extract_num(__beg, __end, __mem, 0,
    01526                  numeric_limits<int>::max(), 4,
    01527                  __ctype, __err);
    01528           if (!__err)
    01529             __tm->tm_year = __mem - 1900;
    01530           break;
    01531         case 'Z':
    01532           // Timezone info.
    01533           if (__ctype.is(ctype_base::upper, *__beg))
    01534             {
    01535               int __tmp;
    01536               _M_extract_name(__beg, __end, __tmp,
    01537                       __timepunct<_CharT>::_S_timezones,
    01538                       14, __err);
    01539
    01540               // GMT requires special effort.
    01541               char_type __c = *__beg;
    01542               if (!__err && __tmp == 0
    01543               && (__c == __ctype.widen('-')
    01544                   || __c == __ctype.widen('+')))
    01545             {
    01546               _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
    01547                       __ctype, __err);
    01548               _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
    01549                       __ctype, __err);
    01550             }
    01551               }
    01552               else
    01553             __err |= ios_base::failbit;
    01554               break;
    01555             default:
    01556               // Not recognized.
    01557               __err |= ios_base::failbit;
    01558             }
    01559         }
    01560           else
    01561         {
    01562           // Verify format and input match, extract and discard.
    01563           if (__c == __ctype.narrow(*__beg, 0))
    01564             ++__beg;
    01565           else
    01566             __err |= ios_base::failbit;
    01567         }
    01568     }
    01569     }
    01570
    01571   template<typename _CharT, typename _InIter>
    01572     void
    01573     time_get<_CharT, _InIter>::
    01574     _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
    01575            int __min, int __max, size_t __len,
    01576            const ctype<_CharT>& __ctype,
    01577            ios_base::iostate& __err) const
    01578     {
    01579       size_t __i = 0;
    01580       string __digits;
    01581       bool __testvalid = true;
    01582       char_type __c = *__beg;
    01583       while (__beg != __end && __i < __len
    01584          && __ctype.is(ctype_base::digit, __c))
    01585     {
    01586       __digits += __ctype.narrow(__c, 0);
    01587       __c = *(++__beg);
    01588       ++__i;
    01589     }
    01590       if (__i == __len)
    01591     {
    01592       int __value = atoi(__digits.c_str());
    01593       if (__min <= __value && __value <= __max)
    01594         __member = __value;
    01595       else
    01596         __testvalid = false;
    01597     }
    01598       else
    01599     __testvalid = false;
    01600       if (!__testvalid)
    01601     __err |= ios_base::failbit;
    01602     }
    01603
    01604   // Assumptions:
    01605   // All elements in __names are unique.
    01606   template<typename _CharT, typename _InIter>
    01607     void
    01608     time_get<_CharT, _InIter>::
    01609     _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
    01610             const _CharT** __names, size_t __indexlen,
    01611             ios_base::iostate& __err) const
    01612     {
    01613       typedef char_traits<_CharT>       __traits_type;
    01614       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen));
    01615       size_t __nmatches = 0;
    01616       size_t __pos = 0;
    01617       bool __testvalid = true;
    01618       const char_type* __name;
    01619
    01620       char_type __c = *__beg;
    01621       // Look for initial matches.
    01622       for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
    01623     if (__c == __names[__i1][0])
    01624       __matches[__nmatches++] = __i1;
    01625
    01626       while(__nmatches > 1)
    01627     {
    01628       // Find smallest matching string.
    01629       size_t __minlen = 10;
    01630       for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
    01631         __minlen = min(__minlen,
    01632                __traits_type::length(__names[__matches[__i2]]));
    01633
    01634       if (__pos < __minlen && __beg != __end)
    01635         {
    01636           ++__pos;
    01637           __c = *(++__beg);
    01638           for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
    01639         {
    01640           __name = __names[__matches[__i3]];
    01641           if (__name[__pos] != __c)
    01642             __matches[__i3] = __matches[--__nmatches];
    01643         }
    01644         }
    01645       else
    01646         break;
    01647     }
    01648
    01649       if (__nmatches == 1)
    01650     {
    01651       // Make sure found name is completely extracted.
    01652       __name = __names[__matches[0]];
    01653       const size_t __len = __traits_type::length(__name);
    01654       while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
    01655         ++__beg, ++__pos;
    01656
    01657       if (__len == __pos)
    01658         __member = __matches[0];
    01659       else
    01660         __testvalid = false;
    01661     }
    01662       else
    01663     __testvalid = false;
    01664       if (!__testvalid)
    01665     __err |= ios_base::failbit;
    01666     }
    01667
    01668   template<typename _CharT, typename _InIter>
    01669     _InIter
    01670     time_get<_CharT, _InIter>::
    01671     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
    01672         ios_base::iostate& __err, tm* __tm) const
    01673     {
    01674       _CharT __wcs[3];
    01675       const char* __cs = "%X";
    01676       locale __loc = __io.getloc();
    01677       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
    01678       __ctype.widen(__cs, __cs + 3, __wcs);
    01679       _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
    01680       if (__beg == __end)
    01681     __err |= ios_base::eofbit;
    01682       return __beg;
    01683     }
    01684
    01685   template<typename _CharT, typename _InIter>
    01686     _InIter
    01687     time_get<_CharT, _InIter>::
    01688     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
    01689         ios_base::iostate& __err, tm* __tm) const
    01690     {
    01691       _CharT __wcs[3];
    01692       const char* __cs = "%x";
    01693       locale __loc = __io.getloc();
    01694       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
    01695       __ctype.widen(__cs, __cs + 3, __wcs);
    01696       _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
    01697       if (__beg == __end)
    01698     __err |= ios_base::eofbit;
    01699       return __beg;
    01700     }
    01701
    01702   template<typename _CharT, typename _InIter>
    01703     _InIter
    01704     time_get<_CharT, _InIter>::
    01705     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
    01706            ios_base::iostate& __err, tm* __tm) const
    01707     {
    01708       typedef char_traits<_CharT>       __traits_type;
    01709       locale __loc = __io.getloc();
    01710       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
    01711       const char_type*  __days[7];
    01712       __tp._M_days_abbreviated(__days);
    01713       int __tmpwday;
    01714       _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err);
    01715
    01716       // Check to see if non-abbreviated name exists, and extract.
    01717       // NB: Assumes both _M_days and _M_days_abbreviated organized in
    01718       // exact same order, first to last, such that the resulting
    01719       // __days array with the same index points to a day, and that
    01720       // day's abbreviated form.
    01721       // NB: Also assumes that an abbreviated name is a subset of the name.
    01722       if (!__err)
    01723     {
    01724       size_t __pos = __traits_type::length(__days[__tmpwday]);
    01725       __tp._M_days(__days);
    01726       const char_type* __name = __days[__tmpwday];
    01727       if (__name[__pos] == *__beg)
    01728         {
    01729           // Extract the rest of it.
    01730           const size_t __len = __traits_type::length(__name);
    01731           while (__pos < __len && __beg != __end
    01732              && __name[__pos] == *__beg)
    01733         ++__beg, ++__pos;
    01734           if (__len != __pos)
    01735         __err |= ios_base::failbit;
    01736         }
    01737       if (!__err)
    01738         __tm->tm_wday = __tmpwday;
    01739     }
    01740       if (__beg == __end)
    01741     __err |= ios_base::eofbit;
    01742       return __beg;
    01743      }
    01744
    01745   template<typename _CharT, typename _InIter>
    01746     _InIter
    01747     time_get<_CharT, _InIter>::
    01748     do_get_monthname(iter_type __beg, iter_type __end,
    01749                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
    01750     {
    01751       typedef char_traits<_CharT>       __traits_type;
    01752       locale __loc = __io.getloc();
    01753       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
    01754       const char_type*  __months[12];
    01755       __tp._M_months_abbreviated(__months);
    01756       int __tmpmon;
    01757       _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err);
    01758
    01759       // Check to see if non-abbreviated name exists, and extract.
    01760       // NB: Assumes both _M_months and _M_months_abbreviated organized in
    01761       // exact same order, first to last, such that the resulting
    01762       // __months array with the same index points to a month, and that
    01763       // month's abbreviated form.
    01764       // NB: Also assumes that an abbreviated name is a subset of the name.
    01765       if (!__err)
    01766     {
    01767       size_t __pos = __traits_type::length(__months[__tmpmon]);
    01768       __tp._M_months(__months);
    01769       const char_type* __name = __months[__tmpmon];
    01770       if (__name[__pos] == *__beg)
    01771         {
    01772           // Extract the rest of it.
    01773           const size_t __len = __traits_type::length(__name);
    01774           while (__pos < __len && __beg != __end
    01775              && __name[__pos] == *__beg)
    01776         ++__beg, ++__pos;
    01777           if (__len != __pos)
    01778         __err |= ios_base::failbit;
    01779         }
    01780       if (!__err)
    01781         __tm->tm_mon = __tmpmon;
    01782     }
    01783
    01784       if (__beg == __end)
    01785     __err |= ios_base::eofbit;
    01786       return __beg;
    01787     }
    01788
    01789   template<typename _CharT, typename _InIter>
    01790     _InIter
    01791     time_get<_CharT, _InIter>::
    01792     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
    01793         ios_base::iostate& __err, tm* __tm) const
    01794     {
    01795       locale __loc = __io.getloc();
    01796       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    01797
    01798       char_type __c = *__beg;
    01799       size_t __i = 0;
    01800       string __digits;
    01801       while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c))
    01802     {
    01803       __digits += __ctype.narrow(__c, 0);
    01804       __c = *(++__beg);
    01805       ++__i;
    01806     }
    01807       if (__i == 2 || __i == 4)
    01808     {
    01809       long __l;
    01810       __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale);
    01811       if (!(__err & ios_base::failbit) && __l <= INT_MAX)
    01812         {
    01813           __l = __i == 2 ? __l : __l - 1900;
    01814           __tm->tm_year = static_cast<int>(__l);
    01815         }
    01816     }
    01817       else
    01818     __err |= ios_base::failbit;
    01819       if (__beg == __end)
    01820     __err |= ios_base::eofbit;
    01821       return __beg;
    01822     }
    01823
    01824   template<typename _CharT, typename _OutIter>
    01825     _OutIter
    01826     time_put<_CharT, _OutIter>::
    01827     put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
    01828     const _CharT* __beg, const _CharT* __end) const
    01829     {
    01830       locale __loc = __io.getloc();
    01831       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
    01832       while (__beg != __end)
    01833     {
    01834       char __c = __ctype.narrow(*__beg, 0);
    01835       ++__beg;
    01836       if (__c == '%')
    01837         {
    01838           char __format;
    01839           char __mod = 0;
    01840           size_t __len = 1;
    01841           __c = __ctype.narrow(*__beg, 0);
    01842           ++__beg;
    01843           if (__c == 'E' || __c == 'O')
    01844         {
    01845           __mod = __c;
    01846           __format = __ctype.narrow(*__beg, 0);
    01847           ++__beg;
    01848         }
    01849           else
    01850         __format = __c;
    01851           __s = this->do_put(__s, __io, char_type(), __tm, __format,
    01852                  __mod);
    01853         }
    01854       else
    01855         {
    01856           *__s = __c;
    01857           ++__s;
    01858         }
    01859     }
    01860       return __s;
    01861     }
    01862
    01863   template<typename _CharT, typename _OutIter>
    01864     _OutIter
    01865     time_put<_CharT, _OutIter>::
    01866     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
    01867        char __format, char __mod) const
    01868     {
    01869       locale __loc = __io.getloc();
    01870       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
    01871       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
    01872
    01873       // NB: This size is arbitrary. Should this be a data member,
    01874       // initialized at construction?
    01875       const size_t __maxlen = 64;
    01876       char_type* __res =
    01877     static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
    01878
    01879       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
    01880       // is possible that the format character will be longer than one
    01881       // character. Possibilities include 'E' or 'O' followed by a
    01882       // format character: if __mod is not the default argument, assume
    01883       // it's a valid modifier.
    01884       char_type __fmt[4];
    01885       __fmt[0] = __ctype.widen('%');
    01886       if (!__mod)
    01887     {
    01888       __fmt[1] = __format;
    01889       __fmt[2] = char_type();
    01890     }
    01891       else
    01892     {
    01893       __fmt[1] = __mod;
    01894       __fmt[2] = __format;
    01895       __fmt[3] = char_type();
    01896     }
    01897
    01898       __tp._M_put(__res, __maxlen, __fmt, __tm);
    01899
    01900       // Write resulting, fully-formatted string to output iterator.
    01901       size_t __len = char_traits<char_type>::length(__res);
    01902       for (size_t __i = 0; __i < __len; ++__i, ++__s)
    01903     *__s = __res[__i];
    01904       return __s;
    01905     }
    01906
    01907
    01908   // Generic version does nothing.
    01909   template<typename _CharT>
    01910     int
    01911     collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
    01912     { return 0; }
    01913
    01914   // Generic version does nothing.
    01915   template<typename _CharT>
    01916     size_t
    01917     collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
    01918     { return 0; }
    01919
    01920   template<typename _CharT>
    01921     int
    01922     collate<_CharT>::
    01923     do_compare(const _CharT* __lo1, const _CharT* __hi1,
    01924            const _CharT* __lo2, const _CharT* __hi2) const
    01925     {
    01926       const string_type __one(__lo1, __hi1);
    01927       const string_type __two(__lo2, __hi2);
    01928       return _M_compare(__one.c_str(), __two.c_str());
    01929     }
    01930
    01931  template<typename _CharT>
    01932     typename collate<_CharT>::string_type
    01933     collate<_CharT>::
    01934     do_transform(const _CharT* __lo, const _CharT* __hi) const
    01935     {
    01936       size_t __len = (__hi - __lo) * 2;
    01937       // First try a buffer perhaps big enough.
    01938       _CharT* __c =
    01939     static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
    01940       size_t __res = _M_transform(__c, __lo, __len);
    01941       // If the buffer was not large enough, try again with the correct size.
    01942       if (__res >= __len)
    01943     {
    01944       __c =
    01945         static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1)));
    01946       _M_transform(__c, __lo, __res + 1);
    01947     }
    01948       return string_type(__c);
    01949     }
    01950
    01951  template<typename _CharT>
    01952     long
    01953     collate<_CharT>::
    01954     do_hash(const _CharT* __lo, const _CharT* __hi) const
    01955     {
    01956       unsigned long __val = 0;
    01957       for (; __lo < __hi; ++__lo)
    01958     __val = *__lo + ((__val << 7) |
    01959                (__val >> (numeric_limits<unsigned long>::digits - 7)));
    01960       return static_cast<long>(__val);
    01961     }
    01962
    01963   // Convert string to numeric value of type _Tv and store results.
    01964   // NB: This is specialized for all required types, there is no
    01965   // generic definition.
    01966   template<typename _Tv>
    01967     void
    01968     __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err,
    01969            const __c_locale& __cloc, int __base = 10);
    01970
    01971   // Convert numeric value of type _Tv to string and return length of string.
    01972   // If snprintf is available use it, otherwise fall back to the unsafe sprintf
    01973   // which, in general, can be dangerous and should be avoided.
    01974   template<typename _Tv>
    01975     int
    01976     __convert_from_v(char* __out, const int __size, const char* __fmt,
    01977              _Tv __v, const __c_locale&, int __prec = -1);
    01978
    01979   // Construct correctly padded string, as per 22.2.2.2.2
    01980   // Assumes
    01981   // __newlen > __oldlen
    01982   // __news is allocated for __newlen size
    01983   // Used by both num_put and ostream inserters: if __num,
    01984   // internal-adjusted objects are padded according to the rules below
    01985   // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
    01986   // ones are.
    01987
    01988   // NB: Of the two parameters, _CharT can be deduced from the
    01989   // function arguments. The other (_Traits) has to be explicitly specified.
    01990   template<typename _CharT, typename _Traits>
    01991     struct __pad
    01992     {
    01993       static void
    01994       _S_pad(ios_base& __io, _CharT __fill, _CharT* __news,
    01995          const _CharT* __olds, const streamsize __newlen,
    01996          const streamsize __oldlen, const bool __num);
    01997     };
    01998
    01999   template<typename _CharT, typename _Traits>
    02000     void
    02001     __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
    02002                    _CharT* __news, const _CharT* __olds,
    02003                    const streamsize __newlen,
    02004                    const streamsize __oldlen, const bool __num)
    02005     {
    02006       size_t __plen = static_cast<size_t>(__newlen - __oldlen);
    02007       _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen));
    02008       _Traits::assign(__pads, __plen, __fill);
    02009
    02010       _CharT* __beg;
    02011       _CharT* __end;
    02012       size_t __mod = 0;
    02013       size_t __beglen; //either __plen or __oldlen
    02014       ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
    02015
    02016       if (__adjust == ios_base::left)
    02017     {
    02018       // Padding last.
    02019       __beg = const_cast<_CharT*>(__olds);
    02020       __beglen = __oldlen;
    02021       __end = __pads;
    02022     }
    02023       else if (__adjust == ios_base::internal && __num)
    02024     {
    02025       // Pad after the sign, if there is one.
    02026       // Pad after 0[xX], if there is one.
    02027       // Who came up with these rules, anyway? Jeeze.
    02028           locale __loc = __io.getloc();
    02029       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    02030       const _CharT __minus = __ctype.widen('-');
    02031       const _CharT __plus = __ctype.widen('+');
    02032       bool __testsign = _Traits::eq(__olds[0], __minus)
    02033                     || _Traits::eq(__olds[0], __plus);
    02034
    02035       bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0])
    02036                    && (_Traits::eq(__ctype.widen('x'), __olds[1])
    02037                    || _Traits::eq(__ctype.widen('X'), __olds[1]));
    02038       if (__testhex)
    02039         {
    02040           __news[0] = __olds[0];
    02041           __news[1] = __olds[1];
    02042           __mod += 2;
    02043           __news += 2;
    02044           __beg = __pads;
    02045           __beglen = __plen;
    02046           __end = const_cast<_CharT*>(__olds + __mod);
    02047         }
    02048       else if (__testsign)
    02049         {
    02050           _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus;
    02051           ++__mod;
    02052           ++__news;
    02053           __beg = __pads;
    02054           __beglen = __plen;
    02055           __end = const_cast<_CharT*>(__olds + __mod);
    02056         }
    02057       else
    02058         {
    02059           // Padding first.
    02060           __beg = __pads;
    02061           __beglen = __plen;
    02062           __end = const_cast<_CharT*>(__olds);
    02063         }
    02064     }
    02065       else
    02066     {
    02067       // Padding first.
    02068       __beg = __pads;
    02069       __beglen = __plen;
    02070       __end = const_cast<_CharT*>(__olds);
    02071     }
    02072       _Traits::copy(__news, __beg, __beglen);
    02073       _Traits::copy(__news + __beglen, __end,
    02074               __newlen - __beglen - __mod);
    02075     }
    02076
    02077   // Used by both numeric and monetary facets.
    02078   // Check to make sure that the __grouping_tmp string constructed in
    02079   // money_get or num_get matches the canonical grouping for a given
    02080   // locale.
    02081   // __grouping_tmp is parsed L to R
    02082   // 1,222,444 == __grouping_tmp of "/1/3/3"
    02083   // __grouping is parsed R to L
    02084   // 1,222,444 == __grouping of "/3" == "/3/3/3"
    02085   template<typename _CharT>
    02086     bool
    02087     __verify_grouping(const basic_string<_CharT>& __grouping,
    02088               basic_string<_CharT>& __grouping_tmp)
    02089     {
    02090       int __i = 0;
    02091       int __j = 0;
    02092       const int __len = __grouping.size();
    02093       const int __n = __grouping_tmp.size();
    02094       bool __test = true;
    02095
    02096       // Parsed number groupings have to match the
    02097       // numpunct::grouping string exactly, starting at the
    02098       // right-most point of the parsed sequence of elements ...
    02099       while (__test && __i < __n - 1)
    02100     for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
    02101       __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1];
    02102       // ... but the last parsed grouping can be <= numpunct
    02103       // grouping.
    02104       __j == __len ? __j = 0 : __j;
    02105       __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1];
    02106       return __test;
    02107     }
    02108
    02109   // Used by both numeric and monetary facets.
    02110   // Inserts "group separator" characters into an array of characters.
    02111   // It's recursive, one iteration per group.  It moves the characters
    02112   // in the buffer this way: "xxxx12345" -> "12,345xxx".  Call this
    02113   // only with __gbeg != __gend.
    02114   template<typename _CharT>
    02115     _CharT*
    02116     __add_grouping(_CharT* __s, _CharT __sep,
    02117            const char* __gbeg, const char* __gend,
    02118            const _CharT* __first, const _CharT* __last)
    02119     {
    02120       if (__last - __first > *__gbeg)
    02121         {
    02122           __s = __add_grouping(__s,  __sep,
    02123                    (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
    02124                    __gend, __first, __last - *__gbeg);
    02125           __first = __last - *__gbeg;
    02126           *__s++ = __sep;
    02127         }
    02128       do
    02129     *__s++ = *__first++;
    02130       while (__first != __last);
    02131       return __s;
    02132     }
    02133
    02134   // Inhibit implicit instantiations for required instantiations,
    02135   // which are defined via explicit instantiations elsewhere.
    02136   // NB: This syntax is a GNU extension.
    02137   extern template class moneypunct<char, false>;
    02138   extern template class moneypunct<char, true>;
    02139   extern template class moneypunct_byname<char, false>;
    02140   extern template class moneypunct_byname<char, true>;
    02141   extern template class money_get<char>;
    02142   extern template class money_put<char>;
    02143   extern template class numpunct<char>;
    02144   extern template class numpunct_byname<char>;
    02145   extern template class num_get<char>;
    02146   extern template class num_put<char>;
    02147   extern template class __timepunct<char>;
    02148   extern template class time_put<char>;
    02149   extern template class time_put_byname<char>;
    02150   extern template class time_get<char>;
    02151   extern template class time_get_byname<char>;
    02152   extern template class messages<char>;
    02153   extern template class messages_byname<char>;
    02154   extern template class ctype_byname<char>;
    02155   extern template class codecvt_byname<char, char, mbstate_t>;
    02156   extern template class collate<char>;
    02157   extern template class collate_byname<char>;
    02158
    02159   extern template
    02160     const codecvt<char, char, mbstate_t>&
    02161     use_facet<codecvt<char, char, mbstate_t> >(const locale&);
    02162
    02163   extern template
    02164     const collate<char>&
    02165     use_facet<collate<char> >(const locale&);
    02166
    02167   extern template
    02168     const numpunct<char>&
    02169     use_facet<numpunct<char> >(const locale&);
    02170
    02171   extern template
    02172     const num_put<char>&
    02173     use_facet<num_put<char> >(const locale&);
    02174
    02175   extern template
    02176     const num_get<char>&
    02177     use_facet<num_get<char> >(const locale&);
    02178
    02179   extern template
    02180     const moneypunct<char, true>&
    02181     use_facet<moneypunct<char, true> >(const locale&);
    02182
    02183   extern template
    02184     const moneypunct<char, false>&
    02185     use_facet<moneypunct<char, false> >(const locale&);
    02186
    02187   extern template
    02188     const money_put<char>&
    02189     use_facet<money_put<char> >(const locale&);
    02190
    02191   extern template
    02192     const money_get<char>&
    02193     use_facet<money_get<char> >(const locale&);
    02194
    02195   extern template
    02196     const __timepunct<char>&
    02197     use_facet<__timepunct<char> >(const locale&);
    02198
    02199   extern template
    02200     const time_put<char>&
    02201     use_facet<time_put<char> >(const locale&);
    02202
    02203   extern template
    02204     const time_get<char>&
    02205     use_facet<time_get<char> >(const locale&);
    02206
    02207   extern template
    02208     const messages<char>&
    02209     use_facet<messages<char> >(const locale&);
    02210
    02211   extern template
    02212     bool
    02213     has_facet<ctype<char> >(const locale&);
    02214
    02215   extern template
    02216     bool
    02217     has_facet<codecvt<char, char, mbstate_t> >(const locale&);
    02218
    02219   extern template
    02220     bool
    02221     has_facet<collate<char> >(const locale&);
    02222
    02223   extern template
    02224     bool
    02225     has_facet<numpunct<char> >(const locale&);
    02226
    02227   extern template
    02228     bool
    02229     has_facet<num_put<char> >(const locale&);
    02230
    02231   extern template
    02232     bool
    02233     has_facet<num_get<char> >(const locale&);
    02234
    02235   extern template
    02236     bool
    02237     has_facet<moneypunct<char> >(const locale&);
    02238
    02239   extern template
    02240     bool
    02241     has_facet<money_put<char> >(const locale&);
    02242
    02243   extern template
    02244     bool
    02245     has_facet<money_get<char> >(const locale&);
    02246
    02247   extern template
    02248     bool
    02249     has_facet<__timepunct<char> >(const locale&);
    02250
    02251   extern template
    02252     bool
    02253     has_facet<time_put<char> >(const locale&);
    02254
    02255   extern template
    02256     bool
    02257     has_facet<time_get<char> >(const locale&);
    02258
    02259   extern template
    02260     bool
    02261     has_facet<messages<char> >(const locale&);
    02262
    02263 #ifdef _GLIBCPP_USE_WCHAR_T
    02264   extern template class moneypunct<wchar_t, false>;
    02265   extern template class moneypunct<wchar_t, true>;
    02266   extern template class moneypunct_byname<wchar_t, false>;
    02267   extern template class moneypunct_byname<wchar_t, true>;
    02268   extern template class money_get<wchar_t>;
    02269   extern template class money_put<wchar_t>;
    02270   extern template class numpunct<wchar_t>;
    02271   extern template class numpunct_byname<wchar_t>;
    02272   extern template class num_get<wchar_t>;
    02273   extern template class num_put<wchar_t>;
    02274   extern template class __timepunct<wchar_t>;
    02275   extern template class time_put<wchar_t>;
    02276   extern template class time_put_byname<wchar_t>;
    02277   extern template class time_get<wchar_t>;
    02278   extern template class time_get_byname<wchar_t>;
    02279   extern template class messages<wchar_t>;
    02280   extern template class messages_byname<wchar_t>;
    02281   extern template class ctype_byname<wchar_t>;
    02282   extern template class codecvt_byname<wchar_t, char, mbstate_t>;
    02283   extern template class collate<wchar_t>;
    02284   extern template class collate_byname<wchar_t>;
    02285
    02286   extern template
    02287     const codecvt<wchar_t, char, mbstate_t>&
    02288     use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
    02289
    02290   extern template
    02291     const collate<wchar_t>&
    02292     use_facet<collate<wchar_t> >(const locale&);
    02293
    02294   extern template
    02295     const numpunct<wchar_t>&
    02296     use_facet<numpunct<wchar_t> >(const locale&);
    02297
    02298   extern template
    02299     const num_put<wchar_t>&
    02300     use_facet<num_put<wchar_t> >(const locale&);
    02301
    02302   extern template
    02303     const num_get<wchar_t>&
    02304     use_facet<num_get<wchar_t> >(const locale&);
    02305
    02306   extern template
    02307     const moneypunct<wchar_t, true>&
    02308     use_facet<moneypunct<wchar_t, true> >(const locale&);
    02309
    02310   extern template
    02311     const moneypunct<wchar_t, false>&
    02312     use_facet<moneypunct<wchar_t, false> >(const locale&);
    02313
    02314   extern template
    02315     const money_put<wchar_t>&
    02316     use_facet<money_put<wchar_t> >(const locale&);
    02317
    02318   extern template
    02319     const money_get<wchar_t>&
    02320     use_facet<money_get<wchar_t> >(const locale&);
    02321
    02322   extern template
    02323     const __timepunct<wchar_t>&
    02324     use_facet<__timepunct<wchar_t> >(const locale&);
    02325
    02326   extern template
    02327     const time_put<wchar_t>&
    02328     use_facet<time_put<wchar_t> >(const locale&);
    02329
    02330   extern template
    02331     const time_get<wchar_t>&
    02332     use_facet<time_get<wchar_t> >(const locale&);
    02333
    02334   extern template
    02335     const messages<wchar_t>&
    02336     use_facet<messages<wchar_t> >(const locale&);
    02337
    02338  extern template
    02339     bool
    02340     has_facet<ctype<wchar_t> >(const locale&);
    02341
    02342   extern template
    02343     bool
    02344     has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
    02345
    02346   extern template
    02347     bool
    02348     has_facet<collate<wchar_t> >(const locale&);
    02349
    02350   extern template
    02351     bool
    02352     has_facet<numpunct<wchar_t> >(const locale&);
    02353
    02354   extern template
    02355     bool
    02356     has_facet<num_put<wchar_t> >(const locale&);
    02357
    02358   extern template
    02359     bool
    02360     has_facet<num_get<wchar_t> >(const locale&);
    02361
    02362   extern template
    02363     bool
    02364     has_facet<moneypunct<wchar_t> >(const locale&);
    02365
    02366   extern template
    02367     bool
    02368     has_facet<money_put<wchar_t> >(const locale&);
    02369
    02370   extern template
    02371     bool
    02372     has_facet<money_get<wchar_t> >(const locale&);
    02373
    02374   extern template
    02375     bool
    02376     has_facet<__timepunct<wchar_t> >(const locale&);
    02377
    02378   extern template
    02379     bool
    02380     has_facet<time_put<wchar_t> >(const locale&);
    02381
    02382   extern template
    02383     bool
    02384     has_facet<time_get<wchar_t> >(const locale&);
    02385
    02386   extern template
    02387     bool
    02388     has_facet<messages<wchar_t> >(const locale&);
    02389 #endif
    02390 } // namespace std
    02391
    02392 #endif