locale_facets.tcc revision 102782
197403Sobrien// Locale support -*- C++ -*-
297403Sobrien
397403Sobrien// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
497403Sobrien// Free Software Foundation, Inc.
597403Sobrien//
697403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
797403Sobrien// software; you can redistribute it and/or modify it under the
897403Sobrien// terms of the GNU General Public License as published by the
997403Sobrien// Free Software Foundation; either version 2, or (at your option)
1097403Sobrien// any later version.
1197403Sobrien
1297403Sobrien// This library is distributed in the hope that it will be useful,
1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1597403Sobrien// GNU General Public License for more details.
1697403Sobrien
1797403Sobrien// You should have received a copy of the GNU General Public License along
1897403Sobrien// with this library; see the file COPYING.  If not, write to the Free
1997403Sobrien// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2097403Sobrien// USA.
2197403Sobrien
2297403Sobrien// As a special exception, you may use this file as part of a free software
2397403Sobrien// library without restriction.  Specifically, if other files instantiate
2497403Sobrien// templates or use macros or inline functions from this file, or you compile
2597403Sobrien// this file and link it with other files to produce an executable, this
2697403Sobrien// file does not by itself cause the resulting executable to be covered by
2797403Sobrien// the GNU General Public License.  This exception does not however
2897403Sobrien// invalidate any other reasons why the executable file might be covered by
2997403Sobrien// the GNU General Public License.
3097403Sobrien
3197403Sobrien// Warning: this file is not meant for user inclusion. Use <locale>.
3297403Sobrien
3397403Sobrien#ifndef _CPP_BITS_LOCFACETS_TCC
3497403Sobrien#define _CPP_BITS_LOCFACETS_TCC 1
3597403Sobrien
3697403Sobrien#pragma GCC system_header
3797403Sobrien
3897403Sobrien#include <cerrno>
3997403Sobrien#include <clocale>   // For localeconv
4097403Sobrien#include <cstdlib>   // For strof, strtold
4197403Sobrien#include <cmath>     // For ceil
4297403Sobrien#include <cctype>    // For isspace
4397403Sobrien#include <limits>    // For numeric_limits
4497403Sobrien#include <bits/streambuf_iterator.h>
4597403Sobrien#include <typeinfo>  // For bad_cast.
4697403Sobrien
4797403Sobriennamespace std
4897403Sobrien{
4997403Sobrien  template<typename _Facet>
5097403Sobrien    locale
5197403Sobrien    locale::combine(const locale& __other) const
5297403Sobrien    {
5397403Sobrien      _Impl* __tmp = new _Impl(*_M_impl, 1);
5497403Sobrien      __tmp->_M_replace_facet(__other._M_impl, &_Facet::id);
5597403Sobrien      return locale(__tmp);
5697403Sobrien    }
5797403Sobrien
5897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
5997403Sobrien    bool
6097403Sobrien    locale::operator()(const basic_string<_CharT, _Traits, _Alloc>& __s1,
6197403Sobrien                       const basic_string<_CharT, _Traits, _Alloc>& __s2) const
6297403Sobrien    {
6397403Sobrien      typedef std::collate<_CharT> __collate_type;
6497403Sobrien      const __collate_type& __collate = use_facet<__collate_type>(*this);
6597403Sobrien      return (__collate.compare(__s1.data(), __s1.data() + __s1.length(),
6697403Sobrien				__s2.data(), __s2.data() + __s2.length()) < 0);
6797403Sobrien    }
6897403Sobrien
6997403Sobrien  template<typename _Facet>
7097403Sobrien    const _Facet&
7197403Sobrien    use_facet(const locale& __loc)
7297403Sobrien    {
7397403Sobrien      size_t __i = _Facet::id._M_id();
7497403Sobrien      locale::facet** __facets = __loc._M_impl->_M_facets;
7597403Sobrien      if (!(__i < __loc._M_impl->_M_facets_size && __facets[__i]))
7697403Sobrien        __throw_bad_cast();
7797403Sobrien      return static_cast<const _Facet&>(*__facets[__i]);
7897403Sobrien    }
7997403Sobrien
8097403Sobrien  template<typename _Facet>
8197403Sobrien    bool
8297403Sobrien    has_facet(const locale& __loc) throw()
8397403Sobrien    {
8497403Sobrien      size_t __i = _Facet::id._M_id();
8597403Sobrien      locale::facet** __facets = __loc._M_impl->_M_facets;
8697403Sobrien      return (__i < __loc._M_impl->_M_facets_size && __facets[__i]);
8797403Sobrien    }
8897403Sobrien
8997403Sobrien
9097403Sobrien  // Stage 1: Determine a conversion specifier.
9197403Sobrien  template<typename _CharT, typename _InIter>
9297403Sobrien    _InIter
9397403Sobrien    num_get<_CharT, _InIter>::
9497403Sobrien    _M_extract_float(_InIter __beg, _InIter __end, ios_base& __io,
9597403Sobrien		     ios_base::iostate& __err, string& __xtrc) const
9697403Sobrien    {
97102782Skan      typedef char_traits<_CharT>		__traits_type;
9897403Sobrien      const locale __loc = __io.getloc();
9997403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
10097403Sobrien      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
10197403Sobrien
10297403Sobrien      // First check for sign.
10397403Sobrien      const char_type __plus = __ctype.widen('+');
10497403Sobrien      const char_type __minus = __ctype.widen('-');
10597403Sobrien      int __pos = 0;
10697403Sobrien      char_type  __c = *__beg;
107102782Skan      if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus))
108102782Skan	  && __beg != __end)
10997403Sobrien	{
11097403Sobrien	  __xtrc += __ctype.narrow(__c, char());
11197403Sobrien	  ++__pos;
11297403Sobrien	  __c = *(++__beg);
11397403Sobrien	}
11497403Sobrien
11597403Sobrien      // Next, strip leading zeros.
11697403Sobrien      const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
11797403Sobrien      bool __found_zero = false;
118102782Skan      while (__traits_type::eq(__c, __zero) && __beg != __end)
11997403Sobrien	{
12097403Sobrien	  __c = *(++__beg);
12197403Sobrien	  __found_zero = true;
12297403Sobrien	}
12397403Sobrien      if (__found_zero)
12497403Sobrien	{
12597403Sobrien	  __xtrc += _S_atoms[_M_zero];
12697403Sobrien	  ++__pos;
12797403Sobrien	}
12897403Sobrien
12997403Sobrien      // Only need acceptable digits for floating point numbers.
13097403Sobrien      const size_t __len = _M_E - _M_zero + 1;
13197403Sobrien      char_type  __watoms[__len];
13297403Sobrien      __ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
13397403Sobrien      bool __found_dec = false;
13497403Sobrien      bool __found_sci = false;
13597403Sobrien      const char_type __dec = __np.decimal_point();
13697403Sobrien
13797403Sobrien      string __found_grouping;
13897403Sobrien      const string __grouping = __np.grouping();
13997403Sobrien      bool __check_grouping = __grouping.size();
14097403Sobrien      int __sep_pos = 0;
14197403Sobrien      const char_type __sep = __np.thousands_sep();
14297403Sobrien
14397403Sobrien      while (__beg != __end)
14497403Sobrien        {
14597403Sobrien	  // Only look in digits.
14697403Sobrien          const char_type* __p = __traits_type::find(__watoms, 10,  __c);
14797403Sobrien
14897403Sobrien          // NB: strchr returns true for __c == 0x0
149102782Skan          if (__p && !__traits_type::eq(__c, char_type()))
15097403Sobrien	    {
15197403Sobrien	      // Try first for acceptable digit; record it if found.
15297403Sobrien	      ++__pos;
15397403Sobrien	      __xtrc += _S_atoms[__p - __watoms];
15497403Sobrien	      ++__sep_pos;
15597403Sobrien	      __c = *(++__beg);
15697403Sobrien	    }
157102782Skan          else if (__traits_type::eq(__c, __sep) 
158102782Skan		   && __check_grouping && !__found_dec)
15997403Sobrien	    {
16097403Sobrien              // NB: Thousands separator at the beginning of a string
16197403Sobrien              // is a no-no, as is two consecutive thousands separators.
16297403Sobrien              if (__sep_pos)
16397403Sobrien                {
16497403Sobrien                  __found_grouping += static_cast<char>(__sep_pos);
16597403Sobrien                  __sep_pos = 0;
16697403Sobrien		  __c = *(++__beg);
16797403Sobrien                }
16897403Sobrien              else
16997403Sobrien		{
17097403Sobrien		  __err |= ios_base::failbit;
17197403Sobrien		  break;
17297403Sobrien		}
17397403Sobrien            }
174102782Skan	  else if (__traits_type::eq(__c, __dec) && !__found_dec)
17597403Sobrien	    {
17697403Sobrien	      // According to the standard, if no grouping chars are seen,
17797403Sobrien	      // no grouping check is applied. Therefore __found_grouping
17897403Sobrien	      // must be adjusted only if __dec comes after some __sep.
17997403Sobrien	      if (__found_grouping.size())
18097403Sobrien		__found_grouping += static_cast<char>(__sep_pos);
18197403Sobrien	      ++__pos;
18297403Sobrien	      __xtrc += '.';
18397403Sobrien	      __c = *(++__beg);
18497403Sobrien	      __found_dec = true;
18597403Sobrien	    }
186102782Skan	  else if ((__traits_type::eq(__c, __watoms[_M_e]) 
187102782Skan		    || __traits_type::eq(__c, __watoms[_M_E])) 
18897403Sobrien		   && !__found_sci && __pos)
18997403Sobrien	    {
19097403Sobrien	      // Scientific notation.
19197403Sobrien	      ++__pos;
19297403Sobrien	      __xtrc += __ctype.narrow(__c, char());
19397403Sobrien	      __c = *(++__beg);
19497403Sobrien
19597403Sobrien	      // Remove optional plus or minus sign, if they exist.
196102782Skan	      if (__traits_type::eq(__c, __plus) 
197102782Skan		  || __traits_type::eq(__c, __minus))
19897403Sobrien		{
19997403Sobrien		  ++__pos;
20097403Sobrien		  __xtrc += __ctype.narrow(__c, char());
20197403Sobrien		  __c = *(++__beg);
20297403Sobrien		}
20397403Sobrien	      __found_sci = true;
20497403Sobrien	    }
20597403Sobrien	  else
20697403Sobrien	    // Not a valid input item.
20797403Sobrien	    break;
20897403Sobrien        }
20997403Sobrien
21097403Sobrien      // Digit grouping is checked. If grouping and found_grouping don't
21197403Sobrien      // match, then get very very upset, and set failbit.
21297403Sobrien      if (__check_grouping && __found_grouping.size())
21397403Sobrien        {
21497403Sobrien          // Add the ending grouping if a decimal wasn't found.
21597403Sobrien	  if (!__found_dec)
21697403Sobrien	    __found_grouping += static_cast<char>(__sep_pos);
21797403Sobrien          if (!__verify_grouping(__grouping, __found_grouping))
21897403Sobrien	    __err |= ios_base::failbit;
21997403Sobrien        }
22097403Sobrien
22197403Sobrien      // Finish up
22297403Sobrien      __xtrc += char();
22397403Sobrien      if (__beg == __end)
22497403Sobrien        __err |= ios_base::eofbit;
22597403Sobrien      return __beg;
22697403Sobrien    }
22797403Sobrien
22897403Sobrien  // Stage 1: Determine a conversion specifier.
22997403Sobrien  template<typename _CharT, typename _InIter>
23097403Sobrien    _InIter
23197403Sobrien    num_get<_CharT, _InIter>::
23297403Sobrien    _M_extract_int(_InIter __beg, _InIter __end, ios_base& __io,
23397403Sobrien		   ios_base::iostate& __err, string& __xtrc, int& __base) const
23497403Sobrien    {
235102782Skan      typedef char_traits<_CharT>		__traits_type;
23697403Sobrien      const locale __loc = __io.getloc();
23797403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
23897403Sobrien      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
23997403Sobrien 
24097403Sobrien      // NB: Iff __basefield == 0, this can change based on contents.
24197403Sobrien      ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
24297403Sobrien      if (__basefield == ios_base::oct)
24397403Sobrien        __base = 8;
24497403Sobrien      else if (__basefield == ios_base::hex)
24597403Sobrien        __base = 16;
24697403Sobrien      else
24797403Sobrien	__base = 10;
24897403Sobrien
249102782Skan      // First check for sign.
25097403Sobrien      int __pos = 0;
25197403Sobrien      char_type  __c = *__beg;
252102782Skan      const char_type __plus = __ctype.widen('+');
253102782Skan      const char_type __minus = __ctype.widen('-');
254102782Skan
255102782Skan      if ((__traits_type::eq(__c, __plus) || __traits_type::eq(__c, __minus))
25697403Sobrien	  && __beg != __end)
25797403Sobrien	{
25897403Sobrien	  __xtrc += __ctype.narrow(__c, char());
25997403Sobrien	  ++__pos;
26097403Sobrien	  __c = *(++__beg);
26197403Sobrien	}
26297403Sobrien
26397403Sobrien      // Next, strip leading zeros and check required digits for base formats.
26497403Sobrien      const char_type __zero = __ctype.widen(_S_atoms[_M_zero]);
26597403Sobrien      const char_type __x = __ctype.widen('x');
26697403Sobrien      const char_type __X = __ctype.widen('X');
26797403Sobrien      if (__base == 10)
26897403Sobrien	{
26997403Sobrien	  bool __found_zero = false;
270102782Skan	  while (__traits_type::eq(__c, __zero) && __beg != __end)
27197403Sobrien	    {
27297403Sobrien	      __c = *(++__beg);
27397403Sobrien	      __found_zero = true;
27497403Sobrien	    }
27597403Sobrien	  if (__found_zero)
27697403Sobrien	    {
27797403Sobrien	      __xtrc += _S_atoms[_M_zero];
27897403Sobrien	      ++__pos;
27997403Sobrien	      if (__basefield == 0)
28097403Sobrien		{	      
281102782Skan		  if ((__traits_type::eq(__c, __x) 
282102782Skan		       || __traits_type::eq(__c, __X))
283102782Skan		      && __beg != __end)
28497403Sobrien		    {
28597403Sobrien		      __xtrc += __ctype.narrow(__c, char());
28697403Sobrien		      ++__pos;
28797403Sobrien		      __c = *(++__beg);
28897403Sobrien		      __base = 16;
28997403Sobrien		    }
29097403Sobrien		  else 
29197403Sobrien		    __base = 8;
29297403Sobrien		}
29397403Sobrien	    }
29497403Sobrien	}
29597403Sobrien      else if (__base == 16)
29697403Sobrien	{
297102782Skan	  if (__traits_type::eq(__c, __zero) && __beg != __end)
29897403Sobrien	    {
29997403Sobrien	      __xtrc += _S_atoms[_M_zero];
30097403Sobrien	      ++__pos;
30197403Sobrien	      __c = *(++__beg); 
302102782Skan	      if ((__traits_type::eq(__c, __x) || __traits_type::eq(__c, __X))
303102782Skan		  && __beg != __end)
30497403Sobrien		{
30597403Sobrien		  __xtrc += __ctype.narrow(__c, char());
30697403Sobrien		  ++__pos;
30797403Sobrien		  __c = *(++__beg);
30897403Sobrien		}
30997403Sobrien	    }
31097403Sobrien	}
31197403Sobrien
31297403Sobrien      // At this point, base is determined. If not hex, only allow
31397403Sobrien      // base digits as valid input.
31497403Sobrien      size_t __len;
31597403Sobrien      if (__base == 16)
31697403Sobrien	__len = _M_size;
31797403Sobrien      else
31897403Sobrien	__len = __base;
31997403Sobrien
32097403Sobrien      // Extract.
32197403Sobrien      char_type __watoms[_M_size];
32297403Sobrien      __ctype.widen(_S_atoms, _S_atoms + __len, __watoms);
32397403Sobrien      string __found_grouping;
32497403Sobrien      const string __grouping = __np.grouping();
32597403Sobrien      bool __check_grouping = __grouping.size();
32697403Sobrien      int __sep_pos = 0;
32797403Sobrien      const char_type __sep = __np.thousands_sep();
32897403Sobrien      while (__beg != __end)
32997403Sobrien        {
33097403Sobrien          const char_type* __p = __traits_type::find(__watoms, __len,  __c);
33197403Sobrien
33297403Sobrien          // NB: strchr returns true for __c == 0x0
333102782Skan          if (__p && !__traits_type::eq(__c, char_type()))
33497403Sobrien	    {
33597403Sobrien	      // Try first for acceptable digit; record it if found.
33697403Sobrien	      __xtrc += _S_atoms[__p - __watoms];
33797403Sobrien	      ++__pos;
33897403Sobrien	      ++__sep_pos;
33997403Sobrien	      __c = *(++__beg);
34097403Sobrien	    }
341102782Skan          else if (__traits_type::eq(__c, __sep) && __check_grouping)
34297403Sobrien	    {
34397403Sobrien              // NB: Thousands separator at the beginning of a string
34497403Sobrien              // is a no-no, as is two consecutive thousands separators.
34597403Sobrien              if (__sep_pos)
34697403Sobrien                {
34797403Sobrien                  __found_grouping += static_cast<char>(__sep_pos);
34897403Sobrien                  __sep_pos = 0;
34997403Sobrien		  __c = *(++__beg);
35097403Sobrien                }
35197403Sobrien              else
35297403Sobrien		{
35397403Sobrien		  __err |= ios_base::failbit;
35497403Sobrien		  break;
35597403Sobrien		}
35697403Sobrien            }
35797403Sobrien	  else
35897403Sobrien	    // Not a valid input item.
35997403Sobrien	    break;
36097403Sobrien        }
36197403Sobrien
36297403Sobrien      // Digit grouping is checked. If grouping and found_grouping don't
36397403Sobrien      // match, then get very very upset, and set failbit.
36497403Sobrien      if (__check_grouping && __found_grouping.size())
36597403Sobrien        {
36697403Sobrien          // Add the ending grouping.
36797403Sobrien          __found_grouping += static_cast<char>(__sep_pos);
36897403Sobrien          if (!__verify_grouping(__grouping, __found_grouping))
36997403Sobrien	    __err |= ios_base::failbit;
37097403Sobrien        }
37197403Sobrien
37297403Sobrien      // Finish up.
37397403Sobrien      __xtrc += char();
37497403Sobrien      if (__beg == __end)
37597403Sobrien        __err |= ios_base::eofbit;
37697403Sobrien      return __beg;
37797403Sobrien    }
37897403Sobrien
37997403Sobrien#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
38097403Sobrien  //17.  Bad bool parsing
38197403Sobrien  template<typename _CharT, typename _InIter>
38297403Sobrien    _InIter
38397403Sobrien    num_get<_CharT, _InIter>::
38497403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
38597403Sobrien           ios_base::iostate& __err, bool& __v) const
38697403Sobrien    {
38797403Sobrien      // Parse bool values as unsigned long
38897403Sobrien      if (!(__io.flags() & ios_base::boolalpha))
38997403Sobrien        {
39097403Sobrien          // NB: We can't just call do_get(long) here, as it might
39197403Sobrien          // refer to a derived class.
39297403Sobrien          string __xtrc;
39397403Sobrien          int __base;
39497403Sobrien          __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
39597403Sobrien
39697403Sobrien	  unsigned long __ul; 
39797403Sobrien	  __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
39897403Sobrien	  if (!(__err & ios_base::failbit) && __ul <= 1)
39997403Sobrien	    __v = __ul;
40097403Sobrien	  else 
40197403Sobrien            __err |= ios_base::failbit;
40297403Sobrien        }
40397403Sobrien
40497403Sobrien      // Parse bool values as alphanumeric
40597403Sobrien      else
40697403Sobrien        {
407102782Skan	  typedef char_traits<_CharT>	      	__traits_type;
408102782Skan	  typedef basic_string<_CharT>   	__string_type;
409102782Skan
41097403Sobrien          locale __loc = __io.getloc();
41197403Sobrien	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
41297403Sobrien	  const __string_type __true = __np.truename();
41397403Sobrien	  const __string_type __false = __np.falsename();
41497403Sobrien          const char_type* __trues = __true.c_str();
41597403Sobrien          const char_type* __falses = __false.c_str();
41697403Sobrien          const size_t __truen =  __true.size() - 1;
41797403Sobrien          const size_t __falsen =  __false.size() - 1;
41897403Sobrien
41997403Sobrien          for (size_t __n = 0; __beg != __end; ++__n)
42097403Sobrien            {
42197403Sobrien              char_type __c = *__beg++;
422102782Skan              bool __testf = __n <= __falsen 
423102782Skan		             ? __traits_type::eq(__c, __falses[__n]) : false;
424102782Skan              bool __testt = __n <= __truen 
425102782Skan		             ? __traits_type::eq(__c, __trues[__n]) : false;
42697403Sobrien              if (!(__testf || __testt))
42797403Sobrien                {
42897403Sobrien                  __err |= ios_base::failbit;
42997403Sobrien                  break;
43097403Sobrien                }
43197403Sobrien              else if (__testf && __n == __falsen)
43297403Sobrien                {
43397403Sobrien                  __v = 0;
43497403Sobrien                  break;
43597403Sobrien                }
43697403Sobrien              else if (__testt && __n == __truen)
43797403Sobrien                {
43897403Sobrien                  __v = 1;
43997403Sobrien                  break;
44097403Sobrien                }
44197403Sobrien            }
44297403Sobrien          if (__beg == __end)
44397403Sobrien            __err |= ios_base::eofbit;
44497403Sobrien        }
44597403Sobrien      return __beg;
44697403Sobrien    }
44797403Sobrien#endif
44897403Sobrien
44997403Sobrien  template<typename _CharT, typename _InIter>
45097403Sobrien    _InIter
45197403Sobrien    num_get<_CharT, _InIter>::
45297403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
45397403Sobrien           ios_base::iostate& __err, long& __v) const
45497403Sobrien    {
45597403Sobrien      string __xtrc;
45697403Sobrien      int __base;
45797403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
45897403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
45997403Sobrien      return __beg;
46097403Sobrien    }
46197403Sobrien
46297403Sobrien  template<typename _CharT, typename _InIter>
46397403Sobrien    _InIter
46497403Sobrien    num_get<_CharT, _InIter>::
46597403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
46697403Sobrien           ios_base::iostate& __err, unsigned short& __v) const
46797403Sobrien    {
46897403Sobrien      string __xtrc;
46997403Sobrien      int __base;
47097403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
47197403Sobrien      unsigned long __ul;
47297403Sobrien      __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
47397403Sobrien      if (!(__err & ios_base::failbit) 
47497403Sobrien	  && __ul <= numeric_limits<unsigned short>::max())
47597403Sobrien	__v = static_cast<unsigned short>(__ul);
47697403Sobrien      else 
47797403Sobrien	__err |= ios_base::failbit;
47897403Sobrien      return __beg;
47997403Sobrien    }
48097403Sobrien
48197403Sobrien  template<typename _CharT, typename _InIter>
48297403Sobrien    _InIter
48397403Sobrien    num_get<_CharT, _InIter>::
48497403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
48597403Sobrien           ios_base::iostate& __err, unsigned int& __v) const
48697403Sobrien    {
48797403Sobrien      string __xtrc;
48897403Sobrien      int __base;
48997403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
49097403Sobrien      unsigned long __ul;
49197403Sobrien      __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
49297403Sobrien      if (!(__err & ios_base::failbit) 
49397403Sobrien	  && __ul <= numeric_limits<unsigned int>::max())
49497403Sobrien	__v = static_cast<unsigned int>(__ul);
49597403Sobrien      else 
49697403Sobrien	__err |= ios_base::failbit;
49797403Sobrien      return __beg;
49897403Sobrien    }
49997403Sobrien
50097403Sobrien  template<typename _CharT, typename _InIter>
50197403Sobrien    _InIter
50297403Sobrien    num_get<_CharT, _InIter>::
50397403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
50497403Sobrien           ios_base::iostate& __err, unsigned long& __v) const
50597403Sobrien    {
50697403Sobrien      string __xtrc;
50797403Sobrien      int __base;
50897403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
50997403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
51097403Sobrien      return __beg;
51197403Sobrien    }
51297403Sobrien
51397403Sobrien#ifdef _GLIBCPP_USE_LONG_LONG
51497403Sobrien  template<typename _CharT, typename _InIter>
51597403Sobrien    _InIter
51697403Sobrien    num_get<_CharT, _InIter>::
51797403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
51897403Sobrien           ios_base::iostate& __err, long long& __v) const
51997403Sobrien    {
52097403Sobrien      string __xtrc;
52197403Sobrien      int __base;
52297403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
52397403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
52497403Sobrien      return __beg;
52597403Sobrien    }
52697403Sobrien
52797403Sobrien  template<typename _CharT, typename _InIter>
52897403Sobrien    _InIter
52997403Sobrien    num_get<_CharT, _InIter>::
53097403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
53197403Sobrien           ios_base::iostate& __err, unsigned long long& __v) const
53297403Sobrien    {
53397403Sobrien      string __xtrc;
53497403Sobrien      int __base;
53597403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
53697403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale, __base);
53797403Sobrien      return __beg;
53897403Sobrien    }
53997403Sobrien#endif
54097403Sobrien
54197403Sobrien  template<typename _CharT, typename _InIter>
54297403Sobrien    _InIter
54397403Sobrien    num_get<_CharT, _InIter>::
54497403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io, 
54597403Sobrien	   ios_base::iostate& __err, float& __v) const
54697403Sobrien    {
54797403Sobrien      string __xtrc;
54897403Sobrien      __xtrc.reserve(32);
54997403Sobrien      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
55097403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
55197403Sobrien      return __beg;
55297403Sobrien    }
55397403Sobrien
55497403Sobrien  template<typename _CharT, typename _InIter>
55597403Sobrien    _InIter
55697403Sobrien    num_get<_CharT, _InIter>::
55797403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
55897403Sobrien           ios_base::iostate& __err, double& __v) const
55997403Sobrien    {
56097403Sobrien      string __xtrc;
56197403Sobrien      __xtrc.reserve(32);
56297403Sobrien      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
56397403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
56497403Sobrien      return __beg;
56597403Sobrien    }
56697403Sobrien
56797403Sobrien  template<typename _CharT, typename _InIter>
56897403Sobrien    _InIter
56997403Sobrien    num_get<_CharT, _InIter>::
57097403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
57197403Sobrien           ios_base::iostate& __err, long double& __v) const
57297403Sobrien    {
57397403Sobrien      string __xtrc;
57497403Sobrien      __xtrc.reserve(32);
57597403Sobrien      __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc);
57697403Sobrien      __convert_to_v(__xtrc.c_str(), __v, __err, _S_c_locale);
57797403Sobrien      return __beg;
57897403Sobrien    }
57997403Sobrien
58097403Sobrien  template<typename _CharT, typename _InIter>
58197403Sobrien    _InIter
58297403Sobrien    num_get<_CharT, _InIter>::
58397403Sobrien    do_get(iter_type __beg, iter_type __end, ios_base& __io,
58497403Sobrien           ios_base::iostate& __err, void*& __v) const
58597403Sobrien    {
58697403Sobrien      // Prepare for hex formatted input
58797403Sobrien      typedef ios_base::fmtflags        fmtflags;
58897403Sobrien      fmtflags __fmt = __io.flags();
58997403Sobrien      fmtflags __fmtmask = ~(ios_base::showpos | ios_base::basefield
59097403Sobrien                             | ios_base::uppercase | ios_base::internal);
59197403Sobrien      __io.flags(__fmt & __fmtmask | (ios_base::hex | ios_base::showbase));
59297403Sobrien
59397403Sobrien      string __xtrc;
59497403Sobrien      int __base;
59597403Sobrien      __beg = _M_extract_int(__beg, __end, __io, __err, __xtrc, __base);
59697403Sobrien
59797403Sobrien      // Reset from hex formatted input
59897403Sobrien      __io.flags(__fmt);
59997403Sobrien
60097403Sobrien      unsigned long __ul;
60197403Sobrien      __convert_to_v(__xtrc.c_str(), __ul, __err, _S_c_locale, __base);
60297403Sobrien      if (!(__err & ios_base::failbit))
60397403Sobrien	__v = reinterpret_cast<void*>(__ul);
60497403Sobrien      else 
60597403Sobrien	__err |= ios_base::failbit;
60697403Sobrien      return __beg;
60797403Sobrien    }
60897403Sobrien
60997403Sobrien  // The following code uses snprintf (or sprintf(), when _GLIBCPP_USE_C99
61097403Sobrien  // is not defined) to convert floating point values for insertion into a
61197403Sobrien  // stream.  An optimization would be to replace them with code that works
61297403Sobrien  // directly on a wide buffer and then use __pad to do the padding.
61397403Sobrien  // It would be good to replace them anyway to gain back the efficiency
61497403Sobrien  // that C++ provides by knowing up front the type of the values to insert.
61597403Sobrien  // Also, sprintf is dangerous since may lead to accidental buffer overruns.
61697403Sobrien  // This implementation follows the C++ standard fairly directly as
61797403Sobrien  // outlined in 22.2.2.2 [lib.locale.num.put]
61897403Sobrien  template<typename _CharT, typename _OutIter>
61997403Sobrien    template<typename _ValueT>
62097403Sobrien      _OutIter
62197403Sobrien      num_put<_CharT, _OutIter>::
62297403Sobrien      _M_convert_float(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
62397403Sobrien		       _ValueT __v) const
62497403Sobrien      {
62597403Sobrien	// Note: digits10 is rounded down.  We need to add 1 to ensure
62697403Sobrien	// we get the full available precision.
62797403Sobrien	const int __max_digits = numeric_limits<_ValueT>::digits10 + 1;
62897403Sobrien	streamsize __prec = __io.precision();
62997403Sobrien
63097403Sobrien	if (__prec > static_cast<streamsize>(__max_digits))
63197403Sobrien	  __prec = static_cast<streamsize>(__max_digits);
63297403Sobrien
63397403Sobrien	// Long enough for the max format spec.
63497403Sobrien	char __fbuf[16];
63597403Sobrien
63697403Sobrien	// [22.2.2.2.2] Stage 1, numeric conversion to character.
63797403Sobrien	int __len;
63897403Sobrien#ifdef _GLIBCPP_USE_C99
63997403Sobrien	// First try a buffer perhaps big enough (for sure sufficient for
64097403Sobrien	// non-ios_base::fixed outputs)
64197403Sobrien	int __cs_size = __max_digits * 3;
64297403Sobrien	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
64397403Sobrien
64497403Sobrien	const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec);
64597403Sobrien	if (__fp)
64697403Sobrien	  __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
64797403Sobrien				   _S_c_locale, __prec);
64897403Sobrien	else
64997403Sobrien	  __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
65097403Sobrien
65197403Sobrien	// If the buffer was not large enough, try again with the correct size.
65297403Sobrien	if (__len >= __cs_size)
65397403Sobrien	  {
65497403Sobrien	    __cs_size = __len + 1; 
65597403Sobrien	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
65697403Sobrien	    if (__fp)
65797403Sobrien	      __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
65897403Sobrien				       _S_c_locale, __prec);
65997403Sobrien	    else
66097403Sobrien	      __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
66197403Sobrien				       _S_c_locale);
66297403Sobrien	  }
66397403Sobrien#else
66497403Sobrien	// Consider the possibility of long ios_base::fixed outputs
66597403Sobrien	const bool __fixed = __io.flags() & ios_base::fixed;
66697403Sobrien	const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
66797403Sobrien	// ios_base::fixed outputs may need up to __max_exp+1 chars
66897403Sobrien	// for the integer part + up to __max_digits chars for the
66997403Sobrien	// fractional part + 3 chars for sign, decimal point, '\0'. On
67097403Sobrien	// the other hand, for non-fixed outputs __max_digits*3 chars
67197403Sobrien	// are largely sufficient.
67297403Sobrien	const int __cs_size = __fixed ? __max_exp + __max_digits + 4 
67397403Sobrien	                              : __max_digits * 3;
67497403Sobrien	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
67597403Sobrien
67697403Sobrien	if (_S_format_float(__io, __fbuf, __mod, __prec))
67797403Sobrien	  __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
67897403Sobrien	else
67997403Sobrien	  __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
68097403Sobrien#endif
68197403Sobrien	return _M_widen_float(__s, __io, __fill, __cs, __len);
68297403Sobrien      }
68397403Sobrien
68497403Sobrien  template<typename _CharT, typename _OutIter>
68597403Sobrien    template<typename _ValueT>
68697403Sobrien      _OutIter
68797403Sobrien      num_put<_CharT, _OutIter>::
68897403Sobrien      _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
68997403Sobrien		     char __modl, _ValueT __v) const
69097403Sobrien      {
69197403Sobrien	// [22.2.2.2.2] Stage 1, numeric conversion to character.
69297403Sobrien
69397403Sobrien	// Long enough for the max format spec.
69497403Sobrien	char __fbuf[16];
69597403Sobrien	_S_format_int(__io, __fbuf, __mod, __modl);
69697403Sobrien#ifdef _GLIBCPP_USE_C99
69797403Sobrien	// First try a buffer perhaps big enough.
69897403Sobrien	int __cs_size = 64;
69997403Sobrien	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
70097403Sobrien	int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
70197403Sobrien				     _S_c_locale);
70297403Sobrien	// If the buffer was not large enough, try again with the correct size.
70397403Sobrien	if (__len >= __cs_size)
70497403Sobrien	  {
70597403Sobrien	    __cs_size = __len + 1;
70697403Sobrien	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
70797403Sobrien	    __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
70897403Sobrien				     _S_c_locale);
70997403Sobrien	  }
71097403Sobrien#else
71197403Sobrien	// Leave room for "+/-," "0x," and commas. This size is
71297403Sobrien	// arbitrary, but should be largely sufficient.
71397403Sobrien	char __cs[128];
71497403Sobrien	int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
71597403Sobrien#endif
71697403Sobrien	return _M_widen_int(__s, __io, __fill, __cs, __len);
71797403Sobrien      }
71897403Sobrien
71997403Sobrien  template<typename _CharT, typename _OutIter>
72097403Sobrien    _OutIter
72197403Sobrien    num_put<_CharT, _OutIter>::
72297403Sobrien    _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
72397403Sobrien		   int __len) const
72497403Sobrien    {
725102782Skan      typedef char_traits<_CharT> 		__traits_type;
72697403Sobrien      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
72797403Sobrien      // numpunct.decimal_point() values for '.' and adding grouping.
72897403Sobrien      const locale __loc = __io.getloc();
72997403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
73097403Sobrien      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
73197403Sobrien							   * __len));
73297403Sobrien      // Grouping can add (almost) as many separators as the number of
73397403Sobrien      // digits, but no more.
73497403Sobrien      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
73597403Sobrien			 				    * __len * 2));
73697403Sobrien      __ctype.widen(__cs, __cs + __len, __ws);
73797403Sobrien      
73897403Sobrien      // Replace decimal point.
73997403Sobrien      const _CharT* __p;
74097403Sobrien      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
741102782Skan      if (__p = __traits_type::find(__ws, __len, __ctype.widen('.')))
74297403Sobrien	__ws[__p - __ws] = __np.decimal_point();
74397403Sobrien
74497403Sobrien#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
74597403Sobrien//282. What types does numpunct grouping refer to?
74697403Sobrien      // Add grouping, if necessary. 
74797403Sobrien      const string __grouping = __np.grouping();
74897403Sobrien      ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
74997403Sobrien      if (__grouping.size())
75097403Sobrien	{
75197403Sobrien	  _CharT* __p2;
75297403Sobrien	  int __declen = __p ? __p - __ws : __len;
75397403Sobrien	  __p2 = __add_grouping(__ws2, __np.thousands_sep(), 
75497403Sobrien				__grouping.c_str(),
75597403Sobrien				__grouping.c_str() + __grouping.size(),
75697403Sobrien				__ws, __ws + __declen);
75797403Sobrien	  int __newlen = __p2 - __ws2;
75897403Sobrien	
75997403Sobrien	  // Tack on decimal part.
76097403Sobrien	  if (__p)
76197403Sobrien	    {
762102782Skan	      __traits_type::copy(__p2, __p, __len - __declen);
76397403Sobrien	      __newlen += __len - __declen;
76497403Sobrien	    }    
76597403Sobrien
76697403Sobrien	  // Switch strings, establish correct new length.
76797403Sobrien	  __ws = __ws2;
76897403Sobrien	  __len = __newlen;
76997403Sobrien	}
77097403Sobrien#endif
77197403Sobrien      return _M_insert(__s, __io, __fill, __ws, __len);
77297403Sobrien    }
77397403Sobrien
77497403Sobrien  template<typename _CharT, typename _OutIter>
77597403Sobrien    _OutIter
77697403Sobrien    num_put<_CharT, _OutIter>::
77797403Sobrien    _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
77897403Sobrien		 int __len) const
77997403Sobrien    {
78097403Sobrien      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
78197403Sobrien      // numpunct.decimal_point() values for '.' and adding grouping.
78297403Sobrien      const locale __loc = __io.getloc();
78397403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
78497403Sobrien      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
78597403Sobrien							   * __len));
78697403Sobrien      // Grouping can add (almost) as many separators as the number of
78797403Sobrien      // digits, but no more.
78897403Sobrien      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
78997403Sobrien							    * __len * 2));
79097403Sobrien      __ctype.widen(__cs, __cs + __len, __ws);
79197403Sobrien
79297403Sobrien      // Add grouping, if necessary. 
79397403Sobrien      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
79497403Sobrien      const string __grouping = __np.grouping();
79597403Sobrien      const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
79697403Sobrien      if (__grouping.size())
79797403Sobrien	{
79897403Sobrien	  // By itself __add_grouping cannot deal correctly with __ws when
79997403Sobrien	  // ios::showbase is set and ios_base::oct || ios_base::hex.
80097403Sobrien	  // Therefore we take care "by hand" of the initial 0, 0x or 0X.
80197403Sobrien	  streamsize __off = 0;
80297403Sobrien	  if (__io.flags() & ios_base::showbase)
80397403Sobrien	    if (__basefield == ios_base::oct)
80497403Sobrien	      {
80597403Sobrien		__off = 1;
80697403Sobrien		*__ws2 = *__ws;
80797403Sobrien	      }
80897403Sobrien	    else if (__basefield == ios_base::hex)
80997403Sobrien	      {
81097403Sobrien		__off = 2;
81197403Sobrien		*__ws2 = *__ws;
81297403Sobrien		*(__ws2 + 1) = *(__ws + 1);
81397403Sobrien	      }
81497403Sobrien	  _CharT* __p;
81597403Sobrien	  __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 
81697403Sobrien			       __grouping.c_str(),
81797403Sobrien			       __grouping.c_str() + __grouping.size(),
81897403Sobrien			       __ws + __off, __ws + __len);
81997403Sobrien	  __len = __p - __ws2;
82097403Sobrien	  // Switch strings.
82197403Sobrien	  __ws = __ws2;
82297403Sobrien	}
82397403Sobrien      return _M_insert(__s, __io, __fill, __ws, __len);
82497403Sobrien    }
82597403Sobrien
82697403Sobrien  // For use by integer and floating-point types after they have been
82797403Sobrien  // converted into a char_type string.
82897403Sobrien  template<typename _CharT, typename _OutIter>
82997403Sobrien    _OutIter
83097403Sobrien    num_put<_CharT, _OutIter>::
83197403Sobrien    _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 
83297403Sobrien	      int __len) const
83397403Sobrien    {
834102782Skan      typedef char_traits<_CharT> 		__traits_type;
83597403Sobrien      // [22.2.2.2.2] Stage 3.
83697403Sobrien      streamsize __w = __io.width();
83797403Sobrien      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
83897403Sobrien							    * __w));
83997403Sobrien      if (__w > static_cast<streamsize>(__len))
84097403Sobrien	{
841102782Skan	  __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 
842102782Skan					       __w, __len, true);
84397403Sobrien	  __len = static_cast<int>(__w);
84497403Sobrien	  // Switch strings.
84597403Sobrien	  __ws = __ws2;
84697403Sobrien	}
84797403Sobrien      __io.width(0);
84897403Sobrien
84997403Sobrien      // [22.2.2.2.2] Stage 4.
85097403Sobrien      // Write resulting, fully-formatted string to output iterator.
85197403Sobrien      for (int __j = 0; __j < __len; ++__j, ++__s)
85297403Sobrien	*__s = __ws[__j];
85397403Sobrien      return __s;
85497403Sobrien    }
85597403Sobrien
85697403Sobrien  template<typename _CharT, typename _OutIter>
85797403Sobrien    _OutIter
85897403Sobrien    num_put<_CharT, _OutIter>::
85997403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
86097403Sobrien    {
86197403Sobrien      ios_base::fmtflags __flags = __io.flags();
86297403Sobrien      if ((__flags & ios_base::boolalpha) == 0)
86397403Sobrien        {
86497403Sobrien          unsigned long __uv = __v;
865102782Skan          __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv);
86697403Sobrien        }
86797403Sobrien      else
86897403Sobrien        {
86997403Sobrien	  typedef basic_string<_CharT> __string_type;
87097403Sobrien          locale __loc = __io.getloc();
87197403Sobrien	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
87297403Sobrien	  __string_type __name;
87397403Sobrien          if (__v)
87497403Sobrien	    __name = __np.truename();
87597403Sobrien          else
87697403Sobrien	    __name = __np.falsename();
87797403Sobrien	  __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); 
87897403Sobrien	}
87997403Sobrien      return __s;
88097403Sobrien    }
88197403Sobrien
88297403Sobrien  template<typename _CharT, typename _OutIter>
88397403Sobrien    _OutIter
88497403Sobrien    num_put<_CharT, _OutIter>::
88597403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
886102782Skan    { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); }
88797403Sobrien
88897403Sobrien  template<typename _CharT, typename _OutIter>
88997403Sobrien    _OutIter
89097403Sobrien    num_put<_CharT, _OutIter>::
89197403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
89297403Sobrien           unsigned long __v) const
893102782Skan    { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); }
89497403Sobrien
89597403Sobrien#ifdef _GLIBCPP_USE_LONG_LONG
89697403Sobrien  template<typename _CharT, typename _OutIter>
89797403Sobrien    _OutIter
89897403Sobrien    num_put<_CharT, _OutIter>::
89997403Sobrien    do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
90097403Sobrien    { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); }
90197403Sobrien
90297403Sobrien  template<typename _CharT, typename _OutIter>
90397403Sobrien    _OutIter
90497403Sobrien    num_put<_CharT, _OutIter>::
90597403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
90697403Sobrien           unsigned long long __v) const
90797403Sobrien    { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); }
90897403Sobrien#endif
90997403Sobrien
91097403Sobrien  template<typename _CharT, typename _OutIter>
91197403Sobrien    _OutIter
91297403Sobrien    num_put<_CharT, _OutIter>::
91397403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
914102782Skan    { return _M_convert_float(__s, __io, __fill, char(), __v); }
91597403Sobrien
91697403Sobrien  template<typename _CharT, typename _OutIter>
91797403Sobrien    _OutIter
91897403Sobrien    num_put<_CharT, _OutIter>::
91997403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, 
92097403Sobrien	   long double __v) const
92197403Sobrien    { return _M_convert_float(__s, __io, __fill, 'L', __v); }
92297403Sobrien
92397403Sobrien  template<typename _CharT, typename _OutIter>
92497403Sobrien    _OutIter
92597403Sobrien    num_put<_CharT, _OutIter>::
92697403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
92797403Sobrien           const void* __v) const
92897403Sobrien    {
92997403Sobrien      ios_base::fmtflags __flags = __io.flags();
93097403Sobrien      ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
93197403Sobrien				   | ios_base::uppercase | ios_base::internal);
93297403Sobrien      __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
93397403Sobrien      try 
93497403Sobrien	{
935102782Skan	  __s = _M_convert_int(__s, __io, __fill, 'u', char(),
93697403Sobrien			       reinterpret_cast<unsigned long>(__v));
93797403Sobrien	  __io.flags(__flags);
93897403Sobrien	}
93997403Sobrien      catch (...) 
94097403Sobrien	{
94197403Sobrien	  __io.flags(__flags);
94297403Sobrien	  __throw_exception_again;
94397403Sobrien	}
94497403Sobrien      return __s;
94597403Sobrien    }
94697403Sobrien
94797403Sobrien
94897403Sobrien  template<typename _CharT, typename _InIter>
94997403Sobrien    _InIter
95097403Sobrien    money_get<_CharT, _InIter>::
95197403Sobrien    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 
95297403Sobrien	   ios_base::iostate& __err, long double& __units) const
95397403Sobrien    { 
95497403Sobrien      string_type __str;
95597403Sobrien      __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 
95697403Sobrien
95797403Sobrien      const int __n = numeric_limits<long double>::digits10;
95897403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__n));
95997403Sobrien      const locale __loc = __io.getloc();
96097403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
96197403Sobrien      const _CharT* __wcs = __str.c_str();
96297403Sobrien      __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);      
96397403Sobrien      __convert_to_v(__cs, __units, __err, _S_c_locale);
96497403Sobrien      return __beg;
96597403Sobrien    }
96697403Sobrien
96797403Sobrien  template<typename _CharT, typename _InIter>
96897403Sobrien    _InIter
96997403Sobrien    money_get<_CharT, _InIter>::
97097403Sobrien    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 
97197403Sobrien	   ios_base::iostate& __err, string_type& __units) const
97297403Sobrien    { 
97397403Sobrien      // These contortions are quite unfortunate.
97497403Sobrien      typedef moneypunct<_CharT, true> 		__money_true;
97597403Sobrien      typedef moneypunct<_CharT, false> 	__money_false;
97697403Sobrien      typedef money_base::part 			part;
97797403Sobrien      typedef typename string_type::size_type 	size_type;
97897403Sobrien
97997403Sobrien      const locale __loc = __io.getloc();
98097403Sobrien      const __money_true& __mpt = use_facet<__money_true>(__loc); 
98197403Sobrien      const __money_false& __mpf = use_facet<__money_false>(__loc); 
98297403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
98397403Sobrien
98497403Sobrien      const money_base::pattern __p = __intl ? __mpt.neg_format() 
98597403Sobrien					     : __mpf.neg_format();
98697403Sobrien
98797403Sobrien      const string_type __pos_sign =__intl ? __mpt.positive_sign() 
98897403Sobrien					   : __mpf.positive_sign();
98997403Sobrien      const string_type __neg_sign =__intl ? __mpt.negative_sign() 
99097403Sobrien					   : __mpf.negative_sign();
99197403Sobrien      const char_type __d = __intl ? __mpt.decimal_point() 
99297403Sobrien  	    	       		   : __mpf.decimal_point();
99397403Sobrien      const char_type __sep = __intl ? __mpt.thousands_sep() 
99497403Sobrien		    		     : __mpf.thousands_sep();
99597403Sobrien
99697403Sobrien      const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
99797403Sobrien
99897403Sobrien      // Set to deduced positive or negative sign, depending.
99997403Sobrien      string_type __sign;
100097403Sobrien      // String of grouping info from thousands_sep plucked from __units.
100197403Sobrien      string __grouping_tmp; 
100297403Sobrien      // Marker for thousands_sep position.
100397403Sobrien      int __sep_pos = 0;
100497403Sobrien      // If input iterator is in a valid state.
100597403Sobrien      bool __testvalid = true;
100697403Sobrien      // Flag marking when a decimal point is found.
100797403Sobrien      bool __testdecfound = false; 
100897403Sobrien
100997403Sobrien      // The tentative returned string is stored here.
101097403Sobrien      string_type __temp_units;
101197403Sobrien
101297403Sobrien      char_type __c = *__beg;
101397403Sobrien      char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
101497403Sobrien      for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
101597403Sobrien	{
101697403Sobrien	  part __which = static_cast<part>(__p.field[__i]);
101797403Sobrien	  switch (__which)
101897403Sobrien		{
101997403Sobrien		case money_base::symbol:
102097403Sobrien		  if (__io.flags() & ios_base::showbase 
102197403Sobrien		      || __i < 2 || __sign.size() > 1
102297403Sobrien		      || ((static_cast<part>(__p.field[3]) != money_base::none)
102397403Sobrien			  && __i == 2)) 
102497403Sobrien		    {
102597403Sobrien		      // According to 22.2.6.1.2.2, symbol is required
102697403Sobrien		      // if (__io.flags() & ios_base::showbase),
102797403Sobrien		      // otherwise is optional and consumed only if
102897403Sobrien		      // other characters are needed to complete the
102997403Sobrien		      // format.
103097403Sobrien		      const string_type __symbol = __intl ? __mpt.curr_symbol()
103197403Sobrien						    	 : __mpf.curr_symbol();
103297403Sobrien		      size_type __len = __symbol.size();
103397403Sobrien		      size_type __j = 0;
103497403Sobrien		      while (__beg != __end 
103597403Sobrien			     && __j < __len && __symbol[__j] == __c)
103697403Sobrien			{
103797403Sobrien			  __c = *(++__beg);
103897403Sobrien			  ++__j;
103997403Sobrien			}
104097403Sobrien		      // When (__io.flags() & ios_base::showbase)
104197403Sobrien		      // symbol is required.
104297403Sobrien		      if (__j != __len && (__io.flags() & ios_base::showbase))
104397403Sobrien			__testvalid = false;
104497403Sobrien		    }
104597403Sobrien		  break;
104697403Sobrien		case money_base::sign:		    
104797403Sobrien		  // Sign might not exist, or be more than one character long. 
104897403Sobrien		  if (__pos_sign.size() && __neg_sign.size())
104997403Sobrien		  {
105097403Sobrien		    // Sign is mandatory.
105197403Sobrien		    if (__c == __pos_sign[0])
105297403Sobrien		      {
105397403Sobrien			__sign = __pos_sign;
105497403Sobrien			__c = *(++__beg);
105597403Sobrien		      }
105697403Sobrien		    else if (__c == __neg_sign[0])
105797403Sobrien		      {
105897403Sobrien			__sign = __neg_sign;
105997403Sobrien			__c = *(++__beg);
106097403Sobrien		      }
106197403Sobrien		    else
106297403Sobrien		      __testvalid = false;
106397403Sobrien		  }
106497403Sobrien		  else if (__pos_sign.size() && __c == __pos_sign[0])
106597403Sobrien		    {
106697403Sobrien		      __sign = __pos_sign;
106797403Sobrien		      __c = *(++__beg);
106897403Sobrien		    }
106997403Sobrien		  else if (__neg_sign.size() && __c == __neg_sign[0])
107097403Sobrien		    {
107197403Sobrien		      __sign = __neg_sign;
107297403Sobrien		      __c = *(++__beg);
107397403Sobrien		    }
107497403Sobrien		  break;
107597403Sobrien		case money_base::value:
107697403Sobrien		  // Extract digits, remove and stash away the
107797403Sobrien		  // grouping of found thousands separators.
107897403Sobrien		  while (__beg != __end 
107997403Sobrien			 && (__ctype.is(ctype_base::digit, __c) 
108097403Sobrien			     || (__c == __d && !__testdecfound)
108197403Sobrien			     || __c == __sep))
108297403Sobrien		    {
108397403Sobrien		      if (__c == __d)
108497403Sobrien			{
108597403Sobrien			  __grouping_tmp += static_cast<char>(__sep_pos);
108697403Sobrien			  __sep_pos = 0;
108797403Sobrien			  __testdecfound = true;
108897403Sobrien			}
108997403Sobrien		      else if (__c == __sep)
109097403Sobrien			{
109197403Sobrien			  if (__grouping.size())
109297403Sobrien			    {
109397403Sobrien			      // Mark position for later analysis.
109497403Sobrien			      __grouping_tmp += static_cast<char>(__sep_pos);
109597403Sobrien			      __sep_pos = 0;
109697403Sobrien			    }
109797403Sobrien			  else
109897403Sobrien			    {
109997403Sobrien			      __testvalid = false;
110097403Sobrien			      break;
110197403Sobrien			    }
110297403Sobrien			}
110397403Sobrien		      else
110497403Sobrien			{
110597403Sobrien			  __temp_units += __c;
110697403Sobrien			  ++__sep_pos;
110797403Sobrien			}
110897403Sobrien		      __c = *(++__beg);
110997403Sobrien		    }
111097403Sobrien		  break;
111197403Sobrien		case money_base::space:
111297403Sobrien		case money_base::none:
111397403Sobrien		  // Only if not at the end of the pattern.
111497403Sobrien		  if (__i != 3)
111597403Sobrien		    while (__beg != __end 
111697403Sobrien			   && __ctype.is(ctype_base::space, __c))
111797403Sobrien		      __c = *(++__beg);
111897403Sobrien		  break;
111997403Sobrien		}
112097403Sobrien	}
112197403Sobrien
112297403Sobrien      // Need to get the rest of the sign characters, if they exist.
112397403Sobrien      if (__sign.size() > 1)
112497403Sobrien	{
112597403Sobrien	  size_type __len = __sign.size();
112697403Sobrien	  size_type __i = 1;
112797403Sobrien	  for (; __c != __eof && __i < __len; ++__i)
112897403Sobrien	    while (__beg != __end && __c != __sign[__i])
112997403Sobrien	      __c = *(++__beg);
113097403Sobrien	  
113197403Sobrien	  if (__i != __len)
113297403Sobrien	    __testvalid = false;
113397403Sobrien	}
113497403Sobrien
113597403Sobrien      // Strip leading zeros.
113697403Sobrien      while (__temp_units[0] == __ctype.widen('0'))
113797403Sobrien	__temp_units.erase(__temp_units.begin());
113897403Sobrien
113997403Sobrien      if (__sign.size() && __sign == __neg_sign)
114097403Sobrien	__temp_units.insert(__temp_units.begin(), __ctype.widen('-'));
114197403Sobrien
114297403Sobrien      // Test for grouping fidelity.
114397403Sobrien      if (__grouping.size() && __grouping_tmp.size())
114497403Sobrien	{
114597403Sobrien	  if (!__verify_grouping(__grouping, __grouping_tmp))
114697403Sobrien	    __testvalid = false;
114797403Sobrien	}
114897403Sobrien
114997403Sobrien      // Iff no more characters are available.      
115097403Sobrien      if (__c == __eof)
115197403Sobrien	__err |= ios_base::eofbit;
115297403Sobrien
115397403Sobrien      // Iff valid sequence is not recognized.
115497403Sobrien      if (!__testvalid || !__temp_units.size())
115597403Sobrien	__err |= ios_base::failbit;
115697403Sobrien      else
115797403Sobrien	// Use the "swap trick" to copy __temp_units into __units.
115897403Sobrien	__temp_units.swap(__units);
115997403Sobrien
116097403Sobrien      return __beg; 
116197403Sobrien    }
116297403Sobrien
116397403Sobrien  template<typename _CharT, typename _OutIter>
116497403Sobrien    _OutIter
116597403Sobrien    money_put<_CharT, _OutIter>::
116697403Sobrien    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
116797403Sobrien	   long double __units) const
116897403Sobrien    { 
116997403Sobrien      const locale __loc = __io.getloc();
117097403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
117197403Sobrien#ifdef _GLIBCPP_USE_C99
117297403Sobrien      // First try a buffer perhaps big enough.
117397403Sobrien      int __cs_size = 64;
117497403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
117597403Sobrien      int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 
117697403Sobrien				   _S_c_locale);
117797403Sobrien      // If the buffer was not large enough, try again with the correct size.
117897403Sobrien      if (__len >= __cs_size)
117997403Sobrien	{
118097403Sobrien	  __cs_size = __len + 1;
118197403Sobrien	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
118297403Sobrien	  __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 
118397403Sobrien				   _S_c_locale);
118497403Sobrien	}
118597403Sobrien#else
118697403Sobrien      // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point,
118797403Sobrien      // decimal digit, '\0'. 
118897403Sobrien      const int __cs_size = numeric_limits<long double>::max_exponent10 + 5;
118997403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
119097403Sobrien      int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale);
119197403Sobrien#endif
119297403Sobrien      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size));
119397403Sobrien      __ctype.widen(__cs, __cs + __len, __ws);
119497403Sobrien      string_type __digits(__ws);
119597403Sobrien      return this->do_put(__s, __intl, __io, __fill, __digits); 
119697403Sobrien    }
119797403Sobrien
119897403Sobrien  template<typename _CharT, typename _OutIter>
119997403Sobrien    _OutIter
120097403Sobrien    money_put<_CharT, _OutIter>::
120197403Sobrien    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
120297403Sobrien	   const string_type& __digits) const
120397403Sobrien    { 
120497403Sobrien      typedef typename string_type::size_type 	size_type;
120597403Sobrien      typedef money_base::part 			part;
120697403Sobrien
120797403Sobrien      const locale __loc = __io.getloc();
120897403Sobrien      const size_type __width = static_cast<size_type>(__io.width());
120997403Sobrien
121097403Sobrien      // These contortions are quite unfortunate.
121197403Sobrien      typedef moneypunct<_CharT, true> __money_true;
121297403Sobrien      typedef moneypunct<_CharT, false> __money_false;
121397403Sobrien      const __money_true& __mpt = use_facet<__money_true>(__loc); 
121497403Sobrien      const __money_false& __mpf = use_facet<__money_false>(__loc); 
121597403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
121697403Sobrien
121797403Sobrien      // Determine if negative or positive formats are to be used, and
121897403Sobrien      // discard leading negative_sign if it is present.
121997403Sobrien      const char_type* __beg = __digits.data();
122097403Sobrien      const char_type* __end = __beg + __digits.size();
122197403Sobrien      money_base::pattern __p;
122297403Sobrien      string_type __sign;
122397403Sobrien      if (*__beg != __ctype.widen('-'))
122497403Sobrien	{
122597403Sobrien	  __p = __intl ? __mpt.pos_format() : __mpf.pos_format();
122697403Sobrien	  __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
122797403Sobrien	}
122897403Sobrien      else
122997403Sobrien	{
123097403Sobrien	  __p = __intl ? __mpt.neg_format() : __mpf.neg_format();
123197403Sobrien	  __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
123297403Sobrien	  ++__beg;
123397403Sobrien	}
123497403Sobrien      
123597403Sobrien      // Look for valid numbers in the current ctype facet within input digits.
123697403Sobrien      __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
123797403Sobrien      if (__beg != __end)
123897403Sobrien	{
123997403Sobrien	  // Assume valid input, and attempt to format.
124097403Sobrien	  // Break down input numbers into base components, as follows:
124197403Sobrien	  //   final_value = grouped units + (decimal point) + (digits)
124297403Sobrien	  string_type __res;
124397403Sobrien	  string_type __value;
124497403Sobrien	  const string_type __symbol = __intl ? __mpt.curr_symbol() 
124597403Sobrien	    				      : __mpf.curr_symbol();
124697403Sobrien
124797403Sobrien	  // Deal with decimal point, decimal digits.
124897403Sobrien	  const int __frac = __intl ? __mpt.frac_digits() 
124997403Sobrien	    			    : __mpf.frac_digits();
125097403Sobrien	  if (__frac > 0)
125197403Sobrien	    {
125297403Sobrien	      const char_type __d = __intl ? __mpt.decimal_point() 
125397403Sobrien					   : __mpf.decimal_point();
125497403Sobrien	      if (__end - __beg >= __frac)
125597403Sobrien		{
125697403Sobrien		  __value = string_type(__end - __frac, __end);
125797403Sobrien		  __value.insert(__value.begin(), __d);
125897403Sobrien		  __end -= __frac;
125997403Sobrien		}
126097403Sobrien	      else
126197403Sobrien		{
126297403Sobrien		  // Have to pad zeros in the decimal position.
126397403Sobrien		  __value = string_type(__beg, __end);
126497403Sobrien		  int __paddec = __frac - (__end - __beg);
126597403Sobrien		  char_type __zero = __ctype.widen('0');
126697403Sobrien		  __value.insert(__value.begin(), __paddec, __zero);
126797403Sobrien		  __value.insert(__value.begin(), __d);
126897403Sobrien		  __beg = __end;
126997403Sobrien		}
127097403Sobrien	    }
127197403Sobrien
127297403Sobrien	  // Add thousands separators to non-decimal digits, per
127397403Sobrien	  // grouping rules.
127497403Sobrien	  if (__beg != __end)
127597403Sobrien	    {
127697403Sobrien	      const string __grouping = __intl ? __mpt.grouping() 
127797403Sobrien					       : __mpf.grouping();
127897403Sobrien	      if (__grouping.size())
127997403Sobrien		{
128097403Sobrien		  const char_type __sep = __intl ? __mpt.thousands_sep() 
128197403Sobrien		    			         : __mpf.thousands_sep();
128297403Sobrien		  const char* __gbeg = __grouping.c_str();
128397403Sobrien		  const char* __gend = __gbeg + __grouping.size();
128497403Sobrien		  const int __n = (__end - __beg) * 2;
128597403Sobrien		  _CharT* __ws2 =
128697403Sobrien		    static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
128797403Sobrien		  _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 
128897403Sobrien						    __gend, __beg, __end);
128997403Sobrien		  __value.insert(0, __ws2, __ws_end - __ws2);
129097403Sobrien		}
129197403Sobrien	      else
129297403Sobrien		__value.insert(0, string_type(__beg, __end));
129397403Sobrien	    }
129497403Sobrien
129597403Sobrien	  // Calculate length of resulting string.
129697403Sobrien	  ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
129797403Sobrien	  size_type __len = __value.size() + __sign.size();
129897403Sobrien	  __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
129997403Sobrien	  bool __testipad = __f == ios_base::internal && __len < __width;
130097403Sobrien
130197403Sobrien	  // Fit formatted digits into the required pattern.
130297403Sobrien	  for (int __i = 0; __i < 4; ++__i)
130397403Sobrien	    {
130497403Sobrien	      part __which = static_cast<part>(__p.field[__i]);
130597403Sobrien	      switch (__which)
130697403Sobrien		{
130797403Sobrien		case money_base::symbol:
130897403Sobrien		  if (__io.flags() & ios_base::showbase)
130997403Sobrien		    __res += __symbol;
131097403Sobrien		  break;
131197403Sobrien		case money_base::sign:		    
131297403Sobrien		  // Sign might not exist, or be more than one
131397403Sobrien		  // charater long. In that case, add in the rest
131497403Sobrien		  // below.
131597403Sobrien		  if (__sign.size())
131697403Sobrien		    __res += __sign[0];
131797403Sobrien		  break;
131897403Sobrien		case money_base::value:
131997403Sobrien		  __res += __value;
132097403Sobrien		  break;
132197403Sobrien		case money_base::space:
132297403Sobrien		  // At least one space is required, but if internal
132397403Sobrien		  // formatting is required, an arbitrary number of
132497403Sobrien		  // fill spaces will be necessary.
132597403Sobrien		  if (__testipad)
132697403Sobrien		    __res += string_type(__width - __len, __fill);
132797403Sobrien		  else
132897403Sobrien		    __res += __ctype.widen(__fill);
132997403Sobrien		  break;
133097403Sobrien		case money_base::none:
133197403Sobrien		  if (__testipad)
133297403Sobrien		    __res += string_type(__width - __len, __fill);
133397403Sobrien		  break;
133497403Sobrien		}
133597403Sobrien	    }
133697403Sobrien
133797403Sobrien	  // Special case of multi-part sign parts.
133897403Sobrien	  if (__sign.size() > 1)
133997403Sobrien	    __res += string_type(__sign.begin() + 1, __sign.end());
134097403Sobrien
134197403Sobrien	  // Pad, if still necessary.
134297403Sobrien	  __len = __res.size();
134397403Sobrien	  if (__width > __len)
134497403Sobrien	    {
134597403Sobrien	      if (__f == ios_base::left)
134697403Sobrien		// After.
134797403Sobrien		__res.append(__width - __len, __fill);
134897403Sobrien	      else
134997403Sobrien		// Before.
135097403Sobrien		__res.insert(0, string_type(__width - __len, __fill));
135197403Sobrien	      __len = __width;
135297403Sobrien	    }
135397403Sobrien
135497403Sobrien	  // Write resulting, fully-formatted string to output iterator.
135597403Sobrien	  for (size_type __j = 0; __j < __len; ++__j, ++__s)
135697403Sobrien	    *__s = __res[__j];
135797403Sobrien	}
135897403Sobrien      __io.width(0);
135997403Sobrien      return __s; 
136097403Sobrien    }
136197403Sobrien
136297403Sobrien
136397403Sobrien  // NB: Not especially useful. Without an ios_base object or some
136497403Sobrien  // kind of locale reference, we are left clawing at the air where
136597403Sobrien  // the side of the mountain used to be...
136697403Sobrien  template<typename _CharT, typename _InIter>
136797403Sobrien    time_base::dateorder
136897403Sobrien    time_get<_CharT, _InIter>::do_date_order() const
136997403Sobrien    { return time_base::no_order; }
137097403Sobrien
137197403Sobrien  template<typename _CharT, typename _InIter>
137297403Sobrien    void
137397403Sobrien    time_get<_CharT, _InIter>::
137497403Sobrien    _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
137597403Sobrien			  ios_base::iostate& __err, tm* __tm, 
137697403Sobrien			  const _CharT* __format) const
137797403Sobrien    {  
137897403Sobrien      locale __loc = __io.getloc();
137997403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
138097403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
138197403Sobrien      size_t __len = char_traits<_CharT>::length(__format);
138297403Sobrien
138397403Sobrien      for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
138497403Sobrien	{
138597403Sobrien	  char __c = __format[__i];
138697403Sobrien	  if (__c == '%')
138797403Sobrien	    {
138897403Sobrien	      // Verify valid formatting code, attempt to extract.
138997403Sobrien	      __c = __format[++__i];
139097403Sobrien	      char __mod = 0;
139197403Sobrien	      int __mem = 0; 
139297403Sobrien	      if (__c == 'E' || __c == 'O')
139397403Sobrien		{
139497403Sobrien		  __mod = __c;
139597403Sobrien		  __c = __format[++__i];
139697403Sobrien		}
139797403Sobrien	      switch (__c)
139897403Sobrien		{
139997403Sobrien		  const char* __cs;
140097403Sobrien		  _CharT __wcs[10];
140197403Sobrien		case 'a':
140297403Sobrien		  // Abbreviated weekday name [tm_wday]
140397403Sobrien		  const char_type*  __days1[7];
140497403Sobrien		  __tp._M_days_abbreviated(__days1);
140597403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 
140697403Sobrien				  __err);
140797403Sobrien		  break;
140897403Sobrien		case 'A':
140997403Sobrien		  // Weekday name [tm_wday].
141097403Sobrien		  const char_type*  __days2[7];
141197403Sobrien		  __tp._M_days(__days2);
141297403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 
141397403Sobrien				  __err);
141497403Sobrien		  break;
141597403Sobrien		case 'h':
141697403Sobrien		case 'b':
141797403Sobrien		  // Abbreviated month name [tm_mon]
141897403Sobrien		  const char_type*  __months1[12];
141997403Sobrien		  __tp._M_months_abbreviated(__months1);
142097403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 
142197403Sobrien				  __err);
142297403Sobrien		  break;
142397403Sobrien		case 'B':
142497403Sobrien		  // Month name [tm_mon].
142597403Sobrien		  const char_type*  __months2[12];
142697403Sobrien		  __tp._M_months(__months2);
142797403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 
142897403Sobrien				  __err);
142997403Sobrien		  break;
143097403Sobrien		case 'c':
143197403Sobrien		  // Default time and date representation.
143297403Sobrien		  const char_type*  __dt[2];
143397403Sobrien		  __tp._M_date_time_formats(__dt);
143497403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
143597403Sobrien					__dt[0]);
143697403Sobrien		  break;
143797403Sobrien		case 'd':
143897403Sobrien		  // Day [01, 31]. [tm_mday]
143997403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 
144097403Sobrien				 __ctype, __err);
144197403Sobrien		  break;
144297403Sobrien		case 'D':
144397403Sobrien		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
144497403Sobrien		  __cs = "%m/%d/%y";
144597403Sobrien		  __ctype.widen(__cs, __cs + 9, __wcs);
144697403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
144797403Sobrien					__wcs);
144897403Sobrien		  break;
144997403Sobrien		case 'H':
145097403Sobrien		  // Hour [00, 23]. [tm_hour]
145197403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
145297403Sobrien				 __ctype, __err);
145397403Sobrien		  break;
145497403Sobrien		case 'I':
145597403Sobrien		  // Hour [01, 12]. [tm_hour]
145697403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 
145797403Sobrien				 __ctype, __err);
145897403Sobrien		  break;
145997403Sobrien		case 'm':
146097403Sobrien		  // Month [01, 12]. [tm_mon]
146197403Sobrien		  _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 
146297403Sobrien				 __err);
146397403Sobrien		  if (!__err)
146497403Sobrien		    __tm->tm_mon = __mem - 1;
146597403Sobrien		  break;
146697403Sobrien		case 'M':
146797403Sobrien		  // Minute [00, 59]. [tm_min]
146897403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
146997403Sobrien				 __ctype, __err);
147097403Sobrien		  break;
147197403Sobrien		case 'n':
147297403Sobrien		  if (__ctype.narrow(*__beg, 0) == '\n')
147397403Sobrien		    ++__beg;
147497403Sobrien		  else
147597403Sobrien		    __err |= ios_base::failbit;
147697403Sobrien		  break;
147797403Sobrien		case 'R':
147897403Sobrien		  // Equivalent to (%H:%M).
147997403Sobrien		  __cs = "%H:%M";
148097403Sobrien		  __ctype.widen(__cs, __cs + 6, __wcs);
148197403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
148297403Sobrien					__wcs);
148397403Sobrien		  break;
148497403Sobrien		case 'S':
148597403Sobrien		  // Seconds.
148697403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
148797403Sobrien				 __ctype, __err);
148897403Sobrien		  break;
148997403Sobrien		case 't':
149097403Sobrien		  if (__ctype.narrow(*__beg, 0) == '\t')
149197403Sobrien		    ++__beg;
149297403Sobrien		  else
149397403Sobrien		__err |= ios_base::failbit;
149497403Sobrien		  break;
149597403Sobrien		case 'T':
149697403Sobrien		  // Equivalent to (%H:%M:%S).
149797403Sobrien		  __cs = "%H:%M:%S";
149897403Sobrien		  __ctype.widen(__cs, __cs + 9, __wcs);
149997403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
150097403Sobrien					__wcs);
150197403Sobrien		  break;
150297403Sobrien		case 'x':
150397403Sobrien		  // Locale's date.
150497403Sobrien		  const char_type*  __dates[2];
150597403Sobrien		  __tp._M_date_formats(__dates);
150697403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
150797403Sobrien					__dates[0]);
150897403Sobrien		  break;
150997403Sobrien		case 'X':
151097403Sobrien		  // Locale's time.
151197403Sobrien		  const char_type*  __times[2];
151297403Sobrien		  __tp._M_time_formats(__times);
151397403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
151497403Sobrien					__times[0]);
151597403Sobrien		  break;
151697403Sobrien		case 'y':
151797403Sobrien		  // Two digit year. [tm_year]
151897403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 
151997403Sobrien				 __ctype, __err);
152097403Sobrien		  break;
152197403Sobrien		case 'Y':
152297403Sobrien		  // Year [1900). [tm_year]
152397403Sobrien		  _M_extract_num(__beg, __end, __mem, 0, 
152497403Sobrien				 numeric_limits<int>::max(), 4, 
152597403Sobrien				 __ctype, __err);
152697403Sobrien		  if (!__err)
152797403Sobrien		    __tm->tm_year = __mem - 1900;
152897403Sobrien		  break;
152997403Sobrien		case 'Z':
153097403Sobrien		  // Timezone info.
153197403Sobrien		  if (__ctype.is(ctype_base::upper, *__beg))
153297403Sobrien		    {
153397403Sobrien		      int __tmp;
153497403Sobrien		      _M_extract_name(__beg, __end, __tmp, 
153597403Sobrien				      __timepunct<_CharT>::_S_timezones, 
153697403Sobrien				      14, __err);
153797403Sobrien		      
153897403Sobrien		      // GMT requires special effort.
153997403Sobrien		      char_type __c = *__beg;
154097403Sobrien		      if (!__err && __tmp == 0 
154197403Sobrien			  && (__c == __ctype.widen('-') 
154297403Sobrien			      || __c == __ctype.widen('+')))
154397403Sobrien			{
154497403Sobrien			  _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
154597403Sobrien					  __ctype, __err);
154697403Sobrien			  _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
154797403Sobrien					  __ctype, __err);
154897403Sobrien			}	    
154997403Sobrien			  }
155097403Sobrien		      else
155197403Sobrien			__err |= ios_base::failbit;
155297403Sobrien		      break;
155397403Sobrien		    default:
155497403Sobrien		      // Not recognized.
155597403Sobrien		      __err |= ios_base::failbit;
155697403Sobrien		    }
155797403Sobrien		}
155897403Sobrien	      else
155997403Sobrien		{
156097403Sobrien		  // Verify format and input match, extract and discard.
156197403Sobrien		  if (__c == __ctype.narrow(*__beg, 0))
156297403Sobrien		    ++__beg;
156397403Sobrien		  else
156497403Sobrien		    __err |= ios_base::failbit;
156597403Sobrien		}
156697403Sobrien	}
156797403Sobrien    }
156897403Sobrien
156997403Sobrien  template<typename _CharT, typename _InIter>
157097403Sobrien    void
157197403Sobrien    time_get<_CharT, _InIter>::
157297403Sobrien    _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
157397403Sobrien		   int __min, int __max, size_t __len, 
157497403Sobrien		   const ctype<_CharT>& __ctype, 
157597403Sobrien		   ios_base::iostate& __err) const
157697403Sobrien    {
157797403Sobrien      size_t __i = 0;
157897403Sobrien      string __digits;
157997403Sobrien      bool __testvalid = true;
158097403Sobrien      char_type __c = *__beg;
158197403Sobrien      while (__beg != __end && __i < __len 
158297403Sobrien	     && __ctype.is(ctype_base::digit, __c)) 
158397403Sobrien	{
158497403Sobrien	  __digits += __ctype.narrow(__c, 0);
158597403Sobrien	  __c = *(++__beg);
158697403Sobrien	  ++__i;
158797403Sobrien	}
158897403Sobrien      if (__i == __len)
158997403Sobrien	{
159097403Sobrien	  int __value = atoi(__digits.c_str());
159197403Sobrien	  if (__min <= __value && __value <= __max)
159297403Sobrien	    __member = __value;
159397403Sobrien	  else
159497403Sobrien	    __testvalid = false;
159597403Sobrien	}
159697403Sobrien      else
159797403Sobrien	__testvalid = false;
159897403Sobrien      if (!__testvalid)
159997403Sobrien	__err |= ios_base::failbit;
160097403Sobrien    }
160197403Sobrien
160297403Sobrien  // Assumptions:
160397403Sobrien  // All elements in __names are unique.
160497403Sobrien  template<typename _CharT, typename _InIter>
160597403Sobrien    void
160697403Sobrien    time_get<_CharT, _InIter>::
160797403Sobrien    _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
160897403Sobrien		    const _CharT** __names, size_t __indexlen, 
160997403Sobrien		    ios_base::iostate& __err) const
161097403Sobrien    {
1611102782Skan      typedef char_traits<_CharT> 		__traits_type;
161297403Sobrien      int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen));
161397403Sobrien      size_t __nmatches = 0;
161497403Sobrien      size_t __pos = 0;
161597403Sobrien      bool __testvalid = true;
161697403Sobrien      const char_type* __name;
161797403Sobrien
161897403Sobrien      char_type __c = *__beg;
161997403Sobrien      // Look for initial matches.
162097403Sobrien      for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
162197403Sobrien	if (__c == __names[__i1][0])
162297403Sobrien	  __matches[__nmatches++] = __i1;
162397403Sobrien      
162497403Sobrien      while(__nmatches > 1)
162597403Sobrien	{
162697403Sobrien	  // Find smallest matching string.
162797403Sobrien	  size_t __minlen = 10;
162897403Sobrien	  for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
162997403Sobrien	    __minlen = min(__minlen, 
163097403Sobrien			   __traits_type::length(__names[__matches[__i2]]));
163197403Sobrien	  
163297403Sobrien	  if (__pos < __minlen && __beg != __end)
163397403Sobrien	    {
163497403Sobrien	      ++__pos;
163597403Sobrien	      __c = *(++__beg);
163697403Sobrien	      for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
163797403Sobrien		{
163897403Sobrien		  __name = __names[__matches[__i3]];
163997403Sobrien		  if (__name[__pos] != __c)
164097403Sobrien		    __matches[__i3] = __matches[--__nmatches];
164197403Sobrien		}
164297403Sobrien	    }
164397403Sobrien	  else
164497403Sobrien	    break;
164597403Sobrien	}
164697403Sobrien
164797403Sobrien      if (__nmatches == 1)
164897403Sobrien	{
164997403Sobrien	  // Make sure found name is completely extracted.
165097403Sobrien	  __name = __names[__matches[0]];
165197403Sobrien	  const size_t __len = __traits_type::length(__name);
165297403Sobrien	  while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
165397403Sobrien	    ++__beg, ++__pos;
165497403Sobrien
165597403Sobrien	  if (__len == __pos)
165697403Sobrien	    __member = __matches[0];
165797403Sobrien	  else
165897403Sobrien	    __testvalid = false;
165997403Sobrien	}
166097403Sobrien      else
166197403Sobrien	__testvalid = false;
166297403Sobrien      if (!__testvalid)
166397403Sobrien	__err |= ios_base::failbit;
166497403Sobrien    }
166597403Sobrien
166697403Sobrien  template<typename _CharT, typename _InIter>
166797403Sobrien    _InIter
166897403Sobrien    time_get<_CharT, _InIter>::
166997403Sobrien    do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
167097403Sobrien		ios_base::iostate& __err, tm* __tm) const
167197403Sobrien    {
167297403Sobrien      _CharT __wcs[3];
167397403Sobrien      const char* __cs = "%X";
167497403Sobrien      locale __loc = __io.getloc();
167597403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
167697403Sobrien      __ctype.widen(__cs, __cs + 3, __wcs);
167797403Sobrien      _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
167897403Sobrien      if (__beg == __end)
167997403Sobrien	__err |= ios_base::eofbit;
168097403Sobrien      return __beg;
168197403Sobrien    }
168297403Sobrien
168397403Sobrien  template<typename _CharT, typename _InIter>
168497403Sobrien    _InIter
168597403Sobrien    time_get<_CharT, _InIter>::
168697403Sobrien    do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
168797403Sobrien		ios_base::iostate& __err, tm* __tm) const
168897403Sobrien    {
168997403Sobrien      _CharT __wcs[3];
169097403Sobrien      const char* __cs = "%x";
169197403Sobrien      locale __loc = __io.getloc();
169297403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
169397403Sobrien      __ctype.widen(__cs, __cs + 3, __wcs);
169497403Sobrien      _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
169597403Sobrien      if (__beg == __end)
169697403Sobrien	__err |= ios_base::eofbit;
169797403Sobrien      return __beg;
169897403Sobrien    }
169997403Sobrien
170097403Sobrien  template<typename _CharT, typename _InIter>
170197403Sobrien    _InIter
170297403Sobrien    time_get<_CharT, _InIter>::
170397403Sobrien    do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 
170497403Sobrien		   ios_base::iostate& __err, tm* __tm) const
170597403Sobrien    {
1706102782Skan      typedef char_traits<_CharT> 		__traits_type;
170797403Sobrien      locale __loc = __io.getloc();
170897403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
170997403Sobrien      const char_type*  __days[7];
171097403Sobrien      __tp._M_days_abbreviated(__days);
171197403Sobrien      int __tmpwday;
171297403Sobrien      _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err);
171397403Sobrien
171497403Sobrien      // Check to see if non-abbreviated name exists, and extract.
171597403Sobrien      // NB: Assumes both _M_days and _M_days_abbreviated organized in
171697403Sobrien      // exact same order, first to last, such that the resulting
171797403Sobrien      // __days array with the same index points to a day, and that
171897403Sobrien      // day's abbreviated form.
171997403Sobrien      // NB: Also assumes that an abbreviated name is a subset of the name. 
172097403Sobrien      if (!__err)
172197403Sobrien	{
172297403Sobrien	  size_t __pos = __traits_type::length(__days[__tmpwday]);
172397403Sobrien	  __tp._M_days(__days);
172497403Sobrien	  const char_type* __name = __days[__tmpwday];
172597403Sobrien	  if (__name[__pos] == *__beg)
172697403Sobrien	    {
172797403Sobrien	      // Extract the rest of it.
172897403Sobrien	      const size_t __len = __traits_type::length(__name);
172997403Sobrien	      while (__pos < __len && __beg != __end 
173097403Sobrien		     && __name[__pos] == *__beg)
173197403Sobrien		++__beg, ++__pos;
173297403Sobrien	      if (__len != __pos)
173397403Sobrien		__err |= ios_base::failbit;
173497403Sobrien	    }
173597403Sobrien	  if (!__err)
173697403Sobrien	    __tm->tm_wday = __tmpwday;
173797403Sobrien	}
173897403Sobrien      if (__beg == __end)
173997403Sobrien	__err |= ios_base::eofbit;
174097403Sobrien      return __beg;
174197403Sobrien     }
174297403Sobrien
174397403Sobrien  template<typename _CharT, typename _InIter>
174497403Sobrien    _InIter
174597403Sobrien    time_get<_CharT, _InIter>::
174697403Sobrien    do_get_monthname(iter_type __beg, iter_type __end,
174797403Sobrien                     ios_base& __io, ios_base::iostate& __err, tm* __tm) const
174897403Sobrien    {
1749102782Skan      typedef char_traits<_CharT> 		__traits_type;
175097403Sobrien      locale __loc = __io.getloc();
175197403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
175297403Sobrien      const char_type*  __months[12];
175397403Sobrien      __tp._M_months_abbreviated(__months);
175497403Sobrien      int __tmpmon;
175597403Sobrien      _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err);
175697403Sobrien
175797403Sobrien      // Check to see if non-abbreviated name exists, and extract.
175897403Sobrien      // NB: Assumes both _M_months and _M_months_abbreviated organized in
175997403Sobrien      // exact same order, first to last, such that the resulting
176097403Sobrien      // __months array with the same index points to a month, and that
176197403Sobrien      // month's abbreviated form.
176297403Sobrien      // NB: Also assumes that an abbreviated name is a subset of the name. 
176397403Sobrien      if (!__err)
176497403Sobrien	{
176597403Sobrien	  size_t __pos = __traits_type::length(__months[__tmpmon]);
176697403Sobrien	  __tp._M_months(__months);
176797403Sobrien	  const char_type* __name = __months[__tmpmon];
176897403Sobrien	  if (__name[__pos] == *__beg)
176997403Sobrien	    {
177097403Sobrien	      // Extract the rest of it.
177197403Sobrien	      const size_t __len = __traits_type::length(__name);
177297403Sobrien	      while (__pos < __len && __beg != __end 
177397403Sobrien		     && __name[__pos] == *__beg)
177497403Sobrien		++__beg, ++__pos;
177597403Sobrien	      if (__len != __pos)
177697403Sobrien		__err |= ios_base::failbit;
177797403Sobrien	    }
177897403Sobrien	  if (!__err)
177997403Sobrien	    __tm->tm_mon = __tmpmon;
178097403Sobrien	}
178197403Sobrien 
178297403Sobrien      if (__beg == __end)
178397403Sobrien	__err |= ios_base::eofbit;
178497403Sobrien      return __beg;
178597403Sobrien    }
178697403Sobrien
178797403Sobrien  template<typename _CharT, typename _InIter>
178897403Sobrien    _InIter
178997403Sobrien    time_get<_CharT, _InIter>::
179097403Sobrien    do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 
179197403Sobrien		ios_base::iostate& __err, tm* __tm) const
179297403Sobrien    {
179397403Sobrien      locale __loc = __io.getloc();
179497403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
179597403Sobrien
179697403Sobrien      char_type __c = *__beg;
179797403Sobrien      size_t __i = 0;
179897403Sobrien      string __digits;
179997403Sobrien      while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c))
180097403Sobrien	{
180197403Sobrien	  __digits += __ctype.narrow(__c, 0);
180297403Sobrien	  __c = *(++__beg);
180397403Sobrien	  ++__i;
180497403Sobrien	}
180597403Sobrien      if (__i == 2 || __i == 4)
180697403Sobrien	{
180797403Sobrien	  long __l;
180897403Sobrien	  __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale);
180997403Sobrien	  if (!(__err & ios_base::failbit) && __l <= INT_MAX)
181097403Sobrien	    {
181197403Sobrien	      __l = __i == 2 ? __l : __l - 1900; 
181297403Sobrien	      __tm->tm_year = static_cast<int>(__l);
181397403Sobrien	    }
181497403Sobrien	}
181597403Sobrien      else
181697403Sobrien	__err |= ios_base::failbit;
181797403Sobrien      if (__beg == __end)
181897403Sobrien	__err |= ios_base::eofbit;
181997403Sobrien      return __beg;
182097403Sobrien    }
182197403Sobrien
182297403Sobrien  template<typename _CharT, typename _OutIter>
182397403Sobrien    _OutIter
182497403Sobrien    time_put<_CharT, _OutIter>::
182597403Sobrien    put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 
182697403Sobrien	const _CharT* __beg, const _CharT* __end) const
182797403Sobrien    {
182897403Sobrien      locale __loc = __io.getloc();
182997403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
183097403Sobrien      while (__beg != __end)
183197403Sobrien	{
183297403Sobrien	  char __c = __ctype.narrow(*__beg, 0);
183397403Sobrien	  ++__beg;
183497403Sobrien	  if (__c == '%')
183597403Sobrien	    {
183697403Sobrien	      char __format;
183797403Sobrien	      char __mod = 0;
183897403Sobrien	      size_t __len = 1; 
183997403Sobrien	      __c = __ctype.narrow(*__beg, 0);
184097403Sobrien	      ++__beg;
184197403Sobrien	      if (__c == 'E' || __c == 'O')
184297403Sobrien		{
184397403Sobrien		  __mod = __c;
184497403Sobrien		  __format = __ctype.narrow(*__beg, 0);
184597403Sobrien		  ++__beg;
184697403Sobrien		}
184797403Sobrien	      else
184897403Sobrien		__format = __c;
184997403Sobrien	      __s = this->do_put(__s, __io, char_type(), __tm, __format, 
185097403Sobrien				 __mod);
185197403Sobrien	    }
185297403Sobrien	  else
185397403Sobrien	    {
185497403Sobrien	      *__s = __c;
185597403Sobrien	      ++__s;
185697403Sobrien	    }
185797403Sobrien	}
185897403Sobrien      return __s;
185997403Sobrien    }
186097403Sobrien
186197403Sobrien  template<typename _CharT, typename _OutIter>
186297403Sobrien    _OutIter
186397403Sobrien    time_put<_CharT, _OutIter>::
186497403Sobrien    do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 
186597403Sobrien	   char __format, char __mod) const
186697403Sobrien    { 
186797403Sobrien      locale __loc = __io.getloc();
186897403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
186997403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
187097403Sobrien
187197403Sobrien      // NB: This size is arbitrary. Should this be a data member,
187297403Sobrien      // initialized at construction?
187397403Sobrien      const size_t __maxlen = 64;
187497403Sobrien      char_type* __res =
187597403Sobrien	static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
187697403Sobrien
187797403Sobrien      // NB: In IEE 1003.1-200x, and perhaps other locale models, it
187897403Sobrien      // is possible that the format character will be longer than one
187997403Sobrien      // character. Possibilities include 'E' or 'O' followed by a
188097403Sobrien      // format character: if __mod is not the default argument, assume
188197403Sobrien      // it's a valid modifier.
188297403Sobrien      char_type __fmt[4];
188397403Sobrien      __fmt[0] = __ctype.widen('%'); 
188497403Sobrien      if (!__mod)
188597403Sobrien	{
188697403Sobrien	  __fmt[1] = __format;
188797403Sobrien	  __fmt[2] = char_type();
188897403Sobrien	}
188997403Sobrien      else
189097403Sobrien	{
189197403Sobrien	  __fmt[1] = __mod;
189297403Sobrien	  __fmt[2] = __format;
189397403Sobrien	  __fmt[3] = char_type();
189497403Sobrien	}
189597403Sobrien
189697403Sobrien      __tp._M_put(__res, __maxlen, __fmt, __tm);
189797403Sobrien
189897403Sobrien      // Write resulting, fully-formatted string to output iterator.
189997403Sobrien      size_t __len = char_traits<char_type>::length(__res);
190097403Sobrien      for (size_t __i = 0; __i < __len; ++__i, ++__s)
190197403Sobrien	*__s = __res[__i];
190297403Sobrien      return __s;
190397403Sobrien    }
190497403Sobrien
190597403Sobrien
190697403Sobrien  // Generic version does nothing.
190797403Sobrien  template<typename _CharT>
190897403Sobrien    int
190997403Sobrien    collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
191097403Sobrien    { return 0; }
191197403Sobrien
191297403Sobrien  // Generic version does nothing.
191397403Sobrien  template<typename _CharT>
191497403Sobrien    size_t
191597403Sobrien    collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
191697403Sobrien    { return 0; }
191797403Sobrien
191897403Sobrien  template<typename _CharT>
191997403Sobrien    int
192097403Sobrien    collate<_CharT>::
192197403Sobrien    do_compare(const _CharT* __lo1, const _CharT* __hi1, 
192297403Sobrien	       const _CharT* __lo2, const _CharT* __hi2) const
192397403Sobrien    { 
192497403Sobrien      const string_type __one(__lo1, __hi1);
192597403Sobrien      const string_type __two(__lo2, __hi2);
192697403Sobrien      return _M_compare(__one.c_str(), __two.c_str());
192797403Sobrien    }
192897403Sobrien
192997403Sobrien template<typename _CharT>
193097403Sobrien    typename collate<_CharT>::string_type
193197403Sobrien    collate<_CharT>::
193297403Sobrien    do_transform(const _CharT* __lo, const _CharT* __hi) const
193397403Sobrien    {
193497403Sobrien      size_t __len = (__hi - __lo) * 2;
193597403Sobrien      // First try a buffer perhaps big enough.
193697403Sobrien      _CharT* __c =
193797403Sobrien	static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
193897403Sobrien      size_t __res = _M_transform(__c, __lo, __len);
193997403Sobrien      // If the buffer was not large enough, try again with the correct size.
194097403Sobrien      if (__res >= __len)
194197403Sobrien	{
194297403Sobrien	  __c =
194397403Sobrien	    static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1)));
194497403Sobrien	  _M_transform(__c, __lo, __res + 1);
194597403Sobrien	}
194697403Sobrien      return string_type(__c);
194797403Sobrien    }
194897403Sobrien
194997403Sobrien template<typename _CharT>
195097403Sobrien    long
195197403Sobrien    collate<_CharT>::
195297403Sobrien    do_hash(const _CharT* __lo, const _CharT* __hi) const
195397403Sobrien    { 
195497403Sobrien      unsigned long __val = 0;
195597403Sobrien      for (; __lo < __hi; ++__lo)
195697403Sobrien	__val = *__lo + ((__val << 7) | 
195797403Sobrien		       (__val >> (numeric_limits<unsigned long>::digits - 7)));
195897403Sobrien      return static_cast<long>(__val);
195997403Sobrien    }
196097403Sobrien
196197403Sobrien  // Convert string to numeric value of type _Tv and store results.  
196297403Sobrien  // NB: This is specialized for all required types, there is no
196397403Sobrien  // generic definition.
196497403Sobrien  template<typename _Tv>
196597403Sobrien    void
196697403Sobrien    __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err, 
196797403Sobrien		   const __c_locale& __cloc, int __base = 10);
196897403Sobrien
196997403Sobrien  // Convert numeric value of type _Tv to string and return length of string.
197097403Sobrien  // If snprintf is available use it, otherwise fall back to the unsafe sprintf
197197403Sobrien  // which, in general, can be dangerous and should be avoided.
197297403Sobrien#ifdef _GLIBCPP_USE_C99
197397403Sobrien  template<typename _Tv>
197497403Sobrien    int
197597403Sobrien    __convert_from_v(char* __out, const int __size, const char* __fmt,
197697403Sobrien		     _Tv __v, const __c_locale&, int __prec = -1)
197797403Sobrien    {
197897403Sobrien      int __ret;
1979102782Skan      char* __old = strdup(setlocale(LC_ALL, NULL));
1980102782Skan      setlocale(LC_ALL, "C");
198197403Sobrien      if (__prec >= 0)
198297403Sobrien        __ret = snprintf(__out, __size, __fmt, __prec, __v);
198397403Sobrien      else
198497403Sobrien        __ret = snprintf(__out, __size, __fmt, __v);
198597403Sobrien      setlocale(LC_ALL, __old);
1986102782Skan      free(__old);
198797403Sobrien      return __ret;
198897403Sobrien    }
198997403Sobrien#else
199097403Sobrien  template<typename _Tv>
199197403Sobrien    int
199297403Sobrien    __convert_from_v(char* __out, const int, const char* __fmt, _Tv __v,
199397403Sobrien		     const __c_locale&, int __prec = -1)
199497403Sobrien    {
199597403Sobrien      int __ret;
1996102782Skan      char* __old = strdup(setlocale(LC_ALL, NULL));
1997102782Skan      setlocale(LC_ALL, "C");
199897403Sobrien      if (__prec >= 0)
199997403Sobrien        __ret = sprintf(__out, __fmt, __prec, __v);
200097403Sobrien      else
200197403Sobrien        __ret = sprintf(__out, __fmt, __v);
200297403Sobrien      setlocale(LC_ALL, __old);
2003102782Skan      free(__old);
200497403Sobrien      return __ret;
200597403Sobrien    }
200697403Sobrien#endif
200797403Sobrien
200897403Sobrien  // Construct correctly padded string, as per 22.2.2.2.2
200997403Sobrien  // Assumes 
201097403Sobrien  // __newlen > __oldlen
201197403Sobrien  // __news is allocated for __newlen size
201297403Sobrien  // Used by both num_put and ostream inserters: if __num,
201397403Sobrien  // internal-adjusted objects are padded according to the rules below
201497403Sobrien  // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
201597403Sobrien  // ones are.
2016102782Skan
2017102782Skan  // NB: Of the two parameters, _CharT can be deduced from the
2018102782Skan  // function arguments. The other (_Traits) has to be explicitly specified.
201997403Sobrien  template<typename _CharT, typename _Traits>
2020102782Skan    struct __pad
202197403Sobrien    {
2022102782Skan      static void
2023102782Skan      _S_pad(ios_base& __io, _CharT __fill, _CharT* __news, 
2024102782Skan	     const _CharT* __olds, const streamsize __newlen, 
2025102782Skan	     const streamsize __oldlen, const bool __num);
2026102782Skan    };
202797403Sobrien
2028102782Skan  template<typename _CharT, typename _Traits>
2029102782Skan    void 
2030102782Skan    __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 
2031102782Skan				   _CharT* __news, const _CharT* __olds, 
2032102782Skan				   const streamsize __newlen, 
2033102782Skan				   const streamsize __oldlen, const bool __num)
2034102782Skan    {
2035102782Skan      size_t __plen = static_cast<size_t>(__newlen - __oldlen);
2036102782Skan      _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen));
2037102782Skan      _Traits::assign(__pads, __plen, __fill); 
2038102782Skan
2039102782Skan      _CharT* __beg;
2040102782Skan      _CharT* __end;
204197403Sobrien      size_t __mod = 0;
204297403Sobrien      size_t __beglen; //either __plen or __oldlen
204397403Sobrien      ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
204497403Sobrien
204597403Sobrien      if (__adjust == ios_base::left)
204697403Sobrien	{
204797403Sobrien	  // Padding last.
2048102782Skan	  __beg = const_cast<_CharT*>(__olds);
204997403Sobrien	  __beglen = __oldlen;
205097403Sobrien	  __end = __pads;
205197403Sobrien	}
205297403Sobrien      else if (__adjust == ios_base::internal && __num)
205397403Sobrien	{
205497403Sobrien	  // Pad after the sign, if there is one.
205597403Sobrien	  // Pad after 0[xX], if there is one.
205697403Sobrien	  // Who came up with these rules, anyway? Jeeze.
205797403Sobrien          locale __loc = __io.getloc();
205897403Sobrien	  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
2059102782Skan	  const _CharT __minus = __ctype.widen('-');
2060102782Skan	  const _CharT __plus = __ctype.widen('+');
2061102782Skan	  bool __testsign = _Traits::eq(__olds[0], __minus)
2062102782Skan	    		    || _Traits::eq(__olds[0], __plus);
2063102782Skan
2064102782Skan	  bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) 
2065102782Skan	    		   && (_Traits::eq(__ctype.widen('x'), __olds[1]) 
2066102782Skan			       || _Traits::eq(__ctype.widen('X'), __olds[1]));
206797403Sobrien	  if (__testhex)
206897403Sobrien	    {
206997403Sobrien	      __news[0] = __olds[0]; 
207097403Sobrien	      __news[1] = __olds[1];
207197403Sobrien	      __mod += 2;
207297403Sobrien	      __news += 2;
207397403Sobrien	      __beg = __pads;
207497403Sobrien	      __beglen = __plen;
2075102782Skan	      __end = const_cast<_CharT*>(__olds + __mod);
207697403Sobrien	    }
207797403Sobrien	  else if (__testsign)
207897403Sobrien	    {
2079102782Skan	      _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus;
208097403Sobrien	      ++__mod;
208197403Sobrien	      ++__news;
208297403Sobrien	      __beg = __pads;
208397403Sobrien	      __beglen = __plen;
2084102782Skan	      __end = const_cast<_CharT*>(__olds + __mod);
208597403Sobrien	    }
208697403Sobrien	  else
208797403Sobrien	    {
208897403Sobrien	      // Padding first.
208997403Sobrien	      __beg = __pads;
209097403Sobrien	      __beglen = __plen;
2091102782Skan	      __end = const_cast<_CharT*>(__olds);
209297403Sobrien	    }
209397403Sobrien	}
209497403Sobrien      else
209597403Sobrien	{
209697403Sobrien	  // Padding first.
209797403Sobrien	  __beg = __pads;
209897403Sobrien	  __beglen = __plen;
2099102782Skan	  __end = const_cast<_CharT*>(__olds);
210097403Sobrien	}
2101102782Skan      _Traits::copy(__news, __beg, __beglen);
2102102782Skan      _Traits::copy(__news + __beglen, __end, 
2103102782Skan			  __newlen - __beglen - __mod);
210497403Sobrien    }
210597403Sobrien
210697403Sobrien  // Used by both numeric and monetary facets.
210797403Sobrien  // Check to make sure that the __grouping_tmp string constructed in
210897403Sobrien  // money_get or num_get matches the canonical grouping for a given
210997403Sobrien  // locale.
211097403Sobrien  // __grouping_tmp is parsed L to R
211197403Sobrien  // 1,222,444 == __grouping_tmp of "/1/3/3"
211297403Sobrien  // __grouping is parsed R to L
211397403Sobrien  // 1,222,444 == __grouping of "/3" == "/3/3/3"
211497403Sobrien  template<typename _CharT>
211597403Sobrien    bool
211697403Sobrien    __verify_grouping(const basic_string<_CharT>& __grouping, 
211797403Sobrien		      basic_string<_CharT>& __grouping_tmp)
211897403Sobrien    {         
211997403Sobrien      int __i = 0;
212097403Sobrien      int __j = 0;
212197403Sobrien      const int __len = __grouping.size();
212297403Sobrien      const int __n = __grouping_tmp.size();
212397403Sobrien      bool __test = true;
212497403Sobrien      
212597403Sobrien      // Parsed number groupings have to match the
212697403Sobrien      // numpunct::grouping string exactly, starting at the
212797403Sobrien      // right-most point of the parsed sequence of elements ...
212897403Sobrien      while (__test && __i < __n - 1)
212997403Sobrien	for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
213097403Sobrien	  __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1];
213197403Sobrien      // ... but the last parsed grouping can be <= numpunct
213297403Sobrien      // grouping.
213397403Sobrien      __j == __len ? __j = 0 : __j;
213497403Sobrien      __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1];
213597403Sobrien      return __test;
213697403Sobrien    }
213797403Sobrien
213897403Sobrien  // Used by both numeric and monetary facets.
213997403Sobrien  // Inserts "group separator" characters into an array of characters.
214097403Sobrien  // It's recursive, one iteration per group.  It moves the characters
214197403Sobrien  // in the buffer this way: "xxxx12345" -> "12,345xxx".  Call this
214297403Sobrien  // only with __gbeg != __gend.
214397403Sobrien  template<typename _CharT>
214497403Sobrien    _CharT*
214597403Sobrien    __add_grouping(_CharT* __s, _CharT __sep,  
214697403Sobrien		   const char* __gbeg, const char* __gend, 
214797403Sobrien		   const _CharT* __first, const _CharT* __last)
214897403Sobrien    {
214997403Sobrien      if (__last - __first > *__gbeg)
215097403Sobrien        {
215197403Sobrien          __s = __add_grouping(__s,  __sep, 
215297403Sobrien			       (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
215397403Sobrien			       __gend, __first, __last - *__gbeg);
215497403Sobrien          __first = __last - *__gbeg;
215597403Sobrien          *__s++ = __sep;
215697403Sobrien        }
215797403Sobrien      do
215897403Sobrien	*__s++ = *__first++;
215997403Sobrien      while (__first != __last);
216097403Sobrien      return __s;
216197403Sobrien    }
216297403Sobrien
216397403Sobrien  // Inhibit implicit instantiations for required instantiations,
216497403Sobrien  // which are defined via explicit instantiations elsewhere.  
216597403Sobrien  // NB: This syntax is a GNU extension.
216697403Sobrien  extern template class moneypunct<char, false>;
216797403Sobrien  extern template class moneypunct<char, true>;
216897403Sobrien  extern template class moneypunct_byname<char, false>;
216997403Sobrien  extern template class moneypunct_byname<char, true>;
217097403Sobrien  extern template class money_get<char>;
217197403Sobrien  extern template class money_put<char>;
217297403Sobrien  extern template class moneypunct<wchar_t, false>;
217397403Sobrien  extern template class moneypunct<wchar_t, true>;
217497403Sobrien  extern template class moneypunct_byname<wchar_t, false>;
217597403Sobrien  extern template class moneypunct_byname<wchar_t, true>;
217697403Sobrien  extern template class money_get<wchar_t>;
217797403Sobrien  extern template class money_put<wchar_t>;
217897403Sobrien  extern template class numpunct<char>;
217997403Sobrien  extern template class numpunct_byname<char>;
218097403Sobrien  extern template class num_get<char>;
218197403Sobrien  extern template class num_put<char>; 
218297403Sobrien  extern template class numpunct<wchar_t>;
218397403Sobrien  extern template class numpunct_byname<wchar_t>;
218497403Sobrien  extern template class num_get<wchar_t>;
218597403Sobrien  extern template class num_put<wchar_t>;
218697403Sobrien  extern template class __timepunct<char>;
218797403Sobrien  extern template class time_put<char>;
218897403Sobrien  extern template class time_put_byname<char>;
218997403Sobrien  extern template class time_get<char>;
219097403Sobrien  extern template class time_get_byname<char>;
219197403Sobrien  extern template class __timepunct<wchar_t>;
219297403Sobrien  extern template class time_put<wchar_t>;
219397403Sobrien  extern template class time_put_byname<wchar_t>;
219497403Sobrien  extern template class time_get<wchar_t>;
219597403Sobrien  extern template class time_get_byname<wchar_t>;
219697403Sobrien  extern template class messages<char>;
219797403Sobrien  extern template class messages_byname<char>;
219897403Sobrien  extern template class messages<wchar_t>;
219997403Sobrien  extern template class messages_byname<wchar_t>;
220097403Sobrien  extern template class ctype_byname<char>;
220197403Sobrien  extern template class ctype_byname<wchar_t>;
220297403Sobrien  extern template class codecvt_byname<char, char, mbstate_t>;
220397403Sobrien  extern template class codecvt_byname<wchar_t, char, mbstate_t>;
220497403Sobrien  extern template class collate<char>;
220597403Sobrien  extern template class collate_byname<char>;
220697403Sobrien  extern template class collate<wchar_t>;
220797403Sobrien  extern template class collate_byname<wchar_t>;
220897403Sobrien
220997403Sobrien  extern template
221097403Sobrien    const codecvt<char, char, mbstate_t>& 
221197403Sobrien    use_facet<codecvt<char, char, mbstate_t> >(const locale&);
221297403Sobrien
221397403Sobrien  extern template
221497403Sobrien    const collate<char>& 
221597403Sobrien    use_facet<collate<char> >(const locale&);
221697403Sobrien
221797403Sobrien  extern template
221897403Sobrien    const numpunct<char>& 
221997403Sobrien    use_facet<numpunct<char> >(const locale&);
222097403Sobrien
222197403Sobrien  extern template 
222297403Sobrien    const num_put<char>& 
222397403Sobrien    use_facet<num_put<char> >(const locale&);
222497403Sobrien
222597403Sobrien  extern template 
222697403Sobrien    const num_get<char>& 
222797403Sobrien    use_facet<num_get<char> >(const locale&);
222897403Sobrien
222997403Sobrien  extern template
223097403Sobrien    const moneypunct<char, true>& 
223197403Sobrien    use_facet<moneypunct<char, true> >(const locale&);
223297403Sobrien
223397403Sobrien  extern template
223497403Sobrien    const moneypunct<char, false>& 
223597403Sobrien    use_facet<moneypunct<char, false> >(const locale&);
223697403Sobrien
223797403Sobrien  extern template 
223897403Sobrien    const money_put<char>& 
223997403Sobrien    use_facet<money_put<char> >(const locale&);
224097403Sobrien
224197403Sobrien  extern template 
224297403Sobrien    const money_get<char>& 
224397403Sobrien    use_facet<money_get<char> >(const locale&);
224497403Sobrien
224597403Sobrien  extern template
224697403Sobrien    const __timepunct<char>& 
224797403Sobrien    use_facet<__timepunct<char> >(const locale&);
224897403Sobrien
224997403Sobrien  extern template 
225097403Sobrien    const time_put<char>& 
225197403Sobrien    use_facet<time_put<char> >(const locale&);
225297403Sobrien
225397403Sobrien  extern template 
225497403Sobrien    const time_get<char>& 
225597403Sobrien    use_facet<time_get<char> >(const locale&);
225697403Sobrien
225797403Sobrien  extern template 
225897403Sobrien    const messages<char>& 
225997403Sobrien    use_facet<messages<char> >(const locale&);
226097403Sobrien
226197403Sobrien  extern template
226297403Sobrien    const codecvt<wchar_t, char, mbstate_t>& 
226397403Sobrien    use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
226497403Sobrien
226597403Sobrien  extern template
226697403Sobrien    const collate<wchar_t>& 
226797403Sobrien    use_facet<collate<wchar_t> >(const locale&);
226897403Sobrien
226997403Sobrien  extern template
227097403Sobrien    const numpunct<wchar_t>& 
227197403Sobrien    use_facet<numpunct<wchar_t> >(const locale&);
227297403Sobrien
227397403Sobrien  extern template 
227497403Sobrien    const num_put<wchar_t>& 
227597403Sobrien    use_facet<num_put<wchar_t> >(const locale&);
227697403Sobrien
227797403Sobrien  extern template 
227897403Sobrien    const num_get<wchar_t>& 
227997403Sobrien    use_facet<num_get<wchar_t> >(const locale&);
228097403Sobrien
228197403Sobrien  extern template
228297403Sobrien    const moneypunct<wchar_t, true>& 
228397403Sobrien    use_facet<moneypunct<wchar_t, true> >(const locale&);
228497403Sobrien
228597403Sobrien  extern template
228697403Sobrien    const moneypunct<wchar_t, false>& 
228797403Sobrien    use_facet<moneypunct<wchar_t, false> >(const locale&);
228897403Sobrien 
228997403Sobrien  extern template 
229097403Sobrien    const money_put<wchar_t>& 
229197403Sobrien    use_facet<money_put<wchar_t> >(const locale&);
229297403Sobrien
229397403Sobrien  extern template 
229497403Sobrien    const money_get<wchar_t>& 
229597403Sobrien    use_facet<money_get<wchar_t> >(const locale&);
229697403Sobrien
229797403Sobrien  extern template
229897403Sobrien    const __timepunct<wchar_t>& 
229997403Sobrien    use_facet<__timepunct<wchar_t> >(const locale&);
230097403Sobrien
230197403Sobrien  extern template 
230297403Sobrien    const time_put<wchar_t>& 
230397403Sobrien    use_facet<time_put<wchar_t> >(const locale&);
230497403Sobrien
230597403Sobrien  extern template 
230697403Sobrien    const time_get<wchar_t>& 
230797403Sobrien    use_facet<time_get<wchar_t> >(const locale&);
230897403Sobrien
230997403Sobrien  extern template 
231097403Sobrien    const messages<wchar_t>& 
231197403Sobrien    use_facet<messages<wchar_t> >(const locale&);
231297403Sobrien
231397403Sobrien
231497403Sobrien  extern template 
231597403Sobrien    bool
231697403Sobrien    has_facet<ctype<char> >(const locale&);
231797403Sobrien
231897403Sobrien  extern template 
231997403Sobrien    bool
232097403Sobrien    has_facet<codecvt<char, char, mbstate_t> >(const locale&);
232197403Sobrien
232297403Sobrien  extern template 
232397403Sobrien    bool
232497403Sobrien    has_facet<collate<char> >(const locale&);
232597403Sobrien
232697403Sobrien  extern template 
232797403Sobrien    bool
232897403Sobrien    has_facet<numpunct<char> >(const locale&);
232997403Sobrien
233097403Sobrien  extern template 
233197403Sobrien    bool
233297403Sobrien    has_facet<num_put<char> >(const locale&);
233397403Sobrien
233497403Sobrien  extern template 
233597403Sobrien    bool
233697403Sobrien    has_facet<num_get<char> >(const locale&);
233797403Sobrien
233897403Sobrien  extern template 
233997403Sobrien    bool
234097403Sobrien    has_facet<moneypunct<char> >(const locale&);
234197403Sobrien
234297403Sobrien  extern template 
234397403Sobrien    bool
234497403Sobrien    has_facet<money_put<char> >(const locale&);
234597403Sobrien
234697403Sobrien  extern template 
234797403Sobrien    bool
234897403Sobrien    has_facet<money_get<char> >(const locale&);
234997403Sobrien
235097403Sobrien  extern template 
235197403Sobrien    bool
235297403Sobrien    has_facet<__timepunct<char> >(const locale&);
235397403Sobrien
235497403Sobrien  extern template 
235597403Sobrien    bool
235697403Sobrien    has_facet<time_put<char> >(const locale&);
235797403Sobrien
235897403Sobrien  extern template 
235997403Sobrien    bool
236097403Sobrien    has_facet<time_get<char> >(const locale&);
236197403Sobrien
236297403Sobrien  extern template 
236397403Sobrien    bool
236497403Sobrien    has_facet<messages<char> >(const locale&);
236597403Sobrien
236697403Sobrien extern template 
236797403Sobrien    bool
236897403Sobrien    has_facet<ctype<wchar_t> >(const locale&);
236997403Sobrien
237097403Sobrien  extern template 
237197403Sobrien    bool
237297403Sobrien    has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
237397403Sobrien
237497403Sobrien  extern template 
237597403Sobrien    bool
237697403Sobrien    has_facet<collate<wchar_t> >(const locale&);
237797403Sobrien
237897403Sobrien  extern template 
237997403Sobrien    bool
238097403Sobrien    has_facet<numpunct<wchar_t> >(const locale&);
238197403Sobrien
238297403Sobrien  extern template 
238397403Sobrien    bool
238497403Sobrien    has_facet<num_put<wchar_t> >(const locale&);
238597403Sobrien
238697403Sobrien  extern template 
238797403Sobrien    bool
238897403Sobrien    has_facet<num_get<wchar_t> >(const locale&);
238997403Sobrien
239097403Sobrien  extern template 
239197403Sobrien    bool
239297403Sobrien    has_facet<moneypunct<wchar_t> >(const locale&);
239397403Sobrien
239497403Sobrien  extern template 
239597403Sobrien    bool
239697403Sobrien    has_facet<money_put<wchar_t> >(const locale&);
239797403Sobrien
239897403Sobrien  extern template 
239997403Sobrien    bool
240097403Sobrien    has_facet<money_get<wchar_t> >(const locale&);
240197403Sobrien
240297403Sobrien  extern template 
240397403Sobrien    bool
240497403Sobrien    has_facet<__timepunct<wchar_t> >(const locale&);
240597403Sobrien
240697403Sobrien  extern template 
240797403Sobrien    bool
240897403Sobrien    has_facet<time_put<wchar_t> >(const locale&);
240997403Sobrien
241097403Sobrien  extern template 
241197403Sobrien    bool
241297403Sobrien    has_facet<time_get<wchar_t> >(const locale&);
241397403Sobrien
241497403Sobrien  extern template 
241597403Sobrien    bool
241697403Sobrien    has_facet<messages<wchar_t> >(const locale&);
241797403Sobrien} // namespace std
241897403Sobrien
241997403Sobrien#endif
2420