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