1 // Locale support -*- C++ -*-
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
4 // Free Software Foundation, Inc.
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING. If not, write to the Free
19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction. Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License. This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
31 // Warning: this file is not meant for user inclusion. Use <locale>.
33 #ifndef _CPP_BITS_LOCFACETS_TCC
34 #define _CPP_BITS_LOCFACETS_TCC 1
37 #include <clocale> // For localeconv
38 #include <cstdlib> // For strof, strtold
39 #include <cmath> // For ceil
40 #include <cctype> // For isspace
41 #include <limits> // For numeric_limits
42 #include <memory> // For auto_ptr
43 #include <bits/streambuf_iterator.h>
45 #include <typeinfo> // For bad_cast.
49 template<typename _Facet>
51 locale::combine(const locale& __other) const
53 _Impl* __tmp = new _Impl(*_M_impl, 1);
54 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
58 template<typename _CharT, typename _Traits, typename _Alloc>
60 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
61 const basic_string<_CharT, _Traits, _Alloc>& __s2) const
63 typedef std::collate<_CharT> __collate_type;
64 const __collate_type& __collate = use_facet<__collate_type>(*this);
65 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
66 __s2.data(), __s2.data() + __s2.length()) < 0);
69 template<typename _Facet>
71 use_facet(const locale& __loc)
73 size_t __i = _Facet::id._M_index;
74 locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets;
75 const locale::facet* __fp = (*__facet)[__i];
76 if (__fp == 0 || __i >= __facet->size())
78 return static_cast<const _Facet&>(*__fp);
81 template<typename _Facet>
83 has_facet(const locale& __loc) throw()
85 size_t __i = _Facet::id._M_index;
86 locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets;
87 return (__i < __facet->size() && (*__facet)[__i] != 0);
91 // Stage 1: Determine a conversion specifier.
92 template<typename _CharT, typename _InIter>
94 num_get<_CharT, _InIter>::
95 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
96 ios_base::iostate& __err, string& __xtrc) const
98 const locale __loc = __io.getloc();
99 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
100 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
102 // First check for sign.
103 const char_type __plus = __ctype.widen('+');
104 const char_type __minus = __ctype.widen('-');
106 char_type __c = *__beg;
107 if ((__c == __plus || __c == __minus) && __beg != __end)
109 __xtrc += __ctype.narrow(__c, char());
114 // Next, strip leading zeros.
115 const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
116 bool __found_zero = false;
117 while (__c == __zero && __beg != __end)
124 __xtrc += _S_atoms[_M_zero];
128 // Only need acceptable digits for floating point numbers.
129 const size_t __len = _M_E - _M_zero + 1;
130 char_type __watoms[__len];
131 __ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
132 bool __found_dec = false;
133 bool __found_sci = false;
134 const char_type __dec = __np.decimal_point();
136 string __found_grouping;
137 const string __grouping = __np.grouping();
138 bool __check_grouping = __grouping.size();
140 const char_type __sep = __np.thousands_sep();
142 while (__beg != __end)
144 // Only look in digits.
145 typedef char_traits<_CharT> __traits_type;
146 const char_type* __p = __traits_type::find(__watoms, 10, __c);
148 // NB: strchr returns true for __c == 0x0
151 // Try first for acceptable digit; record it if found.
153 __xtrc += _S_atoms[__p - __watoms];
157 else if (__c == __sep && __check_grouping && !__found_dec)
159 // NB: Thousands separator at the beginning of a string
160 // is a no-no, as is two consecutive thousands separators.
163 __found_grouping += static_cast<char>(__sep_pos);
169 __err |= ios_base::failbit;
173 else if (__c == __dec && !__found_dec)
175 __found_grouping += static_cast<char>(__sep_pos);
181 else if ((__c == __watoms[_M_e] || __c == __watoms[_M_E])
182 && !__found_sci && __pos)
184 // Scientific notation.
186 __xtrc += __ctype.narrow(__c, char());
189 // Remove optional plus or minus sign, if they exist.
190 if (__c == __plus || __c == __minus)
193 __xtrc += __ctype.narrow(__c, char());
199 // Not a valid input item.
203 // Digit grouping is checked. If grouping and found_grouping don't
204 // match, then get very very upset, and set failbit.
205 if (__check_grouping && __found_grouping.size())
207 // Add the ending grouping if a decimal wasn't found.
209 __found_grouping += static_cast<char>(__sep_pos);
210 if (!__verify_grouping(__grouping, __found_grouping))
211 __err |= ios_base::failbit;
217 __err |= ios_base::eofbit;
221 // Stage 1: Determine a conversion specifier.
222 template<typename _CharT, typename _InIter>
224 num_get<_CharT, _InIter>::
225 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
226 ios_base::iostate& __err, string& __xtrc, int& __base) const
228 const locale __loc = __io.getloc();
229 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
230 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
232 // NB: Iff __basefield == 0, this can change based on contents.
233 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
234 if (__basefield == ios_base::oct)
236 else if (__basefield == ios_base::hex)
241 // First check for sign.
243 char_type __c = *__beg;
244 if ((__c == __ctype.widen('+') || __c == __ctype.widen('-'))
247 __xtrc += __ctype.narrow(__c, char());
252 // Next, strip leading zeros and check required digits for base formats.
253 const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
254 const char_type __x = __ctype.widen('x');
255 const char_type __X = __ctype.widen('X');
258 bool __found_zero = false;
259 while (__c == __zero && __beg != __end)
266 __xtrc += _S_atoms[_M_zero];
268 if (__basefield == 0)
270 if ((__c == __x || __c == __X) && __beg != __end)
272 __xtrc += __ctype.narrow(__c, char());
282 else if (__base == 16)
284 if (__c == __zero && __beg != __end)
286 __xtrc += _S_atoms[_M_zero];
289 if ((__c == __x || __c == __X) && __beg != __end)
291 __xtrc += __ctype.narrow(__c, char());
298 // At this point, base is determined. If not hex, only allow
299 // base digits as valid input.
307 char_type __watoms[_M_size];
308 __ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
309 string __found_grouping;
310 const string __grouping = __np.grouping();
311 bool __check_grouping = __grouping.size() && __base == 10;
313 const char_type __sep = __np.thousands_sep();
314 while (__beg != __end)
316 typedef char_traits<_CharT> __traits_type;
317 const char_type* __p = __traits_type::find(__watoms, __len, __c);
319 // NB: strchr returns true for __c == 0x0
322 // Try first for acceptable digit; record it if found.
323 __xtrc += _S_atoms[__p - __watoms];
328 else if (__c == __sep && __check_grouping)
330 // NB: Thousands separator at the beginning of a string
331 // is a no-no, as is two consecutive thousands separators.
334 __found_grouping += static_cast<char>(__sep_pos);
340 __err |= ios_base::failbit;
345 // Not a valid input item.
349 // Digit grouping is checked. If grouping and found_grouping don't
350 // match, then get very very upset, and set failbit.
351 if (__check_grouping && __found_grouping.size())
353 // Add the ending grouping.
354 __found_grouping += static_cast<char>(__sep_pos);
355 if (!__verify_grouping(__grouping, __found_grouping))
356 __err |= ios_base::failbit;
362 __err |= ios_base::eofbit;
366 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
367 //17. Bad bool parsing
368 template<typename _CharT, typename _InIter>
370 num_get<_CharT, _InIter>::
371 do_get(iter_type __beg, iter_type __end, ios_base& __io,
372 ios_base::iostate& __err, bool& __v) const
374 // Parse bool values as unsigned long
375 if (!(__io.flags() & ios_base::boolalpha))
377 // NB: We can't just call do_get(long) here, as it might
378 // refer to a derived class.
381 // According to 18.2.1.2.9, digits10 is "Number of base 10 digits
382 // that can be represented without change" so we have to add 1 to it
383 // in order to obtain the max number of digits. The same for the
384 // other do_get for integral types below.
385 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
388 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
389 if (!(__err & ios_base::failbit) && __ul <= 1)
392 __err |= ios_base::failbit;
395 // Parse bool values as alphanumeric
398 locale __loc = __io.getloc();
399 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
400 const char_type* __true = __np.truename().c_str();
401 const char_type* __false = __np.falsename().c_str();
403 const size_t __truen = __np.truename().size() - 1;
404 const size_t __falsen = __np.falsename().size() - 1;
406 for (size_t __n = 0; __beg != __end; ++__n)
408 char_type __c = *__beg++;
409 bool __testf = __n <= __falsen ? __c == __false[__n] : false;
410 bool __testt = __n <= __truen ? __c == __true[__n] : false;
411 if (!(__testf || __testt))
413 __err |= ios_base::failbit;
416 else if (__testf && __n == __falsen)
421 else if (__testt && __n == __truen)
428 __err |= ios_base::eofbit;
434 template<typename _CharT, typename _InIter>
436 num_get<_CharT, _InIter>::
437 do_get(iter_type __beg, iter_type __end, ios_base& __io,
438 ios_base::iostate& __err, long& __v) const
442 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
443 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
447 template<typename _CharT, typename _InIter>
449 num_get<_CharT, _InIter>::
450 do_get(iter_type __beg, iter_type __end, ios_base& __io,
451 ios_base::iostate& __err, unsigned short& __v) const
455 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
457 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
458 if (!(__err & ios_base::failbit)
459 && __ul <= numeric_limits<unsigned short>::max())
460 __v = static_cast<unsigned short>(__ul);
462 __err |= ios_base::failbit;
466 template<typename _CharT, typename _InIter>
468 num_get<_CharT, _InIter>::
469 do_get(iter_type __beg, iter_type __end, ios_base& __io,
470 ios_base::iostate& __err, unsigned int& __v) const
474 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
476 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
477 if (!(__err & ios_base::failbit)
478 && __ul <= numeric_limits<unsigned int>::max())
479 __v = static_cast<unsigned int>(__ul);
481 __err |= ios_base::failbit;
485 template<typename _CharT, typename _InIter>
487 num_get<_CharT, _InIter>::
488 do_get(iter_type __beg, iter_type __end, ios_base& __io,
489 ios_base::iostate& __err, unsigned long& __v) const
493 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
494 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
498 #ifdef _GLIBCPP_USE_LONG_LONG
499 template<typename _CharT, typename _InIter>
501 num_get<_CharT, _InIter>::
502 do_get(iter_type __beg, iter_type __end, ios_base& __io,
503 ios_base::iostate& __err, long long& __v) const
507 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
508 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
512 template<typename _CharT, typename _InIter>
514 num_get<_CharT, _InIter>::
515 do_get(iter_type __beg, iter_type __end, ios_base& __io,
516 ios_base::iostate& __err, unsigned long long& __v) const
520 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
521 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
526 template<typename _CharT, typename _InIter>
528 num_get<_CharT, _InIter>::
529 do_get(iter_type __beg, iter_type __end, ios_base& __io,
530 ios_base::iostate& __err, float& __v) const
534 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
535 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
539 template<typename _CharT, typename _InIter>
541 num_get<_CharT, _InIter>::
542 do_get(iter_type __beg, iter_type __end, ios_base& __io,
543 ios_base::iostate& __err, double& __v) const
547 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
548 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
552 template<typename _CharT, typename _InIter>
554 num_get<_CharT, _InIter>::
555 do_get(iter_type __beg, iter_type __end, ios_base& __io,
556 ios_base::iostate& __err, long double& __v) const
560 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
561 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
565 template<typename _CharT, typename _InIter>
567 num_get<_CharT, _InIter>::
568 do_get(iter_type __beg, iter_type __end, ios_base& __io,
569 ios_base::iostate& __err, void*& __v) const
571 // Prepare for hex formatted input
572 typedef ios_base::fmtflags fmtflags;
573 fmtflags __fmt = __io.flags();
574 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
575 | ios_base::uppercase | ios_base::internal);
576 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
580 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
582 // Reset from hex formatted input
586 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
587 if (!(__err & ios_base::failbit))
588 __v = reinterpret_cast<void*>(__ul);
590 __err |= ios_base::failbit;
595 // The following code uses sprintf() to convert floating point
596 // values for insertion into a stream. An optimization would be to
597 // replace sprintf() with code that works directly on a wide buffer
598 // and then use __pad to do the padding. It would be good
599 // to replace sprintf() anyway to avoid accidental buffer overruns
600 // and to gain back the efficiency that C++ provides by knowing up
601 // front the type of the values to insert. This implementation
602 // follows the C++ standard fairly directly as outlined in 22.2.2.2
603 // [lib.locale.num.put]
604 template<typename _CharT, typename _OutIter>
605 template<typename _ValueT>
607 num_put<_CharT, _OutIter>::
608 _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
611 const int __max_digits = numeric_limits<_ValueT>::digits10;
612 streamsize __prec = __io.precision();
613 // Protect against sprintf() buffer overflows.
614 if (__prec > static_cast<streamsize>(__max_digits))
615 __prec = static_cast<streamsize>(__max_digits);
617 // Long enough for the max format spec.
620 // Consider the possibility of long ios_base::fixed outputs
621 const bool __fixed = __io.flags() & ios_base::fixed;
622 const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
623 // ios_base::fixed outputs may need up to __max_exp+1 chars
624 // for the integer part + up to __max_digits chars for the
625 // fractional part + 3 chars for sign, decimal point, '\0'. On
626 // the other hand, for non-fixed outputs __max_digits*3 chars
627 // are largely sufficient.
628 const int __cs_size = __fixed ? __max_exp + __max_digits + 4
630 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
633 // [22.2.2.2.2] Stage 1, numeric conversion to character.
634 if (_S_format_float(__io, __fbuf, __mod, __prec))
635 __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale, __prec);
637 __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale);
638 return _M_widen_float(__s, __io, __fill, __cs, __len);
641 template<typename _CharT, typename _OutIter>
642 template<typename _ValueT>
644 num_put<_CharT, _OutIter>::
645 _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
646 char __modl, _ValueT __v) const
648 // [22.2.2.2.2] Stage 1, numeric conversion to character.
649 // Leave room for "+/-," "0x," and commas. This size is
650 // arbitrary, but should work.
652 // Long enough for the max format spec.
654 _S_format_int(__io, __fbuf, __mod, __modl);
655 int __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale);
656 return _M_widen_int(__s, __io, __fill, __cs, __len);
659 template<typename _CharT, typename _OutIter>
661 num_put<_CharT, _OutIter>::
662 _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
665 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
666 // numpunct.decimal_point() values for '.' and adding grouping.
667 const locale __loc = __io.getloc();
668 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
669 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
671 // Grouping can add (almost) as many separators as the number of
672 // digits, but no more.
673 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
675 __ctype.widen(__cs, __cs + __len, __ws);
677 // Replace decimal point.
679 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
680 if (__p = char_traits<_CharT>::find(__ws, __len, __ctype.widen('.')))
681 __ws[__p - __ws] = __np.decimal_point();
683 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
684 //282. What types does numpunct grouping refer to?
685 // Add grouping, if necessary.
686 const string __grouping = __np.grouping();
687 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
688 if (__grouping.size())
691 int __declen = __p ? __p - __ws : __len;
692 __p2 = __add_grouping(__ws2, __np.thousands_sep(),
694 __grouping.c_str() + __grouping.size(),
695 __ws, __ws + __declen);
696 int __newlen = __p2 - __ws2;
698 // Tack on decimal part.
701 char_traits<_CharT>::copy(__p2, __p, __len - __declen);
702 __newlen += __len - __declen;
705 // Switch strings, establish correct new length.
710 return _M_insert(__s, __io, __fill, __ws, __len);
713 template<typename _CharT, typename _OutIter>
715 num_put<_CharT, _OutIter>::
716 _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
719 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
720 // numpunct.decimal_point() values for '.' and adding grouping.
721 const locale __loc = __io.getloc();
722 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
723 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
725 // Grouping can add (almost) as many separators as the number of
726 // digits, but no more.
727 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
729 __ctype.widen(__cs, __cs + __len, __ws);
731 // Add grouping, if necessary.
732 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
733 const string __grouping = __np.grouping();
734 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
735 bool __dec = __basefield != ios_base::oct
736 && __basefield != ios_base::hex;
737 if (__grouping.size() && __dec)
740 __p = __add_grouping(__ws2, __np.thousands_sep(), __grouping.c_str(),
741 __grouping.c_str() + __grouping.size(),
747 return _M_insert(__s, __io, __fill, __ws, __len);
750 // For use by integer and floating-point types after they have been
751 // converted into a char_type string.
752 template<typename _CharT, typename _OutIter>
754 num_put<_CharT, _OutIter>::
755 _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws,
758 // [22.2.2.2.2] Stage 3.
759 streamsize __w = __io.width();
760 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
762 if (__w > static_cast<streamsize>(__len))
764 __pad(__io, __fill, __ws2, __ws, __w, __len, true);
765 __len = static_cast<int>(__w);
771 // [22.2.2.2.2] Stage 4.
772 // Write resulting, fully-formatted string to output iterator.
773 for (int __j = 0; __j < __len; ++__j, ++__s)
778 template<typename _CharT, typename _OutIter>
780 num_put<_CharT, _OutIter>::
781 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
783 ios_base::fmtflags __flags = __io.flags();
784 if ((__flags & ios_base::boolalpha) == 0)
786 unsigned long __uv = __v;
787 __s = _M_convert_int(__s, __io, __fill, 'u', char_type(), __uv);
791 locale __loc = __io.getloc();
792 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
793 const char_type* __ws;
797 __ws = __np.truename().c_str();
798 __len = __np.truename().size();
802 __ws = __np.falsename().c_str();
803 __len = __np.falsename().size();
805 __s = _M_insert(__s, __io, __fill, __ws, __len);
810 template<typename _CharT, typename _OutIter>
812 num_put<_CharT, _OutIter>::
813 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
814 { return _M_convert_int(__s, __io, __fill, 'd', char_type(), __v); }
816 template<typename _CharT, typename _OutIter>
818 num_put<_CharT, _OutIter>::
819 do_put(iter_type __s, ios_base& __io, char_type __fill,
820 unsigned long __v) const
821 { return _M_convert_int(__s, __io, __fill, 'u', char_type(), __v); }
823 #ifdef _GLIBCPP_USE_LONG_LONG
824 template<typename _CharT, typename _OutIter>
826 num_put<_CharT, _OutIter>::
827 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
828 { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); }
830 template<typename _CharT, typename _OutIter>
832 num_put<_CharT, _OutIter>::
833 do_put(iter_type __s, ios_base& __io, char_type __fill,
834 unsigned long long __v) const
835 { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); }
838 template<typename _CharT, typename _OutIter>
840 num_put<_CharT, _OutIter>::
841 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
842 { return _M_convert_float(__s, __io, __fill, char_type(), __v); }
844 template<typename _CharT, typename _OutIter>
846 num_put<_CharT, _OutIter>::
847 do_put(iter_type __s, ios_base& __io, char_type __fill,
848 long double __v) const
849 { return _M_convert_float(__s, __io, __fill, 'L', __v); }
851 template<typename _CharT, typename _OutIter>
853 num_put<_CharT, _OutIter>::
854 do_put(iter_type __s, ios_base& __io, char_type __fill,
855 const void* __v) const
857 ios_base::fmtflags __flags = __io.flags();
858 ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
859 | ios_base::uppercase | ios_base::internal);
860 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
863 __s = _M_convert_int(__s, __io, __fill, 'u', char_type(),
864 reinterpret_cast<unsigned long>(__v));
870 __throw_exception_again;
876 template<typename _CharT, typename _InIter>
878 money_get<_CharT, _InIter>::
879 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
880 ios_base::iostate& __err, long double& __units) const
883 __beg = this->do_get(__beg, __end, __intl, __io, __err, __str);
885 const int __n = numeric_limits<long double>::digits10;
886 char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
887 const locale __loc = __io.getloc();
888 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
889 const _CharT* __wcs = __str.c_str();
890 __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);
891 __convert_to_v(__cs, __units, __err, _S_c_locale);
895 template<typename _CharT, typename _InIter>
897 money_get<_CharT, _InIter>::
898 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
899 ios_base::iostate& __err, string_type& __units) const
901 // These contortions are quite unfortunate.
902 typedef moneypunct<_CharT, true> __money_true;
903 typedef moneypunct<_CharT, false> __money_false;
904 typedef money_base::part part;
905 typedef typename string_type::size_type size_type;
907 const locale __loc = __io.getloc();
908 const __money_true& __mpt = use_facet<__money_true>(__loc);
909 const __money_false& __mpf = use_facet<__money_false>(__loc);
910 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
912 const money_base::pattern __p = __intl ? __mpt.neg_format()
913 : __mpf.neg_format();
915 const string_type __pos_sign =__intl ? __mpt.positive_sign()
916 : __mpf.positive_sign();
917 const string_type __neg_sign =__intl ? __mpt.negative_sign()
918 : __mpf.negative_sign();
919 const char_type __d = __intl ? __mpt.decimal_point()
920 : __mpf.decimal_point();
921 const char_type __sep = __intl ? __mpt.thousands_sep()
922 : __mpf.thousands_sep();
924 const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
926 // Set to deduced positive or negative sign, depending.
928 // String of grouping info from thousands_sep plucked from __units.
929 string __grouping_tmp;
930 // Marker for thousands_sep position.
932 // If input iterator is in a valid state.
933 bool __testvalid = true;
934 // Flag marking when a decimal point is found.
935 bool __testdecfound = false;
937 char_type __c = *__beg;
938 char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
939 for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
941 part __which = static_cast<part>(__p.field[__i]);
944 case money_base::symbol:
945 if (__io.flags() & ios_base::showbase)
947 // Symbol is required.
948 const string_type __symbol = __intl ? __mpt.curr_symbol()
949 : __mpf.curr_symbol();
950 size_type __len = __symbol.size();
952 while (__beg != __end
953 && __i < __len && __symbol[__i] == __c)
962 case money_base::sign:
963 // Sign might not exist, or be more than one character long.
964 if (__pos_sign.size() && __neg_sign.size())
966 // Sign is mandatory.
967 if (__c == __pos_sign[0])
972 else if (__c == __neg_sign[0])
980 else if (__pos_sign.size() && __c == __pos_sign[0])
985 else if (__neg_sign.size() && __c == __neg_sign[0])
991 case money_base::value:
992 // Extract digits, remove and stash away the
993 // grouping of found thousands separators.
994 while (__beg != __end
995 && (__ctype.is(ctype_base::digit, __c)
996 || (__c == __d && !__testdecfound)
1001 __grouping_tmp += static_cast<char>(__sep_pos);
1003 __testdecfound = true;
1005 else if (__c == __sep)
1007 if (__grouping.size())
1009 // Mark position for later analysis.
1010 __grouping_tmp += static_cast<char>(__sep_pos);
1015 __testvalid = false;
1027 case money_base::space:
1028 case money_base::none:
1029 // Only if not at the end of the pattern.
1031 while (__beg != __end
1032 && __ctype.is(ctype_base::space, __c))
1038 // Need to get the rest of the sign characters, if they exist.
1039 if (__sign.size() > 1)
1041 size_type __len = __sign.size();
1043 for (; __c != __eof && __i < __len; ++__i)
1044 while (__beg != __end && __c != __sign[__i])
1048 __testvalid = false;
1051 // Strip leading zeros.
1052 while (__units[0] == __ctype.widen('0'))
1053 __units.erase(__units.begin());
1055 if (__sign.size() && __sign == __neg_sign)
1056 __units.insert(__units.begin(), __ctype.widen('-'));
1058 // Test for grouping fidelity.
1059 if (__grouping.size() && __grouping_tmp.size())
1061 if (!__verify_grouping(__grouping, __grouping_tmp))
1062 __testvalid = false;
1065 // Iff no more characters are available.
1067 __err |= ios_base::eofbit;
1069 // Iff valid sequence is not recognized.
1070 if (!__testvalid || !__units.size())
1071 __err |= ios_base::failbit;
1075 template<typename _CharT, typename _OutIter>
1077 money_put<_CharT, _OutIter>::
1078 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1079 long double __units) const
1081 const locale __loc = __io.getloc();
1082 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1083 const int __n = numeric_limits<long double>::digits10;
1084 char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
1085 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
1086 int __len = __convert_from_v(__cs, "%.01Lf", __units, _S_c_locale);
1087 __ctype.widen(__cs, __cs + __len, __ws);
1088 string_type __digits(__ws);
1089 return this->do_put(__s, __intl, __io, __fill, __digits);
1092 template<typename _CharT, typename _OutIter>
1094 money_put<_CharT, _OutIter>::
1095 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1096 const string_type& __digits) const
1098 typedef typename string_type::size_type size_type;
1099 typedef money_base::part part;
1101 const locale __loc = __io.getloc();
1102 const size_type __width = static_cast<size_type>(__io.width());
1104 // These contortions are quite unfortunate.
1105 typedef moneypunct<_CharT, true> __money_true;
1106 typedef moneypunct<_CharT, false> __money_false;
1107 const __money_true& __mpt = use_facet<__money_true>(__loc);
1108 const __money_false& __mpf = use_facet<__money_false>(__loc);
1109 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1111 // Determine if negative or positive formats are to be used, and
1112 // discard leading negative_sign if it is present.
1113 const char_type* __beg = __digits.data();
1114 const char_type* __end = __beg + __digits.size();
1115 money_base::pattern __p;
1117 if (*__beg != __ctype.widen('-'))
1119 __p = __intl ? __mpt.pos_format() : __mpf.pos_format();
1120 __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
1124 __p = __intl ? __mpt.neg_format() : __mpf.neg_format();
1125 __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
1129 // Look for valid numbers in the current ctype facet within input digits.
1130 __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
1133 // Assume valid input, and attempt to format.
1134 // Break down input numbers into base components, as follows:
1135 // final_value = grouped units + (decimal point) + (digits)
1137 string_type __value;
1138 const string_type __symbol = __intl ? __mpt.curr_symbol()
1139 : __mpf.curr_symbol();
1141 // Deal with decimal point, decimal digits.
1142 const int __frac = __intl ? __mpt.frac_digits()
1143 : __mpf.frac_digits();
1146 const char_type __d = __intl ? __mpt.decimal_point()
1147 : __mpf.decimal_point();
1148 if (__end - __beg >= __frac)
1150 __value = string_type(__end - __frac, __end);
1151 __value.insert(__value.begin(), __d);
1156 // Have to pad zeros in the decimal position.
1157 __value = string_type(__beg, __end);
1158 int __paddec = __frac - (__end - __beg);
1159 char_type __zero = __ctype.widen('0');
1160 __value.insert(__value.begin(), __paddec, __zero);
1161 __value.insert(__value.begin(), __d);
1166 // Add thousands separators to non-decimal digits, per
1170 const string __grouping = __intl ? __mpt.grouping()
1172 if (__grouping.size())
1174 const char_type __sep = __intl ? __mpt.thousands_sep()
1175 : __mpf.thousands_sep();
1176 const char* __gbeg = __grouping.c_str();
1177 const char* __gend = __gbeg + __grouping.size();
1178 const int __n = numeric_limits<long double>::digits10 * 2;
1179 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
1180 _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg,
1181 __gend, __beg, __end);
1182 __value.insert(0, __ws2, __ws_end - __ws2);
1185 __value.insert(0, string_type(__beg, __end));
1188 // Calculate length of resulting string.
1189 ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
1190 size_type __len = __value.size() + __sign.size();
1191 __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
1192 bool __testipad = __f == ios_base::internal && __len < __width;
1194 // Fit formatted digits into the required pattern.
1195 for (int __i = 0; __i < 4; ++__i)
1197 part __which = static_cast<part>(__p.field[__i]);
1200 case money_base::symbol:
1201 if (__io.flags() & ios_base::showbase)
1204 case money_base::sign:
1205 // Sign might not exist, or be more than one
1206 // charater long. In that case, add in the rest
1211 case money_base::value:
1214 case money_base::space:
1215 // At least one space is required, but if internal
1216 // formatting is required, an arbitrary number of
1217 // fill spaces will be necessary.
1219 __res += string_type(__width - __len, __fill);
1221 __res += __ctype.widen(' ');
1223 case money_base::none:
1225 __res += string_type(__width - __len, __fill);
1230 // Special case of multi-part sign parts.
1231 if (__sign.size() > 1)
1232 __res += string_type(__sign.begin() + 1, __sign.end());
1234 // Pad, if still necessary.
1235 __len = __res.size();
1236 if (__width > __len)
1238 if (__f == ios_base::left)
1240 __res.append(__width - __len, __fill);
1243 __res.insert(0, string_type(__width - __len, __fill));
1247 // Write resulting, fully-formatted string to output iterator.
1248 for (size_type __j = 0; __j < __len; ++__j, ++__s)
1256 // NB: Not especially useful. Without an ios_base object or some
1257 // kind of locale reference, we are left clawing at the air where
1258 // the side of the mountain used to be...
1259 template<typename _CharT, typename _InIter>
1260 time_base::dateorder
1261 time_get<_CharT, _InIter>::do_date_order() const
1262 { return time_base::no_order; }
1264 template<typename _CharT, typename _InIter>
1266 time_get<_CharT, _InIter>::
1267 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
1268 ios_base::iostate& __err, tm* __tm,
1269 const _CharT* __format) const
1271 locale __loc = __io.getloc();
1272 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1273 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1274 size_t __len = char_traits<_CharT>::length(__format);
1276 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
1278 char __c = __format[__i];
1281 // Verify valid formatting code, attempt to extract.
1282 __c = __format[++__i];
1285 if (__c == 'E' || __c == 'O')
1288 __c = __format[++__i];
1295 // Abbreviated weekday name [tm_wday]
1296 const char_type* __days1[7];
1297 __tp._M_days_abbreviated(__days1);
1298 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7,
1302 // Weekday name [tm_wday].
1303 const char_type* __days2[7];
1304 __tp._M_days(__days2);
1305 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7,
1310 // Abbreviated month name [tm_mon]
1311 const char_type* __months1[12];
1312 __tp._M_months_abbreviated(__months1);
1313 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12,
1317 // Month name [tm_mon].
1318 const char_type* __months2[12];
1319 __tp._M_months(__months2);
1320 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12,
1324 // Default time and date representation.
1325 const char_type* __dt[2];
1326 __tp._M_date_time_formats(__dt);
1327 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1331 // Day [01, 31]. [tm_mday]
1332 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
1336 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
1338 __ctype.widen(__cs, __cs + 9, __wcs);
1339 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1343 // Hour [00, 23]. [tm_hour]
1344 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1348 // Hour [01, 12]. [tm_hour]
1349 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
1353 // Month [01, 12]. [tm_mon]
1354 _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype,
1357 __tm->tm_mon = __mem - 1;
1360 // Minute [00, 59]. [tm_min]
1361 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1365 if (__ctype.narrow(*__beg, 0) == '\n')
1368 __err |= ios_base::failbit;
1371 // Equivalent to (%H:%M).
1373 __ctype.widen(__cs, __cs + 6, __wcs);
1374 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1379 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
1383 if (__ctype.narrow(*__beg, 0) == '\t')
1386 __err |= ios_base::failbit;
1389 // Equivalent to (%H:%M:%S).
1391 __ctype.widen(__cs, __cs + 9, __wcs);
1392 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1397 const char_type* __dates[2];
1398 __tp._M_date_formats(__dates);
1399 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1404 const char_type* __times[2];
1405 __tp._M_time_formats(__times);
1406 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1410 // Two digit year. [tm_year]
1411 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
1415 // Year [1900). [tm_year]
1416 _M_extract_num(__beg, __end, __mem, 0,
1417 numeric_limits<int>::max(), 4,
1420 __tm->tm_year = __mem - 1900;
1424 if (__ctype.is(ctype_base::upper, *__beg))
1427 _M_extract_name(__beg, __end, __tmp,
1428 __timepunct<_CharT>::_S_timezones,
1431 // GMT requires special effort.
1432 char_type __c = *__beg;
1433 if (!__err && __tmp == 0
1434 && (__c == __ctype.widen('-')
1435 || __c == __ctype.widen('+')))
1437 _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1439 _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1444 __err |= ios_base::failbit;
1448 __err |= ios_base::failbit;
1453 // Verify format and input match, extract and discard.
1454 if (__c == __ctype.narrow(*__beg, 0))
1457 __err |= ios_base::failbit;
1462 template<typename _CharT, typename _InIter>
1464 time_get<_CharT, _InIter>::
1465 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
1466 int __min, int __max, size_t __len,
1467 const ctype<_CharT>& __ctype,
1468 ios_base::iostate& __err) const
1472 bool __testvalid = true;
1473 char_type __c = *__beg;
1474 while (__beg != __end && __i < __len
1475 && __ctype.is(ctype_base::digit, __c))
1477 __digits += __ctype.narrow(__c, 0);
1483 int __value = atoi(__digits.c_str());
1484 if (__min <= __value && __value <= __max)
1487 __testvalid = false;
1490 __testvalid = false;
1492 __err |= ios_base::failbit;
1496 // All elements in __names are unique.
1497 template<typename _CharT, typename _InIter>
1499 time_get<_CharT, _InIter>::
1500 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
1501 const _CharT** __names, size_t __indexlen,
1502 ios_base::iostate& __err) const
1504 typedef char_traits<char_type> __traits_type;
1505 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen));
1506 size_t __nmatches = 0;
1508 bool __testvalid = true;
1509 const char_type* __name;
1511 char_type __c = *__beg;
1512 // Look for initial matches.
1513 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1514 if (__c == __names[__i1][0])
1515 __matches[__nmatches++] = __i1;
1517 while(__nmatches > 1)
1519 // Find smallest matching string.
1520 size_t __minlen = 10;
1521 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
1522 __minlen = min(__minlen,
1523 __traits_type::length(__names[__matches[__i2]]));
1525 if (__pos < __minlen && __beg != __end)
1529 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1531 __name = __names[__matches[__i3]];
1532 if (__name[__pos] != __c)
1533 __matches[__i3] = __matches[--__nmatches];
1540 if (__nmatches == 1)
1542 // Make sure found name is completely extracted.
1543 __name = __names[__matches[0]];
1544 const size_t __len = __traits_type::length(__name);
1545 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
1549 __member = __matches[0];
1551 __testvalid = false;
1554 __testvalid = false;
1556 __err |= ios_base::failbit;
1559 template<typename _CharT, typename _InIter>
1561 time_get<_CharT, _InIter>::
1562 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1563 ios_base::iostate& __err, tm* __tm) const
1566 const char* __cs = "%X";
1567 locale __loc = __io.getloc();
1568 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1569 __ctype.widen(__cs, __cs + 3, __wcs);
1570 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1572 __err |= ios_base::eofbit;
1576 template<typename _CharT, typename _InIter>
1578 time_get<_CharT, _InIter>::
1579 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1580 ios_base::iostate& __err, tm* __tm) const
1583 const char* __cs = "%x";
1584 locale __loc = __io.getloc();
1585 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1586 __ctype.widen(__cs, __cs + 3, __wcs);
1587 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1589 __err |= ios_base::eofbit;
1593 template<typename _CharT, typename _InIter>
1595 time_get<_CharT, _InIter>::
1596 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1597 ios_base::iostate& __err, tm* __tm) const
1599 typedef char_traits<char_type> __traits_type;
1600 locale __loc = __io.getloc();
1601 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1602 const char_type* __days[7];
1603 __tp._M_days_abbreviated(__days);
1605 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err);
1607 // Check to see if non-abbreviated name exists, and extract.
1608 // NB: Assumes both _M_days and _M_days_abbreviated organized in
1609 // exact same order, first to last, such that the resulting
1610 // __days array with the same index points to a day, and that
1611 // day's abbreviated form.
1612 // NB: Also assumes that an abbreviated name is a subset of the name.
1615 size_t __pos = __traits_type::length(__days[__tmpwday]);
1616 __tp._M_days(__days);
1617 const char_type* __name = __days[__tmpwday];
1618 if (__name[__pos] == *__beg)
1620 // Extract the rest of it.
1621 const size_t __len = __traits_type::length(__name);
1622 while (__pos < __len && __beg != __end
1623 && __name[__pos] == *__beg)
1626 __err |= ios_base::failbit;
1629 __tm->tm_wday = __tmpwday;
1632 __err |= ios_base::eofbit;
1636 template<typename _CharT, typename _InIter>
1638 time_get<_CharT, _InIter>::
1639 do_get_monthname(iter_type __beg, iter_type __end,
1640 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1642 typedef char_traits<char_type> __traits_type;
1643 locale __loc = __io.getloc();
1644 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1645 const char_type* __months[12];
1646 __tp._M_months_abbreviated(__months);
1648 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err);
1650 // Check to see if non-abbreviated name exists, and extract.
1651 // NB: Assumes both _M_months and _M_months_abbreviated organized in
1652 // exact same order, first to last, such that the resulting
1653 // __months array with the same index points to a month, and that
1654 // month's abbreviated form.
1655 // NB: Also assumes that an abbreviated name is a subset of the name.
1658 size_t __pos = __traits_type::length(__months[__tmpmon]);
1659 __tp._M_months(__months);
1660 const char_type* __name = __months[__tmpmon];
1661 if (__name[__pos] == *__beg)
1663 // Extract the rest of it.
1664 const size_t __len = __traits_type::length(__name);
1665 while (__pos < __len && __beg != __end
1666 && __name[__pos] == *__beg)
1669 __err |= ios_base::failbit;
1672 __tm->tm_mon = __tmpmon;
1676 __err |= ios_base::eofbit;
1680 template<typename _CharT, typename _InIter>
1682 time_get<_CharT, _InIter>::
1683 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1684 ios_base::iostate& __err, tm* __tm) const
1686 locale __loc = __io.getloc();
1687 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1689 char_type __c = *__beg;
1692 while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c))
1694 __digits += __ctype.narrow(__c, 0);
1698 if (__i == 2 || __i == 4)
1701 __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale);
1702 if (!(__err & ios_base::failbit) && __l <= INT_MAX)
1704 __l = __i == 2 ? __l : __l - 1900;
1705 __tm->tm_year = static_cast<int>(__l);
1709 __err |= ios_base::failbit;
1711 __err |= ios_base::eofbit;
1715 template<typename _CharT, typename _OutIter>
1717 time_put<_CharT, _OutIter>::
1718 put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1719 const _CharT* __beg, const _CharT* __end) const
1721 locale __loc = __io.getloc();
1722 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1723 while (__beg != __end)
1725 char __c = __ctype.narrow(*__beg, 0);
1732 __c = __ctype.narrow(*__beg, 0);
1734 if (__c == 'E' || __c == 'O')
1737 __format = __ctype.narrow(*__beg, 0);
1742 __s = this->do_put(__s, __io, char_type(), __tm, __format,
1754 template<typename _CharT, typename _OutIter>
1756 time_put<_CharT, _OutIter>::
1757 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1758 char __format, char __mod) const
1760 locale __loc = __io.getloc();
1761 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1762 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1764 // NB: This size is arbitrary. Should this be a data member,
1765 // initialized at construction?
1766 const size_t __maxlen = 64;
1767 char_type* __res = static_cast<char_type*>(__builtin_alloca(__maxlen));
1769 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1770 // is possible that the format character will be longer than one
1771 // character. Possibilities include 'E' or 'O' followed by a
1772 // format character: if __mod is not the default argument, assume
1773 // it's a valid modifier.
1775 __fmt[0] = __ctype.widen('%');
1778 __fmt[1] = __format;
1779 __fmt[2] = char_type();
1784 __fmt[2] = __format;
1785 __fmt[3] = char_type();
1788 __tp._M_put_helper(__res, __maxlen, __fmt, __tm);
1790 // Write resulting, fully-formatted string to output iterator.
1791 size_t __len = char_traits<char_type>::length(__res);
1792 for (size_t __i = 0; __i < __len; ++__i, ++__s)
1798 // Generic version does nothing.
1799 template<typename _CharT>
1801 collate<_CharT>::_M_compare_helper(const _CharT*, const _CharT*) const
1804 // Generic version does nothing.
1805 template<typename _CharT>
1807 collate<_CharT>::_M_transform_helper(_CharT*, const _CharT*, size_t) const
1810 template<typename _CharT>
1813 do_compare(const _CharT* __lo1, const _CharT* __hi1,
1814 const _CharT* __lo2, const _CharT* __hi2) const
1816 const string_type __one(__lo1, __hi1);
1817 const string_type __two(__lo2, __hi2);
1818 return _M_compare_helper(__one.c_str(), __two.c_str());
1821 template<typename _CharT>
1822 typename collate<_CharT>::string_type
1824 do_transform(const _CharT* __lo, const _CharT* __hi) const
1826 size_t __len = __hi - __lo;
1827 _CharT* __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
1828 size_t __res = _M_transform_helper(__c, __lo, __len);
1831 // Try to increment size of translated string.
1832 size_t __len2 = __len * 2;
1833 _CharT* __c2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len2));
1834 __res = _M_transform_helper(__c2, __lo, __len);
1835 // XXX Throw exception if still indeterminate?
1837 return string_type(__c);
1840 template<typename _CharT>
1843 do_hash(const _CharT* __lo, const _CharT* __hi) const
1845 unsigned long __val = 0;
1846 for (; __lo < __hi; ++__lo)
1847 __val = *__lo + ((__val << 7) |
1848 (__val >> (numeric_limits<unsigned long>::digits - 1)));
1849 return static_cast<long>(__val);
1852 // Convert string to numeric value of type T and store results.
1853 // NB: This is specialized for all required types, there is no
1854 // generic definition.
1855 template<typename _T>
1857 __convert_to_v(const char* __in, _T& __out, ios_base::iostate& __err,
1858 const __c_locale& __cloc, int __base = 10);
1860 // Convert numeric value of type T to string and return length of string.
1861 template<typename _T>
1863 __convert_from_v(char* __out, const char* __fmt, _T __v,
1864 const __c_locale&, int __prec = -1)
1867 const char* __old = setlocale(LC_ALL, "C");
1869 __ret = sprintf(__out, __fmt, __prec, __v);
1871 __ret = sprintf(__out, __fmt, __v);
1872 setlocale(LC_ALL, __old);
1876 // Construct correctly padded string, as per 22.2.2.2.2
1878 // __newlen > __oldlen
1879 // __news is allocated for __newlen size
1880 // Used by both num_put and ostream inserters: if __num,
1881 // internal-adjusted objects are padded according to the rules below
1882 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
1884 template<typename _CharT, typename _Traits>
1886 __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds,
1887 const streamsize __newlen, const streamsize __oldlen,
1890 typedef _CharT char_type;
1891 typedef _Traits traits_type;
1892 typedef typename traits_type::int_type int_type;
1894 int_type __plen = static_cast<size_t>(__newlen - __oldlen);
1895 char_type* __pads = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen));
1896 traits_type::assign(__pads, __plen, __fill);
1901 size_t __beglen; //either __plen or __oldlen
1902 ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
1904 if (__adjust == ios_base::left)
1907 __beg = const_cast<char_type*>(__olds);
1908 __beglen = __oldlen;
1911 else if (__adjust == ios_base::internal && __num)
1913 // Pad after the sign, if there is one.
1914 // Pad after 0[xX], if there is one.
1915 // Who came up with these rules, anyway? Jeeze.
1916 locale __loc = __io.getloc();
1917 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1918 const char_type __minus = __ctype.widen('-');
1919 const char_type __plus = __ctype.widen('+');
1920 bool __testsign = __olds[0] == __minus || __olds[0] == __plus;
1921 bool __testhex = __ctype.widen('0') == __olds[0]
1922 && (__ctype.widen('x') == __olds[1]
1923 || __ctype.widen('X') == __olds[1]);
1926 __news[0] = __olds[0];
1927 __news[1] = __olds[1];
1932 __end = const_cast<char_type*>(__olds + __mod);
1934 else if (__testsign)
1936 __news[0] = __olds[0] == __plus ? __plus : __minus;
1941 __end = const_cast<char_type*>(__olds + __mod);
1948 __end = const_cast<char_type*>(__olds);
1956 __end = const_cast<char_type*>(__olds);
1958 traits_type::copy(__news, __beg, __beglen);
1959 traits_type::copy(__news + __beglen, __end, __newlen - __beglen - __mod);
1962 // NB: Can't have default argument on non-member template, and
1963 // num_put doesn't have a _Traits template parameter, so this
1964 // forwarding template adds in the default template argument.
1965 template<typename _CharT>
1967 __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds,
1968 const streamsize __newlen, const streamsize __oldlen,
1971 return __pad<_CharT, char_traits<_CharT> >(__io, __fill, __news, __olds,
1972 __newlen, __oldlen, __num);
1975 // Used by both numeric and monetary facets.
1976 // Check to make sure that the __grouping_tmp string constructed in
1977 // money_get or num_get matches the canonical grouping for a given
1979 // __grouping_tmp is parsed L to R
1980 // 1,222,444 == __grouping_tmp of "/1/3/3"
1981 // __grouping is parsed R to L
1982 // 1,222,444 == __grouping of "/3" == "/3/3/3"
1983 template<typename _CharT>
1985 __verify_grouping(const basic_string<_CharT>& __grouping,
1986 basic_string<_CharT>& __grouping_tmp)
1990 const int __len = __grouping.size();
1991 const int __n = __grouping_tmp.size();
1994 // Parsed number groupings have to match the
1995 // numpunct::grouping string exactly, starting at the
1996 // right-most point of the parsed sequence of elements ...
1997 while (__test && __i < __n - 1)
1998 for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
1999 __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1];
2000 // ... but the last parsed grouping can be <= numpunct
2002 __j == __len ? __j = 0 : __j;
2003 __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1];
2007 // Used by both numeric and monetary facets.
2008 // Inserts "group separator" characters into an array of characters.
2009 // It's recursive, one iteration per group. It moves the characters
2010 // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this
2011 // only with __gbeg != __gend.
2012 template<typename _CharT>
2014 __add_grouping(_CharT* __s, _CharT __sep,
2015 const char* __gbeg, const char* __gend,
2016 const _CharT* __first, const _CharT* __last)
2018 if (__last - __first > *__gbeg)
2020 __s = __add_grouping(__s, __sep,
2021 (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
2022 __gend, __first, __last - *__gbeg);
2023 __first = __last - *__gbeg;
2027 *__s++ = *__first++;
2028 while (__first != __last);