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 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
384 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
385 if (!(__err & ios_base::failbit) && __ul <= 1)
388 __err |= ios_base::failbit;
391 // Parse bool values as alphanumeric
394 locale __loc = __io.getloc();
395 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
396 const char_type* __true = __np.truename().c_str();
397 const char_type* __false = __np.falsename().c_str();
399 const size_t __truen = __np.truename().size() - 1;
400 const size_t __falsen = __np.falsename().size() - 1;
402 for (size_t __n = 0; __beg != __end; ++__n)
404 char_type __c = *__beg++;
405 bool __testf = __n <= __falsen ? __c == __false[__n] : false;
406 bool __testt = __n <= __truen ? __c == __true[__n] : false;
407 if (!(__testf || __testt))
409 __err |= ios_base::failbit;
412 else if (__testf && __n == __falsen)
417 else if (__testt && __n == __truen)
424 __err |= ios_base::eofbit;
430 template<typename _CharT, typename _InIter>
432 num_get<_CharT, _InIter>::
433 do_get(iter_type __beg, iter_type __end, ios_base& __io,
434 ios_base::iostate& __err, long& __v) const
438 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
439 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
443 template<typename _CharT, typename _InIter>
445 num_get<_CharT, _InIter>::
446 do_get(iter_type __beg, iter_type __end, ios_base& __io,
447 ios_base::iostate& __err, unsigned short& __v) const
451 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
453 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
454 if (!(__err & ios_base::failbit)
455 && __ul <= numeric_limits<unsigned short>::max())
456 __v = static_cast<unsigned short>(__ul);
458 __err |= ios_base::failbit;
462 template<typename _CharT, typename _InIter>
464 num_get<_CharT, _InIter>::
465 do_get(iter_type __beg, iter_type __end, ios_base& __io,
466 ios_base::iostate& __err, unsigned int& __v) const
470 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
472 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
473 if (!(__err & ios_base::failbit)
474 && __ul <= numeric_limits<unsigned int>::max())
475 __v = static_cast<unsigned int>(__ul);
477 __err |= ios_base::failbit;
481 template<typename _CharT, typename _InIter>
483 num_get<_CharT, _InIter>::
484 do_get(iter_type __beg, iter_type __end, ios_base& __io,
485 ios_base::iostate& __err, unsigned long& __v) const
489 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
490 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
494 #ifdef _GLIBCPP_USE_LONG_LONG
495 template<typename _CharT, typename _InIter>
497 num_get<_CharT, _InIter>::
498 do_get(iter_type __beg, iter_type __end, ios_base& __io,
499 ios_base::iostate& __err, long long& __v) const
503 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
504 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
508 template<typename _CharT, typename _InIter>
510 num_get<_CharT, _InIter>::
511 do_get(iter_type __beg, iter_type __end, ios_base& __io,
512 ios_base::iostate& __err, unsigned long long& __v) const
516 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
517 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
522 template<typename _CharT, typename _InIter>
524 num_get<_CharT, _InIter>::
525 do_get(iter_type __beg, iter_type __end, ios_base& __io,
526 ios_base::iostate& __err, float& __v) const
530 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
531 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
535 template<typename _CharT, typename _InIter>
537 num_get<_CharT, _InIter>::
538 do_get(iter_type __beg, iter_type __end, ios_base& __io,
539 ios_base::iostate& __err, double& __v) const
543 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
544 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
548 template<typename _CharT, typename _InIter>
550 num_get<_CharT, _InIter>::
551 do_get(iter_type __beg, iter_type __end, ios_base& __io,
552 ios_base::iostate& __err, long double& __v) const
556 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
557 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
561 template<typename _CharT, typename _InIter>
563 num_get<_CharT, _InIter>::
564 do_get(iter_type __beg, iter_type __end, ios_base& __io,
565 ios_base::iostate& __err, void*& __v) const
567 // Prepare for hex formatted input
568 typedef ios_base::fmtflags fmtflags;
569 fmtflags __fmt = __io.flags();
570 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
571 | ios_base::uppercase | ios_base::internal);
572 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
576 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
578 // Reset from hex formatted input
582 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
583 if (!(__err & ios_base::failbit))
584 __v = reinterpret_cast<void*>(__ul);
586 __err |= ios_base::failbit;
591 // The following code uses sprintf() to convert floating point
592 // values for insertion into a stream. An optimization would be to
593 // replace sprintf() with code that works directly on a wide buffer
594 // and then use __pad to do the padding. It would be good
595 // to replace sprintf() anyway to avoid accidental buffer overruns
596 // and to gain back the efficiency that C++ provides by knowing up
597 // front the type of the values to insert. This implementation
598 // follows the C++ standard fairly directly as outlined in 22.2.2.2
599 // [lib.locale.num.put]
600 template<typename _CharT, typename _OutIter>
601 template<typename _ValueT>
603 num_put<_CharT, _OutIter>::
604 _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
607 const int __max_digits = numeric_limits<_ValueT>::digits10;
608 streamsize __prec = __io.precision();
609 // Protect against sprintf() buffer overflows.
610 if (__prec > static_cast<streamsize>(__max_digits))
611 __prec = static_cast<streamsize>(__max_digits);
613 // Long enough for the max format spec.
616 // Consider the possibility of long ios_base::fixed outputs
617 const bool __fixed = __io.flags() & ios_base::fixed;
618 const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
619 // ios_base::fixed outputs may need up to __max_exp+1 chars
620 // for the integer part + up to __max_digits chars for the
621 // fractional part + 3 chars for sign, decimal point, '\0'. On
622 // the other hand, for non-fixed outputs __max_digits*3 chars
623 // are largely sufficient.
624 const int __cs_size = __fixed ? __max_exp + __max_digits + 4
626 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
629 // [22.2.2.2.2] Stage 1, numeric conversion to character.
630 if (_S_format_float(__io, __fbuf, __mod, __prec))
631 __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale, __prec);
633 __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale);
634 return _M_widen_float(__s, __io, __fill, __cs, __len);
637 template<typename _CharT, typename _OutIter>
638 template<typename _ValueT>
640 num_put<_CharT, _OutIter>::
641 _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
642 char __modl, _ValueT __v) const
644 // [22.2.2.2.2] Stage 1, numeric conversion to character.
645 // Leave room for "+/-," "0x," and commas. This size is
646 // arbitrary, but should work.
648 // Long enough for the max format spec.
650 _S_format_int(__io, __fbuf, __mod, __modl);
651 int __len = __convert_from_v(__cs, __fbuf, __v, _S_c_locale);
652 return _M_widen_int(__s, __io, __fill, __cs, __len);
655 template<typename _CharT, typename _OutIter>
657 num_put<_CharT, _OutIter>::
658 _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
661 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
662 // numpunct.decimal_point() values for '.' and adding grouping.
663 const locale __loc = __io.getloc();
664 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
665 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
667 // Grouping can add (almost) as many separators as the number of
668 // digits, but no more.
669 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
671 __ctype.widen(__cs, __cs + __len, __ws);
673 // Replace decimal point.
675 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
676 if (__p = char_traits<_CharT>::find(__ws, __len, __ctype.widen('.')))
677 __ws[__p - __ws] = __np.decimal_point();
679 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
680 //282. What types does numpunct grouping refer to?
681 // Add grouping, if necessary.
682 const string __grouping = __np.grouping();
683 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
684 if (__grouping.size())
687 int __declen = __p ? __p - __ws : __len;
688 __p2 = __add_grouping(__ws2, __np.thousands_sep(),
690 __grouping.c_str() + __grouping.size(),
691 __ws, __ws + __declen);
692 int __newlen = __p2 - __ws2;
694 // Tack on decimal part.
697 char_traits<_CharT>::copy(__p2, __p, __len - __declen);
698 __newlen += __len - __declen;
701 // Switch strings, establish correct new length.
706 return _M_insert(__s, __io, __fill, __ws, __len);
709 template<typename _CharT, typename _OutIter>
711 num_put<_CharT, _OutIter>::
712 _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
715 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
716 // numpunct.decimal_point() values for '.' and adding grouping.
717 const locale __loc = __io.getloc();
718 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
719 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
721 // Grouping can add (almost) as many separators as the number of
722 // digits, but no more.
723 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
725 __ctype.widen(__cs, __cs + __len, __ws);
727 // Add grouping, if necessary.
728 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
729 const string __grouping = __np.grouping();
730 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
731 bool __dec = __basefield != ios_base::oct
732 && __basefield != ios_base::hex;
733 if (__grouping.size() && __dec)
736 __p = __add_grouping(__ws2, __np.thousands_sep(), __grouping.c_str(),
737 __grouping.c_str() + __grouping.size(),
743 return _M_insert(__s, __io, __fill, __ws, __len);
746 // For use by integer and floating-point types after they have been
747 // converted into a char_type string.
748 template<typename _CharT, typename _OutIter>
750 num_put<_CharT, _OutIter>::
751 _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws,
754 // [22.2.2.2.2] Stage 3.
755 streamsize __w = __io.width();
756 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
758 if (__w > static_cast<streamsize>(__len))
760 __pad(__io, __fill, __ws2, __ws, __w, __len, true);
761 __len = static_cast<int>(__w);
767 // [22.2.2.2.2] Stage 4.
768 // Write resulting, fully-formatted string to output iterator.
769 for (int __j = 0; __j < __len; ++__j, ++__s)
774 template<typename _CharT, typename _OutIter>
776 num_put<_CharT, _OutIter>::
777 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
779 ios_base::fmtflags __flags = __io.flags();
780 if ((__flags & ios_base::boolalpha) == 0)
782 unsigned long __uv = __v;
783 __s = _M_convert_int(__s, __io, __fill, 'u', char_type(), __uv);
787 locale __loc = __io.getloc();
788 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
789 const char_type* __ws;
793 __ws = __np.truename().c_str();
794 __len = __np.truename().size();
798 __ws = __np.falsename().c_str();
799 __len = __np.falsename().size();
801 __s = _M_insert(__s, __io, __fill, __ws, __len);
806 template<typename _CharT, typename _OutIter>
808 num_put<_CharT, _OutIter>::
809 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
810 { return _M_convert_int(__s, __io, __fill, 'd', char_type(), __v); }
812 template<typename _CharT, typename _OutIter>
814 num_put<_CharT, _OutIter>::
815 do_put(iter_type __s, ios_base& __io, char_type __fill,
816 unsigned long __v) const
817 { return _M_convert_int(__s, __io, __fill, 'u', char_type(), __v); }
819 #ifdef _GLIBCPP_USE_LONG_LONG
820 template<typename _CharT, typename _OutIter>
822 num_put<_CharT, _OutIter>::
823 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
824 { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); }
826 template<typename _CharT, typename _OutIter>
828 num_put<_CharT, _OutIter>::
829 do_put(iter_type __s, ios_base& __io, char_type __fill,
830 unsigned long long __v) const
831 { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); }
834 template<typename _CharT, typename _OutIter>
836 num_put<_CharT, _OutIter>::
837 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
838 { return _M_convert_float(__s, __io, __fill, char_type(), __v); }
840 template<typename _CharT, typename _OutIter>
842 num_put<_CharT, _OutIter>::
843 do_put(iter_type __s, ios_base& __io, char_type __fill,
844 long double __v) const
845 { return _M_convert_float(__s, __io, __fill, 'L', __v); }
847 template<typename _CharT, typename _OutIter>
849 num_put<_CharT, _OutIter>::
850 do_put(iter_type __s, ios_base& __io, char_type __fill,
851 const void* __v) const
853 ios_base::fmtflags __flags = __io.flags();
854 ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
855 | ios_base::uppercase | ios_base::internal);
856 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
859 __s = _M_convert_int(__s, __io, __fill, 'u', char_type(),
860 reinterpret_cast<unsigned long>(__v));
866 __throw_exception_again;
872 template<typename _CharT, typename _InIter>
874 money_get<_CharT, _InIter>::
875 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
876 ios_base::iostate& __err, long double& __units) const
879 __beg = this->do_get(__beg, __end, __intl, __io, __err, __str);
881 const int __n = numeric_limits<long double>::digits10;
882 char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
883 const locale __loc = __io.getloc();
884 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
885 const _CharT* __wcs = __str.c_str();
886 __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);
887 __convert_to_v(__cs, __units, __err, _S_c_locale);
891 template<typename _CharT, typename _InIter>
893 money_get<_CharT, _InIter>::
894 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
895 ios_base::iostate& __err, string_type& __units) const
897 // These contortions are quite unfortunate.
898 typedef moneypunct<_CharT, true> __money_true;
899 typedef moneypunct<_CharT, false> __money_false;
900 typedef money_base::part part;
901 typedef typename string_type::size_type size_type;
903 const locale __loc = __io.getloc();
904 const __money_true& __mpt = use_facet<__money_true>(__loc);
905 const __money_false& __mpf = use_facet<__money_false>(__loc);
906 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
908 const money_base::pattern __p = __intl ? __mpt.neg_format()
909 : __mpf.neg_format();
911 const string_type __pos_sign =__intl ? __mpt.positive_sign()
912 : __mpf.positive_sign();
913 const string_type __neg_sign =__intl ? __mpt.negative_sign()
914 : __mpf.negative_sign();
915 const char_type __d = __intl ? __mpt.decimal_point()
916 : __mpf.decimal_point();
917 const char_type __sep = __intl ? __mpt.thousands_sep()
918 : __mpf.thousands_sep();
920 const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
922 // Set to deduced positive or negative sign, depending.
924 // String of grouping info from thousands_sep plucked from __units.
925 string __grouping_tmp;
926 // Marker for thousands_sep position.
928 // If input iterator is in a valid state.
929 bool __testvalid = true;
930 // Flag marking when a decimal point is found.
931 bool __testdecfound = false;
933 // The tentative returned string is stored here.
934 string_type __temp_units;
936 char_type __c = *__beg;
937 char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
938 for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
940 part __which = static_cast<part>(__p.field[__i]);
943 case money_base::symbol:
944 if (__io.flags() & ios_base::showbase
946 || (__i == 2 && static_cast<part>(__p.field[3]) != money_base::none)
947 || __sign.size() > 1)
949 // According to 22.2.6.1.2.2, symbol is required if
950 // (__io.flags() & ios_base::showbase), otherwise is optional
951 // and consumed only if other characters are needed to complete
953 const string_type __symbol = __intl ? __mpt.curr_symbol()
954 : __mpf.curr_symbol();
955 size_type __len = __symbol.size();
957 while (__beg != __end
958 && __j < __len && __symbol[__j] == __c)
963 // When (__io.flags() & ios_base::showbase) symbol is required.
964 if (__j != __len && (__io.flags() & ios_base::showbase))
968 case money_base::sign:
969 // Sign might not exist, or be more than one character long.
970 if (__pos_sign.size() && __neg_sign.size())
972 // Sign is mandatory.
973 if (__c == __pos_sign[0])
978 else if (__c == __neg_sign[0])
986 else if (__pos_sign.size() && __c == __pos_sign[0])
991 else if (__neg_sign.size() && __c == __neg_sign[0])
997 case money_base::value:
998 // Extract digits, remove and stash away the
999 // grouping of found thousands separators.
1000 while (__beg != __end
1001 && (__ctype.is(ctype_base::digit, __c)
1002 || (__c == __d && !__testdecfound)
1007 __grouping_tmp += static_cast<char>(__sep_pos);
1009 __testdecfound = true;
1011 else if (__c == __sep)
1013 if (__grouping.size())
1015 // Mark position for later analysis.
1016 __grouping_tmp += static_cast<char>(__sep_pos);
1021 __testvalid = false;
1027 __temp_units += __c;
1033 case money_base::space:
1034 case money_base::none:
1035 // Only if not at the end of the pattern.
1037 while (__beg != __end
1038 && __ctype.is(ctype_base::space, __c))
1044 // Need to get the rest of the sign characters, if they exist.
1045 if (__sign.size() > 1)
1047 size_type __len = __sign.size();
1049 for (; __c != __eof && __i < __len; ++__i)
1050 while (__beg != __end && __c != __sign[__i])
1054 __testvalid = false;
1057 // Strip leading zeros.
1058 while (__temp_units[0] == __ctype.widen('0'))
1059 __temp_units.erase(__temp_units.begin());
1061 if (__sign.size() && __sign == __neg_sign)
1062 __temp_units.insert(__temp_units.begin(), __ctype.widen('-'));
1064 // Test for grouping fidelity.
1065 if (__grouping.size() && __grouping_tmp.size())
1067 if (!__verify_grouping(__grouping, __grouping_tmp))
1068 __testvalid = false;
1071 // Iff no more characters are available.
1073 __err |= ios_base::eofbit;
1075 // Iff valid sequence is not recognized.
1076 if (!__testvalid || !__temp_units.size())
1077 __err |= ios_base::failbit;
1079 // Use the "swap trick" to copy __temp_units into __units.
1080 __temp_units.swap(__units);
1085 template<typename _CharT, typename _OutIter>
1087 money_put<_CharT, _OutIter>::
1088 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1089 long double __units) const
1091 const locale __loc = __io.getloc();
1092 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1093 const int __n = numeric_limits<long double>::digits10;
1094 char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
1095 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
1096 int __len = __convert_from_v(__cs, "%.01Lf", __units, _S_c_locale);
1097 __ctype.widen(__cs, __cs + __len, __ws);
1098 string_type __digits(__ws);
1099 return this->do_put(__s, __intl, __io, __fill, __digits);
1102 template<typename _CharT, typename _OutIter>
1104 money_put<_CharT, _OutIter>::
1105 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1106 const string_type& __digits) const
1108 typedef typename string_type::size_type size_type;
1109 typedef money_base::part part;
1111 const locale __loc = __io.getloc();
1112 const size_type __width = static_cast<size_type>(__io.width());
1114 // These contortions are quite unfortunate.
1115 typedef moneypunct<_CharT, true> __money_true;
1116 typedef moneypunct<_CharT, false> __money_false;
1117 const __money_true& __mpt = use_facet<__money_true>(__loc);
1118 const __money_false& __mpf = use_facet<__money_false>(__loc);
1119 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1121 // Determine if negative or positive formats are to be used, and
1122 // discard leading negative_sign if it is present.
1123 const char_type* __beg = __digits.data();
1124 const char_type* __end = __beg + __digits.size();
1125 money_base::pattern __p;
1127 if (*__beg != __ctype.widen('-'))
1129 __p = __intl ? __mpt.pos_format() : __mpf.pos_format();
1130 __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
1134 __p = __intl ? __mpt.neg_format() : __mpf.neg_format();
1135 __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
1139 // Look for valid numbers in the current ctype facet within input digits.
1140 __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
1143 // Assume valid input, and attempt to format.
1144 // Break down input numbers into base components, as follows:
1145 // final_value = grouped units + (decimal point) + (digits)
1147 string_type __value;
1148 const string_type __symbol = __intl ? __mpt.curr_symbol()
1149 : __mpf.curr_symbol();
1151 // Deal with decimal point, decimal digits.
1152 const int __frac = __intl ? __mpt.frac_digits()
1153 : __mpf.frac_digits();
1156 const char_type __d = __intl ? __mpt.decimal_point()
1157 : __mpf.decimal_point();
1158 if (__end - __beg >= __frac)
1160 __value = string_type(__end - __frac, __end);
1161 __value.insert(__value.begin(), __d);
1166 // Have to pad zeros in the decimal position.
1167 __value = string_type(__beg, __end);
1168 int __paddec = __frac - (__end - __beg);
1169 char_type __zero = __ctype.widen('0');
1170 __value.insert(__value.begin(), __paddec, __zero);
1171 __value.insert(__value.begin(), __d);
1176 // Add thousands separators to non-decimal digits, per
1180 const string __grouping = __intl ? __mpt.grouping()
1182 if (__grouping.size())
1184 const char_type __sep = __intl ? __mpt.thousands_sep()
1185 : __mpf.thousands_sep();
1186 const char* __gbeg = __grouping.c_str();
1187 const char* __gend = __gbeg + __grouping.size();
1188 const int __n = numeric_limits<long double>::digits10 * 2;
1189 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
1190 _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg,
1191 __gend, __beg, __end);
1192 __value.insert(0, __ws2, __ws_end - __ws2);
1195 __value.insert(0, string_type(__beg, __end));
1198 // Calculate length of resulting string.
1199 ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
1200 size_type __len = __value.size() + __sign.size();
1201 __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
1202 bool __testipad = __f == ios_base::internal && __len < __width;
1204 // Fit formatted digits into the required pattern.
1205 for (int __i = 0; __i < 4; ++__i)
1207 part __which = static_cast<part>(__p.field[__i]);
1210 case money_base::symbol:
1211 if (__io.flags() & ios_base::showbase)
1214 case money_base::sign:
1215 // Sign might not exist, or be more than one
1216 // charater long. In that case, add in the rest
1221 case money_base::value:
1224 case money_base::space:
1225 // At least one space is required, but if internal
1226 // formatting is required, an arbitrary number of
1227 // fill spaces will be necessary.
1229 __res += string_type(__width - __len, __fill);
1231 __res += __ctype.widen(' ');
1233 case money_base::none:
1235 __res += string_type(__width - __len, __fill);
1240 // Special case of multi-part sign parts.
1241 if (__sign.size() > 1)
1242 __res += string_type(__sign.begin() + 1, __sign.end());
1244 // Pad, if still necessary.
1245 __len = __res.size();
1246 if (__width > __len)
1248 if (__f == ios_base::left)
1250 __res.append(__width - __len, __fill);
1253 __res.insert(0, string_type(__width - __len, __fill));
1257 // Write resulting, fully-formatted string to output iterator.
1258 for (size_type __j = 0; __j < __len; ++__j, ++__s)
1266 // NB: Not especially useful. Without an ios_base object or some
1267 // kind of locale reference, we are left clawing at the air where
1268 // the side of the mountain used to be...
1269 template<typename _CharT, typename _InIter>
1270 time_base::dateorder
1271 time_get<_CharT, _InIter>::do_date_order() const
1272 { return time_base::no_order; }
1274 template<typename _CharT, typename _InIter>
1276 time_get<_CharT, _InIter>::
1277 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
1278 ios_base::iostate& __err, tm* __tm,
1279 const _CharT* __format) const
1281 locale __loc = __io.getloc();
1282 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1283 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1284 size_t __len = char_traits<_CharT>::length(__format);
1286 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
1288 char __c = __format[__i];
1291 // Verify valid formatting code, attempt to extract.
1292 __c = __format[++__i];
1295 if (__c == 'E' || __c == 'O')
1298 __c = __format[++__i];
1305 // Abbreviated weekday name [tm_wday]
1306 const char_type* __days1[7];
1307 __tp._M_days_abbreviated(__days1);
1308 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7,
1312 // Weekday name [tm_wday].
1313 const char_type* __days2[7];
1314 __tp._M_days(__days2);
1315 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7,
1320 // Abbreviated month name [tm_mon]
1321 const char_type* __months1[12];
1322 __tp._M_months_abbreviated(__months1);
1323 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12,
1327 // Month name [tm_mon].
1328 const char_type* __months2[12];
1329 __tp._M_months(__months2);
1330 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12,
1334 // Default time and date representation.
1335 const char_type* __dt[2];
1336 __tp._M_date_time_formats(__dt);
1337 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1341 // Day [01, 31]. [tm_mday]
1342 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
1346 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
1348 __ctype.widen(__cs, __cs + 9, __wcs);
1349 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1353 // Hour [00, 23]. [tm_hour]
1354 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1358 // Hour [01, 12]. [tm_hour]
1359 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
1363 // Month [01, 12]. [tm_mon]
1364 _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype,
1367 __tm->tm_mon = __mem - 1;
1370 // Minute [00, 59]. [tm_min]
1371 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1375 if (__ctype.narrow(*__beg, 0) == '\n')
1378 __err |= ios_base::failbit;
1381 // Equivalent to (%H:%M).
1383 __ctype.widen(__cs, __cs + 6, __wcs);
1384 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1389 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
1393 if (__ctype.narrow(*__beg, 0) == '\t')
1396 __err |= ios_base::failbit;
1399 // Equivalent to (%H:%M:%S).
1401 __ctype.widen(__cs, __cs + 9, __wcs);
1402 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1407 const char_type* __dates[2];
1408 __tp._M_date_formats(__dates);
1409 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1414 const char_type* __times[2];
1415 __tp._M_time_formats(__times);
1416 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1420 // Two digit year. [tm_year]
1421 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
1425 // Year [1900). [tm_year]
1426 _M_extract_num(__beg, __end, __mem, 0,
1427 numeric_limits<int>::max(), 4,
1430 __tm->tm_year = __mem - 1900;
1434 if (__ctype.is(ctype_base::upper, *__beg))
1437 _M_extract_name(__beg, __end, __tmp,
1438 __timepunct<_CharT>::_S_timezones,
1441 // GMT requires special effort.
1442 char_type __c = *__beg;
1443 if (!__err && __tmp == 0
1444 && (__c == __ctype.widen('-')
1445 || __c == __ctype.widen('+')))
1447 _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1449 _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1454 __err |= ios_base::failbit;
1458 __err |= ios_base::failbit;
1463 // Verify format and input match, extract and discard.
1464 if (__c == __ctype.narrow(*__beg, 0))
1467 __err |= ios_base::failbit;
1472 template<typename _CharT, typename _InIter>
1474 time_get<_CharT, _InIter>::
1475 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
1476 int __min, int __max, size_t __len,
1477 const ctype<_CharT>& __ctype,
1478 ios_base::iostate& __err) const
1482 bool __testvalid = true;
1483 char_type __c = *__beg;
1484 while (__beg != __end && __i < __len
1485 && __ctype.is(ctype_base::digit, __c))
1487 __digits += __ctype.narrow(__c, 0);
1493 int __value = atoi(__digits.c_str());
1494 if (__min <= __value && __value <= __max)
1497 __testvalid = false;
1500 __testvalid = false;
1502 __err |= ios_base::failbit;
1506 // All elements in __names are unique.
1507 template<typename _CharT, typename _InIter>
1509 time_get<_CharT, _InIter>::
1510 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
1511 const _CharT** __names, size_t __indexlen,
1512 ios_base::iostate& __err) const
1514 typedef char_traits<char_type> __traits_type;
1515 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen));
1516 size_t __nmatches = 0;
1518 bool __testvalid = true;
1519 const char_type* __name;
1521 char_type __c = *__beg;
1522 // Look for initial matches.
1523 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1524 if (__c == __names[__i1][0])
1525 __matches[__nmatches++] = __i1;
1527 while(__nmatches > 1)
1529 // Find smallest matching string.
1530 size_t __minlen = 10;
1531 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
1532 __minlen = min(__minlen,
1533 __traits_type::length(__names[__matches[__i2]]));
1535 if (__pos < __minlen && __beg != __end)
1539 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1541 __name = __names[__matches[__i3]];
1542 if (__name[__pos] != __c)
1543 __matches[__i3] = __matches[--__nmatches];
1550 if (__nmatches == 1)
1552 // Make sure found name is completely extracted.
1553 __name = __names[__matches[0]];
1554 const size_t __len = __traits_type::length(__name);
1555 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
1559 __member = __matches[0];
1561 __testvalid = false;
1564 __testvalid = false;
1566 __err |= ios_base::failbit;
1569 template<typename _CharT, typename _InIter>
1571 time_get<_CharT, _InIter>::
1572 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1573 ios_base::iostate& __err, tm* __tm) const
1576 const char* __cs = "%X";
1577 locale __loc = __io.getloc();
1578 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1579 __ctype.widen(__cs, __cs + 3, __wcs);
1580 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1582 __err |= ios_base::eofbit;
1586 template<typename _CharT, typename _InIter>
1588 time_get<_CharT, _InIter>::
1589 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1590 ios_base::iostate& __err, tm* __tm) const
1593 const char* __cs = "%x";
1594 locale __loc = __io.getloc();
1595 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1596 __ctype.widen(__cs, __cs + 3, __wcs);
1597 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1599 __err |= ios_base::eofbit;
1603 template<typename _CharT, typename _InIter>
1605 time_get<_CharT, _InIter>::
1606 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1607 ios_base::iostate& __err, tm* __tm) const
1609 typedef char_traits<char_type> __traits_type;
1610 locale __loc = __io.getloc();
1611 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1612 const char_type* __days[7];
1613 __tp._M_days_abbreviated(__days);
1615 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err);
1617 // Check to see if non-abbreviated name exists, and extract.
1618 // NB: Assumes both _M_days and _M_days_abbreviated organized in
1619 // exact same order, first to last, such that the resulting
1620 // __days array with the same index points to a day, and that
1621 // day's abbreviated form.
1622 // NB: Also assumes that an abbreviated name is a subset of the name.
1625 size_t __pos = __traits_type::length(__days[__tmpwday]);
1626 __tp._M_days(__days);
1627 const char_type* __name = __days[__tmpwday];
1628 if (__name[__pos] == *__beg)
1630 // Extract the rest of it.
1631 const size_t __len = __traits_type::length(__name);
1632 while (__pos < __len && __beg != __end
1633 && __name[__pos] == *__beg)
1636 __err |= ios_base::failbit;
1639 __tm->tm_wday = __tmpwday;
1642 __err |= ios_base::eofbit;
1646 template<typename _CharT, typename _InIter>
1648 time_get<_CharT, _InIter>::
1649 do_get_monthname(iter_type __beg, iter_type __end,
1650 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1652 typedef char_traits<char_type> __traits_type;
1653 locale __loc = __io.getloc();
1654 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1655 const char_type* __months[12];
1656 __tp._M_months_abbreviated(__months);
1658 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err);
1660 // Check to see if non-abbreviated name exists, and extract.
1661 // NB: Assumes both _M_months and _M_months_abbreviated organized in
1662 // exact same order, first to last, such that the resulting
1663 // __months array with the same index points to a month, and that
1664 // month's abbreviated form.
1665 // NB: Also assumes that an abbreviated name is a subset of the name.
1668 size_t __pos = __traits_type::length(__months[__tmpmon]);
1669 __tp._M_months(__months);
1670 const char_type* __name = __months[__tmpmon];
1671 if (__name[__pos] == *__beg)
1673 // Extract the rest of it.
1674 const size_t __len = __traits_type::length(__name);
1675 while (__pos < __len && __beg != __end
1676 && __name[__pos] == *__beg)
1679 __err |= ios_base::failbit;
1682 __tm->tm_mon = __tmpmon;
1686 __err |= ios_base::eofbit;
1690 template<typename _CharT, typename _InIter>
1692 time_get<_CharT, _InIter>::
1693 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1694 ios_base::iostate& __err, tm* __tm) const
1696 locale __loc = __io.getloc();
1697 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1699 char_type __c = *__beg;
1702 while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c))
1704 __digits += __ctype.narrow(__c, 0);
1708 if (__i == 2 || __i == 4)
1711 __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale);
1712 if (!(__err & ios_base::failbit) && __l <= INT_MAX)
1714 __l = __i == 2 ? __l : __l - 1900;
1715 __tm->tm_year = static_cast<int>(__l);
1719 __err |= ios_base::failbit;
1721 __err |= ios_base::eofbit;
1725 template<typename _CharT, typename _OutIter>
1727 time_put<_CharT, _OutIter>::
1728 put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1729 const _CharT* __beg, const _CharT* __end) const
1731 locale __loc = __io.getloc();
1732 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1733 while (__beg != __end)
1735 char __c = __ctype.narrow(*__beg, 0);
1742 __c = __ctype.narrow(*__beg, 0);
1744 if (__c == 'E' || __c == 'O')
1747 __format = __ctype.narrow(*__beg, 0);
1752 __s = this->do_put(__s, __io, char_type(), __tm, __format,
1764 template<typename _CharT, typename _OutIter>
1766 time_put<_CharT, _OutIter>::
1767 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1768 char __format, char __mod) const
1770 locale __loc = __io.getloc();
1771 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1772 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1774 // NB: This size is arbitrary. Should this be a data member,
1775 // initialized at construction?
1776 const size_t __maxlen = 64;
1777 char_type* __res = static_cast<char_type*>(__builtin_alloca(__maxlen));
1779 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1780 // is possible that the format character will be longer than one
1781 // character. Possibilities include 'E' or 'O' followed by a
1782 // format character: if __mod is not the default argument, assume
1783 // it's a valid modifier.
1785 __fmt[0] = __ctype.widen('%');
1788 __fmt[1] = __format;
1789 __fmt[2] = char_type();
1794 __fmt[2] = __format;
1795 __fmt[3] = char_type();
1798 __tp._M_put_helper(__res, __maxlen, __fmt, __tm);
1800 // Write resulting, fully-formatted string to output iterator.
1801 size_t __len = char_traits<char_type>::length(__res);
1802 for (size_t __i = 0; __i < __len; ++__i, ++__s)
1808 // Generic version does nothing.
1809 template<typename _CharT>
1811 collate<_CharT>::_M_compare_helper(const _CharT*, const _CharT*) const
1814 // Generic version does nothing.
1815 template<typename _CharT>
1817 collate<_CharT>::_M_transform_helper(_CharT*, const _CharT*, size_t) const
1820 template<typename _CharT>
1823 do_compare(const _CharT* __lo1, const _CharT* __hi1,
1824 const _CharT* __lo2, const _CharT* __hi2) const
1826 const string_type __one(__lo1, __hi1);
1827 const string_type __two(__lo2, __hi2);
1828 return _M_compare_helper(__one.c_str(), __two.c_str());
1831 template<typename _CharT>
1832 typename collate<_CharT>::string_type
1834 do_transform(const _CharT* __lo, const _CharT* __hi) const
1836 size_t __len = __hi - __lo;
1837 _CharT* __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
1838 size_t __res = _M_transform_helper(__c, __lo, __len);
1841 // Try to increment size of translated string.
1842 size_t __len2 = __len * 2;
1843 _CharT* __c2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len2));
1844 __res = _M_transform_helper(__c2, __lo, __len);
1845 // XXX Throw exception if still indeterminate?
1847 return string_type(__c);
1850 template<typename _CharT>
1853 do_hash(const _CharT* __lo, const _CharT* __hi) const
1855 unsigned long __val = 0;
1856 for (; __lo < __hi; ++__lo)
1857 __val = *__lo + ((__val << 7) |
1858 (__val >> (numeric_limits<unsigned long>::digits - 1)));
1859 return static_cast<long>(__val);
1862 // Convert string to numeric value of type _Tv and store results.
1863 // NB: This is specialized for all required types, there is no
1864 // generic definition.
1865 template<typename _Tv>
1867 __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err,
1868 const __c_locale& __cloc, int __base = 10);
1870 // Convert numeric value of type _Tv to string and return length of string.
1871 template<typename _Tv>
1873 __convert_from_v(char* __out, const char* __fmt, _Tv __v,
1874 const __c_locale&, int __prec = -1)
1877 const char* __old = setlocale(LC_ALL, "C");
1879 __ret = sprintf(__out, __fmt, __prec, __v);
1881 __ret = sprintf(__out, __fmt, __v);
1882 setlocale(LC_ALL, __old);
1886 // Construct correctly padded string, as per 22.2.2.2.2
1888 // __newlen > __oldlen
1889 // __news is allocated for __newlen size
1890 // Used by both num_put and ostream inserters: if __num,
1891 // internal-adjusted objects are padded according to the rules below
1892 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
1894 template<typename _CharT, typename _Traits>
1896 __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds,
1897 const streamsize __newlen, const streamsize __oldlen,
1900 typedef _CharT char_type;
1901 typedef _Traits traits_type;
1902 typedef typename traits_type::int_type int_type;
1904 int_type __plen = static_cast<size_t>(__newlen - __oldlen);
1905 char_type* __pads = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen));
1906 traits_type::assign(__pads, __plen, __fill);
1911 size_t __beglen; //either __plen or __oldlen
1912 ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
1914 if (__adjust == ios_base::left)
1917 __beg = const_cast<char_type*>(__olds);
1918 __beglen = __oldlen;
1921 else if (__adjust == ios_base::internal && __num)
1923 // Pad after the sign, if there is one.
1924 // Pad after 0[xX], if there is one.
1925 // Who came up with these rules, anyway? Jeeze.
1926 locale __loc = __io.getloc();
1927 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1928 const char_type __minus = __ctype.widen('-');
1929 const char_type __plus = __ctype.widen('+');
1930 bool __testsign = __olds[0] == __minus || __olds[0] == __plus;
1931 bool __testhex = __ctype.widen('0') == __olds[0]
1932 && (__ctype.widen('x') == __olds[1]
1933 || __ctype.widen('X') == __olds[1]);
1936 __news[0] = __olds[0];
1937 __news[1] = __olds[1];
1942 __end = const_cast<char_type*>(__olds + __mod);
1944 else if (__testsign)
1946 __news[0] = __olds[0] == __plus ? __plus : __minus;
1951 __end = const_cast<char_type*>(__olds + __mod);
1958 __end = const_cast<char_type*>(__olds);
1966 __end = const_cast<char_type*>(__olds);
1968 traits_type::copy(__news, __beg, __beglen);
1969 traits_type::copy(__news + __beglen, __end, __newlen - __beglen - __mod);
1972 // NB: Can't have default argument on non-member template, and
1973 // num_put doesn't have a _Traits template parameter, so this
1974 // forwarding template adds in the default template argument.
1975 template<typename _CharT>
1977 __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds,
1978 const streamsize __newlen, const streamsize __oldlen,
1981 return __pad<_CharT, char_traits<_CharT> >(__io, __fill, __news, __olds,
1982 __newlen, __oldlen, __num);
1985 // Used by both numeric and monetary facets.
1986 // Check to make sure that the __grouping_tmp string constructed in
1987 // money_get or num_get matches the canonical grouping for a given
1989 // __grouping_tmp is parsed L to R
1990 // 1,222,444 == __grouping_tmp of "/1/3/3"
1991 // __grouping is parsed R to L
1992 // 1,222,444 == __grouping of "/3" == "/3/3/3"
1993 template<typename _CharT>
1995 __verify_grouping(const basic_string<_CharT>& __grouping,
1996 basic_string<_CharT>& __grouping_tmp)
2000 const int __len = __grouping.size();
2001 const int __n = __grouping_tmp.size();
2004 // Parsed number groupings have to match the
2005 // numpunct::grouping string exactly, starting at the
2006 // right-most point of the parsed sequence of elements ...
2007 while (__test && __i < __n - 1)
2008 for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
2009 __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1];
2010 // ... but the last parsed grouping can be <= numpunct
2012 __j == __len ? __j = 0 : __j;
2013 __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1];
2017 // Used by both numeric and monetary facets.
2018 // Inserts "group separator" characters into an array of characters.
2019 // It's recursive, one iteration per group. It moves the characters
2020 // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this
2021 // only with __gbeg != __gend.
2022 template<typename _CharT>
2024 __add_grouping(_CharT* __s, _CharT __sep,
2025 const char* __gbeg, const char* __gend,
2026 const _CharT* __first, const _CharT* __last)
2028 if (__last - __first > *__gbeg)
2030 __s = __add_grouping(__s, __sep,
2031 (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
2032 __gend, __first, __last - *__gbeg);
2033 __first = __last - *__gbeg;
2037 *__s++ = *__first++;
2038 while (__first != __last);