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
36 #pragma GCC system_header
39 #include <clocale> // For localeconv
40 #include <cstdlib> // For strof, strtold
41 #include <cmath> // For ceil
42 #include <cctype> // For isspace
43 #include <limits> // For numeric_limits
44 #include <bits/streambuf_iterator.h>
46 #include <typeinfo> // For bad_cast.
50 template<typename _Facet>
52 locale::combine(const locale& __other) const
54 _Impl* __tmp = new _Impl(*_M_impl, 1);
55 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
59 template<typename _CharT, typename _Traits, typename _Alloc>
61 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
62 const basic_string<_CharT, _Traits, _Alloc>& __s2) const
64 typedef std::collate<_CharT> __collate_type;
65 const __collate_type& __collate = use_facet<__collate_type>(*this);
66 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
67 __s2.data(), __s2.data() + __s2.length()) < 0);
70 template<typename _Facet>
72 use_facet(const locale& __loc)
74 size_t __i = _Facet::id._M_index;
75 locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets;
76 const locale::facet* __fp = (*__facet)[__i];
77 if (__fp == 0 || __i >= __facet->size())
79 return static_cast<const _Facet&>(*__fp);
82 template<typename _Facet>
84 has_facet(const locale& __loc) throw()
86 size_t __i = _Facet::id._M_index;
87 locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets;
88 return (__i < __facet->size() && (*__facet)[__i] != 0);
92 // Stage 1: Determine a conversion specifier.
93 template<typename _CharT, typename _InIter>
95 num_get<_CharT, _InIter>::
96 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
97 ios_base::iostate& __err, string& __xtrc) const
99 const locale __loc = __io.getloc();
100 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
101 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
103 // First check for sign.
104 const char_type __plus = __ctype.widen('+');
105 const char_type __minus = __ctype.widen('-');
107 char_type __c = *__beg;
108 if ((__c == __plus || __c == __minus) && __beg != __end)
110 __xtrc += __ctype.narrow(__c, char());
115 // Next, strip leading zeros.
116 const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
117 bool __found_zero = false;
118 while (__c == __zero && __beg != __end)
125 __xtrc += _S_atoms[_M_zero];
129 // Only need acceptable digits for floating point numbers.
130 const size_t __len = _M_E - _M_zero + 1;
131 char_type __watoms[__len];
132 __ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
133 bool __found_dec = false;
134 bool __found_sci = false;
135 const char_type __dec = __np.decimal_point();
137 string __found_grouping;
138 const string __grouping = __np.grouping();
139 bool __check_grouping = __grouping.size();
141 const char_type __sep = __np.thousands_sep();
143 while (__beg != __end)
145 // Only look in digits.
146 typedef char_traits<_CharT> __traits_type;
147 const char_type* __p = __traits_type::find(__watoms, 10, __c);
149 // NB: strchr returns true for __c == 0x0
152 // Try first for acceptable digit; record it if found.
154 __xtrc += _S_atoms[__p - __watoms];
158 else if (__c == __sep && __check_grouping && !__found_dec)
160 // NB: Thousands separator at the beginning of a string
161 // is a no-no, as is two consecutive thousands separators.
164 __found_grouping += static_cast<char>(__sep_pos);
170 __err |= ios_base::failbit;
174 else if (__c == __dec && !__found_dec)
176 // According to the standard, if no grouping chars are seen,
177 // no grouping check is applied. Therefore __found_grouping
178 // must be adjusted only if __dec comes after some __sep.
179 if (__found_grouping.size())
180 __found_grouping += static_cast<char>(__sep_pos);
186 else if ((__c == __watoms[_M_e] || __c == __watoms[_M_E])
187 && !__found_sci && __pos)
189 // Scientific notation.
191 __xtrc += __ctype.narrow(__c, char());
194 // Remove optional plus or minus sign, if they exist.
195 if (__c == __plus || __c == __minus)
198 __xtrc += __ctype.narrow(__c, char());
204 // Not a valid input item.
208 // Digit grouping is checked. If grouping and found_grouping don't
209 // match, then get very very upset, and set failbit.
210 if (__check_grouping && __found_grouping.size())
212 // Add the ending grouping if a decimal wasn't found.
214 __found_grouping += static_cast<char>(__sep_pos);
215 if (!__verify_grouping(__grouping, __found_grouping))
216 __err |= ios_base::failbit;
222 __err |= ios_base::eofbit;
226 // Stage 1: Determine a conversion specifier.
227 template<typename _CharT, typename _InIter>
229 num_get<_CharT, _InIter>::
230 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
231 ios_base::iostate& __err, string& __xtrc, int& __base) const
233 const locale __loc = __io.getloc();
234 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
235 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
237 // NB: Iff __basefield == 0, this can change based on contents.
238 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
239 if (__basefield == ios_base::oct)
241 else if (__basefield == ios_base::hex)
246 // First check for sign.
248 char_type __c = *__beg;
249 if ((__c == __ctype.widen('+') || __c == __ctype.widen('-'))
252 __xtrc += __ctype.narrow(__c, char());
257 // Next, strip leading zeros and check required digits for base formats.
258 const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
259 const char_type __x = __ctype.widen('x');
260 const char_type __X = __ctype.widen('X');
263 bool __found_zero = false;
264 while (__c == __zero && __beg != __end)
271 __xtrc += _S_atoms[_M_zero];
273 if (__basefield == 0)
275 if ((__c == __x || __c == __X) && __beg != __end)
277 __xtrc += __ctype.narrow(__c, char());
287 else if (__base == 16)
289 if (__c == __zero && __beg != __end)
291 __xtrc += _S_atoms[_M_zero];
294 if ((__c == __x || __c == __X) && __beg != __end)
296 __xtrc += __ctype.narrow(__c, char());
303 // At this point, base is determined. If not hex, only allow
304 // base digits as valid input.
312 char_type __watoms[_M_size];
313 __ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
314 string __found_grouping;
315 const string __grouping = __np.grouping();
316 bool __check_grouping = __grouping.size();
318 const char_type __sep = __np.thousands_sep();
319 while (__beg != __end)
321 typedef char_traits<_CharT> __traits_type;
322 const char_type* __p = __traits_type::find(__watoms, __len, __c);
324 // NB: strchr returns true for __c == 0x0
327 // Try first for acceptable digit; record it if found.
328 __xtrc += _S_atoms[__p - __watoms];
333 else if (__c == __sep && __check_grouping)
335 // NB: Thousands separator at the beginning of a string
336 // is a no-no, as is two consecutive thousands separators.
339 __found_grouping += static_cast<char>(__sep_pos);
345 __err |= ios_base::failbit;
350 // Not a valid input item.
354 // Digit grouping is checked. If grouping and found_grouping don't
355 // match, then get very very upset, and set failbit.
356 if (__check_grouping && __found_grouping.size())
358 // Add the ending grouping.
359 __found_grouping += static_cast<char>(__sep_pos);
360 if (!__verify_grouping(__grouping, __found_grouping))
361 __err |= ios_base::failbit;
367 __err |= ios_base::eofbit;
371 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
372 //17. Bad bool parsing
373 template<typename _CharT, typename _InIter>
375 num_get<_CharT, _InIter>::
376 do_get(iter_type __beg, iter_type __end, ios_base& __io,
377 ios_base::iostate& __err, bool& __v) const
379 // Parse bool values as unsigned long
380 if (!(__io.flags() & ios_base::boolalpha))
382 // NB: We can't just call do_get(long) here, as it might
383 // refer to a derived class.
386 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
389 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
390 if (!(__err & ios_base::failbit) && __ul <= 1)
393 __err |= ios_base::failbit;
396 // Parse bool values as alphanumeric
399 locale __loc = __io.getloc();
400 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
401 const char_type* __true = __np.truename().c_str();
402 const char_type* __false = __np.falsename().c_str();
404 const size_t __truen = __np.truename().size() - 1;
405 const size_t __falsen = __np.falsename().size() - 1;
407 for (size_t __n = 0; __beg != __end; ++__n)
409 char_type __c = *__beg++;
410 bool __testf = __n <= __falsen ? __c == __false[__n] : false;
411 bool __testt = __n <= __truen ? __c == __true[__n] : false;
412 if (!(__testf || __testt))
414 __err |= ios_base::failbit;
417 else if (__testf && __n == __falsen)
422 else if (__testt && __n == __truen)
429 __err |= ios_base::eofbit;
435 template<typename _CharT, typename _InIter>
437 num_get<_CharT, _InIter>::
438 do_get(iter_type __beg, iter_type __end, ios_base& __io,
439 ios_base::iostate& __err, long& __v) const
443 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
444 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
448 template<typename _CharT, typename _InIter>
450 num_get<_CharT, _InIter>::
451 do_get(iter_type __beg, iter_type __end, ios_base& __io,
452 ios_base::iostate& __err, unsigned short& __v) const
456 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
458 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
459 if (!(__err & ios_base::failbit)
460 && __ul <= numeric_limits<unsigned short>::max())
461 __v = static_cast<unsigned short>(__ul);
463 __err |= ios_base::failbit;
467 template<typename _CharT, typename _InIter>
469 num_get<_CharT, _InIter>::
470 do_get(iter_type __beg, iter_type __end, ios_base& __io,
471 ios_base::iostate& __err, unsigned int& __v) const
475 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
477 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
478 if (!(__err & ios_base::failbit)
479 && __ul <= numeric_limits<unsigned int>::max())
480 __v = static_cast<unsigned int>(__ul);
482 __err |= ios_base::failbit;
486 template<typename _CharT, typename _InIter>
488 num_get<_CharT, _InIter>::
489 do_get(iter_type __beg, iter_type __end, ios_base& __io,
490 ios_base::iostate& __err, unsigned long& __v) const
494 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
495 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
499 #ifdef _GLIBCPP_USE_LONG_LONG
500 template<typename _CharT, typename _InIter>
502 num_get<_CharT, _InIter>::
503 do_get(iter_type __beg, iter_type __end, ios_base& __io,
504 ios_base::iostate& __err, long long& __v) const
508 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
509 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
513 template<typename _CharT, typename _InIter>
515 num_get<_CharT, _InIter>::
516 do_get(iter_type __beg, iter_type __end, ios_base& __io,
517 ios_base::iostate& __err, unsigned long long& __v) const
521 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
522 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
527 template<typename _CharT, typename _InIter>
529 num_get<_CharT, _InIter>::
530 do_get(iter_type __beg, iter_type __end, ios_base& __io,
531 ios_base::iostate& __err, float& __v) const
535 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
536 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
540 template<typename _CharT, typename _InIter>
542 num_get<_CharT, _InIter>::
543 do_get(iter_type __beg, iter_type __end, ios_base& __io,
544 ios_base::iostate& __err, double& __v) const
548 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
549 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
553 template<typename _CharT, typename _InIter>
555 num_get<_CharT, _InIter>::
556 do_get(iter_type __beg, iter_type __end, ios_base& __io,
557 ios_base::iostate& __err, long double& __v) const
561 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
562 __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
566 template<typename _CharT, typename _InIter>
568 num_get<_CharT, _InIter>::
569 do_get(iter_type __beg, iter_type __end, ios_base& __io,
570 ios_base::iostate& __err, void*& __v) const
572 // Prepare for hex formatted input
573 typedef ios_base::fmtflags fmtflags;
574 fmtflags __fmt = __io.flags();
575 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
576 | ios_base::uppercase | ios_base::internal);
577 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
581 __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
583 // Reset from hex formatted input
587 __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
588 if (!(__err & ios_base::failbit))
589 __v = reinterpret_cast<void*>(__ul);
591 __err |= ios_base::failbit;
595 // The following code uses snprintf (or sprintf(), when _GLIBCPP_USE_C99
596 // is not defined) to convert floating point values for insertion into a
597 // stream. An optimization would be to replace them with code that works
598 // directly on a wide buffer and then use __pad to do the padding.
599 // It would be good to replace them anyway to gain back the efficiency
600 // that C++ provides by knowing up front the type of the values to insert.
601 // Also, sprintf is dangerous since may lead to accidental buffer overruns.
602 // This implementation follows the C++ standard fairly directly as
603 // outlined in 22.2.2.2 [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 // Note: digits10 is rounded down. We need to add 1 to ensure
612 // we get the full available precision.
613 const int __max_digits = numeric_limits<_ValueT>::digits10 + 1;
614 streamsize __prec = __io.precision();
616 if (__prec > static_cast<streamsize>(__max_digits))
617 __prec = static_cast<streamsize>(__max_digits);
619 // Long enough for the max format spec.
622 // [22.2.2.2.2] Stage 1, numeric conversion to character.
624 #ifdef _GLIBCPP_USE_C99
625 // First try a buffer perhaps big enough (for sure sufficient for
626 // non-ios_base::fixed outputs)
627 int __cs_size = __max_digits * 3;
628 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
630 const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec);
632 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale, __prec);
634 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
636 // If the buffer was not large enough, try again with the correct size.
637 if (__len >= __cs_size)
639 __cs_size = __len + 1;
640 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
642 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale, __prec);
644 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
647 // Consider the possibility of long ios_base::fixed outputs
648 const bool __fixed = __io.flags() & ios_base::fixed;
649 const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
650 // ios_base::fixed outputs may need up to __max_exp+1 chars
651 // for the integer part + up to __max_digits chars for the
652 // fractional part + 3 chars for sign, decimal point, '\0'. On
653 // the other hand, for non-fixed outputs __max_digits*3 chars
654 // are largely sufficient.
655 const int __cs_size = __fixed ? __max_exp + __max_digits + 4
657 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
659 if (_S_format_float(__io, __fbuf, __mod, __prec))
660 __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
662 __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
664 return _M_widen_float(__s, __io, __fill, __cs, __len);
667 template<typename _CharT, typename _OutIter>
668 template<typename _ValueT>
670 num_put<_CharT, _OutIter>::
671 _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
672 char __modl, _ValueT __v) const
674 // [22.2.2.2.2] Stage 1, numeric conversion to character.
676 // Long enough for the max format spec.
678 _S_format_int(__io, __fbuf, __mod, __modl);
679 #ifdef _GLIBCPP_USE_C99
680 // First try a buffer perhaps big enough.
682 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
683 int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
684 // If the buffer was not large enough, try again with the correct size.
685 if (__len >= __cs_size)
687 __cs_size = __len + 1;
688 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
689 __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
692 // Leave room for "+/-," "0x," and commas. This size is
693 // arbitrary, but should be largely sufficient.
695 int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
697 return _M_widen_int(__s, __io, __fill, __cs, __len);
700 template<typename _CharT, typename _OutIter>
702 num_put<_CharT, _OutIter>::
703 _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
706 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
707 // numpunct.decimal_point() values for '.' and adding grouping.
708 const locale __loc = __io.getloc();
709 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
710 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
712 // Grouping can add (almost) as many separators as the number of
713 // digits, but no more.
714 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
716 __ctype.widen(__cs, __cs + __len, __ws);
718 // Replace decimal point.
720 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
721 if (__p = char_traits<_CharT>::find(__ws, __len, __ctype.widen('.')))
722 __ws[__p - __ws] = __np.decimal_point();
724 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
725 //282. What types does numpunct grouping refer to?
726 // Add grouping, if necessary.
727 const string __grouping = __np.grouping();
728 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
729 if (__grouping.size())
732 int __declen = __p ? __p - __ws : __len;
733 __p2 = __add_grouping(__ws2, __np.thousands_sep(),
735 __grouping.c_str() + __grouping.size(),
736 __ws, __ws + __declen);
737 int __newlen = __p2 - __ws2;
739 // Tack on decimal part.
742 char_traits<_CharT>::copy(__p2, __p, __len - __declen);
743 __newlen += __len - __declen;
746 // Switch strings, establish correct new length.
751 return _M_insert(__s, __io, __fill, __ws, __len);
754 template<typename _CharT, typename _OutIter>
756 num_put<_CharT, _OutIter>::
757 _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
760 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
761 // numpunct.decimal_point() values for '.' and adding grouping.
762 const locale __loc = __io.getloc();
763 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
764 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
766 // Grouping can add (almost) as many separators as the number of
767 // digits, but no more.
768 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
770 __ctype.widen(__cs, __cs + __len, __ws);
772 // Add grouping, if necessary.
773 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
774 const string __grouping = __np.grouping();
775 const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
776 if (__grouping.size())
778 // By itself __add_grouping cannot deal correctly with __ws when
779 // ios::showbase is set and ios_base::oct || ios_base::hex.
780 // Therefore we take care "by hand" of the initial 0, 0x or 0X.
781 streamsize __off = 0;
782 if (__io.flags() & ios_base::showbase)
783 if (__basefield == ios_base::oct)
788 else if (__basefield == ios_base::hex)
792 *(__ws2 + 1) = *(__ws + 1);
795 __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), __grouping.c_str(),
796 __grouping.c_str() + __grouping.size(),
797 __ws + __off, __ws + __len);
802 return _M_insert(__s, __io, __fill, __ws, __len);
805 // For use by integer and floating-point types after they have been
806 // converted into a char_type string.
807 template<typename _CharT, typename _OutIter>
809 num_put<_CharT, _OutIter>::
810 _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws,
813 // [22.2.2.2.2] Stage 3.
814 streamsize __w = __io.width();
815 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
817 if (__w > static_cast<streamsize>(__len))
819 __pad(__io, __fill, __ws2, __ws, __w, __len, true);
820 __len = static_cast<int>(__w);
826 // [22.2.2.2.2] Stage 4.
827 // Write resulting, fully-formatted string to output iterator.
828 for (int __j = 0; __j < __len; ++__j, ++__s)
833 template<typename _CharT, typename _OutIter>
835 num_put<_CharT, _OutIter>::
836 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
838 ios_base::fmtflags __flags = __io.flags();
839 if ((__flags & ios_base::boolalpha) == 0)
841 unsigned long __uv = __v;
842 __s = _M_convert_int(__s, __io, __fill, 'u', char_type(), __uv);
846 locale __loc = __io.getloc();
847 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
848 const char_type* __ws;
852 __ws = __np.truename().c_str();
853 __len = __np.truename().size();
857 __ws = __np.falsename().c_str();
858 __len = __np.falsename().size();
860 __s = _M_insert(__s, __io, __fill, __ws, __len);
865 template<typename _CharT, typename _OutIter>
867 num_put<_CharT, _OutIter>::
868 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
869 { return _M_convert_int(__s, __io, __fill, 'd', char_type(), __v); }
871 template<typename _CharT, typename _OutIter>
873 num_put<_CharT, _OutIter>::
874 do_put(iter_type __s, ios_base& __io, char_type __fill,
875 unsigned long __v) const
876 { return _M_convert_int(__s, __io, __fill, 'u', char_type(), __v); }
878 #ifdef _GLIBCPP_USE_LONG_LONG
879 template<typename _CharT, typename _OutIter>
881 num_put<_CharT, _OutIter>::
882 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
883 { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); }
885 template<typename _CharT, typename _OutIter>
887 num_put<_CharT, _OutIter>::
888 do_put(iter_type __s, ios_base& __io, char_type __fill,
889 unsigned long long __v) const
890 { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); }
893 template<typename _CharT, typename _OutIter>
895 num_put<_CharT, _OutIter>::
896 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
897 { return _M_convert_float(__s, __io, __fill, char_type(), __v); }
899 template<typename _CharT, typename _OutIter>
901 num_put<_CharT, _OutIter>::
902 do_put(iter_type __s, ios_base& __io, char_type __fill,
903 long double __v) const
904 { return _M_convert_float(__s, __io, __fill, 'L', __v); }
906 template<typename _CharT, typename _OutIter>
908 num_put<_CharT, _OutIter>::
909 do_put(iter_type __s, ios_base& __io, char_type __fill,
910 const void* __v) const
912 ios_base::fmtflags __flags = __io.flags();
913 ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
914 | ios_base::uppercase | ios_base::internal);
915 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
918 __s = _M_convert_int(__s, __io, __fill, 'u', char_type(),
919 reinterpret_cast<unsigned long>(__v));
925 __throw_exception_again;
931 template<typename _CharT, typename _InIter>
933 money_get<_CharT, _InIter>::
934 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
935 ios_base::iostate& __err, long double& __units) const
938 __beg = this->do_get(__beg, __end, __intl, __io, __err, __str);
940 const int __n = numeric_limits<long double>::digits10;
941 char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
942 const locale __loc = __io.getloc();
943 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
944 const _CharT* __wcs = __str.c_str();
945 __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);
946 __convert_to_v(__cs, __units, __err, _S_c_locale);
950 template<typename _CharT, typename _InIter>
952 money_get<_CharT, _InIter>::
953 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
954 ios_base::iostate& __err, string_type& __units) const
956 // These contortions are quite unfortunate.
957 typedef moneypunct<_CharT, true> __money_true;
958 typedef moneypunct<_CharT, false> __money_false;
959 typedef money_base::part part;
960 typedef typename string_type::size_type size_type;
962 const locale __loc = __io.getloc();
963 const __money_true& __mpt = use_facet<__money_true>(__loc);
964 const __money_false& __mpf = use_facet<__money_false>(__loc);
965 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
967 const money_base::pattern __p = __intl ? __mpt.neg_format()
968 : __mpf.neg_format();
970 const string_type __pos_sign =__intl ? __mpt.positive_sign()
971 : __mpf.positive_sign();
972 const string_type __neg_sign =__intl ? __mpt.negative_sign()
973 : __mpf.negative_sign();
974 const char_type __d = __intl ? __mpt.decimal_point()
975 : __mpf.decimal_point();
976 const char_type __sep = __intl ? __mpt.thousands_sep()
977 : __mpf.thousands_sep();
979 const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
981 // Set to deduced positive or negative sign, depending.
983 // String of grouping info from thousands_sep plucked from __units.
984 string __grouping_tmp;
985 // Marker for thousands_sep position.
987 // If input iterator is in a valid state.
988 bool __testvalid = true;
989 // Flag marking when a decimal point is found.
990 bool __testdecfound = false;
992 // The tentative returned string is stored here.
993 string_type __temp_units;
995 char_type __c = *__beg;
996 char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
997 for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
999 part __which = static_cast<part>(__p.field[__i]);
1002 case money_base::symbol:
1003 if (__io.flags() & ios_base::showbase
1005 || (__i == 2 && static_cast<part>(__p.field[3]) != money_base::none)
1006 || __sign.size() > 1)
1008 // According to 22.2.6.1.2.2, symbol is required if
1009 // (__io.flags() & ios_base::showbase), otherwise is optional
1010 // and consumed only if other characters are needed to complete
1012 const string_type __symbol = __intl ? __mpt.curr_symbol()
1013 : __mpf.curr_symbol();
1014 size_type __len = __symbol.size();
1016 while (__beg != __end
1017 && __j < __len && __symbol[__j] == __c)
1022 // When (__io.flags() & ios_base::showbase) symbol is required.
1023 if (__j != __len && (__io.flags() & ios_base::showbase))
1024 __testvalid = false;
1027 case money_base::sign:
1028 // Sign might not exist, or be more than one character long.
1029 if (__pos_sign.size() && __neg_sign.size())
1031 // Sign is mandatory.
1032 if (__c == __pos_sign[0])
1034 __sign = __pos_sign;
1037 else if (__c == __neg_sign[0])
1039 __sign = __neg_sign;
1043 __testvalid = false;
1045 else if (__pos_sign.size() && __c == __pos_sign[0])
1047 __sign = __pos_sign;
1050 else if (__neg_sign.size() && __c == __neg_sign[0])
1052 __sign = __neg_sign;
1056 case money_base::value:
1057 // Extract digits, remove and stash away the
1058 // grouping of found thousands separators.
1059 while (__beg != __end
1060 && (__ctype.is(ctype_base::digit, __c)
1061 || (__c == __d && !__testdecfound)
1066 __grouping_tmp += static_cast<char>(__sep_pos);
1068 __testdecfound = true;
1070 else if (__c == __sep)
1072 if (__grouping.size())
1074 // Mark position for later analysis.
1075 __grouping_tmp += static_cast<char>(__sep_pos);
1080 __testvalid = false;
1086 __temp_units += __c;
1092 case money_base::space:
1093 case money_base::none:
1094 // Only if not at the end of the pattern.
1096 while (__beg != __end
1097 && __ctype.is(ctype_base::space, __c))
1103 // Need to get the rest of the sign characters, if they exist.
1104 if (__sign.size() > 1)
1106 size_type __len = __sign.size();
1108 for (; __c != __eof && __i < __len; ++__i)
1109 while (__beg != __end && __c != __sign[__i])
1113 __testvalid = false;
1116 // Strip leading zeros.
1117 while (__temp_units[0] == __ctype.widen('0'))
1118 __temp_units.erase(__temp_units.begin());
1120 if (__sign.size() && __sign == __neg_sign)
1121 __temp_units.insert(__temp_units.begin(), __ctype.widen('-'));
1123 // Test for grouping fidelity.
1124 if (__grouping.size() && __grouping_tmp.size())
1126 if (!__verify_grouping(__grouping, __grouping_tmp))
1127 __testvalid = false;
1130 // Iff no more characters are available.
1132 __err |= ios_base::eofbit;
1134 // Iff valid sequence is not recognized.
1135 if (!__testvalid || !__temp_units.size())
1136 __err |= ios_base::failbit;
1138 // Use the "swap trick" to copy __temp_units into __units.
1139 __temp_units.swap(__units);
1144 template<typename _CharT, typename _OutIter>
1146 money_put<_CharT, _OutIter>::
1147 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1148 long double __units) const
1150 const locale __loc = __io.getloc();
1151 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1152 #ifdef _GLIBCPP_USE_C99
1153 // First try a buffer perhaps big enough.
1155 char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __cs_size));
1156 int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, _S_c_locale);
1157 // If the buffer was not large enough, try again with the correct size.
1158 if (__len >= __cs_size)
1160 __cs_size = __len + 1;
1161 __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __cs_size));
1162 __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, _S_c_locale);
1165 // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point,
1166 // decimal digit, '\0'.
1167 const int __cs_size = numeric_limits<long double>::max_exponent10 + 5;
1168 char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __cs_size));
1169 int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale);
1171 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size));
1172 __ctype.widen(__cs, __cs + __len, __ws);
1173 string_type __digits(__ws);
1174 return this->do_put(__s, __intl, __io, __fill, __digits);
1177 template<typename _CharT, typename _OutIter>
1179 money_put<_CharT, _OutIter>::
1180 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1181 const string_type& __digits) const
1183 typedef typename string_type::size_type size_type;
1184 typedef money_base::part part;
1186 const locale __loc = __io.getloc();
1187 const size_type __width = static_cast<size_type>(__io.width());
1189 // These contortions are quite unfortunate.
1190 typedef moneypunct<_CharT, true> __money_true;
1191 typedef moneypunct<_CharT, false> __money_false;
1192 const __money_true& __mpt = use_facet<__money_true>(__loc);
1193 const __money_false& __mpf = use_facet<__money_false>(__loc);
1194 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1196 // Determine if negative or positive formats are to be used, and
1197 // discard leading negative_sign if it is present.
1198 const char_type* __beg = __digits.data();
1199 const char_type* __end = __beg + __digits.size();
1200 money_base::pattern __p;
1202 if (*__beg != __ctype.widen('-'))
1204 __p = __intl ? __mpt.pos_format() : __mpf.pos_format();
1205 __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
1209 __p = __intl ? __mpt.neg_format() : __mpf.neg_format();
1210 __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
1214 // Look for valid numbers in the current ctype facet within input digits.
1215 __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
1218 // Assume valid input, and attempt to format.
1219 // Break down input numbers into base components, as follows:
1220 // final_value = grouped units + (decimal point) + (digits)
1222 string_type __value;
1223 const string_type __symbol = __intl ? __mpt.curr_symbol()
1224 : __mpf.curr_symbol();
1226 // Deal with decimal point, decimal digits.
1227 const int __frac = __intl ? __mpt.frac_digits()
1228 : __mpf.frac_digits();
1231 const char_type __d = __intl ? __mpt.decimal_point()
1232 : __mpf.decimal_point();
1233 if (__end - __beg >= __frac)
1235 __value = string_type(__end - __frac, __end);
1236 __value.insert(__value.begin(), __d);
1241 // Have to pad zeros in the decimal position.
1242 __value = string_type(__beg, __end);
1243 int __paddec = __frac - (__end - __beg);
1244 char_type __zero = __ctype.widen('0');
1245 __value.insert(__value.begin(), __paddec, __zero);
1246 __value.insert(__value.begin(), __d);
1251 // Add thousands separators to non-decimal digits, per
1255 const string __grouping = __intl ? __mpt.grouping()
1257 if (__grouping.size())
1259 const char_type __sep = __intl ? __mpt.thousands_sep()
1260 : __mpf.thousands_sep();
1261 const char* __gbeg = __grouping.c_str();
1262 const char* __gend = __gbeg + __grouping.size();
1263 const int __n = (__end - __beg) * 2;
1265 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
1266 _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg,
1267 __gend, __beg, __end);
1268 __value.insert(0, __ws2, __ws_end - __ws2);
1271 __value.insert(0, string_type(__beg, __end));
1274 // Calculate length of resulting string.
1275 ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
1276 size_type __len = __value.size() + __sign.size();
1277 __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
1278 bool __testipad = __f == ios_base::internal && __len < __width;
1280 // Fit formatted digits into the required pattern.
1281 for (int __i = 0; __i < 4; ++__i)
1283 part __which = static_cast<part>(__p.field[__i]);
1286 case money_base::symbol:
1287 if (__io.flags() & ios_base::showbase)
1290 case money_base::sign:
1291 // Sign might not exist, or be more than one
1292 // charater long. In that case, add in the rest
1297 case money_base::value:
1300 case money_base::space:
1301 // At least one space is required, but if internal
1302 // formatting is required, an arbitrary number of
1303 // fill spaces will be necessary.
1305 __res += string_type(__width - __len, __fill);
1307 __res += __ctype.widen(__fill);
1309 case money_base::none:
1311 __res += string_type(__width - __len, __fill);
1316 // Special case of multi-part sign parts.
1317 if (__sign.size() > 1)
1318 __res += string_type(__sign.begin() + 1, __sign.end());
1320 // Pad, if still necessary.
1321 __len = __res.size();
1322 if (__width > __len)
1324 if (__f == ios_base::left)
1326 __res.append(__width - __len, __fill);
1329 __res.insert(0, string_type(__width - __len, __fill));
1333 // Write resulting, fully-formatted string to output iterator.
1334 for (size_type __j = 0; __j < __len; ++__j, ++__s)
1342 // NB: Not especially useful. Without an ios_base object or some
1343 // kind of locale reference, we are left clawing at the air where
1344 // the side of the mountain used to be...
1345 template<typename _CharT, typename _InIter>
1346 time_base::dateorder
1347 time_get<_CharT, _InIter>::do_date_order() const
1348 { return time_base::no_order; }
1350 template<typename _CharT, typename _InIter>
1352 time_get<_CharT, _InIter>::
1353 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
1354 ios_base::iostate& __err, tm* __tm,
1355 const _CharT* __format) const
1357 locale __loc = __io.getloc();
1358 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1359 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1360 size_t __len = char_traits<_CharT>::length(__format);
1362 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
1364 char __c = __format[__i];
1367 // Verify valid formatting code, attempt to extract.
1368 __c = __format[++__i];
1371 if (__c == 'E' || __c == 'O')
1374 __c = __format[++__i];
1381 // Abbreviated weekday name [tm_wday]
1382 const char_type* __days1[7];
1383 __tp._M_days_abbreviated(__days1);
1384 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7,
1388 // Weekday name [tm_wday].
1389 const char_type* __days2[7];
1390 __tp._M_days(__days2);
1391 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7,
1396 // Abbreviated month name [tm_mon]
1397 const char_type* __months1[12];
1398 __tp._M_months_abbreviated(__months1);
1399 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12,
1403 // Month name [tm_mon].
1404 const char_type* __months2[12];
1405 __tp._M_months(__months2);
1406 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12,
1410 // Default time and date representation.
1411 const char_type* __dt[2];
1412 __tp._M_date_time_formats(__dt);
1413 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1417 // Day [01, 31]. [tm_mday]
1418 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
1422 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
1424 __ctype.widen(__cs, __cs + 9, __wcs);
1425 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1429 // Hour [00, 23]. [tm_hour]
1430 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1434 // Hour [01, 12]. [tm_hour]
1435 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
1439 // Month [01, 12]. [tm_mon]
1440 _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype,
1443 __tm->tm_mon = __mem - 1;
1446 // Minute [00, 59]. [tm_min]
1447 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1451 if (__ctype.narrow(*__beg, 0) == '\n')
1454 __err |= ios_base::failbit;
1457 // Equivalent to (%H:%M).
1459 __ctype.widen(__cs, __cs + 6, __wcs);
1460 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1465 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
1469 if (__ctype.narrow(*__beg, 0) == '\t')
1472 __err |= ios_base::failbit;
1475 // Equivalent to (%H:%M:%S).
1477 __ctype.widen(__cs, __cs + 9, __wcs);
1478 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1483 const char_type* __dates[2];
1484 __tp._M_date_formats(__dates);
1485 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1490 const char_type* __times[2];
1491 __tp._M_time_formats(__times);
1492 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1496 // Two digit year. [tm_year]
1497 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
1501 // Year [1900). [tm_year]
1502 _M_extract_num(__beg, __end, __mem, 0,
1503 numeric_limits<int>::max(), 4,
1506 __tm->tm_year = __mem - 1900;
1510 if (__ctype.is(ctype_base::upper, *__beg))
1513 _M_extract_name(__beg, __end, __tmp,
1514 __timepunct<_CharT>::_S_timezones,
1517 // GMT requires special effort.
1518 char_type __c = *__beg;
1519 if (!__err && __tmp == 0
1520 && (__c == __ctype.widen('-')
1521 || __c == __ctype.widen('+')))
1523 _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1525 _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1530 __err |= ios_base::failbit;
1534 __err |= ios_base::failbit;
1539 // Verify format and input match, extract and discard.
1540 if (__c == __ctype.narrow(*__beg, 0))
1543 __err |= ios_base::failbit;
1548 template<typename _CharT, typename _InIter>
1550 time_get<_CharT, _InIter>::
1551 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
1552 int __min, int __max, size_t __len,
1553 const ctype<_CharT>& __ctype,
1554 ios_base::iostate& __err) const
1558 bool __testvalid = true;
1559 char_type __c = *__beg;
1560 while (__beg != __end && __i < __len
1561 && __ctype.is(ctype_base::digit, __c))
1563 __digits += __ctype.narrow(__c, 0);
1569 int __value = atoi(__digits.c_str());
1570 if (__min <= __value && __value <= __max)
1573 __testvalid = false;
1576 __testvalid = false;
1578 __err |= ios_base::failbit;
1582 // All elements in __names are unique.
1583 template<typename _CharT, typename _InIter>
1585 time_get<_CharT, _InIter>::
1586 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
1587 const _CharT** __names, size_t __indexlen,
1588 ios_base::iostate& __err) const
1590 typedef char_traits<char_type> __traits_type;
1591 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen));
1592 size_t __nmatches = 0;
1594 bool __testvalid = true;
1595 const char_type* __name;
1597 char_type __c = *__beg;
1598 // Look for initial matches.
1599 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1600 if (__c == __names[__i1][0])
1601 __matches[__nmatches++] = __i1;
1603 while(__nmatches > 1)
1605 // Find smallest matching string.
1606 size_t __minlen = 10;
1607 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
1608 __minlen = min(__minlen,
1609 __traits_type::length(__names[__matches[__i2]]));
1611 if (__pos < __minlen && __beg != __end)
1615 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1617 __name = __names[__matches[__i3]];
1618 if (__name[__pos] != __c)
1619 __matches[__i3] = __matches[--__nmatches];
1626 if (__nmatches == 1)
1628 // Make sure found name is completely extracted.
1629 __name = __names[__matches[0]];
1630 const size_t __len = __traits_type::length(__name);
1631 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
1635 __member = __matches[0];
1637 __testvalid = false;
1640 __testvalid = false;
1642 __err |= ios_base::failbit;
1645 template<typename _CharT, typename _InIter>
1647 time_get<_CharT, _InIter>::
1648 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1649 ios_base::iostate& __err, tm* __tm) const
1652 const char* __cs = "%X";
1653 locale __loc = __io.getloc();
1654 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1655 __ctype.widen(__cs, __cs + 3, __wcs);
1656 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1658 __err |= ios_base::eofbit;
1662 template<typename _CharT, typename _InIter>
1664 time_get<_CharT, _InIter>::
1665 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1666 ios_base::iostate& __err, tm* __tm) const
1669 const char* __cs = "%x";
1670 locale __loc = __io.getloc();
1671 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1672 __ctype.widen(__cs, __cs + 3, __wcs);
1673 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1675 __err |= ios_base::eofbit;
1679 template<typename _CharT, typename _InIter>
1681 time_get<_CharT, _InIter>::
1682 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1683 ios_base::iostate& __err, tm* __tm) const
1685 typedef char_traits<char_type> __traits_type;
1686 locale __loc = __io.getloc();
1687 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1688 const char_type* __days[7];
1689 __tp._M_days_abbreviated(__days);
1691 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err);
1693 // Check to see if non-abbreviated name exists, and extract.
1694 // NB: Assumes both _M_days and _M_days_abbreviated organized in
1695 // exact same order, first to last, such that the resulting
1696 // __days array with the same index points to a day, and that
1697 // day's abbreviated form.
1698 // NB: Also assumes that an abbreviated name is a subset of the name.
1701 size_t __pos = __traits_type::length(__days[__tmpwday]);
1702 __tp._M_days(__days);
1703 const char_type* __name = __days[__tmpwday];
1704 if (__name[__pos] == *__beg)
1706 // Extract the rest of it.
1707 const size_t __len = __traits_type::length(__name);
1708 while (__pos < __len && __beg != __end
1709 && __name[__pos] == *__beg)
1712 __err |= ios_base::failbit;
1715 __tm->tm_wday = __tmpwday;
1718 __err |= ios_base::eofbit;
1722 template<typename _CharT, typename _InIter>
1724 time_get<_CharT, _InIter>::
1725 do_get_monthname(iter_type __beg, iter_type __end,
1726 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1728 typedef char_traits<char_type> __traits_type;
1729 locale __loc = __io.getloc();
1730 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1731 const char_type* __months[12];
1732 __tp._M_months_abbreviated(__months);
1734 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err);
1736 // Check to see if non-abbreviated name exists, and extract.
1737 // NB: Assumes both _M_months and _M_months_abbreviated organized in
1738 // exact same order, first to last, such that the resulting
1739 // __months array with the same index points to a month, and that
1740 // month's abbreviated form.
1741 // NB: Also assumes that an abbreviated name is a subset of the name.
1744 size_t __pos = __traits_type::length(__months[__tmpmon]);
1745 __tp._M_months(__months);
1746 const char_type* __name = __months[__tmpmon];
1747 if (__name[__pos] == *__beg)
1749 // Extract the rest of it.
1750 const size_t __len = __traits_type::length(__name);
1751 while (__pos < __len && __beg != __end
1752 && __name[__pos] == *__beg)
1755 __err |= ios_base::failbit;
1758 __tm->tm_mon = __tmpmon;
1762 __err |= ios_base::eofbit;
1766 template<typename _CharT, typename _InIter>
1768 time_get<_CharT, _InIter>::
1769 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1770 ios_base::iostate& __err, tm* __tm) const
1772 locale __loc = __io.getloc();
1773 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1775 char_type __c = *__beg;
1778 while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c))
1780 __digits += __ctype.narrow(__c, 0);
1784 if (__i == 2 || __i == 4)
1787 __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale);
1788 if (!(__err & ios_base::failbit) && __l <= INT_MAX)
1790 __l = __i == 2 ? __l : __l - 1900;
1791 __tm->tm_year = static_cast<int>(__l);
1795 __err |= ios_base::failbit;
1797 __err |= ios_base::eofbit;
1801 template<typename _CharT, typename _OutIter>
1803 time_put<_CharT, _OutIter>::
1804 put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1805 const _CharT* __beg, const _CharT* __end) const
1807 locale __loc = __io.getloc();
1808 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1809 while (__beg != __end)
1811 char __c = __ctype.narrow(*__beg, 0);
1818 __c = __ctype.narrow(*__beg, 0);
1820 if (__c == 'E' || __c == 'O')
1823 __format = __ctype.narrow(*__beg, 0);
1828 __s = this->do_put(__s, __io, char_type(), __tm, __format,
1840 template<typename _CharT, typename _OutIter>
1842 time_put<_CharT, _OutIter>::
1843 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1844 char __format, char __mod) const
1846 locale __loc = __io.getloc();
1847 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1848 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1850 // NB: This size is arbitrary. Should this be a data member,
1851 // initialized at construction?
1852 const size_t __maxlen = 64;
1854 static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
1856 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1857 // is possible that the format character will be longer than one
1858 // character. Possibilities include 'E' or 'O' followed by a
1859 // format character: if __mod is not the default argument, assume
1860 // it's a valid modifier.
1862 __fmt[0] = __ctype.widen('%');
1865 __fmt[1] = __format;
1866 __fmt[2] = char_type();
1871 __fmt[2] = __format;
1872 __fmt[3] = char_type();
1875 __tp._M_put_helper(__res, __maxlen, __fmt, __tm);
1877 // Write resulting, fully-formatted string to output iterator.
1878 size_t __len = char_traits<char_type>::length(__res);
1879 for (size_t __i = 0; __i < __len; ++__i, ++__s)
1885 // Generic version does nothing.
1886 template<typename _CharT>
1888 collate<_CharT>::_M_compare_helper(const _CharT*, const _CharT*) const
1891 // Generic version does nothing.
1892 template<typename _CharT>
1894 collate<_CharT>::_M_transform_helper(_CharT*, const _CharT*, size_t) const
1897 template<typename _CharT>
1900 do_compare(const _CharT* __lo1, const _CharT* __hi1,
1901 const _CharT* __lo2, const _CharT* __hi2) const
1903 const string_type __one(__lo1, __hi1);
1904 const string_type __two(__lo2, __hi2);
1905 return _M_compare_helper(__one.c_str(), __two.c_str());
1908 template<typename _CharT>
1909 typename collate<_CharT>::string_type
1911 do_transform(const _CharT* __lo, const _CharT* __hi) const
1913 size_t __len = (__hi - __lo) * 2;
1914 // First try a buffer perhaps big enough.
1916 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
1917 size_t __res = _M_transform_helper(__c, __lo, __len);
1918 // If the buffer was not large enough, try again with the correct size.
1922 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1)));
1923 _M_transform_helper(__c, __lo, __res + 1);
1925 return string_type(__c);
1928 template<typename _CharT>
1931 do_hash(const _CharT* __lo, const _CharT* __hi) const
1933 unsigned long __val = 0;
1934 for (; __lo < __hi; ++__lo)
1935 __val = *__lo + ((__val << 7) |
1936 (__val >> (numeric_limits<unsigned long>::digits - 7)));
1937 return static_cast<long>(__val);
1940 // Convert string to numeric value of type _Tv and store results.
1941 // NB: This is specialized for all required types, there is no
1942 // generic definition.
1943 template<typename _Tv>
1945 __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err,
1946 const __c_locale& __cloc, int __base = 10);
1948 // Convert numeric value of type _Tv to string and return length of string.
1949 // If snprintf is available use it, otherwise fall back to the unsafe sprintf
1950 // which, in general, can be dangerous and should be avoided.
1951 #ifdef _GLIBCPP_USE_C99
1952 template<typename _Tv>
1954 __convert_from_v(char* __out, const int __size, const char* __fmt,
1955 _Tv __v, const __c_locale&, int __prec = -1)
1958 const char* __old = setlocale(LC_ALL, "C");
1960 __ret = snprintf(__out, __size, __fmt, __prec, __v);
1962 __ret = snprintf(__out, __size, __fmt, __v);
1963 setlocale(LC_ALL, __old);
1967 template<typename _Tv>
1969 __convert_from_v(char* __out, const int, const char* __fmt, _Tv __v,
1970 const __c_locale&, int __prec = -1)
1973 const char* __old = setlocale(LC_ALL, "C");
1975 __ret = sprintf(__out, __fmt, __prec, __v);
1977 __ret = sprintf(__out, __fmt, __v);
1978 setlocale(LC_ALL, __old);
1983 // Construct correctly padded string, as per 22.2.2.2.2
1985 // __newlen > __oldlen
1986 // __news is allocated for __newlen size
1987 // Used by both num_put and ostream inserters: if __num,
1988 // internal-adjusted objects are padded according to the rules below
1989 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
1991 template<typename _CharT, typename _Traits>
1993 __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds,
1994 const streamsize __newlen, const streamsize __oldlen,
1997 typedef _CharT char_type;
1998 typedef _Traits traits_type;
1999 typedef typename traits_type::int_type int_type;
2001 int_type __plen = static_cast<size_t>(__newlen - __oldlen);
2002 char_type* __pads = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen));
2003 traits_type::assign(__pads, __plen, __fill);
2008 size_t __beglen; //either __plen or __oldlen
2009 ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
2011 if (__adjust == ios_base::left)
2014 __beg = const_cast<char_type*>(__olds);
2015 __beglen = __oldlen;
2018 else if (__adjust == ios_base::internal && __num)
2020 // Pad after the sign, if there is one.
2021 // Pad after 0[xX], if there is one.
2022 // Who came up with these rules, anyway? Jeeze.
2023 locale __loc = __io.getloc();
2024 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2025 const char_type __minus = __ctype.widen('-');
2026 const char_type __plus = __ctype.widen('+');
2027 bool __testsign = __olds[0] == __minus || __olds[0] == __plus;
2028 bool __testhex = __ctype.widen('0') == __olds[0]
2029 && (__ctype.widen('x') == __olds[1]
2030 || __ctype.widen('X') == __olds[1]);
2033 __news[0] = __olds[0];
2034 __news[1] = __olds[1];
2039 __end = const_cast<char_type*>(__olds + __mod);
2041 else if (__testsign)
2043 __news[0] = __olds[0] == __plus ? __plus : __minus;
2048 __end = const_cast<char_type*>(__olds + __mod);
2055 __end = const_cast<char_type*>(__olds);
2063 __end = const_cast<char_type*>(__olds);
2065 traits_type::copy(__news, __beg, __beglen);
2066 traits_type::copy(__news + __beglen, __end, __newlen - __beglen - __mod);
2069 // NB: Can't have default argument on non-member template, and
2070 // num_put doesn't have a _Traits template parameter, so this
2071 // forwarding template adds in the default template argument.
2072 template<typename _CharT>
2074 __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds,
2075 const streamsize __newlen, const streamsize __oldlen,
2078 return __pad<_CharT, char_traits<_CharT> >(__io, __fill, __news, __olds,
2079 __newlen, __oldlen, __num);
2082 // Used by both numeric and monetary facets.
2083 // Check to make sure that the __grouping_tmp string constructed in
2084 // money_get or num_get matches the canonical grouping for a given
2086 // __grouping_tmp is parsed L to R
2087 // 1,222,444 == __grouping_tmp of "/1/3/3"
2088 // __grouping is parsed R to L
2089 // 1,222,444 == __grouping of "/3" == "/3/3/3"
2090 template<typename _CharT>
2092 __verify_grouping(const basic_string<_CharT>& __grouping,
2093 basic_string<_CharT>& __grouping_tmp)
2097 const int __len = __grouping.size();
2098 const int __n = __grouping_tmp.size();
2101 // Parsed number groupings have to match the
2102 // numpunct::grouping string exactly, starting at the
2103 // right-most point of the parsed sequence of elements ...
2104 while (__test && __i < __n - 1)
2105 for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
2106 __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1];
2107 // ... but the last parsed grouping can be <= numpunct
2109 __j == __len ? __j = 0 : __j;
2110 __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1];
2114 // Used by both numeric and monetary facets.
2115 // Inserts "group separator" characters into an array of characters.
2116 // It's recursive, one iteration per group. It moves the characters
2117 // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this
2118 // only with __gbeg != __gend.
2119 template<typename _CharT>
2121 __add_grouping(_CharT* __s, _CharT __sep,
2122 const char* __gbeg, const char* __gend,
2123 const _CharT* __first, const _CharT* __last)
2125 if (__last - __first > *__gbeg)
2127 __s = __add_grouping(__s, __sep,
2128 (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
2129 __gend, __first, __last - *__gbeg);
2130 __first = __last - *__gbeg;
2134 *__s++ = *__first++;
2135 while (__first != __last);
2139 // Inhibit implicit instantiations for required instantiations,
2140 // which are defined via explicit instantiations elsewhere.
2141 // NB: This syntax is a GNU extension.
2142 extern template class vector<locale::facet*>;
2144 extern template class moneypunct<char, false>;
2145 extern template class moneypunct<char, true>;
2146 extern template class moneypunct_byname<char, false>;
2147 extern template class moneypunct_byname<char, true>;
2148 extern template class money_get<char>;
2149 extern template class money_put<char>;
2150 extern template class moneypunct<wchar_t, false>;
2151 extern template class moneypunct<wchar_t, true>;
2152 extern template class moneypunct_byname<wchar_t, false>;
2153 extern template class moneypunct_byname<wchar_t, true>;
2154 extern template class money_get<wchar_t>;
2155 extern template class money_put<wchar_t>;
2156 extern template class numpunct<char>;
2157 extern template class numpunct_byname<char>;
2158 extern template class num_get<char>;
2159 extern template class num_put<char>;
2160 extern template class numpunct<wchar_t>;
2161 extern template class numpunct_byname<wchar_t>;
2162 extern template class num_get<wchar_t>;
2163 extern template class num_put<wchar_t>;
2164 extern template class __timepunct<char>;
2165 extern template class time_put<char>;
2166 extern template class time_put_byname<char>;
2167 extern template class time_get<char>;
2168 extern template class time_get_byname<char>;
2169 extern template class __timepunct<wchar_t>;
2170 extern template class time_put<wchar_t>;
2171 extern template class time_put_byname<wchar_t>;
2172 extern template class time_get<wchar_t>;
2173 extern template class time_get_byname<wchar_t>;
2174 extern template class messages<char>;
2175 extern template class messages_byname<char>;
2176 extern template class messages<wchar_t>;
2177 extern template class messages_byname<wchar_t>;
2178 extern template class ctype_byname<char>;
2179 extern template class ctype_byname<wchar_t>;
2180 extern template class codecvt_byname<char, char, mbstate_t>;
2181 extern template class codecvt_byname<wchar_t, char, mbstate_t>;
2182 extern template class collate<char>;
2183 extern template class collate_byname<char>;
2184 extern template class collate<wchar_t>;
2185 extern template class collate_byname<wchar_t>;
2188 const codecvt<char, char, mbstate_t>&
2189 use_facet<codecvt<char, char, mbstate_t> >(const locale&);
2192 const collate<char>&
2193 use_facet<collate<char> >(const locale&);
2196 const numpunct<char>&
2197 use_facet<numpunct<char> >(const locale&);
2200 const num_put<char>&
2201 use_facet<num_put<char> >(const locale&);
2204 const num_get<char>&
2205 use_facet<num_get<char> >(const locale&);
2208 const moneypunct<char, true>&
2209 use_facet<moneypunct<char, true> >(const locale&);
2212 const moneypunct<char, false>&
2213 use_facet<moneypunct<char, false> >(const locale&);
2216 const money_put<char>&
2217 use_facet<money_put<char> >(const locale&);
2220 const money_get<char>&
2221 use_facet<money_get<char> >(const locale&);
2224 const __timepunct<char>&
2225 use_facet<__timepunct<char> >(const locale&);
2228 const time_put<char>&
2229 use_facet<time_put<char> >(const locale&);
2232 const time_get<char>&
2233 use_facet<time_get<char> >(const locale&);
2236 const messages<char>&
2237 use_facet<messages<char> >(const locale&);
2240 const codecvt<wchar_t, char, mbstate_t>&
2241 use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
2244 const collate<wchar_t>&
2245 use_facet<collate<wchar_t> >(const locale&);
2248 const numpunct<wchar_t>&
2249 use_facet<numpunct<wchar_t> >(const locale&);
2252 const num_put<wchar_t>&
2253 use_facet<num_put<wchar_t> >(const locale&);
2256 const num_get<wchar_t>&
2257 use_facet<num_get<wchar_t> >(const locale&);
2260 const moneypunct<wchar_t, true>&
2261 use_facet<moneypunct<wchar_t, true> >(const locale&);
2264 const moneypunct<wchar_t, false>&
2265 use_facet<moneypunct<wchar_t, false> >(const locale&);
2268 const money_put<wchar_t>&
2269 use_facet<money_put<wchar_t> >(const locale&);
2272 const money_get<wchar_t>&
2273 use_facet<money_get<wchar_t> >(const locale&);
2276 const __timepunct<wchar_t>&
2277 use_facet<__timepunct<wchar_t> >(const locale&);
2280 const time_put<wchar_t>&
2281 use_facet<time_put<wchar_t> >(const locale&);
2284 const time_get<wchar_t>&
2285 use_facet<time_get<wchar_t> >(const locale&);
2288 const messages<wchar_t>&
2289 use_facet<messages<wchar_t> >(const locale&);
2294 has_facet<ctype<char> >(const locale&);
2298 has_facet<codecvt<char, char, mbstate_t> >(const locale&);
2302 has_facet<collate<char> >(const locale&);
2306 has_facet<numpunct<char> >(const locale&);
2310 has_facet<num_put<char> >(const locale&);
2314 has_facet<num_get<char> >(const locale&);
2318 has_facet<moneypunct<char> >(const locale&);
2322 has_facet<money_put<char> >(const locale&);
2326 has_facet<money_get<char> >(const locale&);
2330 has_facet<__timepunct<char> >(const locale&);
2334 has_facet<time_put<char> >(const locale&);
2338 has_facet<time_get<char> >(const locale&);
2342 has_facet<messages<char> >(const locale&);
2346 has_facet<ctype<wchar_t> >(const locale&);
2350 has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
2354 has_facet<collate<wchar_t> >(const locale&);
2358 has_facet<numpunct<wchar_t> >(const locale&);
2362 has_facet<num_put<wchar_t> >(const locale&);
2366 has_facet<num_get<wchar_t> >(const locale&);
2370 has_facet<moneypunct<wchar_t> >(const locale&);
2374 has_facet<money_put<wchar_t> >(const locale&);
2378 has_facet<money_get<wchar_t> >(const locale&);
2382 has_facet<__timepunct<wchar_t> >(const locale&);
2386 has_facet<time_put<wchar_t> >(const locale&);
2390 has_facet<time_get<wchar_t> >(const locale&);
2394 has_facet<messages<wchar_t> >(const locale&);