1 // Locale support -*- C++ -*-
3 // Copyright (C) 2007 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 2, 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 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
30 /** @file locale_facets_nonio.tcc
31 * This is an internal header file, included by other library headers.
32 * You should not attempt to use it directly.
35 #ifndef _LOCALE_FACETS_NONIO_TCC
36 #define _LOCALE_FACETS_NONIO_TCC 1
38 _GLIBCXX_BEGIN_NAMESPACE(std)
40 template<typename _CharT, bool _Intl>
41 struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
43 const __moneypunct_cache<_CharT, _Intl>*
44 operator() (const locale& __loc) const
46 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
47 const locale::facet** __caches = __loc._M_impl->_M_caches;
50 __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
53 __tmp = new __moneypunct_cache<_CharT, _Intl>;
54 __tmp->_M_cache(__loc);
59 __throw_exception_again;
61 __loc._M_impl->_M_install_cache(__tmp, __i);
64 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
68 template<typename _CharT, bool _Intl>
70 __moneypunct_cache<_CharT, _Intl>::_M_cache(const locale& __loc)
74 const moneypunct<_CharT, _Intl>& __mp =
75 use_facet<moneypunct<_CharT, _Intl> >(__loc);
77 _M_grouping_size = __mp.grouping().size();
78 char* __grouping = new char[_M_grouping_size];
79 __mp.grouping().copy(__grouping, _M_grouping_size);
80 _M_grouping = __grouping;
81 _M_use_grouping = (_M_grouping_size
82 && static_cast<signed char>(__mp.grouping()[0]) > 0);
84 _M_decimal_point = __mp.decimal_point();
85 _M_thousands_sep = __mp.thousands_sep();
86 _M_frac_digits = __mp.frac_digits();
88 _M_curr_symbol_size = __mp.curr_symbol().size();
89 _CharT* __curr_symbol = new _CharT[_M_curr_symbol_size];
90 __mp.curr_symbol().copy(__curr_symbol, _M_curr_symbol_size);
91 _M_curr_symbol = __curr_symbol;
93 _M_positive_sign_size = __mp.positive_sign().size();
94 _CharT* __positive_sign = new _CharT[_M_positive_sign_size];
95 __mp.positive_sign().copy(__positive_sign, _M_positive_sign_size);
96 _M_positive_sign = __positive_sign;
98 _M_negative_sign_size = __mp.negative_sign().size();
99 _CharT* __negative_sign = new _CharT[_M_negative_sign_size];
100 __mp.negative_sign().copy(__negative_sign, _M_negative_sign_size);
101 _M_negative_sign = __negative_sign;
103 _M_pos_format = __mp.pos_format();
104 _M_neg_format = __mp.neg_format();
106 const ctype<_CharT>& __ct = use_facet<ctype<_CharT> >(__loc);
107 __ct.widen(money_base::_S_atoms,
108 money_base::_S_atoms + money_base::_S_end, _M_atoms);
111 _GLIBCXX_BEGIN_LDBL_NAMESPACE
113 template<typename _CharT, typename _InIter>
116 money_get<_CharT, _InIter>::
117 _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
118 ios_base::iostate& __err, string& __units) const
120 typedef char_traits<_CharT> __traits_type;
121 typedef typename string_type::size_type size_type;
122 typedef money_base::part part;
123 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
125 const locale& __loc = __io._M_getloc();
126 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
128 __use_cache<__cache_type> __uc;
129 const __cache_type* __lc = __uc(__loc);
130 const char_type* __lit = __lc->_M_atoms;
133 bool __negative = false;
135 size_type __sign_size = 0;
136 // True if sign is mandatory.
137 const bool __mandatory_sign = (__lc->_M_positive_sign_size
138 && __lc->_M_negative_sign_size);
139 // String of grouping info from thousands_sep plucked from __units.
140 string __grouping_tmp;
141 if (__lc->_M_use_grouping)
142 __grouping_tmp.reserve(32);
143 // Last position before the decimal point.
145 // Separator positions, then, possibly, fractional digits.
147 // If input iterator is in a valid state.
148 bool __testvalid = true;
149 // Flag marking when a decimal point is found.
150 bool __testdecfound = false;
152 // The tentative returned string is stored here.
156 const char_type* __lit_zero = __lit + money_base::_S_zero;
157 const money_base::pattern __p = __lc->_M_neg_format;
158 for (int __i = 0; __i < 4 && __testvalid; ++__i)
160 const part __which = static_cast<part>(__p.field[__i]);
163 case money_base::symbol:
164 // According to 22.2.6.1.2, p2, symbol is required
165 // if (__io.flags() & ios_base::showbase), otherwise
166 // is optional and consumed only if other characters
167 // are needed to complete the format.
168 if (__io.flags() & ios_base::showbase || __sign_size > 1
170 || (__i == 1 && (__mandatory_sign
171 || (static_cast<part>(__p.field[0])
173 || (static_cast<part>(__p.field[2])
174 == money_base::space)))
175 || (__i == 2 && ((static_cast<part>(__p.field[3])
176 == money_base::value)
178 && (static_cast<part>(__p.field[3])
179 == money_base::sign)))))
181 const size_type __len = __lc->_M_curr_symbol_size;
183 for (; __beg != __end && __j < __len
184 && *__beg == __lc->_M_curr_symbol[__j];
187 && (__j || __io.flags() & ios_base::showbase))
191 case money_base::sign:
192 // Sign might not exist, or be more than one character long.
193 if (__lc->_M_positive_sign_size && __beg != __end
194 && *__beg == __lc->_M_positive_sign[0])
196 __sign_size = __lc->_M_positive_sign_size;
199 else if (__lc->_M_negative_sign_size && __beg != __end
200 && *__beg == __lc->_M_negative_sign[0])
203 __sign_size = __lc->_M_negative_sign_size;
206 else if (__lc->_M_positive_sign_size
207 && !__lc->_M_negative_sign_size)
208 // "... if no sign is detected, the result is given the sign
209 // that corresponds to the source of the empty string"
211 else if (__mandatory_sign)
214 case money_base::value:
215 // Extract digits, remove and stash away the
216 // grouping of found thousands separators.
217 for (; __beg != __end; ++__beg)
219 const char_type __c = *__beg;
220 const char_type* __q = __traits_type::find(__lit_zero,
224 __res += money_base::_S_atoms[__q - __lit];
227 else if (__c == __lc->_M_decimal_point
232 __testdecfound = true;
234 else if (__lc->_M_use_grouping
235 && __c == __lc->_M_thousands_sep
240 // Mark position for later analysis.
241 __grouping_tmp += static_cast<char>(__n);
256 case money_base::space:
257 // At least one space is required.
258 if (__beg != __end && __ctype.is(ctype_base::space, *__beg))
262 case money_base::none:
263 // Only if not at the end of the pattern.
265 for (; __beg != __end
266 && __ctype.is(ctype_base::space, *__beg); ++__beg);
271 // Need to get the rest of the sign characters, if they exist.
272 if (__sign_size > 1 && __testvalid)
274 const char_type* __sign = __negative ? __lc->_M_negative_sign
275 : __lc->_M_positive_sign;
277 for (; __beg != __end && __i < __sign_size
278 && *__beg == __sign[__i]; ++__beg, ++__i);
280 if (__i != __sign_size)
286 // Strip leading zeros.
287 if (__res.size() > 1)
289 const size_type __first = __res.find_first_not_of('0');
290 const bool __only_zeros = __first == string::npos;
292 __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
296 if (__negative && __res[0] != '0')
297 __res.insert(__res.begin(), '-');
299 // Test for grouping fidelity.
300 if (__grouping_tmp.size())
302 // Add the ending grouping.
303 __grouping_tmp += static_cast<char>(__testdecfound ? __last_pos
305 if (!std::__verify_grouping(__lc->_M_grouping,
306 __lc->_M_grouping_size,
308 __err |= ios_base::failbit;
311 // Iff not enough digits were supplied after the decimal-point.
312 if (__testdecfound && __lc->_M_frac_digits > 0
313 && __n != __lc->_M_frac_digits)
317 // Iff valid sequence is not recognized.
319 __err |= ios_base::failbit;
323 // Iff no more characters are available.
325 __err |= ios_base::eofbit;
329 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
330 template<typename _CharT, typename _InIter>
332 money_get<_CharT, _InIter>::
333 __do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
334 ios_base::iostate& __err, double& __units) const
337 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
338 : _M_extract<false>(__beg, __end, __io, __err, __str);
339 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
344 template<typename _CharT, typename _InIter>
346 money_get<_CharT, _InIter>::
347 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
348 ios_base::iostate& __err, long double& __units) const
351 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
352 : _M_extract<false>(__beg, __end, __io, __err, __str);
353 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
357 template<typename _CharT, typename _InIter>
359 money_get<_CharT, _InIter>::
360 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
361 ios_base::iostate& __err, string_type& __digits) const
363 typedef typename string::size_type size_type;
365 const locale& __loc = __io._M_getloc();
366 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
369 __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
370 : _M_extract<false>(__beg, __end, __io, __err, __str);
371 const size_type __len = __str.size();
374 __digits.resize(__len);
375 __ctype.widen(__str.data(), __str.data() + __len, &__digits[0]);
380 template<typename _CharT, typename _OutIter>
383 money_put<_CharT, _OutIter>::
384 _M_insert(iter_type __s, ios_base& __io, char_type __fill,
385 const string_type& __digits) const
387 typedef typename string_type::size_type size_type;
388 typedef money_base::part part;
389 typedef __moneypunct_cache<_CharT, _Intl> __cache_type;
391 const locale& __loc = __io._M_getloc();
392 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
394 __use_cache<__cache_type> __uc;
395 const __cache_type* __lc = __uc(__loc);
396 const char_type* __lit = __lc->_M_atoms;
398 // Determine if negative or positive formats are to be used, and
399 // discard leading negative_sign if it is present.
400 const char_type* __beg = __digits.data();
402 money_base::pattern __p;
403 const char_type* __sign;
404 size_type __sign_size;
405 if (!(*__beg == __lit[money_base::_S_minus]))
407 __p = __lc->_M_pos_format;
408 __sign = __lc->_M_positive_sign;
409 __sign_size = __lc->_M_positive_sign_size;
413 __p = __lc->_M_neg_format;
414 __sign = __lc->_M_negative_sign;
415 __sign_size = __lc->_M_negative_sign_size;
420 // Look for valid numbers in the ctype facet within input digits.
421 size_type __len = __ctype.scan_not(ctype_base::digit, __beg,
422 __beg + __digits.size()) - __beg;
425 // Assume valid input, and attempt to format.
426 // Break down input numbers into base components, as follows:
427 // final_value = grouped units + (decimal point) + (digits)
429 __value.reserve(2 * __len);
431 // Add thousands separators to non-decimal digits, per
433 long __paddec = __len - __lc->_M_frac_digits;
436 if (__lc->_M_frac_digits < 0)
438 if (__lc->_M_grouping_size)
440 __value.assign(2 * __paddec, char_type());
442 std::__add_grouping(&__value[0], __lc->_M_thousands_sep,
444 __lc->_M_grouping_size,
445 __beg, __beg + __paddec);
446 __value.erase(__vend - &__value[0]);
449 __value.assign(__beg, __paddec);
452 // Deal with decimal point, decimal digits.
453 if (__lc->_M_frac_digits > 0)
455 __value += __lc->_M_decimal_point;
457 __value.append(__beg + __paddec, __lc->_M_frac_digits);
460 // Have to pad zeros in the decimal position.
461 __value.append(-__paddec, __lit[money_base::_S_zero]);
462 __value.append(__beg, __len);
466 // Calculate length of resulting string.
467 const ios_base::fmtflags __f = __io.flags()
468 & ios_base::adjustfield;
469 __len = __value.size() + __sign_size;
470 __len += ((__io.flags() & ios_base::showbase)
471 ? __lc->_M_curr_symbol_size : 0);
474 __res.reserve(2 * __len);
476 const size_type __width = static_cast<size_type>(__io.width());
477 const bool __testipad = (__f == ios_base::internal
479 // Fit formatted digits into the required pattern.
480 for (int __i = 0; __i < 4; ++__i)
482 const part __which = static_cast<part>(__p.field[__i]);
485 case money_base::symbol:
486 if (__io.flags() & ios_base::showbase)
487 __res.append(__lc->_M_curr_symbol,
488 __lc->_M_curr_symbol_size);
490 case money_base::sign:
491 // Sign might not exist, or be more than one
492 // charater long. In that case, add in the rest
497 case money_base::value:
500 case money_base::space:
501 // At least one space is required, but if internal
502 // formatting is required, an arbitrary number of
503 // fill spaces will be necessary.
505 __res.append(__width - __len, __fill);
509 case money_base::none:
511 __res.append(__width - __len, __fill);
516 // Special case of multi-part sign parts.
518 __res.append(__sign + 1, __sign_size - 1);
520 // Pad, if still necessary.
521 __len = __res.size();
524 if (__f == ios_base::left)
526 __res.append(__width - __len, __fill);
529 __res.insert(0, __width - __len, __fill);
533 // Write resulting, fully-formatted string to output iterator.
534 __s = std::__write(__s, __res.data(), __len);
540 #if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__
541 template<typename _CharT, typename _OutIter>
543 money_put<_CharT, _OutIter>::
544 __do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
545 double __units) const
546 { return this->do_put(__s, __intl, __io, __fill, (long double) __units); }
549 template<typename _CharT, typename _OutIter>
551 money_put<_CharT, _OutIter>::
552 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
553 long double __units) const
555 const locale __loc = __io.getloc();
556 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
557 #ifdef _GLIBCXX_USE_C99
558 // First try a buffer perhaps big enough.
560 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
561 // _GLIBCXX_RESOLVE_LIB_DEFECTS
562 // 328. Bad sprintf format modifier in money_put<>::do_put()
563 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
564 "%.*Lf", 0, __units);
565 // If the buffer was not large enough, try again with the correct size.
566 if (__len >= __cs_size)
568 __cs_size = __len + 1;
569 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
570 __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
571 "%.*Lf", 0, __units);
574 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
575 const int __cs_size =
576 __gnu_cxx::__numeric_traits<long double>::__max_exponent10 + 3;
577 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
578 int __len = std::__convert_from_v(_S_get_c_locale(), __cs, 0, "%.*Lf",
581 string_type __digits(__len, char_type());
582 __ctype.widen(__cs, __cs + __len, &__digits[0]);
583 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
584 : _M_insert<false>(__s, __io, __fill, __digits);
587 template<typename _CharT, typename _OutIter>
589 money_put<_CharT, _OutIter>::
590 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
591 const string_type& __digits) const
592 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
593 : _M_insert<false>(__s, __io, __fill, __digits); }
595 _GLIBCXX_END_LDBL_NAMESPACE
597 // NB: Not especially useful. Without an ios_base object or some
598 // kind of locale reference, we are left clawing at the air where
599 // the side of the mountain used to be...
600 template<typename _CharT, typename _InIter>
602 time_get<_CharT, _InIter>::do_date_order() const
603 { return time_base::no_order; }
605 // Expand a strftime format string and parse it. E.g., do_get_date() may
606 // pass %m/%d/%Y => extracted characters.
607 template<typename _CharT, typename _InIter>
609 time_get<_CharT, _InIter>::
610 _M_extract_via_format(iter_type __beg, iter_type __end, ios_base& __io,
611 ios_base::iostate& __err, tm* __tm,
612 const _CharT* __format) const
614 const locale& __loc = __io._M_getloc();
615 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
616 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
617 const size_t __len = char_traits<_CharT>::length(__format);
619 ios_base::iostate __tmperr = ios_base::goodbit;
620 for (size_t __i = 0; __beg != __end && __i < __len && !__tmperr; ++__i)
622 if (__ctype.narrow(__format[__i], 0) == '%')
624 // Verify valid formatting code, attempt to extract.
625 char __c = __ctype.narrow(__format[++__i], 0);
627 if (__c == 'E' || __c == 'O')
628 __c = __ctype.narrow(__format[++__i], 0);
634 // Abbreviated weekday name [tm_wday]
635 const char_type* __days1[7];
636 __tp._M_days_abbreviated(__days1);
637 __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1,
641 // Weekday name [tm_wday].
642 const char_type* __days2[7];
643 __tp._M_days(__days2);
644 __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2,
649 // Abbreviated month name [tm_mon]
650 const char_type* __months1[12];
651 __tp._M_months_abbreviated(__months1);
652 __beg = _M_extract_name(__beg, __end, __tm->tm_mon,
653 __months1, 12, __io, __tmperr);
656 // Month name [tm_mon].
657 const char_type* __months2[12];
658 __tp._M_months(__months2);
659 __beg = _M_extract_name(__beg, __end, __tm->tm_mon,
660 __months2, 12, __io, __tmperr);
663 // Default time and date representation.
664 const char_type* __dt[2];
665 __tp._M_date_time_formats(__dt);
666 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
670 // Day [01, 31]. [tm_mday]
671 __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
675 // Day [1, 31], with single digits preceded by
677 if (__ctype.is(ctype_base::space, *__beg))
678 __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9,
681 __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31,
685 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
687 __ctype.widen(__cs, __cs + 9, __wcs);
688 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
692 // Hour [00, 23]. [tm_hour]
693 __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
697 // Hour [01, 12]. [tm_hour]
698 __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
702 // Month [01, 12]. [tm_mon]
703 __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2,
706 __tm->tm_mon = __mem - 1;
709 // Minute [00, 59]. [tm_min]
710 __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
714 if (__ctype.narrow(*__beg, 0) == '\n')
717 __tmperr |= ios_base::failbit;
720 // Equivalent to (%H:%M).
722 __ctype.widen(__cs, __cs + 6, __wcs);
723 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
728 // [00, 60] in C99 (one leap-second), [00, 61] in C89.
729 #ifdef _GLIBCXX_USE_C99
730 __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2,
732 __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2,
737 if (__ctype.narrow(*__beg, 0) == '\t')
740 __tmperr |= ios_base::failbit;
743 // Equivalent to (%H:%M:%S).
745 __ctype.widen(__cs, __cs + 9, __wcs);
746 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
751 const char_type* __dates[2];
752 __tp._M_date_formats(__dates);
753 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
758 const char_type* __times[2];
759 __tp._M_time_formats(__times);
760 __beg = _M_extract_via_format(__beg, __end, __io, __tmperr,
765 // Two digit year. [tm_year]
766 __beg = _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
770 // Year [1900). [tm_year]
771 __beg = _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
774 __tm->tm_year = __mem - 1900;
778 if (__ctype.is(ctype_base::upper, *__beg))
781 __beg = _M_extract_name(__beg, __end, __tmp,
782 __timepunct_cache<_CharT>::_S_timezones,
785 // GMT requires special effort.
786 if (__beg != __end && !__tmperr && __tmp == 0
787 && (*__beg == __ctype.widen('-')
788 || *__beg == __ctype.widen('+')))
790 __beg = _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
792 __beg = _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
797 __tmperr |= ios_base::failbit;
801 __tmperr |= ios_base::failbit;
806 // Verify format and input match, extract and discard.
807 if (__format[__i] == *__beg)
810 __tmperr |= ios_base::failbit;
815 __err |= ios_base::failbit;
820 template<typename _CharT, typename _InIter>
822 time_get<_CharT, _InIter>::
823 _M_extract_num(iter_type __beg, iter_type __end, int& __member,
824 int __min, int __max, size_t __len,
825 ios_base& __io, ios_base::iostate& __err) const
827 const locale& __loc = __io._M_getloc();
828 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
830 // As-is works for __len = 1, 2, 4, the values actually used.
831 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
836 for (; __beg != __end && __i < __len; ++__beg, ++__i)
838 const char __c = __ctype.narrow(*__beg, '*');
839 if (__c >= '0' && __c <= '9')
841 __value = __value * 10 + (__c - '0');
842 const int __valuec = __value * __mult;
843 if (__valuec > __max || __valuec + __mult < __min)
853 __err |= ios_base::failbit;
859 // All elements in __names are unique.
860 template<typename _CharT, typename _InIter>
862 time_get<_CharT, _InIter>::
863 _M_extract_name(iter_type __beg, iter_type __end, int& __member,
864 const _CharT** __names, size_t __indexlen,
865 ios_base& __io, ios_base::iostate& __err) const
867 typedef char_traits<_CharT> __traits_type;
868 const locale& __loc = __io._M_getloc();
869 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
871 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
873 size_t __nmatches = 0;
875 bool __testvalid = true;
876 const char_type* __name;
878 // Look for initial matches.
879 // NB: Some of the locale data is in the form of all lowercase
880 // names, and some is in the form of initially-capitalized
881 // names. Look for both.
884 const char_type __c = *__beg;
885 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
886 if (__c == __names[__i1][0]
887 || __c == __ctype.toupper(__names[__i1][0]))
888 __matches[__nmatches++] = __i1;
891 while (__nmatches > 1)
893 // Find smallest matching string.
894 size_t __minlen = __traits_type::length(__names[__matches[0]]);
895 for (size_t __i2 = 1; __i2 < __nmatches; ++__i2)
896 __minlen = std::min(__minlen,
897 __traits_type::length(__names[__matches[__i2]]));
899 if (__pos < __minlen && __beg != __end)
900 for (size_t __i3 = 0; __i3 < __nmatches;)
902 __name = __names[__matches[__i3]];
903 if (!(__name[__pos] == *__beg))
904 __matches[__i3] = __matches[--__nmatches];
914 // Make sure found name is completely extracted.
916 __name = __names[__matches[0]];
917 const size_t __len = __traits_type::length(__name);
918 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
922 __member = __matches[0];
929 __err |= ios_base::failbit;
934 template<typename _CharT, typename _InIter>
936 time_get<_CharT, _InIter>::
937 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
938 ios_base::iostate& __err, tm* __tm) const
940 const locale& __loc = __io._M_getloc();
941 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
942 const char_type* __times[2];
943 __tp._M_time_formats(__times);
944 __beg = _M_extract_via_format(__beg, __end, __io, __err,
947 __err |= ios_base::eofbit;
951 template<typename _CharT, typename _InIter>
953 time_get<_CharT, _InIter>::
954 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
955 ios_base::iostate& __err, tm* __tm) const
957 const locale& __loc = __io._M_getloc();
958 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
959 const char_type* __dates[2];
960 __tp._M_date_formats(__dates);
961 __beg = _M_extract_via_format(__beg, __end, __io, __err,
964 __err |= ios_base::eofbit;
968 template<typename _CharT, typename _InIter>
970 time_get<_CharT, _InIter>::
971 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
972 ios_base::iostate& __err, tm* __tm) const
974 typedef char_traits<_CharT> __traits_type;
975 const locale& __loc = __io._M_getloc();
976 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
977 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
978 const char_type* __days[7];
979 __tp._M_days_abbreviated(__days);
981 ios_base::iostate __tmperr = ios_base::goodbit;
982 __beg = _M_extract_name(__beg, __end, __tmpwday, __days, 7,
985 // Check to see if non-abbreviated name exists, and extract.
986 // NB: Assumes both _M_days and _M_days_abbreviated organized in
987 // exact same order, first to last, such that the resulting
988 // __days array with the same index points to a day, and that
989 // day's abbreviated form.
990 // NB: Also assumes that an abbreviated name is a subset of the name.
991 if (!__tmperr && __beg != __end)
993 size_t __pos = __traits_type::length(__days[__tmpwday]);
994 __tp._M_days(__days);
995 const char_type* __name = __days[__tmpwday];
996 if (__name[__pos] == *__beg)
998 // Extract the rest of it.
999 const size_t __len = __traits_type::length(__name);
1000 while (__pos < __len && __beg != __end
1001 && __name[__pos] == *__beg)
1004 __tmperr |= ios_base::failbit;
1008 __tm->tm_wday = __tmpwday;
1010 __err |= ios_base::failbit;
1013 __err |= ios_base::eofbit;
1017 template<typename _CharT, typename _InIter>
1019 time_get<_CharT, _InIter>::
1020 do_get_monthname(iter_type __beg, iter_type __end,
1021 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1023 typedef char_traits<_CharT> __traits_type;
1024 const locale& __loc = __io._M_getloc();
1025 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1026 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1027 const char_type* __months[12];
1028 __tp._M_months_abbreviated(__months);
1030 ios_base::iostate __tmperr = ios_base::goodbit;
1031 __beg = _M_extract_name(__beg, __end, __tmpmon, __months, 12,
1034 // Check to see if non-abbreviated name exists, and extract.
1035 // NB: Assumes both _M_months and _M_months_abbreviated organized in
1036 // exact same order, first to last, such that the resulting
1037 // __months array with the same index points to a month, and that
1038 // month's abbreviated form.
1039 // NB: Also assumes that an abbreviated name is a subset of the name.
1040 if (!__tmperr && __beg != __end)
1042 size_t __pos = __traits_type::length(__months[__tmpmon]);
1043 __tp._M_months(__months);
1044 const char_type* __name = __months[__tmpmon];
1045 if (__name[__pos] == *__beg)
1047 // Extract the rest of it.
1048 const size_t __len = __traits_type::length(__name);
1049 while (__pos < __len && __beg != __end
1050 && __name[__pos] == *__beg)
1053 __tmperr |= ios_base::failbit;
1057 __tm->tm_mon = __tmpmon;
1059 __err |= ios_base::failbit;
1062 __err |= ios_base::eofbit;
1066 template<typename _CharT, typename _InIter>
1068 time_get<_CharT, _InIter>::
1069 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1070 ios_base::iostate& __err, tm* __tm) const
1072 const locale& __loc = __io._M_getloc();
1073 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1077 for (; __beg != __end && __i < 4; ++__beg, ++__i)
1079 const char __c = __ctype.narrow(*__beg, '*');
1080 if (__c >= '0' && __c <= '9')
1081 __value = __value * 10 + (__c - '0');
1085 if (__i == 2 || __i == 4)
1086 __tm->tm_year = __i == 2 ? __value : __value - 1900;
1088 __err |= ios_base::failbit;
1091 __err |= ios_base::eofbit;
1095 template<typename _CharT, typename _OutIter>
1097 time_put<_CharT, _OutIter>::
1098 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
1099 const _CharT* __beg, const _CharT* __end) const
1101 const locale& __loc = __io._M_getloc();
1102 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1103 for (; __beg != __end; ++__beg)
1104 if (__ctype.narrow(*__beg, 0) != '%')
1109 else if (++__beg != __end)
1113 const char __c = __ctype.narrow(*__beg, 0);
1114 if (__c != 'E' && __c != 'O')
1116 else if (++__beg != __end)
1119 __format = __ctype.narrow(*__beg, 0);
1123 __s = this->do_put(__s, __io, __fill, __tm, __format, __mod);
1130 template<typename _CharT, typename _OutIter>
1132 time_put<_CharT, _OutIter>::
1133 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1134 char __format, char __mod) const
1136 const locale& __loc = __io._M_getloc();
1137 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1138 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1140 // NB: This size is arbitrary. Should this be a data member,
1141 // initialized at construction?
1142 const size_t __maxlen = 128;
1144 static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
1146 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1147 // is possible that the format character will be longer than one
1148 // character. Possibilities include 'E' or 'O' followed by a
1149 // format character: if __mod is not the default argument, assume
1150 // it's a valid modifier.
1152 __fmt[0] = __ctype.widen('%');
1155 __fmt[1] = __format;
1156 __fmt[2] = char_type();
1161 __fmt[2] = __format;
1162 __fmt[3] = char_type();
1165 __tp._M_put(__res, __maxlen, __fmt, __tm);
1167 // Write resulting, fully-formatted string to output iterator.
1168 return std::__write(__s, __res, char_traits<char_type>::length(__res));
1171 // Inhibit implicit instantiations for required instantiations,
1172 // which are defined via explicit instantiations elsewhere.
1173 // NB: This syntax is a GNU extension.
1174 #if _GLIBCXX_EXTERN_TEMPLATE
1175 extern template class moneypunct<char, false>;
1176 extern template class moneypunct<char, true>;
1177 extern template class moneypunct_byname<char, false>;
1178 extern template class moneypunct_byname<char, true>;
1179 extern template class _GLIBCXX_LDBL_NAMESPACE money_get<char>;
1180 extern template class _GLIBCXX_LDBL_NAMESPACE money_put<char>;
1181 extern template class __timepunct<char>;
1182 extern template class time_put<char>;
1183 extern template class time_put_byname<char>;
1184 extern template class time_get<char>;
1185 extern template class time_get_byname<char>;
1186 extern template class messages<char>;
1187 extern template class messages_byname<char>;
1190 const moneypunct<char, true>&
1191 use_facet<moneypunct<char, true> >(const locale&);
1194 const moneypunct<char, false>&
1195 use_facet<moneypunct<char, false> >(const locale&);
1198 const money_put<char>&
1199 use_facet<money_put<char> >(const locale&);
1202 const money_get<char>&
1203 use_facet<money_get<char> >(const locale&);
1206 const __timepunct<char>&
1207 use_facet<__timepunct<char> >(const locale&);
1210 const time_put<char>&
1211 use_facet<time_put<char> >(const locale&);
1214 const time_get<char>&
1215 use_facet<time_get<char> >(const locale&);
1218 const messages<char>&
1219 use_facet<messages<char> >(const locale&);
1223 has_facet<moneypunct<char> >(const locale&);
1227 has_facet<money_put<char> >(const locale&);
1231 has_facet<money_get<char> >(const locale&);
1235 has_facet<__timepunct<char> >(const locale&);
1239 has_facet<time_put<char> >(const locale&);
1243 has_facet<time_get<char> >(const locale&);
1247 has_facet<messages<char> >(const locale&);
1249 #ifdef _GLIBCXX_USE_WCHAR_T
1250 extern template class moneypunct<wchar_t, false>;
1251 extern template class moneypunct<wchar_t, true>;
1252 extern template class moneypunct_byname<wchar_t, false>;
1253 extern template class moneypunct_byname<wchar_t, true>;
1254 extern template class _GLIBCXX_LDBL_NAMESPACE money_get<wchar_t>;
1255 extern template class _GLIBCXX_LDBL_NAMESPACE money_put<wchar_t>;
1256 extern template class __timepunct<wchar_t>;
1257 extern template class time_put<wchar_t>;
1258 extern template class time_put_byname<wchar_t>;
1259 extern template class time_get<wchar_t>;
1260 extern template class time_get_byname<wchar_t>;
1261 extern template class messages<wchar_t>;
1262 extern template class messages_byname<wchar_t>;
1265 const moneypunct<wchar_t, true>&
1266 use_facet<moneypunct<wchar_t, true> >(const locale&);
1269 const moneypunct<wchar_t, false>&
1270 use_facet<moneypunct<wchar_t, false> >(const locale&);
1273 const money_put<wchar_t>&
1274 use_facet<money_put<wchar_t> >(const locale&);
1277 const money_get<wchar_t>&
1278 use_facet<money_get<wchar_t> >(const locale&);
1281 const __timepunct<wchar_t>&
1282 use_facet<__timepunct<wchar_t> >(const locale&);
1285 const time_put<wchar_t>&
1286 use_facet<time_put<wchar_t> >(const locale&);
1289 const time_get<wchar_t>&
1290 use_facet<time_get<wchar_t> >(const locale&);
1293 const messages<wchar_t>&
1294 use_facet<messages<wchar_t> >(const locale&);
1298 has_facet<moneypunct<wchar_t> >(const locale&);
1302 has_facet<money_put<wchar_t> >(const locale&);
1306 has_facet<money_get<wchar_t> >(const locale&);
1310 has_facet<__timepunct<wchar_t> >(const locale&);
1314 has_facet<time_put<wchar_t> >(const locale&);
1318 has_facet<time_get<wchar_t> >(const locale&);
1322 has_facet<messages<wchar_t> >(const locale&);
1326 _GLIBCXX_END_NAMESPACE