# locale_facets_nonio.tcc

Go to the documentation of this file.

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