locale_facets.tcc revision 110614
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      {
625110614Skan	// Note: digits10 is rounded down: we need to add 1 to ensure
62697403Sobrien	// we get the full available precision.
627110614Skan	// Then, in general, one more 1 needs to be added since, when the
628110614Skan	// %{g,G} conversion specifiers are chosen inside _S_format_float, the
629110614Skan	// precision field is "the maximum number of significant digits", *not*
630110614Skan	// the "number of digits to appear after the decimal point", as happens
631110614Skan	// for %{e,E,f,F} (C99, 7.19.6.1,4).
632110614Skan	const int __max_digits = numeric_limits<_ValueT>::digits10 + 2;
63397403Sobrien	streamsize __prec = __io.precision();
63497403Sobrien
63597403Sobrien	if (__prec > static_cast<streamsize>(__max_digits))
63697403Sobrien	  __prec = static_cast<streamsize>(__max_digits);
63797403Sobrien
63897403Sobrien	// Long enough for the max format spec.
63997403Sobrien	char __fbuf[16];
64097403Sobrien
64197403Sobrien	// [22.2.2.2.2] Stage 1, numeric conversion to character.
64297403Sobrien	int __len;
64397403Sobrien#ifdef _GLIBCPP_USE_C99
64497403Sobrien	// First try a buffer perhaps big enough (for sure sufficient for
64597403Sobrien	// non-ios_base::fixed outputs)
64697403Sobrien	int __cs_size = __max_digits * 3;
64797403Sobrien	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
64897403Sobrien
64997403Sobrien	const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec);
65097403Sobrien	if (__fp)
65197403Sobrien	  __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
65297403Sobrien				   _S_c_locale, __prec);
65397403Sobrien	else
65497403Sobrien	  __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
65597403Sobrien
65697403Sobrien	// If the buffer was not large enough, try again with the correct size.
65797403Sobrien	if (__len >= __cs_size)
65897403Sobrien	  {
65997403Sobrien	    __cs_size = __len + 1; 
66097403Sobrien	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
66197403Sobrien	    if (__fp)
66297403Sobrien	      __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
66397403Sobrien				       _S_c_locale, __prec);
66497403Sobrien	    else
66597403Sobrien	      __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
66697403Sobrien				       _S_c_locale);
66797403Sobrien	  }
66897403Sobrien#else
66997403Sobrien	// Consider the possibility of long ios_base::fixed outputs
67097403Sobrien	const bool __fixed = __io.flags() & ios_base::fixed;
67197403Sobrien	const int __max_exp = numeric_limits<_ValueT>::max_exponent10;
67297403Sobrien	// ios_base::fixed outputs may need up to __max_exp+1 chars
67397403Sobrien	// for the integer part + up to __max_digits chars for the
67497403Sobrien	// fractional part + 3 chars for sign, decimal point, '\0'. On
67597403Sobrien	// the other hand, for non-fixed outputs __max_digits*3 chars
67697403Sobrien	// are largely sufficient.
67797403Sobrien	const int __cs_size = __fixed ? __max_exp + __max_digits + 4 
67897403Sobrien	                              : __max_digits * 3;
67997403Sobrien	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
68097403Sobrien
68197403Sobrien	if (_S_format_float(__io, __fbuf, __mod, __prec))
68297403Sobrien	  __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
68397403Sobrien	else
68497403Sobrien	  __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
68597403Sobrien#endif
68697403Sobrien	return _M_widen_float(__s, __io, __fill, __cs, __len);
68797403Sobrien      }
68897403Sobrien
68997403Sobrien  template<typename _CharT, typename _OutIter>
69097403Sobrien    template<typename _ValueT>
69197403Sobrien      _OutIter
69297403Sobrien      num_put<_CharT, _OutIter>::
69397403Sobrien      _M_convert_int(_OutIter __s, ios_base& __io, _CharT __fill, char __mod,
69497403Sobrien		     char __modl, _ValueT __v) const
69597403Sobrien      {
69697403Sobrien	// [22.2.2.2.2] Stage 1, numeric conversion to character.
69797403Sobrien
69897403Sobrien	// Long enough for the max format spec.
69997403Sobrien	char __fbuf[16];
70097403Sobrien	_S_format_int(__io, __fbuf, __mod, __modl);
70197403Sobrien#ifdef _GLIBCPP_USE_C99
70297403Sobrien	// First try a buffer perhaps big enough.
70397403Sobrien	int __cs_size = 64;
70497403Sobrien	char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
70597403Sobrien	int __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
70697403Sobrien				     _S_c_locale);
70797403Sobrien	// If the buffer was not large enough, try again with the correct size.
70897403Sobrien	if (__len >= __cs_size)
70997403Sobrien	  {
71097403Sobrien	    __cs_size = __len + 1;
71197403Sobrien	    __cs = static_cast<char*>(__builtin_alloca(__cs_size));
71297403Sobrien	    __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, 
71397403Sobrien				     _S_c_locale);
71497403Sobrien	  }
71597403Sobrien#else
71697403Sobrien	// Leave room for "+/-," "0x," and commas. This size is
71797403Sobrien	// arbitrary, but should be largely sufficient.
71897403Sobrien	char __cs[128];
71997403Sobrien	int __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
72097403Sobrien#endif
72197403Sobrien	return _M_widen_int(__s, __io, __fill, __cs, __len);
72297403Sobrien      }
72397403Sobrien
72497403Sobrien  template<typename _CharT, typename _OutIter>
72597403Sobrien    _OutIter
72697403Sobrien    num_put<_CharT, _OutIter>::
72797403Sobrien    _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
72897403Sobrien		   int __len) const
72997403Sobrien    {
730102782Skan      typedef char_traits<_CharT> 		__traits_type;
73197403Sobrien      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
73297403Sobrien      // numpunct.decimal_point() values for '.' and adding grouping.
73397403Sobrien      const locale __loc = __io.getloc();
73497403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
73597403Sobrien      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
73697403Sobrien							   * __len));
73797403Sobrien      // Grouping can add (almost) as many separators as the number of
73897403Sobrien      // digits, but no more.
73997403Sobrien      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
74097403Sobrien			 				    * __len * 2));
74197403Sobrien      __ctype.widen(__cs, __cs + __len, __ws);
74297403Sobrien      
74397403Sobrien      // Replace decimal point.
74497403Sobrien      const _CharT* __p;
74597403Sobrien      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
746102782Skan      if (__p = __traits_type::find(__ws, __len, __ctype.widen('.')))
74797403Sobrien	__ws[__p - __ws] = __np.decimal_point();
74897403Sobrien
74997403Sobrien#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
75097403Sobrien//282. What types does numpunct grouping refer to?
75197403Sobrien      // Add grouping, if necessary. 
75297403Sobrien      const string __grouping = __np.grouping();
75397403Sobrien      ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
75497403Sobrien      if (__grouping.size())
75597403Sobrien	{
75697403Sobrien	  _CharT* __p2;
75797403Sobrien	  int __declen = __p ? __p - __ws : __len;
75897403Sobrien	  __p2 = __add_grouping(__ws2, __np.thousands_sep(), 
75997403Sobrien				__grouping.c_str(),
76097403Sobrien				__grouping.c_str() + __grouping.size(),
76197403Sobrien				__ws, __ws + __declen);
76297403Sobrien	  int __newlen = __p2 - __ws2;
76397403Sobrien	
76497403Sobrien	  // Tack on decimal part.
76597403Sobrien	  if (__p)
76697403Sobrien	    {
767102782Skan	      __traits_type::copy(__p2, __p, __len - __declen);
76897403Sobrien	      __newlen += __len - __declen;
76997403Sobrien	    }    
77097403Sobrien
77197403Sobrien	  // Switch strings, establish correct new length.
77297403Sobrien	  __ws = __ws2;
77397403Sobrien	  __len = __newlen;
77497403Sobrien	}
77597403Sobrien#endif
77697403Sobrien      return _M_insert(__s, __io, __fill, __ws, __len);
77797403Sobrien    }
77897403Sobrien
77997403Sobrien  template<typename _CharT, typename _OutIter>
78097403Sobrien    _OutIter
78197403Sobrien    num_put<_CharT, _OutIter>::
78297403Sobrien    _M_widen_int(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs, 
78397403Sobrien		 int __len) const
78497403Sobrien    {
78597403Sobrien      // [22.2.2.2.2] Stage 2, convert to char_type, using correct
78697403Sobrien      // numpunct.decimal_point() values for '.' and adding grouping.
78797403Sobrien      const locale __loc = __io.getloc();
78897403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
78997403Sobrien      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
79097403Sobrien							   * __len));
79197403Sobrien      // Grouping can add (almost) as many separators as the number of
79297403Sobrien      // digits, but no more.
79397403Sobrien      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
79497403Sobrien							    * __len * 2));
79597403Sobrien      __ctype.widen(__cs, __cs + __len, __ws);
79697403Sobrien
79797403Sobrien      // Add grouping, if necessary. 
79897403Sobrien      const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
79997403Sobrien      const string __grouping = __np.grouping();
80097403Sobrien      const ios_base::fmtflags __basefield = __io.flags() & ios_base::basefield;
80197403Sobrien      if (__grouping.size())
80297403Sobrien	{
80397403Sobrien	  // By itself __add_grouping cannot deal correctly with __ws when
80497403Sobrien	  // ios::showbase is set and ios_base::oct || ios_base::hex.
80597403Sobrien	  // Therefore we take care "by hand" of the initial 0, 0x or 0X.
806104754Skan	  // However, remember that the latter do not occur if the number
807104754Skan	  // printed is '0' (__len == 1).
80897403Sobrien	  streamsize __off = 0;
809104754Skan	  if ((__io.flags() & ios_base::showbase) && __len > 1)
81097403Sobrien	    if (__basefield == ios_base::oct)
81197403Sobrien	      {
81297403Sobrien		__off = 1;
81397403Sobrien		*__ws2 = *__ws;
81497403Sobrien	      }
81597403Sobrien	    else if (__basefield == ios_base::hex)
81697403Sobrien	      {
81797403Sobrien		__off = 2;
81897403Sobrien		*__ws2 = *__ws;
81997403Sobrien		*(__ws2 + 1) = *(__ws + 1);
82097403Sobrien	      }
82197403Sobrien	  _CharT* __p;
82297403Sobrien	  __p = __add_grouping(__ws2 + __off, __np.thousands_sep(), 
82397403Sobrien			       __grouping.c_str(),
82497403Sobrien			       __grouping.c_str() + __grouping.size(),
82597403Sobrien			       __ws + __off, __ws + __len);
82697403Sobrien	  __len = __p - __ws2;
82797403Sobrien	  // Switch strings.
82897403Sobrien	  __ws = __ws2;
82997403Sobrien	}
83097403Sobrien      return _M_insert(__s, __io, __fill, __ws, __len);
83197403Sobrien    }
83297403Sobrien
83397403Sobrien  // For use by integer and floating-point types after they have been
83497403Sobrien  // converted into a char_type string.
83597403Sobrien  template<typename _CharT, typename _OutIter>
83697403Sobrien    _OutIter
83797403Sobrien    num_put<_CharT, _OutIter>::
83897403Sobrien    _M_insert(_OutIter __s, ios_base& __io, _CharT __fill, const _CharT* __ws, 
83997403Sobrien	      int __len) const
84097403Sobrien    {
841102782Skan      typedef char_traits<_CharT> 		__traits_type;
84297403Sobrien      // [22.2.2.2.2] Stage 3.
84397403Sobrien      streamsize __w = __io.width();
84497403Sobrien      _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) 
84597403Sobrien							    * __w));
84697403Sobrien      if (__w > static_cast<streamsize>(__len))
84797403Sobrien	{
848102782Skan	  __pad<_CharT, __traits_type>::_S_pad(__io, __fill, __ws2, __ws, 
849102782Skan					       __w, __len, true);
85097403Sobrien	  __len = static_cast<int>(__w);
85197403Sobrien	  // Switch strings.
85297403Sobrien	  __ws = __ws2;
85397403Sobrien	}
85497403Sobrien      __io.width(0);
85597403Sobrien
85697403Sobrien      // [22.2.2.2.2] Stage 4.
85797403Sobrien      // Write resulting, fully-formatted string to output iterator.
85897403Sobrien      for (int __j = 0; __j < __len; ++__j, ++__s)
85997403Sobrien	*__s = __ws[__j];
86097403Sobrien      return __s;
86197403Sobrien    }
86297403Sobrien
86397403Sobrien  template<typename _CharT, typename _OutIter>
86497403Sobrien    _OutIter
86597403Sobrien    num_put<_CharT, _OutIter>::
86697403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, bool __v) const
86797403Sobrien    {
86897403Sobrien      ios_base::fmtflags __flags = __io.flags();
86997403Sobrien      if ((__flags & ios_base::boolalpha) == 0)
87097403Sobrien        {
87197403Sobrien          unsigned long __uv = __v;
872102782Skan          __s = _M_convert_int(__s, __io, __fill, 'u', char(), __uv);
87397403Sobrien        }
87497403Sobrien      else
87597403Sobrien        {
87697403Sobrien	  typedef basic_string<_CharT> __string_type;
87797403Sobrien          locale __loc = __io.getloc();
87897403Sobrien	  const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); 
87997403Sobrien	  __string_type __name;
88097403Sobrien          if (__v)
88197403Sobrien	    __name = __np.truename();
88297403Sobrien          else
88397403Sobrien	    __name = __np.falsename();
88497403Sobrien	  __s = _M_insert(__s, __io, __fill, __name.c_str(), __name.size()); 
88597403Sobrien	}
88697403Sobrien      return __s;
88797403Sobrien    }
88897403Sobrien
88997403Sobrien  template<typename _CharT, typename _OutIter>
89097403Sobrien    _OutIter
89197403Sobrien    num_put<_CharT, _OutIter>::
89297403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, long __v) const
893102782Skan    { return _M_convert_int(__s, __io, __fill, 'd', char(), __v); }
89497403Sobrien
89597403Sobrien  template<typename _CharT, typename _OutIter>
89697403Sobrien    _OutIter
89797403Sobrien    num_put<_CharT, _OutIter>::
89897403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
89997403Sobrien           unsigned long __v) const
900102782Skan    { return _M_convert_int(__s, __io, __fill, 'u', char(), __v); }
90197403Sobrien
90297403Sobrien#ifdef _GLIBCPP_USE_LONG_LONG
90397403Sobrien  template<typename _CharT, typename _OutIter>
90497403Sobrien    _OutIter
90597403Sobrien    num_put<_CharT, _OutIter>::
90697403Sobrien    do_put(iter_type __s, ios_base& __b, char_type __fill, long long __v) const
90797403Sobrien    { return _M_convert_int(__s, __b, __fill, 'd', 'l', __v); }
90897403Sobrien
90997403Sobrien  template<typename _CharT, typename _OutIter>
91097403Sobrien    _OutIter
91197403Sobrien    num_put<_CharT, _OutIter>::
91297403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
91397403Sobrien           unsigned long long __v) const
91497403Sobrien    { return _M_convert_int(__s, __io, __fill, 'u', 'l', __v); }
91597403Sobrien#endif
91697403Sobrien
91797403Sobrien  template<typename _CharT, typename _OutIter>
91897403Sobrien    _OutIter
91997403Sobrien    num_put<_CharT, _OutIter>::
92097403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill, double __v) const
921102782Skan    { return _M_convert_float(__s, __io, __fill, char(), __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	   long double __v) const
92897403Sobrien    { return _M_convert_float(__s, __io, __fill, 'L', __v); }
92997403Sobrien
93097403Sobrien  template<typename _CharT, typename _OutIter>
93197403Sobrien    _OutIter
93297403Sobrien    num_put<_CharT, _OutIter>::
93397403Sobrien    do_put(iter_type __s, ios_base& __io, char_type __fill,
93497403Sobrien           const void* __v) const
93597403Sobrien    {
93697403Sobrien      ios_base::fmtflags __flags = __io.flags();
93797403Sobrien      ios_base::fmtflags __fmt = ~(ios_base::showpos | ios_base::basefield
93897403Sobrien				   | ios_base::uppercase | ios_base::internal);
93997403Sobrien      __io.flags(__flags & __fmt | (ios_base::hex | ios_base::showbase));
94097403Sobrien      try 
94197403Sobrien	{
942102782Skan	  __s = _M_convert_int(__s, __io, __fill, 'u', char(),
94397403Sobrien			       reinterpret_cast<unsigned long>(__v));
94497403Sobrien	  __io.flags(__flags);
94597403Sobrien	}
94697403Sobrien      catch (...) 
94797403Sobrien	{
94897403Sobrien	  __io.flags(__flags);
94997403Sobrien	  __throw_exception_again;
95097403Sobrien	}
95197403Sobrien      return __s;
95297403Sobrien    }
95397403Sobrien
95497403Sobrien
95597403Sobrien  template<typename _CharT, typename _InIter>
95697403Sobrien    _InIter
95797403Sobrien    money_get<_CharT, _InIter>::
95897403Sobrien    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 
95997403Sobrien	   ios_base::iostate& __err, long double& __units) const
96097403Sobrien    { 
96197403Sobrien      string_type __str;
96297403Sobrien      __beg = this->do_get(__beg, __end, __intl, __io, __err, __str); 
96397403Sobrien
96497403Sobrien      const int __n = numeric_limits<long double>::digits10;
96597403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__n));
96697403Sobrien      const locale __loc = __io.getloc();
96797403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
96897403Sobrien      const _CharT* __wcs = __str.c_str();
96997403Sobrien      __ctype.narrow(__wcs, __wcs + __str.size() + 1, char(), __cs);      
97097403Sobrien      __convert_to_v(__cs, __units, __err, _S_c_locale);
97197403Sobrien      return __beg;
97297403Sobrien    }
97397403Sobrien
97497403Sobrien  template<typename _CharT, typename _InIter>
97597403Sobrien    _InIter
97697403Sobrien    money_get<_CharT, _InIter>::
97797403Sobrien    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io, 
97897403Sobrien	   ios_base::iostate& __err, string_type& __units) const
97997403Sobrien    { 
98097403Sobrien      // These contortions are quite unfortunate.
98197403Sobrien      typedef moneypunct<_CharT, true> 		__money_true;
98297403Sobrien      typedef moneypunct<_CharT, false> 	__money_false;
98397403Sobrien      typedef money_base::part 			part;
98497403Sobrien      typedef typename string_type::size_type 	size_type;
98597403Sobrien
98697403Sobrien      const locale __loc = __io.getloc();
98797403Sobrien      const __money_true& __mpt = use_facet<__money_true>(__loc); 
98897403Sobrien      const __money_false& __mpf = use_facet<__money_false>(__loc); 
98997403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
99097403Sobrien
99197403Sobrien      const money_base::pattern __p = __intl ? __mpt.neg_format() 
99297403Sobrien					     : __mpf.neg_format();
99397403Sobrien
99497403Sobrien      const string_type __pos_sign =__intl ? __mpt.positive_sign() 
99597403Sobrien					   : __mpf.positive_sign();
99697403Sobrien      const string_type __neg_sign =__intl ? __mpt.negative_sign() 
99797403Sobrien					   : __mpf.negative_sign();
99897403Sobrien      const char_type __d = __intl ? __mpt.decimal_point() 
99997403Sobrien  	    	       		   : __mpf.decimal_point();
100097403Sobrien      const char_type __sep = __intl ? __mpt.thousands_sep() 
100197403Sobrien		    		     : __mpf.thousands_sep();
100297403Sobrien
100397403Sobrien      const string __grouping = __intl ? __mpt.grouping() : __mpf.grouping();
100497403Sobrien
100597403Sobrien      // Set to deduced positive or negative sign, depending.
100697403Sobrien      string_type __sign;
100797403Sobrien      // String of grouping info from thousands_sep plucked from __units.
100897403Sobrien      string __grouping_tmp; 
100997403Sobrien      // Marker for thousands_sep position.
101097403Sobrien      int __sep_pos = 0;
101197403Sobrien      // If input iterator is in a valid state.
101297403Sobrien      bool __testvalid = true;
101397403Sobrien      // Flag marking when a decimal point is found.
101497403Sobrien      bool __testdecfound = false; 
101597403Sobrien
101697403Sobrien      // The tentative returned string is stored here.
101797403Sobrien      string_type __temp_units;
101897403Sobrien
101997403Sobrien      char_type __c = *__beg;
102097403Sobrien      char_type __eof = static_cast<char_type>(char_traits<char_type>::eof());
102197403Sobrien      for (int __i = 0; __beg != __end && __i < 4 && __testvalid; ++__i)
102297403Sobrien	{
102397403Sobrien	  part __which = static_cast<part>(__p.field[__i]);
102497403Sobrien	  switch (__which)
102597403Sobrien		{
102697403Sobrien		case money_base::symbol:
102797403Sobrien		  if (__io.flags() & ios_base::showbase 
102897403Sobrien		      || __i < 2 || __sign.size() > 1
102997403Sobrien		      || ((static_cast<part>(__p.field[3]) != money_base::none)
103097403Sobrien			  && __i == 2)) 
103197403Sobrien		    {
103297403Sobrien		      // According to 22.2.6.1.2.2, symbol is required
103397403Sobrien		      // if (__io.flags() & ios_base::showbase),
103497403Sobrien		      // otherwise is optional and consumed only if
103597403Sobrien		      // other characters are needed to complete the
103697403Sobrien		      // format.
103797403Sobrien		      const string_type __symbol = __intl ? __mpt.curr_symbol()
103897403Sobrien						    	 : __mpf.curr_symbol();
103997403Sobrien		      size_type __len = __symbol.size();
104097403Sobrien		      size_type __j = 0;
104197403Sobrien		      while (__beg != __end 
104297403Sobrien			     && __j < __len && __symbol[__j] == __c)
104397403Sobrien			{
104497403Sobrien			  __c = *(++__beg);
104597403Sobrien			  ++__j;
104697403Sobrien			}
104797403Sobrien		      // When (__io.flags() & ios_base::showbase)
104897403Sobrien		      // symbol is required.
104997403Sobrien		      if (__j != __len && (__io.flags() & ios_base::showbase))
105097403Sobrien			__testvalid = false;
105197403Sobrien		    }
105297403Sobrien		  break;
105397403Sobrien		case money_base::sign:		    
105497403Sobrien		  // Sign might not exist, or be more than one character long. 
105597403Sobrien		  if (__pos_sign.size() && __neg_sign.size())
105697403Sobrien		  {
105797403Sobrien		    // Sign is mandatory.
105897403Sobrien		    if (__c == __pos_sign[0])
105997403Sobrien		      {
106097403Sobrien			__sign = __pos_sign;
106197403Sobrien			__c = *(++__beg);
106297403Sobrien		      }
106397403Sobrien		    else if (__c == __neg_sign[0])
106497403Sobrien		      {
106597403Sobrien			__sign = __neg_sign;
106697403Sobrien			__c = *(++__beg);
106797403Sobrien		      }
106897403Sobrien		    else
106997403Sobrien		      __testvalid = false;
107097403Sobrien		  }
107197403Sobrien		  else if (__pos_sign.size() && __c == __pos_sign[0])
107297403Sobrien		    {
107397403Sobrien		      __sign = __pos_sign;
107497403Sobrien		      __c = *(++__beg);
107597403Sobrien		    }
107697403Sobrien		  else if (__neg_sign.size() && __c == __neg_sign[0])
107797403Sobrien		    {
107897403Sobrien		      __sign = __neg_sign;
107997403Sobrien		      __c = *(++__beg);
108097403Sobrien		    }
108197403Sobrien		  break;
108297403Sobrien		case money_base::value:
108397403Sobrien		  // Extract digits, remove and stash away the
108497403Sobrien		  // grouping of found thousands separators.
108597403Sobrien		  while (__beg != __end 
108697403Sobrien			 && (__ctype.is(ctype_base::digit, __c) 
108797403Sobrien			     || (__c == __d && !__testdecfound)
108897403Sobrien			     || __c == __sep))
108997403Sobrien		    {
109097403Sobrien		      if (__c == __d)
109197403Sobrien			{
109297403Sobrien			  __grouping_tmp += static_cast<char>(__sep_pos);
109397403Sobrien			  __sep_pos = 0;
109497403Sobrien			  __testdecfound = true;
109597403Sobrien			}
109697403Sobrien		      else if (__c == __sep)
109797403Sobrien			{
109897403Sobrien			  if (__grouping.size())
109997403Sobrien			    {
110097403Sobrien			      // Mark position for later analysis.
110197403Sobrien			      __grouping_tmp += static_cast<char>(__sep_pos);
110297403Sobrien			      __sep_pos = 0;
110397403Sobrien			    }
110497403Sobrien			  else
110597403Sobrien			    {
110697403Sobrien			      __testvalid = false;
110797403Sobrien			      break;
110897403Sobrien			    }
110997403Sobrien			}
111097403Sobrien		      else
111197403Sobrien			{
111297403Sobrien			  __temp_units += __c;
111397403Sobrien			  ++__sep_pos;
111497403Sobrien			}
111597403Sobrien		      __c = *(++__beg);
111697403Sobrien		    }
111797403Sobrien		  break;
111897403Sobrien		case money_base::space:
111997403Sobrien		case money_base::none:
112097403Sobrien		  // Only if not at the end of the pattern.
112197403Sobrien		  if (__i != 3)
112297403Sobrien		    while (__beg != __end 
112397403Sobrien			   && __ctype.is(ctype_base::space, __c))
112497403Sobrien		      __c = *(++__beg);
112597403Sobrien		  break;
112697403Sobrien		}
112797403Sobrien	}
112897403Sobrien
112997403Sobrien      // Need to get the rest of the sign characters, if they exist.
113097403Sobrien      if (__sign.size() > 1)
113197403Sobrien	{
113297403Sobrien	  size_type __len = __sign.size();
113397403Sobrien	  size_type __i = 1;
113497403Sobrien	  for (; __c != __eof && __i < __len; ++__i)
113597403Sobrien	    while (__beg != __end && __c != __sign[__i])
113697403Sobrien	      __c = *(++__beg);
113797403Sobrien	  
113897403Sobrien	  if (__i != __len)
113997403Sobrien	    __testvalid = false;
114097403Sobrien	}
114197403Sobrien
114297403Sobrien      // Strip leading zeros.
114397403Sobrien      while (__temp_units[0] == __ctype.widen('0'))
114497403Sobrien	__temp_units.erase(__temp_units.begin());
114597403Sobrien
114697403Sobrien      if (__sign.size() && __sign == __neg_sign)
114797403Sobrien	__temp_units.insert(__temp_units.begin(), __ctype.widen('-'));
114897403Sobrien
114997403Sobrien      // Test for grouping fidelity.
115097403Sobrien      if (__grouping.size() && __grouping_tmp.size())
115197403Sobrien	{
115297403Sobrien	  if (!__verify_grouping(__grouping, __grouping_tmp))
115397403Sobrien	    __testvalid = false;
115497403Sobrien	}
115597403Sobrien
115697403Sobrien      // Iff no more characters are available.      
115797403Sobrien      if (__c == __eof)
115897403Sobrien	__err |= ios_base::eofbit;
115997403Sobrien
116097403Sobrien      // Iff valid sequence is not recognized.
116197403Sobrien      if (!__testvalid || !__temp_units.size())
116297403Sobrien	__err |= ios_base::failbit;
116397403Sobrien      else
116497403Sobrien	// Use the "swap trick" to copy __temp_units into __units.
116597403Sobrien	__temp_units.swap(__units);
116697403Sobrien
116797403Sobrien      return __beg; 
116897403Sobrien    }
116997403Sobrien
117097403Sobrien  template<typename _CharT, typename _OutIter>
117197403Sobrien    _OutIter
117297403Sobrien    money_put<_CharT, _OutIter>::
117397403Sobrien    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
117497403Sobrien	   long double __units) const
117597403Sobrien    { 
117697403Sobrien      const locale __loc = __io.getloc();
117797403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
117897403Sobrien#ifdef _GLIBCPP_USE_C99
117997403Sobrien      // First try a buffer perhaps big enough.
118097403Sobrien      int __cs_size = 64;
118197403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
118297403Sobrien      int __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 
118397403Sobrien				   _S_c_locale);
118497403Sobrien      // If the buffer was not large enough, try again with the correct size.
118597403Sobrien      if (__len >= __cs_size)
118697403Sobrien	{
118797403Sobrien	  __cs_size = __len + 1;
118897403Sobrien	  __cs = static_cast<char*>(__builtin_alloca(__cs_size));
118997403Sobrien	  __len = __convert_from_v(__cs, __cs_size, "%.01Lf", __units, 
119097403Sobrien				   _S_c_locale);
119197403Sobrien	}
119297403Sobrien#else
119397403Sobrien      // max_exponent10 + 1 for the integer part, + 4 for sign, decimal point,
119497403Sobrien      // decimal digit, '\0'. 
119597403Sobrien      const int __cs_size = numeric_limits<long double>::max_exponent10 + 5;
119697403Sobrien      char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
119797403Sobrien      int __len = __convert_from_v(__cs, 0, "%.01Lf", __units, _S_c_locale);
119897403Sobrien#endif
119997403Sobrien      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size));
120097403Sobrien      __ctype.widen(__cs, __cs + __len, __ws);
120197403Sobrien      string_type __digits(__ws);
120297403Sobrien      return this->do_put(__s, __intl, __io, __fill, __digits); 
120397403Sobrien    }
120497403Sobrien
120597403Sobrien  template<typename _CharT, typename _OutIter>
120697403Sobrien    _OutIter
120797403Sobrien    money_put<_CharT, _OutIter>::
120897403Sobrien    do_put(iter_type __s, bool __intl, ios_base& __io, char_type __fill,
120997403Sobrien	   const string_type& __digits) const
121097403Sobrien    { 
121197403Sobrien      typedef typename string_type::size_type 	size_type;
121297403Sobrien      typedef money_base::part 			part;
121397403Sobrien
121497403Sobrien      const locale __loc = __io.getloc();
121597403Sobrien      const size_type __width = static_cast<size_type>(__io.width());
121697403Sobrien
121797403Sobrien      // These contortions are quite unfortunate.
121897403Sobrien      typedef moneypunct<_CharT, true> __money_true;
121997403Sobrien      typedef moneypunct<_CharT, false> __money_false;
122097403Sobrien      const __money_true& __mpt = use_facet<__money_true>(__loc); 
122197403Sobrien      const __money_false& __mpf = use_facet<__money_false>(__loc); 
122297403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
122397403Sobrien
122497403Sobrien      // Determine if negative or positive formats are to be used, and
122597403Sobrien      // discard leading negative_sign if it is present.
122697403Sobrien      const char_type* __beg = __digits.data();
122797403Sobrien      const char_type* __end = __beg + __digits.size();
122897403Sobrien      money_base::pattern __p;
122997403Sobrien      string_type __sign;
123097403Sobrien      if (*__beg != __ctype.widen('-'))
123197403Sobrien	{
123297403Sobrien	  __p = __intl ? __mpt.pos_format() : __mpf.pos_format();
123397403Sobrien	  __sign =__intl ? __mpt.positive_sign() : __mpf.positive_sign();
123497403Sobrien	}
123597403Sobrien      else
123697403Sobrien	{
123797403Sobrien	  __p = __intl ? __mpt.neg_format() : __mpf.neg_format();
123897403Sobrien	  __sign =__intl ? __mpt.negative_sign() : __mpf.negative_sign();
123997403Sobrien	  ++__beg;
124097403Sobrien	}
124197403Sobrien      
124297403Sobrien      // Look for valid numbers in the current ctype facet within input digits.
124397403Sobrien      __end = __ctype.scan_not(ctype_base::digit, __beg, __end);
124497403Sobrien      if (__beg != __end)
124597403Sobrien	{
124697403Sobrien	  // Assume valid input, and attempt to format.
124797403Sobrien	  // Break down input numbers into base components, as follows:
124897403Sobrien	  //   final_value = grouped units + (decimal point) + (digits)
124997403Sobrien	  string_type __res;
125097403Sobrien	  string_type __value;
125197403Sobrien	  const string_type __symbol = __intl ? __mpt.curr_symbol() 
125297403Sobrien	    				      : __mpf.curr_symbol();
125397403Sobrien
125497403Sobrien	  // Deal with decimal point, decimal digits.
125597403Sobrien	  const int __frac = __intl ? __mpt.frac_digits() 
125697403Sobrien	    			    : __mpf.frac_digits();
125797403Sobrien	  if (__frac > 0)
125897403Sobrien	    {
125997403Sobrien	      const char_type __d = __intl ? __mpt.decimal_point() 
126097403Sobrien					   : __mpf.decimal_point();
126197403Sobrien	      if (__end - __beg >= __frac)
126297403Sobrien		{
126397403Sobrien		  __value = string_type(__end - __frac, __end);
126497403Sobrien		  __value.insert(__value.begin(), __d);
126597403Sobrien		  __end -= __frac;
126697403Sobrien		}
126797403Sobrien	      else
126897403Sobrien		{
126997403Sobrien		  // Have to pad zeros in the decimal position.
127097403Sobrien		  __value = string_type(__beg, __end);
127197403Sobrien		  int __paddec = __frac - (__end - __beg);
127297403Sobrien		  char_type __zero = __ctype.widen('0');
127397403Sobrien		  __value.insert(__value.begin(), __paddec, __zero);
127497403Sobrien		  __value.insert(__value.begin(), __d);
127597403Sobrien		  __beg = __end;
127697403Sobrien		}
127797403Sobrien	    }
127897403Sobrien
127997403Sobrien	  // Add thousands separators to non-decimal digits, per
128097403Sobrien	  // grouping rules.
128197403Sobrien	  if (__beg != __end)
128297403Sobrien	    {
128397403Sobrien	      const string __grouping = __intl ? __mpt.grouping() 
128497403Sobrien					       : __mpf.grouping();
128597403Sobrien	      if (__grouping.size())
128697403Sobrien		{
128797403Sobrien		  const char_type __sep = __intl ? __mpt.thousands_sep() 
128897403Sobrien		    			         : __mpf.thousands_sep();
128997403Sobrien		  const char* __gbeg = __grouping.c_str();
129097403Sobrien		  const char* __gend = __gbeg + __grouping.size();
129197403Sobrien		  const int __n = (__end - __beg) * 2;
129297403Sobrien		  _CharT* __ws2 =
129397403Sobrien		    static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __n));
129497403Sobrien		  _CharT* __ws_end = __add_grouping(__ws2, __sep, __gbeg, 
129597403Sobrien						    __gend, __beg, __end);
129697403Sobrien		  __value.insert(0, __ws2, __ws_end - __ws2);
129797403Sobrien		}
129897403Sobrien	      else
129997403Sobrien		__value.insert(0, string_type(__beg, __end));
130097403Sobrien	    }
130197403Sobrien
130297403Sobrien	  // Calculate length of resulting string.
130397403Sobrien	  ios_base::fmtflags __f = __io.flags() & ios_base::adjustfield;
130497403Sobrien	  size_type __len = __value.size() + __sign.size();
130597403Sobrien	  __len += (__io.flags() & ios_base::showbase) ? __symbol.size() : 0;
130697403Sobrien	  bool __testipad = __f == ios_base::internal && __len < __width;
130797403Sobrien
130897403Sobrien	  // Fit formatted digits into the required pattern.
130997403Sobrien	  for (int __i = 0; __i < 4; ++__i)
131097403Sobrien	    {
131197403Sobrien	      part __which = static_cast<part>(__p.field[__i]);
131297403Sobrien	      switch (__which)
131397403Sobrien		{
131497403Sobrien		case money_base::symbol:
131597403Sobrien		  if (__io.flags() & ios_base::showbase)
131697403Sobrien		    __res += __symbol;
131797403Sobrien		  break;
131897403Sobrien		case money_base::sign:		    
131997403Sobrien		  // Sign might not exist, or be more than one
132097403Sobrien		  // charater long. In that case, add in the rest
132197403Sobrien		  // below.
132297403Sobrien		  if (__sign.size())
132397403Sobrien		    __res += __sign[0];
132497403Sobrien		  break;
132597403Sobrien		case money_base::value:
132697403Sobrien		  __res += __value;
132797403Sobrien		  break;
132897403Sobrien		case money_base::space:
132997403Sobrien		  // At least one space is required, but if internal
133097403Sobrien		  // formatting is required, an arbitrary number of
133197403Sobrien		  // fill spaces will be necessary.
133297403Sobrien		  if (__testipad)
133397403Sobrien		    __res += string_type(__width - __len, __fill);
133497403Sobrien		  else
133597403Sobrien		    __res += __ctype.widen(__fill);
133697403Sobrien		  break;
133797403Sobrien		case money_base::none:
133897403Sobrien		  if (__testipad)
133997403Sobrien		    __res += string_type(__width - __len, __fill);
134097403Sobrien		  break;
134197403Sobrien		}
134297403Sobrien	    }
134397403Sobrien
134497403Sobrien	  // Special case of multi-part sign parts.
134597403Sobrien	  if (__sign.size() > 1)
134697403Sobrien	    __res += string_type(__sign.begin() + 1, __sign.end());
134797403Sobrien
134897403Sobrien	  // Pad, if still necessary.
134997403Sobrien	  __len = __res.size();
135097403Sobrien	  if (__width > __len)
135197403Sobrien	    {
135297403Sobrien	      if (__f == ios_base::left)
135397403Sobrien		// After.
135497403Sobrien		__res.append(__width - __len, __fill);
135597403Sobrien	      else
135697403Sobrien		// Before.
135797403Sobrien		__res.insert(0, string_type(__width - __len, __fill));
135897403Sobrien	      __len = __width;
135997403Sobrien	    }
136097403Sobrien
136197403Sobrien	  // Write resulting, fully-formatted string to output iterator.
136297403Sobrien	  for (size_type __j = 0; __j < __len; ++__j, ++__s)
136397403Sobrien	    *__s = __res[__j];
136497403Sobrien	}
136597403Sobrien      __io.width(0);
136697403Sobrien      return __s; 
136797403Sobrien    }
136897403Sobrien
136997403Sobrien
137097403Sobrien  // NB: Not especially useful. Without an ios_base object or some
137197403Sobrien  // kind of locale reference, we are left clawing at the air where
137297403Sobrien  // the side of the mountain used to be...
137397403Sobrien  template<typename _CharT, typename _InIter>
137497403Sobrien    time_base::dateorder
137597403Sobrien    time_get<_CharT, _InIter>::do_date_order() const
137697403Sobrien    { return time_base::no_order; }
137797403Sobrien
137897403Sobrien  template<typename _CharT, typename _InIter>
137997403Sobrien    void
138097403Sobrien    time_get<_CharT, _InIter>::
138197403Sobrien    _M_extract_via_format(iter_type& __beg, iter_type& __end, ios_base& __io,
138297403Sobrien			  ios_base::iostate& __err, tm* __tm, 
138397403Sobrien			  const _CharT* __format) const
138497403Sobrien    {  
138597403Sobrien      locale __loc = __io.getloc();
138697403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
138797403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
138897403Sobrien      size_t __len = char_traits<_CharT>::length(__format);
138997403Sobrien
139097403Sobrien      for (size_t __i = 0; __beg != __end && __i < __len && !__err; ++__i)
139197403Sobrien	{
139297403Sobrien	  char __c = __format[__i];
139397403Sobrien	  if (__c == '%')
139497403Sobrien	    {
139597403Sobrien	      // Verify valid formatting code, attempt to extract.
139697403Sobrien	      __c = __format[++__i];
139797403Sobrien	      char __mod = 0;
139897403Sobrien	      int __mem = 0; 
139997403Sobrien	      if (__c == 'E' || __c == 'O')
140097403Sobrien		{
140197403Sobrien		  __mod = __c;
140297403Sobrien		  __c = __format[++__i];
140397403Sobrien		}
140497403Sobrien	      switch (__c)
140597403Sobrien		{
140697403Sobrien		  const char* __cs;
140797403Sobrien		  _CharT __wcs[10];
140897403Sobrien		case 'a':
140997403Sobrien		  // Abbreviated weekday name [tm_wday]
141097403Sobrien		  const char_type*  __days1[7];
141197403Sobrien		  __tp._M_days_abbreviated(__days1);
141297403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_wday, __days1, 7, 
141397403Sobrien				  __err);
141497403Sobrien		  break;
141597403Sobrien		case 'A':
141697403Sobrien		  // Weekday name [tm_wday].
141797403Sobrien		  const char_type*  __days2[7];
141897403Sobrien		  __tp._M_days(__days2);
141997403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_wday, __days2, 7, 
142097403Sobrien				  __err);
142197403Sobrien		  break;
142297403Sobrien		case 'h':
142397403Sobrien		case 'b':
142497403Sobrien		  // Abbreviated month name [tm_mon]
142597403Sobrien		  const char_type*  __months1[12];
142697403Sobrien		  __tp._M_months_abbreviated(__months1);
142797403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_mon, __months1, 12, 
142897403Sobrien				  __err);
142997403Sobrien		  break;
143097403Sobrien		case 'B':
143197403Sobrien		  // Month name [tm_mon].
143297403Sobrien		  const char_type*  __months2[12];
143397403Sobrien		  __tp._M_months(__months2);
143497403Sobrien		  _M_extract_name(__beg, __end, __tm->tm_mon, __months2, 12, 
143597403Sobrien				  __err);
143697403Sobrien		  break;
143797403Sobrien		case 'c':
143897403Sobrien		  // Default time and date representation.
143997403Sobrien		  const char_type*  __dt[2];
144097403Sobrien		  __tp._M_date_time_formats(__dt);
144197403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
144297403Sobrien					__dt[0]);
144397403Sobrien		  break;
144497403Sobrien		case 'd':
144597403Sobrien		  // Day [01, 31]. [tm_mday]
144697403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, 
144797403Sobrien				 __ctype, __err);
144897403Sobrien		  break;
144997403Sobrien		case 'D':
145097403Sobrien		  // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year]
145197403Sobrien		  __cs = "%m/%d/%y";
145297403Sobrien		  __ctype.widen(__cs, __cs + 9, __wcs);
145397403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
145497403Sobrien					__wcs);
145597403Sobrien		  break;
145697403Sobrien		case 'H':
145797403Sobrien		  // Hour [00, 23]. [tm_hour]
145897403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2,
145997403Sobrien				 __ctype, __err);
146097403Sobrien		  break;
146197403Sobrien		case 'I':
146297403Sobrien		  // Hour [01, 12]. [tm_hour]
146397403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, 
146497403Sobrien				 __ctype, __err);
146597403Sobrien		  break;
146697403Sobrien		case 'm':
146797403Sobrien		  // Month [01, 12]. [tm_mon]
146897403Sobrien		  _M_extract_num(__beg, __end, __mem, 1, 12, 2, __ctype, 
146997403Sobrien				 __err);
147097403Sobrien		  if (!__err)
147197403Sobrien		    __tm->tm_mon = __mem - 1;
147297403Sobrien		  break;
147397403Sobrien		case 'M':
147497403Sobrien		  // Minute [00, 59]. [tm_min]
147597403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2,
147697403Sobrien				 __ctype, __err);
147797403Sobrien		  break;
147897403Sobrien		case 'n':
147997403Sobrien		  if (__ctype.narrow(*__beg, 0) == '\n')
148097403Sobrien		    ++__beg;
148197403Sobrien		  else
148297403Sobrien		    __err |= ios_base::failbit;
148397403Sobrien		  break;
148497403Sobrien		case 'R':
148597403Sobrien		  // Equivalent to (%H:%M).
148697403Sobrien		  __cs = "%H:%M";
148797403Sobrien		  __ctype.widen(__cs, __cs + 6, __wcs);
148897403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
148997403Sobrien					__wcs);
149097403Sobrien		  break;
149197403Sobrien		case 'S':
149297403Sobrien		  // Seconds.
149397403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_sec, 0, 59, 2,
149497403Sobrien				 __ctype, __err);
149597403Sobrien		  break;
149697403Sobrien		case 't':
149797403Sobrien		  if (__ctype.narrow(*__beg, 0) == '\t')
149897403Sobrien		    ++__beg;
149997403Sobrien		  else
150097403Sobrien		__err |= ios_base::failbit;
150197403Sobrien		  break;
150297403Sobrien		case 'T':
150397403Sobrien		  // Equivalent to (%H:%M:%S).
150497403Sobrien		  __cs = "%H:%M:%S";
150597403Sobrien		  __ctype.widen(__cs, __cs + 9, __wcs);
150697403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
150797403Sobrien					__wcs);
150897403Sobrien		  break;
150997403Sobrien		case 'x':
151097403Sobrien		  // Locale's date.
151197403Sobrien		  const char_type*  __dates[2];
151297403Sobrien		  __tp._M_date_formats(__dates);
151397403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
151497403Sobrien					__dates[0]);
151597403Sobrien		  break;
151697403Sobrien		case 'X':
151797403Sobrien		  // Locale's time.
151897403Sobrien		  const char_type*  __times[2];
151997403Sobrien		  __tp._M_time_formats(__times);
152097403Sobrien		  _M_extract_via_format(__beg, __end, __io, __err, __tm, 
152197403Sobrien					__times[0]);
152297403Sobrien		  break;
152397403Sobrien		case 'y':
152497403Sobrien		  // Two digit year. [tm_year]
152597403Sobrien		  _M_extract_num(__beg, __end, __tm->tm_year, 0, 99, 2, 
152697403Sobrien				 __ctype, __err);
152797403Sobrien		  break;
152897403Sobrien		case 'Y':
152997403Sobrien		  // Year [1900). [tm_year]
153097403Sobrien		  _M_extract_num(__beg, __end, __mem, 0, 
153197403Sobrien				 numeric_limits<int>::max(), 4, 
153297403Sobrien				 __ctype, __err);
153397403Sobrien		  if (!__err)
153497403Sobrien		    __tm->tm_year = __mem - 1900;
153597403Sobrien		  break;
153697403Sobrien		case 'Z':
153797403Sobrien		  // Timezone info.
153897403Sobrien		  if (__ctype.is(ctype_base::upper, *__beg))
153997403Sobrien		    {
154097403Sobrien		      int __tmp;
154197403Sobrien		      _M_extract_name(__beg, __end, __tmp, 
154297403Sobrien				      __timepunct<_CharT>::_S_timezones, 
154397403Sobrien				      14, __err);
154497403Sobrien		      
154597403Sobrien		      // GMT requires special effort.
154697403Sobrien		      char_type __c = *__beg;
154797403Sobrien		      if (!__err && __tmp == 0 
154897403Sobrien			  && (__c == __ctype.widen('-') 
154997403Sobrien			      || __c == __ctype.widen('+')))
155097403Sobrien			{
155197403Sobrien			  _M_extract_num(__beg, __end, __tmp, 0, 23, 2,
155297403Sobrien					  __ctype, __err);
155397403Sobrien			  _M_extract_num(__beg, __end, __tmp, 0, 59, 2,
155497403Sobrien					  __ctype, __err);
155597403Sobrien			}	    
155697403Sobrien			  }
155797403Sobrien		      else
155897403Sobrien			__err |= ios_base::failbit;
155997403Sobrien		      break;
156097403Sobrien		    default:
156197403Sobrien		      // Not recognized.
156297403Sobrien		      __err |= ios_base::failbit;
156397403Sobrien		    }
156497403Sobrien		}
156597403Sobrien	      else
156697403Sobrien		{
156797403Sobrien		  // Verify format and input match, extract and discard.
156897403Sobrien		  if (__c == __ctype.narrow(*__beg, 0))
156997403Sobrien		    ++__beg;
157097403Sobrien		  else
157197403Sobrien		    __err |= ios_base::failbit;
157297403Sobrien		}
157397403Sobrien	}
157497403Sobrien    }
157597403Sobrien
157697403Sobrien  template<typename _CharT, typename _InIter>
157797403Sobrien    void
157897403Sobrien    time_get<_CharT, _InIter>::
157997403Sobrien    _M_extract_num(iter_type& __beg, iter_type& __end, int& __member,
158097403Sobrien		   int __min, int __max, size_t __len, 
158197403Sobrien		   const ctype<_CharT>& __ctype, 
158297403Sobrien		   ios_base::iostate& __err) const
158397403Sobrien    {
158497403Sobrien      size_t __i = 0;
158597403Sobrien      string __digits;
158697403Sobrien      bool __testvalid = true;
158797403Sobrien      char_type __c = *__beg;
158897403Sobrien      while (__beg != __end && __i < __len 
158997403Sobrien	     && __ctype.is(ctype_base::digit, __c)) 
159097403Sobrien	{
159197403Sobrien	  __digits += __ctype.narrow(__c, 0);
159297403Sobrien	  __c = *(++__beg);
159397403Sobrien	  ++__i;
159497403Sobrien	}
159597403Sobrien      if (__i == __len)
159697403Sobrien	{
159797403Sobrien	  int __value = atoi(__digits.c_str());
159897403Sobrien	  if (__min <= __value && __value <= __max)
159997403Sobrien	    __member = __value;
160097403Sobrien	  else
160197403Sobrien	    __testvalid = false;
160297403Sobrien	}
160397403Sobrien      else
160497403Sobrien	__testvalid = false;
160597403Sobrien      if (!__testvalid)
160697403Sobrien	__err |= ios_base::failbit;
160797403Sobrien    }
160897403Sobrien
160997403Sobrien  // Assumptions:
161097403Sobrien  // All elements in __names are unique.
161197403Sobrien  template<typename _CharT, typename _InIter>
161297403Sobrien    void
161397403Sobrien    time_get<_CharT, _InIter>::
161497403Sobrien    _M_extract_name(iter_type& __beg, iter_type& __end, int& __member,
161597403Sobrien		    const _CharT** __names, size_t __indexlen, 
161697403Sobrien		    ios_base::iostate& __err) const
161797403Sobrien    {
1618102782Skan      typedef char_traits<_CharT> 		__traits_type;
161997403Sobrien      int* __matches = static_cast<int*>(__builtin_alloca(sizeof(int) * __indexlen));
162097403Sobrien      size_t __nmatches = 0;
162197403Sobrien      size_t __pos = 0;
162297403Sobrien      bool __testvalid = true;
162397403Sobrien      const char_type* __name;
162497403Sobrien
162597403Sobrien      char_type __c = *__beg;
162697403Sobrien      // Look for initial matches.
162797403Sobrien      for (size_t __i1 = 0; __i1 < __indexlen; ++__i1)
162897403Sobrien	if (__c == __names[__i1][0])
162997403Sobrien	  __matches[__nmatches++] = __i1;
163097403Sobrien      
163197403Sobrien      while(__nmatches > 1)
163297403Sobrien	{
163397403Sobrien	  // Find smallest matching string.
163497403Sobrien	  size_t __minlen = 10;
163597403Sobrien	  for (size_t __i2 = 0; __i2 < __nmatches; ++__i2)
1636110614Skan	    __minlen = min(__minlen,
163797403Sobrien			   __traits_type::length(__names[__matches[__i2]]));
163897403Sobrien	  
163997403Sobrien	  if (__pos < __minlen && __beg != __end)
164097403Sobrien	    {
164197403Sobrien	      ++__pos;
164297403Sobrien	      __c = *(++__beg);
164397403Sobrien	      for (size_t __i3 = 0; __i3 < __nmatches; ++__i3)
164497403Sobrien		{
164597403Sobrien		  __name = __names[__matches[__i3]];
164697403Sobrien		  if (__name[__pos] != __c)
164797403Sobrien		    __matches[__i3] = __matches[--__nmatches];
164897403Sobrien		}
164997403Sobrien	    }
165097403Sobrien	  else
165197403Sobrien	    break;
165297403Sobrien	}
165397403Sobrien
165497403Sobrien      if (__nmatches == 1)
165597403Sobrien	{
165697403Sobrien	  // Make sure found name is completely extracted.
165797403Sobrien	  __name = __names[__matches[0]];
165897403Sobrien	  const size_t __len = __traits_type::length(__name);
165997403Sobrien	  while (__pos < __len && __beg != __end && __name[__pos] == *__beg)
166097403Sobrien	    ++__beg, ++__pos;
166197403Sobrien
166297403Sobrien	  if (__len == __pos)
166397403Sobrien	    __member = __matches[0];
166497403Sobrien	  else
166597403Sobrien	    __testvalid = false;
166697403Sobrien	}
166797403Sobrien      else
166897403Sobrien	__testvalid = false;
166997403Sobrien      if (!__testvalid)
167097403Sobrien	__err |= ios_base::failbit;
167197403Sobrien    }
167297403Sobrien
167397403Sobrien  template<typename _CharT, typename _InIter>
167497403Sobrien    _InIter
167597403Sobrien    time_get<_CharT, _InIter>::
167697403Sobrien    do_get_time(iter_type __beg, iter_type __end, ios_base& __io,
167797403Sobrien		ios_base::iostate& __err, tm* __tm) const
167897403Sobrien    {
167997403Sobrien      _CharT __wcs[3];
168097403Sobrien      const char* __cs = "%X";
168197403Sobrien      locale __loc = __io.getloc();
168297403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
168397403Sobrien      __ctype.widen(__cs, __cs + 3, __wcs);
168497403Sobrien      _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
168597403Sobrien      if (__beg == __end)
168697403Sobrien	__err |= ios_base::eofbit;
168797403Sobrien      return __beg;
168897403Sobrien    }
168997403Sobrien
169097403Sobrien  template<typename _CharT, typename _InIter>
169197403Sobrien    _InIter
169297403Sobrien    time_get<_CharT, _InIter>::
169397403Sobrien    do_get_date(iter_type __beg, iter_type __end, ios_base& __io,
169497403Sobrien		ios_base::iostate& __err, tm* __tm) const
169597403Sobrien    {
169697403Sobrien      _CharT __wcs[3];
169797403Sobrien      const char* __cs = "%x";
169897403Sobrien      locale __loc = __io.getloc();
169997403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
170097403Sobrien      __ctype.widen(__cs, __cs + 3, __wcs);
170197403Sobrien      _M_extract_via_format(__beg, __end, __io, __err, __tm, __wcs);
170297403Sobrien      if (__beg == __end)
170397403Sobrien	__err |= ios_base::eofbit;
170497403Sobrien      return __beg;
170597403Sobrien    }
170697403Sobrien
170797403Sobrien  template<typename _CharT, typename _InIter>
170897403Sobrien    _InIter
170997403Sobrien    time_get<_CharT, _InIter>::
171097403Sobrien    do_get_weekday(iter_type __beg, iter_type __end, ios_base& __io, 
171197403Sobrien		   ios_base::iostate& __err, tm* __tm) const
171297403Sobrien    {
1713102782Skan      typedef char_traits<_CharT> 		__traits_type;
171497403Sobrien      locale __loc = __io.getloc();
171597403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
171697403Sobrien      const char_type*  __days[7];
171797403Sobrien      __tp._M_days_abbreviated(__days);
171897403Sobrien      int __tmpwday;
171997403Sobrien      _M_extract_name(__beg, __end, __tmpwday, __days, 7, __err);
172097403Sobrien
172197403Sobrien      // Check to see if non-abbreviated name exists, and extract.
172297403Sobrien      // NB: Assumes both _M_days and _M_days_abbreviated organized in
172397403Sobrien      // exact same order, first to last, such that the resulting
172497403Sobrien      // __days array with the same index points to a day, and that
172597403Sobrien      // day's abbreviated form.
172697403Sobrien      // NB: Also assumes that an abbreviated name is a subset of the name. 
172797403Sobrien      if (!__err)
172897403Sobrien	{
172997403Sobrien	  size_t __pos = __traits_type::length(__days[__tmpwday]);
173097403Sobrien	  __tp._M_days(__days);
173197403Sobrien	  const char_type* __name = __days[__tmpwday];
173297403Sobrien	  if (__name[__pos] == *__beg)
173397403Sobrien	    {
173497403Sobrien	      // Extract the rest of it.
173597403Sobrien	      const size_t __len = __traits_type::length(__name);
173697403Sobrien	      while (__pos < __len && __beg != __end 
173797403Sobrien		     && __name[__pos] == *__beg)
173897403Sobrien		++__beg, ++__pos;
173997403Sobrien	      if (__len != __pos)
174097403Sobrien		__err |= ios_base::failbit;
174197403Sobrien	    }
174297403Sobrien	  if (!__err)
174397403Sobrien	    __tm->tm_wday = __tmpwday;
174497403Sobrien	}
174597403Sobrien      if (__beg == __end)
174697403Sobrien	__err |= ios_base::eofbit;
174797403Sobrien      return __beg;
174897403Sobrien     }
174997403Sobrien
175097403Sobrien  template<typename _CharT, typename _InIter>
175197403Sobrien    _InIter
175297403Sobrien    time_get<_CharT, _InIter>::
175397403Sobrien    do_get_monthname(iter_type __beg, iter_type __end,
175497403Sobrien                     ios_base& __io, ios_base::iostate& __err, tm* __tm) const
175597403Sobrien    {
1756102782Skan      typedef char_traits<_CharT> 		__traits_type;
175797403Sobrien      locale __loc = __io.getloc();
175897403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
175997403Sobrien      const char_type*  __months[12];
176097403Sobrien      __tp._M_months_abbreviated(__months);
176197403Sobrien      int __tmpmon;
176297403Sobrien      _M_extract_name(__beg, __end, __tmpmon, __months, 12, __err);
176397403Sobrien
176497403Sobrien      // Check to see if non-abbreviated name exists, and extract.
176597403Sobrien      // NB: Assumes both _M_months and _M_months_abbreviated organized in
176697403Sobrien      // exact same order, first to last, such that the resulting
176797403Sobrien      // __months array with the same index points to a month, and that
176897403Sobrien      // month's abbreviated form.
176997403Sobrien      // NB: Also assumes that an abbreviated name is a subset of the name. 
177097403Sobrien      if (!__err)
177197403Sobrien	{
177297403Sobrien	  size_t __pos = __traits_type::length(__months[__tmpmon]);
177397403Sobrien	  __tp._M_months(__months);
177497403Sobrien	  const char_type* __name = __months[__tmpmon];
177597403Sobrien	  if (__name[__pos] == *__beg)
177697403Sobrien	    {
177797403Sobrien	      // Extract the rest of it.
177897403Sobrien	      const size_t __len = __traits_type::length(__name);
177997403Sobrien	      while (__pos < __len && __beg != __end 
178097403Sobrien		     && __name[__pos] == *__beg)
178197403Sobrien		++__beg, ++__pos;
178297403Sobrien	      if (__len != __pos)
178397403Sobrien		__err |= ios_base::failbit;
178497403Sobrien	    }
178597403Sobrien	  if (!__err)
178697403Sobrien	    __tm->tm_mon = __tmpmon;
178797403Sobrien	}
178897403Sobrien 
178997403Sobrien      if (__beg == __end)
179097403Sobrien	__err |= ios_base::eofbit;
179197403Sobrien      return __beg;
179297403Sobrien    }
179397403Sobrien
179497403Sobrien  template<typename _CharT, typename _InIter>
179597403Sobrien    _InIter
179697403Sobrien    time_get<_CharT, _InIter>::
179797403Sobrien    do_get_year(iter_type __beg, iter_type __end, ios_base& __io, 
179897403Sobrien		ios_base::iostate& __err, tm* __tm) const
179997403Sobrien    {
180097403Sobrien      locale __loc = __io.getloc();
180197403Sobrien      const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
180297403Sobrien
180397403Sobrien      char_type __c = *__beg;
180497403Sobrien      size_t __i = 0;
180597403Sobrien      string __digits;
180697403Sobrien      while (__i < 4 && __beg != __end && __ctype.is(ctype_base::digit, __c))
180797403Sobrien	{
180897403Sobrien	  __digits += __ctype.narrow(__c, 0);
180997403Sobrien	  __c = *(++__beg);
181097403Sobrien	  ++__i;
181197403Sobrien	}
181297403Sobrien      if (__i == 2 || __i == 4)
181397403Sobrien	{
181497403Sobrien	  long __l;
181597403Sobrien	  __convert_to_v(__digits.c_str(), __l, __err, _S_c_locale);
181697403Sobrien	  if (!(__err & ios_base::failbit) && __l <= INT_MAX)
181797403Sobrien	    {
181897403Sobrien	      __l = __i == 2 ? __l : __l - 1900; 
181997403Sobrien	      __tm->tm_year = static_cast<int>(__l);
182097403Sobrien	    }
182197403Sobrien	}
182297403Sobrien      else
182397403Sobrien	__err |= ios_base::failbit;
182497403Sobrien      if (__beg == __end)
182597403Sobrien	__err |= ios_base::eofbit;
182697403Sobrien      return __beg;
182797403Sobrien    }
182897403Sobrien
182997403Sobrien  template<typename _CharT, typename _OutIter>
183097403Sobrien    _OutIter
183197403Sobrien    time_put<_CharT, _OutIter>::
183297403Sobrien    put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 
183397403Sobrien	const _CharT* __beg, const _CharT* __end) const
183497403Sobrien    {
183597403Sobrien      locale __loc = __io.getloc();
183697403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
183797403Sobrien      while (__beg != __end)
183897403Sobrien	{
183997403Sobrien	  char __c = __ctype.narrow(*__beg, 0);
184097403Sobrien	  ++__beg;
184197403Sobrien	  if (__c == '%')
184297403Sobrien	    {
184397403Sobrien	      char __format;
184497403Sobrien	      char __mod = 0;
184597403Sobrien	      size_t __len = 1; 
184697403Sobrien	      __c = __ctype.narrow(*__beg, 0);
184797403Sobrien	      ++__beg;
184897403Sobrien	      if (__c == 'E' || __c == 'O')
184997403Sobrien		{
185097403Sobrien		  __mod = __c;
185197403Sobrien		  __format = __ctype.narrow(*__beg, 0);
185297403Sobrien		  ++__beg;
185397403Sobrien		}
185497403Sobrien	      else
185597403Sobrien		__format = __c;
185697403Sobrien	      __s = this->do_put(__s, __io, char_type(), __tm, __format, 
185797403Sobrien				 __mod);
185897403Sobrien	    }
185997403Sobrien	  else
186097403Sobrien	    {
186197403Sobrien	      *__s = __c;
186297403Sobrien	      ++__s;
186397403Sobrien	    }
186497403Sobrien	}
186597403Sobrien      return __s;
186697403Sobrien    }
186797403Sobrien
186897403Sobrien  template<typename _CharT, typename _OutIter>
186997403Sobrien    _OutIter
187097403Sobrien    time_put<_CharT, _OutIter>::
187197403Sobrien    do_put(iter_type __s, ios_base& __io, char_type, const tm* __tm, 
187297403Sobrien	   char __format, char __mod) const
187397403Sobrien    { 
187497403Sobrien      locale __loc = __io.getloc();
187597403Sobrien      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
187697403Sobrien      __timepunct<_CharT> const& __tp = use_facet<__timepunct<_CharT> >(__loc);
187797403Sobrien
187897403Sobrien      // NB: This size is arbitrary. Should this be a data member,
187997403Sobrien      // initialized at construction?
188097403Sobrien      const size_t __maxlen = 64;
188197403Sobrien      char_type* __res =
188297403Sobrien	static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __maxlen));
188397403Sobrien
188497403Sobrien      // NB: In IEE 1003.1-200x, and perhaps other locale models, it
188597403Sobrien      // is possible that the format character will be longer than one
188697403Sobrien      // character. Possibilities include 'E' or 'O' followed by a
188797403Sobrien      // format character: if __mod is not the default argument, assume
188897403Sobrien      // it's a valid modifier.
188997403Sobrien      char_type __fmt[4];
189097403Sobrien      __fmt[0] = __ctype.widen('%'); 
189197403Sobrien      if (!__mod)
189297403Sobrien	{
189397403Sobrien	  __fmt[1] = __format;
189497403Sobrien	  __fmt[2] = char_type();
189597403Sobrien	}
189697403Sobrien      else
189797403Sobrien	{
189897403Sobrien	  __fmt[1] = __mod;
189997403Sobrien	  __fmt[2] = __format;
190097403Sobrien	  __fmt[3] = char_type();
190197403Sobrien	}
190297403Sobrien
190397403Sobrien      __tp._M_put(__res, __maxlen, __fmt, __tm);
190497403Sobrien
190597403Sobrien      // Write resulting, fully-formatted string to output iterator.
190697403Sobrien      size_t __len = char_traits<char_type>::length(__res);
190797403Sobrien      for (size_t __i = 0; __i < __len; ++__i, ++__s)
190897403Sobrien	*__s = __res[__i];
190997403Sobrien      return __s;
191097403Sobrien    }
191197403Sobrien
191297403Sobrien
191397403Sobrien  // Generic version does nothing.
191497403Sobrien  template<typename _CharT>
191597403Sobrien    int
191697403Sobrien    collate<_CharT>::_M_compare(const _CharT*, const _CharT*) const
191797403Sobrien    { return 0; }
191897403Sobrien
191997403Sobrien  // Generic version does nothing.
192097403Sobrien  template<typename _CharT>
192197403Sobrien    size_t
192297403Sobrien    collate<_CharT>::_M_transform(_CharT*, const _CharT*, size_t) const
192397403Sobrien    { return 0; }
192497403Sobrien
192597403Sobrien  template<typename _CharT>
192697403Sobrien    int
192797403Sobrien    collate<_CharT>::
192897403Sobrien    do_compare(const _CharT* __lo1, const _CharT* __hi1, 
192997403Sobrien	       const _CharT* __lo2, const _CharT* __hi2) const
193097403Sobrien    { 
193197403Sobrien      const string_type __one(__lo1, __hi1);
193297403Sobrien      const string_type __two(__lo2, __hi2);
193397403Sobrien      return _M_compare(__one.c_str(), __two.c_str());
193497403Sobrien    }
193597403Sobrien
193697403Sobrien template<typename _CharT>
193797403Sobrien    typename collate<_CharT>::string_type
193897403Sobrien    collate<_CharT>::
193997403Sobrien    do_transform(const _CharT* __lo, const _CharT* __hi) const
194097403Sobrien    {
194197403Sobrien      size_t __len = (__hi - __lo) * 2;
194297403Sobrien      // First try a buffer perhaps big enough.
194397403Sobrien      _CharT* __c =
194497403Sobrien	static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
194597403Sobrien      size_t __res = _M_transform(__c, __lo, __len);
194697403Sobrien      // If the buffer was not large enough, try again with the correct size.
194797403Sobrien      if (__res >= __len)
194897403Sobrien	{
194997403Sobrien	  __c =
195097403Sobrien	    static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * (__res + 1)));
195197403Sobrien	  _M_transform(__c, __lo, __res + 1);
195297403Sobrien	}
195397403Sobrien      return string_type(__c);
195497403Sobrien    }
195597403Sobrien
195697403Sobrien template<typename _CharT>
195797403Sobrien    long
195897403Sobrien    collate<_CharT>::
195997403Sobrien    do_hash(const _CharT* __lo, const _CharT* __hi) const
196097403Sobrien    { 
196197403Sobrien      unsigned long __val = 0;
196297403Sobrien      for (; __lo < __hi; ++__lo)
196397403Sobrien	__val = *__lo + ((__val << 7) | 
196497403Sobrien		       (__val >> (numeric_limits<unsigned long>::digits - 7)));
196597403Sobrien      return static_cast<long>(__val);
196697403Sobrien    }
196797403Sobrien
196897403Sobrien  // Convert string to numeric value of type _Tv and store results.  
196997403Sobrien  // NB: This is specialized for all required types, there is no
197097403Sobrien  // generic definition.
197197403Sobrien  template<typename _Tv>
197297403Sobrien    void
197397403Sobrien    __convert_to_v(const char* __in, _Tv& __out, ios_base::iostate& __err, 
197497403Sobrien		   const __c_locale& __cloc, int __base = 10);
197597403Sobrien
197697403Sobrien  // Convert numeric value of type _Tv to string and return length of string.
197797403Sobrien  // If snprintf is available use it, otherwise fall back to the unsafe sprintf
197897403Sobrien  // which, in general, can be dangerous and should be avoided.
197997403Sobrien  template<typename _Tv>
198097403Sobrien    int
198197403Sobrien    __convert_from_v(char* __out, const int __size, const char* __fmt,
1982103447Skan		     _Tv __v, const __c_locale&, int __prec = -1);
198397403Sobrien
198497403Sobrien  // Construct correctly padded string, as per 22.2.2.2.2
198597403Sobrien  // Assumes 
198697403Sobrien  // __newlen > __oldlen
198797403Sobrien  // __news is allocated for __newlen size
198897403Sobrien  // Used by both num_put and ostream inserters: if __num,
198997403Sobrien  // internal-adjusted objects are padded according to the rules below
199097403Sobrien  // concerning 0[xX] and +-, otherwise, exactly as right-adjusted
199197403Sobrien  // ones are.
1992102782Skan
1993102782Skan  // NB: Of the two parameters, _CharT can be deduced from the
1994102782Skan  // function arguments. The other (_Traits) has to be explicitly specified.
199597403Sobrien  template<typename _CharT, typename _Traits>
1996102782Skan    struct __pad
199797403Sobrien    {
1998102782Skan      static void
1999102782Skan      _S_pad(ios_base& __io, _CharT __fill, _CharT* __news, 
2000102782Skan	     const _CharT* __olds, const streamsize __newlen, 
2001102782Skan	     const streamsize __oldlen, const bool __num);
2002102782Skan    };
200397403Sobrien
2004102782Skan  template<typename _CharT, typename _Traits>
2005102782Skan    void 
2006102782Skan    __pad<_CharT, _Traits>::_S_pad(ios_base& __io, _CharT __fill, 
2007102782Skan				   _CharT* __news, const _CharT* __olds, 
2008102782Skan				   const streamsize __newlen, 
2009102782Skan				   const streamsize __oldlen, const bool __num)
2010102782Skan    {
2011102782Skan      size_t __plen = static_cast<size_t>(__newlen - __oldlen);
2012102782Skan      _CharT* __pads = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __plen));
2013102782Skan      _Traits::assign(__pads, __plen, __fill); 
2014102782Skan
2015102782Skan      _CharT* __beg;
2016102782Skan      _CharT* __end;
201797403Sobrien      size_t __mod = 0;
201897403Sobrien      size_t __beglen; //either __plen or __oldlen
201997403Sobrien      ios_base::fmtflags __adjust = __io.flags() & ios_base::adjustfield;
202097403Sobrien
202197403Sobrien      if (__adjust == ios_base::left)
202297403Sobrien	{
202397403Sobrien	  // Padding last.
2024102782Skan	  __beg = const_cast<_CharT*>(__olds);
202597403Sobrien	  __beglen = __oldlen;
202697403Sobrien	  __end = __pads;
202797403Sobrien	}
202897403Sobrien      else if (__adjust == ios_base::internal && __num)
202997403Sobrien	{
203097403Sobrien	  // Pad after the sign, if there is one.
203197403Sobrien	  // Pad after 0[xX], if there is one.
203297403Sobrien	  // Who came up with these rules, anyway? Jeeze.
203397403Sobrien          locale __loc = __io.getloc();
203497403Sobrien	  const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc); 
2035102782Skan	  const _CharT __minus = __ctype.widen('-');
2036102782Skan	  const _CharT __plus = __ctype.widen('+');
2037102782Skan	  bool __testsign = _Traits::eq(__olds[0], __minus)
2038102782Skan	    		    || _Traits::eq(__olds[0], __plus);
2039102782Skan
2040102782Skan	  bool __testhex = _Traits::eq(__ctype.widen('0'), __olds[0]) 
2041102782Skan	    		   && (_Traits::eq(__ctype.widen('x'), __olds[1]) 
2042102782Skan			       || _Traits::eq(__ctype.widen('X'), __olds[1]));
204397403Sobrien	  if (__testhex)
204497403Sobrien	    {
204597403Sobrien	      __news[0] = __olds[0]; 
204697403Sobrien	      __news[1] = __olds[1];
204797403Sobrien	      __mod += 2;
204897403Sobrien	      __news += 2;
204997403Sobrien	      __beg = __pads;
205097403Sobrien	      __beglen = __plen;
2051102782Skan	      __end = const_cast<_CharT*>(__olds + __mod);
205297403Sobrien	    }
205397403Sobrien	  else if (__testsign)
205497403Sobrien	    {
2055102782Skan	      _Traits::eq((__news[0] = __olds[0]), __plus) ? __plus : __minus;
205697403Sobrien	      ++__mod;
205797403Sobrien	      ++__news;
205897403Sobrien	      __beg = __pads;
205997403Sobrien	      __beglen = __plen;
2060102782Skan	      __end = const_cast<_CharT*>(__olds + __mod);
206197403Sobrien	    }
206297403Sobrien	  else
206397403Sobrien	    {
206497403Sobrien	      // Padding first.
206597403Sobrien	      __beg = __pads;
206697403Sobrien	      __beglen = __plen;
2067102782Skan	      __end = const_cast<_CharT*>(__olds);
206897403Sobrien	    }
206997403Sobrien	}
207097403Sobrien      else
207197403Sobrien	{
207297403Sobrien	  // Padding first.
207397403Sobrien	  __beg = __pads;
207497403Sobrien	  __beglen = __plen;
2075102782Skan	  __end = const_cast<_CharT*>(__olds);
207697403Sobrien	}
2077102782Skan      _Traits::copy(__news, __beg, __beglen);
2078102782Skan      _Traits::copy(__news + __beglen, __end, 
2079102782Skan			  __newlen - __beglen - __mod);
208097403Sobrien    }
208197403Sobrien
208297403Sobrien  // Used by both numeric and monetary facets.
208397403Sobrien  // Check to make sure that the __grouping_tmp string constructed in
208497403Sobrien  // money_get or num_get matches the canonical grouping for a given
208597403Sobrien  // locale.
208697403Sobrien  // __grouping_tmp is parsed L to R
208797403Sobrien  // 1,222,444 == __grouping_tmp of "/1/3/3"
208897403Sobrien  // __grouping is parsed R to L
208997403Sobrien  // 1,222,444 == __grouping of "/3" == "/3/3/3"
209097403Sobrien  template<typename _CharT>
209197403Sobrien    bool
209297403Sobrien    __verify_grouping(const basic_string<_CharT>& __grouping, 
209397403Sobrien		      basic_string<_CharT>& __grouping_tmp)
209497403Sobrien    {         
209597403Sobrien      int __i = 0;
209697403Sobrien      int __j = 0;
209797403Sobrien      const int __len = __grouping.size();
209897403Sobrien      const int __n = __grouping_tmp.size();
209997403Sobrien      bool __test = true;
210097403Sobrien      
210197403Sobrien      // Parsed number groupings have to match the
210297403Sobrien      // numpunct::grouping string exactly, starting at the
210397403Sobrien      // right-most point of the parsed sequence of elements ...
210497403Sobrien      while (__test && __i < __n - 1)
210597403Sobrien	for (__j = 0; __test && __j < __len && __i < __n - 1; ++__j,++__i)
210697403Sobrien	  __test &= __grouping[__j] == __grouping_tmp[__n - __i - 1];
210797403Sobrien      // ... but the last parsed grouping can be <= numpunct
210897403Sobrien      // grouping.
210997403Sobrien      __j == __len ? __j = 0 : __j;
211097403Sobrien      __test &= __grouping[__j] >= __grouping_tmp[__n - __i - 1];
211197403Sobrien      return __test;
211297403Sobrien    }
211397403Sobrien
211497403Sobrien  // Used by both numeric and monetary facets.
211597403Sobrien  // Inserts "group separator" characters into an array of characters.
211697403Sobrien  // It's recursive, one iteration per group.  It moves the characters
211797403Sobrien  // in the buffer this way: "xxxx12345" -> "12,345xxx".  Call this
211897403Sobrien  // only with __gbeg != __gend.
211997403Sobrien  template<typename _CharT>
212097403Sobrien    _CharT*
212197403Sobrien    __add_grouping(_CharT* __s, _CharT __sep,  
212297403Sobrien		   const char* __gbeg, const char* __gend, 
212397403Sobrien		   const _CharT* __first, const _CharT* __last)
212497403Sobrien    {
212597403Sobrien      if (__last - __first > *__gbeg)
212697403Sobrien        {
212797403Sobrien          __s = __add_grouping(__s,  __sep, 
212897403Sobrien			       (__gbeg + 1 == __gend ? __gbeg : __gbeg + 1),
212997403Sobrien			       __gend, __first, __last - *__gbeg);
213097403Sobrien          __first = __last - *__gbeg;
213197403Sobrien          *__s++ = __sep;
213297403Sobrien        }
213397403Sobrien      do
213497403Sobrien	*__s++ = *__first++;
213597403Sobrien      while (__first != __last);
213697403Sobrien      return __s;
213797403Sobrien    }
213897403Sobrien
213997403Sobrien  // Inhibit implicit instantiations for required instantiations,
214097403Sobrien  // which are defined via explicit instantiations elsewhere.  
214197403Sobrien  // NB: This syntax is a GNU extension.
214297403Sobrien  extern template class moneypunct<char, false>;
214397403Sobrien  extern template class moneypunct<char, true>;
214497403Sobrien  extern template class moneypunct_byname<char, false>;
214597403Sobrien  extern template class moneypunct_byname<char, true>;
214697403Sobrien  extern template class money_get<char>;
214797403Sobrien  extern template class money_put<char>;
214897403Sobrien  extern template class numpunct<char>;
214997403Sobrien  extern template class numpunct_byname<char>;
215097403Sobrien  extern template class num_get<char>;
215197403Sobrien  extern template class num_put<char>; 
215297403Sobrien  extern template class __timepunct<char>;
215397403Sobrien  extern template class time_put<char>;
215497403Sobrien  extern template class time_put_byname<char>;
215597403Sobrien  extern template class time_get<char>;
215697403Sobrien  extern template class time_get_byname<char>;
215797403Sobrien  extern template class messages<char>;
215897403Sobrien  extern template class messages_byname<char>;
215997403Sobrien  extern template class ctype_byname<char>;
216097403Sobrien  extern template class codecvt_byname<char, char, mbstate_t>;
216197403Sobrien  extern template class collate<char>;
216297403Sobrien  extern template class collate_byname<char>;
216397403Sobrien
216497403Sobrien  extern template
216597403Sobrien    const codecvt<char, char, mbstate_t>& 
216697403Sobrien    use_facet<codecvt<char, char, mbstate_t> >(const locale&);
216797403Sobrien
216897403Sobrien  extern template
216997403Sobrien    const collate<char>& 
217097403Sobrien    use_facet<collate<char> >(const locale&);
217197403Sobrien
217297403Sobrien  extern template
217397403Sobrien    const numpunct<char>& 
217497403Sobrien    use_facet<numpunct<char> >(const locale&);
217597403Sobrien
217697403Sobrien  extern template 
217797403Sobrien    const num_put<char>& 
217897403Sobrien    use_facet<num_put<char> >(const locale&);
217997403Sobrien
218097403Sobrien  extern template 
218197403Sobrien    const num_get<char>& 
218297403Sobrien    use_facet<num_get<char> >(const locale&);
218397403Sobrien
218497403Sobrien  extern template
218597403Sobrien    const moneypunct<char, true>& 
218697403Sobrien    use_facet<moneypunct<char, true> >(const locale&);
218797403Sobrien
218897403Sobrien  extern template
218997403Sobrien    const moneypunct<char, false>& 
219097403Sobrien    use_facet<moneypunct<char, false> >(const locale&);
219197403Sobrien
219297403Sobrien  extern template 
219397403Sobrien    const money_put<char>& 
219497403Sobrien    use_facet<money_put<char> >(const locale&);
219597403Sobrien
219697403Sobrien  extern template 
219797403Sobrien    const money_get<char>& 
219897403Sobrien    use_facet<money_get<char> >(const locale&);
219997403Sobrien
220097403Sobrien  extern template
220197403Sobrien    const __timepunct<char>& 
220297403Sobrien    use_facet<__timepunct<char> >(const locale&);
220397403Sobrien
220497403Sobrien  extern template 
220597403Sobrien    const time_put<char>& 
220697403Sobrien    use_facet<time_put<char> >(const locale&);
220797403Sobrien
220897403Sobrien  extern template 
220997403Sobrien    const time_get<char>& 
221097403Sobrien    use_facet<time_get<char> >(const locale&);
221197403Sobrien
221297403Sobrien  extern template 
221397403Sobrien    const messages<char>& 
221497403Sobrien    use_facet<messages<char> >(const locale&);
221597403Sobrien
2216107606Sobrien  extern template 
2217107606Sobrien    bool
2218107606Sobrien    has_facet<ctype<char> >(const locale&);
2219107606Sobrien
2220107606Sobrien  extern template 
2221107606Sobrien    bool
2222107606Sobrien    has_facet<codecvt<char, char, mbstate_t> >(const locale&);
2223107606Sobrien
2224107606Sobrien  extern template 
2225107606Sobrien    bool
2226107606Sobrien    has_facet<collate<char> >(const locale&);
2227107606Sobrien
2228107606Sobrien  extern template 
2229107606Sobrien    bool
2230107606Sobrien    has_facet<numpunct<char> >(const locale&);
2231107606Sobrien
2232107606Sobrien  extern template 
2233107606Sobrien    bool
2234107606Sobrien    has_facet<num_put<char> >(const locale&);
2235107606Sobrien
2236107606Sobrien  extern template 
2237107606Sobrien    bool
2238107606Sobrien    has_facet<num_get<char> >(const locale&);
2239107606Sobrien
2240107606Sobrien  extern template 
2241107606Sobrien    bool
2242107606Sobrien    has_facet<moneypunct<char> >(const locale&);
2243107606Sobrien
2244107606Sobrien  extern template 
2245107606Sobrien    bool
2246107606Sobrien    has_facet<money_put<char> >(const locale&);
2247107606Sobrien
2248107606Sobrien  extern template 
2249107606Sobrien    bool
2250107606Sobrien    has_facet<money_get<char> >(const locale&);
2251107606Sobrien
2252107606Sobrien  extern template 
2253107606Sobrien    bool
2254107606Sobrien    has_facet<__timepunct<char> >(const locale&);
2255107606Sobrien
2256107606Sobrien  extern template 
2257107606Sobrien    bool
2258107606Sobrien    has_facet<time_put<char> >(const locale&);
2259107606Sobrien
2260107606Sobrien  extern template 
2261107606Sobrien    bool
2262107606Sobrien    has_facet<time_get<char> >(const locale&);
2263107606Sobrien
2264107606Sobrien  extern template 
2265107606Sobrien    bool
2266107606Sobrien    has_facet<messages<char> >(const locale&);
2267107606Sobrien
2268107606Sobrien#ifdef _GLIBCPP_USE_WCHAR_T
2269107606Sobrien  extern template class moneypunct<wchar_t, false>;
2270107606Sobrien  extern template class moneypunct<wchar_t, true>;
2271107606Sobrien  extern template class moneypunct_byname<wchar_t, false>;
2272107606Sobrien  extern template class moneypunct_byname<wchar_t, true>;
2273107606Sobrien  extern template class money_get<wchar_t>;
2274107606Sobrien  extern template class money_put<wchar_t>;
2275107606Sobrien  extern template class numpunct<wchar_t>;
2276107606Sobrien  extern template class numpunct_byname<wchar_t>;
2277107606Sobrien  extern template class num_get<wchar_t>;
2278107606Sobrien  extern template class num_put<wchar_t>;
2279107606Sobrien  extern template class __timepunct<wchar_t>;
2280107606Sobrien  extern template class time_put<wchar_t>;
2281107606Sobrien  extern template class time_put_byname<wchar_t>;
2282107606Sobrien  extern template class time_get<wchar_t>;
2283107606Sobrien  extern template class time_get_byname<wchar_t>;
2284107606Sobrien  extern template class messages<wchar_t>;
2285107606Sobrien  extern template class messages_byname<wchar_t>;
2286107606Sobrien  extern template class ctype_byname<wchar_t>;
2287107606Sobrien  extern template class codecvt_byname<wchar_t, char, mbstate_t>;
2288107606Sobrien  extern template class collate<wchar_t>;
2289107606Sobrien  extern template class collate_byname<wchar_t>;
2290107606Sobrien
229197403Sobrien  extern template
229297403Sobrien    const codecvt<wchar_t, char, mbstate_t>& 
229397403Sobrien    use_facet<codecvt<wchar_t, char, mbstate_t> >(locale const&);
229497403Sobrien
229597403Sobrien  extern template
229697403Sobrien    const collate<wchar_t>& 
229797403Sobrien    use_facet<collate<wchar_t> >(const locale&);
229897403Sobrien
229997403Sobrien  extern template
230097403Sobrien    const numpunct<wchar_t>& 
230197403Sobrien    use_facet<numpunct<wchar_t> >(const locale&);
230297403Sobrien
230397403Sobrien  extern template 
230497403Sobrien    const num_put<wchar_t>& 
230597403Sobrien    use_facet<num_put<wchar_t> >(const locale&);
230697403Sobrien
230797403Sobrien  extern template 
230897403Sobrien    const num_get<wchar_t>& 
230997403Sobrien    use_facet<num_get<wchar_t> >(const locale&);
231097403Sobrien
231197403Sobrien  extern template
231297403Sobrien    const moneypunct<wchar_t, true>& 
231397403Sobrien    use_facet<moneypunct<wchar_t, true> >(const locale&);
231497403Sobrien
231597403Sobrien  extern template
231697403Sobrien    const moneypunct<wchar_t, false>& 
231797403Sobrien    use_facet<moneypunct<wchar_t, false> >(const locale&);
231897403Sobrien 
231997403Sobrien  extern template 
232097403Sobrien    const money_put<wchar_t>& 
232197403Sobrien    use_facet<money_put<wchar_t> >(const locale&);
232297403Sobrien
232397403Sobrien  extern template 
232497403Sobrien    const money_get<wchar_t>& 
232597403Sobrien    use_facet<money_get<wchar_t> >(const locale&);
232697403Sobrien
232797403Sobrien  extern template
232897403Sobrien    const __timepunct<wchar_t>& 
232997403Sobrien    use_facet<__timepunct<wchar_t> >(const locale&);
233097403Sobrien
233197403Sobrien  extern template 
233297403Sobrien    const time_put<wchar_t>& 
233397403Sobrien    use_facet<time_put<wchar_t> >(const locale&);
233497403Sobrien
233597403Sobrien  extern template 
233697403Sobrien    const time_get<wchar_t>& 
233797403Sobrien    use_facet<time_get<wchar_t> >(const locale&);
233897403Sobrien
233997403Sobrien  extern template 
234097403Sobrien    const messages<wchar_t>& 
234197403Sobrien    use_facet<messages<wchar_t> >(const locale&);
234297403Sobrien
234397403Sobrien extern template 
234497403Sobrien    bool
234597403Sobrien    has_facet<ctype<wchar_t> >(const locale&);
234697403Sobrien
234797403Sobrien  extern template 
234897403Sobrien    bool
234997403Sobrien    has_facet<codecvt<wchar_t, char, mbstate_t> >(const locale&);
235097403Sobrien
235197403Sobrien  extern template 
235297403Sobrien    bool
235397403Sobrien    has_facet<collate<wchar_t> >(const locale&);
235497403Sobrien
235597403Sobrien  extern template 
235697403Sobrien    bool
235797403Sobrien    has_facet<numpunct<wchar_t> >(const locale&);
235897403Sobrien
235997403Sobrien  extern template 
236097403Sobrien    bool
236197403Sobrien    has_facet<num_put<wchar_t> >(const locale&);
236297403Sobrien
236397403Sobrien  extern template 
236497403Sobrien    bool
236597403Sobrien    has_facet<num_get<wchar_t> >(const locale&);
236697403Sobrien
236797403Sobrien  extern template 
236897403Sobrien    bool
236997403Sobrien    has_facet<moneypunct<wchar_t> >(const locale&);
237097403Sobrien
237197403Sobrien  extern template 
237297403Sobrien    bool
237397403Sobrien    has_facet<money_put<wchar_t> >(const locale&);
237497403Sobrien
237597403Sobrien  extern template 
237697403Sobrien    bool
237797403Sobrien    has_facet<money_get<wchar_t> >(const locale&);
237897403Sobrien
237997403Sobrien  extern template 
238097403Sobrien    bool
238197403Sobrien    has_facet<__timepunct<wchar_t> >(const locale&);
238297403Sobrien
238397403Sobrien  extern template 
238497403Sobrien    bool
238597403Sobrien    has_facet<time_put<wchar_t> >(const locale&);
238697403Sobrien
238797403Sobrien  extern template 
238897403Sobrien    bool
238997403Sobrien    has_facet<time_get<wchar_t> >(const locale&);
239097403Sobrien
239197403Sobrien  extern template 
239297403Sobrien    bool
239397403Sobrien    has_facet<messages<wchar_t> >(const locale&);
2394107606Sobrien#endif
239597403Sobrien} // namespace std
239697403Sobrien
239797403Sobrien#endif
2398