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  _M_decimal_point = __mp.decimal_point();
75  _M_thousands_sep = __mp.thousands_sep();
76  _M_frac_digits = __mp.frac_digits();
77 
78  char* __grouping = 0;
79  _CharT* __curr_symbol = 0;
80  _CharT* __positive_sign = 0;
81  _CharT* __negative_sign = 0;
82  __try
83  {
84  const string& __g = __mp.grouping();
85  _M_grouping_size = __g.size();
86  __grouping = new char[_M_grouping_size];
87  __g.copy(__grouping, _M_grouping_size);
88  _M_use_grouping = (_M_grouping_size
89  && static_cast<signed char>(__grouping[0]) > 0
90  && (__grouping[0]
91  != __gnu_cxx::__numeric_traits<char>::__max));
92 
93  const basic_string<_CharT>& __cs = __mp.curr_symbol();
94  _M_curr_symbol_size = __cs.size();
95  __curr_symbol = new _CharT[_M_curr_symbol_size];
96  __cs.copy(__curr_symbol, _M_curr_symbol_size);
97 
98  const basic_string<_CharT>& __ps = __mp.positive_sign();
99  _M_positive_sign_size = __ps.size();
100  __positive_sign = new _CharT[_M_positive_sign_size];
101  __ps.copy(__positive_sign, _M_positive_sign_size);
102 
103  const basic_string<_CharT>& __ns = __mp.negative_sign();
104  _M_negative_sign_size = __ns.size();
105  __negative_sign = new _CharT[_M_negative_sign_size];
106  __ns.copy(__negative_sign, _M_negative_sign_size);
107 
108  _M_pos_format = __mp.pos_format();
109  _M_neg_format = __mp.neg_format();
110 
111  const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
112  __ct.widen(money_base::_S_atoms,
113  money_base::_S_atoms + money_base::_S_end, _M_atoms);
114 
115  _M_grouping = __grouping;
116  _M_curr_symbol = __curr_symbol;
117  _M_positive_sign = __positive_sign;
118  _M_negative_sign = __negative_sign;
119  _M_allocated = true;
120  }
121  __catch(...)
122  {
123  delete [] __grouping;
124  delete [] __curr_symbol;
125  delete [] __positive_sign;
126  delete [] __negative_sign;
127  __throw_exception_again;
128  }
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  template<typename _CharT, typename _OutIter>
639  _OutIter
641  __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
642  __ibm128 __units) const
643  {
644  const locale __loc = __io.getloc();
645  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
646 #if _GLIBCXX_USE_C99_STDIO
647  // First try a buffer perhaps big enough.
648  int __cs_size = 64;
649  char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
650  // _GLIBCXX_RESOLVE_LIB_DEFECTS
651  // 328. Bad sprintf format modifier in money_put<>::do_put()
652  int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
653  "%.*Lf", 0, __units);
654  // If the buffer was not large enough, try again with the correct size.
655  if (__len >= __cs_size)
656  {
657  __cs_size = __len + 1;
658  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
659  __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
660  "%.*Lf", 0, __units);
661  }
662 #else
663  // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
664  const int __cs_size =
665  __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
666  char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
667  int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
668  0, __units);
669 #endif
670  string_type __digits(__len, char_type());
671  __ctype.widen(__cs, __cs + __len, &__digits[0]);
672  return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
673  : _M_insert<false>(__s, __io, __fill, __digits);
674  }
675 #endif
676 
677 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
678 
679  // NB: Not especially useful. Without an ios_base object or some
680  // kind of locale reference, we are left clawing at the air where
681  // the side of the mountain used to be...
682  template<typename _CharT, typename _InIter>
683  time_base::dateorder
685  { return time_base::no_order; }
686 
687  // Expand a strptime format string and parse it. E.g., do_get_date() may
688  // pass %m/%d/%Y => extracted characters.
689  template<typename _CharT, typename _InIter>
690  _InIter
692  _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
693  ios_base::iostate& __err, tm* __tm,
694  const _CharT* __format,
695  __time_get_state &__state) const
696  {
697  const locale& __loc = __io._M_getloc();
698  const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
699  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
700  const size_t __len = char_traits<_CharT>::length(__format);
701 
702  ios_base::iostate __tmperr = ios_base::goodbit;
703  size_t __i = 0;
704  for (; __beg != __end && __i < __len && !__tmperr; ++__i)
705  {
706  if (__ctype.narrow(__format[__i], 0) == '%')
707  {
708  // Verify valid formatting code, attempt to extract.
709  char __c = __ctype.narrow(__format[++__i], 0);
710  int __mem = 0;
711  if (__c == 'E' || __c == 'O')
712  __c = __ctype.narrow(__format[++__i], 0);
713  switch (__c)
714  {
715  const char* __cs;
716  _CharT __wcs[10];
717  case 'a':
718  case 'A':
719  // Weekday name (possibly abbreviated) [tm_wday]
720  const char_type* __days[14];
721  __tp._M_days(&__days[0]);
722  __tp._M_days_abbreviated(&__days[7]);
723  __beg = _M_extract_name(__beg, __end, __mem, __days,
724  14, __io, __tmperr);
725  if (!__tmperr)
726  {
727  __tm->tm_wday = __mem % 7;
728  __state._M_have_wday = 1;
729  }
730  break;
731  case 'h':
732  case 'b':
733  case 'B':
734  // Month name (possibly abbreviated) [tm_mon]
735  const char_type* __months[24];
736  __tp._M_months(&__months[0]);
737  __tp._M_months_abbreviated(&__months[12]);
738  __beg = _M_extract_name(__beg, __end, __mem,
739  __months, 24, __io, __tmperr);
740  if (!__tmperr)
741  {
742  __tm->tm_mon = __mem % 12;
743  __state._M_have_mon = 1;
744  __state._M_want_xday = 1;
745  }
746  break;
747  case 'c':
748  // Default time and date representation.
749  const char_type* __dt[2];
750  __tp._M_date_time_formats(__dt);
751  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
752  __tm, __dt[0], __state);
753  if (!__tmperr)
754  __state._M_want_xday = 1;
755  break;
756  case 'C':
757  // Century.
758  __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2,
759  __io, __tmperr);
760  if (!__tmperr)
761  {
762  __state._M_century = __mem;
763  __state._M_have_century = 1;
764  __state._M_want_xday = 1;
765  }
766  break;
767  case 'd':
768  case 'e':
769  // Day [1, 31]. [tm_mday]
770  if (__ctype.is(ctype_base::space, *__beg))
771  ++__beg;
772  __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2,
773  __io, __tmperr);
774  if (!__tmperr)
775  {
776  __tm->tm_mday = __mem;
777  __state._M_have_mday = 1;
778  __state._M_want_xday = 1;
779  }
780  break;
781  case 'D':
782  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
783  __cs = "%m/%d/%y";
784  __ctype.widen(__cs, __cs + 9, __wcs);
785  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
786  __tm, __wcs, __state);
787  if (!__tmperr)
788  __state._M_want_xday = 1;
789  break;
790  case 'H':
791  // Hour [00, 23]. [tm_hour]
792  __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2,
793  __io, __tmperr);
794  if (!__tmperr)
795  {
796  __tm->tm_hour = __mem;
797  __state._M_have_I = 0;
798  }
799  break;
800  case 'I':
801  // Hour [01, 12]. [tm_hour]
802  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
803  __io, __tmperr);
804  if (!__tmperr)
805  {
806  __tm->tm_hour = __mem % 12;
807  __state._M_have_I = 1;
808  }
809  break;
810  case 'j':
811  // Day number of year.
812  __beg = _M_extract_num(__beg, __end, __mem, 1, 366, 3,
813  __io, __tmperr);
814  if (!__tmperr)
815  {
816  __tm->tm_yday = __mem - 1;
817  __state._M_have_yday = 1;
818  }
819  break;
820  case 'm':
821  // Month [01, 12]. [tm_mon]
822  __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
823  __io, __tmperr);
824  if (!__tmperr)
825  {
826  __tm->tm_mon = __mem - 1;
827  __state._M_have_mon = 1;
828  }
829  break;
830  case 'M':
831  // Minute [00, 59]. [tm_min]
832  __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2,
833  __io, __tmperr);
834  if (!__tmperr)
835  __tm->tm_min = __mem;
836  break;
837  case 'n':
838  case 't':
839  while (__beg != __end
840  && __ctype.is(ctype_base::space, *__beg))
841  ++__beg;
842  break;
843  case 'p':
844  // Locale's a.m. or p.m.
845  const char_type* __ampm[2];
846  __tp._M_am_pm(&__ampm[0]);
847  if (!__ampm[0][0] || !__ampm[1][0])
848  break;
849  __beg = _M_extract_name(__beg, __end, __mem, __ampm,
850  2, __io, __tmperr);
851  if (!__tmperr && __mem)
852  __state._M_is_pm = 1;
853  break;
854  case 'r':
855  // Locale's 12-hour clock time format (in C %I:%M:%S %p).
856  const char_type* __ampm_format;
857  __tp._M_am_pm_format(&__ampm_format);
858  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
859  __tm, __ampm_format, __state);
860  break;
861  case 'R':
862  // Equivalent to (%H:%M).
863  __cs = "%H:%M";
864  __ctype.widen(__cs, __cs + 6, __wcs);
865  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
866  __tm, __wcs, __state);
867  break;
868  case 'S':
869  // Seconds. [tm_sec]
870  // [00, 60] in C99 (one leap-second), [00, 61] in C89.
871 #if _GLIBCXX_USE_C99
872  __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2,
873 #else
874  __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2,
875 #endif
876  __io, __tmperr);
877  if (!__tmperr)
878  __tm->tm_sec = __mem;
879  break;
880  case 'T':
881  // Equivalent to (%H:%M:%S).
882  __cs = "%H:%M:%S";
883  __ctype.widen(__cs, __cs + 9, __wcs);
884  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
885  __tm, __wcs, __state);
886  break;
887  case 'U':
888  // Week number of the year (Sunday as first day of week).
889  __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2,
890  __io, __tmperr);
891  if (!__tmperr)
892  {
893  __state._M_week_no = __mem;
894  __state._M_have_uweek = 1;
895  }
896  break;
897  case 'w':
898  // Weekday [tm_wday]
899  __beg = _M_extract_num(__beg, __end, __mem, 0, 6, 1,
900  __io, __tmperr);
901  if (!__tmperr)
902  {
903  __tm->tm_wday = __mem;
904  __state._M_have_wday = 1;
905  }
906  break;
907  case 'W':
908  // Week number of the year (Monday as first day of week).
909  __beg = _M_extract_num(__beg, __end, __mem, 0, 53, 2,
910  __io, __tmperr);
911  if (!__tmperr)
912  {
913  __state._M_week_no = __mem;
914  __state._M_have_wweek = 1;
915  }
916  break;
917  case 'x':
918  // Locale's date.
919  const char_type* __dates[2];
920  __tp._M_date_formats(__dates);
921  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
922  __tm, __dates[0], __state);
923  break;
924  case 'X':
925  // Locale's time.
926  const char_type* __times[2];
927  __tp._M_time_formats(__times);
928  __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
929  __tm, __times[0], __state);
930  break;
931  case 'y':
932  // The last 2 digits of year.
933  __beg = _M_extract_num(__beg, __end, __mem, 0, 99, 2,
934  __io, __tmperr);
935  if (!__tmperr)
936  {
937  __state._M_want_century = 1;
938  __state._M_want_xday = 1;
939  // As an extension, if the 2 digits are followed by
940  // 1-2 further digits, treat it like %Y.
941  __c = 0;
942  if (__beg != __end)
943  __c = __ctype.narrow(*__beg, '*');
944  if (__c >= '0' && __c <= '9')
945  {
946  ++__beg;
947  __mem = __mem * 10 + (__c - '0');
948  if (__beg != __end)
949  {
950  __c = __ctype.narrow(*__beg, '*');
951  if (__c >= '0' && __c <= '9')
952  {
953  ++__beg;
954  __mem = __mem * 10 + (__c - '0');
955  }
956  }
957  __mem -= 1900;
958  __state._M_want_century = 0;
959  }
960  // Otherwise, as per POSIX 2008, 00-68 is 2000-2068,
961  // while 69-99 is 1969-1999.
962  else if (__mem < 69)
963  __mem += 100;
964  __tm->tm_year = __mem;
965  }
966  break;
967  case 'Y':
968  // Year.
969  __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
970  __io, __tmperr);
971  if (!__tmperr)
972  {
973  __tm->tm_year = __mem - 1900;
974  __state._M_want_century = 0;
975  __state._M_want_xday = 1;
976  }
977  break;
978  case 'Z':
979  // Timezone info.
980  if (__ctype.is(ctype_base::upper, *__beg))
981  {
982  int __tmp;
983  __beg = _M_extract_name(__beg, __end, __tmp,
984  __timepunct_cache<_CharT>::_S_timezones,
985  14, __io, __tmperr);
986 
987  // GMT requires special effort.
988  if (__beg != __end && !__tmperr && __tmp == 0
989  && (*__beg == __ctype.widen('-')
990  || *__beg == __ctype.widen('+')))
991  {
992  __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
993  __io, __tmperr);
994  __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
995  __io, __tmperr);
996  }
997  }
998  else
999  __tmperr |= ios_base::failbit;
1000  break;
1001  case '%':
1002  if (*__beg == __ctype.widen('%'))
1003  ++__beg;
1004  else
1005  __tmperr |= ios_base::failbit;
1006  break;
1007  default:
1008  // Not recognized.
1009  __tmperr |= ios_base::failbit;
1010  }
1011  }
1012  else if (__ctype.is(ctype_base::space, __format[__i]))
1013  {
1014  // Skip any whitespace.
1015  while (__beg != __end
1016  && __ctype.is(ctype_base::space, *__beg))
1017  ++__beg;
1018  }
1019  else
1020  {
1021  // Verify format and input match, extract and discard.
1022  // TODO real case-insensitive comparison
1023  if (__ctype.tolower(__format[__i]) == __ctype.tolower(*__beg)
1024  || __ctype.toupper(__format[__i]) == __ctype.toupper(*__beg))
1025  ++__beg;
1026  else
1027  __tmperr |= ios_base::failbit;
1028  }
1029  }
1030 
1031  if (__tmperr || __i != __len)
1032  __err |= ios_base::failbit;
1033 
1034  return __beg;
1035  }
1036 
1037  template<typename _CharT, typename _InIter>
1038  _InIter
1039  time_get<_CharT, _InIter>::
1040  _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
1041  ios_base::iostate& __err, tm* __tm,
1042  const _CharT* __format) const
1043  {
1044  __time_get_state __state = __time_get_state();
1045  return _M_extract_via_format(__beg, __end, __io, __err, __tm,
1046  __format, __state);
1047  }
1048 
1049  template<typename _CharT, typename _InIter>
1050  _InIter
1051  time_get<_CharT, _InIter>::
1052  _M_extract_num(iter_type __beg, iter_type __end, int& __member,
1053  int __min, int __max, size_t __len,
1054  ios_base& __io, ios_base::iostate& __err) const
1055  {
1056  const locale& __loc = __io._M_getloc();
1057  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1058 
1059  size_t __i = 0;
1060  int __value = 0;
1061  for (; __beg != __end && __i < __len; ++__beg, (void)++__i)
1062  {
1063  const char __c = __ctype.narrow(*__beg, '*');
1064  if (__c >= '0' && __c <= '9')
1065  {
1066  __value = __value * 10 + (__c - '0');
1067  if (__value > __max)
1068  break;
1069  }
1070  else
1071  break;
1072  }
1073  if (__i && __value >= __min && __value <= __max)
1074  __member = __value;
1075  else
1076  __err |= ios_base::failbit;
1077 
1078  return __beg;
1079  }
1080 
1081  // Assumptions:
1082  // All elements in __names are unique, except if __indexlen is
1083  // even __names in the first half could be the same as corresponding
1084  // __names in the second half (May is abbreviated as May). Some __names
1085  // elements could be prefixes of other __names elements.
1086  template<typename _CharT, typename _InIter>
1087  _InIter
1088  time_get<_CharT, _InIter>::
1089  _M_extract_name(iter_type __beg, iter_type __end, int& __member,
1090  const _CharT** __names, size_t __indexlen,
1091  ios_base& __io, ios_base::iostate& __err) const
1092  {
1093  typedef char_traits<_CharT> __traits_type;
1094  const locale& __loc = __io._M_getloc();
1095  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1096 
1097  size_t* __matches
1098  = static_cast<size_t*>(__builtin_alloca(2 * sizeof(size_t)
1099  * __indexlen));
1100  size_t* __lengths = __matches + __indexlen;
1101  size_t __nmatches = 0;
1102  size_t __pos = 0;
1103  bool __testvalid = true;
1104  const char_type* __name;
1105  bool __begupdated = false;
1106 
1107  // Look for initial matches.
1108  if (__beg != __end)
1109  {
1110  const char_type __c = *__beg;
1111  // TODO real case-insensitive comparison
1112  const char_type __cl = __ctype.tolower(__c);
1113  const char_type __cu = __ctype.toupper(__c);
1114  for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1115  if (__cl == __ctype.tolower(__names[__i1][0])
1116  || __cu == __ctype.toupper(__names[__i1][0]))
1117  {
1118  __lengths[__nmatches]
1119  = __traits_type::length(__names[__i1]);
1120  __matches[__nmatches++] = __i1;
1121  }
1122  }
1123 
1124  while (__nmatches > 1)
1125  {
1126  // Find smallest matching string.
1127  size_t __minlen = __lengths[0];
1128  for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
1129  __minlen = std::min(__minlen, __lengths[__i2]);
1130  ++__pos;
1131  ++__beg;
1132  if (__pos == __minlen)
1133  {
1134  // If some match has remaining length of 0,
1135  // need to decide if any match with remaining
1136  // length non-zero matches the next character.
1137  // If so, remove all matches with remaining length
1138  // 0 from consideration, otherwise keep only matches
1139  // with remaining length 0.
1140  bool __match_longer = false;
1141 
1142  if (__beg != __end)
1143  {
1144  // TODO real case-insensitive comparison
1145  const char_type __cl = __ctype.tolower(*__beg);
1146  const char_type __cu = __ctype.toupper(*__beg);
1147  for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1148  {
1149  __name = __names[__matches[__i3]];
1150  if (__lengths[__i3] > __pos
1151  && (__ctype.tolower(__name[__pos]) == __cl
1152  || __ctype.toupper(__name[__pos]) == __cu))
1153  {
1154  __match_longer = true;
1155  break;
1156  }
1157  }
1158  }
1159  for (size_t __i4 = 0; __i4 < __nmatches;)
1160  if (__match_longer == (__lengths[__i4] == __pos))
1161  {
1162  __matches[__i4] = __matches[--__nmatches];
1163  __lengths[__i4] = __lengths[__nmatches];
1164  }
1165  else
1166  ++__i4;
1167  if (__match_longer)
1168  {
1169  __minlen = __lengths[0];
1170  for (size_t __i5 = 1; __i5 < __nmatches; ++__i5)
1171  __minlen = std::min(__minlen, __lengths[__i5]);
1172  }
1173  else
1174  {
1175  // Deal with May being full as well as abbreviated month
1176  // name. Pick the smaller index.
1177  if (__nmatches == 2 && (__indexlen & 1) == 0)
1178  {
1179  if (__matches[0] < __indexlen / 2)
1180  {
1181  if (__matches[1] == __matches[0] + __indexlen / 2)
1182  __nmatches = 1;
1183  }
1184  else if (__matches[1] == __matches[0] - __indexlen / 2)
1185  {
1186  __matches[0] = __matches[1];
1187  __lengths[0] = __lengths[1];
1188  __nmatches = 1;
1189  }
1190  }
1191  __begupdated = true;
1192  break;
1193  }
1194  }
1195  if (__pos < __minlen && __beg != __end)
1196  {
1197  // TODO real case-insensitive comparison
1198  const char_type __cl = __ctype.tolower(*__beg);
1199  const char_type __cu = __ctype.toupper(*__beg);
1200  for (size_t __i6 = 0; __i6 < __nmatches;)
1201  {
1202  __name = __names[__matches[__i6]];
1203  if (__ctype.tolower(__name[__pos]) != __cl
1204  && __ctype.toupper(__name[__pos]) != __cu)
1205  {
1206  __matches[__i6] = __matches[--__nmatches];
1207  __lengths[__i6] = __lengths[__nmatches];
1208  }
1209  else
1210  ++__i6;
1211  }
1212  }
1213  else
1214  break;
1215  }
1216 
1217  if (__nmatches == 1)
1218  {
1219  // Make sure found name is completely extracted.
1220  if (!__begupdated)
1221  {
1222  ++__beg;
1223  ++__pos;
1224  }
1225  __name = __names[__matches[0]];
1226  const size_t __len = __lengths[0];
1227  while (__pos < __len
1228  && __beg != __end
1229  // TODO real case-insensitive comparison
1230  && (__ctype.tolower(__name[__pos]) == __ctype.tolower(*__beg)
1231  || (__ctype.toupper(__name[__pos])
1232  == __ctype.toupper(*__beg))))
1233  ++__beg, (void)++__pos;
1234 
1235  if (__len == __pos)
1236  __member = __matches[0];
1237  else
1238  __testvalid = false;
1239  }
1240  else
1241  __testvalid = false;
1242  if (!__testvalid)
1243  __err |= ios_base::failbit;
1244 
1245  return __beg;
1246  }
1247 
1248  template<typename _CharT, typename _InIter>
1249  _InIter
1250  time_get<_CharT, _InIter>::
1251  _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
1252  const _CharT** __names, size_t __indexlen,
1253  ios_base& __io, ios_base::iostate& __err) const
1254  {
1255  typedef char_traits<_CharT> __traits_type;
1256  const locale& __loc = __io._M_getloc();
1257  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1258 
1259  int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
1260  * __indexlen));
1261  size_t __nmatches = 0;
1262  size_t* __matches_lengths = 0;
1263  size_t __pos = 0;
1264 
1265  if (__beg != __end)
1266  {
1267  const char_type __c = *__beg;
1268  for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
1269  if (__c == __names[__i][0]
1270  || __c == __ctype.toupper(__names[__i][0]))
1271  __matches[__nmatches++] = __i;
1272  }
1273 
1274  if (__nmatches)
1275  {
1276  ++__beg;
1277  ++__pos;
1278 
1279  __matches_lengths
1280  = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
1281  * __nmatches));
1282  for (size_t __i = 0; __i < __nmatches; ++__i)
1283  __matches_lengths[__i]
1284  = __traits_type::length(__names[__matches[__i]]);
1285  }
1286 
1287  for (; __beg != __end; ++__beg, (void)++__pos)
1288  {
1289  size_t __nskipped = 0;
1290  const char_type __c = *__beg;
1291  for (size_t __i = 0; __i < __nmatches;)
1292  {
1293  const char_type* __name = __names[__matches[__i]];
1294  if (__pos >= __matches_lengths[__i])
1295  ++__nskipped, ++__i;
1296  else if (!(__name[__pos] == __c))
1297  {
1298  --__nmatches;
1299  __matches[__i] = __matches[__nmatches];
1300  __matches_lengths[__i] = __matches_lengths[__nmatches];
1301  }
1302  else
1303  ++__i;
1304  }
1305  if (__nskipped == __nmatches)
1306  break;
1307  }
1308 
1309  if ((__nmatches == 1 && __matches_lengths[0] == __pos)
1310  || (__nmatches == 2 && (__matches_lengths[0] == __pos
1311  || __matches_lengths[1] == __pos)))
1312  __member = (__matches[0] >= (int)__indexlen
1313  ? __matches[0] - (int)__indexlen : __matches[0]);
1314  else
1315  __err |= ios_base::failbit;
1316 
1317  return __beg;
1318  }
1319 
1320  template<typename _CharT, typename _InIter>
1321  _InIter
1323  do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1324  ios_base::iostate& __err, tm* __tm) const
1325  {
1326  const locale& __loc = __io._M_getloc();
1327  const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1328  const char_type* __times[2];
1329  __tp._M_time_formats(__times);
1330  __time_get_state __state = __time_get_state();
1331  __beg = _M_extract_via_format(__beg, __end, __io, __err,
1332  __tm, __times[0], __state);
1333  __state._M_finalize_state(__tm);
1334  if (__beg == __end)
1335  __err |= ios_base::eofbit;
1336  return __beg;
1337  }
1338 
1339  template<typename _CharT, typename _InIter>
1340  _InIter
1342  do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1343  ios_base::iostate& __err, tm* __tm) const
1344  {
1345  const locale& __loc = __io._M_getloc();
1346  const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1347  const char_type* __dates[2];
1348  __tp._M_date_formats(__dates);
1349  __time_get_state __state = __time_get_state();
1350  __beg = _M_extract_via_format(__beg, __end, __io, __err,
1351  __tm, __dates[0], __state);
1352  __state._M_finalize_state(__tm);
1353  if (__beg == __end)
1354  __err |= ios_base::eofbit;
1355  return __beg;
1356  }
1357 
1358  template<typename _CharT, typename _InIter>
1359  _InIter
1361  do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1362  ios_base::iostate& __err, tm* __tm) const
1363  {
1364  const locale& __loc = __io._M_getloc();
1365  const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1366  const char_type* __days[14];
1367  __tp._M_days_abbreviated(__days);
1368  __tp._M_days(__days + 7);
1369  int __tmpwday;
1370  ios_base::iostate __tmperr = ios_base::goodbit;
1371 
1372  __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
1373  __io, __tmperr);
1374  if (!__tmperr)
1375  __tm->tm_wday = __tmpwday;
1376  else
1377  __err |= ios_base::failbit;
1378 
1379  if (__beg == __end)
1380  __err |= ios_base::eofbit;
1381  return __beg;
1382  }
1383 
1384  template<typename _CharT, typename _InIter>
1385  _InIter
1388  ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1389  {
1390  const locale& __loc = __io._M_getloc();
1391  const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1392  const char_type* __months[24];
1393  __tp._M_months_abbreviated(__months);
1394  __tp._M_months(__months + 12);
1395  int __tmpmon;
1396  ios_base::iostate __tmperr = ios_base::goodbit;
1397 
1398  __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
1399  __io, __tmperr);
1400  if (!__tmperr)
1401  __tm->tm_mon = __tmpmon;
1402  else
1403  __err |= ios_base::failbit;
1404 
1405  if (__beg == __end)
1406  __err |= ios_base::eofbit;
1407  return __beg;
1408  }
1409 
1410  template<typename _CharT, typename _InIter>
1411  _InIter
1413  do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1414  ios_base::iostate& __err, tm* __tm) const
1415  {
1416  int __tmpyear;
1417  ios_base::iostate __tmperr = ios_base::goodbit;
1418  const locale& __loc = __io._M_getloc();
1419  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1420 
1421  __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 99, 2,
1422  __io, __tmperr);
1423  if (!__tmperr)
1424  {
1425  char __c = 0;
1426  if (__beg != __end)
1427  __c = __ctype.narrow(*__beg, '*');
1428  // For 1-2 digit year, assume 69-99 is 1969-1999, 0-68 is 2000-2068.
1429  // For 3-4 digit year, use it as year.
1430  // __tm->tm_year needs year - 1900 though.
1431  if (__c >= '0' && __c <= '9')
1432  {
1433  ++__beg;
1434  __tmpyear = __tmpyear * 10 + (__c - '0');
1435  if (__beg != __end)
1436  {
1437  __c = __ctype.narrow(*__beg, '*');
1438  if (__c >= '0' && __c <= '9')
1439  {
1440  ++__beg;
1441  __tmpyear = __tmpyear * 10 + (__c - '0');
1442  }
1443  }
1444  __tmpyear -= 1900;
1445  }
1446  else if (__tmpyear < 69)
1447  __tmpyear += 100;
1448  __tm->tm_year = __tmpyear;
1449  }
1450  else
1451  __err |= ios_base::failbit;
1452 
1453  if (__beg == __end)
1454  __err |= ios_base::eofbit;
1455  return __beg;
1456  }
1457 
1458 #if __cplusplus >= 201103L
1459  template<typename _CharT, typename _InIter>
1460  inline
1461  _InIter
1463  get(iter_type __s, iter_type __end, ios_base& __io,
1464  ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
1465  const char_type* __fmtend) const
1466  {
1467  const locale& __loc = __io._M_getloc();
1468  ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1469  __err = ios_base::goodbit;
1470  bool __use_state = false;
1471 #if __GNUC__ >= 5
1472 #pragma GCC diagnostic push
1473 #pragma GCC diagnostic ignored "-Wpmf-conversions"
1474  // Nasty hack. The C++ standard mandates that get invokes the do_get
1475  // virtual method, but unfortunately at least without an ABI change
1476  // for the facets we can't keep state across the different do_get
1477  // calls. So e.g. if __fmt is "%p %I:%M:%S", we can't handle it
1478  // properly, because we first handle the %p am/pm specifier and only
1479  // later the 12-hour format specifier.
1480  if ((void*)(this->*(&time_get::do_get)) == (void*)(&time_get::do_get))
1481  __use_state = true;
1482 #pragma GCC diagnostic pop
1483 #endif
1484  __time_get_state __state = __time_get_state();
1485  while (__fmt != __fmtend &&
1486  __err == ios_base::goodbit)
1487  {
1488  if (__s == __end)
1489  {
1491  break;
1492  }
1493  else if (__ctype.narrow(*__fmt, 0) == '%')
1494  {
1495  const char_type* __fmt_start = __fmt;
1496  char __format;
1497  char __mod = 0;
1498  if (++__fmt == __fmtend)
1499  {
1500  __err = ios_base::failbit;
1501  break;
1502  }
1503  const char __c = __ctype.narrow(*__fmt, 0);
1504  if (__c != 'E' && __c != 'O')
1505  __format = __c;
1506  else if (++__fmt != __fmtend)
1507  {
1508  __mod = __c;
1509  __format = __ctype.narrow(*__fmt, 0);
1510  }
1511  else
1512  {
1513  __err = ios_base::failbit;
1514  break;
1515  }
1516  if (__use_state)
1517  {
1518  char_type __new_fmt[4];
1519  __new_fmt[0] = __fmt_start[0];
1520  __new_fmt[1] = __fmt_start[1];
1521  if (__mod)
1522  {
1523  __new_fmt[2] = __fmt_start[2];
1524  __new_fmt[3] = char_type();
1525  }
1526  else
1527  __new_fmt[2] = char_type();
1528  __s = _M_extract_via_format(__s, __end, __io, __err, __tm,
1529  __new_fmt, __state);
1530  if (__s == __end)
1531  __err |= ios_base::eofbit;
1532  }
1533  else
1534  __s = this->do_get(__s, __end, __io, __err, __tm, __format,
1535  __mod);
1536  ++__fmt;
1537  }
1538  else if (__ctype.is(ctype_base::space, *__fmt))
1539  {
1540  ++__fmt;
1541  while (__fmt != __fmtend &&
1542  __ctype.is(ctype_base::space, *__fmt))
1543  ++__fmt;
1544 
1545  while (__s != __end &&
1546  __ctype.is(ctype_base::space, *__s))
1547  ++__s;
1548  }
1549  // TODO real case-insensitive comparison
1550  else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
1551  __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
1552  {
1553  ++__s;
1554  ++__fmt;
1555  }
1556  else
1557  {
1558  __err = ios_base::failbit;
1559  break;
1560  }
1561  }
1562  if (__use_state)
1563  __state._M_finalize_state(__tm);
1564  return __s;
1565  }
1566 
1567  template<typename _CharT, typename _InIter>
1568  inline
1569  _InIter
1571  do_get(iter_type __beg, iter_type __end, ios_base& __io,
1572  ios_base::iostate& __err, tm* __tm,
1573  char __format, char __mod) const
1574  {
1575  const locale& __loc = __io._M_getloc();
1576  ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1577  __err = ios_base::goodbit;
1578 
1579  char_type __fmt[4];
1580  __fmt[0] = __ctype.widen('%');
1581  if (!__mod)
1582  {
1583  __fmt[1] = __format;
1584  __fmt[2] = char_type();
1585  }
1586  else
1587  {
1588  __fmt[1] = __mod;
1589  __fmt[2] = __format;
1590  __fmt[3] = char_type();
1591  }
1592 
1593  __time_get_state __state = __time_get_state();
1594  __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt,
1595  __state);
1596  __state._M_finalize_state(__tm);
1597  if (__beg == __end)
1598  __err |= ios_base::eofbit;
1599  return __beg;
1600  }
1601 
1602 #endif // __cplusplus >= 201103L
1603 
1604  template<typename _CharT, typename _OutIter>
1605  _OutIter
1607  put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1608  const _CharT* __beg, const _CharT* __end) const
1609  {
1610  const locale& __loc = __io._M_getloc();
1611  ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1612  for (; __beg != __end; ++__beg)
1613  if (__ctype.narrow(*__beg, 0) != '%')
1614  {
1615  *__s = *__beg;
1616  ++__s;
1617  }
1618  else if (++__beg != __end)
1619  {
1620  char __format;
1621  char __mod = 0;
1622  const char __c = __ctype.narrow(*__beg, 0);
1623  if (__c != 'E' && __c != 'O')
1624  __format = __c;
1625  else if (++__beg != __end)
1626  {
1627  __mod = __c;
1628  __format = __ctype.narrow(*__beg, 0);
1629  }
1630  else
1631  break;
1632  __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1633  }
1634  else
1635  break;
1636  return __s;
1637  }
1638 
1639  template<typename _CharT, typename _OutIter>
1640  _OutIter
1642  do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1643  char __format, char __mod) const
1644  {
1645  const locale& __loc = __io._M_getloc();
1646  ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1647  __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1648 
1649  // NB: This size is arbitrary. Should this be a data member,
1650  // initialized at construction?
1651  const size_t __maxlen = 128;
1652  char_type __res[__maxlen];
1653 
1654  // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1655  // is possible that the format character will be longer than one
1656  // character. Possibilities include 'E' or 'O' followed by a
1657  // format character: if __mod is not the default argument, assume
1658  // it's a valid modifier.
1659  char_type __fmt[4];
1660  __fmt[0] = __ctype.widen('%');
1661  if (!__mod)
1662  {
1663  __fmt[1] = __format;
1664  __fmt[2] = char_type();
1665  }
1666  else
1667  {
1668  __fmt[1] = __mod;
1669  __fmt[2] = __format;
1670  __fmt[3] = char_type();
1671  }
1672 
1673  __tp._M_put(__res, __maxlen, __fmt, __tm);
1674 
1675  // Write resulting, fully-formatted string to output iterator.
1676  return std::__write(__s, __res, char_traits<char_type>::length(__res));
1677  }
1678 
1679 
1680  // Inhibit implicit instantiations for required instantiations,
1681  // which are defined via explicit instantiations elsewhere.
1682 #if _GLIBCXX_EXTERN_TEMPLATE
1683  extern template class moneypunct<char, false>;
1684  extern template class moneypunct<char, true>;
1685  extern template class moneypunct_byname<char, false>;
1686  extern template class moneypunct_byname<char, true>;
1687  extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
1688  extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
1689  extern template class __timepunct<char>;
1690  extern template class time_put<char>;
1691  extern template class time_put_byname<char>;
1692  extern template class time_get<char>;
1693  extern template class time_get_byname<char>;
1694  extern template class messages<char>;
1695  extern template class messages_byname<char>;
1696 
1697  extern template
1698  const moneypunct<char, true>&
1699  use_facet<moneypunct<char, true> >(const locale&);
1700 
1701  extern template
1703  use_facet<moneypunct<char, false> >(const locale&);
1704 
1705  extern template
1706  const money_put<char>&
1707  use_facet<money_put<char> >(const locale&);
1708 
1709  extern template
1710  const money_get<char>&
1711  use_facet<money_get<char> >(const locale&);
1712 
1713  extern template
1714  const __timepunct<char>&
1715  use_facet<__timepunct<char> >(const locale&);
1716 
1717  extern template
1718  const time_put<char>&
1719  use_facet<time_put<char> >(const locale&);
1720 
1721  extern template
1722  const time_get<char>&
1723  use_facet<time_get<char> >(const locale&);
1724 
1725  extern template
1726  const messages<char>&
1727  use_facet<messages<char> >(const locale&);
1728 
1729  extern template
1730  bool
1731  has_facet<moneypunct<char> >(const locale&);
1732 
1733  extern template
1734  bool
1735  has_facet<money_put<char> >(const locale&);
1736 
1737  extern template
1738  bool
1739  has_facet<money_get<char> >(const locale&);
1740 
1741  extern template
1742  bool
1743  has_facet<__timepunct<char> >(const locale&);
1744 
1745  extern template
1746  bool
1747  has_facet<time_put<char> >(const locale&);
1748 
1749  extern template
1750  bool
1751  has_facet<time_get<char> >(const locale&);
1752 
1753  extern template
1754  bool
1755  has_facet<messages<char> >(const locale&);
1756 
1757 #ifdef _GLIBCXX_USE_WCHAR_T
1758  extern template class moneypunct<wchar_t, false>;
1759  extern template class moneypunct<wchar_t, true>;
1760  extern template class moneypunct_byname<wchar_t, false>;
1761  extern template class moneypunct_byname<wchar_t, true>;
1762  extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
1763  extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
1764  extern template class __timepunct<wchar_t>;
1765  extern template class time_put<wchar_t>;
1766  extern template class time_put_byname<wchar_t>;
1767  extern template class time_get<wchar_t>;
1768  extern template class time_get_byname<wchar_t>;
1769  extern template class messages<wchar_t>;
1770  extern template class messages_byname<wchar_t>;
1771 
1772  extern template
1774  use_facet<moneypunct<wchar_t, true> >(const locale&);
1775 
1776  extern template
1778  use_facet<moneypunct<wchar_t, false> >(const locale&);
1779 
1780  extern template
1781  const money_put<wchar_t>&
1782  use_facet<money_put<wchar_t> >(const locale&);
1783 
1784  extern template
1785  const money_get<wchar_t>&
1786  use_facet<money_get<wchar_t> >(const locale&);
1787 
1788  extern template
1789  const __timepunct<wchar_t>&
1790  use_facet<__timepunct<wchar_t> >(const locale&);
1791 
1792  extern template
1793  const time_put<wchar_t>&
1794  use_facet<time_put<wchar_t> >(const locale&);
1795 
1796  extern template
1797  const time_get<wchar_t>&
1798  use_facet<time_get<wchar_t> >(const locale&);
1799 
1800  extern template
1801  const messages<wchar_t>&
1802  use_facet<messages<wchar_t> >(const locale&);
1803 
1804  extern template
1805  bool
1806  has_facet<moneypunct<wchar_t> >(const locale&);
1807 
1808  extern template
1809  bool
1810  has_facet<money_put<wchar_t> >(const locale&);
1811 
1812  extern template
1813  bool
1814  has_facet<money_get<wchar_t> >(const locale&);
1815 
1816  extern template
1817  bool
1818  has_facet<__timepunct<wchar_t> >(const locale&);
1819 
1820  extern template
1821  bool
1822  has_facet<time_put<wchar_t> >(const locale&);
1823 
1824  extern template
1825  bool
1826  has_facet<time_get<wchar_t> >(const locale&);
1827 
1828  extern template
1829  bool
1830  has_facet<messages<wchar_t> >(const locale&);
1831 #endif
1832 #endif
1833 
1834 _GLIBCXX_END_NAMESPACE_VERSION
1835 } // namespace std
1836 
1837 #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.
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:2204
void resize(size_type __n, _CharT __c)
Resizes the string to the specified number of characters.
Definition: cow_string.h:3568
static const size_type npos
Value returned by various member functions when they fail.
Definition: cow_string.h:326
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].