libstdc++
locale_facets_nonio.tcc
Go to the documentation of this file.
1 // Locale support -*- C++ -*-
2 
3 // Copyright (C) 2007-2022 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
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  }
1335 
1336  template<typename _CharT, typename _InIter>
1337  _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  }
1354 
1355  template<typename _CharT, typename _InIter>
1356  _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;
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
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);
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  use_facet<moneypunct<char, true> >(const locale&);
1697 
1698  extern template
1700  use_facet<moneypunct<char, false> >(const locale&);
1701 
1702  extern template
1703  const money_put<char>&
1704  use_facet<money_put<char> >(const locale&);
1705 
1706  extern template
1707  const money_get<char>&
1708  use_facet<money_get<char> >(const locale&);
1709 
1710  extern template
1711  const __timepunct<char>&
1712  use_facet<__timepunct<char> >(const locale&);
1713 
1714  extern template
1715  const time_put<char>&
1716  use_facet<time_put<char> >(const locale&);
1717 
1718  extern template
1719  const time_get<char>&
1720  use_facet<time_get<char> >(const locale&);
1721 
1722  extern template
1723  const messages<char>&
1724  use_facet<messages<char> >(const locale&);
1725 
1726  extern template
1727  bool
1728  has_facet<moneypunct<char> >(const locale&);
1729 
1730  extern template
1731  bool
1732  has_facet<money_put<char> >(const locale&);
1733 
1734  extern template
1735  bool
1736  has_facet<money_get<char> >(const locale&);
1737 
1738  extern template
1739  bool
1740  has_facet<__timepunct<char> >(const locale&);
1741 
1742  extern template
1743  bool
1744  has_facet<time_put<char> >(const locale&);
1745 
1746  extern template
1747  bool
1748  has_facet<time_get<char> >(const locale&);
1749 
1750  extern template
1751  bool
1752  has_facet<messages<char> >(const locale&);
1753 
1754 #ifdef _GLIBCXX_USE_WCHAR_T
1755  extern template class moneypunct<wchar_t, false>;
1756  extern template class moneypunct<wchar_t, true>;
1757  extern template class moneypunct_byname<wchar_t, false>;
1758  extern template class moneypunct_byname<wchar_t, true>;
1759  extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
1760  extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
1761  extern template class __timepunct<wchar_t>;
1762  extern template class time_put<wchar_t>;
1763  extern template class time_put_byname<wchar_t>;
1764  extern template class time_get<wchar_t>;
1765  extern template class time_get_byname<wchar_t>;
1766  extern template class messages<wchar_t>;
1767  extern template class messages_byname<wchar_t>;
1768 
1769  extern template
1771  use_facet<moneypunct<wchar_t, true> >(const locale&);
1772 
1773  extern template
1775  use_facet<moneypunct<wchar_t, false> >(const locale&);
1776 
1777  extern template
1778  const money_put<wchar_t>&
1779  use_facet<money_put<wchar_t> >(const locale&);
1780 
1781  extern template
1782  const money_get<wchar_t>&
1783  use_facet<money_get<wchar_t> >(const locale&);
1784 
1785  extern template
1786  const __timepunct<wchar_t>&
1787  use_facet<__timepunct<wchar_t> >(const locale&);
1788 
1789  extern template
1790  const time_put<wchar_t>&
1791  use_facet<time_put<wchar_t> >(const locale&);
1792 
1793  extern template
1794  const time_get<wchar_t>&
1795  use_facet<time_get<wchar_t> >(const locale&);
1796 
1797  extern template
1798  const messages<wchar_t>&
1799  use_facet<messages<wchar_t> >(const locale&);
1800 
1801  extern template
1802  bool
1803  has_facet<moneypunct<wchar_t> >(const locale&);
1804 
1805  extern template
1806  bool
1807  has_facet<money_put<wchar_t> >(const locale&);
1808 
1809  extern template
1810  bool
1811  has_facet<money_get<wchar_t> >(const locale&);
1812 
1813  extern template
1814  bool
1815  has_facet<__timepunct<wchar_t> >(const locale&);
1816 
1817  extern template
1818  bool
1819  has_facet<time_put<wchar_t> >(const locale&);
1820 
1821  extern template
1822  bool
1823  has_facet<time_get<wchar_t> >(const locale&);
1824 
1825  extern template
1826  bool
1827  has_facet<messages<wchar_t> >(const locale&);
1828 #endif
1829 #endif
1830 
1831 _GLIBCXX_END_NAMESPACE_VERSION
1832 } // namespace std
1833 
1834 #endif
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:230
ISO C++ entities toplevel namespace is std.
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
Definition: range_access.h:264
Basis for explicit traits specializations.
Definition: char_traits.h:330
const _CharT * c_str() const noexcept
Return const pointer to null-terminated contents.
Definition: cow_string.h:2206
void resize(size_type __n, _CharT __c)
Resizes the string to the specified number of characters.
Definition: cow_string.h:3570
static const size_type npos
Value returned by various member functions when they fail.
Definition: cow_string.h:328
The base of the I/O class hierarchy.
Definition: ios_base.h:230
_Ios_Fmtflags fmtflags
This is a bitmask type.
Definition: ios_base.h:342
_Ios_Iostate iostate
This is a bitmask type.
Definition: ios_base.h:417
const locale & _M_getloc() const
Locale access.
Definition: ios_base.h:813
static const fmtflags showbase
Generates a prefix indicating the numeric base of generated integer output.
Definition: ios_base.h:377
static const fmtflags internal
Adds fill characters at a designated internal point in certain generated output, or identical to righ...
Definition: ios_base.h:359
static const iostate eofbit
Indicates that an input operation reached the end of an input sequence.
Definition: ios_base.h:424
static const iostate goodbit
Indicates all is well.
Definition: ios_base.h:432
static const fmtflags left
Adds fill characters on the right (final positions) of certain generated output. (I....
Definition: ios_base.h:363
locale getloc() const
Locale access.
Definition: ios_base.h:802
static const iostate failbit
Indicates that an input operation failed to read the expected characters, or that an output operation...
Definition: ios_base.h:429
static const fmtflags adjustfield
A mask of left|right|internal. Useful for the 2-arg form of setf.
Definition: ios_base.h:397
Container class for localization functionality.
char_type tolower(char_type __c) const
Convert to lowercase.
char_type toupper(char_type __c) const
Convert to uppercase.
char_type widen(char __c) const
Widen char to char_type.
char narrow(char_type __c, char __dfault) const
Narrow char_type to char.
bool is(mask __m, char_type __c) const
Test char_type classification.
Primary class template ctype facet.
Primary class template time_get.
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.
_InIter iter_type
Public typedefs.
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.
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.
_CharT char_type
Public typedefs.
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 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.
virtual dateorder do_date_order() const
Return preferred order of month, day, and year.
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.
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.
class time_get_byname [22.2.5.2].
Primary class template time_put.
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.
_CharT char_type
Public typedefs.
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.
class time_put_byname [22.2.5.4].
Primary class template moneypunct.
static locale::id id
Numpunct facet id.
class moneypunct_byname [22.2.6.4].
Primary class template money_get.
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.
_InIter iter_type
Public typedefs.
Primary class template money_put.
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.
_OutIter iter_type
Public typedefs.
_CharT char_type
Public typedefs.
Primary class template messages.
class messages_byname [22.2.7.2].