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