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