1 // Locale support -*- C++ -*-
3 // Copyright (C) 2007-2018 Free Software Foundation, Inc.
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)
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.
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.
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/>.
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}
30 #ifndef _LOCALE_FACETS_NONIO_TCC
31 #define _LOCALE_FACETS_NONIO_TCC 1
33 #pragma GCC system_header
35 namespace std _GLIBCXX_VISIBILITY(default)
37 _GLIBCXX_BEGIN_NAMESPACE_VERSION
39 template<typename _CharT, bool _Intl>
40 struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
42 const __moneypunct_cache<_CharT, _Intl>*
43 operator() (const locale& __loc) const
45 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
46 const locale::facet** __caches = __loc._M_impl->_M_caches;
49 __moneypunct_cache<_CharT, _Intl>* __tmp = 0;
52 __tmp = new __moneypunct_cache<_CharT, _Intl>;
53 __tmp->_M_cache(__loc);
58 __throw_exception_again;
60 __loc._M_impl->_M_install_cache(__tmp, __i);
63 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
67 template<typename _CharT, bool _Intl>
69 __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
71 const moneypunct<_CharT, _Intl>& __mp =
72 use_facet<moneypunct<_CharT, _Intl> >(__loc);
74 _M_decimal_point = __mp.decimal_point();
75 _M_thousands_sep = __mp.thousands_sep();
76 _M_frac_digits = __mp.frac_digits();
79 _CharT* __curr_symbol = 0;
80 _CharT* __positive_sign = 0;
81 _CharT* __negative_sign = 0;
84 const string& __g = __mp.grouping();
85 _M_grouping_size = __g.size();
86 __grouping = new char[_M_grouping_size];
87 __g.copy(__grouping, _M_grouping_size);
88 _M_use_grouping = (_M_grouping_size
89 && static_cast<signed char>(__grouping[0]) > 0
91 != __gnu_cxx::__numeric_traits<char>::__max));
93 const basic_string<_CharT>& __cs = __mp.curr_symbol();
94 _M_curr_symbol_size = __cs.size();
95 __curr_symbol = new _CharT[_M_curr_symbol_size];
96 __cs.copy(__curr_symbol, _M_curr_symbol_size);
98 const basic_string<_CharT>& __ps = __mp.positive_sign();
99 _M_positive_sign_size = __ps.size();
100 __positive_sign = new _CharT[_M_positive_sign_size];
101 __ps.copy(__positive_sign, _M_positive_sign_size);
103 const basic_string<_CharT>& __ns = __mp.negative_sign();
104 _M_negative_sign_size = __ns.size();
105 __negative_sign = new _CharT[_M_negative_sign_size];
106 __ns.copy(__negative_sign, _M_negative_sign_size);
108 _M_pos_format = __mp.pos_format();
109 _M_neg_format = __mp.neg_format();
111 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
112 __ct.widen(money_base::_S_atoms,
113 money_base::_S_atoms + money_base::_S_end, _M_atoms);
115 _M_grouping = __grouping;
116 _M_curr_symbol = __curr_symbol;
117 _M_positive_sign = __positive_sign;
118 _M_negative_sign = __negative_sign;
123 delete [] __grouping;
124 delete [] __curr_symbol;
125 delete [] __positive_sign;
126 delete [] __negative_sign;
127 __throw_exception_again;
131 _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
133 template<typename _CharT, typename _InIter>
136 money_get<_CharT, _InIter>::
137 _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
138 ios_base::iostate& __err, string& __units) const
140 typedef char_traits<_CharT> __traits_type;
141 typedef typename string_type::size_type size_type;
142 typedef money_base::part part;
143 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
145 const locale& __loc = __io._M_getloc();
146 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
148 __use_cache<__cache_type> __uc;
149 const __cache_type* __lc = __uc(__loc);
150 const char_type* __lit = __lc->_M_atoms;
153 bool __negative = false;
155 size_type __sign_size = 0;
156 // True if sign is mandatory.
157 const bool __mandatory_sign = (__lc->_M_positive_sign_size
158 && __lc->_M_negative_sign_size);
159 // String of grouping info from thousands_sep plucked from __units.
160 string __grouping_tmp;
161 if (__lc->_M_use_grouping)
162 __grouping_tmp.reserve(32);
163 // Last position before the decimal point.
165 // Separator positions, then, possibly, fractional digits.
167 // If input iterator is in a valid state.
168 bool __testvalid = true;
169 // Flag marking when a decimal point is found.
170 bool __testdecfound = false;
172 // The tentative returned string is stored here.
176 const char_type* __lit_zero = __lit + money_base::_S_zero;
177 const money_base::pattern __p = __lc->_M_neg_format;
178 for (int __i = 0; __i < 4 && __testvalid; ++__i)
180 const part __which = static_cast<part>(__p.field[__i]);
183 case money_base::symbol:
184 // According to 22.2.6.1.2, p2, symbol is required
185 // if (__io.flags() & ios_base::showbase), otherwise
186 // is optional and consumed only if other characters
187 // are needed to complete the format.
188 if (__io.flags() & ios_base::showbase || __sign_size > 1
190 || (__i == 1 && (__mandatory_sign
191 || (static_cast<part>(__p.field[0])
193 || (static_cast<part>(__p.field[2])
194 == money_base::space)))
195 || (__i == 2 && ((static_cast<part>(__p.field[3])
196 == money_base::value)
198 && (static_cast<part>(__p.field[3])
199 == money_base::sign)))))
201 const size_type __len = __lc->_M_curr_symbol_size;
203 for (; __beg != __end && __j < __len
204 && *__beg == __lc->_M_curr_symbol[__j];
205 ++__beg, (void)++__j);
207 && (__j || __io.flags() & ios_base::showbase))
211 case money_base::sign:
212 // Sign might not exist, or be more than one character long.
213 if (__lc->_M_positive_sign_size && __beg != __end
214 && *__beg == __lc->_M_positive_sign[0])
216 __sign_size = __lc->_M_positive_sign_size;
219 else if (__lc->_M_negative_sign_size && __beg != __end
220 && *__beg == __lc->_M_negative_sign[0])
223 __sign_size = __lc->_M_negative_sign_size;
226 else if (__lc->_M_positive_sign_size
227 && !__lc->_M_negative_sign_size)
228 // "... if no sign is detected, the result is given the sign
229 // that corresponds to the source of the empty string"
231 else if (__mandatory_sign)
234 case money_base::value:
235 // Extract digits, remove and stash away the
236 // grouping of found thousands separators.
237 for (; __beg != __end; ++__beg)
239 const char_type __c = *__beg;
240 const char_type* __q = __traits_type::find(__lit_zero,
244 __res += money_base::_S_atoms[__q - __lit];
247 else if (__c == __lc->_M_decimal_point
250 if (__lc->_M_frac_digits <= 0)
255 __testdecfound = true;
257 else if (__lc->_M_use_grouping
258 && __c == __lc->_M_thousands_sep
263 // Mark position for later analysis.
264 __grouping_tmp += static_cast<char>(__n);
279 case money_base::space:
280 // At least one space is required.
281 if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
286 case money_base::none:
287 // Only if not at the end of the pattern.
289 for (; __beg != __end
290 && __ctype.is(ctype_base::space, *__beg); ++__beg);
295 // Need to get the rest of the sign characters, if they exist.
296 if (__sign_size > 1 && __testvalid)
298 const char_type* __sign = __negative ? __lc->_M_negative_sign
299 : __lc->_M_positive_sign;
301 for (; __beg != __end && __i < __sign_size
302 && *__beg == __sign[__i]; ++__beg, (void)++__i);
304 if (__i != __sign_size)
310 // Strip leading zeros.
311 if (__res.size() > 1)
313 const size_type __first = __res.find_first_not_of('0');
314 const bool __only_zeros = __first == string::npos;
316 __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
320 if (__negative && __res[0] != '0')
321 __res.insert(__res.begin(), '-');
323 // Test for grouping fidelity.
324 if (__grouping_tmp.size())
326 // Add the ending grouping.
327 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
329 if (!std::__verify_grouping(__lc->_M_grouping,
330 __lc->_M_grouping_size,
332 __err |= ios_base::failbit;
335 // Iff not enough digits were supplied after the decimal-point.
336 if (__testdecfound && __n != __lc->_M_frac_digits)
340 // Iff valid sequence is not recognized.
342 __err |= ios_base::failbit;
346 // Iff no more characters are available.
348 __err |= ios_base::eofbit;
352 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
353 && _GLIBCXX_USE_CXX11_ABI == 0
354 template<typename _CharT, typename _InIter>
356 money_get<_CharT, _InIter>::
357 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
358 ios_base::iostate& __err, double& __units) const
361 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
362 : _M_extract<false>(__beg, __end, __io, __err, __str);
363 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
368 template<typename _CharT, typename _InIter>
370 money_get<_CharT, _InIter>::
371 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
372 ios_base::iostate& __err, long double& __units) const
375 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
376 : _M_extract<false>(__beg, __end, __io, __err, __str);
377 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
381 template<typename _CharT, typename _InIter>
383 money_get<_CharT, _InIter>::
384 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
385 ios_base::iostate& __err, string_type& __digits) const
387 typedef typename string::size_type size_type;
389 const locale& __loc = __io._M_getloc();
390 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
393 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
394 : _M_extract<false>(__beg, __end, __io, __err, __str);
395 const size_type __len = __str.size();
398 __digits.resize(__len);
399 __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
404 template<typename _CharT, typename _OutIter>
407 money_put<_CharT, _OutIter>::
408 _M_insert(iter_type __s, ios_base& __io, char_type __fill,
409 const string_type& __digits) const
411 typedef typename string_type::size_type size_type;
412 typedef money_base::part part;
413 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
415 const locale& __loc = __io._M_getloc();
416 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
418 __use_cache<__cache_type> __uc;
419 const __cache_type* __lc = __uc(__loc);
420 const char_type* __lit = __lc->_M_atoms;
422 // Determine if negative or positive formats are to be used, and
423 // discard leading negative_sign if it is present.
424 const char_type* __beg = __digits.data();
426 money_base::pattern __p;
427 const char_type* __sign;
428 size_type __sign_size;
429 if (!(*__beg == __lit[money_base::_S_minus]))
431 __p = __lc->_M_pos_format;
432 __sign = __lc->_M_positive_sign;
433 __sign_size = __lc->_M_positive_sign_size;
437 __p = __lc->_M_neg_format;
438 __sign = __lc->_M_negative_sign;
439 __sign_size = __lc->_M_negative_sign_size;
444 // Look for valid numbers in the ctype facet within input digits.
445 size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
446 __beg + __digits.size()) - __beg;
449 // Assume valid input, and attempt to format.
450 // Break down input numbers into base components, as follows:
451 // final_value = grouped units + (decimal point) + (digits)
453 __value.reserve(2 * __len);
455 // Add thousands separators to non-decimal digits, per
457 long __paddec = __len - __lc->_M_frac_digits;
460 if (__lc->_M_frac_digits < 0)
462 if (__lc->_M_grouping_size)
464 __value.assign(2 * __paddec, char_type());
466 std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
468 __lc->_M_grouping_size,
469 __beg, __beg + __paddec);
470 __value.erase(__vend - &__value[0]);
473 __value.assign(__beg, __paddec);
476 // Deal with decimal point, decimal digits.
477 if (__lc->_M_frac_digits > 0)
479 __value += __lc->_M_decimal_point;
481 __value.append(__beg + __paddec, __lc->_M_frac_digits);
484 // Have to pad zeros in the decimal position.
485 __value.append(-__paddec, __lit[money_base::_S_zero]);
486 __value.append(__beg, __len);
490 // Calculate length of resulting string.
491 const ios_base::fmtflags __f = __io.flags()
492 & ios_base::adjustfield;
493 __len = __value.size() + __sign_size;
494 __len += ((__io.flags() & ios_base::showbase)
495 ? __lc->_M_curr_symbol_size : 0);
498 __res.reserve(2 * __len);
500 const size_type __width = static_cast<size_type>(__io.width());
501 const bool __testipad = (__f == ios_base::internal
503 // Fit formatted digits into the required pattern.
504 for (int __i = 0; __i < 4; ++__i)
506 const part __which = static_cast<part>(__p.field[__i]);
509 case money_base::symbol:
510 if (__io.flags() & ios_base::showbase)
511 __res.append(__lc->_M_curr_symbol,
512 __lc->_M_curr_symbol_size);
514 case money_base::sign:
515 // Sign might not exist, or be more than one
516 // character long. In that case, add in the rest
521 case money_base::value:
524 case money_base::space:
525 // At least one space is required, but if internal
526 // formatting is required, an arbitrary number of
527 // fill spaces will be necessary.
529 __res.append(__width - __len, __fill);
533 case money_base::none:
535 __res.append(__width - __len, __fill);
540 // Special case of multi-part sign parts.
542 __res.append(__sign + 1, __sign_size - 1);
544 // Pad, if still necessary.
545 __len = __res.size();
548 if (__f == ios_base::left)
550 __res.append(__width - __len, __fill);
553 __res.insert(0, __width - __len, __fill);
557 // Write resulting, fully-formatted string to output iterator.
558 __s = std::__write(__s, __res.data(), __len);
564 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ \
565 && _GLIBCXX_USE_CXX11_ABI == 0
566 template<typename _CharT, typename _OutIter>
568 money_put<_CharT, _OutIter>::
569 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
570 double __units) const
571 { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
574 template<typename _CharT, typename _OutIter>
576 money_put<_CharT, _OutIter>::
577 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
578 long double __units) const
580 const locale __loc = __io.getloc();
581 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
582 #if _GLIBCXX_USE_C99_STDIO
583 // First try a buffer perhaps big enough.
585 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
586 // _GLIBCXX_RESOLVE_LIB_DEFECTS
587 // 328. Bad sprintf format modifier in money_put<>::do_put()
588 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
589 "%.*Lf", 0, __units);
590 // If the buffer was not large enough, try again with the correct size.
591 if (__len >= __cs_size)
593 __cs_size = __len + 1;
594 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
595 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
596 "%.*Lf", 0, __units);
599 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
600 const int __cs_size =
601 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
602 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
603 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
606 string_type __digits(__len, char_type());
607 __ctype.widen(__cs, __cs + __len, &__digits[0]);
608 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
609 : _M_insert<false>(__s, __io, __fill, __digits);
612 template<typename _CharT, typename _OutIter>
614 money_put<_CharT, _OutIter>::
615 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
616 const string_type& __digits) const
617 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
618 : _M_insert<false>(__s, __io, __fill, __digits); }
620 _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
622 // NB: Not especially useful. Without an ios_base object or some
623 // kind of locale reference, we are left clawing at the air where
624 // the side of the mountain used to be...
625 template<typename _CharT, typename _InIter>
627 time_get<_CharT, _InIter>::do_date_order() const
628 { return time_base::no_order; }
630 // Expand a strftime format string and parse it. E.g., do_get_date() may
631 // pass %m/%d/%Y => extracted characters.
632 template<typename _CharT, typename _InIter>
634 time_get<_CharT, _InIter>::
635 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
636 ios_base::iostate& __err, tm* __tm,
637 const _CharT* __format) const
639 const locale& __loc = __io._M_getloc();
640 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
641 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
642 const size_t __len = char_traits<_CharT>::length(__format);
644 ios_base::iostate __tmperr = ios_base::goodbit;
646 for (; __beg != __end && __i < __len && !__tmperr; ++__i)
648 if (__ctype.narrow(__format[__i], 0) == '%')
650 // Verify valid formatting code, attempt to extract.
651 char __c = __ctype.narrow(__format[++__i], 0);
653 if (__c == 'E' || __c == 'O')
654 __c = __ctype.narrow(__format[++__i], 0);
660 // Abbreviated weekday name [tm_wday]
661 const char_type* __days1[7];
662 __tp._M_days_abbreviated(__days1);
663 __beg = _M_extract_name(__beg, __end, __mem, __days1,
666 __tm->tm_wday = __mem;
669 // Weekday name [tm_wday].
670 const char_type* __days2[7];
671 __tp._M_days(__days2);
672 __beg = _M_extract_name(__beg, __end, __mem, __days2,
675 __tm->tm_wday = __mem;
679 // Abbreviated month name [tm_mon]
680 const char_type* __months1[12];
681 __tp._M_months_abbreviated(__months1);
682 __beg = _M_extract_name(__beg, __end, __mem,
683 __months1, 12, __io, __tmperr);
685 __tm->tm_mon = __mem;
688 // Month name [tm_mon].
689 const char_type* __months2[12];
690 __tp._M_months(__months2);
691 __beg = _M_extract_name(__beg, __end, __mem,
692 __months2, 12, __io, __tmperr);
694 __tm->tm_mon = __mem;
697 // Default time and date representation.
698 const char_type* __dt[2];
699 __tp._M_date_time_formats(__dt);
700 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
704 // Day [01, 31]. [tm_mday]
705 __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2,
708 __tm->tm_mday = __mem;
711 // Day [1, 31], with single digits preceded by
713 if (__ctype.is(ctype_base::space, *__beg))
714 __beg = _M_extract_num(++__beg, __end, __mem, 1, 9,
717 __beg = _M_extract_num(__beg, __end, __mem, 10, 31,
720 __tm->tm_mday = __mem;
723 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
725 __ctype.widen(__cs, __cs + 9, __wcs);
726 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
730 // Hour [00, 23]. [tm_hour]
731 __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2,
734 __tm->tm_hour = __mem;
737 // Hour [01, 12]. [tm_hour]
738 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
741 __tm->tm_hour = __mem;
744 // Month [01, 12]. [tm_mon]
745 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
748 __tm->tm_mon = __mem - 1;
751 // Minute [00, 59]. [tm_min]
752 __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2,
755 __tm->tm_min = __mem;
758 if (__ctype.narrow(*__beg, 0) == '\n')
761 __tmperr |= ios_base::failbit;
764 // Equivalent to (%H:%M).
766 __ctype.widen(__cs, __cs + 6, __wcs);
767 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
772 // [00, 60] in C99 (one leap-second), [00, 61] in C89.
774 __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2,
776 __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2,
780 __tm->tm_sec = __mem;
783 if (__ctype.narrow(*__beg, 0) == '\t')
786 __tmperr |= ios_base::failbit;
789 // Equivalent to (%H:%M:%S).
791 __ctype.widen(__cs, __cs + 9, __wcs);
792 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
797 const char_type* __dates[2];
798 __tp._M_date_formats(__dates);
799 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
804 const char_type* __times[2];
805 __tp._M_time_formats(__times);
806 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
814 // NB: We parse either two digits, implicitly years since
815 // 1900, or 4 digits, full year. In both cases we can
816 // reconstruct [tm_year]. See also libstdc++/26701.
817 __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
820 __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
824 if (__ctype.is(ctype_base::upper, *__beg))
827 __beg = _M_extract_name(__beg, __end, __tmp,
828 __timepunct_cache<_CharT>::_S_timezones,
831 // GMT requires special effort.
832 if (__beg != __end && !__tmperr && __tmp == 0
833 && (*__beg == __ctype.widen('-')
834 || *__beg == __ctype.widen('+')))
836 __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
838 __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
843 __tmperr |= ios_base::failbit;
847 __tmperr |= ios_base::failbit;
852 // Verify format and input match, extract and discard.
853 if (__format[__i] == *__beg)
856 __tmperr |= ios_base::failbit;
860 if (__tmperr || __i != __len)
861 __err |= ios_base::failbit;
866 template<typename _CharT, typename _InIter>
868 time_get<_CharT, _InIter>::
869 _M_extract_num(iter_type __beg, iter_type __end, int& __member,
870 int __min, int __max, size_t __len,
871 ios_base& __io, ios_base::iostate& __err) const
873 const locale& __loc = __io._M_getloc();
874 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
876 // As-is works for __len = 1, 2, 4, the values actually used.
877 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
882 for (; __beg != __end && __i < __len; ++__beg, (void)++__i)
884 const char __c = __ctype.narrow(*__beg, '*');
885 if (__c >= '0' && __c <= '9')
887 __value = __value * 10 + (__c - '0');
888 const int __valuec = __value * __mult;
889 if (__valuec > __max || __valuec + __mult < __min)
898 // Special encoding for do_get_year, 'y', and 'Y' above.
899 else if (__len == 4 && __i == 2)
900 __member = __value - 100;
902 __err |= ios_base::failbit;
908 // All elements in __names are unique.
909 template<typename _CharT, typename _InIter>
911 time_get<_CharT, _InIter>::
912 _M_extract_name(iter_type __beg, iter_type __end, int& __member,
913 const _CharT** __names, size_t __indexlen,
914 ios_base& __io, ios_base::iostate& __err) const
916 typedef char_traits<_CharT> __traits_type;
917 const locale& __loc = __io._M_getloc();
918 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
920 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
922 size_t __nmatches = 0;
924 bool __testvalid = true;
925 const char_type* __name;
927 // Look for initial matches.
928 // NB: Some of the locale data is in the form of all lowercase
929 // names, and some is in the form of initially-capitalized
930 // names. Look for both.
933 const char_type __c = *__beg;
934 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
935 if (__c == __names[__i1][0]
936 || __c == __ctype.toupper(__names[__i1][0]))
937 __matches[__nmatches++] = __i1;
940 while (__nmatches > 1)
942 // Find smallest matching string.
943 size_t __minlen = __traits_type::length(__names[__matches[0]]);
944 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
945 __minlen = std::min(__minlen,
946 __traits_type::length(__names[__matches[__i2]]));
949 if (__pos < __minlen && __beg != __end)
950 for (size_t __i3 = 0; __i3 < __nmatches;)
952 __name = __names[__matches[__i3]];
953 if (!(__name[__pos] == *__beg))
954 __matches[__i3] = __matches[--__nmatches];
964 // Make sure found name is completely extracted.
967 __name = __names[__matches[0]];
968 const size_t __len = __traits_type::length(__name);
969 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
970 ++__beg, (void)++__pos;
973 __member = __matches[0];
980 __err |= ios_base::failbit;
985 template<typename _CharT, typename _InIter>
987 time_get<_CharT, _InIter>::
988 _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
989 const _CharT** __names, size_t __indexlen,
990 ios_base& __io, ios_base::iostate& __err) const
992 typedef char_traits<_CharT> __traits_type;
993 const locale& __loc = __io._M_getloc();
994 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
996 int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
998 size_t __nmatches = 0;
999 size_t* __matches_lengths = 0;
1004 const char_type __c = *__beg;
1005 for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
1006 if (__c == __names[__i][0]
1007 || __c == __ctype.toupper(__names[__i][0]))
1008 __matches[__nmatches++] = __i;
1017 = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
1019 for (size_t __i = 0; __i < __nmatches; ++__i)
1020 __matches_lengths[__i]
1021 = __traits_type::length(__names[__matches[__i]]);
1024 for (; __beg != __end; ++__beg, (void)++__pos)
1026 size_t __nskipped = 0;
1027 const char_type __c = *__beg;
1028 for (size_t __i = 0; __i < __nmatches;)
1030 const char_type* __name = __names[__matches[__i]];
1031 if (__pos >= __matches_lengths[__i])
1032 ++__nskipped, ++__i;
1033 else if (!(__name[__pos] == __c))
1036 __matches[__i] = __matches[__nmatches];
1037 __matches_lengths[__i] = __matches_lengths[__nmatches];
1042 if (__nskipped == __nmatches)
1046 if ((__nmatches == 1 && __matches_lengths[0] == __pos)
1047 || (__nmatches == 2 && (__matches_lengths[0] == __pos
1048 || __matches_lengths[1] == __pos)))
1049 __member = (__matches[0] >= __indexlen
1050 ? __matches[0] - __indexlen : __matches[0]);
1052 __err |= ios_base::failbit;
1057 template<typename _CharT, typename _InIter>
1059 time_get<_CharT, _InIter>::
1060 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1061 ios_base::iostate& __err, tm* __tm) const
1063 const locale& __loc = __io._M_getloc();
1064 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1065 const char_type* __times[2];
1066 __tp._M_time_formats(__times);
1067 __beg = _M_extract_via_format(__beg, __end, __io, __err,
1070 __err |= ios_base::eofbit;
1074 template<typename _CharT, typename _InIter>
1076 time_get<_CharT, _InIter>::
1077 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1078 ios_base::iostate& __err, tm* __tm) const
1080 const locale& __loc = __io._M_getloc();
1081 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1082 const char_type* __dates[2];
1083 __tp._M_date_formats(__dates);
1084 __beg = _M_extract_via_format(__beg, __end, __io, __err,
1087 __err |= ios_base::eofbit;
1091 template<typename _CharT, typename _InIter>
1093 time_get<_CharT, _InIter>::
1094 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1095 ios_base::iostate& __err, tm* __tm) const
1097 const locale& __loc = __io._M_getloc();
1098 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1099 const char_type* __days[14];
1100 __tp._M_days_abbreviated(__days);
1101 __tp._M_days(__days + 7);
1103 ios_base::iostate __tmperr = ios_base::goodbit;
1105 __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
1108 __tm->tm_wday = __tmpwday;
1110 __err |= ios_base::failbit;
1113 __err |= ios_base::eofbit;
1117 template<typename _CharT, typename _InIter>
1119 time_get<_CharT, _InIter>::
1120 do_get_monthname(iter_type __beg, iter_type __end,
1121 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1123 const locale& __loc = __io._M_getloc();
1124 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1125 const char_type* __months[24];
1126 __tp._M_months_abbreviated(__months);
1127 __tp._M_months(__months + 12);
1129 ios_base::iostate __tmperr = ios_base::goodbit;
1131 __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
1134 __tm->tm_mon = __tmpmon;
1136 __err |= ios_base::failbit;
1139 __err |= ios_base::eofbit;
1143 template<typename _CharT, typename _InIter>
1145 time_get<_CharT, _InIter>::
1146 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1147 ios_base::iostate& __err, tm* __tm) const
1150 ios_base::iostate __tmperr = ios_base::goodbit;
1152 __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
1155 __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
1157 __err |= ios_base::failbit;
1160 __err |= ios_base::eofbit;
1164 #if __cplusplus >= 201103L
1165 template<typename _CharT, typename _InIter>
1168 time_get<_CharT, _InIter>::
1169 get(iter_type __s, iter_type __end, ios_base& __io,
1170 ios_base::iostate& __err, tm* __tm, const char_type* __fmt,
1171 const char_type* __fmtend) const
1173 const locale& __loc = __io._M_getloc();
1174 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1175 __err = ios_base::goodbit;
1176 while (__fmt != __fmtend &&
1177 __err == ios_base::goodbit)
1181 __err = ios_base::eofbit | ios_base::failbit;
1184 else if (__ctype.narrow(*__fmt, 0) == '%')
1188 if (++__fmt == __fmtend)
1190 __err = ios_base::failbit;
1193 const char __c = __ctype.narrow(*__fmt, 0);
1194 if (__c != 'E' && __c != 'O')
1196 else if (++__fmt != __fmtend)
1199 __format = __ctype.narrow(*__fmt, 0);
1203 __err = ios_base::failbit;
1206 __s = this->do_get(__s, __end, __io, __err, __tm, __format,
1210 else if (__ctype.is(ctype_base::space, *__fmt))
1213 while (__fmt != __fmtend &&
1214 __ctype.is(ctype_base::space, *__fmt))
1217 while (__s != __end &&
1218 __ctype.is(ctype_base::space, *__s))
1221 // TODO real case-insensitive comparison
1222 else if (__ctype.tolower(*__s) == __ctype.tolower(*__fmt) ||
1223 __ctype.toupper(*__s) == __ctype.toupper(*__fmt))
1230 __err = ios_base::failbit;
1237 template<typename _CharT, typename _InIter>
1240 time_get<_CharT, _InIter>::
1241 do_get(iter_type __beg, iter_type __end, ios_base& __io,
1242 ios_base::iostate& __err, tm* __tm,
1243 char __format, char __mod) const
1245 const locale& __loc = __io._M_getloc();
1246 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1247 __err = ios_base::goodbit;
1250 __fmt[0] = __ctype.widen('%');
1253 __fmt[1] = __format;
1254 __fmt[2] = char_type();
1259 __fmt[2] = __format;
1260 __fmt[3] = char_type();
1263 __beg = _M_extract_via_format(__beg, __end, __io, __err, __tm, __fmt);
1265 __err |= ios_base::eofbit;
1269 #endif // __cplusplus >= 201103L
1271 template<typename _CharT, typename _OutIter>
1273 time_put<_CharT, _OutIter>::
1274 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1275 const _CharT* __beg, const _CharT* __end) const
1277 const locale& __loc = __io._M_getloc();
1278 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1279 for (; __beg != __end; ++__beg)
1280 if (__ctype.narrow(*__beg, 0) != '%')
1285 else if (++__beg != __end)
1289 const char __c = __ctype.narrow(*__beg, 0);
1290 if (__c != 'E' && __c != 'O')
1292 else if (++__beg != __end)
1295 __format = __ctype.narrow(*__beg, 0);
1299 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1306 template<typename _CharT, typename _OutIter>
1308 time_put<_CharT, _OutIter>::
1309 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1310 char __format, char __mod) const
1312 const locale& __loc = __io._M_getloc();
1313 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1314 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1316 // NB: This size is arbitrary. Should this be a data member,
1317 // initialized at construction?
1318 const size_t __maxlen = 128;
1319 char_type __res[__maxlen];
1321 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1322 // is possible that the format character will be longer than one
1323 // character. Possibilities include 'E' or 'O' followed by a
1324 // format character: if __mod is not the default argument, assume
1325 // it's a valid modifier.
1327 __fmt[0] = __ctype.widen('%');
1330 __fmt[1] = __format;
1331 __fmt[2] = char_type();
1336 __fmt[2] = __format;
1337 __fmt[3] = char_type();
1340 __tp._M_put(__res, __maxlen, __fmt, __tm);
1342 // Write resulting, fully-formatted string to output iterator.
1343 return std::__write(__s, __res, char_traits<char_type>::length(__res));
1347 // Inhibit implicit instantiations for required instantiations,
1348 // which are defined via explicit instantiations elsewhere.
1349 #if _GLIBCXX_EXTERN_TEMPLATE
1350 extern template class moneypunct<char, false>;
1351 extern template class moneypunct<char, true>;
1352 extern template class moneypunct_byname<char, false>;
1353 extern template class moneypunct_byname<char, true>;
1354 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<char>;
1355 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<char>;
1356 extern template class __timepunct<char>;
1357 extern template class time_put<char>;
1358 extern template class time_put_byname<char>;
1359 extern template class time_get<char>;
1360 extern template class time_get_byname<char>;
1361 extern template class messages<char>;
1362 extern template class messages_byname<char>;
1365 const moneypunct<char, true>&
1366 use_facet<moneypunct<char, true> >(const locale&);
1369 const moneypunct<char, false>&
1370 use_facet<moneypunct<char, false> >(const locale&);
1373 const money_put<char>&
1374 use_facet<money_put<char> >(const locale&);
1377 const money_get<char>&
1378 use_facet<money_get<char> >(const locale&);
1381 const __timepunct<char>&
1382 use_facet<__timepunct<char> >(const locale&);
1385 const time_put<char>&
1386 use_facet<time_put<char> >(const locale&);
1389 const time_get<char>&
1390 use_facet<time_get<char> >(const locale&);
1393 const messages<char>&
1394 use_facet<messages<char> >(const locale&);
1398 has_facet<moneypunct<char> >(const locale&);
1402 has_facet<money_put<char> >(const locale&);
1406 has_facet<money_get<char> >(const locale&);
1410 has_facet<__timepunct<char> >(const locale&);
1414 has_facet<time_put<char> >(const locale&);
1418 has_facet<time_get<char> >(const locale&);
1422 has_facet<messages<char> >(const locale&);
1424 #ifdef _GLIBCXX_USE_WCHAR_T
1425 extern template class moneypunct<wchar_t, false>;
1426 extern template class moneypunct<wchar_t, true>;
1427 extern template class moneypunct_byname<wchar_t, false>;
1428 extern template class moneypunct_byname<wchar_t, true>;
1429 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_get<wchar_t>;
1430 extern template class _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 money_put<wchar_t>;
1431 extern template class __timepunct<wchar_t>;
1432 extern template class time_put<wchar_t>;
1433 extern template class time_put_byname<wchar_t>;
1434 extern template class time_get<wchar_t>;
1435 extern template class time_get_byname<wchar_t>;
1436 extern template class messages<wchar_t>;
1437 extern template class messages_byname<wchar_t>;
1440 const moneypunct<wchar_t, true>&
1441 use_facet<moneypunct<wchar_t, true> >(const locale&);
1444 const moneypunct<wchar_t, false>&
1445 use_facet<moneypunct<wchar_t, false> >(const locale&);
1448 const money_put<wchar_t>&
1449 use_facet<money_put<wchar_t> >(const locale&);
1452 const money_get<wchar_t>&
1453 use_facet<money_get<wchar_t> >(const locale&);
1456 const __timepunct<wchar_t>&
1457 use_facet<__timepunct<wchar_t> >(const locale&);
1460 const time_put<wchar_t>&
1461 use_facet<time_put<wchar_t> >(const locale&);
1464 const time_get<wchar_t>&
1465 use_facet<time_get<wchar_t> >(const locale&);
1468 const messages<wchar_t>&
1469 use_facet<messages<wchar_t> >(const locale&);
1473 has_facet<moneypunct<wchar_t> >(const locale&);
1477 has_facet<money_put<wchar_t> >(const locale&);
1481 has_facet<money_get<wchar_t> >(const locale&);
1485 has_facet<__timepunct<wchar_t> >(const locale&);
1489 has_facet<time_put<wchar_t> >(const locale&);
1493 has_facet<time_get<wchar_t> >(const locale&);
1497 has_facet<messages<wchar_t> >(const locale&);
1501 _GLIBCXX_END_NAMESPACE_VERSION