libstdc++
locale_facets_nonio.tcc
Go to the documentation of this file.
1 // Locale support -*- C++ -*-
2 
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.
10 
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.
15 
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.
19 
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/>.
24 
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  */
29 
30 #ifndef _LOCALE_FACETS_NONIO_TCC
31 #define _LOCALE_FACETS_NONIO_TCC 1
32 
33 #pragma GCC system_header
34 
35 namespace std _GLIBCXX_VISIBILITY(default)
36 {
37 _GLIBCXX_BEGIN_NAMESPACE_VERSION
38 
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  };
66 
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);
73 
74  struct _Scoped_str
75  {
76  size_t _M_len;
77  _CharT* _M_str;
78 
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); }
83 
84  ~_Scoped_str() { delete[] _M_str; }
85 
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  };
94 
95  _Scoped_str __curr_symbol(__mp.curr_symbol());
96  _Scoped_str __positive_sign(__mp.positive_sign());
97  _Scoped_str __negative_sign(__mp.negative_sign());
98 
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);
103 
104  // All allocations succeeded without throwing, OK to modify *this now.
105 
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));
112 
113  _M_decimal_point = __mp.decimal_point();
114  _M_thousands_sep = __mp.thousands_sep();
115 
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);
119 
120  _M_frac_digits = __mp.frac_digits();
121  _M_pos_format = __mp.pos_format();
122  _M_neg_format = __mp.neg_format();
123 
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);
127 
128  _M_allocated = true;
129  }
130 
131 _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
132 
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);
147 
148  __use_cache<__cache_type> __uc;
149  const __cache_type* __lc = __uc(__loc);
150  const char_type* __lit = __lc->_M_atoms;
151 
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;
171 
172  // The tentative returned string is stored here.
173  string __res;
174  __res.reserve(32);
175 
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;
252 
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  }
294 
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  }
307 
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  }
318 
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  }
339 
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  }
351 
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
367 
368  template<typename _CharT, typename _InIter>
369  _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  }
380 
381  template<typename _CharT, typename _InIter>
382  _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;
388 
389  const locale& __loc = __io._M_getloc();
390  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
391 
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  }
403 
404 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
405  && defined __LONG_DOUBLE_IEEE128__
406  template<typename _CharT, typename _InIter>
407  _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
419 
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);
433 
434  __use_cache<__cache_type> __uc;
435  const __cache_type* __lc = __uc(__loc);
436  const char_type* __lit = __lc->_M_atoms;
437 
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();
441 
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);
470 
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  }
491 
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()
509  __len = __value.size() + __sign_size;
510  __len += ((__io.flags() & ios_base::showbase)
511  ? __lc->_M_curr_symbol_size : 0);
512 
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  }
579 
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
589 
590  template<typename _CharT, typename _OutIter>
591  _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  }
627 
628  template<typename _CharT, typename _OutIter>
629  _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); }
635 
636 #if defined _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT \
637  && defined __LONG_DOUBLE_IEEE128__
638 extern "C"
639 __typeof__(__builtin_snprintf) __glibcxx_snprintfibm128 __asm__("snprintf");
640 
641  template<typename _CharT, typename _OutIter>
642  _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());
653 
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
673 
674 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
675 
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
682  { return time_base::no_order; }
683 
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
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);
698 
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);
983 
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  }
1027 
1028  if (__tmperr || __i != __len)
1029  __err |= ios_base::failbit;
1030 
1031  return __beg;
1032  }
1033 
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  }
1045 
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);
1055 
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;
1074 
1075  return __beg;
1076  }
1077 
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);
1093 
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;
1103 
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  }
1120 
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;
1138 
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  }
1213 
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;
1231 
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;
1241 
1242  return __beg;
1243  }
1244 
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);
1255 
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;
1261 
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  }
1270 
1271  if (__nmatches)
1272  {
1273  ++__beg;
1274  ++__pos;
1275 
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  }
1283 
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  }
1305 
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;
1313 
1314  return __beg;
1315  }
1316 
1317  template<typename _CharT, typename _InIter>
1318  _InIter
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  }
1335 
1336  template<typename _CharT, typename _InIter>
1337  _InIter
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  }
1354 
1355  template<typename _CharT, typename _InIter>
1356  _InIter
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;
1368 
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;
1375 
1376  if (__beg == __end)
1377  __err |= ios_base::eofbit;
1378  return __beg;
1379  }
1380 
1381  template<typename _CharT, typename _InIter>
1382  _InIter
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;
1394 
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;
1401 
1402  if (__beg == __end)
1403  __err |= ios_base::eofbit;
1404  return __beg;
1405  }
1406 
1407  template<typename _CharT, typename _InIter>
1408  _InIter
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);
1417 
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;
1449 
1450  if (__beg == __end)
1451  __err |= ios_base::eofbit;
1452  return __beg;
1453  }
1454 
1455 #if __cplusplus >= 201103L
1456  template<typename _CharT, typename _InIter>
1457  inline
1458  _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(__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  {
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;
1541 
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  }
1563 
1564  template<typename _CharT, typename _InIter>
1565  inline
1566  _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;
1575 
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  }
1589 
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  }
1598 
1599 #endif // __cplusplus >= 201103L
1600 
1601  template<typename _CharT, typename _OutIter>
1602  _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  }
1635 
1636  template<typename _CharT, typename _OutIter>
1637  _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);
1645 
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];
1650 
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  }
1669 
1670  __tp._M_put(__res, __maxlen, __fmt, __tm);
1671 
1672  // Write resulting, fully-formatted string to output iterator.
1673  return std::__write(__s, __res, char_traits<char_type>::length(__res));
1674  }
1675 
1676 
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>;
1693 
1694  extern template
1695  const moneypunct<char, true>*
1696  __try_use_facet<moneypunct<char, true> >(const locale&) _GLIBCXX_NOTHROW;
1697 
1698  extern template
1700  __try_use_facet<moneypunct<char, false> >(const locale&) _GLIBCXX_NOTHROW;
1701 
1702  extern template
1703  const money_put<char>*
1704  __try_use_facet<money_put<char> >(const locale&) _GLIBCXX_NOTHROW;
1705 
1706  extern template
1707  const money_get<char>*
1708  __try_use_facet<money_get<char> >(const locale&) _GLIBCXX_NOTHROW;
1709 
1710  extern template
1711  const __timepunct<char>*
1712  __try_use_facet<__timepunct<char> >(const locale&) _GLIBCXX_NOTHROW;
1713 
1714  extern template
1715  const time_put<char>*
1716  __try_use_facet<time_put<char> >(const locale&) _GLIBCXX_NOTHROW;
1717 
1718  extern template
1719  const time_get<char>*
1720  __try_use_facet<time_get<char> >(const locale&) _GLIBCXX_NOTHROW;
1721 
1722  extern template
1723  const messages<char>*
1724  __try_use_facet<messages<char> >(const locale&) _GLIBCXX_NOTHROW;
1725 
1726  extern template
1727  const moneypunct<char, true>&
1728  use_facet<moneypunct<char, true> >(const locale&);
1729 
1730  extern template
1732  use_facet<moneypunct<char, false> >(const locale&);
1733 
1734  extern template
1735  const money_put<char>&
1736  use_facet<money_put<char> >(const locale&);
1737 
1738  extern template
1739  const money_get<char>&
1740  use_facet<money_get<char> >(const locale&);
1741 
1742  extern template
1743  const __timepunct<char>&
1744  use_facet<__timepunct<char> >(const locale&);
1745 
1746  extern template
1747  const time_put<char>&
1748  use_facet<time_put<char> >(const locale&);
1749 
1750  extern template
1751  const time_get<char>&
1752  use_facet<time_get<char> >(const locale&);
1753 
1754  extern template
1755  const messages<char>&
1756  use_facet<messages<char> >(const locale&);
1757 
1758  extern template
1759  bool
1760  has_facet<moneypunct<char> >(const locale&);
1761 
1762  extern template
1763  bool
1764  has_facet<money_put<char> >(const locale&);
1765 
1766  extern template
1767  bool
1768  has_facet<money_get<char> >(const locale&);
1769 
1770  extern template
1771  bool
1772  has_facet<__timepunct<char> >(const locale&);
1773 
1774  extern template
1775  bool
1776  has_facet<time_put<char> >(const locale&);
1777 
1778  extern template
1779  bool
1780  has_facet<time_get<char> >(const locale&);
1781 
1782  extern template
1783  bool
1784  has_facet<messages<char> >(const locale&);
1785 
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>;
1800 
1801  extern template
1803  __try_use_facet<moneypunct<wchar_t, true> >(const locale&) _GLIBCXX_NOTHROW;
1804 
1805  extern template
1807  __try_use_facet<moneypunct<wchar_t, false> >(const locale&) _GLIBCXX_NOTHROW;
1808 
1809  extern template
1810  const money_put<wchar_t>*
1811  __try_use_facet<money_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1812 
1813  extern template
1814  const money_get<wchar_t>*
1815  __try_use_facet<money_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1816 
1817  extern template
1818  const __timepunct<wchar_t>*
1819  __try_use_facet<__timepunct<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1820 
1821  extern template
1822  const time_put<wchar_t>*
1823  __try_use_facet<time_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1824 
1825  extern template
1826  const time_get<wchar_t>*
1827  __try_use_facet<time_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1828 
1829  extern template
1830  const messages<wchar_t>*
1831  __try_use_facet<messages<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1832 
1833  extern template
1835  use_facet<moneypunct<wchar_t, true> >(const locale&);
1836 
1837  extern template
1839  use_facet<moneypunct<wchar_t, false> >(const locale&);
1840 
1841  extern template
1842  const money_put<wchar_t>&
1843  use_facet<money_put<wchar_t> >(const locale&);
1844 
1845  extern template
1846  const money_get<wchar_t>&
1847  use_facet<money_get<wchar_t> >(const locale&);
1848 
1849  extern template
1850  const __timepunct<wchar_t>&
1851  use_facet<__timepunct<wchar_t> >(const locale&);
1852 
1853  extern template
1854  const time_put<wchar_t>&
1855  use_facet<time_put<wchar_t> >(const locale&);
1856 
1857  extern template
1858  const time_get<wchar_t>&
1859  use_facet<time_get<wchar_t> >(const locale&);
1860 
1861  extern template
1862  const messages<wchar_t>&
1863  use_facet<messages<wchar_t> >(const locale&);
1864 
1865  extern template
1866  bool
1867  has_facet<moneypunct<wchar_t> >(const locale&);
1868 
1869  extern template
1870  bool
1871  has_facet<money_put<wchar_t> >(const locale&);
1872 
1873  extern template
1874  bool
1875  has_facet<money_get<wchar_t> >(const locale&);
1876 
1877  extern template
1878  bool
1879  has_facet<__timepunct<wchar_t> >(const locale&);
1880 
1881  extern template
1882  bool
1883  has_facet<time_put<wchar_t> >(const locale&);
1884 
1885  extern template
1886  bool
1887  has_facet<time_get<wchar_t> >(const locale&);
1888 
1889  extern template
1890  bool
1891  has_facet<messages<wchar_t> >(const locale&);
1892 #endif
1893 #endif
1894 
1895 _GLIBCXX_END_NAMESPACE_VERSION
1896 } // namespace std
1897 
1898 #endif
_CharT char_type
Public typedefs.
ISO C++ entities toplevel namespace is std.
class moneypunct_byname [22.2.6.4].
virtual iter_type do_put(iter_type __s, bool __intl, ios_base &__io, char_type __fill, long double __units) const
Format and output a monetary value.
static const fmtflags adjustfield
A mask of left|right|internal. Useful for the 2-arg form of setf.
Definition: ios_base.h:422
class messages_byname [22.2.7.2].
virtual iter_type do_get_date(iter_type __beg, iter_type __end, ios_base &__io, ios_base::iostate &__err, tm *__tm) const
Parse input date string.
Primary class template money_put.This facet encapsulates the code to format and output a monetary amo...
bool is(mask __m, char_type __c) const
Test char_type classification.
iter_type do_get(iter_type __s, iter_type __end, ios_base &__f, ios_base::iostate &__err, tm *__tm, char __format, char __modifier) const
Parse input string according to format.
iter_type put(iter_type __s, ios_base &__io, char_type __fill, const tm *__tm, const _CharT *__beg, const _CharT *__end) const
Format and output a time or date.
_OutIter iter_type
Public typedefs.
Primary class template time_put.This facet encapsulates the code to format and output dates and times...
static const iostate failbit
Indicates that an input operation failed to read the expected characters, or that an output operation...
Definition: ios_base.h:454
Container class for localization functionality.The locale class is first a class wrapper for C librar...
const _CharT * c_str() const noexcept
Return const pointer to null-terminated contents.
Definition: cow_string.h:2249
char_type toupper(char_type __c) const
Convert to uppercase.
_InIter iter_type
Public typedefs.
Primary class template ctype facet.This template class defines classification and conversion function...
_CharT char_type
Public typedefs.
Primary class template moneypunct.This facet encapsulates the punctuation, grouping and other formatt...
_OutIter iter_type
Public typedefs.
class time_get_byname [22.2.5.2].
_Ios_Fmtflags fmtflags
This is a bitmask type.
Definition: ios_base.h:367
virtual iter_type do_get_time(iter_type __beg, iter_type __end, ios_base &__io, ios_base::iostate &__err, tm *__tm) const
Parse input time string.
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:233
static const size_type npos
Value returned by various member functions when they fail.
Definition: cow_string.h:322
Primary class template messages.This facet encapsulates the code to retrieve messages from message ca...
_InIter iter_type
Public typedefs.
Primary class template money_get.This facet encapsulates the code to parse and return a monetary amou...
virtual iter_type do_get_year(iter_type __beg, iter_type __end, ios_base &__io, ios_base::iostate &__err, tm *__tm) const
Parse input year string.
iter_type get(iter_type __s, iter_type __end, ios_base &__io, ios_base::iostate &__err, tm *__tm, char __format, char __modifier=0) const
Parse input string according to format.
static const fmtflags left
Adds fill characters on the right (final positions) of certain generated output. (I.e., the thing you print is flush left.)
Definition: ios_base.h:388
static locale::id id
Numpunct facet id.
The base of the I/O class hierarchy.This class defines everything that can be defined about I/O that ...
Definition: ios_base.h:254
virtual iter_type do_put(iter_type __s, ios_base &__io, char_type __fill, const tm *__tm, char __format, char __mod) const
Format and output a time or date.
char_type tolower(char_type __c) const
Convert to lowercase.
static const fmtflags showbase
Generates a prefix indicating the numeric base of generated integer output.
Definition: ios_base.h:402
void resize(size_type __n, _CharT __c)
Resizes the string to the specified number of characters.
Definition: cow_string.h:3669
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
Definition: range_access.h:262
virtual iter_type do_get_weekday(iter_type __beg, iter_type __end, ios_base &, ios_base::iostate &__err, tm *__tm) const
Parse input weekday string.
static const iostate eofbit
Indicates that an input operation reached the end of an input sequence.
Definition: ios_base.h:449
const locale & _M_getloc() const
Locale access.
Definition: ios_base.h:837
virtual dateorder do_date_order() const
Return preferred order of month, day, and year.
_Ios_Iostate iostate
This is a bitmask type.
Definition: ios_base.h:442
Basis for explicit traits specializations.
Definition: char_traits.h:323
static const iostate goodbit
Indicates all is well.
Definition: ios_base.h:457
virtual iter_type do_get_monthname(iter_type __beg, iter_type __end, ios_base &, ios_base::iostate &__err, tm *__tm) const
Parse input month string.
virtual iter_type do_get(iter_type __s, iter_type __end, bool __intl, ios_base &__io, ios_base::iostate &__err, long double &__units) const
Read and parse a monetary value.
locale getloc() const
Locale access.
Definition: ios_base.h:826
static const fmtflags internal
Adds fill characters at a designated internal point in certain generated output, or identical to righ...
Definition: ios_base.h:384
_CharT char_type
Public typedefs.
char narrow(char_type __c, char __dfault) const
Narrow char_type to char.
class time_put_byname [22.2.5.4].
char_type widen(char __c) const
Widen char to char_type.
Primary class template time_get.This facet encapsulates the code to parse and return a date or time f...