1 // Locale support -*- C++ -*-
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
30 // Warning: this file is not meant for user inclusion. Use <locale>.
32 #ifndef _CPP_BITS_LOCFACETS_TCC
33 #define _CPP_BITS_LOCFACETS_TCC 1
35 #include <bits/std_cerrno.h>
36 #include <bits/std_clocale.h> // For localeconv
37 #include <bits/std_cstdlib.h> // For strof, strtold
38 #include <bits/std_cmath.h> // For ceil
39 #include <bits/std_limits.h> // For numeric_limits
40 #include <bits/std_memory.h> // For auto_ptr
41 #include <bits/streambuf_iterator.h> // For streambuf_iterators
42 #include <bits/std_cctype.h> // For isspace
43 #include <typeinfo> // For bad_cast
44 #include <bits/std_vector.h>
48 template<typename _Facet>
50 locale::combine(const locale& __other) const
52 _Impl* __tmp = new _Impl(*_M_impl, 1);
53 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
57 template<typename _CharT, typename _Traits, typename _Alloc>
59 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
60 const basic_string<_CharT, _Traits, _Alloc>& __s2) const
62 typedef std::collate<_CharT> __collate_type;
63 const __collate_type& __collate = use_facet<__collate_type>(*this);
64 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
65 __s2.data(), __s2.data() + __s2.length()) < 0);
68 template<typename _Facet>
70 use_facet(const locale& __loc)
72 size_t __i = _Facet::id._M_index;
73 locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets;
74 const locale::facet* __fp = (*__facet)[__i];
75 if (__fp == 0 || __i >= __facet->size())
77 return static_cast<const _Facet&>(*__fp);
80 template<typename _Facet>
82 has_facet(const locale& __loc) throw()
84 size_t __i = _Facet::id._M_index;
85 locale::_Impl::__vec_facet* __facet = __loc._M_impl->_M_facets;
86 return (__i < __facet->size() && (*__facet)[__i] != 0);
90 template<typename _CharT, typename _InIter>
92 num_get<_CharT, _InIter>::
93 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
94 ios_base::iostate& __err, string& __xtrc) const
96 const locale __loc = __io.getloc();
97 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
98 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
100 // Check first for sign.
101 const char_type __plus = __ctype.widen('+');
102 const char_type __minus = __ctype.widen('-');
104 char_type __c = *__beg;
105 if ((__c == __plus || __c == __minus) && __beg != __end)
107 __xtrc += __ctype.narrow(__c, char());
112 // Next, strip leading zeros.
113 const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
114 bool __found_zero = false;
115 while (__c == __zero && __beg != __end)
122 __xtrc += _S_atoms[_M_zero];
126 // Only need acceptable digits for floating point numbers.
127 const size_t __len = _M_E - _M_zero + 1;
128 char_type __watoms[__len];
129 __ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
130 bool __found_dec = false;
131 bool __found_sci = false;
132 const char_type __dec = __np.decimal_point();
134 string __found_grouping;
135 const string __grouping = __np.grouping();
136 bool __check_grouping = __grouping.size();
138 const char_type __sep = __np.thousands_sep();
140 while (__beg != __end)
142 // Only look in digits.
143 typedef char_traits<_CharT> __traits_type;
144 const char_type* __p = __traits_type::find(__watoms, 10, __c);
146 // NB: strchr returns true for __c == 0x0
149 // Try first for acceptable digit; record it if found.
151 __xtrc += _S_atoms[__p - __watoms];
155 else if (__c == __sep && __check_grouping && !__found_dec)
157 // NB: Thousands separator at the beginning of a string
158 // is a no-no, as is two consecutive thousands separators.
161 __found_grouping += static_cast<char>(__sep_pos);
167 __err |= ios_base::failbit;
171 else if (__c == __dec && !__found_dec)
173 __found_grouping += static_cast<char>(__sep_pos);
179 else if ((__c == __watoms[_M_e] || __c == __watoms[_M_E])
180 && !__found_sci && __pos)
182 // Scientific notation.
184 __xtrc += __ctype.narrow(__c, char());
187 // Remove optional plus or minus sign, if they exist.
188 if (__c == __plus || __c == __minus)
191 __xtrc += __ctype.narrow(__c, char());
197 // Not a valid input item.
201 // Digit grouping is checked. If grouping and found_grouping don't
202 // match, then get very very upset, and set failbit.
203 if (__check_grouping && __found_grouping.size())
205 // Add the ending grouping if a decimal wasn't found.
207 __found_grouping += static_cast<char>(__sep_pos);
208 if (!__verify_grouping(__grouping, __found_grouping))
209 __err |= ios_base::failbit;
215 __err |= ios_base::eofbit;
218 template<typename _CharT, typename _InIter>
220 num_get<_CharT, _InIter>::
221 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
222 ios_base::iostate& __err, char* __xtrc, int __max,
225 const locale __loc = __io.getloc();
226 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
227 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
229 // Stage 1: determine a conversion specifier.
230 // NB: Iff __basefield == 0, this can change based on contents.
231 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
232 if (__basefield == ios_base::oct)
234 else if (__basefield == ios_base::hex)
239 // Check first for sign.
241 char_type __c = *__beg;
242 if ((__c == __ctype.widen('+') || __c == __ctype.widen('-'))
245 __xtrc[__pos++] = __ctype.narrow(__c, char());
249 // Next, strip leading zeros and check required digits for base formats.
250 const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
251 const char_type __x = __ctype.widen('x');
252 const char_type __X = __ctype.widen('X');
255 bool __found_zero = false;
256 while (__c == __zero && __beg != __end)
263 __xtrc[__pos++] = _S_atoms[_M_zero];
264 if (__basefield == 0)
266 if ((__c == __x || __c == __X) && __beg != __end)
268 __xtrc[__pos++] = __ctype.narrow(__c, char());
277 else if (__base == 16)
279 if (__c == __zero && __beg != __end)
281 __xtrc[__pos++] = _S_atoms[_M_zero];
283 if ((__c == __x || __c == __X) && __beg != __end)
285 __xtrc[__pos++] = __ctype.narrow(__c, char());
291 // At this point, base is determined. If not hex, only allow
292 // base digits as valid input.
299 // Figure out the maximum number of digits that can be extracted
300 // for the given type, using the determined base.
303 __max_digits = static_cast<int>(ceil(__max * log(10.0)
304 /log(static_cast<double>(__base))));
306 __max_digits = __max;
307 // Add in what's already been extracted.
308 __max_digits += __pos;
311 char_type __watoms[_M_size];
312 __ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
313 string __found_grouping;
314 const string __grouping = __np.grouping();
315 bool __check_grouping = __grouping.size() && __base == 10;
317 const char_type __sep = __np.thousands_sep();
318 while (__beg != __end && __pos <= __max_digits)
320 typedef char_traits<_CharT> __traits_type;
321 const char_type* __p = __traits_type::find(__watoms, __len, __c);
323 // NB: strchr returns true for __c == 0x0
326 // Try first for acceptable digit; record it if found.
327 __xtrc[__pos++] = _S_atoms[__p - __watoms];
331 else if (__c == __sep && __check_grouping)
333 // NB: Thousands separator at the beginning of a string
334 // is a no-no, as is two consecutive thousands separators.
337 __found_grouping += static_cast<char>(__sep_pos);
343 __err |= ios_base::failbit;
348 // Not a valid input item.
352 // If one more than the maximum number of digits is extracted.
353 if (__pos > __max_digits)
354 __err |= ios_base::failbit;
356 // Digit grouping is checked. If grouping and found_grouping don't
357 // match, then get very very upset, and set failbit.
358 if (__check_grouping && __found_grouping.size())
360 // Add the ending grouping.
361 __found_grouping += static_cast<char>(__sep_pos);
362 if (!__verify_grouping(__grouping, __found_grouping))
363 __err |= ios_base::failbit;
367 __xtrc[__pos] = char();
369 __err |= ios_base::eofbit;
372 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
373 //17. Bad bool parsing
374 template<typename _CharT, typename _InIter>
376 num_get<_CharT, _InIter>::
377 do_get(iter_type __beg, iter_type __end, ios_base& __io,
378 ios_base::iostate& __err, bool& __v) const
380 // Parse bool values as long
381 if (!(__io.flags() & ios_base::boolalpha))
383 // NB: We can't just call do_get(long) here, as it might
384 // refer to a derived class.
386 // Stage 1: extract and determine the conversion specifier.
387 // Assuming leading zeros eliminated, thus the size of 32 for
391 _M_extract_int(__beg, __end, __io, __err, __xtrc,
392 numeric_limits<bool>::digits10, __base);
394 // Stage 2: convert and store results.
397 long __l = strtol(__xtrc, &__sanity, __base);
398 if (!(__err & ios_base::failbit)
400 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
403 __err |= ios_base::failbit;
406 // Parse bool values as alphanumeric
409 locale __loc = __io.getloc();
410 const numpunct<char_type>& __np = use_facet<numpunct<char_type> >(__loc);
411 const char_type* __true = __np.truename().c_str();
412 const char_type* __false = __np.falsename().c_str();
414 const size_t __truen = __np.truename().size() - 1;
415 const size_t __falsen = __np.falsename().size() - 1;
417 for (size_t __n = 0; __beg != __end; ++__n)
419 char_type __c = *__beg++;
420 bool __testf = __n <= __falsen ? __c == __false[__n] : false;
421 bool __testt = __n <= __truen ? __c == __true[__n] : false;
422 if (!(__testf || __testt))
424 __err |= ios_base::failbit;
427 else if (__testf && __n == __falsen)
432 else if (__testt && __n == __truen)
439 __err |= ios_base::eofbit;
445 template<typename _CharT, typename _InIter>
447 num_get<_CharT, _InIter>::
448 do_get(iter_type __beg, iter_type __end, ios_base& __io,
449 ios_base::iostate& __err, long& __v) const
451 // Stage 1: extract and determine the conversion specifier.
452 // Assuming leading zeros eliminated, thus the size of 32 for
456 _M_extract_int(__beg, __end, __io, __err, __xtrc,
457 numeric_limits<long>::digits10, __base);
459 // Stage 2: convert and store results.
462 long __l = strtol(__xtrc, &__sanity, __base);
463 if (!(__err & ios_base::failbit)
464 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
467 __err |= ios_base::failbit;
471 template<typename _CharT, typename _InIter>
473 num_get<_CharT, _InIter>::
474 do_get(iter_type __beg, iter_type __end, ios_base& __io,
475 ios_base::iostate& __err, unsigned short& __v) const
477 // Stage 1: extract and determine the conversion specifier.
478 // Assuming leading zeros eliminated, thus the size of 32 for
482 _M_extract_int(__beg, __end, __io, __err, __xtrc,
483 numeric_limits<unsigned short>::digits10, __base);
485 // Stage 2: convert and store results.
488 unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
489 if (!(__err & ios_base::failbit)
490 && __sanity != __xtrc && *__sanity == '\0' && errno == 0
491 && __ul <= USHRT_MAX)
492 __v = static_cast<unsigned short>(__ul);
494 __err |= ios_base::failbit;
498 template<typename _CharT, typename _InIter>
500 num_get<_CharT, _InIter>::
501 do_get(iter_type __beg, iter_type __end, ios_base& __io,
502 ios_base::iostate& __err, unsigned int& __v) const
504 // Stage 1: extract and determine the conversion specifier.
505 // Assuming leading zeros eliminated, thus the size of 32 for
509 _M_extract_int(__beg, __end, __io, __err, __xtrc,
510 numeric_limits<unsigned int>::digits10, __base);
512 // Stage 2: convert and store results.
515 unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
516 if (!(__err & ios_base::failbit)
517 && __sanity != __xtrc && *__sanity == '\0' && errno == 0
519 __v = static_cast<unsigned int>(__ul);
521 __err |= ios_base::failbit;
525 template<typename _CharT, typename _InIter>
527 num_get<_CharT, _InIter>::
528 do_get(iter_type __beg, iter_type __end, ios_base& __io,
529 ios_base::iostate& __err, unsigned long& __v) const
531 // Stage 1: extract and determine the conversion specifier.
532 // Assuming leading zeros eliminated, thus the size of 32 for
536 _M_extract_int(__beg, __end, __io, __err, __xtrc,
537 numeric_limits<unsigned long>::digits10, __base);
539 // Stage 2: convert and store results.
542 unsigned long __ul = strtoul(__xtrc, &__sanity, __base);
543 if (!(__err & ios_base::failbit)
544 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
547 __err |= ios_base::failbit;
551 #ifdef _GLIBCPP_USE_LONG_LONG
552 template<typename _CharT, typename _InIter>
554 num_get<_CharT, _InIter>::
555 do_get(iter_type __beg, iter_type __end, ios_base& __io,
556 ios_base::iostate& __err, long long& __v) const
558 // Stage 1: extract and determine the conversion specifier.
559 // Assuming leading zeros eliminated, thus the size of 32 for
563 _M_extract_int(__beg, __end, __io, __err, __xtrc,
564 numeric_limits<long long>::digits10, __base);
566 // Stage 2: convert and store results.
569 long long __ll = strtoll(__xtrc, &__sanity, __base);
570 if (!(__err & ios_base::failbit)
571 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
574 __err |= ios_base::failbit;
578 template<typename _CharT, typename _InIter>
580 num_get<_CharT, _InIter>::
581 do_get(iter_type __beg, iter_type __end, ios_base& __io,
582 ios_base::iostate& __err, unsigned long long& __v) const
584 // Stage 1: extract and determine the conversion specifier.
585 // Assuming leading zeros eliminated, thus the size of 32 for
589 _M_extract_int(__beg, __end, __io, __err, __xtrc,
590 numeric_limits<unsigned long long>::digits10, __base);
592 // Stage 2: convert and store results.
595 unsigned long long __ull = strtoull(__xtrc, &__sanity, __base);
596 if (!(__err & ios_base::failbit)
597 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
600 __err |= ios_base::failbit;
605 template<typename _CharT, typename _InIter>
607 num_get<_CharT, _InIter>::
608 do_get(iter_type __beg, iter_type __end, ios_base& __io,
609 ios_base::iostate& __err, float& __v) const
611 // Stage 1: extract and determine the conversion specifier.
614 _M_extract_float(__beg, __end, __io, __err, __xtrc);
616 // Stage 2: convert and store results.
619 #ifdef _GLIBCPP_USE_C99
620 float __f = strtof(__xtrc.c_str(), &__sanity);
622 float __f = static_cast<float>(strtod(__xtrc.c_str(), &__sanity));
624 if (!(__err & ios_base::failbit)
625 && __sanity != __xtrc.c_str() && *__sanity == '\0' && errno == 0)
628 __err |= ios_base::failbit;
632 template<typename _CharT, typename _InIter>
634 num_get<_CharT, _InIter>::
635 do_get(iter_type __beg, iter_type __end, ios_base& __io,
636 ios_base::iostate& __err, double& __v) const
638 // Stage 1: extract and determine the conversion specifier.
641 _M_extract_float(__beg, __end, __io, __err, __xtrc);
643 // Stage 2: convert and store results.
646 double __d = strtod(__xtrc.c_str(), &__sanity);
647 if (!(__err & ios_base::failbit)
648 && __sanity != __xtrc.c_str() && *__sanity == '\0' && errno == 0)
651 __err |= ios_base::failbit;
655 template<typename _CharT, typename _InIter>
657 num_get<_CharT, _InIter>::
658 do_get(iter_type __beg, iter_type __end, ios_base& __io,
659 ios_base::iostate& __err, long double& __v) const
661 // Stage 1: extract and determine the conversion specifier.
664 _M_extract_float(__beg, __end, __io, __err, __xtrc);
666 #if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
667 // Stage 2: convert and store results.
670 long double __ld = strtold(__xtrc.c_str(), &__sanity);
671 if (!(__err & ios_base::failbit)
672 && __sanity != __xtrc.c_str() && *__sanity == '\0' && errno == 0)
675 // Stage 2: determine a conversion specifier.
676 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
678 if (__basefield == ios_base::oct)
680 else if (__basefield == ios_base::hex)
682 else if (__basefield == 0)
687 // Stage 3: store results.
688 typedef typename char_traits<_CharT>::int_type int_type;
690 int __p = sscanf(__xtrc.c_str(), __conv, &__ld);
691 if (!(__err & ios_base::failbit) && __p
692 && static_cast<int_type>(__p) != char_traits<_CharT>::eof())
696 __err |= ios_base::failbit;
700 template<typename _CharT, typename _InIter>
702 num_get<_CharT, _InIter>::
703 do_get(iter_type __beg, iter_type __end, ios_base& __io,
704 ios_base::iostate& __err, void*& __v) const
706 // Prepare for hex formatted input
707 typedef ios_base::fmtflags fmtflags;
708 fmtflags __fmt = __io.flags();
709 fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
710 | ios_base::uppercase | ios_base::internal);
711 __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
713 // Stage 1: extract and determine the conversion specifier.
714 // Assuming leading zeros eliminated, thus the size of 32 for
718 _M_extract_int(__beg, __end, __io, __err, __xtrc,
719 numeric_limits<unsigned long>::digits10, __base);
721 // Stage 2: convert and store results.
724 void* __vp = reinterpret_cast<void*>(strtoul(__xtrc, &__sanity, __base));
725 if (!(__err & ios_base::failbit)
726 && __sanity != __xtrc && *__sanity == '\0' && errno == 0)
729 __err |= ios_base::failbit;
731 // Reset from hex formatted input
737 // The following code uses sprintf() to convert floating point
738 // values for insertion into a stream. An optimization would be to
739 // replace sprintf() with code that works directly on a wide buffer
740 // and then use __pad to do the padding. It would be good
741 // to replace sprintf() anyway to avoid accidental buffer overruns
742 // and to gain back the efficiency that C++ provides by knowing up
743 // front the type of the values to insert. This implementation
744 // follows the C++ standard fairly directly as outlined in 22.2.2.2
745 // [lib.locale.num.put]
746 template<typename _CharT, typename _OutIter>
747 template<typename _ValueT>
749 num_put<_CharT, _OutIter>::
750 _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
753 const int __max_digits = numeric_limits<_ValueT>::digits10;
754 streamsize __prec = __io.precision();
755 // Protect against sprintf() buffer overflows.
756 if (__prec > static_cast<streamsize>(__max_digits))
757 __prec = static_cast<streamsize>(__max_digits);
759 // Long enough for the max format spec.
762 // Consider the possibility of long ios_base::fixed outputs
763 const bool __fixed = __io.flags() & ios_base::fixed;
764 const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
765 // XXX Why + 4? Why * 4? What's going on? Who's on first?
766 const int __cs_size = __fixed ? __max_exp + __max_digits + 4
768 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
771 // [22.2.2.2.2] Stage 1, numeric conversion to character.
772 if (_S_format_float(__io, __fbuf, __mod, __prec))
773 __len = sprintf(__cs, __fbuf, __prec, __v);
775 __len = sprintf(__cs, __fbuf, __v);
776 return _M_widen_float(__s, __io, __fill, __cs, __len);
779 template<typename _CharT, typename _OutIter>
780 template<typename _ValueT>
782 num_put<_CharT, _OutIter>::
783 _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
784 char __modl, _ValueT __v) const
786 // [22.2.2.2.2] Stage 1, numeric conversion to character.
787 // Leave room for "+/-," "0x," and commas. This size is
788 // arbitrary, but should work.
790 // Long enough for the max format spec.
792 _S_format_int(__io, __fbuf, __mod, __modl);
793 int __len = sprintf(__cs, __fbuf, __v);
794 return _M_widen_int(__s, __io, __fill, __cs, __len);
797 template<typename _CharT, typename _OutIter>
799 num_put<_CharT, _OutIter>::
800 _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
803 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
804 // numpunct.decimal_point() values for '.' and adding grouping.
805 const locale __loc = __io.getloc();
806 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
807 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
809 // Grouping can add (almost) as many separators as the number of
810 // digits, but no more.
811 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
813 __ctype.widen(__cs, __cs + __len, __ws);
815 // Replace decimal point.
817 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
818 if (__p = char_traits<_CharT>::find(__ws, __len, __ctype.widen('.')))
819 __ws[__p - __ws] = __np.decimal_point();
821 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
822 //282. What types does numpunct grouping refer to?
823 // Add grouping, if necessary.
824 const string __grouping = __np.grouping();
825 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
826 if (__grouping.size())
829 int __declen = __p ? __p - __ws : __len;
830 __p2 = __add_grouping(__ws2, __np.thousands_sep(),
832 __grouping.c_str() + __grouping.size(),
833 __ws, __ws + __declen);
834 int __newlen = __p2 - __ws2;
836 // Tack on decimal part.
839 char_traits<_CharT>::copy(__p2, __p, __len - __declen);
840 __newlen += __len - __declen;
843 // Switch strings, establish correct new length.
848 return _M_insert(__s, __io, __fill, __ws, __len);
851 template<typename _CharT, typename _OutIter>
853 num_put<_CharT, _OutIter>::
854 _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
857 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
858 // numpunct.decimal_point() values for '.' and adding grouping.
859 const locale __loc = __io.getloc();
860 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
861 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
863 // Grouping can add (almost) as many separators as the number of
864 // digits, but no more.
865 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
867 __ctype.widen(__cs, __cs + __len, __ws);
869 // Add grouping, if necessary.
870 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
871 const string __grouping = __np.grouping();
872 ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
873 bool __dec = __basefield != ios_base::oct
874 && __basefield != ios_base::hex;
875 if (__grouping.size() && __dec)
878 __p = __add_grouping(__ws2, __np.thousands_sep(), __grouping.c_str(),
879 __grouping.c_str() + __grouping.size(),
885 return _M_insert(__s, __io, __fill, __ws, __len);
888 // For use by integer and floating-point types after they have been
889 // converted into a char_type string.
890 template<typename _CharT, typename _OutIter>
892 num_put<_CharT, _OutIter>::
893 _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws,
896 // [22.2.2.2.2] Stage 3.
897 streamsize __w = __io.width();
898 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
900 if (__w > static_cast<streamsize>(__len))
902 __pad(__io, __fill, __ws2, __ws, __w, __len, true);
903 __len = static_cast<int>(__w);
909 // [22.2.2.2.2] Stage 4.
910 // Write resulting, fully-formatted string to output iterator.
911 for (int __j = 0; __j < __len; ++__j, ++__s)
916 template<typename _CharT, typename _OutIter>
918 num_put<_CharT, _OutIter>::
919 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
921 ios_base::fmtflags __flags = __io.flags();
922 if ((__flags & ios_base::boolalpha) == 0)
924 unsigned long __uv = __v;
925 _M_convert_int(__s, __io, __fill, 'u', char_type(), __uv);
929 locale __loc = __io.getloc();
930 const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
931 const char_type* __ws;
935 __ws = __np.truename().c_str();
936 __len = __np.truename().size();
940 __ws = __np.falsename().c_str();
941 __len = __np.falsename().size();
943 _M_insert(__s, __io, __fill, __ws, __len);
948 template<typename _CharT, typename _OutIter>
950 num_put<_CharT, _OutIter>::
951 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
952 { return _M_convert_int(__s, __io, __fill, 'd', char_type(), __v); }
954 template<typename _CharT, typename _OutIter>
956 num_put<_CharT, _OutIter>::
957 do_put(iter_type __s, ios_base& __io, char_type __fill,
958 unsigned long __v) const
959 { return _M_convert_int(__s, __io, __fill, 'u', char_type(), __v); }
961 #ifdef _GLIBCPP_USE_LONG_LONG
962 template<typename _CharT, typename _OutIter>
964 num_put<_CharT, _OutIter>::
965 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
966 { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); }
968 template<typename _CharT, typename _OutIter>
970 num_put<_CharT, _OutIter>::
971 do_put(iter_type __s, ios_base& __io, char_type __fill,
972 unsigned long long __v) const
973 { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); }
976 template<typename _CharT, typename _OutIter>
978 num_put<_CharT, _OutIter>::
979 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
980 { return _M_convert_float(__s, __io, __fill, char_type(), __v); }
982 template<typename _CharT, typename _OutIter>
984 num_put<_CharT, _OutIter>::
985 do_put(iter_type __s, ios_base& __io, char_type __fill,
986 long double __v) const
987 { return _M_convert_float(__s, __io, __fill, 'L', __v); }
989 template<typename _CharT, typename _OutIter>
991 num_put<_CharT, _OutIter>::
992 do_put(iter_type __s, ios_base& __io, char_type __fill,
993 const void* __v) const
995 ios_base::fmtflags __flags = __io.flags();
996 ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
997 | ios_base::uppercase | ios_base::internal);
998 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
1001 _M_convert_int(__s, __io, __fill, 'u', char_type(),
1002 reinterpret_cast<unsigned long>(__v));
1003 __io.flags(__flags);
1007 __io.flags(__flags);
1008 __throw_exception_again;
1014 template<typename _CharT, typename _InIter>
1016 money_get<_CharT, _InIter>::
1017 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1018 ios_base::iostate& __err, long double& __units) const
1021 this->do_get(__beg, __end, __intl, __io, __err, __str);
1023 const int __n = numeric_limits<long double>::digits10;
1024 char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
1025 const locale __loc = __io.getloc();
1026 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1027 const _CharT* __wcs = __str.c_str();
1028 __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);
1030 #if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
1033 long double __ld = strtold(__cs, &__sanity);
1034 if (!(__err & ios_base::failbit)
1035 && __sanity != __cs && *__sanity == '\0' && errno == 0)
1038 typedef typename char_traits<_CharT>::int_type int_type;
1040 int __p = sscanf(__cs, "%Lf", &__ld);
1041 if (!(__err & ios_base::failbit)
1042 && __p && static_cast<int_type>(__p) != char_traits<_CharT>::eof())
1048 template<typename _CharT, typename _InIter>
1050 money_get<_CharT, _InIter>::
1051 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1052 ios_base::iostate& __err, string_type& __units) const
1054 // These contortions are quite unfortunate.
1055 typedef moneypunct<_CharT, true> __money_true;
1056 typedef moneypunct<_CharT, false> __money_false;
1057 typedef money_base::part part;
1058 typedef typename string_type::size_type size_type;
1060 const locale __loc = __io.getloc();
1061 const __money_true& __mpt = use_facet<__money_true>(__loc);
1062 const __money_false& __mpf = use_facet<__money_false>(__loc);
1063 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1065 const money_base::pattern __p = __intl ? __mpt.neg_format()
1066 : __mpf.neg_format();
1068 const string_type __pos_sign =__intl ? __mpt.positive_sign()
1069 : __mpf.positive_sign();
1070 const string_type __neg_sign =__intl ? __mpt.negative_sign()
1071 : __mpf.negative_sign();
1072 const char_type __d = __intl ? __mpt.decimal_point()
1073 : __mpf.decimal_point();
1074 const char_type __sep = __intl ? __mpt.thousands_sep()
1075 : __mpf.thousands_sep();
1077 const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
1079 // Set to deduced positive or negative sign, depending.
1081 // String of grouping info from thousands_sep plucked from __units.
1082 string __grouping_tmp;
1083 // Marker for thousands_sep position.
1085 // If input iterator is in a valid state.
1086 bool __testvalid = true;
1087 // Flag marking when a decimal point is found.
1088 bool __testdecfound = false;
1090 char_type __c = *__beg;
1091 char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
1092 for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
1094 part __which = static_cast<part>(__p.field[__i]);
1097 case money_base::symbol:
1098 if (__io.flags() & ios_base::showbase)
1100 // Symbol is required.
1101 const string_type __symbol = __intl ? __mpt.curr_symbol()
1102 : __mpf.curr_symbol();
1103 size_type __len = __symbol.size();
1105 while (__beg != __end
1106 && __i < __len && __symbol[__i] == __c)
1112 __testvalid = false;
1115 case money_base::sign:
1116 // Sign might not exist, or be more than one character long.
1117 if (__pos_sign.size() && __neg_sign.size())
1119 // Sign is mandatory.
1120 if (__c == __pos_sign[0])
1122 __sign = __pos_sign;
1125 else if (__c == __neg_sign[0])
1127 __sign = __neg_sign;
1131 __testvalid = false;
1133 else if (__pos_sign.size() && __c == __pos_sign[0])
1135 __sign = __pos_sign;
1138 else if (__neg_sign.size() && __c == __neg_sign[0])
1140 __sign = __neg_sign;
1144 case money_base::value:
1145 // Extract digits, remove and stash away the
1146 // grouping of found thousands separators.
1147 while (__beg != __end
1148 && (__ctype.is(ctype_base::digit, __c)
1149 || (__c == __d && !__testdecfound)
1154 __grouping_tmp += static_cast<char>(__sep_pos);
1156 __testdecfound = true;
1158 else if (__c == __sep)
1160 if (__grouping.size())
1162 // Mark position for later analysis.
1163 __grouping_tmp += static_cast<char>(__sep_pos);
1168 __testvalid = false;
1180 case money_base::space:
1181 case money_base::none:
1182 // Only if not at the end of the pattern.
1184 while (__beg != __end
1185 && __ctype.is(ctype_base::space, __c))
1191 // Need to get the rest of the sign characters, if they exist.
1192 if (__sign.size() > 1)
1194 size_type __len = __sign.size();
1196 for (; __c != __eof && __i < __len; ++__i)
1197 while (__beg != __end && __c != __sign[__i])
1201 __testvalid = false;
1204 // Strip leading zeros.
1205 while (__units[0] == __ctype.widen('0'))
1206 __units.erase(__units.begin());
1208 if (__sign == __neg_sign)
1209 __units.insert(__units.begin(), __ctype.widen('-'));
1211 // Test for grouping fidelity.
1212 if (__grouping.size() && __grouping_tmp.size())
1214 if (!__verify_grouping(__grouping, __grouping_tmp))
1215 __testvalid = false;
1218 // Iff no more characters are available.
1220 __err |= ios_base::eofbit;
1222 // Iff valid sequence is not recognized.
1223 if (!__testvalid || !__units.size())
1224 __err |= ios_base::failbit;
1228 template<typename _CharT, typename _OutIter>
1230 money_put<_CharT, _OutIter>::
1231 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1232 long double __units) const
1234 const locale __loc = __io.getloc();
1235 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1236 const int __n = numeric_limits<long double>::digits10;
1237 char* __cs = static_cast<char*>(__builtin_alloca(sizeof(char) * __n));
1238 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
1239 int __len = sprintf(__cs, "%.01Lf", __units);
1240 __ctype.widen(__cs, __cs + __len, __ws);
1241 string_type __digits(__ws);
1242 return this->do_put(__s, __intl, __io, __fill, __digits);
1245 template<typename _CharT, typename _OutIter>
1247 money_put<_CharT, _OutIter>::
1248 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1249 const string_type& __digits) const
1251 typedef typename string_type::size_type size_type;
1252 typedef money_base::part part;
1254 const locale __loc = __io.getloc();
1255 const size_type __width = static_cast<size_type>(__io.width());
1257 // These contortions are quite unfortunate.
1258 typedef moneypunct<_CharT, true> __money_true;
1259 typedef moneypunct<_CharT, false> __money_false;
1260 const __money_true& __mpt = use_facet<__money_true>(__loc);
1261 const __money_false& __mpf = use_facet<__money_false>(__loc);
1262 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1264 // Determine if negative or positive formats are to be used, and
1265 // discard leading negative_sign if it is present.
1266 const char_type* __beg = __digits.data();
1267 const char_type* __end = __beg + __digits.size();
1268 money_base::pattern __p;
1270 if (*__beg != __ctype.widen('-'))
1272 __p = __intl ? __mpt.pos_format() : __mpf.pos_format();
1273 __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
1277 __p = __intl ? __mpt.neg_format() : __mpf.neg_format();
1278 __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
1282 // Look for valid numbers in the current ctype facet within input digits.
1283 __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
1286 // Assume valid input, and attempt to format.
1287 // Break down input numbers into base components, as follows:
1288 // final_value = grouped units + (decimal point) + (digits)
1290 string_type __value;
1291 const string_type __symbol = __intl ? __mpt.curr_symbol()
1292 : __mpf.curr_symbol();
1294 // Deal with decimal point, decimal digits.
1295 const int __frac = __intl ? __mpt.frac_digits()
1296 : __mpf.frac_digits();
1299 const char_type __d = __intl ? __mpt.decimal_point()
1300 : __mpf.decimal_point();
1301 if (__end - __beg >= __frac)
1303 __value = string_type(__end - __frac, __end);
1304 __value.insert(__value.begin(), __d);
1309 // Have to pad zeros in the decimal position.
1310 __value = string_type(__beg, __end);
1311 int __paddec = __frac - (__end - __beg);
1312 char_type __zero = __ctype.widen('0');
1313 __value.insert(__value.begin(), __paddec, __zero);
1314 __value.insert(__value.begin(), __d);
1319 // Add thousands separators to non-decimal digits, per
1323 const string __grouping = __intl ? __mpt.grouping()
1325 if (__grouping.size())
1327 const char_type __sep = __intl ? __mpt.thousands_sep()
1328 : __mpf.thousands_sep();
1329 const char* __gbeg = __grouping.c_str();
1330 const char* __gend = __gbeg + __grouping.size();
1331 const int __n = numeric_limits<long double>::digits10 * 2;
1332 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
1333 _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg,
1334 __gend, __beg, __end);
1335 __value.insert(0, __ws2, __ws_end - __ws2);
1338 __value.insert(0, string_type(__beg, __end));
1341 // Calculate length of resulting string.
1342 ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
1343 size_type __len = __value.size() + __sign.size();
1344 __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
1345 bool __testipad = __f == ios_base::internal && __len < __width;
1347 // Fit formatted digits into the required pattern.
1348 for (int __i = 0; __i < 4; ++__i)
1350 part __which = static_cast<part>(__p.field[__i]);
1353 case money_base::symbol:
1354 if (__io.flags() & ios_base::showbase)
1357 case money_base::sign:
1358 // Sign might not exist, or be more than one
1359 // charater long. In that case, add in the rest
1364 case money_base::value:
1367 case money_base::space:
1368 // At least one space is required, but if internal
1369 // formatting is required, an arbitrary number of
1370 // fill spaces will be necessary.
1372 __res += string_type(__width - __len, __fill);
1374 __res += __ctype.widen(' ');
1376 case money_base::none:
1378 __res += string_type(__width - __len, __fill);
1383 // Special case of multi-part sign parts.
1384 if (__sign.size() > 1)
1385 __res += string_type(__sign.begin() + 1, __sign.end());
1387 // Pad, if still necessary.
1388 __len = __res.size();
1389 if (__width > __len)
1391 if (__f == ios_base::left)
1393 __res.append(__width - __len, __fill);
1396 __res.insert(0, string_type(__width - __len, __fill));
1400 // Write resulting, fully-formatted string to output iterator.
1401 for (size_type __j = 0; __j < __len; ++__j)
1409 // NB: Not especially useful. Without an ios_base object or some
1410 // kind of locale reference, we are left clawing at the air where
1411 // the side of the mountain used to be...
1412 template<typename _CharT, typename _InIter>
1413 time_base::dateorder
1414 time_get<_CharT, _InIter>::do_date_order() const
1415 { return time_base::no_order; }
1417 template<typename _CharT, typename _InIter>
1419 time_get<_CharT, _InIter>::
1420 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
1421 ios_base::iostate& __err, tm* __tm,
1422 const _CharT* __format) const
1424 locale __loc = __io.getloc();
1425 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1426 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1427 size_t __len = char_traits<_CharT>::length(__format);
1429 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
1431 char __c = __format[__i];
1434 // Verify valid formatting code, attempt to extract.
1435 __c = __format[++__i];
1438 if (__c == 'E' || __c == 'O')
1441 __c = __format[++__i];
1448 // Abbreviated weekday name [tm_wday]
1449 const char_type* __days1[7];
1450 __tp._M_days_abbreviated(__days1);
1451 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7,
1455 // Weekday name [tm_wday].
1456 const char_type* __days2[7];
1457 __tp._M_days(__days2);
1458 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7,
1463 // Abbreviated month name [tm_mon]
1464 const char_type* __months1[12];
1465 __tp._M_months_abbreviated(__months1);
1466 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12,
1470 // Month name [tm_mon].
1471 const char_type* __months2[12];
1472 __tp._M_months(__months2);
1473 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12,
1477 // Default time and date representation.
1478 const char_type* __dt[2];
1479 __tp._M_date_time_formats(__dt);
1480 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1484 // Day [01, 31]. [tm_mday]
1485 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
1489 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
1491 __ctype.widen(__cs, __cs + 9, __wcs);
1492 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1496 // Hour [00, 23]. [tm_hour]
1497 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1501 // Hour [01, 12]. [tm_hour]
1502 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
1506 // Month [01, 12]. [tm_mon]
1507 _M_extract_num(__beg, __end, __mem, 1, 12, 2,
1510 __tm->tm_mon = __mem - 1;
1513 // Minute [00, 59]. [tm_min]
1514 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1518 if (__ctype.narrow(*__beg, 0) == '\n')
1521 __err |= ios_base::failbit;
1524 // Equivalent to (%H:%M).
1526 __ctype.widen(__cs, __cs + 6, __wcs);
1527 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1532 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
1536 if (__ctype.narrow(*__beg, 0) == '\t')
1539 __err |= ios_base::failbit;
1542 // Equivalent to (%H:%M:%S).
1544 __ctype.widen(__cs, __cs + 9, __wcs);
1545 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1550 const char_type* __dates[2];
1551 __tp._M_date_formats(__dates);
1552 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1557 const char_type* __times[2];
1558 __tp._M_time_formats(__times);
1559 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1563 // Two digit year. [tm_year]
1564 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
1568 // Year [1900). [tm_year]
1569 _M_extract_num(__beg, __end, __mem, 0,
1570 numeric_limits<int>::max(), 4,
1573 __tm->tm_year = __mem - 1900;
1577 if (__ctype.is(ctype_base::upper, *__beg))
1580 _M_extract_name(__beg, __end, __tmp,
1581 __timepunct<_CharT>::_S_timezones,
1584 // GMT requires special effort.
1585 char_type __c = *__beg;
1586 if (!__err && __tmp == 0
1587 && (__c == __ctype.widen('-')
1588 || __c == __ctype.widen('+')))
1590 _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1592 _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1597 __err |= ios_base::failbit;
1601 __err |= ios_base::failbit;
1606 // Verify format and input match, extract and discard.
1607 if (__c == __ctype.narrow(*__beg, 0))
1610 __err |= ios_base::failbit;
1615 template<typename _CharT, typename _InIter>
1617 time_get<_CharT, _InIter>::
1618 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
1619 int __min, int __max, size_t __len,
1620 const ctype<_CharT>& __ctype,
1621 ios_base::iostate& __err) const
1625 bool __testvalid = true;
1626 char_type __c = *__beg;
1627 while (__beg != __end && __i < __len
1628 && __ctype.is(ctype_base::digit, __c))
1630 __digits += __ctype.narrow(__c, 0);
1636 int __value = atoi(__digits.c_str());
1637 if (__min <= __value && __value <= __max)
1640 __testvalid = false;
1643 __testvalid = false;
1645 __err |= ios_base::failbit;
1649 // All elements in __names are unique.
1650 template<typename _CharT, typename _InIter>
1652 time_get<_CharT, _InIter>::
1653 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
1654 const _CharT** __names, size_t __indexlen,
1655 ios_base::iostate& __err) const
1657 typedef char_traits<char_type> __traits_type;
1658 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen));
1659 size_t __nmatches = 0;
1661 bool __testvalid = true;
1662 const char_type* __name;
1664 char_type __c = *__beg;
1665 // Look for initial matches.
1666 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1667 if (__c == __names[__i1][0])
1668 __matches[__nmatches++] = __i1;
1670 while(__nmatches > 1)
1672 // Find smallest matching string.
1673 size_t __minlen = 10;
1674 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
1675 __minlen = min(__minlen,
1676 __traits_type::length(__names[__matches[__i2]]));
1678 if (__pos < __minlen && __beg != __end)
1682 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1684 __name = __names[__matches[__i3]];
1685 if (__name[__pos] != __c)
1686 __matches[__i3] = __matches[--__nmatches];
1693 if (__nmatches == 1)
1695 // Make sure found name is completely extracted.
1696 __name = __names[__matches[0]];
1697 const size_t __len = __traits_type::length(__name);
1698 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
1702 __member = __matches[0];
1704 __testvalid = false;
1707 __testvalid = false;
1709 __err |= ios_base::failbit;
1712 template<typename _CharT, typename _InIter>
1714 time_get<_CharT, _InIter>::
1715 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1716 ios_base::iostate& __err, tm* __tm) const
1719 const char* __cs = "%X";
1720 locale __loc = __io.getloc();
1721 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1722 __ctype.widen(__cs, __cs + 3, __wcs);
1723 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1725 __err |= ios_base::eofbit;
1729 template<typename _CharT, typename _InIter>
1731 time_get<_CharT, _InIter>::
1732 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1733 ios_base::iostate& __err, tm* __tm) const
1736 const char* __cs = "%x";
1737 locale __loc = __io.getloc();
1738 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1739 __ctype.widen(__cs, __cs + 3, __wcs);
1740 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1742 __err |= ios_base::eofbit;
1746 template<typename _CharT, typename _InIter>
1748 time_get<_CharT, _InIter>::
1749 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
1750 ios_base::iostate& __err, tm* __tm) const
1752 typedef char_traits<char_type> __traits_type;
1753 locale __loc = __io.getloc();
1754 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1755 const char_type* __days[7];
1756 __tp._M_days_abbreviated(__days);
1758 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err);
1760 // Check to see if non-abbreviated name exists, and extract.
1761 // NB: Assumes both _M_days and _M_days_abbreviated organized in
1762 // exact same order, first to last, such that the resulting
1763 // __days array with the same index points to a day, and that
1764 // day's abbreviated form.
1765 // NB: Also assumes that an abbreviated name is a subset of the name.
1768 size_t __pos = __traits_type::length(__days[__tmpwday]);
1769 __tp._M_days(__days);
1770 const char_type* __name = __days[__tmpwday];
1771 if (__name[__pos] == *__beg)
1773 // Extract the rest of it.
1774 const size_t __len = __traits_type::length(__name);
1775 while (__pos < __len && __beg != __end
1776 && __name[__pos] == *__beg)
1779 __err |= ios_base::failbit;
1782 __tm->tm_wday = __tmpwday;
1785 __err |= ios_base::eofbit;
1789 template<typename _CharT, typename _InIter>
1791 time_get<_CharT, _InIter>::
1792 do_get_monthname(iter_type __beg, iter_type __end,
1793 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
1795 typedef char_traits<char_type> __traits_type;
1796 locale __loc = __io.getloc();
1797 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1798 const char_type* __months[12];
1799 __tp._M_months_abbreviated(__months);
1801 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err);
1803 // Check to see if non-abbreviated name exists, and extract.
1804 // NB: Assumes both _M_months and _M_months_abbreviated organized in
1805 // exact same order, first to last, such that the resulting
1806 // __months array with the same index points to a month, and that
1807 // month's abbreviated form.
1808 // NB: Also assumes that an abbreviated name is a subset of the name.
1811 size_t __pos = __traits_type::length(__months[__tmpmon]);
1812 __tp._M_months(__months);
1813 const char_type* __name = __months[__tmpmon];
1814 if (__name[__pos] == *__beg)
1816 // Extract the rest of it.
1817 const size_t __len = __traits_type::length(__name);
1818 while (__pos < __len && __beg != __end
1819 && __name[__pos] == *__beg)
1822 __err |= ios_base::failbit;
1825 __tm->tm_mon = __tmpmon;
1829 __err |= ios_base::eofbit;
1833 template<typename _CharT, typename _InIter>
1835 time_get<_CharT, _InIter>::
1836 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
1837 ios_base::iostate& __err, tm* __tm) const
1839 locale __loc = __io.getloc();
1840 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1842 char_type __c = *__beg;
1845 while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c))
1847 __digits += __ctype.narrow(__c, 0);
1851 if (__i == 2 || __i == 4)
1853 int __year = atoi(__digits.c_str());
1854 __year = __i == 2 ? __year : __year - 1900;
1855 __tm->tm_year = __year;
1858 __err |= ios_base::failbit;
1860 __err |= ios_base::eofbit;
1864 template<typename _CharT, typename _OutIter>
1866 time_put<_CharT, _OutIter>::
1867 put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1868 const _CharT* __beg, const _CharT* __end) const
1870 locale __loc = __io.getloc();
1871 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1872 while (__beg != __end)
1874 char __c = __ctype.narrow(*__beg, 0);
1881 __c = __ctype.narrow(*__beg, 0);
1883 if (__c == 'E' || __c == 'O')
1886 __format = __ctype.narrow(*__beg, 0);
1891 this->do_put(__s, __io, char_type(), __tm, __format, __mod);
1899 template<typename _CharT, typename _OutIter>
1901 time_put<_CharT, _OutIter>::
1902 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
1903 char __format, char __mod) const
1905 locale __loc = __io.getloc();
1906 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1907 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
1909 // NB: This size is arbitrary. Should this be a data member,
1910 // initialized at construction?
1911 const size_t __maxlen = 64;
1912 char_type* __res = static_cast<char_type*>(__builtin_alloca(__maxlen));
1914 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
1915 // is possible that the format character will be longer than one
1916 // character. Possibilities include 'E' or 'O' followed by a
1917 // format character: if __mod is not the default argument, assume
1918 // it's a valid modifier.
1920 __fmt[0] = __ctype.widen('%');
1923 __fmt[1] = __format;
1924 __fmt[2] = char_type();
1929 __fmt[2] = __format;
1930 __fmt[3] = char_type();
1933 __tp._M_put_helper(__res, __maxlen, __fmt, __tm);
1935 // Write resulting, fully-formatted string to output iterator.
1936 size_t __len = char_traits<char_type>::length(__res);
1937 for (size_t __i = 0; __i < __len; ++__i)
1943 // Generic version does nothing.
1944 template<typename _CharT>
1946 collate<_CharT>::_M_compare_helper(const _CharT*, const _CharT*) const
1949 // Generic version does nothing.
1950 template<typename _CharT>
1952 collate<_CharT>::_M_transform_helper(_CharT*, const _CharT*, size_t) const
1955 template<typename _CharT>
1958 do_compare(const _CharT* __lo1, const _CharT* __hi1,
1959 const _CharT* __lo2, const _CharT* __hi2) const
1961 const string_type __one(__lo1, __hi1);
1962 const string_type __two(__lo2, __hi2);
1963 return _M_compare_helper(__one.c_str(), __two.c_str());
1966 template<typename _CharT>
1967 collate<_CharT>::string_type
1969 do_transform(const _CharT* __lo, const _CharT* __hi) const
1971 size_t __len = __hi - __lo;
1972 _CharT* __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
1973 size_t __res = _M_transform_helper(__c, __lo, __len);
1976 // Try to increment size of translated string.
1977 size_t __len2 = __len * 2;
1978 _CharT* __c2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len2));
1979 __res = _M_transform_helper(__c2, __lo, __len);
1980 // XXX Throw exception if still indeterminate?
1982 return string_type(__c);
1985 template<typename _CharT>
1988 do_hash(const _CharT* __lo, const _CharT* __hi) const
1990 unsigned long __val = 0;
1991 for (; __lo < __hi; ++__lo)
1992 __val = *__lo + ((__val << 7) |
1993 (__val >> (numeric_limits<unsigned long>::digits - 1)));
1994 return static_cast<long>(__val);
1997 // Construct correctly padded string, as per 22.2.2.2.2
1999 // __newlen > __oldlen
2000 // __news is allocated for __newlen size
2001 // Used by both num_put and ostream inserters: if __num,
2002 // internal-adjusted objects are padded according to the rules below
2003 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
2005 template<typename _CharT, typename _Traits>
2007 __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds,
2008 const streamsize __newlen, const streamsize __oldlen,
2011 typedef _CharT char_type;
2012 typedef _Traits traits_type;
2013 typedef typename traits_type::int_type int_type;
2015 int_type __plen = static_cast<size_t>(__newlen - __oldlen);
2016 char_type* __pads = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen));
2017 traits_type::assign(__pads, __plen, __fill);
2022 size_t __beglen; //either __plen or __oldlen
2023 ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
2025 if (__adjust == ios_base::left)
2028 __beg = const_cast<char_type*>(__olds);
2029 __beglen = __oldlen;
2032 else if (__adjust == ios_base::internal && __num)
2034 // Pad after the sign, if there is one.
2035 // Pad after 0[xX], if there is one.
2036 // Who came up with these rules, anyway? Jeeze.
2037 locale __loc = __io.getloc();
2038 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2039 const char_type __minus = __ctype.widen('-');
2040 const char_type __plus = __ctype.widen('+');
2041 bool __testsign = __olds[0] == __minus || __olds[0] == __plus;
2042 bool __testhex = __ctype.widen('0') == __olds[0]
2043 && (__ctype.widen('x') == __olds[1]
2044 || __ctype.widen('X') == __olds[1]);
2047 __news[0] = __olds[0];
2048 __news[1] = __olds[1];
2053 __end = const_cast<char_type*>(__olds + __mod);
2055 else if (__testsign)
2057 __news[0] = __olds[0] == __plus ? __plus : __minus;
2062 __end = const_cast<char_type*>(__olds + __mod);
2069 __end = const_cast<char_type*>(__olds);
2077 __end = const_cast<char_type*>(__olds);
2079 traits_type::copy(__news, __beg, __beglen);
2080 traits_type::copy(__news + __beglen, __end, __newlen - __beglen - __mod);
2083 // NB: Can't have default argument on non-member template, and
2084 // num_put doesn't have a _Traits template parameter, so this
2085 // forwarding template adds in the default template argument.
2086 template<typename _CharT>
2088 __pad(ios_base& __io, _CharT __fill, _CharT* __news, const _CharT* __olds,
2089 const streamsize __newlen, const streamsize __oldlen,
2092 return __pad<_CharT, char_traits<_CharT> >(__io, __fill, __news, __olds,
2093 __newlen, __oldlen, __num);
2096 // Used by both numeric and monetary facets.
2097 // Check to make sure that the __grouping_tmp string constructed in
2098 // money_get or num_get matches the canonical grouping for a given
2100 // __grouping_tmp is parsed L to R
2101 // 1,222,444 == __grouping_tmp of "/1/3/3"
2102 // __grouping is parsed R to L
2103 // 1,222,444 == __grouping of "/3" == "/3/3/3"
2104 template<typename _CharT>
2106 __verify_grouping(const basic_string<_CharT>& __grouping,
2107 basic_string<_CharT>& __grouping_tmp)
2111 const int __len = __grouping.size();
2112 const int __n = __grouping_tmp.size();
2115 // Parsed number groupings have to match the
2116 // numpunct::grouping string exactly, starting at the
2117 // right-most point of the parsed sequence of elements ...
2118 while (__test && __i < __n - 1)
2119 for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
2120 __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1];
2121 // ... but the last parsed grouping can be <= numpunct
2123 __j == __len ? __j = 0 : __j;
2124 __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1];
2128 // Used by both numeric and monetary facets.
2129 // Inserts "group separator" characters into an array of characters.
2130 // It's recursive, one iteration per group. It moves the characters
2131 // in the buffer this way: "xxxx12345" -> "12,345xxx". Call this
2132 // only with __gbeg != __gend.
2133 template<typename _CharT>
2135 __add_grouping(_CharT* __s, _CharT __sep,
2136 const char* __gbeg, const char* __gend,
2137 const _CharT* __first, const _CharT* __last)
2139 if (__last - __first > *__gbeg)
2141 __s = __add_grouping(__s, __sep,
2142 (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
2143 __gend, __first, __last - *__gbeg);
2144 __first = __last - *__gbeg;
2148 *__s++ = *__first++;
2149 while (__first != __last);