1 // Locale support -*- C++ -*-
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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 _LOCALE_FACETS_TCC
34 #define _LOCALE_FACETS_TCC 1
36 #pragma GCC system_header
38 #include <limits> // For numeric_limits
39 #include <typeinfo> // For bad_cast.
40 #include <bits/streambuf_iterator.h>
44 template<typename _Facet>
46 locale::combine(const locale& __other) const
48 _Impl* __tmp = new _Impl(*_M_impl, 1);
51 __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
55 __tmp->_M_remove_reference();
56 __throw_exception_again;
61 template<typename _CharT, typename _Traits, typename _Alloc>
63 locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
64 const basic_string<_CharT, _Traits, _Alloc>& __s2) const
66 typedef std::collate<_CharT> __collate_type;
67 const __collate_type& __collate = use_facet<__collate_type>(*this);
68 return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
69 __s2.data(), __s2.data() + __s2.length()) < 0);
73 * @brief Test for the presence of a facet.
75 * has_facet tests the locale argument for the presence of the facet type
76 * provided as the template parameter. Facets derived from the facet
77 * parameter will also return true.
79 * @param Facet The facet type to test the presence of.
80 * @param locale The locale to test.
81 * @return true if locale contains a facet of type Facet, else false.
82 * @throw std::bad_cast if locale doesn't contain the facet.
84 template<typename _Facet>
86 has_facet(const locale& __loc) throw()
88 const size_t __i = _Facet::id._M_id();
89 const locale::facet** __facets = __loc._M_impl->_M_facets;
90 return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
94 * @brief Return a facet.
96 * use_facet looks for and returns a reference to a facet of type Facet
97 * where Facet is the template parameter. If has_facet(locale) is true,
98 * there is a suitable facet to return. It throws std::bad_cast if the
99 * locale doesn't contain a facet of type Facet.
101 * @param Facet The facet type to access.
102 * @param locale The locale to use.
103 * @return Reference to facet of type Facet.
104 * @throw std::bad_cast if locale doesn't contain a facet of type Facet.
106 template<typename _Facet>
108 use_facet(const locale& __loc)
110 const size_t __i = _Facet::id._M_id();
111 const locale::facet** __facets = __loc._M_impl->_M_facets;
112 if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
114 return static_cast<const _Facet&>(*__facets[__i]);
117 // Routine to access a cache for the facet. If the cache didn't
118 // exist before, it gets constructed on the fly.
119 template<typename _Facet>
123 operator() (const locale& __loc) const;
126 template<typename _CharT>
127 struct __use_cache<__numpunct_cache<_CharT> >
129 const __numpunct_cache<_CharT>*
130 operator() (const locale& __loc) const
132 const size_t __i = numpunct<_CharT>::id._M_id();
133 const locale::facet** __caches = __loc._M_impl->_M_caches;
136 __numpunct_cache<_CharT>* __tmp = NULL;
139 __tmp = new __numpunct_cache<_CharT>;
140 __tmp->_M_cache(__loc);
145 __throw_exception_again;
147 __loc._M_impl->_M_install_cache(__tmp, __i);
149 return static_cast<const __numpunct_cache<_CharT>*>(__caches[__i]);
153 // Used by both numeric and monetary facets.
154 // Check to make sure that the __grouping_tmp string constructed in
155 // money_get or num_get matches the canonical grouping for a given
157 // __grouping_tmp is parsed L to R
158 // 1,222,444 == __grouping_tmp of "\1\3\3"
159 // __grouping is parsed R to L
160 // 1,222,444 == __grouping of "\3" == "\3\3\3"
162 __verify_grouping(const char* __grouping, size_t __grouping_size,
163 const string& __grouping_tmp);
165 template<typename _CharT, typename _InIter>
167 num_get<_CharT, _InIter>::
168 _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
169 ios_base::iostate& __err, string& __xtrc) const
171 typedef char_traits<_CharT> __traits_type;
172 typedef typename numpunct<_CharT>::__cache_type __cache_type;
173 __use_cache<__cache_type> __uc;
174 const locale& __loc = __io._M_getloc();
175 const __cache_type* __lc = __uc(__loc);
176 const _CharT* __lit = __lc->_M_atoms_in;
178 // True if a mantissa is found.
179 bool __found_mantissa = false;
181 // First check for sign.
184 const char_type __c = *__beg;
185 const bool __plus = __traits_type::eq(__c, __lit[_S_iplus]);
186 if ((__plus || __traits_type::eq(__c, __lit[_S_iminus]))
187 && !__traits_type::eq(__c, __lc->_M_decimal_point)
188 && (!__lc->_M_use_grouping
189 || !__traits_type::eq(__c, __lc->_M_thousands_sep)))
191 __xtrc += __plus ? _S_atoms_in[_S_iplus]
192 : _S_atoms_in[_S_iminus];
197 // Next, look for leading zeros.
198 while (__beg != __end)
200 const char_type __c = *__beg;
201 if (__traits_type::eq(__c, __lc->_M_decimal_point)
202 || (__lc->_M_use_grouping
203 && __traits_type::eq(__c, __lc->_M_thousands_sep)))
205 else if (__traits_type::eq(__c, __lit[_S_izero]))
207 if (!__found_mantissa)
209 __xtrc += _S_atoms_in[_S_izero];
210 __found_mantissa = true;
218 // Only need acceptable digits for floating point numbers.
219 bool __found_dec = false;
220 bool __found_sci = false;
221 string __found_grouping;
222 if (__lc->_M_use_grouping)
223 __found_grouping.reserve(32);
226 const char_type* __q;
227 while (__beg != __end)
229 // According to 22.2.2.1.2, p8-9, first look for thousands_sep
230 // and decimal_point.
231 const char_type __c = *__beg;
232 if (__lc->_M_use_grouping
233 && __traits_type::eq(__c, __lc->_M_thousands_sep))
235 if (!__found_dec && !__found_sci)
237 // NB: Thousands separator at the beginning of a string
238 // is a no-no, as is two consecutive thousands separators.
241 __found_grouping += static_cast<char>(__sep_pos);
247 __err |= ios_base::failbit;
254 else if (__traits_type::eq(__c, __lc->_M_decimal_point))
256 if (!__found_dec && !__found_sci)
258 // If no grouping chars are seen, no grouping check
259 // is applied. Therefore __found_grouping is adjusted
260 // only if decimal_point comes after some thousands_sep.
261 if (__found_grouping.size())
262 __found_grouping += static_cast<char>(__sep_pos);
270 else if (__q = __traits_type::find(__lit + _S_izero, 10, __c))
272 __xtrc += _S_atoms_in[__q - __lit];
273 __found_mantissa = true;
277 else if ((__e = __traits_type::eq(__c, __lit[_S_ie])
278 || __traits_type::eq(__c, __lit[_S_iE]))
279 && __found_mantissa && !__found_sci)
281 // Scientific notation.
282 __xtrc += __e ? _S_atoms_in[_S_ie] : _S_atoms_in[_S_iE];
285 // Remove optional plus or minus sign, if they exist.
286 if (++__beg != __end)
288 const bool __plus = __traits_type::eq(*__beg,
290 if (__plus || __traits_type::eq(*__beg, __lit[_S_iminus]))
292 __xtrc += __plus ? _S_atoms_in[_S_iplus]
293 : _S_atoms_in[_S_iminus];
299 // Not a valid input item.
303 // Digit grouping is checked. If grouping and found_grouping don't
304 // match, then get very very upset, and set failbit.
305 if (__found_grouping.size())
307 // Add the ending grouping if a decimal wasn't found.
309 __found_grouping += static_cast<char>(__sep_pos);
311 if (!std::__verify_grouping(__lc->_M_grouping, __lc->_M_grouping_size,
313 __err |= ios_base::failbit;
318 __err |= ios_base::eofbit;
322 template<typename _CharT, typename _InIter>
323 template<typename _ValueT>
325 num_get<_CharT, _InIter>::
326 _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
327 ios_base::iostate& __err, _ValueT& __v) const
329 typedef char_traits<_CharT> __traits_type;
330 typedef typename numpunct<_CharT>::__cache_type __cache_type;
331 __use_cache<__cache_type> __uc;
332 const locale& __loc = __io._M_getloc();
333 const __cache_type* __lc = __uc(__loc);
334 const _CharT* __lit = __lc->_M_atoms_in;
336 // NB: Iff __basefield == 0, __base can change based on contents.
337 const ios_base::fmtflags __basefield = __io.flags()
338 & ios_base::basefield;
339 const bool __oct = __basefield == ios_base::oct;
340 int __base = __oct ? 8 : (__basefield == ios_base::hex ? 16 : 10);
342 // True if numeric digits are found.
343 bool __found_num = false;
345 // First check for sign.
346 bool __negative = false;
349 const char_type __c = *__beg;
350 if (numeric_limits<_ValueT>::is_signed)
351 __negative = __traits_type::eq(__c, __lit[_S_iminus]);
352 if ((__negative || __traits_type::eq(__c, __lit[_S_iplus]))
353 && !__traits_type::eq(__c, __lc->_M_decimal_point)
354 && (!__lc->_M_use_grouping
355 || !__traits_type::eq(__c, __lc->_M_thousands_sep)))
359 // Next, look for leading zeros and check required digits
361 while (__beg != __end)
363 const char_type __c = *__beg;
364 if (__traits_type::eq(__c, __lc->_M_decimal_point)
365 || (__lc->_M_use_grouping
366 && __traits_type::eq(__c, __lc->_M_thousands_sep)))
368 else if (__traits_type::eq(__c, __lit[_S_izero])
369 && (!__found_num || __base == 10))
374 else if (__found_num)
376 if (__traits_type::eq(__c, __lit[_S_ix])
377 || __traits_type::eq(__c, __lit[_S_iX]))
379 if (__basefield == 0)
387 else if (__basefield == 0)
395 // At this point, base is determined. If not hex, only allow
396 // base digits as valid input.
397 const size_t __len = __base == 16 ? _S_iend - _S_izero : __base;
400 string __found_grouping;
401 if (__lc->_M_use_grouping)
402 __found_grouping.reserve(32);
404 bool __overflow = false;
405 _ValueT __result = 0;
406 const char_type* __lit_zero = __lit + _S_izero;
407 const char_type* __q;
410 const _ValueT __min = numeric_limits<_ValueT>::min() / __base;
411 for (; __beg != __end; ++__beg)
413 // According to 22.2.2.1.2, p8-9, first look for thousands_sep
414 // and decimal_point.
415 const char_type __c = *__beg;
416 if (__lc->_M_use_grouping
417 && __traits_type::eq(__c, __lc->_M_thousands_sep))
419 // NB: Thousands separator at the beginning of a string
420 // is a no-no, as is two consecutive thousands separators.
423 __found_grouping += static_cast<char>(__sep_pos);
428 __err |= ios_base::failbit;
432 else if (__traits_type::eq(__c, __lc->_M_decimal_point))
434 else if (__q = __traits_type::find(__lit_zero, __len, __c))
436 int __digit = __q - __lit_zero;
439 if (__result < __min)
443 const _ValueT __new_result = __result * __base
445 __overflow |= __new_result > __result;
446 __result = __new_result;
452 // Not a valid input item.
458 const _ValueT __max = numeric_limits<_ValueT>::max() / __base;
459 for (; __beg != __end; ++__beg)
461 const char_type __c = *__beg;
462 if (__lc->_M_use_grouping
463 && __traits_type::eq(__c, __lc->_M_thousands_sep))
467 __found_grouping += static_cast<char>(__sep_pos);
472 __err |= ios_base::failbit;
476 else if (__traits_type::eq(__c, __lc->_M_decimal_point))
478 else if (__q = __traits_type::find(__lit_zero, __len, __c))
480 int __digit = __q - __lit_zero;
483 if (__result > __max)
487 const _ValueT __new_result = __result * __base
489 __overflow |= __new_result < __result;
490 __result = __new_result;
500 // Digit grouping is checked. If grouping and found_grouping don't
501 // match, then get very very upset, and set failbit.
502 if (__found_grouping.size())
504 // Add the ending grouping.
505 __found_grouping += static_cast<char>(__sep_pos);
507 if (!std::__verify_grouping(__lc->_M_grouping,
508 __lc->_M_grouping_size,
510 __err |= ios_base::failbit;
513 if (!(__err & ios_base::failbit) && !__overflow
517 __err |= ios_base::failbit;
520 __err |= ios_base::eofbit;
524 // _GLIBCXX_RESOLVE_LIB_DEFECTS
525 // 17. Bad bool parsing
526 template<typename _CharT, typename _InIter>
528 num_get<_CharT, _InIter>::
529 do_get(iter_type __beg, iter_type __end, ios_base& __io,
530 ios_base::iostate& __err, bool& __v) const
532 if (!(__io.flags() & ios_base::boolalpha))
534 // Parse bool values as long.
535 // NB: We can't just call do_get(long) here, as it might
536 // refer to a derived class.
538 __beg = _M_extract_int(__beg, __end, __io, __err, __l);
539 if (__l == 0 || __l == 1)
542 __err |= ios_base::failbit;
546 // Parse bool values as alphanumeric.
547 typedef char_traits<_CharT> __traits_type;
548 typedef typename numpunct<_CharT>::__cache_type __cache_type;
549 __use_cache<__cache_type> __uc;
550 const locale& __loc = __io._M_getloc();
551 const __cache_type* __lc = __uc(__loc);
556 for (__n = 0; __beg != __end; ++__n, ++__beg)
559 if (__n < __lc->_M_falsename_size)
560 __testf = __traits_type::eq(*__beg, __lc->_M_falsename[__n]);
565 if (__n < __lc->_M_truename_size)
566 __testt = __traits_type::eq(*__beg, __lc->_M_truename[__n]);
570 if (!__testf && !__testt)
573 if (__testf && __n == __lc->_M_falsename_size)
575 else if (__testt && __n == __lc->_M_truename_size)
578 __err |= ios_base::failbit;
581 __err |= ios_base::eofbit;
586 template<typename _CharT, typename _InIter>
588 num_get<_CharT, _InIter>::
589 do_get(iter_type __beg, iter_type __end, ios_base& __io,
590 ios_base::iostate& __err, long& __v) const
591 { return _M_extract_int(__beg, __end, __io, __err, __v); }
593 template<typename _CharT, typename _InIter>
595 num_get<_CharT, _InIter>::
596 do_get(iter_type __beg, iter_type __end, ios_base& __io,
597 ios_base::iostate& __err, unsigned short& __v) const
598 { return _M_extract_int(__beg, __end, __io, __err, __v); }
600 template<typename _CharT, typename _InIter>
602 num_get<_CharT, _InIter>::
603 do_get(iter_type __beg, iter_type __end, ios_base& __io,
604 ios_base::iostate& __err, unsigned int& __v) const
605 { return _M_extract_int(__beg, __end, __io, __err, __v); }
607 template<typename _CharT, typename _InIter>
609 num_get<_CharT, _InIter>::
610 do_get(iter_type __beg, iter_type __end, ios_base& __io,
611 ios_base::iostate& __err, unsigned long& __v) const
612 { return _M_extract_int(__beg, __end, __io, __err, __v); }
614 #ifdef _GLIBCXX_USE_LONG_LONG
615 template<typename _CharT, typename _InIter>
617 num_get<_CharT, _InIter>::
618 do_get(iter_type __beg, iter_type __end, ios_base& __io,
619 ios_base::iostate& __err, long long& __v) const
620 { return _M_extract_int(__beg, __end, __io, __err, __v); }
622 template<typename _CharT, typename _InIter>
624 num_get<_CharT, _InIter>::
625 do_get(iter_type __beg, iter_type __end, ios_base& __io,
626 ios_base::iostate& __err, unsigned long long& __v) const
627 { return _M_extract_int(__beg, __end, __io, __err, __v); }
630 template<typename _CharT, typename _InIter>
632 num_get<_CharT, _InIter>::
633 do_get(iter_type __beg, iter_type __end, ios_base& __io,
634 ios_base::iostate& __err, float& __v) const
638 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
639 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
643 template<typename _CharT, typename _InIter>
645 num_get<_CharT, _InIter>::
646 do_get(iter_type __beg, iter_type __end, ios_base& __io,
647 ios_base::iostate& __err, double& __v) const
651 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
652 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
656 template<typename _CharT, typename _InIter>
658 num_get<_CharT, _InIter>::
659 do_get(iter_type __beg, iter_type __end, ios_base& __io,
660 ios_base::iostate& __err, long double& __v) const
664 __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
665 std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale());
669 template<typename _CharT, typename _InIter>
671 num_get<_CharT, _InIter>::
672 do_get(iter_type __beg, iter_type __end, ios_base& __io,
673 ios_base::iostate& __err, void*& __v) const
675 // Prepare for hex formatted input.
676 typedef ios_base::fmtflags fmtflags;
677 const fmtflags __fmt = __io.flags();
678 __io.flags(__fmt & ~ios_base::basefield | ios_base::hex);
681 __beg = _M_extract_int(__beg, __end, __io, __err, __ul);
683 // Reset from hex formatted input.
686 if (!(__err & ios_base::failbit))
687 __v = reinterpret_cast<void*>(__ul);
689 __err |= ios_base::failbit;
693 // For use by integer and floating-point types after they have been
694 // converted into a char_type string.
695 template<typename _CharT, typename _OutIter>
697 num_put<_CharT, _OutIter>::
698 _M_pad(_CharT __fill, streamsize __w, ios_base& __io,
699 _CharT* __new, const _CharT* __cs, int& __len) const
701 // [22.2.2.2.2] Stage 3.
702 // If necessary, pad.
703 __pad<_CharT, char_traits<_CharT> >::_S_pad(__io, __fill, __new, __cs,
705 __len = static_cast<int>(__w);
708 // Forwarding functions to peel signed from unsigned integer types.
709 template<typename _CharT>
711 __int_to_char(_CharT* __bufend, long __v, const _CharT* __lit,
712 ios_base::fmtflags __flags)
714 unsigned long __ul = static_cast<unsigned long>(__v);
721 return __int_to_char(__bufend, __ul, __lit, __flags, __neg);
724 template<typename _CharT>
726 __int_to_char(_CharT* __bufend, unsigned long __v, const _CharT* __lit,
727 ios_base::fmtflags __flags)
728 { return __int_to_char(__bufend, __v, __lit, __flags, false); }
730 #ifdef _GLIBCXX_USE_LONG_LONG
731 template<typename _CharT>
733 __int_to_char(_CharT* __bufend, long long __v, const _CharT* __lit,
734 ios_base::fmtflags __flags)
736 unsigned long long __ull = static_cast<unsigned long long>(__v);
743 return __int_to_char(__bufend, __ull, __lit, __flags, __neg);
746 template<typename _CharT>
748 __int_to_char(_CharT* __bufend, unsigned long long __v, const _CharT* __lit,
749 ios_base::fmtflags __flags)
750 { return __int_to_char(__bufend, __v, __lit, __flags, false); }
753 template<typename _CharT, typename _ValueT>
755 __int_to_char(_CharT* __bufend, _ValueT __v, const _CharT* __lit,
756 ios_base::fmtflags __flags, bool __neg)
758 // Don't write base if already 0.
759 const bool __showbase = (__flags & ios_base::showbase) && __v;
760 const ios_base::fmtflags __basefield = __flags & ios_base::basefield;
761 _CharT* __buf = __bufend - 1;
763 if (__builtin_expect(__basefield != ios_base::oct &&
764 __basefield != ios_base::hex, true))
769 *__buf-- = __lit[(__v % 10) + __num_base::_S_odigits];
774 *__buf-- = __lit[__num_base::_S_ominus];
775 else if (__flags & ios_base::showpos)
776 *__buf-- = __lit[__num_base::_S_oplus];
778 else if (__basefield == ios_base::oct)
783 *__buf-- = __lit[(__v & 0x7) + __num_base::_S_odigits];
788 *__buf-- = __lit[__num_base::_S_odigits];
793 const bool __uppercase = __flags & ios_base::uppercase;
794 const int __case_offset = __uppercase ? __num_base::_S_oudigits
795 : __num_base::_S_odigits;
798 *__buf-- = __lit[(__v & 0xf) + __case_offset];
805 *__buf-- = __lit[__num_base::_S_ox + __uppercase];
807 *__buf-- = __lit[__num_base::_S_odigits];
810 return __bufend - __buf - 1;
813 template<typename _CharT, typename _OutIter>
815 num_put<_CharT, _OutIter>::
816 _M_group_int(const char* __grouping, size_t __grouping_size, _CharT __sep,
817 ios_base& __io, _CharT* __new, _CharT* __cs, int& __len) const
819 // By itself __add_grouping cannot deal correctly with __cs when
820 // ios::showbase is set and ios_base::oct || ios_base::hex.
821 // Therefore we take care "by hand" of the initial 0, 0x or 0X.
822 // However, remember that the latter do not occur if the number
823 // printed is '0' (__len == 1).
824 streamsize __off = 0;
825 const ios_base::fmtflags __basefield = __io.flags()
826 & ios_base::basefield;
827 if ((__io.flags() & ios_base::showbase) && __len > 1)
828 if (__basefield == ios_base::oct)
833 else if (__basefield == ios_base::hex)
840 __p = std::__add_grouping(__new + __off, __sep, __grouping,
841 __grouping_size, __cs + __off,
846 template<typename _CharT, typename _OutIter>
847 template<typename _ValueT>
849 num_put<_CharT, _OutIter>::
850 _M_insert_int(_OutIter __s, ios_base& __io, _CharT __fill,
853 typedef typename numpunct<_CharT>::__cache_type __cache_type;
854 __use_cache<__cache_type> __uc;
855 const locale& __loc = __io._M_getloc();
856 const __cache_type* __lc = __uc(__loc);
857 const _CharT* __lit = __lc->_M_atoms_out;
859 // Long enough to hold hex, dec, and octal representations.
860 const int __ilen = 4 * sizeof(_ValueT);
861 _CharT* __cs = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
864 // [22.2.2.2.2] Stage 1, numeric conversion to character.
865 // Result is returned right-justified in the buffer.
867 __len = __int_to_char(__cs + __ilen, __v, __lit, __io.flags());
868 __cs += __ilen - __len;
870 // Add grouping, if necessary.
871 if (__lc->_M_use_grouping)
873 // Grouping can add (almost) as many separators as the
874 // number of digits, but no more.
875 _CharT* __cs2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
877 _M_group_int(__lc->_M_grouping, __lc->_M_grouping_size,
878 __lc->_M_thousands_sep, __io, __cs2, __cs, __len);
883 const streamsize __w = __io.width();
884 if (__w > static_cast<streamsize>(__len))
886 _CharT* __cs3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
888 _M_pad(__fill, __w, __io, __cs3, __cs, __len);
893 // [22.2.2.2.2] Stage 4.
894 // Write resulting, fully-formatted string to output iterator.
895 return std::__write(__s, __cs, __len);
898 template<typename _CharT, typename _OutIter>
900 num_put<_CharT, _OutIter>::
901 _M_group_float(const char* __grouping, size_t __grouping_size,
902 _CharT __sep, const _CharT* __p, _CharT* __new,
903 _CharT* __cs, int& __len) const
905 // _GLIBCXX_RESOLVE_LIB_DEFECTS
906 // 282. What types does numpunct grouping refer to?
907 // Add grouping, if necessary.
909 const int __declen = __p ? __p - __cs : __len;
910 __p2 = std::__add_grouping(__new, __sep, __grouping, __grouping_size,
911 __cs, __cs + __declen);
913 // Tack on decimal part.
914 int __newlen = __p2 - __new;
917 char_traits<_CharT>::copy(__p2, __p, __len - __declen);
918 __newlen += __len - __declen;
923 // The following code uses snprintf (or sprintf(), when
924 // _GLIBCXX_USE_C99 is not defined) to convert floating point values
925 // for insertion into a stream. An optimization would be to replace
926 // them with code that works directly on a wide buffer and then use
927 // __pad to do the padding. It would be good to replace them anyway
928 // to gain back the efficiency that C++ provides by knowing up front
929 // the type of the values to insert. Also, sprintf is dangerous
930 // since may lead to accidental buffer overruns. This
931 // implementation follows the C++ standard fairly directly as
932 // outlined in 22.2.2.2 [lib.locale.num.put]
933 template<typename _CharT, typename _OutIter>
934 template<typename _ValueT>
936 num_put<_CharT, _OutIter>::
937 _M_insert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
940 typedef typename numpunct<_CharT>::__cache_type __cache_type;
941 __use_cache<__cache_type> __uc;
942 const locale& __loc = __io._M_getloc();
943 const __cache_type* __lc = __uc(__loc);
945 // Note: digits10 is rounded down: add 1 to ensure the maximum
946 // available precision. Then, in general, one more 1 needs to
947 // be added since, when the %{g,G} conversion specifiers are
948 // chosen inside _S_format_float, the precision field is "the
949 // maximum number of significant digits", *not* the "number of
950 // digits to appear after the decimal point", as happens for
951 // %{e,E,f,F} (C99, 7.19.6.1,4).
952 const int __max_digits = numeric_limits<_ValueT>::digits10 + 2;
954 // Use default precision if out of range.
955 streamsize __prec = __io.precision();
956 if (__prec > static_cast<streamsize>(__max_digits))
957 __prec = static_cast<streamsize>(__max_digits);
958 else if (__prec < static_cast<streamsize>(0))
959 __prec = static_cast<streamsize>(6);
961 // [22.2.2.2.2] Stage 1, numeric conversion to character.
963 // Long enough for the max format spec.
966 #ifdef _GLIBCXX_USE_C99
967 // First try a buffer perhaps big enough (for sure sufficient
968 // for non-ios_base::fixed outputs)
969 int __cs_size = __max_digits * 3;
970 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
972 _S_format_float(__io, __fbuf, __mod);
973 __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
974 _S_get_c_locale(), __prec);
976 // If the buffer was not large enough, try again with the correct size.
977 if (__len >= __cs_size)
979 __cs_size = __len + 1;
980 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
981 __len = std::__convert_from_v(__cs, __cs_size, __fbuf, __v,
982 _S_get_c_locale(), __prec);
985 // Consider the possibility of long ios_base::fixed outputs
986 const bool __fixed = __io.flags() & ios_base::fixed;
987 const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
989 // The size of the output string is computed as follows.
990 // ios_base::fixed outputs may need up to __max_exp+1 chars
991 // for the integer part + up to __max_digits chars for the
992 // fractional part + 3 chars for sign, decimal point, '\0'. On
993 // the other hand, for non-fixed outputs __max_digits*3 chars
994 // are largely sufficient.
995 const int __cs_size = __fixed ? __max_exp + __max_digits + 4
997 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
999 _S_format_float(__io, __fbuf, __mod);
1000 __len = std::__convert_from_v(__cs, 0, __fbuf, __v,
1001 _S_get_c_locale(), __prec);
1004 // [22.2.2.2.2] Stage 2, convert to char_type, using correct
1005 // numpunct.decimal_point() values for '.' and adding grouping.
1006 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1008 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1010 __ctype.widen(__cs, __cs + __len, __ws);
1012 // Replace decimal point.
1013 const _CharT __cdec = __ctype.widen('.');
1014 const _CharT __dec = __lc->_M_decimal_point;
1016 if (__p = char_traits<_CharT>::find(__ws, __len, __cdec))
1017 __ws[__p - __ws] = __dec;
1019 // Add grouping, if necessary.
1020 if (__lc->_M_use_grouping)
1022 // Grouping can add (almost) as many separators as the
1023 // number of digits, but no more.
1024 _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1026 _M_group_float(__lc->_M_grouping, __lc->_M_grouping_size,
1027 __lc->_M_thousands_sep, __p, __ws2, __ws, __len);
1032 const streamsize __w = __io.width();
1033 if (__w > static_cast<streamsize>(__len))
1035 _CharT* __ws3 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1037 _M_pad(__fill, __w, __io, __ws3, __ws, __len);
1042 // [22.2.2.2.2] Stage 4.
1043 // Write resulting, fully-formatted string to output iterator.
1044 return std::__write(__s, __ws, __len);
1047 template<typename _CharT, typename _OutIter>
1049 num_put<_CharT, _OutIter>::
1050 do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
1052 const ios_base::fmtflags __flags = __io.flags();
1053 if ((__flags & ios_base::boolalpha) == 0)
1055 unsigned long __uv = __v;
1056 __s = _M_insert_int(__s, __io, __fill, __uv);
1060 typedef typename numpunct<_CharT>::__cache_type __cache_type;
1061 __use_cache<__cache_type> __uc;
1062 const locale& __loc = __io._M_getloc();
1063 const __cache_type* __lc = __uc(__loc);
1065 const _CharT* __name = __v ? __lc->_M_truename
1066 : __lc->_M_falsename;
1067 int __len = __v ? __lc->_M_truename_size
1068 : __lc->_M_falsename_size;
1070 const streamsize __w = __io.width();
1071 if (__w > static_cast<streamsize>(__len))
1074 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1076 _M_pad(__fill, __w, __io, __cs, __name, __len);
1080 __s = std::__write(__s, __name, __len);
1085 template<typename _CharT, typename _OutIter>
1087 num_put<_CharT, _OutIter>::
1088 do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
1089 { return _M_insert_int(__s, __io, __fill, __v); }
1091 template<typename _CharT, typename _OutIter>
1093 num_put<_CharT, _OutIter>::
1094 do_put(iter_type __s, ios_base& __io, char_type __fill,
1095 unsigned long __v) const
1096 { return _M_insert_int(__s, __io, __fill, __v); }
1098 #ifdef _GLIBCXX_USE_LONG_LONG
1099 template<typename _CharT, typename _OutIter>
1101 num_put<_CharT, _OutIter>::
1102 do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
1103 { return _M_insert_int(__s, __b, __fill, __v); }
1105 template<typename _CharT, typename _OutIter>
1107 num_put<_CharT, _OutIter>::
1108 do_put(iter_type __s, ios_base& __io, char_type __fill,
1109 unsigned long long __v) const
1110 { return _M_insert_int(__s, __io, __fill, __v); }
1113 template<typename _CharT, typename _OutIter>
1115 num_put<_CharT, _OutIter>::
1116 do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
1117 { return _M_insert_float(__s, __io, __fill, char(), __v); }
1119 template<typename _CharT, typename _OutIter>
1121 num_put<_CharT, _OutIter>::
1122 do_put(iter_type __s, ios_base& __io, char_type __fill,
1123 long double __v) const
1124 { return _M_insert_float(__s, __io, __fill, 'L', __v); }
1126 template<typename _CharT, typename _OutIter>
1128 num_put<_CharT, _OutIter>::
1129 do_put(iter_type __s, ios_base& __io, char_type __fill,
1130 const void* __v) const
1132 const ios_base::fmtflags __flags = __io.flags();
1133 const ios_base::fmtflags __fmt = ~(ios_base::showpos
1134 | ios_base::basefield
1135 | ios_base::uppercase
1136 | ios_base::internal);
1137 __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
1139 __s = _M_insert_int(__s, __io, __fill,
1140 reinterpret_cast<unsigned long>(__v));
1141 __io.flags(__flags);
1145 template<typename _CharT, bool _Intl>
1146 struct __use_cache<__moneypunct_cache<_CharT, _Intl> >
1148 const __moneypunct_cache<_CharT, _Intl>*
1149 operator() (const locale& __loc) const
1151 const size_t __i = moneypunct<_CharT, _Intl>::id._M_id();
1152 const locale::facet** __caches = __loc._M_impl->_M_caches;
1155 __moneypunct_cache<_CharT, _Intl>* __tmp = NULL;
1158 __tmp = new __moneypunct_cache<_CharT, _Intl>;
1159 __tmp->_M_cache(__loc);
1164 __throw_exception_again;
1166 __loc._M_impl->_M_install_cache(__tmp, __i);
1169 const __moneypunct_cache<_CharT, _Intl>*>(__caches[__i]);
1173 template<typename _CharT, typename _InIter>
1174 template<bool _Intl>
1176 money_get<_CharT, _InIter>::
1177 _M_extract(iter_type __beg, iter_type __end, ios_base& __io,
1178 ios_base::iostate& __err, string& __units) const
1180 typedef char_traits<_CharT> __traits_type;
1181 typedef typename string_type::size_type size_type;
1182 typedef money_base::part part;
1183 typedef moneypunct<_CharT, _Intl> __moneypunct_type;
1184 typedef typename __moneypunct_type::__cache_type __cache_type;
1186 const locale& __loc = __io._M_getloc();
1187 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1189 __use_cache<__cache_type> __uc;
1190 const __cache_type* __lc = __uc(__loc);
1191 const char_type* __lit = __lc->_M_atoms;
1193 const money_base::pattern __p = __lc->_M_neg_format;
1196 bool __negative = false;
1197 // True for more than one character long sign.
1198 bool __long_sign = false;
1199 // String of grouping info from thousands_sep plucked from __units.
1200 string __grouping_tmp;
1201 if (__lc->_M_use_grouping)
1202 __grouping_tmp.reserve(32);
1203 // Marker for thousands_sep position.
1205 // If input iterator is in a valid state.
1206 bool __testvalid = true;
1207 // Flag marking when a decimal point is found.
1208 bool __testdecfound = false;
1210 // The tentative returned string is stored here.
1214 const char_type* __lit_zero = __lit + _S_zero;
1215 const char_type* __q;
1216 for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
1218 const part __which = static_cast<part>(__p.field[__i]);
1221 case money_base::symbol:
1222 if (__io.flags() & ios_base::showbase
1223 || __i < 2 || __long_sign
1224 || ((static_cast<part>(__p.field[3]) != money_base::none)
1227 // According to 22.2.6.1.2, p2, symbol is required
1228 // if (__io.flags() & ios_base::showbase),
1229 // otherwise is optional and consumed only if
1230 // other characters are needed to complete the
1232 const size_type __len = __lc->_M_curr_symbol_size;
1234 for (; __beg != __end && __j < __len
1235 && *__beg == __lc->_M_curr_symbol[__j];
1237 // When (__io.flags() & ios_base::showbase)
1238 // symbol is required.
1239 if (__j != __len && (__io.flags() & ios_base::showbase))
1240 __testvalid = false;
1243 case money_base::sign:
1244 // Sign might not exist, or be more than one character long.
1245 if (__lc->_M_positive_sign_size
1246 && *__beg == __lc->_M_positive_sign[0])
1248 if (__lc->_M_positive_sign_size > 1)
1252 else if (__lc->_M_negative_sign_size
1253 && *__beg == __lc->_M_negative_sign[0])
1256 if (__lc->_M_negative_sign_size > 1)
1260 else if (__lc->_M_positive_sign_size
1261 && !__lc->_M_negative_sign_size)
1262 // "... if no sign is detected, the result is given the sign
1263 // that corresponds to the source of the empty string"
1265 else if (__lc->_M_positive_sign_size
1266 && __lc->_M_negative_sign_size)
1268 // Sign is mandatory.
1269 __testvalid = false;
1272 case money_base::value:
1273 // Extract digits, remove and stash away the
1274 // grouping of found thousands separators.
1275 for (; __beg != __end; ++__beg)
1276 if (__q = __traits_type::find(__lit_zero, 10, *__beg))
1278 __res += _S_atoms[__q - __lit];
1281 else if (*__beg == __lc->_M_decimal_point && !__testdecfound)
1283 // If no grouping chars are seen, no grouping check
1284 // is applied. Therefore __grouping_tmp is adjusted
1285 // only if decimal_point comes after some thousands_sep.
1286 if (__grouping_tmp.size())
1287 __grouping_tmp += static_cast<char>(__sep_pos);
1289 __testdecfound = true;
1291 else if (__lc->_M_use_grouping
1292 && *__beg == __lc->_M_thousands_sep)
1294 if (!__testdecfound)
1296 // Mark position for later analysis.
1297 __grouping_tmp += static_cast<char>(__sep_pos);
1302 __testvalid = false;
1309 case money_base::space:
1310 case money_base::none:
1311 // Only if not at the end of the pattern.
1313 for (; __beg != __end
1314 && __ctype.is(ctype_base::space, *__beg); ++__beg);
1319 // Need to get the rest of the sign characters, if they exist.
1322 const char_type* __sign = __negative ? __lc->_M_negative_sign
1323 : __lc->_M_positive_sign;
1324 const size_type __len = __negative ? __lc->_M_negative_sign_size
1325 : __lc->_M_positive_sign_size;
1327 for (; __beg != __end && __i < __len
1328 && *__beg == __sign[__i]; ++__beg, ++__i);
1331 __testvalid = false;
1334 if (__testvalid && __res.size())
1336 // Strip leading zeros.
1337 if (__res.size() > 1)
1339 size_type __first = __res.find_first_not_of(__lit[_S_zero]);
1340 const bool __only_zeros = __first == string_type::npos;
1342 __res.erase(0, __only_zeros ? __res.size() - 1 : __first);
1346 if (__negative && __res[0] != __lit[_S_zero])
1347 __res.insert(__res.begin(), __lit[_S_minus]);
1349 // Test for grouping fidelity.
1350 if (__grouping_tmp.size())
1352 // Add the ending grouping if a decimal wasn't found.
1353 if (!__testdecfound)
1354 __grouping_tmp += static_cast<char>(__sep_pos);
1356 if (!std::__verify_grouping(__lc->_M_grouping,
1357 __lc->_M_grouping_size,
1359 __testvalid = false;
1362 // Iff not enough digits were supplied after the decimal-point.
1363 if (__testdecfound && __lc->_M_frac_digits > 0
1364 && __sep_pos != __lc->_M_frac_digits)
1365 __testvalid = false;
1368 __testvalid = false;
1370 // Iff no more characters are available.
1372 __err |= ios_base::eofbit;
1374 // Iff valid sequence is not recognized.
1376 __err |= ios_base::failbit;
1378 __units.swap(__res);
1383 template<typename _CharT, typename _InIter>
1385 money_get<_CharT, _InIter>::
1386 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1387 ios_base::iostate& __err, long double& __units) const
1391 __beg = _M_extract<true>(__beg, __end, __io, __err, __str);
1393 __beg = _M_extract<false>(__beg, __end, __io, __err, __str);
1396 std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
1401 template<typename _CharT, typename _InIter>
1403 money_get<_CharT, _InIter>::
1404 do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
1405 ios_base::iostate& __err, string_type& __units) const
1407 typedef typename string_type::size_type size_type;
1409 const locale& __loc = __io._M_getloc();
1410 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1413 const iter_type __ret = __intl ? _M_extract<true>(__beg, __end, __io,
1415 : _M_extract<false>(__beg, __end, __io,
1417 const size_type __len = __str.size();
1420 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1422 __ctype.widen(__str.data(), __str.data() + __len, __ws);
1423 __units.assign(__ws, __len);
1429 template<typename _CharT, typename _OutIter>
1430 template<bool _Intl>
1432 money_put<_CharT, _OutIter>::
1433 _M_insert(iter_type __s, ios_base& __io, char_type __fill,
1434 const string_type& __digits) const
1436 typedef typename string_type::size_type size_type;
1437 typedef money_base::part part;
1438 typedef moneypunct<_CharT, _Intl> __moneypunct_type;
1439 typedef typename __moneypunct_type::__cache_type __cache_type;
1441 const locale& __loc = __io._M_getloc();
1442 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1444 __use_cache<__cache_type> __uc;
1445 const __cache_type* __lc = __uc(__loc);
1446 const char_type* __lit = __lc->_M_atoms;
1448 // Determine if negative or positive formats are to be used, and
1449 // discard leading negative_sign if it is present.
1450 const char_type* __beg = __digits.data();
1451 const char_type* __end = __beg + __digits.size();
1453 money_base::pattern __p;
1454 const char_type* __sign;
1455 size_type __sign_size;
1456 if (*__beg != __lit[_S_minus])
1458 __p = __lc->_M_pos_format;
1459 __sign = __lc->_M_positive_sign;
1460 __sign_size = __lc->_M_positive_sign_size;
1464 __p = __lc->_M_neg_format;
1465 __sign = __lc->_M_negative_sign;
1466 __sign_size = __lc->_M_negative_sign_size;
1470 // Look for valid numbers in the ctype facet within input digits.
1471 __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
1474 // Assume valid input, and attempt to format.
1475 // Break down input numbers into base components, as follows:
1476 // final_value = grouped units + (decimal point) + (digits)
1477 string_type __value;
1478 size_type __len = __end - __beg;
1479 __value.reserve(2 * __len);
1481 // Add thousands separators to non-decimal digits, per
1483 const int __paddec = __lc->_M_frac_digits - __len;
1486 if (__lc->_M_grouping_size)
1489 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1492 std::__add_grouping(__ws, __lc->_M_thousands_sep,
1494 __lc->_M_grouping_size,
1495 __beg, __end - __lc->_M_frac_digits);
1496 __value.assign(__ws, __ws_end - __ws);
1499 __value.assign(__beg, -__paddec);
1502 // Deal with decimal point, decimal digits.
1503 if (__lc->_M_frac_digits > 0)
1505 __value += __lc->_M_decimal_point;
1507 __value.append(__end - __lc->_M_frac_digits,
1508 __lc->_M_frac_digits);
1511 // Have to pad zeros in the decimal position.
1512 __value.append(__paddec, __lit[_S_zero]);
1513 __value.append(__beg, __len);
1517 // Calculate length of resulting string.
1518 const ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
1519 __len = __value.size() + __sign_size;
1520 __len += ((__io.flags() & ios_base::showbase)
1521 ? __lc->_M_curr_symbol_size : 0);
1524 __res.reserve(2 * __len);
1526 const size_type __width = static_cast<size_type>(__io.width());
1527 const bool __testipad = (__f == ios_base::internal
1528 && __len < __width);
1529 // Fit formatted digits into the required pattern.
1530 for (int __i = 0; __i < 4; ++__i)
1532 const part __which = static_cast<part>(__p.field[__i]);
1535 case money_base::symbol:
1536 if (__io.flags() & ios_base::showbase)
1537 __res.append(__lc->_M_curr_symbol,
1538 __lc->_M_curr_symbol_size);
1540 case money_base::sign:
1541 // Sign might not exist, or be more than one
1542 // charater long. In that case, add in the rest
1547 case money_base::value:
1550 case money_base::space:
1551 // At least one space is required, but if internal
1552 // formatting is required, an arbitrary number of
1553 // fill spaces will be necessary.
1555 __res.append(__width - __len, __fill);
1559 case money_base::none:
1561 __res.append(__width - __len, __fill);
1566 // Special case of multi-part sign parts.
1567 if (__sign_size > 1)
1568 __res.append(__sign + 1, __sign_size - 1);
1570 // Pad, if still necessary.
1571 __len = __res.size();
1572 if (__width > __len)
1574 if (__f == ios_base::left)
1576 __res.append(__width - __len, __fill);
1579 __res.insert(0, __width - __len, __fill);
1583 // Write resulting, fully-formatted string to output iterator.
1584 __s = std::__write(__s, __res.data(), __len);
1590 template<typename _CharT, typename _OutIter>
1592 money_put<_CharT, _OutIter>::
1593 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1594 long double __units) const
1596 const locale __loc = __io.getloc();
1597 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1598 #ifdef _GLIBCXX_USE_C99
1599 // First try a buffer perhaps big enough.
1601 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1602 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1603 // 328. Bad sprintf format modifier in money_put<>::do_put()
1604 int __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
1606 // If the buffer was not large enough, try again with the correct size.
1607 if (__len >= __cs_size)
1609 __cs_size = __len + 1;
1610 __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1611 __len = std::__convert_from_v(__cs, __cs_size, "%.0Lf", __units,
1615 // max_exponent10 + 1 for the integer part, + 2 for sign and '\0'.
1616 const int __cs_size = numeric_limits<long double>::max_exponent10 + 3;
1617 char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
1618 int __len = std::__convert_from_v(__cs, 0, "%.0Lf", __units,
1621 _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
1623 __ctype.widen(__cs, __cs + __len, __ws);
1624 const string_type __digits(__ws, __len);
1625 return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1626 : _M_insert<false>(__s, __io, __fill, __digits);
1629 template<typename _CharT, typename _OutIter>
1631 money_put<_CharT, _OutIter>::
1632 do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
1633 const string_type& __digits) const
1634 { return __intl ? _M_insert<true>(__s, __io, __fill, __digits)
1635 : _M_insert<false>(__s, __io, __fill, __digits); }
1637 // NB: Not especially useful. Without an ios_base object or some
1638 // kind of locale reference, we are left clawing at the air where
1639 // the side of the mountain used to be...
1640 template<typename _CharT, typename _InIter>
1641 time_base::dateorder
1642 time_get<_CharT, _InIter>::do_date_order() const
1643 { return time_base::no_order; }
1645 // Recursively expand a strftime format string and parse it. Starts w/ %x
1646 // and %X from do_get_time() and do_get_date(), which translate to a more
1647 // specific string, which may contain yet more strings. I.e. %x => %r =>
1648 // %H:%M:%S => extracted characters.
1649 template<typename _CharT, typename _InIter>
1651 time_get<_CharT, _InIter>::
1652 _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
1653 ios_base::iostate& __err, tm* __tm,
1654 const _CharT* __format) const
1656 const locale __loc = __io.getloc();
1657 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
1658 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
1659 const size_t __len = char_traits<_CharT>::length(__format);
1661 for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
1663 if (__ctype.narrow(__format[__i], 0) == '%')
1665 // Verify valid formatting code, attempt to extract.
1666 char __c = __ctype.narrow(__format[++__i], 0);
1668 if (__c == 'E' || __c == 'O')
1669 __c = __ctype.narrow(__format[++__i], 0);
1675 // Abbreviated weekday name [tm_wday]
1676 const char_type* __days1[7];
1677 __tp._M_days_abbreviated(__days1);
1678 _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7,
1682 // Weekday name [tm_wday].
1683 const char_type* __days2[7];
1684 __tp._M_days(__days2);
1685 _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7,
1690 // Abbreviated month name [tm_mon]
1691 const char_type* __months1[12];
1692 __tp._M_months_abbreviated(__months1);
1693 _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12,
1697 // Month name [tm_mon].
1698 const char_type* __months2[12];
1699 __tp._M_months(__months2);
1700 _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12,
1704 // Default time and date representation.
1705 const char_type* __dt[2];
1706 __tp._M_date_time_formats(__dt);
1707 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1711 // Day [01, 31]. [tm_mday]
1712 _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2,
1716 // Day [1, 31], with single digits preceded by
1718 if (__ctype.is(ctype_base::space, *__beg))
1719 _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9, 1,
1722 _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31, 2,
1726 // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
1728 __ctype.widen(__cs, __cs + 9, __wcs);
1729 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1733 // Hour [00, 23]. [tm_hour]
1734 _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
1738 // Hour [01, 12]. [tm_hour]
1739 _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2,
1743 // Month [01, 12]. [tm_mon]
1744 _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype,
1747 __tm->tm_mon = __mem - 1;
1750 // Minute [00, 59]. [tm_min]
1751 _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
1755 if (__ctype.narrow(*__beg, 0) == '\n')
1758 __err |= ios_base::failbit;
1761 // Equivalent to (%H:%M).
1763 __ctype.widen(__cs, __cs + 6, __wcs);
1764 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1769 _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
1773 if (__ctype.narrow(*__beg, 0) == '\t')
1776 __err |= ios_base::failbit;
1779 // Equivalent to (%H:%M:%S).
1781 __ctype.widen(__cs, __cs + 9, __wcs);
1782 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1787 const char_type* __dates[2];
1788 __tp._M_date_formats(__dates);
1789 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1794 const char_type* __times[2];
1795 __tp._M_time_formats(__times);
1796 _M_extract_via_format(__beg, __end, __io, __err, __tm,
1801 // Two digit year. [tm_year]
1802 _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2,
1806 // Year [1900). [tm_year]
1807 _M_extract_num(__beg, __end, __mem, 0, 9999, 4,
1810 __tm->tm_year = __mem - 1900;
1814 if (__ctype.is(ctype_base::upper, *__beg))
1817 _M_extract_name(__beg, __end, __tmp,
1818 __timepunct_cache<_CharT>::_S_timezones,
1819 14, __ctype, __err);
1821 // GMT requires special effort.
1822 if (__beg != __end && !__err && __tmp == 0
1823 && (*__beg == __ctype.widen('-')
1824 || *__beg == __ctype.widen('+')))
1826 _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
1828 _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
1833 __err |= ios_base::failbit;
1837 __err |= ios_base::failbit;
1842 // Verify format and input match, extract and discard.
1843 if (__format[__i] == *__beg)
1846 __err |= ios_base::failbit;
1851 template<typename _CharT, typename _InIter>
1853 time_get<_CharT, _InIter>::
1854 _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
1855 int __min, int __max, size_t __len,
1856 const ctype<_CharT>& __ctype,
1857 ios_base::iostate& __err) const
1859 // As-is works for __len = 1, 2, 4, the values actually used.
1860 int __mult = __len == 2 ? 10 : (__len == 4 ? 1000 : 1);
1865 for (; __beg != __end && __i < __len; ++__beg, ++__i)
1867 const char __c = __ctype.narrow(*__beg, '*');
1868 if (__c >= '0' && __c <= '9')
1870 __value = __value * 10 + (__c - '0');
1871 const int __valuec = __value * __mult;
1872 if (__valuec > __max || __valuec + __mult < __min)
1882 __err |= ios_base::failbit;
1886 // All elements in __names are unique.
1887 template<typename _CharT, typename _InIter>
1889 time_get<_CharT, _InIter>::
1890 _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
1891 const _CharT** __names, size_t __indexlen,
1892 const ctype<_CharT>& __ctype,
1893 ios_base::iostate& __err) const
1895 typedef char_traits<_CharT> __traits_type;
1896 int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int)
1898 size_t __nmatches = 0;
1900 bool __testvalid = true;
1901 const char_type* __name;
1903 // Look for initial matches.
1904 // NB: Some of the locale data is in the form of all lowercase
1905 // names, and some is in the form of initially-capitalized
1906 // names. Look for both.
1909 const char_type __c = *__beg;
1910 for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
1911 if (__c == __names[__i1][0]
1912 || __c == __ctype.toupper(__names[__i1][0]))
1913 __matches[__nmatches++] = __i1;
1916 while (__nmatches > 1)
1918 // Find smallest matching string.
1919 size_t __minlen = 10;
1920 for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
1921 __minlen = std::min(__minlen,
1922 __traits_type::length(__names[__matches[__i2]]));
1924 if (__pos < __minlen && __beg != __end)
1927 for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
1929 __name = __names[__matches[__i3]];
1930 if (__name[__pos] != *__beg)
1931 __matches[__i3] = __matches[--__nmatches];
1938 if (__nmatches == 1)
1940 // If there was only one match, the first compare is redundant.
1947 // Make sure found name is completely extracted.
1948 __name = __names[__matches[0]];
1949 const size_t __len = __traits_type::length(__name);
1950 while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
1954 __member = __matches[0];
1956 __testvalid = false;
1959 __testvalid = false;
1961 __err |= ios_base::failbit;
1964 template<typename _CharT, typename _InIter>
1966 time_get<_CharT, _InIter>::
1967 do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
1968 ios_base::iostate& __err, tm* __tm) const
1971 const char* __cs = "%X";
1972 const locale __loc = __io.getloc();
1973 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1974 __ctype.widen(__cs, __cs + 3, __wcs);
1975 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1977 __err |= ios_base::eofbit;
1981 template<typename _CharT, typename _InIter>
1983 time_get<_CharT, _InIter>::
1984 do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
1985 ios_base::iostate& __err, tm* __tm) const
1988 const char* __cs = "%x";
1989 const locale __loc = __io.getloc();
1990 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
1991 __ctype.widen(__cs, __cs + 3, __wcs);
1992 _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
1994 __err |= ios_base::eofbit;
1998 template<typename _CharT, typename _InIter>
2000 time_get<_CharT, _InIter>::
2001 do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io,
2002 ios_base::iostate& __err, tm* __tm) const
2004 typedef char_traits<_CharT> __traits_type;
2005 const locale __loc = __io.getloc();
2006 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2007 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2008 const char_type* __days[7];
2009 __tp._M_days_abbreviated(__days);
2011 _M_extract_name(__beg, __end, __tmpwday, __days, 7, __ctype, __err);
2013 // Check to see if non-abbreviated name exists, and extract.
2014 // NB: Assumes both _M_days and _M_days_abbreviated organized in
2015 // exact same order, first to last, such that the resulting
2016 // __days array with the same index points to a day, and that
2017 // day's abbreviated form.
2018 // NB: Also assumes that an abbreviated name is a subset of the name.
2021 size_t __pos = __traits_type::length(__days[__tmpwday]);
2022 __tp._M_days(__days);
2023 const char_type* __name = __days[__tmpwday];
2024 if (__name[__pos] == *__beg)
2026 // Extract the rest of it.
2027 const size_t __len = __traits_type::length(__name);
2028 while (__pos < __len && __beg != __end
2029 && __name[__pos] == *__beg)
2032 __err |= ios_base::failbit;
2035 __tm->tm_wday = __tmpwday;
2038 __err |= ios_base::eofbit;
2042 template<typename _CharT, typename _InIter>
2044 time_get<_CharT, _InIter>::
2045 do_get_monthname(iter_type __beg, iter_type __end,
2046 ios_base& __io, ios_base::iostate& __err, tm* __tm) const
2048 typedef char_traits<_CharT> __traits_type;
2049 const locale __loc = __io.getloc();
2050 const __timepunct<_CharT>& __tp = use_facet<__timepunct<_CharT> >(__loc);
2051 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2052 const char_type* __months[12];
2053 __tp._M_months_abbreviated(__months);
2055 _M_extract_name(__beg, __end, __tmpmon, __months, 12, __ctype, __err);
2057 // Check to see if non-abbreviated name exists, and extract.
2058 // NB: Assumes both _M_months and _M_months_abbreviated organized in
2059 // exact same order, first to last, such that the resulting
2060 // __months array with the same index points to a month, and that
2061 // month's abbreviated form.
2062 // NB: Also assumes that an abbreviated name is a subset of the name.
2065 size_t __pos = __traits_type::length(__months[__tmpmon]);
2066 __tp._M_months(__months);
2067 const char_type* __name = __months[__tmpmon];
2068 if (__name[__pos] == *__beg)
2070 // Extract the rest of it.
2071 const size_t __len = __traits_type::length(__name);
2072 while (__pos < __len && __beg != __end
2073 && __name[__pos] == *__beg)
2076 __err |= ios_base::failbit;
2079 __tm->tm_mon = __tmpmon;
2083 __err |= ios_base::eofbit;
2087 template<typename _CharT, typename _InIter>
2089 time_get<_CharT, _InIter>::
2090 do_get_year(iter_type __beg, iter_type __end, ios_base& __io,
2091 ios_base::iostate& __err, tm* __tm) const
2093 const locale __loc = __io.getloc();
2094 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2098 for (; __beg != __end && __i < 4; ++__beg, ++__i)
2100 const char __c = __ctype.narrow(*__beg, '*');
2101 if (__c >= '0' && __c <= '9')
2102 __value = __value * 10 + (__c - '0');
2106 if (__i == 2 || __i == 4)
2107 __tm->tm_year = __i == 2 ? __value : __value - 1900;
2109 __err |= ios_base::failbit;
2111 __err |= ios_base::eofbit;
2115 template<typename _CharT, typename _OutIter>
2117 time_put<_CharT, _OutIter>::
2118 put(iter_type __s, ios_base& __io, char_type __fill, const tm* __tm,
2119 const _CharT* __beg, const _CharT* __end) const
2121 const locale __loc = __io.getloc();
2122 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
2123 for (; __beg != __end; ++__beg)
2124 if (__ctype.narrow(*__beg, 0) != '%')
2129 else if (++__beg != __end)
2133 const char __c = __ctype.narrow(*__beg, 0);
2134 if (__c != 'E' && __c != 'O')
2136 else if (++__beg != __end)
2139 __format = __ctype.narrow(*__beg, 0);
2143 __s = this->do_put(__s, __io, __fill, __tm,
2151 template<typename _CharT, typename _OutIter>
2153 time_put<_CharT, _OutIter>::
2154 do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm,
2155 char __format, char __mod) const
2157 const locale __loc = __io.getloc();
2158 ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
2159 __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
2161 // NB: This size is arbitrary. Should this be a data member,
2162 // initialized at construction?
2163 const size_t __maxlen = 64;
2165 static_cast<char_type*>(__builtin_alloca(sizeof(char_type)
2168 // NB: In IEE 1003.1-200x, and perhaps other locale models, it
2169 // is possible that the format character will be longer than one
2170 // character. Possibilities include 'E' or 'O' followed by a
2171 // format character: if __mod is not the default argument, assume
2172 // it's a valid modifier.
2174 __fmt[0] = __ctype.widen('%');
2177 __fmt[1] = __format;
2178 __fmt[2] = char_type();
2183 __fmt[2] = __format;
2184 __fmt[3] = char_type();
2187 __tp._M_put(__res, __maxlen, __fmt, __tm);
2189 // Write resulting, fully-formatted string to output iterator.
2190 return std::__write(__s, __res, char_traits<char_type>::length(__res));
2194 // Generic version does nothing.
2195 template<typename _CharT>
2197 collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
2200 // Generic version does nothing.
2201 template<typename _CharT>
2203 collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
2206 template<typename _CharT>
2209 do_compare(const _CharT* __lo1, const _CharT* __hi1,
2210 const _CharT* __lo2, const _CharT* __hi2) const
2212 // strcoll assumes zero-terminated strings so we make a copy
2213 // and then put a zero at the end.
2214 const string_type __one(__lo1, __hi1);
2215 const string_type __two(__lo2, __hi2);
2217 const _CharT* __p = __one.c_str();
2218 const _CharT* __pend = __one.data() + __one.length();
2219 const _CharT* __q = __two.c_str();
2220 const _CharT* __qend = __two.data() + __two.length();
2222 // strcoll stops when it sees a nul character so we break
2223 // the strings into zero-terminated substrings and pass those
2227 const int __res = _M_compare(__p, __q);
2231 __p += char_traits<_CharT>::length(__p);
2232 __q += char_traits<_CharT>::length(__q);
2233 if (__p == __pend && __q == __qend)
2235 else if (__p == __pend)
2237 else if (__q == __qend)
2245 template<typename _CharT>
2246 typename collate<_CharT>::string_type
2248 do_transform(const _CharT* __lo, const _CharT* __hi) const
2250 // strxfrm assumes zero-terminated strings so we make a copy
2251 string_type __str(__lo, __hi);
2253 const _CharT* __p = __str.c_str();
2254 const _CharT* __pend = __str.data() + __str.length();
2256 size_t __len = (__hi - __lo) * 2;
2260 // strxfrm stops when it sees a nul character so we break
2261 // the string into zero-terminated substrings and pass those
2265 // First try a buffer perhaps big enough.
2267 static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
2268 size_t __res = _M_transform(__c, __p, __len);
2269 // If the buffer was not large enough, try again with the
2274 __c = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
2276 __res = _M_transform(__c, __p, __res + 1);
2279 __ret.append(__c, __res);
2280 __p += char_traits<_CharT>::length(__p);
2285 __ret.push_back(_CharT());
2289 template<typename _CharT>
2292 do_hash(const _CharT* __lo, const _CharT* __hi) const
2294 unsigned long __val = 0;
2295 for (; __lo < __hi; ++__lo)
2296 __val = *__lo + ((__val << 7) |
2297 (__val >> (numeric_limits<unsigned long>::digits - 7)));
2298 return static_cast<long>(__val);
2301 // Construct correctly padded string, as per 22.2.2.2.2
2303 // __newlen > __oldlen
2304 // __news is allocated for __newlen size
2305 // Used by both num_put and ostream inserters: if __num,
2306 // internal-adjusted objects are padded according to the rules below
2307 // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
2310 // NB: Of the two parameters, _CharT can be deduced from the
2311 // function arguments. The other (_Traits) has to be explicitly specified.
2312 template<typename _CharT, typename _Traits>
2314 __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill,
2315 _CharT* __news, const _CharT* __olds,
2316 const streamsize __newlen,
2317 const streamsize __oldlen, const bool __num)
2319 const size_t __plen = static_cast<size_t>(__newlen - __oldlen);
2320 const ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
2323 if (__adjust == ios_base::left)
2325 _Traits::copy(__news, const_cast<_CharT*>(__olds), __oldlen);
2326 _Traits::assign(__news + __oldlen, __plen, __fill);
2331 if (__adjust == ios_base::internal && __num)
2333 // Pad after the sign, if there is one.
2334 // Pad after 0[xX], if there is one.
2335 // Who came up with these rules, anyway? Jeeze.
2336 const locale& __loc = __io._M_getloc();
2337 const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
2339 const bool __testsign = _Traits::eq(__ctype.widen('-'), __olds[0])
2340 || _Traits::eq(__ctype.widen('+'), __olds[0]);
2341 const bool __testhex = (_Traits::eq(__ctype.widen('0'), __olds[0])
2343 && (_Traits::eq(__ctype.widen('x'), __olds[1])
2344 || _Traits::eq(__ctype.widen('X'),
2348 __news[0] = __olds[0];
2349 __news[1] = __olds[1];
2353 else if (__testsign)
2355 __news[0] = __olds[0];
2359 // else Padding first.
2361 _Traits::assign(__news, __plen, __fill);
2362 _Traits::copy(__news + __plen, const_cast<_CharT*>(__olds + __mod),
2367 __verify_grouping(const char* __grouping, size_t __grouping_size,
2368 const string& __grouping_tmp)
2370 const size_t __n = __grouping_tmp.size() - 1;
2371 const size_t __min = std::min(__n, __grouping_size - 1);
2375 // Parsed number groupings have to match the
2376 // numpunct::grouping string exactly, starting at the
2377 // right-most point of the parsed sequence of elements ...
2378 for (size_t __j = 0; __j < __min && __test; --__i, ++__j)
2379 __test = __grouping_tmp[__i] == __grouping[__j];
2380 for (; __i && __test; --__i)
2381 __test = __grouping_tmp[__i] == __grouping[__min];
2382 // ... but the last parsed grouping can be <= numpunct
2384 __test &= __grouping_tmp[0] <= __grouping[__min];
2388 template<typename _CharT>
2390 __add_grouping(_CharT* __s, _CharT __sep,
2391 const char* __gbeg, size_t __gsize,
2392 const _CharT* __first, const _CharT* __last)
2394 if (__last - __first > *__gbeg)
2396 const bool __bump = __gsize != 1;
2397 __s = std::__add_grouping(__s, __sep, __gbeg + __bump,
2398 __gsize - __bump, __first,
2400 __first = __last - *__gbeg;
2404 *__s++ = *__first++;
2405 while (__first != __last);
2409 // Inhibit implicit instantiations for required instantiations,
2410 // which are defined via explicit instantiations elsewhere.
2411 // NB: This syntax is a GNU extension.
2412 #if _GLIBCXX_EXTERN_TEMPLATE
2413 extern template class moneypunct<char, false>;
2414 extern template class moneypunct<char, true>;
2415 extern template class moneypunct_byname<char, false>;
2416 extern template class moneypunct_byname<char, true>;
2417 extern template class money_get<char>;
2418 extern template class money_put<char>;
2419 extern template class numpunct<char>;
2420 extern template class numpunct_byname<char>;
2421 extern template class num_get<char>;
2422 extern template class num_put<char>;
2423 extern template class __timepunct<char>;
2424 extern template class time_put<char>;
2425 extern template class time_put_byname<char>;
2426 extern template class time_get<char>;
2427 extern template class time_get_byname<char>;
2428 extern template class messages<char>;
2429 extern template class messages_byname<char>;
2430 extern template class ctype_byname<char>;
2431 extern template class codecvt_byname<char, char, mbstate_t>;
2432 extern template class collate<char>;
2433 extern template class collate_byname<char>;
2436 const codecvt<char, char, mbstate_t>&
2437 use_facet<codecvt<char, char, mbstate_t> >(const locale&);
2440 const collate<char>&
2441 use_facet<collate<char> >(const locale&);
2444 const numpunct<char>&
2445 use_facet<numpunct<char> >(const locale&);
2448 const num_put<char>&
2449 use_facet<num_put<char> >(const locale&);
2452 const num_get<char>&
2453 use_facet<num_get<char> >(const locale&);
2456 const moneypunct<char, true>&
2457 use_facet<moneypunct<char, true> >(const locale&);
2460 const moneypunct<char, false>&
2461 use_facet<moneypunct<char, false> >(const locale&);
2464 const money_put<char>&
2465 use_facet<money_put<char> >(const locale&);
2468 const money_get<char>&
2469 use_facet<money_get<char> >(const locale&);
2472 const __timepunct<char>&
2473 use_facet<__timepunct<char> >(const locale&);
2476 const time_put<char>&
2477 use_facet<time_put<char> >(const locale&);
2480 const time_get<char>&
2481 use_facet<time_get<char> >(const locale&);
2484 const messages<char>&
2485 use_facet<messages<char> >(const locale&);
2489 has_facet<ctype<char> >(const locale&);
2493 has_facet<codecvt<char, char, mbstate_t> >(const locale&);
2497 has_facet<collate<char> >(const locale&);
2501 has_facet<numpunct<char> >(const locale&);
2505 has_facet<num_put<char> >(const locale&);
2509 has_facet<num_get<char> >(const locale&);
2513 has_facet<moneypunct<char> >(const locale&);
2517 has_facet<money_put<char> >(const locale&);
2521 has_facet<money_get<char> >(const locale&);
2525 has_facet<__timepunct<char> >(const locale&);
2529 has_facet<time_put<char> >(const locale&);
2533 has_facet<time_get<char> >(const locale&);
2537 has_facet<messages<char> >(const locale&);
2539 #ifdef _GLIBCXX_USE_WCHAR_T
2540 extern template class moneypunct<wchar_t, false>;
2541 extern template class moneypunct<wchar_t, true>;
2542 extern template class moneypunct_byname<wchar_t, false>;
2543 extern template class moneypunct_byname<wchar_t, true>;
2544 extern template class money_get<wchar_t>;
2545 extern template class money_put<wchar_t>;
2546 extern template class numpunct<wchar_t>;
2547 extern template class numpunct_byname<wchar_t>;
2548 extern template class num_get<wchar_t>;
2549 extern template class num_put<wchar_t>;
2550 extern template class __timepunct<wchar_t>;
2551 extern template class time_put<wchar_t>;
2552 extern template class time_put_byname<wchar_t>;
2553 extern template class time_get<wchar_t>;
2554 extern template class time_get_byname<wchar_t>;
2555 extern template class messages<wchar_t>;
2556 extern template class messages_byname<wchar_t>;
2557 extern template class ctype_byname<wchar_t>;
2558 extern template class codecvt_byname<wchar_t, char, mbstate_t>;
2559 extern template class collate<wchar_t>;
2560 extern template class collate_byname<wchar_t>;
2563 const codecvt<wchar_t, char, mbstate_t>&
2564 use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
2567 const collate<wchar_t>&
2568 use_facet<collate<wchar_t> >(const locale&);
2571 const numpunct<wchar_t>&
2572 use_facet<numpunct<wchar_t> >(const locale&);
2575 const num_put<wchar_t>&
2576 use_facet<num_put<wchar_t> >(const locale&);
2579 const num_get<wchar_t>&
2580 use_facet<num_get<wchar_t> >(const locale&);
2583 const moneypunct<wchar_t, true>&
2584 use_facet<moneypunct<wchar_t, true> >(const locale&);
2587 const moneypunct<wchar_t, false>&
2588 use_facet<moneypunct<wchar_t, false> >(const locale&);
2591 const money_put<wchar_t>&
2592 use_facet<money_put<wchar_t> >(const locale&);
2595 const money_get<wchar_t>&
2596 use_facet<money_get<wchar_t> >(const locale&);
2599 const __timepunct<wchar_t>&
2600 use_facet<__timepunct<wchar_t> >(const locale&);
2603 const time_put<wchar_t>&
2604 use_facet<time_put<wchar_t> >(const locale&);
2607 const time_get<wchar_t>&
2608 use_facet<time_get<wchar_t> >(const locale&);
2611 const messages<wchar_t>&
2612 use_facet<messages<wchar_t> >(const locale&);
2616 has_facet<ctype<wchar_t> >(const locale&);
2620 has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
2624 has_facet<collate<wchar_t> >(const locale&);
2628 has_facet<numpunct<wchar_t> >(const locale&);
2632 has_facet<num_put<wchar_t> >(const locale&);
2636 has_facet<num_get<wchar_t> >(const locale&);
2640 has_facet<moneypunct<wchar_t> >(const locale&);
2644 has_facet<money_put<wchar_t> >(const locale&);
2648 has_facet<money_get<wchar_t> >(const locale&);
2652 has_facet<__timepunct<wchar_t> >(const locale&);
2656 has_facet<time_put<wchar_t> >(const locale&);
2660 has_facet<time_get<wchar_t> >(const locale&);
2664 has_facet<messages<wchar_t> >(const locale&);