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