libstdc++
locale_facets_nonio.tcc
Go to the documentation of this file.
00001 // Locale support -*- C++ -*-
00002 
00003 // Copyright (C) 2007-2015 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, ++__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, ++__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 #ifdef _GLIBCXX_USE_C99
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 #ifdef _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, ++__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, ++__pos;
00927           if (__pos < __minlen && __beg != __end)
00928             for (size_t __i3 = 0; __i3 < __nmatches;)
00929               {
00930                 __name = __names[__matches[__i3]];
00931                 if (!(__name[__pos] == *__beg))
00932                   __matches[__i3] = __matches[--__nmatches];
00933                 else
00934                   ++__i3;
00935               }
00936           else
00937             break;
00938         }
00939 
00940       if (__nmatches == 1)
00941         {
00942           // Make sure found name is completely extracted.
00943           ++__beg, ++__pos;
00944           __name = __names[__matches[0]];
00945           const size_t __len = __traits_type::length(__name);
00946           while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
00947             ++__beg, ++__pos;
00948 
00949           if (__len == __pos)
00950             __member = __matches[0];
00951           else
00952             __testvalid = false;
00953         }
00954       else
00955         __testvalid = false;
00956       if (!__testvalid)
00957         __err |= ios_base::failbit;
00958 
00959       return __beg;
00960     }
00961 
00962   template<typename _CharT, typename _InIter>
00963     _InIter
00964     time_get<_CharT, _InIter>::
00965     _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
00966                              const _CharT** __names, size_t __indexlen,
00967                              ios_base& __io, ios_base::iostate& __err) const
00968     {
00969       typedef char_traits<_CharT>               __traits_type;
00970       const locale& __loc = __io._M_getloc();
00971       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
00972 
00973       int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
00974                                                           * __indexlen));
00975       size_t __nmatches = 0;
00976       size_t* __matches_lengths = 0;
00977       size_t __pos = 0;
00978 
00979       if (__beg != __end)
00980         {
00981           const char_type __c = *__beg;
00982           for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
00983             if (__c == __names[__i][0]
00984                 || __c == __ctype.toupper(__names[__i][0]))
00985               __matches[__nmatches++] = __i;
00986         }
00987 
00988       if (__nmatches)
00989         {
00990           ++__beg, ++__pos;
00991 
00992           __matches_lengths
00993             = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
00994                                                     * __nmatches));
00995           for (size_t __i = 0; __i < __nmatches; ++__i)
00996             __matches_lengths[__i]
00997               = __traits_type::length(__names[__matches[__i]]);
00998         }
00999 
01000       for (; __beg != __end; ++__beg, ++__pos)
01001         {
01002           size_t __nskipped = 0;
01003           const char_type __c = *__beg;
01004           for (size_t __i = 0; __i < __nmatches;)
01005             {
01006               const char_type* __name = __names[__matches[__i]];
01007               if (__pos >= __matches_lengths[__i])
01008                 ++__nskipped, ++__i;
01009               else if (!(__name[__pos] == __c))
01010                 {
01011                   --__nmatches;
01012                   __matches[__i] = __matches[__nmatches];
01013                   __matches_lengths[__i] = __matches_lengths[__nmatches];
01014                 }
01015               else
01016                 ++__i;
01017             }
01018           if (__nskipped == __nmatches)
01019             break;
01020         }
01021 
01022       if ((__nmatches == 1 && __matches_lengths[0] == __pos)
01023           || (__nmatches == 2 && (__matches_lengths[0] == __pos
01024                                   || __matches_lengths[1] == __pos)))
01025         __member = (__matches[0] >= __indexlen
01026                     ? __matches[0] - __indexlen : __matches[0]);
01027       else
01028         __err |= ios_base::failbit;
01029 
01030       return __beg;
01031     }
01032 
01033   template<typename _CharT, typename _InIter>
01034     _InIter
01035     time_get<_CharT, _InIter>::
01036     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
01037                 ios_base::iostate& __err, tm* __tm) const
01038     {
01039       const locale& __loc = __io._M_getloc();
01040       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01041       const char_type*  __times[2];
01042       __tp._M_time_formats(__times);
01043       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01044                                     __tm, __times[0]);
01045       if (__beg == __end)
01046         __err |= ios_base::eofbit;
01047       return __beg;
01048     }
01049 
01050   template<typename _CharT, typename _InIter>
01051     _InIter
01052     time_get<_CharT, _InIter>::
01053     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
01054                 ios_base::iostate& __err, tm* __tm) const
01055     {
01056       const locale& __loc = __io._M_getloc();
01057       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01058       const char_type*  __dates[2];
01059       __tp._M_date_formats(__dates);
01060       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
01061                                     __tm, __dates[0]);
01062       if (__beg == __end)
01063         __err |= ios_base::eofbit;
01064       return __beg;
01065     }
01066 
01067   template<typename _CharT, typename _InIter>
01068     _InIter
01069     time_get<_CharT, _InIter>::
01070     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
01071                    ios_base::iostate& __err, tm* __tm) const
01072     {
01073       const locale& __loc = __io._M_getloc();
01074       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01075       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01076       const char_type* __days[14];
01077       __tp._M_days_abbreviated(__days);
01078       __tp._M_days(__days + 7);
01079       int __tmpwday;
01080       ios_base::iostate __tmperr = ios_base::goodbit;
01081 
01082       __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
01083                                        __io, __tmperr);
01084       if (!__tmperr)
01085         __tm->tm_wday = __tmpwday;
01086       else
01087         __err |= ios_base::failbit;
01088 
01089       if (__beg == __end)
01090         __err |= ios_base::eofbit;
01091       return __beg;
01092      }
01093 
01094   template<typename _CharT, typename _InIter>
01095     _InIter
01096     time_get<_CharT, _InIter>::
01097     do_get_monthname(iter_type __beg, iter_type __end,
01098                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
01099     {
01100       const locale& __loc = __io._M_getloc();
01101       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
01102       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01103       const char_type*  __months[24];
01104       __tp._M_months_abbreviated(__months);
01105       __tp._M_months(__months + 12);
01106       int __tmpmon;
01107       ios_base::iostate __tmperr = ios_base::goodbit;
01108 
01109       __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
01110                                        __io, __tmperr);
01111       if (!__tmperr)
01112         __tm->tm_mon = __tmpmon;
01113       else
01114         __err |= ios_base::failbit;
01115 
01116       if (__beg == __end)
01117         __err |= ios_base::eofbit;
01118       return __beg;
01119     }
01120 
01121   template<typename _CharT, typename _InIter>
01122     _InIter
01123     time_get<_CharT, _InIter>::
01124     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
01125                 ios_base::iostate& __err, tm* __tm) const
01126     {
01127       const locale& __loc = __io._M_getloc();
01128       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
01129       int __tmpyear;
01130       ios_base::iostate __tmperr = ios_base::goodbit;
01131 
01132       __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
01133                              __io, __tmperr);
01134       if (!__tmperr)
01135         __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
01136       else
01137         __err |= ios_base::failbit;
01138 
01139       if (__beg == __end)
01140         __err |= ios_base::eofbit;
01141       return __beg;
01142     }
01143 
01144 #if __cplusplus >= 201103L
01145   template<typename _CharT, typename _InIter>
01146     inline
01147     _InIter
01148     time_get<_CharT, _InIter>::
01149     get(iter_type __s, iter_type __end, ios_base& __io,
01150         ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
01151         const char_type* __fmtend) const
01152     {
01153       const locale& __loc = __io._M_getloc();
01154       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
01155       __err = ios_base::goodbit;
01156       while (__fmt != __fmtend &&
01157              __err == ios_base::goodbit)
01158         {
01159           if (__s == __end)
01160             {
01161               __err = ios_base::eofbit | ios_base::failbit;
01162               break;
01163             }
01164           else if (__ctype.narrow(*__fmt, 0) == '%')
01165             {
01166               char __format;
01167               char __mod = 0;
01168               if (++__fmt == __fmtend)
01169                 {
01170                   __err = ios_base::failbit;
01171                   break;
01172                 }
01173               const char __c = __ctype.narrow(*__fmt, 0);
01174               if (__c != 'E' && __c != 'O')
01175                 __format = __c;
01176               else if (++__fmt != __fmtend)
01177                 {
01178                   __mod = __c;
01179                   __format = __ctype.narrow(*__fmt, 0);
01180                 }
01181               else
01182                 {
01183                   __err = ios_base::failbit;
01184                   break;
01185                 }
01186               __s = this->do_get(__s, __end, __io, __err, __tm, __format,
01187                                  __mod);
01188               ++__fmt;
01189             }
01190           else if (__ctype.is(ctype_base::space, *__fmt))
01191             {
01192               ++__fmt;
01193               while (__fmt != __fmtend &&
01194                      __ctype.is(ctype_base::space, *__fmt))
01195                 ++__fmt;
01196 
01197               while (__s != __end &&
01198                      __ctype.is(ctype_base::space, *__s))
01199                 ++__s;
01200             }
01201           // TODO real case-insensitive comparison
01202           else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
01203                    __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
01204             {
01205               ++__s;
01206               ++__fmt;
01207             }
01208           else
01209             {
01210               __err = ios_base::failbit;
01211               break;
01212             }
01213         }
01214       return __s;
01215     }
01216 
01217   template<typename _CharT, typename _InIter>
01218     inline
01219     _InIter
01220     time_get<_CharT, _InIter>::
01221     do_get(iter_type __beg, iter_type __end, ios_base& __io,
01222            ios_base::iostate& __err, tm* __tm,
01223            char __format, char __mod) const
01224     {
01225       const locale& __loc = __io._M_getloc();
01226       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
01227       __err = ios_base::goodbit;
01228 
01229       char_type __fmt[4];
01230       __fmt[0] = __ctype.widen('%');
01231       if (!__mod)
01232         {
01233           __fmt[1] = __format;
01234           __fmt[2] = char_type();
01235         }
01236       else
01237         {
01238           __fmt[1] = __mod;
01239           __fmt[2] = __format;
01240           __fmt[3] = char_type();
01241         }
01242 
01243       __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt);
01244       if (__beg == __end)
01245         __err |= ios_base::eofbit;
01246       return __beg;
01247     }
01248 
01249 #endif // __cplusplus >= 201103L
01250 
01251   template<typename _CharT, typename _OutIter>
01252     _OutIter
01253     time_put<_CharT, _OutIter>::
01254     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
01255         const _CharT* __beg, const _CharT* __end) const
01256     {
01257       const locale& __loc = __io._M_getloc();
01258       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
01259       for (; __beg != __end; ++__beg)
01260         if (__ctype.narrow(*__beg, 0) != '%')
01261           {
01262             *__s = *__beg;
01263             ++__s;
01264           }
01265         else if (++__beg != __end)
01266           {
01267             char __format;
01268             char __mod = 0;
01269             const char __c = __ctype.narrow(*__beg, 0);
01270             if (__c != 'E' && __c != 'O')
01271               __format = __c;
01272             else if (++__beg != __end)
01273               {
01274                 __mod = __c;
01275                 __format = __ctype.narrow(*__beg, 0);
01276               }
01277             else
01278               break;
01279             __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
01280           }
01281         else
01282           break;
01283       return __s;
01284     }
01285 
01286   template<typename _CharT, typename _OutIter>
01287     _OutIter
01288     time_put<_CharT, _OutIter>::
01289     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
01290            char __format, char __mod) const
01291     {
01292       const locale& __loc = __io._M_getloc();
01293       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
01294       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
01295 
01296       // NB: This size is arbitrary. Should this be a data member,
01297       // initialized at construction?
01298       const size_t __maxlen = 128;
01299       char_type __res[__maxlen];
01300 
01301       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
01302       // is possible that the format character will be longer than one
01303       // character. Possibilities include 'E' or 'O' followed by a
01304       // format character: if __mod is not the default argument, assume
01305       // it's a valid modifier.
01306       char_type __fmt[4];
01307       __fmt[0] = __ctype.widen('%');
01308       if (!__mod)
01309         {
01310           __fmt[1] = __format;
01311           __fmt[2] = char_type();
01312         }
01313       else
01314         {
01315           __fmt[1] = __mod;
01316           __fmt[2] = __format;
01317           __fmt[3] = char_type();
01318         }
01319 
01320       __tp._M_put(__res, __maxlen, __fmt, __tm);
01321 
01322       // Write resulting, fully-formatted string to output iterator.
01323       return std::__write(__s, __res, char_traits<char_type>::length(__res));
01324     }
01325 
01326 
01327   // Inhibit implicit instantiations for required instantiations,
01328   // which are defined via explicit instantiations elsewhere.
01329 #if _GLIBCXX_EXTERN_TEMPLATE
01330   extern template class moneypunct<char, false>;
01331   extern template class moneypunct<char, true>;
01332   extern template class moneypunct_byname<char, false>;
01333   extern template class moneypunct_byname<char, true>;
01334   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
01335   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
01336   extern template class __timepunct<char>;
01337   extern template class time_put<char>;
01338   extern template class time_put_byname<char>;
01339   extern template class time_get<char>;
01340   extern template class time_get_byname<char>;
01341   extern template class messages<char>;
01342   extern template class messages_byname<char>;
01343 
01344   extern template
01345     const moneypunct<char, true>&
01346     use_facet<moneypunct<char, true> >(const locale&);
01347 
01348   extern template
01349     const moneypunct<char, false>&
01350     use_facet<moneypunct<char, false> >(const locale&);
01351 
01352   extern template
01353     const money_put<char>&
01354     use_facet<money_put<char> >(const locale&);
01355 
01356   extern template
01357     const money_get<char>&
01358     use_facet<money_get<char> >(const locale&);
01359 
01360   extern template
01361     const __timepunct<char>&
01362     use_facet<__timepunct<char> >(const locale&);
01363 
01364   extern template
01365     const time_put<char>&
01366     use_facet<time_put<char> >(const locale&);
01367 
01368   extern template
01369     const time_get<char>&
01370     use_facet<time_get<char> >(const locale&);
01371 
01372   extern template
01373     const messages<char>&
01374     use_facet<messages<char> >(const locale&);
01375 
01376   extern template
01377     bool
01378     has_facet<moneypunct<char> >(const locale&);
01379 
01380   extern template
01381     bool
01382     has_facet<money_put<char> >(const locale&);
01383 
01384   extern template
01385     bool
01386     has_facet<money_get<char> >(const locale&);
01387 
01388   extern template
01389     bool
01390     has_facet<__timepunct<char> >(const locale&);
01391 
01392   extern template
01393     bool
01394     has_facet<time_put<char> >(const locale&);
01395 
01396   extern template
01397     bool
01398     has_facet<time_get<char> >(const locale&);
01399 
01400   extern template
01401     bool
01402     has_facet<messages<char> >(const locale&);
01403 
01404 #ifdef _GLIBCXX_USE_WCHAR_T
01405   extern template class moneypunct<wchar_t, false>;
01406   extern template class moneypunct<wchar_t, true>;
01407   extern template class moneypunct_byname<wchar_t, false>;
01408   extern template class moneypunct_byname<wchar_t, true>;
01409   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
01410   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
01411   extern template class __timepunct<wchar_t>;
01412   extern template class time_put<wchar_t>;
01413   extern template class time_put_byname<wchar_t>;
01414   extern template class time_get<wchar_t>;
01415   extern template class time_get_byname<wchar_t>;
01416   extern template class messages<wchar_t>;
01417   extern template class messages_byname<wchar_t>;
01418 
01419   extern template
01420     const moneypunct<wchar_t, true>&
01421     use_facet<moneypunct<wchar_t, true> >(const locale&);
01422 
01423   extern template
01424     const moneypunct<wchar_t, false>&
01425     use_facet<moneypunct<wchar_t, false> >(const locale&);
01426 
01427   extern template
01428     const money_put<wchar_t>&
01429     use_facet<money_put<wchar_t> >(const locale&);
01430 
01431   extern template
01432     const money_get<wchar_t>&
01433     use_facet<money_get<wchar_t> >(const locale&);
01434 
01435   extern template
01436     const __timepunct<wchar_t>&
01437     use_facet<__timepunct<wchar_t> >(const locale&);
01438 
01439   extern template
01440     const time_put<wchar_t>&
01441     use_facet<time_put<wchar_t> >(const locale&);
01442 
01443   extern template
01444     const time_get<wchar_t>&
01445     use_facet<time_get<wchar_t> >(const locale&);
01446 
01447   extern template
01448     const messages<wchar_t>&
01449     use_facet<messages<wchar_t> >(const locale&);
01450 
01451   extern template
01452     bool
01453     has_facet<moneypunct<wchar_t> >(const locale&);
01454 
01455   extern template
01456     bool
01457     has_facet<money_put<wchar_t> >(const locale&);
01458 
01459   extern template
01460     bool
01461     has_facet<money_get<wchar_t> >(const locale&);
01462 
01463   extern template
01464     bool
01465     has_facet<__timepunct<wchar_t> >(const locale&);
01466 
01467   extern template
01468     bool
01469     has_facet<time_put<wchar_t> >(const locale&);
01470 
01471   extern template
01472     bool
01473     has_facet<time_get<wchar_t> >(const locale&);
01474 
01475   extern template
01476     bool
01477     has_facet<messages<wchar_t> >(const locale&);
01478 #endif
01479 #endif
01480 
01481 _GLIBCXX_END_NAMESPACE_VERSION
01482 } // namespace std
01483 
01484 #endif