1 // Locale support -*- C++ -*-
3 // Copyright (C) 2007, 2008, 2009, 2010 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 locale_facets_nonio.tcc
26 * This is an internal header file, included by other library headers.
27 * You should not attempt to use it directly.
30 #ifndef _LOCALE_FACETS_NONIO_TCC
31 #define _LOCALE_FACETS_NONIO_TCC 1
33 #pragma GCC system_header
35 _GLIBCXX_BEGIN_NAMESPACE(std)
37 template<typename _CharT, bool _Intl>
38 struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
40 const __moneypunct_cache<_CharT, _Intl>*
41 operator() (const locale& __loc) const
43 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
44 const locale::facet** __caches = __loc._M_impl->_M_caches;
47 __moneypunct_cache<_CharT, _Intl>* __tmp = 0;
50 __tmp = new __moneypunct_cache<_CharT, _Intl>;
51 __tmp->_M_cache(__loc);
56 __throw_exception_again;
58 __loc._M_impl->_M_install_cache(__tmp, __i);
61 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
65 template<typename _CharT, bool _Intl>
67 __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 _M_grouping_size = __mp.grouping().size();
85 __grouping = new char[_M_grouping_size];
86 __mp.grouping().copy(__grouping, _M_grouping_size);
87 _M_grouping = __grouping;
88 _M_use_grouping = (_M_grouping_size
89 && static_cast<signed char>(_M_grouping[0]) > 0
91 != __gnu_cxx::__numeric_traits<char>::__max));
93 _M_curr_symbol_size = __mp.curr_symbol().size();
94 __curr_symbol = new _CharT[_M_curr_symbol_size];
95 __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
96 _M_curr_symbol = __curr_symbol;
98 _M_positive_sign_size = __mp.positive_sign().size();
99 __positive_sign = new _CharT[_M_positive_sign_size];
100 __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
101 _M_positive_sign = __positive_sign;
103 _M_negative_sign_size = __mp.negative_sign().size();
104 __negative_sign = new _CharT[_M_negative_sign_size];
105 __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
106 _M_negative_sign = __negative_sign;
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);
117 delete [] __grouping;
118 delete [] __curr_symbol;
119 delete [] __positive_sign;
120 delete [] __negative_sign;
121 __throw_exception_again;
125 _GLIBCXX_BEGIN_LDBL_NAMESPACE
127 template<typename _CharT, typename _InIter>
130 money_get<_CharT, _InIter>::
131 _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
132 ios_base::iostate& __err, string& __units) const
134 typedef char_traits<_CharT> __traits_type;
135 typedef typename string_type::size_type size_type;
136 typedef money_base::part part;
137 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
139 const locale& __loc = __io._M_getloc();
140 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
142 __use_cache<__cache_type> __uc;
143 const __cache_type* __lc = __uc(__loc);
144 const char_type* __lit = __lc->_M_atoms;
147 bool __negative = false;
149 size_type __sign_size = 0;
150 // True if sign is mandatory.
151 const bool __mandatory_sign = (__lc->_M_positive_sign_size
152 && __lc->_M_negative_sign_size);
153 // String of grouping info from thousands_sep plucked from __units.
154 string __grouping_tmp;
155 if (__lc->_M_use_grouping)
156 __grouping_tmp.reserve(32);
157 // Last position before the decimal point.
159 // Separator positions, then, possibly, fractional digits.
161 // If input iterator is in a valid state.
162 bool __testvalid = true;
163 // Flag marking when a decimal point is found.
164 bool __testdecfound = false;
166 // The tentative returned string is stored here.
170 const char_type* __lit_zero = __lit + money_base::_S_zero;
171 const money_base::pattern __p = __lc->_M_neg_format;
172 for (int __i = 0; __i < 4 && __testvalid; ++__i)
174 const part __which = static_cast<part>(__p.field[__i]);
177 case money_base::symbol:
178 // According to 22.2.6.1.2, p2, symbol is required
179 // if (__io.flags() & ios_base::showbase), otherwise
180 // is optional and consumed only if other characters
181 // are needed to complete the format.
182 if (__io.flags() & ios_base::showbase || __sign_size > 1
184 || (__i == 1 && (__mandatory_sign
185 || (static_cast<part>(__p.field[0])
187 || (static_cast<part>(__p.field[2])
188 == money_base::space)))
189 || (__i == 2 && ((static_cast<part>(__p.field[3])
190 == money_base::value)
192 && (static_cast<part>(__p.field[3])
193 == money_base::sign)))))
195 const size_type __len = __lc->_M_curr_symbol_size;
197 for (; __beg != __end && __j < __len
198 && *__beg == __lc->_M_curr_symbol[__j];
201 && (__j || __io.flags() & ios_base::showbase))
205 case money_base::sign:
206 // Sign might not exist, or be more than one character long.
207 if (__lc->_M_positive_sign_size && __beg != __end
208 && *__beg == __lc->_M_positive_sign[0])
210 __sign_size = __lc->_M_positive_sign_size;
213 else if (__lc->_M_negative_sign_size && __beg != __end
214 && *__beg == __lc->_M_negative_sign[0])
217 __sign_size = __lc->_M_negative_sign_size;
220 else if (__lc->_M_positive_sign_size
221 && !__lc->_M_negative_sign_size)
222 // "... if no sign is detected, the result is given the sign
223 // that corresponds to the source of the empty string"
225 else if (__mandatory_sign)
228 case money_base::value:
229 // Extract digits, remove and stash away the
230 // grouping of found thousands separators.
231 for (; __beg != __end; ++__beg)
233 const char_type __c = *__beg;
234 const char_type* __q = __traits_type::find(__lit_zero,
238 __res += money_base::_S_atoms[__q - __lit];
241 else if (__c == __lc->_M_decimal_point
244 if (__lc->_M_frac_digits <= 0)
249 __testdecfound = true;
251 else if (__lc->_M_use_grouping
252 && __c == __lc->_M_thousands_sep
257 // Mark position for later analysis.
258 __grouping_tmp += static_cast<char>(__n);
273 case money_base::space:
274 // At least one space is required.
275 if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
279 case money_base::none:
280 // Only if not at the end of the pattern.
282 for (; __beg != __end
283 && __ctype.is(ctype_base::space, *__beg); ++__beg);
288 // Need to get the rest of the sign characters, if they exist.
289 if (__sign_size > 1 && __testvalid)
291 const char_type* __sign = __negative ? __lc->_M_negative_sign
292 : __lc->_M_positive_sign;
294 for (; __beg != __end && __i < __sign_size
295 && *__beg == __sign[__i]; ++__beg, ++__i);
297 if (__i != __sign_size)
303 // Strip leading zeros.
304 if (__res.size() > 1)
306 const size_type __first = __res.find_first_not_of('0');
307 const bool __only_zeros = __first == string::npos;
309 __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
313 if (__negative && __res[0] != '0')
314 __res.insert(__res.begin(), '-');
316 // Test for grouping fidelity.
317 if (__grouping_tmp.size())
319 // Add the ending grouping.
320 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
322 if (!std::__verify_grouping(__lc->_M_grouping,
323 __lc->_M_grouping_size,
325 __err |= ios_base::failbit;
328 // Iff not enough digits were supplied after the decimal-point.
329 if (__testdecfound && __n != __lc->_M_frac_digits)
333 // Iff valid sequence is not recognized.
335 __err |= ios_base::failbit;
339 // Iff no more characters are available.
341 __err |= ios_base::eofbit;
345 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
346 template<typename _CharT, typename _InIter>
348 money_get<_CharT, _InIter>::
349 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
350 ios_base::iostate& __err, double& __units) const
353 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
354 : _M_extract<false>(__beg, __end, __io, __err, __str);
355 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
360 template<typename _CharT, typename _InIter>
362 money_get<_CharT, _InIter>::
363 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
364 ios_base::iostate& __err, long double& __units) const
367 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
368 : _M_extract<false>(__beg, __end, __io, __err, __str);
369 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
373 template<typename _CharT, typename _InIter>
375 money_get<_CharT, _InIter>::
376 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
377 ios_base::iostate& __err, string_type& __digits) const
379 typedef typename string::size_type size_type;
381 const locale& __loc = __io._M_getloc();
382 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
385 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
386 : _M_extract<false>(__beg, __end, __io, __err, __str);
387 const size_type __len = __str.size();
390 __digits.resize(__len);
391 __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
396 template<typename _CharT, typename _OutIter>
399 money_put<_CharT, _OutIter>::
400 _M_insert(iter_type __s, ios_base& __io, char_type __fill,
401 const string_type& __digits) const
403 typedef typename string_type::size_type size_type;
404 typedef money_base::part part;
405 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
407 const locale& __loc = __io._M_getloc();
408 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
410 __use_cache<__cache_type> __uc;
411 const __cache_type* __lc = __uc(__loc);
412 const char_type* __lit = __lc->_M_atoms;
414 // Determine if negative or positive formats are to be used, and
415 // discard leading negative_sign if it is present.
416 const char_type* __beg = __digits.data();
418 money_base::pattern __p;
419 const char_type* __sign;
420 size_type __sign_size;
421 if (!(*__beg == __lit[money_base::_S_minus]))
423 __p = __lc->_M_pos_format;
424 __sign = __lc->_M_positive_sign;
425 __sign_size = __lc->_M_positive_sign_size;
429 __p = __lc->_M_neg_format;
430 __sign = __lc->_M_negative_sign;
431 __sign_size = __lc->_M_negative_sign_size;
436 // Look for valid numbers in the ctype facet within input digits.
437 size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
438 __beg + __digits.size()) - __beg;
441 // Assume valid input, and attempt to format.
442 // Break down input numbers into base components, as follows:
443 // final_value = grouped units + (decimal point) + (digits)
445 __value.reserve(2 * __len);
447 // Add thousands separators to non-decimal digits, per
449 long __paddec = __len - __lc->_M_frac_digits;
452 if (__lc->_M_frac_digits < 0)
454 if (__lc->_M_grouping_size)
456 __value.assign(2 * __paddec, char_type());
458 std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
460 __lc->_M_grouping_size,
461 __beg, __beg + __paddec);
462 __value.erase(__vend - &__value[0]);
465 __value.assign(__beg, __paddec);
468 // Deal with decimal point, decimal digits.
469 if (__lc->_M_frac_digits > 0)
471 __value += __lc->_M_decimal_point;
473 __value.append(__beg + __paddec, __lc->_M_frac_digits);
476 // Have to pad zeros in the decimal position.
477 __value.append(-__paddec, __lit[money_base::_S_zero]);
478 __value.append(__beg, __len);
482 // Calculate length of resulting string.
483 const ios_base::fmtflags __f = __io.flags()
484 & ios_base::adjustfield;
485 __len = __value.size() + __sign_size;
486 __len += ((__io.flags() & ios_base::showbase)
487 ? __lc->_M_curr_symbol_size : 0);
490 __res.reserve(2 * __len);
492 const size_type __width = static_cast<size_type>(__io.width());
493 const bool __testipad = (__f == ios_base::internal
495 // Fit formatted digits into the required pattern.
496 for (int __i = 0; __i < 4; ++__i)
498 const part __which = static_cast<part>(__p.field[__i]);
501 case money_base::symbol:
502 if (__io.flags() & ios_base::showbase)
503 __res.append(__lc->_M_curr_symbol,
504 __lc->_M_curr_symbol_size);
506 case money_base::sign:
507 // Sign might not exist, or be more than one
508 // character long. In that case, add in the rest
513 case money_base::value:
516 case money_base::space:
517 // At least one space is required, but if internal
518 // formatting is required, an arbitrary number of
519 // fill spaces will be necessary.
521 __res.append(__width - __len, __fill);
525 case money_base::none:
527 __res.append(__width - __len, __fill);
532 // Special case of multi-part sign parts.
534 __res.append(__sign + 1, __sign_size - 1);
536 // Pad, if still necessary.
537 __len = __res.size();
540 if (__f == ios_base::left)
542 __res.append(__width - __len, __fill);
545 __res.insert(0, __width - __len, __fill);
549 // Write resulting, fully-formatted string to output iterator.
550 __s = std::__write(__s, __res.data(), __len);
556 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
557 template<typename _CharT, typename _OutIter>
559 money_put<_CharT, _OutIter>::
560 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
561 double __units) const
562 { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
565 template<typename _CharT, typename _OutIter>
567 money_put<_CharT, _OutIter>::
568 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
569 long double __units) const
571 const locale __loc = __io.getloc();
572 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
573 #ifdef _GLIBCXX_USE_C99
574 // First try a buffer perhaps big enough.
576 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
577 // _GLIBCXX_RESOLVE_LIB_DEFECTS
578 // 328. Bad sprintf format modifier in money_put<>::do_put()
579 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
580 "%.*Lf", 0, __units);
581 // If the buffer was not large enough, try again with the correct size.
582 if (__len >= __cs_size)
584 __cs_size = __len + 1;
585 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
586 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
587 "%.*Lf", 0, __units);
590 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
591 const int __cs_size =
592 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
593 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
594 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
597 string_type __digits(__len, char_type());
598 __ctype.widen(__cs, __cs + __len, &__digits[0]);
599 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
600 : _M_insert<false>(__s, __io, __fill, __digits);
603 template<typename _CharT, typename _OutIter>
605 money_put<_CharT, _OutIter>::
606 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
607 const string_type& __digits) const
608 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
609 : _M_insert<false>(__s, __io, __fill, __digits); }
611 _GLIBCXX_END_LDBL_NAMESPACE
613 // NB: Not especially useful. Without an ios_base object or some
614 // kind of locale reference, we are left clawing at the air where
615 // the side of the mountain used to be...
616 template<typename _CharT, typename _InIter>
618 time_get<_CharT, _InIter>::do_date_order() const
619 { return time_base::no_order; }
621 // Expand a strftime format string and parse it. E.g., do_get_date() may
622 // pass %m/%d/%Y => extracted characters.
623 template<typename _CharT, typename _InIter>
625 time_get<_CharT, _InIter>::
626 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
627 ios_base::iostate& __err, tm* __tm,
628 const _CharT* __format) const
630 const locale& __loc = __io._M_getloc();
631 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
632 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
633 const size_t __len = char_traits<_CharT>::length(__format);
635 ios_base::iostate __tmperr = ios_base::goodbit;
637 for (; __beg != __end && __i < __len && !__tmperr; ++__i)
639 if (__ctype.narrow(__format[__i], 0) == '%')
641 // Verify valid formatting code, attempt to extract.
642 char __c = __ctype.narrow(__format[++__i], 0);
644 if (__c == 'E' || __c == 'O')
645 __c = __ctype.narrow(__format[++__i], 0);
651 // Abbreviated weekday name [tm_wday]
652 const char_type* __days1[7];
653 __tp._M_days_abbreviated(__days1);
654 __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
658 // Weekday name [tm_wday].
659 const char_type* __days2[7];
660 __tp._M_days(__days2);
661 __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
666 // Abbreviated month name [tm_mon]
667 const char_type* __months1[12];
668 __tp._M_months_abbreviated(__months1);
669 __beg = _M_extract_name(__beg, __end, __tm->tm_mon,
670 __months1, 12, __io, __tmperr);
673 // Month name [tm_mon].
674 const char_type* __months2[12];
675 __tp._M_months(__months2);
676 __beg = _M_extract_name(__beg, __end, __tm->tm_mon,
677 __months2, 12, __io, __tmperr);
680 // Default time and date representation.
681 const char_type* __dt[2];
682 __tp._M_date_time_formats(__dt);
683 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
687 // Day [01, 31]. [tm_mday]
688 __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
692 // Day [1, 31], with single digits preceded by
694 if (__ctype.is(ctype_base::space, *__beg))
695 __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
698 __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
702 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
704 __ctype.widen(__cs, __cs + 9, __wcs);
705 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
709 // Hour [00, 23]. [tm_hour]
710 __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
714 // Hour [01, 12]. [tm_hour]
715 __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
719 // Month [01, 12]. [tm_mon]
720 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
723 __tm->tm_mon = __mem - 1;
726 // Minute [00, 59]. [tm_min]
727 __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
731 if (__ctype.narrow(*__beg, 0) == '\n')
734 __tmperr |= ios_base::failbit;
737 // Equivalent to (%H:%M).
739 __ctype.widen(__cs, __cs + 6, __wcs);
740 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
745 // [00, 60] in C99 (one leap-second), [00, 61] in C89.
746 #ifdef _GLIBCXX_USE_C99
747 __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
749 __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
754 if (__ctype.narrow(*__beg, 0) == '\t')
757 __tmperr |= ios_base::failbit;
760 // Equivalent to (%H:%M:%S).
762 __ctype.widen(__cs, __cs + 9, __wcs);
763 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
768 const char_type* __dates[2];
769 __tp._M_date_formats(__dates);
770 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
775 const char_type* __times[2];
776 __tp._M_time_formats(__times);
777 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
785 // NB: We parse either two digits, implicitly years since
786 // 1900, or 4 digits, full year. In both cases we can
787 // reconstruct [tm_year]. See also libstdc++/26701.
788 __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
791 __tm->tm_year = __mem < 0 ? __mem + 100 : __mem - 1900;
795 if (__ctype.is(ctype_base::upper, *__beg))
798 __beg = _M_extract_name(__beg, __end, __tmp,
799 __timepunct_cache<_CharT>::_S_timezones,
802 // GMT requires special effort.
803 if (__beg != __end && !__tmperr && __tmp == 0
804 && (*__beg == __ctype.widen('-')
805 || *__beg == __ctype.widen('+')))
807 __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
809 __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
814 __tmperr |= ios_base::failbit;
818 __tmperr |= ios_base::failbit;
823 // Verify format and input match, extract and discard.
824 if (__format[__i] == *__beg)
827 __tmperr |= ios_base::failbit;
831 if (__tmperr || __i != __len)
832 __err |= ios_base::failbit;
837 template<typename _CharT, typename _InIter>
839 time_get<_CharT, _InIter>::
840 _M_extract_num(iter_type __beg, iter_type __end, int& __member,
841 int __min, int __max, size_t __len,
842 ios_base& __io, ios_base::iostate& __err) const
844 const locale& __loc = __io._M_getloc();
845 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
847 // As-is works for __len = 1, 2, 4, the values actually used.
848 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
853 for (; __beg != __end && __i < __len; ++__beg, ++__i)
855 const char __c = __ctype.narrow(*__beg, '*');
856 if (__c >= '0' && __c <= '9')
858 __value = __value * 10 + (__c - '0');
859 const int __valuec = __value * __mult;
860 if (__valuec > __max || __valuec + __mult < __min)
869 // Special encoding for do_get_year, 'y', and 'Y' above.
870 else if (__len == 4 && __i == 2)
871 __member = __value - 100;
873 __err |= ios_base::failbit;
879 // All elements in __names are unique.
880 template<typename _CharT, typename _InIter>
882 time_get<_CharT, _InIter>::
883 _M_extract_name(iter_type __beg, iter_type __end, int& __member,
884 const _CharT** __names, size_t __indexlen,
885 ios_base& __io, ios_base::iostate& __err) const
887 typedef char_traits<_CharT> __traits_type;
888 const locale& __loc = __io._M_getloc();
889 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
891 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
893 size_t __nmatches = 0;
895 bool __testvalid = true;
896 const char_type* __name;
898 // Look for initial matches.
899 // NB: Some of the locale data is in the form of all lowercase
900 // names, and some is in the form of initially-capitalized
901 // names. Look for both.
904 const char_type __c = *__beg;
905 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
906 if (__c == __names[__i1][0]
907 || __c == __ctype.toupper(__names[__i1][0]))
908 __matches[__nmatches++] = __i1;
911 while (__nmatches > 1)
913 // Find smallest matching string.
914 size_t __minlen = __traits_type::length(__names[__matches[0]]);
915 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
916 __minlen = std::min(__minlen,
917 __traits_type::length(__names[__matches[__i2]]));
919 if (__pos < __minlen && __beg != __end)
920 for (size_t __i3 = 0; __i3 < __nmatches;)
922 __name = __names[__matches[__i3]];
923 if (!(__name[__pos] == *__beg))
924 __matches[__i3] = __matches[--__nmatches];
934 // Make sure found name is completely extracted.
936 __name = __names[__matches[0]];
937 const size_t __len = __traits_type::length(__name);
938 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
942 __member = __matches[0];
949 __err |= ios_base::failbit;
954 template<typename _CharT, typename _InIter>
956 time_get<_CharT, _InIter>::
957 _M_extract_wday_or_month(iter_type __beg, iter_type __end, int& __member,
958 const _CharT** __names, size_t __indexlen,
959 ios_base& __io, ios_base::iostate& __err) const
961 typedef char_traits<_CharT> __traits_type;
962 const locale& __loc = __io._M_getloc();
963 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
965 int* __matches = static_cast<int*>(__builtin_alloca(2 * sizeof(int)
967 size_t __nmatches = 0;
968 size_t* __matches_lengths = 0;
973 const char_type __c = *__beg;
974 for (size_t __i = 0; __i < 2 * __indexlen; ++__i)
975 if (__c == __names[__i][0]
976 || __c == __ctype.toupper(__names[__i][0]))
977 __matches[__nmatches++] = __i;
985 = static_cast<size_t*>(__builtin_alloca(sizeof(size_t)
987 for (size_t __i = 0; __i < __nmatches; ++__i)
988 __matches_lengths[__i]
989 = __traits_type::length(__names[__matches[__i]]);
992 for (; __beg != __end; ++__beg, ++__pos)
994 size_t __nskipped = 0;
995 const char_type __c = *__beg;
996 for (size_t __i = 0; __i < __nmatches;)
998 const char_type* __name = __names[__matches[__i]];
999 if (__pos >= __matches_lengths[__i])
1000 ++__nskipped, ++__i;
1001 else if (!(__name[__pos] == __c))
1004 __matches[__i] = __matches[__nmatches];
1005 __matches_lengths[__i] = __matches_lengths[__nmatches];
1010 if (__nskipped == __nmatches)
1014 if ((__nmatches == 1 && __matches_lengths[0] == __pos)
1015 || (__nmatches == 2 && (__matches_lengths[0] == __pos
1016 || __matches_lengths[1] == __pos)))
1017 __member = (__matches[0] >= __indexlen
1018 ? __matches[0] - __indexlen : __matches[0]);
1020 __err |= ios_base::failbit;
1025 template<typename _CharT, typename _InIter>
1027 time_get<_CharT, _InIter>::
1028 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1029 ios_base::iostate& __err, tm* __tm) const
1031 const locale& __loc = __io._M_getloc();
1032 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1033 const char_type* __times[2];
1034 __tp._M_time_formats(__times);
1035 __beg = _M_extract_via_format(__beg, __end, __io, __err,
1038 __err |= ios_base::eofbit;
1042 template<typename _CharT, typename _InIter>
1044 time_get<_CharT, _InIter>::
1045 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1046 ios_base::iostate& __err, tm* __tm) const
1048 const locale& __loc = __io._M_getloc();
1049 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1050 const char_type* __dates[2];
1051 __tp._M_date_formats(__dates);
1052 __beg = _M_extract_via_format(__beg, __end, __io, __err,
1055 __err |= ios_base::eofbit;
1059 template<typename _CharT, typename _InIter>
1061 time_get<_CharT, _InIter>::
1062 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1063 ios_base::iostate& __err, tm* __tm) const
1065 typedef char_traits<_CharT> __traits_type;
1066 const locale& __loc = __io._M_getloc();
1067 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1068 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1069 const char_type* __days[14];
1070 __tp._M_days_abbreviated(__days);
1071 __tp._M_days(__days + 7);
1073 ios_base::iostate __tmperr = ios_base::goodbit;
1075 __beg = _M_extract_wday_or_month(__beg, __end, __tmpwday, __days, 7,
1078 __tm->tm_wday = __tmpwday;
1080 __err |= ios_base::failbit;
1083 __err |= ios_base::eofbit;
1087 template<typename _CharT, typename _InIter>
1089 time_get<_CharT, _InIter>::
1090 do_get_monthname(iter_type __beg, iter_type __end,
1091 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1093 typedef char_traits<_CharT> __traits_type;
1094 const locale& __loc = __io._M_getloc();
1095 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1096 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1097 const char_type* __months[24];
1098 __tp._M_months_abbreviated(__months);
1099 __tp._M_months(__months + 12);
1101 ios_base::iostate __tmperr = ios_base::goodbit;
1103 __beg = _M_extract_wday_or_month(__beg, __end, __tmpmon, __months, 12,
1106 __tm->tm_mon = __tmpmon;
1108 __err |= ios_base::failbit;
1111 __err |= ios_base::eofbit;
1115 template<typename _CharT, typename _InIter>
1117 time_get<_CharT, _InIter>::
1118 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1119 ios_base::iostate& __err, tm* __tm) const
1121 const locale& __loc = __io._M_getloc();
1122 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1124 ios_base::iostate __tmperr = ios_base::goodbit;
1126 __beg = _M_extract_num(__beg, __end, __tmpyear, 0, 9999, 4,
1129 __tm->tm_year = __tmpyear < 0 ? __tmpyear + 100 : __tmpyear - 1900;
1131 __err |= ios_base::failbit;
1134 __err |= ios_base::eofbit;
1138 template<typename _CharT, typename _OutIter>
1140 time_put<_CharT, _OutIter>::
1141 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1142 const _CharT* __beg, const _CharT* __end) const
1144 const locale& __loc = __io._M_getloc();
1145 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1146 for (; __beg != __end; ++__beg)
1147 if (__ctype.narrow(*__beg, 0) != '%')
1152 else if (++__beg != __end)
1156 const char __c = __ctype.narrow(*__beg, 0);
1157 if (__c != 'E' && __c != 'O')
1159 else if (++__beg != __end)
1162 __format = __ctype.narrow(*__beg, 0);
1166 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1173 template<typename _CharT, typename _OutIter>
1175 time_put<_CharT, _OutIter>::
1176 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1177 char __format, char __mod) const
1179 const locale& __loc = __io._M_getloc();
1180 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1181 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1183 // NB: This size is arbitrary. Should this be a data member,
1184 // initialized at construction?
1185 const size_t __maxlen = 128;
1186 char_type __res[__maxlen];
1188 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1189 // is possible that the format character will be longer than one
1190 // character. Possibilities include 'E' or 'O' followed by a
1191 // format character: if __mod is not the default argument, assume
1192 // it's a valid modifier.
1194 __fmt[0] = __ctype.widen('%');
1197 __fmt[1] = __format;
1198 __fmt[2] = char_type();
1203 __fmt[2] = __format;
1204 __fmt[3] = char_type();
1207 __tp._M_put(__res, __maxlen, __fmt, __tm);
1209 // Write resulting, fully-formatted string to output iterator.
1210 return std::__write(__s, __res, char_traits<char_type>::length(__res));
1214 // Inhibit implicit instantiations for required instantiations,
1215 // which are defined via explicit instantiations elsewhere.
1216 // NB: This syntax is a GNU extension.
1217 #if _GLIBCXX_EXTERN_TEMPLATE
1218 extern template class moneypunct<char, false>;
1219 extern template class moneypunct<char, true>;
1220 extern template class moneypunct_byname<char, false>;
1221 extern template class moneypunct_byname<char, true>;
1222 extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
1223 extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
1224 extern template class __timepunct<char>;
1225 extern template class time_put<char>;
1226 extern template class time_put_byname<char>;
1227 extern template class time_get<char>;
1228 extern template class time_get_byname<char>;
1229 extern template class messages<char>;
1230 extern template class messages_byname<char>;
1233 const moneypunct<char, true>&
1234 use_facet<moneypunct<char, true> >(const locale&);
1237 const moneypunct<char, false>&
1238 use_facet<moneypunct<char, false> >(const locale&);
1241 const money_put<char>&
1242 use_facet<money_put<char> >(const locale&);
1245 const money_get<char>&
1246 use_facet<money_get<char> >(const locale&);
1249 const __timepunct<char>&
1250 use_facet<__timepunct<char> >(const locale&);
1253 const time_put<char>&
1254 use_facet<time_put<char> >(const locale&);
1257 const time_get<char>&
1258 use_facet<time_get<char> >(const locale&);
1261 const messages<char>&
1262 use_facet<messages<char> >(const locale&);
1266 has_facet<moneypunct<char> >(const locale&);
1270 has_facet<money_put<char> >(const locale&);
1274 has_facet<money_get<char> >(const locale&);
1278 has_facet<__timepunct<char> >(const locale&);
1282 has_facet<time_put<char> >(const locale&);
1286 has_facet<time_get<char> >(const locale&);
1290 has_facet<messages<char> >(const locale&);
1292 #ifdef _GLIBCXX_USE_WCHAR_T
1293 extern template class moneypunct<wchar_t, false>;
1294 extern template class moneypunct<wchar_t, true>;
1295 extern template class moneypunct_byname<wchar_t, false>;
1296 extern template class moneypunct_byname<wchar_t, true>;
1297 extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
1298 extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
1299 extern template class __timepunct<wchar_t>;
1300 extern template class time_put<wchar_t>;
1301 extern template class time_put_byname<wchar_t>;
1302 extern template class time_get<wchar_t>;
1303 extern template class time_get_byname<wchar_t>;
1304 extern template class messages<wchar_t>;
1305 extern template class messages_byname<wchar_t>;
1308 const moneypunct<wchar_t, true>&
1309 use_facet<moneypunct<wchar_t, true> >(const locale&);
1312 const moneypunct<wchar_t, false>&
1313 use_facet<moneypunct<wchar_t, false> >(const locale&);
1316 const money_put<wchar_t>&
1317 use_facet<money_put<wchar_t> >(const locale&);
1320 const money_get<wchar_t>&
1321 use_facet<money_get<wchar_t> >(const locale&);
1324 const __timepunct<wchar_t>&
1325 use_facet<__timepunct<wchar_t> >(const locale&);
1328 const time_put<wchar_t>&
1329 use_facet<time_put<wchar_t> >(const locale&);
1332 const time_get<wchar_t>&
1333 use_facet<time_get<wchar_t> >(const locale&);
1336 const messages<wchar_t>&
1337 use_facet<messages<wchar_t> >(const locale&);
1341 has_facet<moneypunct<wchar_t> >(const locale&);
1345 has_facet<money_put<wchar_t> >(const locale&);
1349 has_facet<money_get<wchar_t> >(const locale&);
1353 has_facet<__timepunct<wchar_t> >(const locale&);
1357 has_facet<time_put<wchar_t> >(const locale&);
1361 has_facet<time_get<wchar_t> >(const locale&);
1365 has_facet<messages<wchar_t> >(const locale&);
1369 _GLIBCXX_END_NAMESPACE