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
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
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
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
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
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.
char_type widen(char __c) const
Widen char to char_type.
bool is(mask __m, char_type __c) const
Test char_type classification.
_Ios_Fmtflags fmtflags
This is a bitmask type.
Definition: ios_base.h:378
char narrow(char_type __c, char __dfault) const
Narrow char_type to char.
class time_put_byname [22.2.5.4].
Primary class template time_get.This facet encapsulates the code to parse and return a date or time f...
static const fmtflags adjustfield
A mask of left|right|internal. Useful for the 2-arg form of setf.
Definition: ios_base.h:433
Basis for explicit traits specializations.
Definition: char_traits.h:325
class moneypunct_byname [22.2.6.4].
static const iostate eofbit
Indicates that an input operation reached the end of an input sequence.
Definition: ios_base.h:460
Primary class template time_put.This facet encapsulates the code to format and output dates and times...
_CharT char_type
Public typedefs.
static const size_type npos
Value returned by various member functions when they fail.
Definition: cow_string.h:322
void resize(size_type __n, _CharT __c)
Resizes the string to the specified number of characters.
Definition: cow_string.h:3801
class messages_byname [22.2.7.2].
_OutIter iter_type
Public typedefs.
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.
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.
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:234
Primary class template money_put.This facet encapsulates the code to format and output a monetary amo...
char_type toupper(char_type __c) const
Convert to uppercase.
Primary class template ctype facet.This template class defines classification and conversion function...
Primary class template moneypunct.This facet encapsulates the punctuation, grouping and other formatt...
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.
virtual dateorder do_date_order() const
Return preferred order of month, day, and year.
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.
_InIter iter_type
Public typedefs.
char_type tolower(char_type __c) const
Convert to lowercase.
Primary class template messages.This facet encapsulates the code to retrieve messages from message ca...
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 iostate goodbit
Indicates all is well.
Definition: ios_base.h:468
_Ios_Iostate iostate
This is a bitmask type.
Definition: ios_base.h:453
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.
_OutIter iter_type
Public typedefs.
Container class for localization functionality.The locale class is first a class wrapper for C librar...
_CharT char_type
Public typedefs.
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
locale getloc() const
Locale access.
Definition: ios_base.h:841
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.
_CharT char_type
Public typedefs.
const locale & _M_getloc() const
Locale access.
Definition: ios_base.h:852
ISO C++ entities toplevel namespace is std.
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.
static const fmtflags left
Adds fill characters on the right (final positions) of certain generated output. (I.e., the thing you print is flush left.)
Definition: ios_base.h:399
The base of the I/O class hierarchy.This class defines everything that can be defined about I/O that ...
Definition: ios_base.h:265
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
Definition: range_access.h:274
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.
const _CharT * c_str() const noexcept
Return const pointer to null-terminated contents.
Definition: cow_string.h:2376
_InIter iter_type
Public typedefs.
static const fmtflags showbase
Generates a prefix indicating the numeric base of generated integer output.
Definition: ios_base.h:413
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.
static locale::id id
Numpunct facet id.
class time_get_byname [22.2.5.2].
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.
Primary class template money_get.This facet encapsulates the code to parse and return a monetary amou...