s390: Check for ADDR_REGS in s390_decompose_addrstyle_without_index
[official-gcc.git] / libstdc++-v3 / include / bits / locale_facets_nonio.tcc
blob72136f42f0866a6537d529af46461e7e496d741b
1 // Locale support -*- C++ -*-
3 // Copyright (C) 2007-2024 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file bits/locale_facets_nonio.tcc
26  *  This is an internal header file, included by other library headers.
27  *  Do not attempt to use it directly. @headername{locale}
28  */
30 #ifndef _LOCALE_FACETS_NONIO_TCC
31 #define _LOCALE_FACETS_NONIO_TCC 1
33 #pragma GCC system_header
35 namespace std _GLIBCXX_VISIBILITY(default)
37 _GLIBCXX_BEGIN_NAMESPACE_VERSION
39   template<typename _CharT, bool _Intl>
40     struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
41     {
42       const __moneypunct_cache<_CharT, _Intl>*
43       operator() (const locale& __loc) const
44       {
45         const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
46         const locale::facet** __caches = __loc._M_impl->_M_caches;
47         if (!__caches[__i])
48           {
49             __moneypunct_cache<_CharT, _Intl>* __tmp = 0;
50             __try
51               {
52                 __tmp = new __moneypunct_cache<_CharT, _Intl>;
53                 __tmp->_M_cache(__loc);
54               }
55             __catch(...)
56               {
57                 delete __tmp;
58                 __throw_exception_again;
59               }
60             __loc._M_impl->_M_install_cache(__tmp, __i);
61           }
62         return static_cast<
63           const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
64       }
65     };
67   template<typename _CharT, bool _Intl>
68     void
69     __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
70     {
71       const moneypunct<_CharT, _Intl>& __mp =
72         use_facet<moneypunct<_CharT, _Intl> >(__loc);
74       struct _Scoped_str
75       {
76         size_t _M_len;
77         _CharT* _M_str;
79         explicit
80         _Scoped_str(const basic_string<_CharT>& __str)
81         : _M_len(__str.size()), _M_str(new _CharT[_M_len])
82         { __str.copy(_M_str, _M_len); }
84         ~_Scoped_str() { delete[] _M_str; }
86         void
87         _M_release(const _CharT*& __p, size_t& __n)
88         {
89           __p = _M_str;
90           __n = _M_len;
91           _M_str = 0;
92         }
93       };
95       _Scoped_str __curr_symbol(__mp.curr_symbol());
96       _Scoped_str __positive_sign(__mp.positive_sign());
97       _Scoped_str __negative_sign(__mp.negative_sign());
99       const string& __g = __mp.grouping();
100       const size_t __g_size = __g.size();
101       char* const __grouping = new char[__g_size];
102       __g.copy(__grouping, __g_size);
104       // All allocations succeeded without throwing, OK to modify *this now.
106       _M_grouping = __grouping;
107       _M_grouping_size = __g_size;
108       _M_use_grouping = (__g_size
109                          && static_cast<signed char>(__grouping[0]) > 0
110                          && (__grouping[0]
111                              != __gnu_cxx::__numeric_traits<char>::__max));
113       _M_decimal_point = __mp.decimal_point();
114       _M_thousands_sep = __mp.thousands_sep();
116       __curr_symbol._M_release(_M_curr_symbol, _M_curr_symbol_size);
117       __positive_sign._M_release(_M_positive_sign, _M_positive_sign_size);
118       __negative_sign._M_release(_M_negative_sign, _M_negative_sign_size);
120       _M_frac_digits = __mp.frac_digits();
121       _M_pos_format = __mp.pos_format();
122       _M_neg_format = __mp.neg_format();
124       const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
125       __ct.widen(money_base::_S_atoms,
126                  money_base::_S_atoms + money_base::_S_end, _M_atoms);
128       _M_allocated = true;
129     }
131 _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
133   template<typename _CharT, typename _InIter>
134     template<bool _Intl>
135       _InIter
136       money_get<_CharT, _InIter>::
137       _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
138                  ios_base::iostate& __err, string& __units) const
139       {
140         typedef char_traits<_CharT>                       __traits_type;
141         typedef typename string_type::size_type           size_type;    
142         typedef money_base::part                          part;
143         typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
144         
145         const locale& __loc = __io._M_getloc();
146         const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
148         __use_cache<__cache_type> __uc;
149         const __cache_type* __lc = __uc(__loc);
150         const char_type* __lit = __lc->_M_atoms;
152         // Deduced sign.
153         bool __negative = false;
154         // Sign size.
155         size_type __sign_size = 0;
156         // True if sign is mandatory.
157         const bool __mandatory_sign = (__lc->_M_positive_sign_size
158                                        && __lc->_M_negative_sign_size);
159         // String of grouping info from thousands_sep plucked from __units.
160         string __grouping_tmp;
161         if (__lc->_M_use_grouping)
162           __grouping_tmp.reserve(32);
163         // Last position before the decimal point.
164         int __last_pos = 0;
165         // Separator positions, then, possibly, fractional digits.
166         int __n = 0;
167         // If input iterator is in a valid state.
168         bool __testvalid = true;
169         // Flag marking when a decimal point is found.
170         bool __testdecfound = false;
172         // The tentative returned string is stored here.
173         string __res;
174         __res.reserve(32);
176         const char_type* __lit_zero = __lit + money_base::_S_zero;
177         const money_base::pattern __p = __lc->_M_neg_format;
178         for (int __i = 0; __i < 4 && __testvalid; ++__i)
179           {
180             const part __which = static_cast<part>(__p.field[__i]);
181             switch (__which)
182               {
183               case money_base::symbol:
184                 // According to 22.2.6.1.2, p2, symbol is required
185                 // if (__io.flags() & ios_base::showbase), otherwise
186                 // is optional and consumed only if other characters
187                 // are needed to complete the format.
188                 if (__io.flags() & ios_base::showbase || __sign_size > 1
189                     || __i == 0
190                     || (__i == 1 && (__mandatory_sign
191                                      || (static_cast<part>(__p.field[0])
192                                          == money_base::sign)
193                                      || (static_cast<part>(__p.field[2])
194                                          == money_base::space)))
195                     || (__i == 2 && ((static_cast<part>(__p.field[3])
196                                       == money_base::value)
197                                      || (__mandatory_sign
198                                          && (static_cast<part>(__p.field[3])
199                                              == money_base::sign)))))
200                   {
201                     const size_type __len = __lc->_M_curr_symbol_size;
202                     size_type __j = 0;
203                     for (; __beg != __end && __j < __len
204                            && *__beg == __lc->_M_curr_symbol[__j];
205                          ++__beg, (void)++__j);
206                     if (__j != __len
207                         && (__j || __io.flags() & ios_base::showbase))
208                       __testvalid = false;
209                   }
210                 break;
211               case money_base::sign:
212                 // Sign might not exist, or be more than one character long.
213                 if (__lc->_M_positive_sign_size && __beg != __end
214                     && *__beg == __lc->_M_positive_sign[0])
215                   {
216                     __sign_size = __lc->_M_positive_sign_size;
217                     ++__beg;
218                   }
219                 else if (__lc->_M_negative_sign_size && __beg != __end
220                          && *__beg == __lc->_M_negative_sign[0])
221                   {
222                     __negative = true;
223                     __sign_size = __lc->_M_negative_sign_size;
224                     ++__beg;
225                   }
226                 else if (__lc->_M_positive_sign_size
227                          && !__lc->_M_negative_sign_size)
228                   // "... if no sign is detected, the result is given the sign
229                   // that corresponds to the source of the empty string"
230                   __negative = true;
231                 else if (__mandatory_sign)
232                   __testvalid = false;
233                 break;
234               case money_base::value:
235                 // Extract digits, remove and stash away the
236                 // grouping of found thousands separators.
237                 for (; __beg != __end; ++__beg)
238                   {
239                     const char_type __c = *__beg;
240                     const char_type* __q = __traits_type::find(__lit_zero, 
241                                                                10, __c);
242                     if (__q != 0)
243                       {
244                         __res += money_base::_S_atoms[__q - __lit];
245                         ++__n;
246                       }
247                     else if (__c == __lc->_M_decimal_point 
248                              && !__testdecfound)
249                       {
250                         if (__lc->_M_frac_digits <= 0)
251                           break;
253                         __last_pos = __n;
254                         __n = 0;
255                         __testdecfound = true;
256                       }
257                     else if (__lc->_M_use_grouping
258                              && __c == __lc->_M_thousands_sep
259                              && !__testdecfound)
260                       {
261                         if (__n)
262                           {
263                             // Mark position for later analysis.
264                             __grouping_tmp += static_cast<char>(__n);
265                             __n = 0;
266                           }
267                         else
268                           {
269                             __testvalid = false;
270                             break;
271                           }
272                       }
273                     else
274                       break;
275                   }
276                 if (__res.empty())
277                   __testvalid = false;
278                 break;
279               case money_base::space:
280                 // At least one space is required.
281                 if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
282                   ++__beg;
283                 else
284                   __testvalid = false;
285                 // fallthrough
286               case money_base::none:
287                 // Only if not at the end of the pattern.
288                 if (__i != 3)
289                   for (; __beg != __end
290                          && __ctype.is(ctype_base::space, *__beg); ++__beg);
291                 break;
292               }
293           }
295         // Need to get the rest of the sign characters, if they exist.
296         if (__sign_size > 1 && __testvalid)
297           {
298             const char_type* __sign = __negative ? __lc->_M_negative_sign
299                                                  : __lc->_M_positive_sign;
300             size_type __i = 1;
301             for (; __beg != __end && __i < __sign_size
302                    && *__beg == __sign[__i]; ++__beg, (void)++__i);
303             
304             if (__i != __sign_size)
305               __testvalid = false;
306           }
308         if (__testvalid)
309           {
310             // Strip leading zeros.
311             if (__res.size() > 1)
312               {
313                 const size_type __first = __res.find_first_not_of('0');
314                 const bool __only_zeros = __first == string::npos;
315                 if (__first)
316                   __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
317               }
319             // 22.2.6.1.2, p4
320             if (__negative && __res[0] != '0')
321               __res.insert(__res.begin(), '-');
322             
323             // Test for grouping fidelity.
324             if (__grouping_tmp.size())
325               {
326                 // Add the ending grouping.
327                 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
328                                                                    : __n);
329                 if (!std::__verify_grouping(__lc->_M_grouping,
330                                             __lc->_M_grouping_size,
331                                             __grouping_tmp))
332                   __err |= ios_base::failbit;
333               }
334             
335             // Iff not enough digits were supplied after the decimal-point.
336             if (__testdecfound && __n != __lc->_M_frac_digits)
337               __testvalid = false;
338           }
340         // Iff valid sequence is not recognized.
341         if (!__testvalid)
342           __err |= ios_base::failbit;
343         else
344           __units.swap(__res);
345         
346         // Iff no more characters are available.
347         if (__beg == __end)
348           __err |= ios_base::eofbit;
349         return __beg;
350       }
352 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
353       && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
354   template<typename _CharT, typename _InIter>
355     _InIter
356     money_get<_CharT, _InIter>::
357     __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
358              ios_base::iostate& __err, double& __units) const
359     {
360       string __str;
361       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
362                      : _M_extract<false>(__beg, __end, __io, __err, __str);
363       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
364       return __beg;
365     }
366 #endif
368   template<typename _CharT, typename _InIter>
369     _InIter
370     money_get<_CharT, _InIter>::
371     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
372            ios_base::iostate& __err, long double& __units) const
373     {
374       string __str;
375       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
376                      : _M_extract<false>(__beg, __end, __io, __err, __str);
377       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
378       return __beg;
379     }
381   template<typename _CharT, typename _InIter>
382     _InIter
383     money_get<_CharT, _InIter>::
384     do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
385            ios_base::iostate& __err, string_type& __digits) const
386     {
387       typedef typename string::size_type                  size_type;
389       const locale& __loc = __io._M_getloc();
390       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
392       string __str;
393       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
394                      : _M_extract<false>(__beg, __end, __io, __err, __str);
395       const size_type __len = __str.size();
396       if (__len)
397         {
398           __digits.resize(__len);
399           __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
400         }
401       return __beg;
402     }
404 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
405       && defined __LONG_DOUBLE_IEEE128__
406   template<typename _CharT, typename _InIter>
407     _InIter
408     money_get<_CharT, _InIter>::
409     __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
410              ios_base::iostate& __err, __ibm128& __units) const
411     {
412       string __str;
413       __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
414                      : _M_extract<false>(__beg, __end, __io, __err, __str);
415       std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
416       return __beg;
417     }
418 #endif
420   template<typename _CharT, typename _OutIter>
421     template<bool _Intl>
422       _OutIter
423       money_put<_CharT, _OutIter>::
424       _M_insert(iter_type __s, ios_base& __io, char_type __fill,
425                 const string_type& __digits) const
426       {
427         typedef typename string_type::size_type           size_type;
428         typedef money_base::part                          part;
429         typedef __moneypunct_cache<_CharT, _Intl>         __cache_type;
430       
431         const locale& __loc = __io._M_getloc();
432         const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
434         __use_cache<__cache_type> __uc;
435         const __cache_type* __lc = __uc(__loc);
436         const char_type* __lit = __lc->_M_atoms;
438         // Determine if negative or positive formats are to be used, and
439         // discard leading negative_sign if it is present.
440         const char_type* __beg = __digits.data();
442         money_base::pattern __p;
443         const char_type* __sign;
444         size_type __sign_size;
445         if (!(*__beg == __lit[money_base::_S_minus]))
446           {
447             __p = __lc->_M_pos_format;
448             __sign = __lc->_M_positive_sign;
449             __sign_size = __lc->_M_positive_sign_size;
450           }
451         else
452           {
453             __p = __lc->_M_neg_format;
454             __sign = __lc->_M_negative_sign;
455             __sign_size = __lc->_M_negative_sign_size;
456             if (__digits.size())
457               ++__beg;
458           }
459        
460         // Look for valid numbers in the ctype facet within input digits.
461         size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
462                                            __beg + __digits.size()) - __beg;
463         if (__len)
464           {
465             // Assume valid input, and attempt to format.
466             // Break down input numbers into base components, as follows:
467             //   final_value = grouped units + (decimal point) + (digits)
468             string_type __value;
469             __value.reserve(2 * __len);
471             // Add thousands separators to non-decimal digits, per
472             // grouping rules.
473             long __paddec = __len - __lc->_M_frac_digits;
474             if (__paddec > 0)
475               {
476                 if (__lc->_M_frac_digits < 0)
477                   __paddec = __len;
478                 if (__lc->_M_grouping_size)
479                   {
480                     __value.assign(2 * __paddec, char_type());
481                     _CharT* __vend =
482                       std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
483                                           __lc->_M_grouping,
484                                           __lc->_M_grouping_size,
485                                           __beg, __beg + __paddec);
486                     __value.erase(__vend - &__value[0]);
487                   }
488                 else
489                   __value.assign(__beg, __paddec);
490               }
492             // Deal with decimal point, decimal digits.
493             if (__lc->_M_frac_digits > 0)
494               {
495                 __value += __lc->_M_decimal_point;
496                 if (__paddec >= 0)
497                   __value.append(__beg + __paddec, __lc->_M_frac_digits);
498                 else
499                   {
500                     // Have to pad zeros in the decimal position.
501                     __value.append(-__paddec, __lit[money_base::_S_zero]);
502                     __value.append(__beg, __len);
503                   }
504               }
505   
506             // Calculate length of resulting string.
507             const ios_base::fmtflags __f = __io.flags() 
508                                            & ios_base::adjustfield;
509             __len = __value.size() + __sign_size;
510             __len += ((__io.flags() & ios_base::showbase)
511                       ? __lc->_M_curr_symbol_size : 0);
513             string_type __res;
514             __res.reserve(2 * __len);
515             
516             const size_type __width = static_cast<size_type>(__io.width());  
517             const bool __testipad = (__f == ios_base::internal
518                                      && __len < __width);
519             // Fit formatted digits into the required pattern.
520             for (int __i = 0; __i < 4; ++__i)
521               {
522                 const part __which = static_cast<part>(__p.field[__i]);
523                 switch (__which)
524                   {
525                   case money_base::symbol:
526                     if (__io.flags() & ios_base::showbase)
527                       __res.append(__lc->_M_curr_symbol,
528                                    __lc->_M_curr_symbol_size);
529                     break;
530                   case money_base::sign:
531                     // Sign might not exist, or be more than one
532                     // character long. In that case, add in the rest
533                     // below.
534                     if (__sign_size)
535                       __res += __sign[0];
536                     break;
537                   case money_base::value:
538                     __res += __value;
539                     break;
540                   case money_base::space:
541                     // At least one space is required, but if internal
542                     // formatting is required, an arbitrary number of
543                     // fill spaces will be necessary.
544                     if (__testipad)
545                       __res.append(__width - __len, __fill);
546                     else
547                       __res += __fill;
548                     break;
549                   case money_base::none:
550                     if (__testipad)
551                       __res.append(__width - __len, __fill);
552                     break;
553                   }
554               }
555             
556             // Special case of multi-part sign parts.
557             if (__sign_size > 1)
558               __res.append(__sign + 1, __sign_size - 1);
559             
560             // Pad, if still necessary.
561             __len = __res.size();
562             if (__width > __len)
563               {
564                 if (__f == ios_base::left)
565                   // After.
566                   __res.append(__width - __len, __fill);
567                 else
568                   // Before.
569                   __res.insert(0, __width - __len, __fill);
570                 __len = __width;
571               }
572             
573             // Write resulting, fully-formatted string to output iterator.
574             __s = std::__write(__s, __res.data(), __len);
575           }
576         __io.width(0);
577         return __s;    
578       }
580 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
581       && (_GLIBCXX_USE_CXX11_ABI == 0 || defined __LONG_DOUBLE_IEEE128__)
582   template<typename _CharT, typename _OutIter>
583     _OutIter
584     money_put<_CharT, _OutIter>::
585     __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
586              double __units) const
587     { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
588 #endif
590   template<typename _CharT, typename _OutIter>
591     _OutIter
592     money_put<_CharT, _OutIter>::
593     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
594            long double __units) const
595     {
596       const locale __loc = __io.getloc();
597       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
598 #if _GLIBCXX_USE_C99_STDIO
599       // First try a buffer perhaps big enough.
600       int __cs_size = 64;
601       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
602       // _GLIBCXX_RESOLVE_LIB_DEFECTS
603       // 328. Bad sprintf format modifier in money_put<>::do_put()
604       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
605                                         "%.*Lf", 0, __units);
606       // If the buffer was not large enough, try again with the correct size.
607       if (__len >= __cs_size)
608         {
609           __cs_size = __len + 1;
610           __cs = static_cast<char*>(__builtin_alloca(__cs_size));
611           __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
612                                         "%.*Lf", 0, __units);
613         }
614 #else
615       // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
616       const int __cs_size =
617         __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
618       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
619       int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf", 
620                                         0, __units);
621 #endif
622       string_type __digits(__len, char_type());
623       __ctype.widen(__cs, __cs + __len, &__digits[0]);
624       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
625                     : _M_insert<false>(__s, __io, __fill, __digits);
626     }
628   template<typename _CharT, typename _OutIter>
629     _OutIter
630     money_put<_CharT, _OutIter>::
631     do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
632            const string_type& __digits) const
633     { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
634                     : _M_insert<false>(__s, __io, __fill, __digits); }
636 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
637       && defined __LONG_DOUBLE_IEEE128__
638 extern "C"
639 __typeof__(__builtin_snprintf) __glibcxx_snprintfibm128 __asm__("snprintf");
641   template<typename _CharT, typename _OutIter>
642     _OutIter
643     money_put<_CharT, _OutIter>::
644     __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
645              __ibm128 __units) const
646     {
647       const locale __loc = __io.getloc();
648       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
649       // First try a buffer perhaps big enough.
650       int __cs_size = 64;
651       char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
652       const __c_locale __old = __gnu_cxx::__uselocale(_S_get_c_locale());
654       // _GLIBCXX_RESOLVE_LIB_DEFECTS
655       // 328. Bad sprintf format modifier in money_put<>::do_put()
656       int __len = __glibcxx_snprintfibm128(__cs, __cs_size, "%.*Lf", 0,
657                                              __units);
658       // If the buffer was not large enough, try again with the correct size.
659       if (__len >= __cs_size)
660         {
661           __cs_size = __len + 1;
662           __cs = static_cast<char*>(__builtin_alloca(__cs_size));
663           __len = __glibcxx_snprintfibm128(__cs, __cs_size, "%.*Lf", 0,
664                                              __units);
665         }
666       __gnu_cxx::__uselocale(__old);
667       string_type __digits(__len, char_type());
668       __ctype.widen(__cs, __cs + __len, &__digits[0]);
669       return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
670                     : _M_insert<false>(__s, __io, __fill, __digits);
671     }
672 #endif
674 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
676   // NB: Not especially useful. Without an ios_base object or some
677   // kind of locale reference, we are left clawing at the air where
678   // the side of the mountain used to be...
679   template<typename _CharT, typename _InIter>
680     time_base::dateorder
681     time_get<_CharT, _InIter>::do_date_order() const
682     { return time_base::no_order; }
684   // Expand a strptime format string and parse it.  E.g., do_get_date() may
685   // pass %m/%d/%Y => extracted characters.
686   template<typename _CharT, typename _InIter>
687     _InIter
688     time_get<_CharT, _InIter>::
689     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
690                           ios_base::iostate& __err, tm* __tm,
691                           const _CharT* __format,
692                           __time_get_state &__state) const
693     {
694       const locale& __loc = __io._M_getloc();
695       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
696       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
697       const size_t __len = char_traits<_CharT>::length(__format);
699       ios_base::iostate __tmperr = ios_base::goodbit;
700       size_t __i = 0;
701       for (; __beg != __end && __i < __len && !__tmperr; ++__i)
702         {
703           if (__ctype.narrow(__format[__i], 0) == '%')
704             {
705               // Verify valid formatting code, attempt to extract.
706               char __c = __ctype.narrow(__format[++__i], 0);
707               int __mem = 0;
708               if (__c == 'E' || __c == 'O')
709                 __c = __ctype.narrow(__format[++__i], 0);
710               switch (__c)
711                 {
712                   const char* __cs;
713                   _CharT __wcs[10];
714                 case 'a':
715                 case 'A':
716                   // Weekday name (possibly abbreviated) [tm_wday]
717                   const char_type*  __days[14];
718                   __tp._M_days(&__days[0]);
719                   __tp._M_days_abbreviated(&__days[7]);
720                   __beg = _M_extract_name(__beg, __end, __mem, __days,
721                                           14, __io, __tmperr);
722                   if (!__tmperr)
723                     {
724                       __tm->tm_wday = __mem % 7;
725                       __state._M_have_wday = 1;
726                     }
727                   break;
728                 case 'h':
729                 case 'b':
730                 case 'B':
731                   // Month name (possibly abbreviated) [tm_mon]
732                   const char_type*  __months[24];
733                   __tp._M_months(&__months[0]);
734                   __tp._M_months_abbreviated(&__months[12]);
735                   __beg = _M_extract_name(__beg, __end, __mem,
736                                           __months, 24, __io, __tmperr);
737                   if (!__tmperr)
738                     {
739                       __tm->tm_mon = __mem % 12;
740                       __state._M_have_mon = 1;
741                       __state._M_want_xday = 1;
742                     }
743                   break;
744                 case 'c':
745                   // Default time and date representation.
746                   const char_type*  __dt[2];
747                   __tp._M_date_time_formats(__dt);
748                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
749                                                 __tm, __dt[0], __state);
750                   if (!__tmperr)
751                     __state._M_want_xday = 1;
752                   break;
753                 case 'C':
754                   // Century.
755                   __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2,
756                                          __io, __tmperr);
757                   if (!__tmperr)
758                     {
759                       __state._M_century = __mem;
760                       __state._M_have_century = 1;
761                       __state._M_want_xday = 1;
762                     }
763                   break;
764                 case 'd':
765                 case 'e':
766                   // Day [1, 31]. [tm_mday]
767                   if (__ctype.is(ctype_base::space, *__beg))
768                     ++__beg;
769                   __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2,
770                                          __io, __tmperr);
771                   if (!__tmperr)
772                     {
773                       __tm->tm_mday = __mem;
774                       __state._M_have_mday = 1;
775                       __state._M_want_xday = 1;
776                     }
777                   break;
778                 case 'D':
779                   // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
780                   __cs = "%m/%d/%y";
781                   __ctype.widen(__cs, __cs + 9, __wcs);
782                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
783                                                 __tm, __wcs, __state);
784                   if (!__tmperr)
785                     __state._M_want_xday = 1;
786                   break;
787                 case 'H':
788                   // Hour [00, 23]. [tm_hour]
789                   __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2,
790                                          __io, __tmperr);
791                   if (!__tmperr)
792                     {
793                       __tm->tm_hour = __mem;
794                       __state._M_have_I = 0;
795                     }
796                   break;
797                 case 'I':
798                   // Hour [01, 12]. [tm_hour]
799                   __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
800                                          __io, __tmperr);
801                   if (!__tmperr)
802                     {
803                       __tm->tm_hour = __mem % 12;
804                       __state._M_have_I = 1;
805                     }
806                   break;
807                 case 'j':
808                   // Day number of year.
809                   __beg = _M_extract_num(__beg, __end, __mem, 1, 366, 3,
810                                          __io, __tmperr);
811                   if (!__tmperr)
812                     {
813                       __tm->tm_yday = __mem - 1;
814                       __state._M_have_yday = 1;
815                     }
816                   break;
817                 case 'm':
818                   // Month [01, 12]. [tm_mon]
819                   __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, 
820                                          __io, __tmperr);
821                   if (!__tmperr)
822                     {
823                       __tm->tm_mon = __mem - 1;
824                       __state._M_have_mon = 1;
825                     }
826                   break;
827                 case 'M':
828                   // Minute [00, 59]. [tm_min]
829                   __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2,
830                                          __io, __tmperr);
831                   if (!__tmperr)
832                     __tm->tm_min = __mem;
833                   break;
834                 case 'n':
835                 case 't':
836                   while (__beg != __end
837                          && __ctype.is(ctype_base::space, *__beg))
838                     ++__beg;
839                   break;
840                 case 'p':
841                   // Locale's a.m. or p.m.
842                   const char_type*  __ampm[2];
843                   __tp._M_am_pm(&__ampm[0]);
844                   if (!__ampm[0][0] || !__ampm[1][0])
845                     break;
846                   __beg = _M_extract_name(__beg, __end, __mem, __ampm,
847                                           2, __io, __tmperr);
848                   if (!__tmperr && __mem)
849                     __state._M_is_pm = 1;
850                   break;
851                 case 'r':
852                   // Locale's 12-hour clock time format (in C %I:%M:%S %p).
853                   const char_type*  __ampm_format;
854                   __tp._M_am_pm_format(&__ampm_format);
855                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
856                                                 __tm, __ampm_format, __state);
857                   break;
858                 case 'R':
859                   // Equivalent to (%H:%M).
860                   __cs = "%H:%M";
861                   __ctype.widen(__cs, __cs + 6, __wcs);
862                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
863                                                 __tm, __wcs, __state);
864                   break;
865                 case 'S':
866                   // Seconds. [tm_sec]
867                   // [00, 60] in C99 (one leap-second), [00, 61] in C89.
868 #if _GLIBCXX_USE_C99
869                   __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2,
870 #else
871                   __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2,
872 #endif
873                                          __io, __tmperr);
874                   if (!__tmperr)
875                     __tm->tm_sec = __mem;
876                   break;
877                 case 'T':
878                   // Equivalent to (%H:%M:%S).
879                   __cs = "%H:%M:%S";
880                   __ctype.widen(__cs, __cs + 9, __wcs);
881                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
882                                                 __tm, __wcs, __state);
883                   break;
884                 case 'U':
885                   // Week number of the year (Sunday as first day of week).
886                   __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2,
887                                          __io, __tmperr);
888                   if (!__tmperr)
889                     {
890                       __state._M_week_no = __mem;
891                       __state._M_have_uweek = 1;
892                     }
893                   break;
894                 case 'w':
895                   // Weekday [tm_wday]
896                   __beg = _M_extract_num(__beg, __end, __mem, 0, 6, 1,
897                                          __io, __tmperr);
898                   if (!__tmperr)
899                     {
900                       __tm->tm_wday = __mem;
901                       __state._M_have_wday = 1;
902                     }
903                   break;
904                 case 'W':
905                   // Week number of the year (Monday as first day of week).
906                   __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2,
907                                          __io, __tmperr);
908                   if (!__tmperr)
909                     {
910                       __state._M_week_no = __mem;
911                       __state._M_have_wweek = 1;
912                     }
913                   break;
914                 case 'x':
915                   // Locale's date.
916                   const char_type*  __dates[2];
917                   __tp._M_date_formats(__dates);
918                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
919                                                 __tm, __dates[0], __state);
920                   break;
921                 case 'X':
922                   // Locale's time.
923                   const char_type*  __times[2];
924                   __tp._M_time_formats(__times);
925                   __beg = _M_extract_via_format(__beg, __end, __io, __tmperr, 
926                                                 __tm, __times[0], __state);
927                   break;
928                 case 'y':
929                   // The last 2 digits of year.
930                   __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2,
931                                          __io, __tmperr);
932                   if (!__tmperr)
933                     {
934                       __state._M_want_century = 1;
935                       __state._M_want_xday = 1;
936                       // As an extension, if the 2 digits are followed by
937                       // 1-2 further digits, treat it like %Y.
938                       __c = 0;
939                       if (__beg != __end)
940                         __c = __ctype.narrow(*__beg, '*');
941                       if (__c >= '0' && __c <= '9')
942                         {
943                           ++__beg;
944                           __mem = __mem * 10 + (__c - '0');
945                           if (__beg != __end)
946                             {
947                               __c = __ctype.narrow(*__beg, '*');
948                               if (__c >= '0' && __c <= '9')
949                                 {
950                                   ++__beg;
951                                   __mem = __mem * 10 + (__c - '0');
952                                 }
953                             }
954                           __mem -= 1900;
955                           __state._M_want_century = 0;
956                         }
957                       // Otherwise, as per POSIX 2008, 00-68 is 2000-2068,
958                       // while 69-99 is 1969-1999.
959                       else if (__mem < 69)
960                         __mem += 100;
961                       __tm->tm_year = __mem;
962                     }
963                   break;
964                 case 'Y':
965                   // Year.
966                   __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
967                                          __io, __tmperr);
968                   if (!__tmperr)
969                     {
970                       __tm->tm_year = __mem - 1900;
971                       __state._M_want_century = 0;
972                       __state._M_want_xday = 1;
973                     }
974                   break;
975                 case 'Z':
976                   // Timezone info.
977                   if (__ctype.is(ctype_base::upper, *__beg))
978                     {
979                       int __tmp;
980                       __beg = _M_extract_name(__beg, __end, __tmp,
981                                        __timepunct_cache<_CharT>::_S_timezones,
982                                               14, __io, __tmperr);
984                       // GMT requires special effort.
985                       if (__beg != __end && !__tmperr && __tmp == 0
986                           && (*__beg == __ctype.widen('-')
987                               || *__beg == __ctype.widen('+')))
988                         {
989                           __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
990                                                  __io, __tmperr);
991                           __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
992                                                  __io, __tmperr);
993                         }
994                     }
995                   else
996                     __tmperr |= ios_base::failbit;
997                   break;
998                 case '%':
999                   if (*__beg == __ctype.widen('%'))
1000                     ++__beg;
1001                   else
1002                     __tmperr |= ios_base::failbit;
1003                   break;
1004                 default:
1005                   // Not recognized.
1006                   __tmperr |= ios_base::failbit;
1007                 }
1008             }
1009           else if (__ctype.is(ctype_base::space, __format[__i]))
1010             {
1011               // Skip any whitespace.
1012               while (__beg != __end
1013                      && __ctype.is(ctype_base::space, *__beg))
1014                 ++__beg;
1015             }
1016           else
1017             {
1018               // Verify format and input match, extract and discard.
1019               // TODO real case-insensitive comparison
1020               if (__ctype.tolower(__format[__i]) == __ctype.tolower(*__beg)
1021                   || __ctype.toupper(__format[__i]) == __ctype.toupper(*__beg))
1022                 ++__beg;
1023               else
1024                 __tmperr |= ios_base::failbit;
1025             }
1026         }
1028       if (__tmperr || __i != __len)
1029         __err |= ios_base::failbit;
1030   
1031       return __beg;
1032     }
1034   template<typename _CharT, typename _InIter>
1035     _InIter
1036     time_get<_CharT, _InIter>::
1037     _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
1038                           ios_base::iostate& __err, tm* __tm,
1039                           const _CharT* __format) const
1040     {
1041       __time_get_state __state = __time_get_state();
1042       return _M_extract_via_format(__beg, __end, __io, __err, __tm,
1043                                    __format, __state);
1044     }
1046   template<typename _CharT, typename _InIter>
1047     _InIter
1048     time_get<_CharT, _InIter>::
1049     _M_extract_num(iter_type __beg, iter_type __end, int& __member,
1050                    int __min, int __max, size_t __len,
1051                    ios_base& __io, ios_base::iostate& __err) const
1052     {
1053       const locale& __loc = __io._M_getloc();
1054       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1056       size_t __i = 0;
1057       int __value = 0;
1058       for (; __beg != __end && __i < __len; ++__beg, (void)++__i)
1059         {
1060           const char __c = __ctype.narrow(*__beg, '*');
1061           if (__c >= '0' && __c <= '9')
1062             {
1063               __value = __value * 10 + (__c - '0');
1064               if (__value > __max)
1065                 break;
1066             }
1067           else
1068             break;
1069         }
1070       if (__i && __value >= __min && __value <= __max)
1071         __member = __value;
1072       else
1073         __err |= ios_base::failbit;
1075       return __beg;
1076     }
1078   // Assumptions:
1079   // All elements in __names are unique, except if __indexlen is
1080   // even __names in the first half could be the same as corresponding
1081   // __names in the second half (May is abbreviated as May).  Some __names
1082   // elements could be prefixes of other __names elements.
1083   template<typename _CharT, typename _InIter>
1084     _InIter
1085     time_get<_CharT, _InIter>::
1086     _M_extract_name(iter_type __beg, iter_type __end, int& __member,
1087                     const _CharT** __names, size_t __indexlen,
1088                     ios_base& __io, ios_base::iostate& __err) const
1089     {
1090       typedef char_traits<_CharT>               __traits_type;
1091       const locale& __loc = __io._M_getloc();
1092       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1094       size_t* __matches
1095         = static_cast<size_t*>(__builtin_alloca(2 * sizeof(size_t)
1096                                                 * __indexlen));
1097       size_t* __lengths = __matches + __indexlen;
1098       size_t __nmatches = 0;
1099       size_t __pos = 0;
1100       bool __testvalid = true;
1101       const char_type* __name;
1102       bool __begupdated = false;
1104       // Look for initial matches.
1105       if (__beg != __end)
1106         {
1107           const char_type __c = *__beg;
1108           // TODO real case-insensitive comparison
1109           const char_type __cl = __ctype.tolower(__c);
1110           const char_type __cu = __ctype.toupper(__c);
1111           for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1112             if (__cl == __ctype.tolower(__names[__i1][0])
1113                 || __cu == __ctype.toupper(__names[__i1][0]))
1114               {
1115                 __lengths[__nmatches]
1116                   = __traits_type::length(__names[__i1]);
1117                 __matches[__nmatches++] = __i1;
1118               }
1119         }
1121       while (__nmatches > 1)
1122         {
1123           // Find smallest matching string.
1124           size_t __minlen = __lengths[0];
1125           for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
1126             __minlen = std::min(__minlen, __lengths[__i2]);
1127           ++__pos;
1128           ++__beg;
1129           if (__pos == __minlen)
1130             {
1131               // If some match has remaining length of 0,
1132               // need to decide if any match with remaining
1133               // length non-zero matches the next character.
1134               // If so, remove all matches with remaining length
1135               // 0 from consideration, otherwise keep only matches
1136               // with remaining length 0.
1137               bool __match_longer = false;
1139               if (__beg != __end)
1140                 {
1141                   // TODO real case-insensitive comparison
1142                   const char_type __cl = __ctype.tolower(*__beg);
1143                   const char_type __cu = __ctype.toupper(*__beg);
1144                   for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1145                     {
1146                       __name = __names[__matches[__i3]];
1147                       if (__lengths[__i3] > __pos
1148                           && (__ctype.tolower(__name[__pos]) == __cl
1149                               || __ctype.toupper(__name[__pos]) == __cu))
1150                         {
1151                           __match_longer = true;
1152                           break;
1153                         }
1154                     }
1155                 }
1156               for (size_t __i4 = 0; __i4 < __nmatches;)
1157                 if (__match_longer == (__lengths[__i4] == __pos))
1158                   {
1159                     __matches[__i4] = __matches[--__nmatches];
1160                     __lengths[__i4] = __lengths[__nmatches];
1161                   }
1162                 else
1163                   ++__i4;
1164               if (__match_longer)
1165                 {
1166                   __minlen = __lengths[0];
1167                   for (size_t __i5 = 1; __i5 < __nmatches; ++__i5)
1168                     __minlen = std::min(__minlen, __lengths[__i5]);
1169                 }
1170               else
1171                 {
1172                   // Deal with May being full as well as abbreviated month
1173                   // name.  Pick the smaller index.
1174                   if (__nmatches == 2 && (__indexlen & 1) == 0)
1175                     {
1176                       if (__matches[0] < __indexlen / 2)
1177                         {
1178                           if (__matches[1] == __matches[0] + __indexlen / 2)
1179                             __nmatches = 1;
1180                         }
1181                       else if (__matches[1] == __matches[0] - __indexlen / 2)
1182                         {
1183                           __matches[0] = __matches[1];
1184                           __lengths[0] = __lengths[1];
1185                           __nmatches = 1;
1186                         }
1187                     }
1188                   __begupdated = true;
1189                   break;
1190                 }
1191             }
1192           if (__pos < __minlen && __beg != __end)
1193             {
1194               // TODO real case-insensitive comparison
1195               const char_type __cl = __ctype.tolower(*__beg);
1196               const char_type __cu = __ctype.toupper(*__beg);
1197               for (size_t __i6 = 0; __i6 < __nmatches;)
1198                 {
1199                   __name = __names[__matches[__i6]];
1200                   if (__ctype.tolower(__name[__pos]) != __cl
1201                       && __ctype.toupper(__name[__pos]) != __cu)
1202                     {
1203                       __matches[__i6] = __matches[--__nmatches];
1204                       __lengths[__i6] = __lengths[__nmatches];
1205                     }
1206                   else
1207                     ++__i6;
1208                 }
1209             }
1210           else
1211             break;
1212         }
1214       if (__nmatches == 1)
1215         {
1216           // Make sure found name is completely extracted.
1217           if (!__begupdated)
1218             {
1219               ++__beg;
1220               ++__pos;
1221             }
1222           __name = __names[__matches[0]];
1223           const size_t __len = __lengths[0];
1224           while (__pos < __len
1225                  && __beg != __end
1226                  // TODO real case-insensitive comparison
1227                  && (__ctype.tolower(__name[__pos]) == __ctype.tolower(*__beg)
1228                      || (__ctype.toupper(__name[__pos])
1229                          == __ctype.toupper(*__beg))))
1230             ++__beg, (void)++__pos;
1232           if (__len == __pos)
1233             __member = __matches[0];
1234           else
1235             __testvalid = false;
1236         }
1237       else
1238         __testvalid = false;
1239       if (!__testvalid)
1240         __err |= ios_base::failbit;
1242       return __beg;
1243     }
1245   template<typename _CharT, typename _InIter>
1246     _InIter
1247     time_get<_CharT, _InIter>::
1248     _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
1249                              const _CharT** __names, size_t __indexlen,
1250                              ios_base& __io, ios_base::iostate& __err) const
1251     {
1252       typedef char_traits<_CharT>               __traits_type;
1253       const locale& __loc = __io._M_getloc();
1254       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1256       int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
1257                                                           * __indexlen));
1258       size_t __nmatches = 0;
1259       size_t* __matches_lengths = 0;
1260       size_t __pos = 0;
1262       if (__beg != __end)
1263         {
1264           const char_type __c = *__beg;
1265           for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
1266             if (__c == __names[__i][0]
1267                 || __c == __ctype.toupper(__names[__i][0]))
1268               __matches[__nmatches++] = __i;
1269         }
1271       if (__nmatches)
1272         {
1273           ++__beg;
1274           ++__pos;
1276           __matches_lengths
1277             = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
1278                                                     * __nmatches));
1279           for (size_t __i = 0; __i < __nmatches; ++__i)
1280             __matches_lengths[__i]
1281               = __traits_type::length(__names[__matches[__i]]);
1282         }
1284       for (; __beg != __end; ++__beg, (void)++__pos)
1285         {
1286           size_t __nskipped = 0;
1287           const char_type __c = *__beg;
1288           for (size_t __i = 0; __i < __nmatches;)
1289             {
1290               const char_type* __name = __names[__matches[__i]];
1291               if (__pos >= __matches_lengths[__i])
1292                 ++__nskipped, ++__i;
1293               else if (!(__name[__pos] == __c))
1294                 {
1295                   --__nmatches;
1296                   __matches[__i] = __matches[__nmatches];
1297                   __matches_lengths[__i] = __matches_lengths[__nmatches];
1298                 }
1299               else
1300                 ++__i;
1301             }
1302           if (__nskipped == __nmatches)
1303             break;
1304         }
1306       if ((__nmatches == 1 && __matches_lengths[0] == __pos)
1307           || (__nmatches == 2 && (__matches_lengths[0] == __pos
1308                                   || __matches_lengths[1] == __pos)))
1309         __member = (__matches[0] >= (int)__indexlen
1310                     ? __matches[0] - (int)__indexlen : __matches[0]);
1311       else
1312         __err |= ios_base::failbit;
1314       return __beg;
1315     }
1317   template<typename _CharT, typename _InIter>
1318     _InIter
1319     time_get<_CharT, _InIter>::
1320     do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1321                 ios_base::iostate& __err, tm* __tm) const
1322     {
1323       const locale& __loc = __io._M_getloc();
1324       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1325       const char_type*  __times[2];
1326       __tp._M_time_formats(__times);
1327       __time_get_state __state = __time_get_state();
1328       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1329                                     __tm, __times[0], __state);
1330       __state._M_finalize_state(__tm);
1331       if (__beg == __end)
1332         __err |= ios_base::eofbit;
1333       return __beg;
1334     }
1336   template<typename _CharT, typename _InIter>
1337     _InIter
1338     time_get<_CharT, _InIter>::
1339     do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1340                 ios_base::iostate& __err, tm* __tm) const
1341     {
1342       const locale& __loc = __io._M_getloc();
1343       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1344       const char_type*  __dates[2];
1345       __tp._M_date_formats(__dates);
1346       __time_get_state __state = __time_get_state();
1347       __beg = _M_extract_via_format(__beg, __end, __io, __err, 
1348                                     __tm, __dates[0], __state);
1349       __state._M_finalize_state(__tm);
1350       if (__beg == __end)
1351         __err |= ios_base::eofbit;
1352       return __beg;
1353     }
1355   template<typename _CharT, typename _InIter>
1356     _InIter
1357     time_get<_CharT, _InIter>::
1358     do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1359                    ios_base::iostate& __err, tm* __tm) const
1360     {
1361       const locale& __loc = __io._M_getloc();
1362       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1363       const char_type* __days[14];
1364       __tp._M_days_abbreviated(__days);
1365       __tp._M_days(__days + 7);
1366       int __tmpwday;
1367       ios_base::iostate __tmperr = ios_base::goodbit;
1369       __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
1370                                        __io, __tmperr);
1371       if (!__tmperr)
1372         __tm->tm_wday = __tmpwday;
1373       else
1374         __err |= ios_base::failbit;
1376       if (__beg == __end)
1377         __err |= ios_base::eofbit;
1378       return __beg;
1379      }
1381   template<typename _CharT, typename _InIter>
1382     _InIter
1383     time_get<_CharT, _InIter>::
1384     do_get_monthname(iter_type __beg, iter_type __end,
1385                      ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1386     {
1387       const locale& __loc = __io._M_getloc();
1388       const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1389       const char_type*  __months[24];
1390       __tp._M_months_abbreviated(__months);
1391       __tp._M_months(__months + 12);
1392       int __tmpmon;
1393       ios_base::iostate __tmperr = ios_base::goodbit;
1395       __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
1396                                        __io, __tmperr);
1397       if (!__tmperr)
1398         __tm->tm_mon = __tmpmon;
1399       else
1400         __err |= ios_base::failbit;
1402       if (__beg == __end)
1403         __err |= ios_base::eofbit;
1404       return __beg;
1405     }
1407   template<typename _CharT, typename _InIter>
1408     _InIter
1409     time_get<_CharT, _InIter>::
1410     do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1411                 ios_base::iostate& __err, tm* __tm) const
1412     {
1413       int __tmpyear;
1414       ios_base::iostate __tmperr = ios_base::goodbit;
1415       const locale& __loc = __io._M_getloc();
1416       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1418       __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 99, 2,
1419                              __io, __tmperr);
1420       if (!__tmperr)
1421         {
1422           char __c = 0;
1423           if (__beg != __end)
1424             __c = __ctype.narrow(*__beg, '*');
1425           // For 1-2 digit year, assume 69-99 is 1969-1999, 0-68 is 2000-2068.
1426           // For 3-4 digit year, use it as year.
1427           // __tm->tm_year needs year - 1900 though.
1428           if (__c >= '0' && __c <= '9')
1429             {
1430               ++__beg;
1431               __tmpyear = __tmpyear * 10 + (__c - '0');
1432               if (__beg != __end)
1433                 {
1434                   __c = __ctype.narrow(*__beg, '*');
1435                   if (__c >= '0' && __c <= '9')
1436                     {
1437                       ++__beg;
1438                       __tmpyear = __tmpyear * 10 + (__c - '0');
1439                     }
1440                 }
1441               __tmpyear -= 1900;
1442             }
1443           else if (__tmpyear < 69)
1444             __tmpyear += 100;
1445           __tm->tm_year = __tmpyear;
1446         }
1447       else
1448         __err |= ios_base::failbit;
1450       if (__beg == __end)
1451         __err |= ios_base::eofbit;
1452       return __beg;
1453     }
1455 #if __cplusplus >= 201103L
1456   template<typename _CharT, typename _InIter>
1457     inline
1458     _InIter
1459     time_get<_CharT, _InIter>::
1460     get(iter_type __s, iter_type __end, ios_base& __io,
1461         ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
1462         const char_type* __fmtend) const
1463     {
1464       const locale& __loc = __io._M_getloc();
1465       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1466       __err = ios_base::goodbit;
1467       bool __use_state = false;
1468 #if __GNUC__ >= 5 && !defined(_GLIBCXX_CLANG)
1469 #pragma GCC diagnostic push
1470 #pragma GCC diagnostic ignored "-Wpmf-conversions"
1471       // Nasty hack.  The C++ standard mandates that get invokes the do_get
1472       // virtual method, but unfortunately at least without an ABI change
1473       // for the facets we can't keep state across the different do_get
1474       // calls.  So e.g. if __fmt is "%p %I:%M:%S", we can't handle it
1475       // properly, because we first handle the %p am/pm specifier and only
1476       // later the 12-hour format specifier.
1477       if ((void*)(this->*(&time_get::do_get)) == (void*)(&time_get::do_get))
1478         __use_state = true;
1479 #pragma GCC diagnostic pop
1480 #endif
1481       __time_get_state __state = __time_get_state();
1482       while (__fmt != __fmtend &&
1483              __err == ios_base::goodbit)
1484         {
1485           if (__s == __end)
1486             {
1487               __err = ios_base::eofbit | ios_base::failbit;
1488               break;
1489             }
1490           else if (__ctype.narrow(*__fmt, 0) == '%')
1491             {
1492               const char_type* __fmt_start = __fmt;
1493               char __format;
1494               char __mod = 0;
1495               if (++__fmt == __fmtend)
1496                 {
1497                   __err = ios_base::failbit;
1498                   break;
1499                 }
1500               const char __c = __ctype.narrow(*__fmt, 0);
1501               if (__c != 'E' && __c != 'O')
1502                 __format = __c;
1503               else if (++__fmt != __fmtend)
1504                 {
1505                   __mod = __c;
1506                   __format = __ctype.narrow(*__fmt, 0);
1507                 }
1508               else
1509                 {
1510                   __err = ios_base::failbit;
1511                   break;
1512                 }
1513               if (__use_state)
1514                 {
1515                   char_type __new_fmt[4];
1516                   __new_fmt[0] = __fmt_start[0];
1517                   __new_fmt[1] = __fmt_start[1];
1518                   if (__mod)
1519                     {
1520                       __new_fmt[2] = __fmt_start[2];
1521                       __new_fmt[3] = char_type();
1522                     }
1523                   else
1524                     __new_fmt[2] = char_type();
1525                   __s = _M_extract_via_format(__s, __end, __io, __err, __tm,
1526                                               __new_fmt, __state);
1527                   if (__s == __end)
1528                     __err |= ios_base::eofbit;
1529                 }
1530               else
1531                 __s = this->do_get(__s, __end, __io, __err, __tm, __format,
1532                                    __mod);
1533               ++__fmt;
1534             }
1535           else if (__ctype.is(ctype_base::space, *__fmt))
1536             {
1537               ++__fmt;
1538               while (__fmt != __fmtend &&
1539                      __ctype.is(ctype_base::space, *__fmt))
1540                 ++__fmt;
1542               while (__s != __end &&
1543                      __ctype.is(ctype_base::space, *__s))
1544                 ++__s;
1545             }
1546           // TODO real case-insensitive comparison
1547           else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
1548                    __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
1549             {
1550               ++__s;
1551               ++__fmt;
1552             }
1553           else
1554             {
1555               __err = ios_base::failbit;
1556               break;
1557             }
1558         }
1559       if (__use_state)
1560         __state._M_finalize_state(__tm);
1561       return __s;
1562     }
1564   template<typename _CharT, typename _InIter>
1565     inline
1566     _InIter
1567     time_get<_CharT, _InIter>::
1568     do_get(iter_type __beg, iter_type __end, ios_base& __io,
1569            ios_base::iostate& __err, tm* __tm,
1570            char __format, char __mod) const
1571     {
1572       const locale& __loc = __io._M_getloc();
1573       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1574       __err = ios_base::goodbit;
1576       char_type __fmt[4];
1577       __fmt[0] = __ctype.widen('%');
1578       if (!__mod)
1579         {
1580           __fmt[1] = __format;
1581           __fmt[2] = char_type();
1582         }
1583       else
1584         {
1585           __fmt[1] = __mod;
1586           __fmt[2] = __format;
1587           __fmt[3] = char_type();
1588         }
1590       __time_get_state __state = __time_get_state();
1591       __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt,
1592                                     __state);
1593       __state._M_finalize_state(__tm);
1594       if (__beg == __end)
1595         __err |= ios_base::eofbit;
1596       return __beg;
1597     }
1599 #endif // __cplusplus >= 201103L
1601   template<typename _CharT, typename _OutIter>
1602     _OutIter
1603     time_put<_CharT, _OutIter>::
1604     put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1605         const _CharT* __beg, const _CharT* __end) const
1606     {
1607       const locale& __loc = __io._M_getloc();
1608       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1609       for (; __beg != __end; ++__beg)
1610         if (__ctype.narrow(*__beg, 0) != '%')
1611           {
1612             *__s = *__beg;
1613             ++__s;
1614           }
1615         else if (++__beg != __end)
1616           {
1617             char __format;
1618             char __mod = 0;
1619             const char __c = __ctype.narrow(*__beg, 0);
1620             if (__c != 'E' && __c != 'O')
1621               __format = __c;
1622             else if (++__beg != __end)
1623               {
1624                 __mod = __c;
1625                 __format = __ctype.narrow(*__beg, 0);
1626               }
1627             else
1628               break;
1629             __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1630           }
1631         else
1632           break;
1633       return __s;
1634     }
1636   template<typename _CharT, typename _OutIter>
1637     _OutIter
1638     time_put<_CharT, _OutIter>::
1639     do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1640            char __format, char __mod) const
1641     {
1642       const locale& __loc = __io._M_getloc();
1643       ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1644       __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1646       // NB: This size is arbitrary. Should this be a data member,
1647       // initialized at construction?
1648       const size_t __maxlen = 128;
1649       char_type __res[__maxlen];
1651       // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1652       // is possible that the format character will be longer than one
1653       // character. Possibilities include 'E' or 'O' followed by a
1654       // format character: if __mod is not the default argument, assume
1655       // it's a valid modifier.
1656       char_type __fmt[4];
1657       __fmt[0] = __ctype.widen('%');
1658       if (!__mod)
1659         {
1660           __fmt[1] = __format;
1661           __fmt[2] = char_type();
1662         }
1663       else
1664         {
1665           __fmt[1] = __mod;
1666           __fmt[2] = __format;
1667           __fmt[3] = char_type();
1668         }
1670       __tp._M_put(__res, __maxlen, __fmt, __tm);
1672       // Write resulting, fully-formatted string to output iterator.
1673       return std::__write(__s, __res, char_traits<char_type>::length(__res));
1674     }
1677   // Inhibit implicit instantiations for required instantiations,
1678   // which are defined via explicit instantiations elsewhere.
1679 #if _GLIBCXX_EXTERN_TEMPLATE
1680   extern template class moneypunct<char, false>;
1681   extern template class moneypunct<char, true>;
1682   extern template class moneypunct_byname<char, false>;
1683   extern template class moneypunct_byname<char, true>;
1684   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
1685   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
1686   extern template class __timepunct<char>;
1687   extern template class time_put<char>;
1688   extern template class time_put_byname<char>;
1689   extern template class time_get<char>;
1690   extern template class time_get_byname<char>;
1691   extern template class messages<char>;
1692   extern template class messages_byname<char>;
1694   extern template
1695     const moneypunct<char, true>*
1696     __try_use_facet<moneypunct<char, true> >(const locale&) _GLIBCXX_NOTHROW;
1698   extern template
1699     const moneypunct<char, false>*
1700     __try_use_facet<moneypunct<char, false> >(const locale&) _GLIBCXX_NOTHROW;
1702   extern template
1703     const money_put<char>*
1704     __try_use_facet<money_put<char> >(const locale&) _GLIBCXX_NOTHROW;
1706   extern template
1707     const money_get<char>*
1708     __try_use_facet<money_get<char> >(const locale&) _GLIBCXX_NOTHROW;
1710   extern template
1711     const __timepunct<char>*
1712     __try_use_facet<__timepunct<char> >(const locale&) _GLIBCXX_NOTHROW;
1714   extern template
1715     const time_put<char>*
1716     __try_use_facet<time_put<char> >(const locale&) _GLIBCXX_NOTHROW;
1718   extern template
1719     const time_get<char>*
1720     __try_use_facet<time_get<char> >(const locale&) _GLIBCXX_NOTHROW;
1722   extern template
1723     const messages<char>*
1724     __try_use_facet<messages<char> >(const locale&) _GLIBCXX_NOTHROW;
1726   extern template
1727     const moneypunct<char, true>&
1728     use_facet<moneypunct<char, true> >(const locale&);
1730   extern template
1731     const moneypunct<char, false>&
1732     use_facet<moneypunct<char, false> >(const locale&);
1734   extern template
1735     const money_put<char>&
1736     use_facet<money_put<char> >(const locale&);
1738   extern template
1739     const money_get<char>&
1740     use_facet<money_get<char> >(const locale&);
1742   extern template
1743     const __timepunct<char>&
1744     use_facet<__timepunct<char> >(const locale&);
1746   extern template
1747     const time_put<char>&
1748     use_facet<time_put<char> >(const locale&);
1750   extern template
1751     const time_get<char>&
1752     use_facet<time_get<char> >(const locale&);
1754   extern template
1755     const messages<char>&
1756     use_facet<messages<char> >(const locale&);
1758   extern template
1759     bool
1760     has_facet<moneypunct<char> >(const locale&);
1762   extern template
1763     bool
1764     has_facet<money_put<char> >(const locale&);
1766   extern template
1767     bool
1768     has_facet<money_get<char> >(const locale&);
1770   extern template
1771     bool
1772     has_facet<__timepunct<char> >(const locale&);
1774   extern template
1775     bool
1776     has_facet<time_put<char> >(const locale&);
1778   extern template
1779     bool
1780     has_facet<time_get<char> >(const locale&);
1782   extern template
1783     bool
1784     has_facet<messages<char> >(const locale&);
1786 #ifdef _GLIBCXX_USE_WCHAR_T
1787   extern template class moneypunct<wchar_t, false>;
1788   extern template class moneypunct<wchar_t, true>;
1789   extern template class moneypunct_byname<wchar_t, false>;
1790   extern template class moneypunct_byname<wchar_t, true>;
1791   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
1792   extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
1793   extern template class __timepunct<wchar_t>;
1794   extern template class time_put<wchar_t>;
1795   extern template class time_put_byname<wchar_t>;
1796   extern template class time_get<wchar_t>;
1797   extern template class time_get_byname<wchar_t>;
1798   extern template class messages<wchar_t>;
1799   extern template class messages_byname<wchar_t>;
1801   extern template
1802     const moneypunct<wchar_t, true>*
1803     __try_use_facet<moneypunct<wchar_t, true> >(const locale&) _GLIBCXX_NOTHROW;
1805   extern template
1806     const moneypunct<wchar_t, false>*
1807     __try_use_facet<moneypunct<wchar_t, false> >(const locale&) _GLIBCXX_NOTHROW;
1809   extern template
1810     const money_put<wchar_t>*
1811     __try_use_facet<money_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1813   extern template
1814     const money_get<wchar_t>*
1815     __try_use_facet<money_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1817   extern template
1818     const __timepunct<wchar_t>*
1819     __try_use_facet<__timepunct<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1821   extern template
1822     const time_put<wchar_t>*
1823     __try_use_facet<time_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1825   extern template
1826     const time_get<wchar_t>*
1827     __try_use_facet<time_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1829   extern template
1830     const messages<wchar_t>*
1831     __try_use_facet<messages<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1833   extern template
1834     const moneypunct<wchar_t, true>&
1835     use_facet<moneypunct<wchar_t, true> >(const locale&);
1837   extern template
1838     const moneypunct<wchar_t, false>&
1839     use_facet<moneypunct<wchar_t, false> >(const locale&);
1841   extern template
1842     const money_put<wchar_t>&
1843     use_facet<money_put<wchar_t> >(const locale&);
1845   extern template
1846     const money_get<wchar_t>&
1847     use_facet<money_get<wchar_t> >(const locale&);
1849   extern template
1850     const __timepunct<wchar_t>&
1851     use_facet<__timepunct<wchar_t> >(const locale&);
1853   extern template
1854     const time_put<wchar_t>&
1855     use_facet<time_put<wchar_t> >(const locale&);
1857   extern template
1858     const time_get<wchar_t>&
1859     use_facet<time_get<wchar_t> >(const locale&);
1861   extern template
1862     const messages<wchar_t>&
1863     use_facet<messages<wchar_t> >(const locale&);
1865   extern template
1866     bool
1867     has_facet<moneypunct<wchar_t> >(const locale&);
1869   extern template
1870     bool
1871     has_facet<money_put<wchar_t> >(const locale&);
1873   extern template
1874     bool
1875     has_facet<money_get<wchar_t> >(const locale&);
1877   extern template
1878     bool
1879     has_facet<__timepunct<wchar_t> >(const locale&);
1881   extern template
1882     bool
1883     has_facet<time_put<wchar_t> >(const locale&);
1885   extern template
1886     bool
1887     has_facet<time_get<wchar_t> >(const locale&);
1889   extern template
1890     bool
1891     has_facet<messages<wchar_t> >(const locale&);
1892 #endif
1893 #endif
1895 _GLIBCXX_END_NAMESPACE_VERSION
1896 } // namespace std
1898 #endif