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 = 0;
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       size_t __i = 0;
00637       for (; __beg != __end && __i < __len && !__tmperr; ++__i)
00638     {
00639       if (__ctype.narrow(__format[__i], 0) == '%')
00640         {
00641           // Verify valid formatting code, attempt to extract.
00642           char __c = __ctype.narrow(__format[++__i], 0);
00643           int __mem = 0;
00644           if (__c == 'E' || __c == 'O')
00645         __c = __ctype.narrow(__format[++__i], 0);
00646           switch (__c)
00647         {
00648           const char* __cs;
00649           _CharT __wcs[10];
00650         case 'a':
00651           // Abbreviated weekday name [tm_wday]
00652           const char_type*  __days1[7];
00653           __tp._M_days_abbreviated(__days1);
00654           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
00655                       7, __io, __tmperr);
00656           break;
00657         case 'A':
00658           // Weekday name [tm_wday].
00659           const char_type*  __days2[7];
00660           __tp._M_days(__days2);
00661           __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
00662                       7, __io, __tmperr);
00663           break;
00664         case 'h':
00665         case 'b':
00666           // Abbreviated month name [tm_mon]
00667           const char_type*  __months1[12];
00668           __tp._M_months_abbreviated(__months1);
00669           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
00670                       __months1, 12, __io, __tmperr);
00671           break;
00672         case 'B':
00673           // Month name [tm_mon].
00674           const char_type*  __months2[12];
00675           __tp._M_months(__months2);
00676           __beg = _M_extract_name(__beg, __end, __tm->tm_mon, 
00677                       __months2, 12, __io, __tmperr);
00678           break;
00679         case 'c':
00680           // Default time and date representation.
00681           const char_type*  __dt[2];
00682           __tp._M_date_time_formats(__dt);
00683           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00684                         __tm, __dt[0]);
00685           break;
00686         case 'd':
00687           // Day [01, 31]. [tm_mday]
00688           __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
00689                      __io, __tmperr);
00690           break;
00691         case 'e':
00692           // Day [1, 31], with single digits preceded by
00693           // space. [tm_mday]
00694           if (__ctype.is(ctype_base::space, *__beg))
00695             __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
00696                        1, __io, __tmperr);
00697           else
00698             __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
00699                        2, __io, __tmperr);
00700           break;
00701         case 'D':
00702           // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
00703           __cs = "%m/%d/%y";
00704           __ctype.widen(__cs, __cs + 9, __wcs);
00705           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00706                         __tm, __wcs);
00707           break;
00708         case 'H':
00709           // Hour [00, 23]. [tm_hour]
00710           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
00711                      __io, __tmperr);
00712           break;
00713         case 'I':
00714           // Hour [01, 12]. [tm_hour]
00715           __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
00716                      __io, __tmperr);
00717           break;
00718         case 'm':
00719           // Month [01, 12]. [tm_mon]
00720           __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
00721                      __io, __tmperr);
00722           if (!__tmperr)
00723             __tm->tm_mon = __mem - 1;
00724           break;
00725         case 'M':
00726           // Minute [00, 59]. [tm_min]
00727           __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
00728                      __io, __tmperr);
00729           break;
00730         case 'n':
00731           if (__ctype.narrow(*__beg, 0) == '\n')
00732             ++__beg;
00733           else
00734             __tmperr |= ios_base::failbit;
00735           break;
00736         case 'R':
00737           // Equivalent to (%H:%M).
00738           __cs = "%H:%M";
00739           __ctype.widen(__cs, __cs + 6, __wcs);
00740           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00741                         __tm, __wcs);
00742           break;
00743         case 'S':
00744           // Seconds. [tm_sec]
00745           // [00, 60] in C99 (one leap-second), [00, 61] in C89.
00746 #ifdef _GLIBCXX_USE_C99
00747           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
00748 #else
00749           __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
00750 #endif
00751                      __io, __tmperr);
00752           break;
00753         case 't':
00754           if (__ctype.narrow(*__beg, 0) == '\t')
00755             ++__beg;
00756           else
00757             __tmperr |= ios_base::failbit;
00758           break;
00759         case 'T':
00760           // Equivalent to (%H:%M:%S).
00761           __cs = "%H:%M:%S";
00762           __ctype.widen(__cs, __cs + 9, __wcs);
00763           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00764                         __tm, __wcs);
00765           break;
00766         case 'x':
00767           // Locale's date.
00768           const char_type*  __dates[2];
00769           __tp._M_date_formats(__dates);
00770           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00771                         __tm, __dates[0]);
00772           break;
00773         case 'X':
00774           // Locale's time.
00775           const char_type*  __times[2];
00776           __tp._M_time_formats(__times);
00777           __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
00778                         __tm, __times[0]);
00779           break;
00780         case 'y':
00781         case 'C': // C99
00782           // Two digit year.
00783         case 'Y':
00784           // Year [1900).
00785           // NB: We parse either two digits, implicitly years since
00786           // 1900, or 4 digits, full year.  In both cases we can 
00787           // reconstruct [tm_year].  See also libstdc++/26701.
00788           __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
00789                      __io, __tmperr);
00790           if (!__tmperr)
00791             __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
00792           break;
00793         case 'Z':
00794           // Timezone info.
00795           if (__ctype.is(ctype_base::upper, *__beg))
00796             {
00797               int __tmp;
00798               __beg = _M_extract_name(__beg, __end, __tmp,
00799                        __timepunct_cache<_CharT>::_S_timezones,
00800                           14, __io, __tmperr);
00801 
00802               // GMT requires special effort.
00803               if (__beg != __end && !__tmperr && __tmp == 0
00804               && (*__beg == __ctype.widen('-')
00805                   || *__beg == __ctype.widen('+')))
00806             {
00807               __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
00808                          __io, __tmperr);
00809               __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
00810                          __io, __tmperr);
00811             }
00812             }
00813           else
00814             __tmperr |= ios_base::failbit;
00815           break;
00816         default:
00817           // Not recognized.
00818           __tmperr |= ios_base::failbit;
00819         }
00820         }
00821       else
00822         {
00823           // Verify format and input match, extract and discard.
00824           if (__format[__i] == *__beg)
00825         ++__beg;
00826           else
00827         __tmperr |= ios_base::failbit;
00828         }
00829     }
00830 
00831       if (__tmperr || __i != __len)
00832     __err |= ios_base::failbit;
00833   
00834       return __beg;
00835     }
00836 
00837   template<typename _CharT, typename _InIter>
00838     _InIter
00839     time_get<_CharT, _InIter>::
00840     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
00841            int __min, int __max, size_t __len,
00842            ios_base& __io, ios_base::iostate& __err) const
00843     {
00844       const locale& __loc = __io._M_getloc();
00845       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00846 
00847       // As-is works for __len = 1, 2, 4, the values actually used.
00848       int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
00849 
00850       ++__min;
00851       size_t __i = 0;
00852       int __value = 0;
00853       for (; __beg != __end && __i < __len; ++__beg, ++__i)
00854     {
00855       const char __c = __ctype.narrow(*__beg, '*');
00856       if (__c >= '0' && __c <= '9')
00857         {
00858           __value = __value * 10 + (__c - '0');
00859           const int __valuec = __value * __mult;
00860           if (__valuec > __max || __valuec + __mult < __min)
00861         break;
00862           __mult /= 10;
00863         }
00864       else
00865         break;
00866     }
00867       if (__i == __len)
00868     __member = __value;
00869       // Special encoding for do_get_year, 'y', and 'Y' above.
00870       else if (__len == 4 && __i == 2)
00871     __member = __value - 100;
00872       else
00873     __err |= ios_base::failbit;
00874 
00875       return __beg;
00876     }
00877 
00878   // Assumptions:
00879   // All elements in __names are unique.
00880   template<typename _CharT, typename _InIter>
00881     _InIter
00882     time_get<_CharT, _InIter>::
00883     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
00884             const _CharT** __names, size_t __indexlen,
00885             ios_base& __io, ios_base::iostate& __err) const
00886     {
00887       typedef char_traits<_CharT>       __traits_type;
00888       const locale& __loc = __io._M_getloc();
00889       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00890 
00891       int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
00892                               * __indexlen));
00893       size_t __nmatches = 0;
00894       size_t __pos = 0;
00895       bool __testvalid = true;
00896       const char_type* __name;
00897 
00898       // Look for initial matches.
00899       // NB: Some of the locale data is in the form of all lowercase
00900       // names, and some is in the form of initially-capitalized
00901       // names. Look for both.
00902       if (__beg != __end)
00903     {
00904       const char_type __c = *__beg;
00905       for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
00906         if (__c == __names[__i1][0]
00907         || __c == __ctype.toupper(__names[__i1][0]))
00908           __matches[__nmatches++] = __i1;
00909     }
00910 
00911       while (__nmatches > 1)
00912     {
00913       // Find smallest matching string.
00914       size_t __minlen = __traits_type::length(__names[__matches[0]]);
00915       for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
00916         __minlen = std::min(__minlen,
00917                   __traits_type::length(__names[__matches[__i2]]));
00918       ++__beg, ++__pos;
00919       if (__pos < __minlen && __beg != __end)
00920         for (size_t __i3 = 0; __i3 < __nmatches;)
00921           {
00922         __name = __names[__matches[__i3]];
00923         if (!(__name[__pos] == *__beg))
00924           __matches[__i3] = __matches[--__nmatches];
00925         else
00926           ++__i3;
00927           }
00928       else
00929         break;
00930     }
00931 
00932       if (__nmatches == 1)
00933     {
00934       // Make sure found name is completely extracted.
00935       ++__beg, ++__pos;
00936       __name = __names[__matches[0]];
00937       const size_t __len = __traits_type::length(__name);
00938       while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
00939         ++__beg, ++__pos;
00940 
00941       if (__len == __pos)
00942         __member = __matches[0];
00943       else
00944         __testvalid = false;
00945     }
00946       else
00947     __testvalid = false;
00948       if (!__testvalid)
00949     __err |= ios_base::failbit;
00950 
00951       return __beg;
00952     }
00953 
00954   template<typename _CharT, typename _InIter>
00955     _InIter
00956     time_get<_CharT, _InIter>::
00957     _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
00958                  const _CharT** __names, size_t __indexlen,
00959                  ios_base& __io, ios_base::iostate& __err) const
00960     {
00961       typedef char_traits<_CharT>       __traits_type;
00962       const locale& __loc = __io._M_getloc();
00963       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00964 
00965       int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
00966                               * __indexlen));
00967       size_t __nmatches = 0;
00968       size_t* __matches_lengths = 0;
00969       size_t __pos = 0;
00970 
00971       if (__beg != __end)
00972     {
00973       const char_type __c = *__beg;
00974       for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
00975         if (__c == __names[__i][0]
00976         || __c == __ctype.toupper(__names[__i][0]))
00977           __matches[__nmatches++] = __i;
00978     }
00979 
00980       if (__nmatches)
00981     {
00982       ++__beg, ++__pos;
00983 
00984       __matches_lengths
00985         = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
00986                             * __nmatches));
00987       for (size_t __i = 0; __i < __nmatches; ++__i)
00988         __matches_lengths[__i]
00989           = __traits_type::length(__names[__matches[__i]]);
00990     }
00991 
00992       for (; __beg != __end; ++__beg, ++__pos)
00993     {
00994       size_t __nskipped = 0;
00995       const char_type __c = *__beg;
00996       for (size_t __i = 0; __i < __nmatches;)
00997         {
00998           const char_type* __name = __names[__matches[__i]];
00999           if (__pos >= __matches_lengths[__i])
01000         ++__nskipped, ++__i;
01001           else if (!(__name[__pos] == __c))
01002         {
01003           --__nmatches;
01004           __matches[__i] = __matches[__nmatches];
01005           __matches_lengths[__i] = __matches_lengths[__nmatches];
01006         }
01007           else
01008         ++__i;
01009         }
01010       if (__nskipped == __nmatches)
01011         break;
01012     }
01013 
01014       if ((__nmatches == 1 && __matches_lengths[0] == __pos)
01015       || (__nmatches == 2 && (__matches_lengths[0] == __pos
01016                   || __matches_lengths[1] == __pos)))
01017     __member = (__matches[0] >= __indexlen
01018             ? __matches[0] - __indexlen : __matches[0]);
01019       else
01020     __err |= ios_base::failbit;
01021 
01022       return __beg;
01023     }
01024 
01025   template<typename _CharT, typename _InIter>
01026     _InIter
01027     time_get<_CharT, _InIter>::
01028     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
01029         ios_base::iostate& __err, tm* __tm) const
01030     {
01031       const locale& __loc = __io._M_getloc();
01032       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01033       const char_type*  __times[2];
01034       __tp._M_time_formats(__times);
01035       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01036                     __tm, __times[0]);
01037       if (__beg == __end)
01038     __err |= ios_base::eofbit;
01039       return __beg;
01040     }
01041 
01042   template<typename _CharT, typename _InIter>
01043     _InIter
01044     time_get<_CharT, _InIter>::
01045     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
01046         ios_base::iostate& __err, tm* __tm) const
01047     {
01048       const locale& __loc = __io._M_getloc();
01049       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01050       const char_type*  __dates[2];
01051       __tp._M_date_formats(__dates);
01052       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01053                     __tm, __dates[0]);
01054       if (__beg == __end)
01055     __err |= ios_base::eofbit;
01056       return __beg;
01057     }
01058 
01059   template<typename _CharT, typename _InIter>
01060     _InIter
01061     time_get<_CharT, _InIter>::
01062     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
01063            ios_base::iostate& __err, tm* __tm) const
01064     {
01065       typedef char_traits<_CharT>       __traits_type;
01066       const locale& __loc = __io._M_getloc();
01067       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01068       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01069       const char_type* __days[14];
01070       __tp._M_days_abbreviated(__days);
01071       __tp._M_days(__days + 7);
01072       int __tmpwday;
01073       ios_base::iostate __tmperr = ios_base::goodbit;
01074 
01075       __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
01076                        __io, __tmperr);
01077       if (!__tmperr)
01078     __tm->tm_wday = __tmpwday;
01079       else
01080     __err |= ios_base::failbit;
01081 
01082       if (__beg == __end)
01083     __err |= ios_base::eofbit;
01084       return __beg;
01085      }
01086 
01087   template<typename _CharT, typename _InIter>
01088     _InIter
01089     time_get<_CharT, _InIter>::
01090     do_get_monthname(iter_type __beg, iter_type __end,
01091                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
01092     {
01093       typedef char_traits<_CharT>       __traits_type;
01094       const locale& __loc = __io._M_getloc();
01095       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01096       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01097       const char_type*  __months[24];
01098       __tp._M_months_abbreviated(__months);
01099       __tp._M_months(__months + 12);
01100       int __tmpmon;
01101       ios_base::iostate __tmperr = ios_base::goodbit;
01102 
01103       __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
01104                        __io, __tmperr);
01105       if (!__tmperr)
01106     __tm->tm_mon = __tmpmon;
01107       else
01108     __err |= ios_base::failbit;
01109 
01110       if (__beg == __end)
01111     __err |= ios_base::eofbit;
01112       return __beg;
01113     }
01114 
01115   template<typename _CharT, typename _InIter>
01116     _InIter
01117     time_get<_CharT, _InIter>::
01118     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
01119         ios_base::iostate& __err, tm* __tm) const
01120     {
01121       const locale& __loc = __io._M_getloc();
01122       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01123       int __tmpyear;
01124       ios_base::iostate __tmperr = ios_base::goodbit;
01125 
01126       __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
01127                  __io, __tmperr);
01128       if (!__tmperr)
01129     __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
01130       else
01131     __err |= ios_base::failbit;
01132 
01133       if (__beg == __end)
01134     __err |= ios_base::eofbit;
01135       return __beg;
01136     }
01137 
01138   template<typename _CharT, typename _OutIter>
01139     _OutIter
01140     time_put<_CharT, _OutIter>::
01141     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
01142     const _CharT* __beg, const _CharT* __end) const
01143     {
01144       const locale& __loc = __io._M_getloc();
01145       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
01146       for (; __beg != __end; ++__beg)
01147     if (__ctype.narrow(*__beg, 0) != '%')
01148       {
01149         *__s = *__beg;
01150         ++__s;
01151       }
01152     else if (++__beg != __end)
01153       {
01154         char __format;
01155         char __mod = 0;
01156         const char __c = __ctype.narrow(*__beg, 0);
01157         if (__c != 'E' && __c != 'O')
01158           __format = __c;
01159         else if (++__beg != __end)
01160           {
01161         __mod = __c;
01162         __format = __ctype.narrow(*__beg, 0);
01163           }
01164         else
01165           break;
01166         __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
01167       }
01168     else
01169       break;
01170       return __s;
01171     }
01172 
01173   template<typename _CharT, typename _OutIter>
01174     _OutIter
01175     time_put<_CharT, _OutIter>::
01176     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
01177        char __format, char __mod) const
01178     {
01179       const locale& __loc = __io._M_getloc();
01180       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
01181       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
01182 
01183       // NB: This size is arbitrary. Should this be a data member,
01184       // initialized at construction?
01185       const size_t __maxlen = 128;
01186       char_type __res[__maxlen];
01187 
01188       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
01189       // is possible that the format character will be longer than one
01190       // character. Possibilities include 'E' or 'O' followed by a
01191       // format character: if __mod is not the default argument, assume
01192       // it's a valid modifier.
01193       char_type __fmt[4];
01194       __fmt[0] = __ctype.widen('%');
01195       if (!__mod)
01196     {
01197       __fmt[1] = __format;
01198       __fmt[2] = char_type();
01199     }
01200       else
01201     {
01202       __fmt[1] = __mod;
01203       __fmt[2] = __format;
01204       __fmt[3] = char_type();
01205     }
01206 
01207       __tp._M_put(__res, __maxlen, __fmt, __tm);
01208 
01209       // Write resulting, fully-formatted string to output iterator.
01210       return std::__write(__s, __res, char_traits<char_type>::length(__res));
01211     }
01212 
01213 
01214   // Inhibit implicit instantiations for required instantiations,
01215   // which are defined via explicit instantiations elsewhere.
01216   // NB: This syntax is a GNU extension.
01217 #if _GLIBCXX_EXTERN_TEMPLATE
01218   extern template class moneypunct<char, false>;
01219   extern template class moneypunct<char, true>;
01220   extern template class moneypunct_byname<char, false>;
01221   extern template class moneypunct_byname<char, true>;
01222   extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
01223   extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
01224   extern template class __timepunct<char>;
01225   extern template class time_put<char>;
01226   extern template class time_put_byname<char>;
01227   extern template class time_get<char>;
01228   extern template class time_get_byname<char>;
01229   extern template class messages<char>;
01230   extern template class messages_byname<char>;
01231 
01232   extern template
01233     const moneypunct<char, true>&
01234     use_facet<moneypunct<char, true> >(const locale&);
01235 
01236   extern template
01237     const moneypunct<char, false>&
01238     use_facet<moneypunct<char, false> >(const locale&);
01239 
01240   extern template
01241     const money_put<char>&
01242     use_facet<money_put<char> >(const locale&);
01243 
01244   extern template
01245     const money_get<char>&
01246     use_facet<money_get<char> >(const locale&);
01247 
01248   extern template
01249     const __timepunct<char>&
01250     use_facet<__timepunct<char> >(const locale&);
01251 
01252   extern template
01253     const time_put<char>&
01254     use_facet<time_put<char> >(const locale&);
01255 
01256   extern template
01257     const time_get<char>&
01258     use_facet<time_get<char> >(const locale&);
01259 
01260   extern template
01261     const messages<char>&
01262     use_facet<messages<char> >(const locale&);
01263 
01264   extern template
01265     bool
01266     has_facet<moneypunct<char> >(const locale&);
01267 
01268   extern template
01269     bool
01270     has_facet<money_put<char> >(const locale&);
01271 
01272   extern template
01273     bool
01274     has_facet<money_get<char> >(const locale&);
01275 
01276   extern template
01277     bool
01278     has_facet<__timepunct<char> >(const locale&);
01279 
01280   extern template
01281     bool
01282     has_facet<time_put<char> >(const locale&);
01283 
01284   extern template
01285     bool
01286     has_facet<time_get<char> >(const locale&);
01287 
01288   extern template
01289     bool
01290     has_facet<messages<char> >(const locale&);
01291 
01292 #ifdef _GLIBCXX_USE_WCHAR_T
01293   extern template class moneypunct<wchar_t, false>;
01294   extern template class moneypunct<wchar_t, true>;
01295   extern template class moneypunct_byname<wchar_t, false>;
01296   extern template class moneypunct_byname<wchar_t, true>;
01297   extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
01298   extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
01299   extern template class __timepunct<wchar_t>;
01300   extern template class time_put<wchar_t>;
01301   extern template class time_put_byname<wchar_t>;
01302   extern template class time_get<wchar_t>;
01303   extern template class time_get_byname<wchar_t>;
01304   extern template class messages<wchar_t>;
01305   extern template class messages_byname<wchar_t>;
01306 
01307   extern template
01308     const moneypunct<wchar_t, true>&
01309     use_facet<moneypunct<wchar_t, true> >(const locale&);
01310 
01311   extern template
01312     const moneypunct<wchar_t, false>&
01313     use_facet<moneypunct<wchar_t, false> >(const locale&);
01314 
01315   extern template
01316     const money_put<wchar_t>&
01317     use_facet<money_put<wchar_t> >(const locale&);
01318 
01319   extern template
01320     const money_get<wchar_t>&
01321     use_facet<money_get<wchar_t> >(const locale&);
01322 
01323   extern template
01324     const __timepunct<wchar_t>&
01325     use_facet<__timepunct<wchar_t> >(const locale&);
01326 
01327   extern template
01328     const time_put<wchar_t>&
01329     use_facet<time_put<wchar_t> >(const locale&);
01330 
01331   extern template
01332     const time_get<wchar_t>&
01333     use_facet<time_get<wchar_t> >(const locale&);
01334 
01335   extern template
01336     const messages<wchar_t>&
01337     use_facet<messages<wchar_t> >(const locale&);
01338 
01339   extern template
01340     bool
01341     has_facet<moneypunct<wchar_t> >(const locale&);
01342 
01343   extern template
01344     bool
01345     has_facet<money_put<wchar_t> >(const locale&);
01346 
01347   extern template
01348     bool
01349     has_facet<money_get<wchar_t> >(const locale&);
01350 
01351   extern template
01352     bool
01353     has_facet<__timepunct<wchar_t> >(const locale&);
01354 
01355   extern template
01356     bool
01357     has_facet<time_put<wchar_t> >(const locale&);
01358 
01359   extern template
01360     bool
01361     has_facet<time_get<wchar_t> >(const locale&);
01362 
01363   extern template
01364     bool
01365     has_facet<messages<wchar_t> >(const locale&);
01366 #endif
01367 #endif
01368 
01369 _GLIBCXX_END_NAMESPACE
01370 
01371 #endif