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