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