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  _InIter
1044  time_get<_CharT, _InIter>::
1045  _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
1046  ios_base::iostate& __err, tm* __tm,
1047  const _CharT* __format) const
1048  {
1049  __time_get_state __state = __time_get_state();
1050  return _M_extract_via_format(__beg, __end, __io, __err, __tm,
1051  __format, __state);
1052  }
1053 
1054  template<typename _CharT, typename _InIter>
1055  _InIter
1056  time_get<_CharT, _InIter>::
1057  _M_extract_num(iter_type __beg, iter_type __end, int& __member,
1058  int __min, int __max, size_t __len,
1059  ios_base& __io, ios_base::iostate& __err) const
1060  {
1061  const locale& __loc = __io._M_getloc();
1062  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1063 
1064  size_t __i = 0;
1065  int __value = 0;
1066  for (; __beg != __end && __i < __len; ++__beg, (void)++__i)
1067  {
1068  const char __c = __ctype.narrow(*__beg, '*');
1069  if (__c >= '0' && __c <= '9')
1070  {
1071  __value = __value * 10 + (__c - '0');
1072  if (__value > __max)
1073  break;
1074  }
1075  else
1076  break;
1077  }
1078  if (__i && __value >= __min && __value <= __max)
1079  __member = __value;
1080  else
1081  __err |= ios_base::failbit;
1082 
1083  return __beg;
1084  }
1085 
1086  // Assumptions:
1087  // All elements in __names are unique, except if __indexlen is
1088  // even __names in the first half could be the same as corresponding
1089  // __names in the second half (May is abbreviated as May). Some __names
1090  // elements could be prefixes of other __names elements.
1091  template<typename _CharT, typename _InIter>
1092  _InIter
1093  time_get<_CharT, _InIter>::
1094  _M_extract_name(iter_type __beg, iter_type __end, int& __member,
1095  const _CharT** __names, size_t __indexlen,
1096  ios_base& __io, ios_base::iostate& __err) const
1097  {
1098  typedef char_traits<_CharT> __traits_type;
1099  const locale& __loc = __io._M_getloc();
1100  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1101 
1102  size_t* __matches
1103  = static_cast<size_t*>(__builtin_alloca(2 * sizeof(size_t)
1104  * __indexlen));
1105  size_t* __lengths = __matches + __indexlen;
1106  size_t __nmatches = 0;
1107  size_t __pos = 0;
1108  bool __testvalid = true;
1109  const char_type* __name;
1110  bool __begupdated = false;
1111 
1112  // Look for initial matches.
1113  if (__beg != __end)
1114  {
1115  const char_type __c = *__beg;
1116  // TODO real case-insensitive comparison
1117  const char_type __cl = __ctype.tolower(__c);
1118  const char_type __cu = __ctype.toupper(__c);
1119  for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1120  if (__cl == __ctype.tolower(__names[__i1][0])
1121  || __cu == __ctype.toupper(__names[__i1][0]))
1122  {
1123  __lengths[__nmatches]
1124  = __traits_type::length(__names[__i1]);
1125  __matches[__nmatches++] = __i1;
1126  }
1127  }
1128 
1129  while (__nmatches > 1)
1130  {
1131  // Find smallest matching string.
1132  size_t __minlen = __lengths[0];
1133  for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
1134  __minlen = std::min(__minlen, __lengths[__i2]);
1135  ++__pos;
1136  ++__beg;
1137  if (__pos == __minlen)
1138  {
1139  // If some match has remaining length of 0,
1140  // need to decide if any match with remaining
1141  // length non-zero matches the next character.
1142  // If so, remove all matches with remaining length
1143  // 0 from consideration, otherwise keep only matches
1144  // with remaining length 0.
1145  bool __match_longer = false;
1146 
1147  if (__beg != __end)
1148  {
1149  // TODO real case-insensitive comparison
1150  const char_type __cl = __ctype.tolower(*__beg);
1151  const char_type __cu = __ctype.toupper(*__beg);
1152  for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1153  {
1154  __name = __names[__matches[__i3]];
1155  if (__lengths[__i3] > __pos
1156  && (__ctype.tolower(__name[__pos]) == __cl
1157  || __ctype.toupper(__name[__pos]) == __cu))
1158  {
1159  __match_longer = true;
1160  break;
1161  }
1162  }
1163  }
1164  for (size_t __i4 = 0; __i4 < __nmatches;)
1165  if (__match_longer == (__lengths[__i4] == __pos))
1166  {
1167  __matches[__i4] = __matches[--__nmatches];
1168  __lengths[__i4] = __lengths[__nmatches];
1169  }
1170  else
1171  ++__i4;
1172  if (__match_longer)
1173  {
1174  __minlen = __lengths[0];
1175  for (size_t __i5 = 1; __i5 < __nmatches; ++__i5)
1176  __minlen = std::min(__minlen, __lengths[__i5]);
1177  }
1178  else
1179  {
1180  // Deal with May being full as well as abbreviated month
1181  // name. Pick the smaller index.
1182  if (__nmatches == 2 && (__indexlen & 1) == 0)
1183  {
1184  if (__matches[0] < __indexlen / 2)
1185  {
1186  if (__matches[1] == __matches[0] + __indexlen / 2)
1187  __nmatches = 1;
1188  }
1189  else if (__matches[1] == __matches[0] - __indexlen / 2)
1190  {
1191  __matches[0] = __matches[1];
1192  __lengths[0] = __lengths[1];
1193  __nmatches = 1;
1194  }
1195  }
1196  __begupdated = true;
1197  break;
1198  }
1199  }
1200  if (__pos < __minlen && __beg != __end)
1201  {
1202  // TODO real case-insensitive comparison
1203  const char_type __cl = __ctype.tolower(*__beg);
1204  const char_type __cu = __ctype.toupper(*__beg);
1205  for (size_t __i6 = 0; __i6 < __nmatches;)
1206  {
1207  __name = __names[__matches[__i6]];
1208  if (__ctype.tolower(__name[__pos]) != __cl
1209  && __ctype.toupper(__name[__pos]) != __cu)
1210  {
1211  __matches[__i6] = __matches[--__nmatches];
1212  __lengths[__i6] = __lengths[__nmatches];
1213  }
1214  else
1215  ++__i6;
1216  }
1217  }
1218  else
1219  break;
1220  }
1221 
1222  if (__nmatches == 1)
1223  {
1224  // Make sure found name is completely extracted.
1225  if (!__begupdated)
1226  {
1227  ++__beg;
1228  ++__pos;
1229  }
1230  __name = __names[__matches[0]];
1231  const size_t __len = __lengths[0];
1232  while (__pos < __len
1233  && __beg != __end
1234  // TODO real case-insensitive comparison
1235  && (__ctype.tolower(__name[__pos]) == __ctype.tolower(*__beg)
1236  || (__ctype.toupper(__name[__pos])
1237  == __ctype.toupper(*__beg))))
1238  ++__beg, (void)++__pos;
1239 
1240  if (__len == __pos)
1241  __member = __matches[0];
1242  else
1243  __testvalid = false;
1244  }
1245  else
1246  __testvalid = false;
1247  if (!__testvalid)
1248  __err |= ios_base::failbit;
1249 
1250  return __beg;
1251  }
1252 
1253  template<typename _CharT, typename _InIter>
1254  _InIter
1255  time_get<_CharT, _InIter>::
1256  _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
1257  const _CharT** __names, size_t __indexlen,
1258  ios_base& __io, ios_base::iostate& __err) const
1259  {
1260  typedef char_traits<_CharT> __traits_type;
1261  const locale& __loc = __io._M_getloc();
1262  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1263 
1264  int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
1265  * __indexlen));
1266  size_t __nmatches = 0;
1267  size_t* __matches_lengths = 0;
1268  size_t __pos = 0;
1269 
1270  if (__beg != __end)
1271  {
1272  const char_type __c = *__beg;
1273  for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
1274  if (__c == __names[__i][0]
1275  || __c == __ctype.toupper(__names[__i][0]))
1276  __matches[__nmatches++] = __i;
1277  }
1278 
1279  if (__nmatches)
1280  {
1281  ++__beg;
1282  ++__pos;
1283 
1284  __matches_lengths
1285  = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
1286  * __nmatches));
1287  for (size_t __i = 0; __i < __nmatches; ++__i)
1288  __matches_lengths[__i]
1289  = __traits_type::length(__names[__matches[__i]]);
1290  }
1291 
1292  for (; __beg != __end; ++__beg, (void)++__pos)
1293  {
1294  size_t __nskipped = 0;
1295  const char_type __c = *__beg;
1296  for (size_t __i = 0; __i < __nmatches;)
1297  {
1298  const char_type* __name = __names[__matches[__i]];
1299  if (__pos >= __matches_lengths[__i])
1300  ++__nskipped, ++__i;
1301  else if (!(__name[__pos] == __c))
1302  {
1303  --__nmatches;
1304  __matches[__i] = __matches[__nmatches];
1305  __matches_lengths[__i] = __matches_lengths[__nmatches];
1306  }
1307  else
1308  ++__i;
1309  }
1310  if (__nskipped == __nmatches)
1311  break;
1312  }
1313 
1314  if ((__nmatches == 1 && __matches_lengths[0] == __pos)
1315  || (__nmatches == 2 && (__matches_lengths[0] == __pos
1316  || __matches_lengths[1] == __pos)))
1317  __member = (__matches[0] >= (int)__indexlen
1318  ? __matches[0] - (int)__indexlen : __matches[0]);
1319  else
1320  __err |= ios_base::failbit;
1321 
1322  return __beg;
1323  }
1324 
1325  template<typename _CharT, typename _InIter>
1326  _InIter
1328  do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1329  ios_base::iostate& __err, tm* __tm) const
1330  {
1331  const locale& __loc = __io._M_getloc();
1332  const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1333  const char_type* __times[2];
1334  __tp._M_time_formats(__times);
1335  __time_get_state __state = __time_get_state();
1336  __beg = _M_extract_via_format(__beg, __end, __io, __err,
1337  __tm, __times[0], __state);
1338  __state._M_finalize_state(__tm);
1339  if (__beg == __end)
1340  __err |= ios_base::eofbit;
1341  return __beg;
1342  }
1343 
1344  template<typename _CharT, typename _InIter>
1345  _InIter
1347  do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1348  ios_base::iostate& __err, tm* __tm) const
1349  {
1350  const locale& __loc = __io._M_getloc();
1351  const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1352  const char_type* __dates[2];
1353  __tp._M_date_formats(__dates);
1354  __time_get_state __state = __time_get_state();
1355  __beg = _M_extract_via_format(__beg, __end, __io, __err,
1356  __tm, __dates[0], __state);
1357  __state._M_finalize_state(__tm);
1358  if (__beg == __end)
1359  __err |= ios_base::eofbit;
1360  return __beg;
1361  }
1362 
1363  template<typename _CharT, typename _InIter>
1364  _InIter
1366  do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1367  ios_base::iostate& __err, tm* __tm) const
1368  {
1369  const locale& __loc = __io._M_getloc();
1370  const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1371  const char_type* __days[14];
1372  __tp._M_days_abbreviated(__days);
1373  __tp._M_days(__days + 7);
1374  int __tmpwday;
1375  ios_base::iostate __tmperr = ios_base::goodbit;
1376 
1377  __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
1378  __io, __tmperr);
1379  if (!__tmperr)
1380  __tm->tm_wday = __tmpwday;
1381  else
1382  __err |= ios_base::failbit;
1383 
1384  if (__beg == __end)
1385  __err |= ios_base::eofbit;
1386  return __beg;
1387  }
1388 
1389  template<typename _CharT, typename _InIter>
1390  _InIter
1393  ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1394  {
1395  const locale& __loc = __io._M_getloc();
1396  const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1397  const char_type* __months[24];
1398  __tp._M_months_abbreviated(__months);
1399  __tp._M_months(__months + 12);
1400  int __tmpmon;
1401  ios_base::iostate __tmperr = ios_base::goodbit;
1402 
1403  __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
1404  __io, __tmperr);
1405  if (!__tmperr)
1406  __tm->tm_mon = __tmpmon;
1407  else
1408  __err |= ios_base::failbit;
1409 
1410  if (__beg == __end)
1411  __err |= ios_base::eofbit;
1412  return __beg;
1413  }
1414 
1415  template<typename _CharT, typename _InIter>
1416  _InIter
1418  do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1419  ios_base::iostate& __err, tm* __tm) const
1420  {
1421  int __tmpyear;
1422  ios_base::iostate __tmperr = ios_base::goodbit;
1423  const locale& __loc = __io._M_getloc();
1424  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1425 
1426  __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 99, 2,
1427  __io, __tmperr);
1428  if (!__tmperr)
1429  {
1430  char __c = 0;
1431  if (__beg != __end)
1432  __c = __ctype.narrow(*__beg, '*');
1433  // For 1-2 digit year, assume 69-99 is 1969-1999, 0-68 is 2000-2068.
1434  // For 3-4 digit year, use it as year.
1435  // __tm->tm_year needs year - 1900 though.
1436  if (__c >= '0' && __c <= '9')
1437  {
1438  ++__beg;
1439  __tmpyear = __tmpyear * 10 + (__c - '0');
1440  if (__beg != __end)
1441  {
1442  __c = __ctype.narrow(*__beg, '*');
1443  if (__c >= '0' && __c <= '9')
1444  {
1445  ++__beg;
1446  __tmpyear = __tmpyear * 10 + (__c - '0');
1447  }
1448  }
1449  __tmpyear -= 1900;
1450  }
1451  else if (__tmpyear < 69)
1452  __tmpyear += 100;
1453  __tm->tm_year = __tmpyear;
1454  }
1455  else
1456  __err |= ios_base::failbit;
1457 
1458  if (__beg == __end)
1459  __err |= ios_base::eofbit;
1460  return __beg;
1461  }
1462 
1463 #if __cplusplus >= 201103L
1464  template<typename _CharT, typename _InIter>
1465  inline
1466  _InIter
1468  get(iter_type __s, iter_type __end, ios_base& __io,
1469  ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
1470  const char_type* __fmtend) const
1471  {
1472  const locale& __loc = __io._M_getloc();
1473  ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1474  __err = ios_base::goodbit;
1475  bool __use_state = false;
1476 #if __GNUC__ >= 5 && !defined(_GLIBCXX_CLANG)
1477 #pragma GCC diagnostic push
1478 #pragma GCC diagnostic ignored "-Wpmf-conversions"
1479  // Nasty hack. The C++ standard mandates that get invokes the do_get
1480  // virtual method, but unfortunately at least without an ABI change
1481  // for the facets we can't keep state across the different do_get
1482  // calls. So e.g. if __fmt is "%p %I:%M:%S", we can't handle it
1483  // properly, because we first handle the %p am/pm specifier and only
1484  // later the 12-hour format specifier.
1485  if ((void*)(this->*(&time_get::do_get)) == (void*)(&time_get::do_get))
1486  __use_state = true;
1487 #pragma GCC diagnostic pop
1488 #endif
1489  __time_get_state __state = __time_get_state();
1490  while (__fmt != __fmtend &&
1491  __err == ios_base::goodbit)
1492  {
1493  if (__s == __end)
1494  {
1496  break;
1497  }
1498  else if (__ctype.narrow(*__fmt, 0) == '%')
1499  {
1500  const char_type* __fmt_start = __fmt;
1501  char __format;
1502  char __mod = 0;
1503  if (++__fmt == __fmtend)
1504  {
1505  __err = ios_base::failbit;
1506  break;
1507  }
1508  const char __c = __ctype.narrow(*__fmt, 0);
1509  if (__c != 'E' && __c != 'O')
1510  __format = __c;
1511  else if (++__fmt != __fmtend)
1512  {
1513  __mod = __c;
1514  __format = __ctype.narrow(*__fmt, 0);
1515  }
1516  else
1517  {
1518  __err = ios_base::failbit;
1519  break;
1520  }
1521  if (__use_state)
1522  {
1523  char_type __new_fmt[4];
1524  __new_fmt[0] = __fmt_start[0];
1525  __new_fmt[1] = __fmt_start[1];
1526  if (__mod)
1527  {
1528  __new_fmt[2] = __fmt_start[2];
1529  __new_fmt[3] = char_type();
1530  }
1531  else
1532  __new_fmt[2] = char_type();
1533  __s = _M_extract_via_format(__s, __end, __io, __err, __tm,
1534  __new_fmt, __state);
1535  if (__s == __end)
1536  __err |= ios_base::eofbit;
1537  }
1538  else
1539  __s = this->do_get(__s, __end, __io, __err, __tm, __format,
1540  __mod);
1541  ++__fmt;
1542  }
1543  else if (__ctype.is(ctype_base::space, *__fmt))
1544  {
1545  ++__fmt;
1546  while (__fmt != __fmtend &&
1547  __ctype.is(ctype_base::space, *__fmt))
1548  ++__fmt;
1549 
1550  while (__s != __end &&
1551  __ctype.is(ctype_base::space, *__s))
1552  ++__s;
1553  }
1554  // TODO real case-insensitive comparison
1555  else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
1556  __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
1557  {
1558  ++__s;
1559  ++__fmt;
1560  }
1561  else
1562  {
1563  __err = ios_base::failbit;
1564  break;
1565  }
1566  }
1567  if (__use_state)
1568  __state._M_finalize_state(__tm);
1569  return __s;
1570  }
1571 
1572  template<typename _CharT, typename _InIter>
1573  inline
1574  _InIter
1576  do_get(iter_type __beg, iter_type __end, ios_base& __io,
1577  ios_base::iostate& __err, tm* __tm,
1578  char __format, char __mod) const
1579  {
1580  const locale& __loc = __io._M_getloc();
1581  ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1582  __err = ios_base::goodbit;
1583 
1584  char_type __fmt[4];
1585  __fmt[0] = __ctype.widen('%');
1586  if (!__mod)
1587  {
1588  __fmt[1] = __format;
1589  __fmt[2] = char_type();
1590  }
1591  else
1592  {
1593  __fmt[1] = __mod;
1594  __fmt[2] = __format;
1595  __fmt[3] = char_type();
1596  }
1597 
1598  __time_get_state __state = __time_get_state();
1599  __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt,
1600  __state);
1601  __state._M_finalize_state(__tm);
1602  if (__beg == __end)
1603  __err |= ios_base::eofbit;
1604  return __beg;
1605  }
1606 
1607 #endif // __cplusplus >= 201103L
1608 
1609  template<typename _CharT, typename _OutIter>
1610  _OutIter
1612  put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1613  const _CharT* __beg, const _CharT* __end) const
1614  {
1615  const locale& __loc = __io._M_getloc();
1616  ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1617  for (; __beg != __end; ++__beg)
1618  if (__ctype.narrow(*__beg, 0) != '%')
1619  {
1620  *__s = *__beg;
1621  ++__s;
1622  }
1623  else if (++__beg != __end)
1624  {
1625  char __format;
1626  char __mod = 0;
1627  const char __c = __ctype.narrow(*__beg, 0);
1628  if (__c != 'E' && __c != 'O')
1629  __format = __c;
1630  else if (++__beg != __end)
1631  {
1632  __mod = __c;
1633  __format = __ctype.narrow(*__beg, 0);
1634  }
1635  else
1636  break;
1637  __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1638  }
1639  else
1640  break;
1641  return __s;
1642  }
1643 
1644  template<typename _CharT, typename _OutIter>
1645  _OutIter
1647  do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1648  char __format, char __mod) const
1649  {
1650  const locale& __loc = __io._M_getloc();
1651  ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1652  __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1653 
1654  // NB: This size is arbitrary. Should this be a data member,
1655  // initialized at construction?
1656  const size_t __maxlen = 128;
1657  char_type __res[__maxlen];
1658 
1659  // NB: In IEEE 1003.1-200x, and perhaps other locale models, it
1660  // is possible that the format character will be longer than one
1661  // character. Possibilities include 'E' or 'O' followed by a
1662  // format character: if __mod is not the default argument, assume
1663  // it's a valid modifier.
1664  char_type __fmt[4];
1665  __fmt[0] = __ctype.widen('%');
1666  if (!__mod)
1667  {
1668  __fmt[1] = __format;
1669  __fmt[2] = char_type();
1670  }
1671  else
1672  {
1673  __fmt[1] = __mod;
1674  __fmt[2] = __format;
1675  __fmt[3] = char_type();
1676  }
1677 
1678  __tp._M_put(__res, __maxlen, __fmt, __tm);
1679 
1680  // Write resulting, fully-formatted string to output iterator.
1681  return std::__write(__s, __res, char_traits<char_type>::length(__res));
1682  }
1683 
1684 
1685  // Inhibit implicit instantiations for required instantiations,
1686  // which are defined via explicit instantiations elsewhere.
1687 #if _GLIBCXX_EXTERN_TEMPLATE
1688 #pragma GCC diagnostic push
1689 #pragma GCC diagnostic ignored "-Wc++11-extensions" // extern template
1690 #pragma GCC diagnostic ignored "-Wlong-long"
1691  extern template class moneypunct<char, false>;
1692  extern template class moneypunct<char, true>;
1693  extern template class moneypunct_byname<char, false>;
1694  extern template class moneypunct_byname<char, true>;
1695  extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
1696  extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
1697  extern template class __timepunct<char>;
1698  extern template class time_put<char>;
1699  extern template class time_put_byname<char>;
1700  extern template class time_get<char>;
1701  extern template class time_get_byname<char>;
1702  extern template class messages<char>;
1703  extern template class messages_byname<char>;
1704 
1705  extern template
1706  const moneypunct<char, true>*
1707  __try_use_facet<moneypunct<char, true> >(const locale&) _GLIBCXX_NOTHROW;
1708 
1709  extern template
1711  __try_use_facet<moneypunct<char, false> >(const locale&) _GLIBCXX_NOTHROW;
1712 
1713  extern template
1714  const money_put<char>*
1715  __try_use_facet<money_put<char> >(const locale&) _GLIBCXX_NOTHROW;
1716 
1717  extern template
1718  const money_get<char>*
1719  __try_use_facet<money_get<char> >(const locale&) _GLIBCXX_NOTHROW;
1720 
1721  extern template
1722  const __timepunct<char>*
1723  __try_use_facet<__timepunct<char> >(const locale&) _GLIBCXX_NOTHROW;
1724 
1725  extern template
1726  const time_put<char>*
1727  __try_use_facet<time_put<char> >(const locale&) _GLIBCXX_NOTHROW;
1728 
1729  extern template
1730  const time_get<char>*
1731  __try_use_facet<time_get<char> >(const locale&) _GLIBCXX_NOTHROW;
1732 
1733  extern template
1734  const messages<char>*
1735  __try_use_facet<messages<char> >(const locale&) _GLIBCXX_NOTHROW;
1736 
1737  extern template
1738  const moneypunct<char, true>&
1739  use_facet<moneypunct<char, true> >(const locale&);
1740 
1741  extern template
1743  use_facet<moneypunct<char, false> >(const locale&);
1744 
1745  extern template
1746  const money_put<char>&
1747  use_facet<money_put<char> >(const locale&);
1748 
1749  extern template
1750  const money_get<char>&
1751  use_facet<money_get<char> >(const locale&);
1752 
1753  extern template
1754  const __timepunct<char>&
1755  use_facet<__timepunct<char> >(const locale&);
1756 
1757  extern template
1758  const time_put<char>&
1759  use_facet<time_put<char> >(const locale&);
1760 
1761  extern template
1762  const time_get<char>&
1763  use_facet<time_get<char> >(const locale&);
1764 
1765  extern template
1766  const messages<char>&
1767  use_facet<messages<char> >(const locale&);
1768 
1769  extern template
1770  bool
1771  has_facet<moneypunct<char> >(const locale&);
1772 
1773  extern template
1774  bool
1775  has_facet<money_put<char> >(const locale&);
1776 
1777  extern template
1778  bool
1779  has_facet<money_get<char> >(const locale&);
1780 
1781  extern template
1782  bool
1783  has_facet<__timepunct<char> >(const locale&);
1784 
1785  extern template
1786  bool
1787  has_facet<time_put<char> >(const locale&);
1788 
1789  extern template
1790  bool
1791  has_facet<time_get<char> >(const locale&);
1792 
1793  extern template
1794  bool
1795  has_facet<messages<char> >(const locale&);
1796 
1797 #ifdef _GLIBCXX_USE_WCHAR_T
1798  extern template class moneypunct<wchar_t, false>;
1799  extern template class moneypunct<wchar_t, true>;
1800  extern template class moneypunct_byname<wchar_t, false>;
1801  extern template class moneypunct_byname<wchar_t, true>;
1802  extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
1803  extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
1804  extern template class __timepunct<wchar_t>;
1805  extern template class time_put<wchar_t>;
1806  extern template class time_put_byname<wchar_t>;
1807  extern template class time_get<wchar_t>;
1808  extern template class time_get_byname<wchar_t>;
1809  extern template class messages<wchar_t>;
1810  extern template class messages_byname<wchar_t>;
1811 
1812  extern template
1814  __try_use_facet<moneypunct<wchar_t, true> >(const locale&) _GLIBCXX_NOTHROW;
1815 
1816  extern template
1818  __try_use_facet<moneypunct<wchar_t, false> >(const locale&) _GLIBCXX_NOTHROW;
1819 
1820  extern template
1821  const money_put<wchar_t>*
1822  __try_use_facet<money_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1823 
1824  extern template
1825  const money_get<wchar_t>*
1826  __try_use_facet<money_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1827 
1828  extern template
1829  const __timepunct<wchar_t>*
1830  __try_use_facet<__timepunct<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1831 
1832  extern template
1833  const time_put<wchar_t>*
1834  __try_use_facet<time_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1835 
1836  extern template
1837  const time_get<wchar_t>*
1838  __try_use_facet<time_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1839 
1840  extern template
1841  const messages<wchar_t>*
1842  __try_use_facet<messages<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
1843 
1844  extern template
1846  use_facet<moneypunct<wchar_t, true> >(const locale&);
1847 
1848  extern template
1850  use_facet<moneypunct<wchar_t, false> >(const locale&);
1851 
1852  extern template
1853  const money_put<wchar_t>&
1854  use_facet<money_put<wchar_t> >(const locale&);
1855 
1856  extern template
1857  const money_get<wchar_t>&
1858  use_facet<money_get<wchar_t> >(const locale&);
1859 
1860  extern template
1861  const __timepunct<wchar_t>&
1862  use_facet<__timepunct<wchar_t> >(const locale&);
1863 
1864  extern template
1865  const time_put<wchar_t>&
1866  use_facet<time_put<wchar_t> >(const locale&);
1867 
1868  extern template
1869  const time_get<wchar_t>&
1870  use_facet<time_get<wchar_t> >(const locale&);
1871 
1872  extern template
1873  const messages<wchar_t>&
1874  use_facet<messages<wchar_t> >(const locale&);
1875 
1876  extern template
1877  bool
1878  has_facet<moneypunct<wchar_t> >(const locale&);
1879 
1880  extern template
1881  bool
1882  has_facet<money_put<wchar_t> >(const locale&);
1883 
1884  extern template
1885  bool
1886  has_facet<money_get<wchar_t> >(const locale&);
1887 
1888  extern template
1889  bool
1890  has_facet<__timepunct<wchar_t> >(const locale&);
1891 
1892  extern template
1893  bool
1894  has_facet<time_put<wchar_t> >(const locale&);
1895 
1896  extern template
1897  bool
1898  has_facet<time_get<wchar_t> >(const locale&);
1899 
1900  extern template
1901  bool
1902  has_facet<messages<wchar_t> >(const locale&);
1903 #endif
1904 #pragma GCC diagnostic pop
1905 #endif
1906 
1907 _GLIBCXX_END_NAMESPACE_VERSION
1908 } // namespace std
1909 
1910 #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].