# locale_facets_nonio.tcc

Go to the documentation of this file.

    00001 // Locale support -*- C++ -*-
    00002
    00003 // Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
    00004 //
    00005 // This file is part of the GNU ISO C++ Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the
    00007 // terms of the GNU General Public License as published by the
    00008 // Free Software Foundation; either version 3, or (at your option)
    00009 // any later version.
    00010
    00011 // This library is distributed in the hope that it will be useful,
    00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014 // GNU General Public License for more details.
    00015
    00016 // Under Section 7 of GPL version 3, you are granted additional
    00017 // permissions described in the GCC Runtime Library Exception, version
    00018 // 3.1, as published by the Free Software Foundation.
    00019
    00020 // You should have received a copy of the GNU General Public License and
    00021 // a copy of the GCC Runtime Library Exception along with this program;
    00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    00023 // <http://www.gnu.org/licenses/>.
    00024
    00025 /** @file locale_facets_nonio.tcc
    00026  *  This is an internal header file, included by other library headers.
    00027  *  You should not attempt to use it directly.
    00028  */
    00029
    00030 #ifndef _LOCALE_FACETS_NONIO_TCC
    00031 #define _LOCALE_FACETS_NONIO_TCC 1
    00032
    00033 #pragma GCC system_header
    00034
    00035 _GLIBCXX_BEGIN_NAMESPACE(std)
    00036
    00037   template<typename _CharT, bool _Intl>
    00038     struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
    00039     {
    00040       const __moneypunct_cache<_CharT, _Intl>*
    00041       operator() (const locale& __loc) const
    00042       {
    00043     const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
    00044     const locale::facet** __caches = __loc._M_impl->_M_caches;
    00045     if (!__caches[__i])
    00046       {
    00047         __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
    00048         __try
    00049           {
    00050         __tmp = new __moneypunct_cache<_CharT, _Intl>;
    00051         __tmp->_M_cache(__loc);
    00052           }
    00053         __catch(...)
    00054           {
    00055         delete __tmp;
    00056         __throw_exception_again;
    00057           }
    00058         __loc._M_impl->_M_install_cache(__tmp, __i);
    00059       }
    00060     return static_cast<
    00061       const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
    00062       }
    00063     };
    00064
    00065   template<typename _CharT, bool _Intl>
    00066     void
    00067     __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
    00068     {
    00069       _M_allocated = true;
    00070
    00071       const moneypunct<_CharT, _Intl>& __mp =
    00072     use_facet<moneypunct<_CharT, _Intl> >(__loc);
    00073
    00074       _M_decimal_point = __mp.decimal_point();
    00075       _M_thousands_sep = __mp.thousands_sep();
    00076       _M_frac_digits = __mp.frac_digits();
    00077
    00078       char* __grouping = 0;
    00079       _CharT* __curr_symbol = 0;
    00080       _CharT* __positive_sign = 0;
    00081       _CharT* __negative_sign = 0;
    00082       __try
    00083     {
    00084       _M_grouping_size = __mp.grouping().size();
    00085       __grouping = new char[_M_grouping_size];
    00086       __mp.grouping().copy(__grouping, _M_grouping_size);
    00087       _M_grouping = __grouping;
    00088       _M_use_grouping = (_M_grouping_size
    00089                  && static_cast<signed char>(_M_grouping[0]) > 0
    00090                  && (_M_grouping[0]
    00091                  != __gnu_cxx::__numeric_traits<char>::__max));
    00092
    00093       _M_curr_symbol_size = __mp.curr_symbol().size();
    00094       __curr_symbol = new _CharT[_M_curr_symbol_size];
    00095       __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
    00096       _M_curr_symbol = __curr_symbol;
    00097
    00098       _M_positive_sign_size = __mp.positive_sign().size();
    00099       __positive_sign = new _CharT[_M_positive_sign_size];
    00100       __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
    00101       _M_positive_sign = __positive_sign;
    00102
    00103       _M_negative_sign_size = __mp.negative_sign().size();
    00104       __negative_sign = new _CharT[_M_negative_sign_size];
    00105       __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
    00106       _M_negative_sign = __negative_sign;
    00107
    00108       _M_pos_format = __mp.pos_format();
    00109       _M_neg_format = __mp.neg_format();
    00110
    00111       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
    00112       __ct.widen(money_base::_S_atoms,
    00113              money_base::_S_atoms + money_base::_S_end, _M_atoms);
    00114     }
    00115       __catch(...)
    00116     {
    00117       delete [] __grouping;
    00118       delete [] __curr_symbol;
    00119       delete [] __positive_sign;
    00120       delete [] __negative_sign;
    00121       __throw_exception_again;
    00122     }
    00123     }
    00124
    00125 _GLIBCXX_BEGIN_LDBL_NAMESPACE
    00126
    00127   template<typename _CharT, typename _InIter>
    00128     template<bool _Intl>
    00129       _InIter
    00130       money_get<_CharT, _InIter>::
    00131       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
    00132          ios_base::iostate& __err, string& __units) const
    00133       {
    00134     typedef char_traits<_CharT>           __traits_type;
    00135     typedef typename string_type::size_type           size_type;
    00136     typedef money_base::part              part;
    00137     typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
    00138
    00139     const locale& __loc = __io._M_getloc();
    00140     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00141
    00142     __use_cache<__cache_type> __uc;
    00143     const __cache_type* __lc = __uc(__loc);
    00144     const char_type* __lit = __lc->_M_atoms;
    00145
    00146     // Deduced sign.
    00147     bool __negative = false;
    00148     // Sign size.
    00149     size_type __sign_size = 0;
    00150     // True if sign is mandatory.
    00151     const bool __mandatory_sign = (__lc->_M_positive_sign_size
    00152                        && __lc->_M_negative_sign_size);
    00153     // String of grouping info from thousands_sep plucked from __units.
    00154     string __grouping_tmp;
    00155     if (__lc->_M_use_grouping)
    00156       __grouping_tmp.reserve(32);
    00157     // Last position before the decimal point.
    00158     int __last_pos = 0;
    00159     // Separator positions, then, possibly, fractional digits.
    00160     int __n = 0;
    00161     // If input iterator is in a valid state.
    00162     bool __testvalid = true;
    00163     // Flag marking when a decimal point is found.
    00164     bool __testdecfound = false;
    00165
    00166     // The tentative returned string is stored here.
    00167     string __res;
    00168     __res.reserve(32);
    00169
    00170     const char_type* __lit_zero = __lit + money_base::_S_zero;
    00171     const money_base::pattern __p = __lc->_M_neg_format;
    00172     for (int __i = 0; __i < 4 && __testvalid; ++__i)
    00173       {
    00174         const part __which = static_cast<part>(__p.field[__i]);
    00175         switch (__which)
    00176           {
    00177           case money_base::symbol:
    00178         // According to 22.2.6.1.2, p2, symbol is required
    00179         // if (__io.flags() & ios_base::showbase), otherwise
    00180         // is optional and consumed only if other characters
    00181         // are needed to complete the format.
    00182         if (__io.flags() & ios_base::showbase || __sign_size > 1
    00183             || __i == 0
    00184             || (__i == 1 && (__mandatory_sign
    00185                      || (static_cast<part>(__p.field[0])
    00186                      == money_base::sign)
    00187                      || (static_cast<part>(__p.field[2])
    00188                      == money_base::space)))
    00189             || (__i == 2 && ((static_cast<part>(__p.field[3])
    00190                       == money_base::value)
    00191                      || (__mandatory_sign
    00192                      && (static_cast<part>(__p.field[3])
    00193                          == money_base::sign)))))
    00194           {
    00195             const size_type __len = __lc->_M_curr_symbol_size;
    00196             size_type __j = 0;
    00197             for (; __beg != __end && __j < __len
    00198                && *__beg == __lc->_M_curr_symbol[__j];
    00199              ++__beg, ++__j);
    00200             if (__j != __len
    00201             && (__j || __io.flags() & ios_base::showbase))
    00202               __testvalid = false;
    00203           }
    00204         break;
    00205           case money_base::sign:
    00206         // Sign might not exist, or be more than one character long.
    00207         if (__lc->_M_positive_sign_size && __beg != __end
    00208             && *__beg == __lc->_M_positive_sign[0])
    00209           {
    00210             __sign_size = __lc->_M_positive_sign_size;
    00211             ++__beg;
    00212           }
    00213         else if (__lc->_M_negative_sign_size && __beg != __end
    00214              && *__beg == __lc->_M_negative_sign[0])
    00215           {
    00216             __negative = true;
    00217             __sign_size = __lc->_M_negative_sign_size;
    00218             ++__beg;
    00219           }
    00220         else if (__lc->_M_positive_sign_size
    00221              && !__lc->_M_negative_sign_size)
    00222           // "... if no sign is detected, the result is given the sign
    00223           // that corresponds to the source of the empty string"
    00224           __negative = true;
    00225         else if (__mandatory_sign)
    00226           __testvalid = false;
    00227         break;
    00228           case money_base::value:
    00229         // Extract digits, remove and stash away the
    00230         // grouping of found thousands separators.
    00231         for (; __beg != __end; ++__beg)
    00232           {
    00233             const char_type __c = *__beg;
    00234             const char_type* __q = __traits_type::find(__lit_zero,
    00235                                    10, __c);
    00236             if (__q != 0)
    00237               {
    00238             __res += money_base::_S_atoms[__q - __lit];
    00239             ++__n;
    00240               }
    00241             else if (__c == __lc->_M_decimal_point
    00242                  && !__testdecfound)
    00243               {
    00244             if (__lc->_M_frac_digits <= 0)
    00245               break;
    00246
    00247             __last_pos = __n;
    00248             __n = 0;
    00249             __testdecfound = true;
    00250               }
    00251             else if (__lc->_M_use_grouping
    00252                  && __c == __lc->_M_thousands_sep
    00253                  && !__testdecfound)
    00254               {
    00255             if (__n)
    00256               {
    00257                 // Mark position for later analysis.
    00258                 __grouping_tmp += static_cast<char>(__n);
    00259                 __n = 0;
    00260               }
    00261             else
    00262               {
    00263                 __testvalid = false;
    00264                 break;
    00265               }
    00266               }
    00267             else
    00268               break;
    00269           }
    00270         if (__res.empty())
    00271           __testvalid = false;
    00272         break;
    00273           case money_base::space:
    00274         // At least one space is required.
    00275         if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
    00276           ++__beg;
    00277         else
    00278           __testvalid = false;
    00279           case money_base::none:
    00280         // Only if not at the end of the pattern.
    00281         if (__i != 3)
    00282           for (; __beg != __end
    00283              && __ctype.is(ctype_base::space, *__beg); ++__beg);
    00284         break;
    00285           }
    00286       }
    00287
    00288     // Need to get the rest of the sign characters, if they exist.
    00289     if (__sign_size > 1 && __testvalid)
    00290       {
    00291         const char_type* __sign = __negative ? __lc->_M_negative_sign
    00292                                              : __lc->_M_positive_sign;
    00293         size_type __i = 1;
    00294         for (; __beg != __end && __i < __sign_size
    00295            && *__beg == __sign[__i]; ++__beg, ++__i);
    00296
    00297         if (__i != __sign_size)
    00298           __testvalid = false;
    00299       }
    00300
    00301     if (__testvalid)
    00302       {
    00303         // Strip leading zeros.
    00304         if (__res.size() > 1)
    00305           {
    00306         const size_type __first = __res.find_first_not_of('0');
    00307         const bool __only_zeros = __first == string::npos;
    00308         if (__first)
    00309           __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
    00310           }
    00311
    00312         // 22.2.6.1.2, p4
    00313         if (__negative && __res[0] != '0')
    00314           __res.insert(__res.begin(), '-');
    00315
    00316         // Test for grouping fidelity.
    00317         if (__grouping_tmp.size())
    00318           {
    00319         // Add the ending grouping.
    00320         __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
    00321                                            : __n);
    00322         if (!std::__verify_grouping(__lc->_M_grouping,
    00323                         __lc->_M_grouping_size,
    00324                         __grouping_tmp))
    00325           __err |= ios_base::failbit;
    00326           }
    00327
    00328         // Iff not enough digits were supplied after the decimal-point.
    00329         if (__testdecfound && __n != __lc->_M_frac_digits)
    00330           __testvalid = false;
    00331       }
    00332
    00333     // Iff valid sequence is not recognized.
    00334     if (!__testvalid)
    00335       __err |= ios_base::failbit;
    00336     else
    00337       __units.swap(__res);
    00338
    00339     // Iff no more characters are available.
    00340     if (__beg == __end)
    00341       __err |= ios_base::eofbit;
    00342     return __beg;
    00343       }
    00344
    00345 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
    00346   template<typename _CharT, typename _InIter>
    00347     _InIter
    00348     money_get<_CharT, _InIter>::
    00349     __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
    00350          ios_base::iostate& __err, double& __units) const
    00351     {
    00352       string __str;
    00353       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
    00354                      : _M_extract<false>(__beg, __end, __io, __err, __str);
    00355       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
    00356       return __beg;
    00357     }
    00358 #endif
    00359
    00360   template<typename _CharT, typename _InIter>
    00361     _InIter
    00362     money_get<_CharT, _InIter>::
    00363     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
    00364        ios_base::iostate& __err, long double& __units) const
    00365     {
    00366       string __str;
    00367       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
    00368                  : _M_extract<false>(__beg, __end, __io, __err, __str);
    00369       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
    00370       return __beg;
    00371     }
    00372
    00373   template<typename _CharT, typename _InIter>
    00374     _InIter
    00375     money_get<_CharT, _InIter>::
    00376     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
    00377        ios_base::iostate& __err, string_type& __digits) const
    00378     {
    00379       typedef typename string::size_type                  size_type;
    00380
    00381       const locale& __loc = __io._M_getloc();
    00382       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00383
    00384       string __str;
    00385       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
    00386                  : _M_extract<false>(__beg, __end, __io, __err, __str);
    00387       const size_type __len = __str.size();
    00388       if (__len)
    00389     {
    00390       __digits.resize(__len);
    00391       __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
    00392     }
    00393       return __beg;
    00394     }
    00395
    00396   template<typename _CharT, typename _OutIter>
    00397     template<bool _Intl>
    00398       _OutIter
    00399       money_put<_CharT, _OutIter>::
    00400       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
    00401         const string_type& __digits) const
    00402       {
    00403     typedef typename string_type::size_type           size_type;
    00404     typedef money_base::part                          part;
    00405     typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
    00406
    00407     const locale& __loc = __io._M_getloc();
    00408     const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00409
    00410     __use_cache<__cache_type> __uc;
    00411     const __cache_type* __lc = __uc(__loc);
    00412     const char_type* __lit = __lc->_M_atoms;
    00413
    00414     // Determine if negative or positive formats are to be used, and
    00415     // discard leading negative_sign if it is present.
    00416     const char_type* __beg = __digits.data();
    00417
    00418     money_base::pattern __p;
    00419     const char_type* __sign;
    00420     size_type __sign_size;
    00421     if (!(*__beg == __lit[money_base::_S_minus]))
    00422       {
    00423         __p = __lc->_M_pos_format;
    00424         __sign = __lc->_M_positive_sign;
    00425         __sign_size = __lc->_M_positive_sign_size;
    00426       }
    00427     else
    00428       {
    00429         __p = __lc->_M_neg_format;
    00430         __sign = __lc->_M_negative_sign;
    00431         __sign_size = __lc->_M_negative_sign_size;
    00432         if (__digits.size())
    00433           ++__beg;
    00434       }
    00435
    00436     // Look for valid numbers in the ctype facet within input digits.
    00437     size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
    00438                        __beg + __digits.size()) - __beg;
    00439     if (__len)
    00440       {
    00441         // Assume valid input, and attempt to format.
    00442         // Break down input numbers into base components, as follows:
    00443         //   final_value = grouped units + (decimal point) + (digits)
    00444         string_type __value;
    00445         __value.reserve(2 * __len);
    00446
    00447         // Add thousands separators to non-decimal digits, per
    00448         // grouping rules.
    00449         long __paddec = __len - __lc->_M_frac_digits;
    00450         if (__paddec > 0)
    00451           {
    00452         if (__lc->_M_frac_digits < 0)
    00453           __paddec = __len;
    00454         if (__lc->_M_grouping_size)
    00455           {
    00456             __value.assign(2 * __paddec, char_type());
    00457             _CharT* __vend =
    00458               std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
    00459                       __lc->_M_grouping,
    00460                       __lc->_M_grouping_size,
    00461                       __beg, __beg + __paddec);
    00462             __value.erase(__vend - &__value[0]);
    00463           }
    00464         else
    00465           __value.assign(__beg, __paddec);
    00466           }
    00467
    00468         // Deal with decimal point, decimal digits.
    00469         if (__lc->_M_frac_digits > 0)
    00470           {
    00471         __value += __lc->_M_decimal_point;
    00472         if (__paddec >= 0)
    00473           __value.append(__beg + __paddec, __lc->_M_frac_digits);
    00474         else
    00475           {
    00476             // Have to pad zeros in the decimal position.
    00477             __value.append(-__paddec, __lit[money_base::_S_zero]);
    00478             __value.append(__beg, __len);
    00479           }
    00480           }
    00481
    00482         // Calculate length of resulting string.
    00483         const ios_base::fmtflags __f = __io.flags()
    00484                                        & ios_base::adjustfield;
    00485         __len = __value.size() + __sign_size;
    00486         __len += ((__io.flags() & ios_base::showbase)
    00487               ? __lc->_M_curr_symbol_size : 0);
    00488
    00489         string_type __res;
    00490         __res.reserve(2 * __len);
    00491
    00492         const size_type __width = static_cast<size_type>(__io.width());
    00493         const bool __testipad = (__f == ios_base::internal
    00494                      && __len < __width);
    00495         // Fit formatted digits into the required pattern.
    00496         for (int __i = 0; __i < 4; ++__i)
    00497           {
    00498         const part __which = static_cast<part>(__p.field[__i]);
    00499         switch (__which)
    00500           {
    00501           case money_base::symbol:
    00502             if (__io.flags() & ios_base::showbase)
    00503               __res.append(__lc->_M_curr_symbol,
    00504                    __lc->_M_curr_symbol_size);
    00505             break;
    00506           case money_base::sign:
    00507             // Sign might not exist, or be more than one
    00508             // character long. In that case, add in the rest
    00509             // below.
    00510             if (__sign_size)
    00511               __res += __sign[0];
    00512             break;
    00513           case money_base::value:
    00514             __res += __value;
    00515             break;
    00516           case money_base::space:
    00517             // At least one space is required, but if internal
    00518             // formatting is required, an arbitrary number of
    00519             // fill spaces will be necessary.
    00520             if (__testipad)
    00521               __res.append(__width - __len, __fill);
    00522             else
    00523               __res += __fill;
    00524             break;
    00525           case money_base::none:
    00526             if (__testipad)
    00527               __res.append(__width - __len, __fill);
    00528             break;
    00529           }
    00530           }
    00531
    00532         // Special case of multi-part sign parts.
    00533         if (__sign_size > 1)
    00534           __res.append(__sign + 1, __sign_size - 1);
    00535
    00536         // Pad, if still necessary.
    00537         __len = __res.size();
    00538         if (__width > __len)
    00539           {
    00540         if (__f == ios_base::left)
    00541           // After.
    00542           __res.append(__width - __len, __fill);
    00543         else
    00544           // Before.
    00545           __res.insert(0, __width - __len, __fill);
    00546         __len = __width;
    00547           }
    00548
    00549         // Write resulting, fully-formatted string to output iterator.
    00550         __s = std::__write(__s, __res.data(), __len);
    00551       }
    00552     __io.width(0);
    00553     return __s;
    00554       }
    00555
    00556 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
    00557   template<typename _CharT, typename _OutIter>
    00558     _OutIter
    00559     money_put<_CharT, _OutIter>::
    00560     __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
    00561          double __units) const
    00562     { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
    00563 #endif
    00564
    00565   template<typename _CharT, typename _OutIter>
    00566     _OutIter
    00567     money_put<_CharT, _OutIter>::
    00568     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
    00569        long double __units) const
    00570     {
    00571       const locale __loc = __io.getloc();
    00572       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00573 #ifdef _GLIBCXX_USE_C99
    00574       // First try a buffer perhaps big enough.
    00575       int __cs_size = 64;
    00576       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    00577       // _GLIBCXX_RESOLVE_LIB_DEFECTS
    00578       // 328. Bad sprintf format modifier in money_put<>::do_put()
    00579       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
    00580                     "%.*Lf", 0, __units);
    00581       // If the buffer was not large enough, try again with the correct size.
    00582       if (__len >= __cs_size)
    00583     {
    00584       __cs_size = __len + 1;
    00585       __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    00586       __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
    00587                     "%.*Lf", 0, __units);
    00588     }
    00589 #else
    00590       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
    00591       const int __cs_size =
    00592     __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
    00593       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    00594       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
    00595                     0, __units);
    00596 #endif
    00597       string_type __digits(__len, char_type());
    00598       __ctype.widen(__cs, __cs + __len, &__digits[0]);
    00599       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
    00600                 : _M_insert<false>(__s, __io, __fill, __digits);
    00601     }
    00602
    00603   template<typename _CharT, typename _OutIter>
    00604     _OutIter
    00605     money_put<_CharT, _OutIter>::
    00606     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
    00607        const string_type& __digits) const
    00608     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
    00609                 : _M_insert<false>(__s, __io, __fill, __digits); }
    00610
    00611 _GLIBCXX_END_LDBL_NAMESPACE
    00612
    00613   // NB: Not especially useful. Without an ios_base object or some
    00614   // kind of locale reference, we are left clawing at the air where
    00615   // the side of the mountain used to be...
    00616   template<typename _CharT, typename _InIter>
    00617     time_base::dateorder
    00618     time_get<_CharT, _InIter>::do_date_order() const
    00619     { return time_base::no_order; }
    00620
    00621   // Expand a strftime format string and parse it.  E.g., do_get_date() may
    00622   // pass %m/%d/%Y => extracted characters.
    00623   template<typename _CharT, typename _InIter>
    00624     _InIter
    00625     time_get<_CharT, _InIter>::
    00626     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
    00627               ios_base::iostate& __err, tm* __tm,
    00628               const _CharT* __format) const
    00629     {
    00630       const locale& __loc = __io._M_getloc();
    00631       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
    00632       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00633       const size_t __len = char_traits<_CharT>::length(__format);
    00634
    00635       ios_base::iostate __tmperr = ios_base::goodbit;
    00636       for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i)
    00637     {
    00638       if (__ctype.narrow(__format[__i], 0) == '%')
    00639         {
    00640           // Verify valid formatting code, attempt to extract.
    00641           char __c = __ctype.narrow(__format[++__i], 0);
    00642           int __mem = 0;
    00643           if (__c == 'E' || __c == 'O')
    00644         __c = __ctype.narrow(__format[++__i], 0);
    00645           switch (__c)
    00646         {
    00647           const char* __cs;
    00648           _CharT __wcs[10];
    00649         case 'a':
    00650           // Abbreviated weekday name [tm_wday]
    00651           const char_type*  __days1[7];
    00652           __tp._M_days_abbreviated(__days1);
    00653           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
    00654                       7, __io, __tmperr);
    00655           break;
    00656         case 'A':
    00657           // Weekday name [tm_wday].
    00658           const char_type*  __days2[7];
    00659           __tp._M_days(__days2);
    00660           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
    00661                       7, __io, __tmperr);
    00662           break;
    00663         case 'h':
    00664         case 'b':
    00665           // Abbreviated month name [tm_mon]
    00666           const char_type*  __months1[12];
    00667           __tp._M_months_abbreviated(__months1);
    00668           __beg = _M_extract_name(__beg, __end, __tm->tm_mon,
    00669                       __months1, 12, __io, __tmperr);
    00670           break;
    00671         case 'B':
    00672           // Month name [tm_mon].
    00673           const char_type*  __months2[12];
    00674           __tp._M_months(__months2);
    00675           __beg = _M_extract_name(__beg, __end, __tm->tm_mon,
    00676                       __months2, 12, __io, __tmperr);
    00677           break;
    00678         case 'c':
    00679           // Default time and date representation.
    00680           const char_type*  __dt[2];
    00681           __tp._M_date_time_formats(__dt);
    00682           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
    00683                         __tm, __dt[0]);
    00684           break;
    00685         case 'd':
    00686           // Day [01, 31]. [tm_mday]
    00687           __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
    00688                      __io, __tmperr);
    00689           break;
    00690         case 'e':
    00691           // Day [1, 31], with single digits preceded by
    00692           // space. [tm_mday]
    00693           if (__ctype.is(ctype_base::space, *__beg))
    00694             __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
    00695                        1, __io, __tmperr);
    00696           else
    00697             __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
    00698                        2, __io, __tmperr);
    00699           break;
    00700         case 'D':
    00701           // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
    00702           __cs = "%m/%d/%y";
    00703           __ctype.widen(__cs, __cs + 9, __wcs);
    00704           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
    00705                         __tm, __wcs);
    00706           break;
    00707         case 'H':
    00708           // Hour [00, 23]. [tm_hour]
    00709           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
    00710                      __io, __tmperr);
    00711           break;
    00712         case 'I':
    00713           // Hour [01, 12]. [tm_hour]
    00714           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
    00715                      __io, __tmperr);
    00716           break;
    00717         case 'm':
    00718           // Month [01, 12]. [tm_mon]
    00719           __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
    00720                      __io, __tmperr);
    00721           if (!__tmperr)
    00722             __tm->tm_mon = __mem - 1;
    00723           break;
    00724         case 'M':
    00725           // Minute [00, 59]. [tm_min]
    00726           __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
    00727                      __io, __tmperr);
    00728           break;
    00729         case 'n':
    00730           if (__ctype.narrow(*__beg, 0) == '\n')
    00731             ++__beg;
    00732           else
    00733             __tmperr |= ios_base::failbit;
    00734           break;
    00735         case 'R':
    00736           // Equivalent to (%H:%M).
    00737           __cs = "%H:%M";
    00738           __ctype.widen(__cs, __cs + 6, __wcs);
    00739           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
    00740                         __tm, __wcs);
    00741           break;
    00742         case 'S':
    00743           // Seconds. [tm_sec]
    00744           // [00, 60] in C99 (one leap-second), [00, 61] in C89.
    00745 #ifdef _GLIBCXX_USE_C99
    00746           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
    00747 #else
    00748           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
    00749 #endif
    00750                      __io, __tmperr);
    00751           break;
    00752         case 't':
    00753           if (__ctype.narrow(*__beg, 0) == '\t')
    00754             ++__beg;
    00755           else
    00756             __tmperr |= ios_base::failbit;
    00757           break;
    00758         case 'T':
    00759           // Equivalent to (%H:%M:%S).
    00760           __cs = "%H:%M:%S";
    00761           __ctype.widen(__cs, __cs + 9, __wcs);
    00762           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
    00763                         __tm, __wcs);
    00764           break;
    00765         case 'x':
    00766           // Locale's date.
    00767           const char_type*  __dates[2];
    00768           __tp._M_date_formats(__dates);
    00769           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
    00770                         __tm, __dates[0]);
    00771           break;
    00772         case 'X':
    00773           // Locale's time.
    00774           const char_type*  __times[2];
    00775           __tp._M_time_formats(__times);
    00776           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
    00777                         __tm, __times[0]);
    00778           break;
    00779         case 'y':
    00780         case 'C': // C99
    00781           // Two digit year.
    00782         case 'Y':
    00783           // Year [1900).
    00784           // NB: We parse either two digits, implicitly years since
    00785           // 1900, or 4 digits, full year.  In both cases we can
    00786           // reconstruct [tm_year].  See also libstdc++/26701.
    00787           __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
    00788                      __io, __tmperr);
    00789           if (!__tmperr)
    00790             __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
    00791           break;
    00792         case 'Z':
    00793           // Timezone info.
    00794           if (__ctype.is(ctype_base::upper, *__beg))
    00795             {
    00796               int __tmp;
    00797               __beg = _M_extract_name(__beg, __end, __tmp,
    00798                        __timepunct_cache<_CharT>::_S_timezones,
    00799                           14, __io, __tmperr);
    00800
    00801               // GMT requires special effort.
    00802               if (__beg != __end && !__tmperr && __tmp == 0
    00803               && (*__beg == __ctype.widen('-')
    00804                   || *__beg == __ctype.widen('+')))
    00805             {
    00806               __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
    00807                          __io, __tmperr);
    00808               __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
    00809                          __io, __tmperr);
    00810             }
    00811             }
    00812           else
    00813             __tmperr |= ios_base::failbit;
    00814           break;
    00815         default:
    00816           // Not recognized.
    00817           __tmperr |= ios_base::failbit;
    00818         }
    00819         }
    00820       else
    00821         {
    00822           // Verify format and input match, extract and discard.
    00823           if (__format[__i] == *__beg)
    00824         ++__beg;
    00825           else
    00826         __tmperr |= ios_base::failbit;
    00827         }
    00828     }
    00829
    00830       if (__tmperr)
    00831     __err |= ios_base::failbit;
    00832
    00833       return __beg;
    00834     }
    00835
    00836   template<typename _CharT, typename _InIter>
    00837     _InIter
    00838     time_get<_CharT, _InIter>::
    00839     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
    00840            int __min, int __max, size_t __len,
    00841            ios_base& __io, ios_base::iostate& __err) const
    00842     {
    00843       const locale& __loc = __io._M_getloc();
    00844       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00845
    00846       // As-is works for __len = 1, 2, 4, the values actually used.
    00847       int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
    00848
    00849       ++__min;
    00850       size_t __i = 0;
    00851       int __value = 0;
    00852       for (; __beg != __end && __i < __len; ++__beg, ++__i)
    00853     {
    00854       const char __c = __ctype.narrow(*__beg, '*');
    00855       if (__c >= '0' && __c <= '9')
    00856         {
    00857           __value = __value * 10 + (__c - '0');
    00858           const int __valuec = __value * __mult;
    00859           if (__valuec > __max || __valuec + __mult < __min)
    00860         break;
    00861           __mult /= 10;
    00862         }
    00863       else
    00864         break;
    00865     }
    00866       if (__i == __len)
    00867     __member = __value;
    00868       // Special encoding for do_get_year, 'y', and 'Y' above.
    00869       else if (__len == 4 && __i == 2)
    00870     __member = __value - 100;
    00871       else
    00872     __err |= ios_base::failbit;
    00873
    00874       return __beg;
    00875     }
    00876
    00877   // Assumptions:
    00878   // All elements in __names are unique.
    00879   template<typename _CharT, typename _InIter>
    00880     _InIter
    00881     time_get<_CharT, _InIter>::
    00882     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
    00883             const _CharT** __names, size_t __indexlen,
    00884             ios_base& __io, ios_base::iostate& __err) const
    00885     {
    00886       typedef char_traits<_CharT>       __traits_type;
    00887       const locale& __loc = __io._M_getloc();
    00888       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00889
    00890       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
    00891                               * __indexlen));
    00892       size_t __nmatches = 0;
    00893       size_t __pos = 0;
    00894       bool __testvalid = true;
    00895       const char_type* __name;
    00896
    00897       // Look for initial matches.
    00898       // NB: Some of the locale data is in the form of all lowercase
    00899       // names, and some is in the form of initially-capitalized
    00900       // names. Look for both.
    00901       if (__beg != __end)
    00902     {
    00903       const char_type __c = *__beg;
    00904       for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
    00905         if (__c == __names[__i1][0]
    00906         || __c == __ctype.toupper(__names[__i1][0]))
    00907           __matches[__nmatches++] = __i1;
    00908     }
    00909
    00910       while (__nmatches > 1)
    00911     {
    00912       // Find smallest matching string.
    00913       size_t __minlen = __traits_type::length(__names[__matches[0]]);
    00914       for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
    00915         __minlen = std::min(__minlen,
    00916                   __traits_type::length(__names[__matches[__i2]]));
    00917       ++__beg, ++__pos;
    00918       if (__pos < __minlen && __beg != __end)
    00919         for (size_t __i3 = 0; __i3 < __nmatches;)
    00920           {
    00921         __name = __names[__matches[__i3]];
    00922         if (!(__name[__pos] == *__beg))
    00923           __matches[__i3] = __matches[--__nmatches];
    00924         else
    00925           ++__i3;
    00926           }
    00927       else
    00928         break;
    00929     }
    00930
    00931       if (__nmatches == 1)
    00932     {
    00933       // Make sure found name is completely extracted.
    00934       ++__beg, ++__pos;
    00935       __name = __names[__matches[0]];
    00936       const size_t __len = __traits_type::length(__name);
    00937       while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
    00938         ++__beg, ++__pos;
    00939
    00940       if (__len == __pos)
    00941         __member = __matches[0];
    00942       else
    00943         __testvalid = false;
    00944     }
    00945       else
    00946     __testvalid = false;
    00947       if (!__testvalid)
    00948     __err |= ios_base::failbit;
    00949
    00950       return __beg;
    00951     }
    00952
    00953   template<typename _CharT, typename _InIter>
    00954     _InIter
    00955     time_get<_CharT, _InIter>::
    00956     _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
    00957                  const _CharT** __names, size_t __indexlen,
    00958                  ios_base& __io, ios_base::iostate& __err) const
    00959     {
    00960       typedef char_traits<_CharT>       __traits_type;
    00961       const locale& __loc = __io._M_getloc();
    00962       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    00963
    00964       int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
    00965                               * __indexlen));
    00966       size_t __nmatches = 0;
    00967       size_t* __matches_lengths = 0;
    00968       size_t __pos = 0;
    00969
    00970       if (__beg != __end)
    00971     {
    00972       const char_type __c = *__beg;
    00973       for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
    00974         if (__c == __names[__i][0]
    00975         || __c == __ctype.toupper(__names[__i][0]))
    00976           __matches[__nmatches++] = __i;
    00977     }
    00978
    00979       if (__nmatches)
    00980     {
    00981       ++__beg, ++__pos;
    00982
    00983       __matches_lengths
    00984         = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
    00985                             * __nmatches));
    00986       for (size_t __i = 0; __i < __nmatches; ++__i)
    00987         __matches_lengths[__i]
    00988           = __traits_type::length(__names[__matches[__i]]);
    00989     }
    00990
    00991       for (; __beg != __end; ++__beg, ++__pos)
    00992     {
    00993       size_t __nskipped = 0;
    00994       const char_type __c = *__beg;
    00995       for (size_t __i = 0; __i < __nmatches;)
    00996         {
    00997           const char_type* __name = __names[__matches[__i]];
    00998           if (__pos >= __matches_lengths[__i])
    00999         ++__nskipped, ++__i;
    01000           else if (!(__name[__pos] == __c))
    01001         {
    01002           --__nmatches;
    01003           __matches[__i] = __matches[__nmatches];
    01004           __matches_lengths[__i] = __matches_lengths[__nmatches];
    01005         }
    01006           else
    01007         ++__i;
    01008         }
    01009       if (__nskipped == __nmatches)
    01010         break;
    01011     }
    01012
    01013       if ((__nmatches == 1 && __matches_lengths[0] == __pos)
    01014       || (__nmatches == 2 && (__matches_lengths[0] == __pos
    01015                   || __matches_lengths[1] == __pos)))
    01016     __member = (__matches[0] >= __indexlen
    01017             ? __matches[0] - __indexlen : __matches[0]);
    01018       else
    01019     __err |= ios_base::failbit;
    01020
    01021       return __beg;
    01022     }
    01023
    01024   template<typename _CharT, typename _InIter>
    01025     _InIter
    01026     time_get<_CharT, _InIter>::
    01027     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
    01028         ios_base::iostate& __err, tm* __tm) const
    01029     {
    01030       const locale& __loc = __io._M_getloc();
    01031       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
    01032       const char_type*  __times[2];
    01033       __tp._M_time_formats(__times);
    01034       __beg = _M_extract_via_format(__beg, __end, __io, __err,
    01035                     __tm, __times[0]);
    01036       if (__beg == __end)
    01037     __err |= ios_base::eofbit;
    01038       return __beg;
    01039     }
    01040
    01041   template<typename _CharT, typename _InIter>
    01042     _InIter
    01043     time_get<_CharT, _InIter>::
    01044     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
    01045         ios_base::iostate& __err, tm* __tm) const
    01046     {
    01047       const locale& __loc = __io._M_getloc();
    01048       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
    01049       const char_type*  __dates[2];
    01050       __tp._M_date_formats(__dates);
    01051       __beg = _M_extract_via_format(__beg, __end, __io, __err,
    01052                     __tm, __dates[0]);
    01053       if (__beg == __end)
    01054     __err |= ios_base::eofbit;
    01055       return __beg;
    01056     }
    01057
    01058   template<typename _CharT, typename _InIter>
    01059     _InIter
    01060     time_get<_CharT, _InIter>::
    01061     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
    01062            ios_base::iostate& __err, tm* __tm) const
    01063     {
    01064       typedef char_traits<_CharT>       __traits_type;
    01065       const locale& __loc = __io._M_getloc();
    01066       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
    01067       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    01068       const char_type* __days[14];
    01069       __tp._M_days_abbreviated(__days);
    01070       __tp._M_days(__days + 7);
    01071       int __tmpwday;
    01072       ios_base::iostate __tmperr = ios_base::goodbit;
    01073
    01074       __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
    01075                        __io, __tmperr);
    01076       if (!__tmperr)
    01077     __tm->tm_wday = __tmpwday;
    01078       else
    01079     __err |= ios_base::failbit;
    01080
    01081       if (__beg == __end)
    01082     __err |= ios_base::eofbit;
    01083       return __beg;
    01084      }
    01085
    01086   template<typename _CharT, typename _InIter>
    01087     _InIter
    01088     time_get<_CharT, _InIter>::
    01089     do_get_monthname(iter_type __beg, iter_type __end,
    01090                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
    01091     {
    01092       typedef char_traits<_CharT>       __traits_type;
    01093       const locale& __loc = __io._M_getloc();
    01094       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
    01095       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    01096       const char_type*  __months[24];
    01097       __tp._M_months_abbreviated(__months);
    01098       __tp._M_months(__months + 12);
    01099       int __tmpmon;
    01100       ios_base::iostate __tmperr = ios_base::goodbit;
    01101
    01102       __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
    01103                        __io, __tmperr);
    01104       if (!__tmperr)
    01105     __tm->tm_mon = __tmpmon;
    01106       else
    01107     __err |= ios_base::failbit;
    01108
    01109       if (__beg == __end)
    01110     __err |= ios_base::eofbit;
    01111       return __beg;
    01112     }
    01113
    01114   template<typename _CharT, typename _InIter>
    01115     _InIter
    01116     time_get<_CharT, _InIter>::
    01117     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
    01118         ios_base::iostate& __err, tm* __tm) const
    01119     {
    01120       const locale& __loc = __io._M_getloc();
    01121       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
    01122       int __tmpyear;
    01123       ios_base::iostate __tmperr = ios_base::goodbit;
    01124
    01125       __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
    01126                  __io, __tmperr);
    01127       if (!__tmperr)
    01128     __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
    01129       else
    01130     __err |= ios_base::failbit;
    01131
    01132       if (__beg == __end)
    01133     __err |= ios_base::eofbit;
    01134       return __beg;
    01135     }
    01136
    01137   template<typename _CharT, typename _OutIter>
    01138     _OutIter
    01139     time_put<_CharT, _OutIter>::
    01140     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
    01141     const _CharT* __beg, const _CharT* __end) const
    01142     {
    01143       const locale& __loc = __io._M_getloc();
    01144       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
    01145       for (; __beg != __end; ++__beg)
    01146     if (__ctype.narrow(*__beg, 0) != '%')
    01147       {
    01148         *__s = *__beg;
    01149         ++__s;
    01150       }
    01151     else if (++__beg != __end)
    01152       {
    01153         char __format;
    01154         char __mod = 0;
    01155         const char __c = __ctype.narrow(*__beg, 0);
    01156         if (__c != 'E' && __c != 'O')
    01157           __format = __c;
    01158         else if (++__beg != __end)
    01159           {
    01160         __mod = __c;
    01161         __format = __ctype.narrow(*__beg, 0);
    01162           }
    01163         else
    01164           break;
    01165         __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
    01166       }
    01167     else
    01168       break;
    01169       return __s;
    01170     }
    01171
    01172   template<typename _CharT, typename _OutIter>
    01173     _OutIter
    01174     time_put<_CharT, _OutIter>::
    01175     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
    01176        char __format, char __mod) const
    01177     {
    01178       const locale& __loc = __io._M_getloc();
    01179       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
    01180       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
    01181
    01182       // NB: This size is arbitrary. Should this be a data member,
    01183       // initialized at construction?
    01184       const size_t __maxlen = 128;
    01185       char_type __res[__maxlen];
    01186
    01187       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
    01188       // is possible that the format character will be longer than one
    01189       // character. Possibilities include 'E' or 'O' followed by a
    01190       // format character: if __mod is not the default argument, assume
    01191       // it's a valid modifier.
    01192       char_type __fmt[4];
    01193       __fmt[0] = __ctype.widen('%');
    01194       if (!__mod)
    01195     {
    01196       __fmt[1] = __format;
    01197       __fmt[2] = char_type();
    01198     }
    01199       else
    01200     {
    01201       __fmt[1] = __mod;
    01202       __fmt[2] = __format;
    01203       __fmt[3] = char_type();
    01204     }
    01205
    01206       __tp._M_put(__res, __maxlen, __fmt, __tm);
    01207
    01208       // Write resulting, fully-formatted string to output iterator.
    01209       return std::__write(__s, __res, char_traits<char_type>::length(__res));
    01210     }
    01211
    01212
    01213   // Inhibit implicit instantiations for required instantiations,
    01214   // which are defined via explicit instantiations elsewhere.
    01215   // NB: This syntax is a GNU extension.
    01216 #if _GLIBCXX_EXTERN_TEMPLATE
    01217   extern template class moneypunct<char, false>;
    01218   extern template class moneypunct<char, true>;
    01219   extern template class moneypunct_byname<char, false>;
    01220   extern template class moneypunct_byname<char, true>;
    01221   extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
    01222   extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
    01223   extern template class __timepunct<char>;
    01224   extern template class time_put<char>;
    01225   extern template class time_put_byname<char>;
    01226   extern template class time_get<char>;
    01227   extern template class time_get_byname<char>;
    01228   extern template class messages<char>;
    01229   extern template class messages_byname<char>;
    01230
    01231   extern template
    01232     const moneypunct<char, true>&
    01233     use_facet<moneypunct<char, true> >(const locale&);
    01234
    01235   extern template
    01236     const moneypunct<char, false>&
    01237     use_facet<moneypunct<char, false> >(const locale&);
    01238
    01239   extern template
    01240     const money_put<char>&
    01241     use_facet<money_put<char> >(const locale&);
    01242
    01243   extern template
    01244     const money_get<char>&
    01245     use_facet<money_get<char> >(const locale&);
    01246
    01247   extern template
    01248     const __timepunct<char>&
    01249     use_facet<__timepunct<char> >(const locale&);
    01250
    01251   extern template
    01252     const time_put<char>&
    01253     use_facet<time_put<char> >(const locale&);
    01254
    01255   extern template
    01256     const time_get<char>&
    01257     use_facet<time_get<char> >(const locale&);
    01258
    01259   extern template
    01260     const messages<char>&
    01261     use_facet<messages<char> >(const locale&);
    01262
    01263   extern template
    01264     bool
    01265     has_facet<moneypunct<char> >(const locale&);
    01266
    01267   extern template
    01268     bool
    01269     has_facet<money_put<char> >(const locale&);
    01270
    01271   extern template
    01272     bool
    01273     has_facet<money_get<char> >(const locale&);
    01274
    01275   extern template
    01276     bool
    01277     has_facet<__timepunct<char> >(const locale&);
    01278
    01279   extern template
    01280     bool
    01281     has_facet<time_put<char> >(const locale&);
    01282
    01283   extern template
    01284     bool
    01285     has_facet<time_get<char> >(const locale&);
    01286
    01287   extern template
    01288     bool
    01289     has_facet<messages<char> >(const locale&);
    01290
    01291 #ifdef _GLIBCXX_USE_WCHAR_T
    01292   extern template class moneypunct<wchar_t, false>;
    01293   extern template class moneypunct<wchar_t, true>;
    01294   extern template class moneypunct_byname<wchar_t, false>;
    01295   extern template class moneypunct_byname<wchar_t, true>;
    01296   extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
    01297   extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
    01298   extern template class __timepunct<wchar_t>;
    01299   extern template class time_put<wchar_t>;
    01300   extern template class time_put_byname<wchar_t>;
    01301   extern template class time_get<wchar_t>;
    01302   extern template class time_get_byname<wchar_t>;
    01303   extern template class messages<wchar_t>;
    01304   extern template class messages_byname<wchar_t>;
    01305
    01306   extern template
    01307     const moneypunct<wchar_t, true>&
    01308     use_facet<moneypunct<wchar_t, true> >(const locale&);
    01309
    01310   extern template
    01311     const moneypunct<wchar_t, false>&
    01312     use_facet<moneypunct<wchar_t, false> >(const locale&);
    01313
    01314   extern template
    01315     const money_put<wchar_t>&
    01316     use_facet<money_put<wchar_t> >(const locale&);
    01317
    01318   extern template
    01319     const money_get<wchar_t>&
    01320     use_facet<money_get<wchar_t> >(const locale&);
    01321
    01322   extern template
    01323     const __timepunct<wchar_t>&
    01324     use_facet<__timepunct<wchar_t> >(const locale&);
    01325
    01326   extern template
    01327     const time_put<wchar_t>&
    01328     use_facet<time_put<wchar_t> >(const locale&);
    01329
    01330   extern template
    01331     const time_get<wchar_t>&
    01332     use_facet<time_get<wchar_t> >(const locale&);
    01333
    01334   extern template
    01335     const messages<wchar_t>&
    01336     use_facet<messages<wchar_t> >(const locale&);
    01337
    01338   extern template
    01339     bool
    01340     has_facet<moneypunct<wchar_t> >(const locale&);
    01341
    01342   extern template
    01343     bool
    01344     has_facet<money_put<wchar_t> >(const locale&);
    01345
    01346   extern template
    01347     bool
    01348     has_facet<money_get<wchar_t> >(const locale&);
    01349
    01350   extern template
    01351     bool
    01352     has_facet<__timepunct<wchar_t> >(const locale&);
    01353
    01354   extern template
    01355     bool
    01356     has_facet<time_put<wchar_t> >(const locale&);
    01357
    01358   extern template
    01359     bool
    01360     has_facet<time_get<wchar_t> >(const locale&);
    01361
    01362   extern template
    01363     bool
    01364     has_facet<messages<wchar_t> >(const locale&);
    01365 #endif
    01366 #endif
    01367
    01368 _GLIBCXX_END_NAMESPACE
    01369
    01370 #endif