/* Metrowerks Standard Library
 * Copyright  1995-2004 Metrowerks Corporation.  All rights reserved.
 *
 * $Date: 2004/06/15 14:17:25 $
 * $Revision: 1.27.2.1 $
 */

// numfacet

#ifndef _NUMFACET
#define _NUMFACET

#include <mslconfig>

#ifndef _MSL_NO_IO

#include <msl_int_limits>
#include <localeimp>
#include <ctype>
#include <iterator>
#include <ios>
#include <vector>
#include <string>
#ifndef _MSL_NO_FLOATING_POINT
	#include <cmath>
#endif

#ifndef RC_INVOKED

#ifdef __MWERKS__
#pragma options align=native
#endif

#ifdef _MSL_FORCE_ENUMS_ALWAYS_INT
	#if _MSL_FORCE_ENUMS_ALWAYS_INT
		#pragma enumsalwaysint on
	#else
		#pragma enumsalwaysint off
	#endif
#endif  // _MSL_FORCE_ENUMS_ALWAYS_INT

#ifdef _MSL_FORCE_ENABLE_BOOL_SUPPORT
	#if _MSL_FORCE_ENABLE_BOOL_SUPPORT
		#pragma bool on
	#else
		#pragma bool off
	#endif
#endif  // _MSL_FORCE_ENABLE_BOOL_SUPPORT

#ifdef min
#undef min
#endif

#ifdef max
#undef max
#endif

#ifndef _MSL_NO_CPP_NAMESPACE
	namespace std {
#endif

#ifndef _MSL_NO_FLOATING_POINT

#ifndef isnan
inline
bool
isnan(double x)
{
	unsigned long long& xr = (unsigned long long&)x;
	return (xr & 0x7FF0000000000000ULL) == 0x7FF0000000000000ULL && (xr & 0x000FFFFFFFFFFFFFULL);
}
#endif  // isnan

#ifndef isinf
inline
bool
isinf(double x)
{
	unsigned long long& xr = (unsigned long long&)x;
	return (xr & 0x7FF0000000000000ULL) == 0x7FF0000000000000ULL && !(xr & 0x000FFFFFFFFFFFFFULL);
}
#endif  // isinf

#ifndef isfinite
inline
bool
isfinite(double x)
{
	unsigned long long& xr = (unsigned long long&)x;
	return (xr & 0x7FF0000000000000ULL) != 0x7FF0000000000000ULL;
}
#endif  // isfinite

#endif  // _MSL_NO_FLOATING_POINT

template <class charT>
inline
void
__false_name(basic_string<charT>* names)
{
	*names = __literal("false", charT());
}

template <class charT>
inline
void
__true_name(basic_string<charT>* names)
{
	*names = __literal("true", charT());
}

template <class charT>
inline
void
__bool_names(basic_string<charT>* names)
{
	__false_name(names);
	__true_name(names+1);
}

#ifndef _MSL_NO_LOCALE

template <class charT>
class numpunct
	: public locale::facet
{
public:
	typedef charT               char_type;
	typedef basic_string<charT> string_type;

	explicit numpunct(size_t refs = 0);

	char_type    decimal_point()   const
	                 {return do_decimal_point();}
	char_type    thousands_sep()   const
	                 {return do_thousands_sep();}
	string       grouping()        const
	                 {return do_grouping();}
	string_type  truename()        const
	                 {return do_truename();}
	string_type  falsename()       const
	                 {return do_falsename();}

	static locale::id id;

protected:
	virtual ~numpunct() {}
	virtual char_type    do_decimal_point() const
	                         {return __decimal_point_;}
	virtual char_type    do_thousands_sep() const
	                         {return __thousands_sep_;}
	virtual string       do_grouping()      const
	                         {return __grouping_;}
	virtual string_type  do_truename()      const
	                         {return __truename_;}
	virtual string_type  do_falsename()     const
	                         {return __falsename_;}

	char_type __decimal_point_;
	char_type __thousands_sep_;
	string    __grouping_;
	string_type __truename_;
	string_type __falsename_;
};

template <class charT>
numpunct<charT>::numpunct(size_t refs)
	: locale::facet(refs),
	  __decimal_point_('.'),
	  __thousands_sep_(',')
{
	__true_name(&__truename_);
	__false_name(&__falsename_);
}

template <class charT>
locale::id numpunct<charT>::id;

template <class charT> struct __facet_traits<numpunct<charT> >
	{static const bool is_standard = true;};

template <class charT, class InputIterator = istreambuf_iterator<charT> >
class num_get
	: public locale::facet
{
public:
	typedef charT            char_type;
	typedef InputIterator    iter_type;

	explicit num_get(size_t refs = 0)
	             : locale::facet(refs) {}

	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, bool& val) const
	              {return do_get(in, end, str, err, val);}
	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long& val) const
	              {return do_get(in, end, str, err, val);}
	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned short& val) const
	              {return do_get(in, end, str, err, val);}
	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned int& val) const
	              {return do_get(in, end, str, err, val);}
	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long& val) const
	              {return do_get(in, end, str, err, val);}
#if _MSL_LONGLONG
	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long long& val) const
	              {return do_get(in, end, str, err, val);}
	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long long& val) const
	              {return do_get(in, end, str, err, val);}
#endif  // _MSL_LONGLONG
#ifndef _MSL_NO_FLOATING_POINT
	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, float& val) const
	              {return do_get(in, end, str, err, val);}
	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, double& val) const
	              {return do_get(in, end, str, err, val);}
	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long double& val) const
	              {return do_get(in, end, str, err, val);}
#endif  // _MSL_NO_FLOATING_POINT
	iter_type get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, void*& val) const
	              {return do_get(in, end, str, err, val);}

	static locale::id id;

protected:
	virtual ~num_get() {}
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, bool& val) const;
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long& val) const;
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned short& val) const;
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned int& val) const;
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long& val) const;
#if _MSL_LONGLONG
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long long& val) const;
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long long& val) const;
#endif  // _MSL_LONGLONG
#ifndef _MSL_NO_FLOATING_POINT
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, float& val) const;
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, double& val) const;
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long double& val) const;
#endif  // _MSL_NO_FLOATING_POINT
	virtual iter_type do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, void*& val) const;
};

template <class charT, class InputIterator> struct __facet_traits<num_get<charT, InputIterator> >
	{static const bool is_standard = true;};

template <class charT, class InputIterator>
locale::id num_get<charT, InputIterator>::id;

#endif  // _MSL_NO_LOCALE

#ifndef _MSL_NO_LOCALE

template <class charT, class InputIterator>
typename num_get<charT, InputIterator>::iter_type
num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str,
	ios_base::iostate& err, bool& val) const

#else  // _MSL_NO_LOCALE

template <class InputIterator>
InputIterator
numget(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, bool& val)

#endif  // _MSL_NO_LOCALE
{
#ifndef _MSL_NO_LOCALE
	typedef typename numpunct<charT>::string_type string_type;
#else
	typedef typename iterator_traits<InputIterator>::value_type charT;
	typedef basic_string<charT> string_type;
#endif  // _MSL_NO_LOCALE
	if (in != end)
	{
		err = ios_base::goodbit;
		if (str.flags() & ios_base::boolalpha)
		{
			string_type names[2];
			const string_type (&const_names)[2] = names;
		#ifndef _MSL_NO_LOCALE
			locale loc = str.getloc();
			const numpunct<charT>& np = _USE_FACET(numpunct<charT>, loc);
			const ctype<charT>& ct = _USE_FACET(ctype<charT>, loc);
			names[0] = np.falsename();
			names[1] = np.truename();
			const string_type* i = __parse_a_word(in, end, const_names, const_names+2, ct, err);
		#else  // _MSL_NO_LOCALE
			__bool_names(names);
			const string_type* i = __parse_a_word(in, end, const_names, const_names+2, err);
		#endif  // _MSL_NO_LOCALE
			switch (i-const_names)
			{
			case 0:
				val = false;
				break;
			case 1:
				val = true;
				break;
			default:
				err |= ios_base::failbit;
				break;
			}
		}
		else
		{
			long value = 2;
		#ifndef _MSL_NO_LOCALE
			do_get(in, end, str, err, value);
		#else
			numget(in, end, str, err, value);
		#endif
			if (value == 0)
				val = false;
			else if (value == 1)
				val = true;
			else
				err |= ios_base::failbit;
		}
	}
	else
		err = ios_base::eofbit | ios_base::failbit;
	return in;
}

#ifndef _MSL_NO_LOCALE
template <class InputIterator, class Ctype>
InputIterator
__ws(InputIterator& in, InputIterator end, ios_base::iostate& err, const Ctype& ct)
#else  // _MSL_NO_LOCALE
template <class InputIterator>
InputIterator
__ws(InputIterator& in, InputIterator end, ios_base::iostate& err)
#endif  // _MSL_NO_LOCALE
{
	if (in == end)
		return in;
	typedef typename iterator_traits<InputIterator>::value_type charT;
	while (true)
	{
		charT c = *in;
	#ifndef _MSL_NO_LOCALE
		if (!ct.is(ctype_base::space, c))
	#else
		if (!isspace(c))
	#endif
			break;
		if (++in == end)
		{
			err |= ios_base::eofbit;
			break;
		}
	}
	return in;
}

#ifndef _MSL_NO_LOCALE
template <class InputIterator, class Ctype>
bool
__parsesign(InputIterator& in, InputIterator end, ios_base::iostate& err, const Ctype& ct)
#else  // _MSL_NO_LOCALE
template <class InputIterator>
bool
__parsesign(InputIterator& in, InputIterator end, ios_base::iostate& err)
#endif  // _MSL_NO_LOCALE
{
	bool result = false;
	if (in == end)
		return false;
	typedef typename iterator_traits<InputIterator>::value_type charT;
	charT sw = *in;
#ifndef _MSL_NO_LOCALE
	char s = ct.narrow(sw, char());
#else
	char s = char(sw);
#endif
	if (s == '-')
	{
		if (++in == end)
			err |= ios_base::eofbit;
		result = true;
#if 0  // lwg issue 338
#ifndef _MSL_NO_LOCALE
		__ws(in, end, err, ct);
#else
		__ws(in, end, err);
#endif
#endif  // 0  // lwg issue 338
	}
	else if (s == '+')
	{
		if (++in == end)
			err |= ios_base::eofbit;
#if 0  // lwg issue 338
#ifndef _MSL_NO_LOCALE
		__ws(in, end, err, ct);
#else
		__ws(in, end, err);
#endif
#endif  // 0  // lwg issue 338
	}
	return result;
}

#ifndef _MSL_NO_LOCALE

// return true if in error
template <class String>
bool
__check_grouping(const String& allowed_grouping, const vector<unsigned char>& actual_grouping)
{
	size_t all = 0;
	unsigned char ng = (unsigned char)numeric_limits<char>::max();
	for (vector<unsigned char>::size_type act = actual_grouping.size(); act > 0; ++all)
	{
		if (all < allowed_grouping.size())
			ng = (unsigned char)allowed_grouping[all];
		if (ng == 0 || ng >= numeric_limits<char>::max())
			break;
		if (--act == 0)
		{
			if (actual_grouping[act] > ng)
				return true;
		}
		else
		{
			if (actual_grouping[act] != ng)
				return true;
		}
	}
	return false;
}

#endif  // _MSL_NO_LOCALE

#ifndef _MSL_NO_LOCALE

template <class InputIterator, class T, class Ctype>
int
__parseDigits(InputIterator& in, InputIterator end, ios_base& str, ios_base::iostate& err, bool minus, T& val, const Ctype& ct, unsigned int base, bool no_grouping)

#else  // _MSL_NO_LOCALE

template <class InputIterator, class T>
int
__parseDigits(InputIterator& in, InputIterator end, ios_base& str, ios_base::iostate& err, bool minus, T& val, unsigned int base)

#endif  // _MSL_NO_LOCALE
{
	if (in == end)
		return 0;
	typedef typename iterator_traits<InputIterator>::value_type charT;
#ifndef _MSL_NO_LOCALE
	const numpunct<charT>& np = _USE_FACET(numpunct<charT>, str.getloc());
	charT thousands_sep = np.thousands_sep();
	string allowed_grouping = np.grouping();
	bool might_group = allowed_grouping.size() > 0;
	bool perform_grouping_check = false;
	vector<unsigned char> actual_grouping;
	unsigned char ng = 0;
	if (no_grouping)
		might_group = false;
#else  // _MSL_NO_LOCALE
	(void)str;
#endif
	int lastDigit;
	val = 0;
	int count = 0;
	err = ios_base::goodbit;
	int state = 0;
	switch (base)
	{
	case 0:
		lastDigit = 3;
		break;
	case 8:
		lastDigit = numeric_limits<T>::digits / 3;
		break;
	case 10:
		lastDigit = numeric_limits<T>::digits10;
		state = 2;
		break;
	case 16:
		lastDigit = numeric_limits<T>::digits / 4;
		break;
	}
	while (err == ios_base::goodbit)
	{
		{
		charT d = *in;
	#ifndef _MSL_NO_LOCALE
		if (ng != 0 && might_group && d == thousands_sep)
		{
			actual_grouping.push_back(ng);
			ng = 0;
			perform_grouping_check = true;
			goto cycle;
		}
		char dn = ct.narrow(ct.toupper(d), char());
		bool isdigit = ct.is(ctype_base::digit, d);
	#else  // _MSL_NO_LOCALE
		char dn = char(toupper(char(d)));
		bool isdigit = static_cast<bool>(_CSTD::isdigit(dn));
	#endif  // _MSL_NO_LOCALE
		switch (state)
		{
		case 0:
			if (dn == '0')
			{
				state = 1;
				count = 1;
				goto cycle;
			}
			state = 2;
			if (base == 0)
			{
				base = 10;
				lastDigit = numeric_limits<T>::digits10;
			}
			break;
		case 1:
			state = 2;
			if (isdigit)
			{
				if (base == 0)
				{
					base = 8;
					lastDigit = numeric_limits<T>::digits / 3;
				}
				count = 1;
				break;
			}
		#ifndef _MSL_NO_LOCALE
			if (d == thousands_sep)
			{
				perform_grouping_check = true;
				actual_grouping.push_back(1);
				count = 1;
				if (base == 0)
				{
					base = 8;
					lastDigit = numeric_limits<T>::digits / 3;
				}
				goto cycle;
			}
		#endif  // _MSL_NO_LOCALE
			if (base == 8)
				return 1;
			if (base == 0)
			{
				base = 16;
				lastDigit = numeric_limits<T>::digits / 4;
			}
			if (dn == 'X')
			{
				count = 0;
				goto cycle;
			}
			break;
		}
		switch (base)
		{
		case 8:
			if (!isdigit || dn > '7')
				goto endloop;
			break;
		case 10:
			if (!isdigit)
				goto endloop;
			break;
		case 16:
		#ifndef _MSL_NO_LOCALE
			if (!ct.is(ctype_base::xdigit, d))
		#else
			if (!isxdigit(d))
		#endif
				goto endloop;
			break;
		}
		T di;
		if (isdigit)
			di = T(dn - '0');
		else
			di = T(dn - 'A' + 10);
		if (++count > lastDigit)
		{
			if (base == 10)
			{
				if (numeric_limits<T>::is_signed && minus)
				{
					if (-val < (numeric_limits<T>::min() + di) / T(base))
					{
						err |= ios_base::failbit;
						val = numeric_limits<T>::min();
					#ifndef _MSL_NO_LOCALE
						perform_grouping_check = false;
					#endif
						goto cycle;
					}
				}
				else
				{
					if ((size_t)val > (numeric_limits<T>::max() - di) / base)
					{
						err |= ios_base::failbit;
						val = numeric_limits<T>::max();
					#ifndef _MSL_NO_LOCALE
						perform_grouping_check = false;
					#endif
						goto cycle;
					}
				}
			}
			else
			{
				typedef typename Metrowerks::to_unsigned<T>::type UT;
				if (UT(val) > (numeric_limits<UT>::max() - UT(di)) / base)
				{
					err |= ios_base::failbit;
					val = T(numeric_limits<UT>::max());
				#ifndef _MSL_NO_LOCALE
					perform_grouping_check = false;
				#endif
					goto cycle;
				}
			}
		}
		val *= static_cast<T>(base);
		val += di;
	#ifndef _MSL_NO_LOCALE
		++ng;
	#endif
		}
	cycle:
		if (++in == end)
		{
			err |= ios_base::eofbit;
			break;
		}
	}
endloop:
	if (minus && !(err & ios_base::failbit))
		val = static_cast<T>(-val);
#ifndef _MSL_NO_LOCALE
	if (perform_grouping_check)
	{
		if (ng != 0)  // hh 980804
			actual_grouping.push_back(ng);
		if (__check_grouping(allowed_grouping, actual_grouping))
		{
			err |= ios_base::failbit;
			count = 0;
		}
	}
#endif  // _MSL_NO_LOCALE
	return count;
}

template <class InputIterator, class T>
InputIterator
__get_integral(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, T& val, bool no_grouping = false)
{
	if (in == end)
	{
		err = ios_base::eofbit | ios_base::failbit;
		return in;
	}
	err = ios_base::goodbit;
	typedef typename iterator_traits<InputIterator>::value_type charT;
#ifndef _MSL_NO_LOCALE
	const ctype<charT>& ct = _USE_FACET(ctype<charT>, str.getloc());
	bool minus = __parsesign(in, end, err, ct);
#else  // _MSL_NO_LOCALE
	bool minus = __parsesign(in, end, err);
#endif
	unsigned int base;
	switch (str.flags() & ios_base::basefield)
	{
	case ios_base::oct:
		base = 8;
		break;
	case ios_base::hex:
		base = 16;
		break;
	case 0:
		base = 0;
		break;
	default:
		base = 10;
		break;
	}
	T i;
#ifndef _MSL_NO_LOCALE
	int count = __parseDigits(in, end, str, err, minus, i, ct, base, no_grouping);
#else
	(void)no_grouping;
	int count = __parseDigits(in, end, str, err, minus, i, base);
#endif  // _MSL_NO_LOCALE
	if (count == 0)
		err |= ios_base::failbit;
	else
		val = i;
	return in;
}

#ifndef _MSL_NO_LOCALE

template <class charT, class InputIterator>
inline
typename num_get<charT, InputIterator>::iter_type
num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long& val) const

#else  // _MSL_NO_LOCALE

template <class InputIterator>
inline
InputIterator
numget(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, long& val)

#endif  // _MSL_NO_LOCALE
{
	return __get_integral(in, end, str, err, val);
}

#ifndef _MSL_NO_LOCALE

template <class charT, class InputIterator>
typename num_get<charT, InputIterator>::iter_type
num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned short& val) const

#else  // _MSL_NO_LOCALE

template <class InputIterator>
InputIterator
numget(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, unsigned short& val)

#endif  // _MSL_NO_LOCALE
{
	return __get_integral(in, end, str, err, val);
}

#ifndef _MSL_NO_LOCALE

template <class charT, class InputIterator>
typename num_get<charT, InputIterator>::iter_type
num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned int& val) const

#else  // _MSL_NO_LOCALE

template <class InputIterator>
InputIterator
numget(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, unsigned int& val)

#endif  // _MSL_NO_LOCALE
{
	return __get_integral(in, end, str, err, val);
}

#ifndef _MSL_NO_LOCALE

template <class charT, class InputIterator>
inline
typename num_get<charT, InputIterator>::iter_type
num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long& val) const

#else  // _MSL_NO_LOCALE

template <class InputIterator>
inline
InputIterator
numget(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, unsigned long& val)

#endif  // _MSL_NO_LOCALE
{
	return __get_integral(in, end, str, err, val);
}

#if _MSL_LONGLONG

#ifndef _MSL_NO_LOCALE
	template <class charT, class InputIterator>
	inline
	typename num_get<charT, InputIterator>::iter_type
	num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long long& val) const
#else  // _MSL_NO_LOCALE
	template <class InputIterator>
	inline
	InputIterator
	numget(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, long long& val)
#endif  // _MSL_NO_LOCALE
	{
		return __get_integral(in, end, str, err, val);
	}

#ifndef _MSL_NO_LOCALE
	template <class charT, class InputIterator>
	inline
	typename num_get<charT, InputIterator>::iter_type
	num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, unsigned long long& val) const
#else  // _MSL_NO_LOCALE
	template <class InputIterator>
	inline
	InputIterator
	numget(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, unsigned long long& val)
#endif  // _MSL_NO_LOCALE
	{
		return __get_integral(in, end, str, err, val);
	}

#endif  // _MSL_LONGLONG

#ifndef _MSL_NO_FLOATING_POINT

	// Binary Coded Decimal class
	// hh 980802 Added to assist in the printing of floating point values

	class _BCD
	{
	public:
		_BCD();
		_MSL_IMP_EXP_CPP _BCD(long double x);
		_MSL_IMP_EXP_CPP string to_string(int precision, int& exponent) const;
		_MSL_IMP_EXP_CPP long double to_long_double() const;
		int exponent() const;
		string& mantissa() {return mantissa_;}
		short& exponent() {return exp_;}
		_MSL_IMP_EXP_CPP int must_round(size_t pos = 0) const;
		bool is_nan() const    {return classification_ == 1;}
		bool is_inf() const    {return classification_ == 2;}
		bool is_finite() const {return classification_ == 0;}
#ifdef _MSL_EXTENDED_PRECISION_OUTP
		_MSL_IMP_EXP_CPP _BCD(size_t x);
		_MSL_IMP_EXP_CPP _BCD(const char* mantissa, int exponent);
		_MSL_IMP_EXP_CPP _BCD& operator += (_BCD rhs);
		_MSL_IMP_EXP_CPP _BCD& operator -= (_BCD rhs);
		_MSL_IMP_EXP_CPP _BCD& operator *= (_BCD rhs);
		friend bool operator == (const _BCD& x, const _BCD& y)
			{ return x.exp_ == y.exp_ && x.mantissa_ == y.mantissa_; }
		friend bool operator < (const _BCD& x, const _BCD& y);
#endif  // _MSL_EXTENDED_PRECISION_OUTP
	private:
		string mantissa_;
		short exp_;
		short classification_;
		static const short decform_digits_ = 32;

#ifdef _MSL_EXTENDED_PRECISION_OUTP
		void trim();
#endif
	};

#ifdef _MSL_EXTENDED_PRECISION_OUTP
	_MSL_IMP_EXP_CPP _BCD __two_exp(short x);

	_MSL_IMP_EXP_CPP bool operator < (const _BCD& x, const _BCD& y);
	inline bool operator != (const _BCD& x, const _BCD& y) {return !(x == y);}
	inline bool operator <= (const _BCD& x, const _BCD& y) {return !(y < x);}
	inline bool operator >  (const _BCD& x, const _BCD& y) {return y < x;}
	inline bool operator >= (const _BCD& x, const _BCD& y) {return !(x < y);}

	inline
	_BCD operator + (const _BCD& x, const _BCD& y)
		{ return _BCD(x) += y; }

	inline
	_BCD operator - (const _BCD& x, const _BCD& y)
		{ return _BCD(x) -= y; }

	inline
	_BCD operator * (const _BCD& x, const _BCD& y)
		{ return _BCD(x) *= y; }
#endif  // _MSL_EXTENDED_PRECISION_OUTP

	inline
	_BCD::_BCD()
		: exp_(0),
		  classification_(0)
	{
	}

#ifdef _MSL_EXTENDED_PRECISION_OUTP
	inline
	void
	_BCD::trim()
	{
		if (mantissa_.size() > 0)
		{
			string::size_type i = mantissa_.find_last_not_of(char());
			if (i == string::npos)
				mantissa_.clear();
			else if (i < mantissa_.size() - 1)
				mantissa_.resize(++i);
		}
	}
#endif  // _MSL_EXTENDED_PRECISION_OUTP

	inline
	int
	_BCD::exponent() const
	{
		return exp_;
	}

	template <class charT>
	inline
	void
	__inf_name(basic_string<charT>* names)
	{
		*names = __literal("inf", charT());
	}

	template <class charT>
	inline
	void
	__infinity_name(basic_string<charT>* names)
	{
		*names = __literal("infinity", charT());
	}

	template <class charT>
	inline
	void
	__nan_name(basic_string<charT>* names)
	{
		*names = __literal("nan", charT());
	}

	template <class charT>
	inline
	void
	__float_names(basic_string<charT>* names)
	{
		__inf_name(names);
		__infinity_name(names+1);
		__nan_name(names+2);
	}

#ifndef _MSL_NO_LOCALE
	template <class Ctype, class InputIterator>
	void
	__parse_nan_inf(InputIterator& in, InputIterator end, const Ctype& ct, ios_base::iostate& err, _BCD& bcd)
#else  // _MSL_NO_LOCALE
	template <class InputIterator>
	void
	__parse_nan_inf(InputIterator& in, InputIterator end, ios_base::iostate& err, _BCD& bcd)
#endif  // _MSL_NO_LOCALE
	{
		typedef typename iterator_traits<InputIterator>::value_type charT;
		typedef basic_string<charT> string_type;
		string_type names[3];
		__float_names(names);
		const string_type (&const_names)[3] = names;
		const bool force_lower = true;
	#ifndef _MSL_NO_LOCALE
		const string_type* i = __parse_a_word(in, end, const_names, const_names+3, ct, err, force_lower);
	#else
		const string_type* i = __parse_a_word(in, end, const_names, const_names+3, err, force_lower);
	#endif
		switch (i-const_names)
		{
		case 0:
		case 1:
			bcd = _BCD((long double)INFINITY);
			break;
		case 2:
			bcd = _BCD((long double)NAN);
			break;
		default:
			err |= ios_base::failbit;
			break;
		}
	}

#ifndef _MSL_NO_LOCALE
	template <class InputIterator, class Ctype, class Numpunct>
	int
	__parseFloatDigits(InputIterator& in, InputIterator end, const Ctype& ct, const Numpunct& np, ios_base::iostate& err, _BCD& bcd)
#else  // _MSL_NO_LOCALE
	template <class InputIterator>
	int
	__parseFloatDigits(InputIterator& in, InputIterator end, ios_base::iostate& err, _BCD& bcd)
#endif  // _MSL_NO_LOCALE
	{
		if (in == end)
			return 0;
		typedef typename iterator_traits<InputIterator>::value_type charT;
	#ifndef _MSL_NO_LOCALE
		charT thousands_sep = np.thousands_sep();
		string allowed_grouping = np.grouping();
		bool might_group = allowed_grouping.size() > 0;
		bool perform_grouping_check = false;
		vector<unsigned char> actual_grouping;
		unsigned char ng = 0;
	#endif  // _MSL_NO_LOCALE
		int count = 0;
		while (true)
		{
			charT dw = *in;
		#ifndef _MSL_NO_LOCALE
			if (ng != 0 && might_group && dw == thousands_sep)
			{
				actual_grouping.push_back(ng);
				ng = 0;
				perform_grouping_check = true;
				goto cycle;
			}
			if (dw == np.decimal_point())
				break;
			if (!ct.is(ctype_base::digit, dw))
		#else  // _MSL_NO_LOCALE
			if (dw == '.')
				break;
			if (!isdigit(char(dw)))
		#endif  // _MSL_NO_LOCALE
			{
				if (count == 0)
				{
				#ifndef _MSL_NO_LOCALE
					__parse_nan_inf(in, end, ct, err, bcd);
				#else
					__parse_nan_inf(in, end, err, bcd);
				#endif
				}
				break;
			}
			{
		#ifndef _MSL_NO_LOCALE
			char d = static_cast<char>(ct.narrow(ct.toupper(dw), char()) - '0');
		#else
			char d = static_cast<char>(toupper(char(dw)) - '0');
		#endif
			if (!(bcd.mantissa().size() == 0 && d == 0))
				bcd.mantissa() += d;
			++count;
		#ifndef _MSL_NO_LOCALE
			++ng;
		#endif
			}
	#ifndef _MSL_NO_LOCALE
		cycle:
	#endif
			if (++in == end)
			{
				err |= ios_base::eofbit;
				break;
			}
		}
	#ifndef _MSL_NO_LOCALE
		if (perform_grouping_check)
		{
			if (ng != 0)  // hh 980804
				actual_grouping.push_back(ng);
			if (__check_grouping(allowed_grouping, actual_grouping))
			{
				err |= ios_base::failbit;
				count = 0;
			}
		}
	#endif  // _MSL_NO_LOCALE
		bcd.exponent() = static_cast<short>(bcd.mantissa().size() - 1);
		return count;
	}

#ifndef _MSL_NO_LOCALE
	template <class InputIterator, class Ctype, class Numpunct>
	bool
	__parseFraction(InputIterator& in, InputIterator end, const Ctype& ct, const Numpunct& np, ios_base::iostate& err, _BCD& bcd)
#else  // _MSL_NO_LOCALE
	template <class InputIterator>
	bool
	__parseFraction(InputIterator& in, InputIterator end, ios_base::iostate& err, _BCD& bcd)
#endif  // _MSL_NO_LOCALE
	{
		if (in == end)
			return false;
		typedef typename iterator_traits<InputIterator>::value_type charT;
		charT c = *in;
		bool foundDigit = false;
	#ifndef _MSL_NO_LOCALE
		if (c == np.decimal_point())
	#else
		if (c == '.')
	#endif
		{
			while (true)
			{
				if (++in == end)
				{
					err |= ios_base::eofbit;
					break;
				}
				c = *in;
			#ifndef _MSL_NO_LOCALE
				if (!ct.is(ctype_base::digit, c))
					break;
				char d = static_cast<char>(ct.narrow(c, char()) - '0');
			#else  // _MSL_NO_LOCALE
				if (!isdigit(c))
					break;
				char d = static_cast<char>(char(c) - '0');
			#endif  // _MSL_NO_LOCALE
				if (!(bcd.mantissa().size() == 0 && d == 0))
					bcd.mantissa() += d;
				else
					--bcd.exponent();
				foundDigit = true;
			}
		}
		return foundDigit;
	}

#ifndef _MSL_NO_LOCALE
	template <class InputIterator, class Ctype>
	bool
	__parseExponent(InputIterator& in, InputIterator end, const Ctype& ct, ios_base::iostate& err, _BCD& bcd)
#else  // _MSL_NO_LOCALE
	template <class InputIterator>
	bool
	__parseExponent(InputIterator& in, InputIterator end, ios_base::iostate& err, _BCD& bcd)
#endif  // _MSL_NO_LOCALE
	{
		typedef typename iterator_traits<InputIterator>::value_type charT;
		if (in == end)
			return false;
	#ifndef _MSL_NO_LOCALE
		char c = ct.narrow(ct.toupper(*in), char());
	#else
		char c = char(toupper(char(*in)));
	#endif
		if (c == 'E')
		{
			if (++in == end)
			{
				err |= ios_base::eofbit | ios_base::failbit;
				return false;
			}
		#ifndef _MSL_NO_LOCALE
			bool minus = __parsesign(in, end, err, ct);
		#else
			bool minus = __parsesign(in, end, err);
		#endif
			if (in == end)
			{
				err |= ios_base::failbit;
				return false;
			}
			long e = 0;
			int count = 0;
			while (count < 10)
			{
				charT d = *in;
			#ifndef _MSL_NO_LOCALE
				if (!ct.is(ctype_base::digit, d))
					break;
				char dn = ct.narrow(d, char());
			#else  // _MSL_NO_LOCALE
				if (!isdigit(char(d)))
					break;
				char dn = char(d);
			#endif  // _MSL_NO_LOCALE
				e *= 10;
				e += long(dn - '0');
				++count;
				if (++in == end)
				{
					err |= ios_base::eofbit;
					break;
				}
			}
			if (count == 0)
			{
				err |= ios_base::failbit;
				return false;
			}
			if (minus)
				e = -e;
			bcd.exponent() += (short)e;
			return true;
		}
		return false;
	}

#ifndef _MSL_NO_LOCALE
	template <class charT, class InputIterator>
	typename num_get<charT, InputIterator>::iter_type
	num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, float& val) const
#else  // _MSL_NO_LOCALE
	template <class InputIterator>
	InputIterator
	numget(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, float& val)
#endif  // _MSL_NO_LOCALE
	{
		long double f;
	#ifndef _MSL_NO_LOCALE
		iter_type result = do_get(in, end, str, err, f);
	#else
		InputIterator result = numget(in, end, str, err, f);
	#endif
		if (!(err & ios_base::failbit))
			val = (float)f;
		return result;
	}

#ifndef _MSL_NO_LOCALE
	template <class charT, class InputIterator>
	typename num_get<charT, InputIterator>::iter_type
	num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, double& val) const
#else  // _MSL_NO_LOCALE
	template <class InputIterator>
	InputIterator
	numget(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, double& val)
#endif  // _MSL_NO_LOCALE
	{
		long double f;
	#ifndef _MSL_NO_LOCALE
		iter_type result = do_get(in, end, str, err, f);
	#else
		InputIterator result = numget(in, end, str, err, f);
	#endif
		if (!(err & ios_base::failbit))
			val = (double)f;
		return result;
	}

#ifndef _MSL_NO_LOCALE
	template <class charT, class InputIterator>
	typename num_get<charT, InputIterator>::iter_type
	num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, long double& val) const
#else  // _MSL_NO_LOCALE
	template <class InputIterator>
	InputIterator
	numget(InputIterator in, InputIterator end, ios_base&, ios_base::iostate& err, long double& val)
#endif  // _MSL_NO_LOCALE
	{
		if (in == end)
		{
			err = ios_base::eofbit | ios_base::failbit;
			return in;
		}
		err = ios_base::goodbit;
	#ifndef _MSL_NO_LOCALE
		locale loc = str.getloc();
		const ctype<charT>& ct = _USE_FACET(ctype<charT>, loc);
		const numpunct<charT>& np = _USE_FACET(numpunct<charT>, loc);
		bool minus = __parsesign(in, end, err, ct);
	#else  // _MSL_NO_LOCALE
		bool minus = __parsesign(in, end, err);
	#endif
		_BCD bcd;
	#ifndef _MSL_NO_LOCALE
		int count = __parseFloatDigits(in, end, ct, np, err, bcd);
	#else
		int count = __parseFloatDigits(in, end, err, bcd);
	#endif
		if (err & ios_base::failbit)
			return in;
		if (bcd.is_finite())
		{
		#ifndef _MSL_NO_LOCALE
			bool found_digits = __parseFraction(in, end, ct, np, err, bcd);
		#else
			bool found_digits = __parseFraction(in, end, err, bcd);
		#endif
			if (!found_digits && count == 0)
			{
				err |= ios_base::failbit;
				return in;
			}
		#ifndef _MSL_NO_LOCALE
			__parseExponent(in, end, ct, err, bcd);
		#else
			__parseExponent(in, end, err, bcd);
		#endif
			if (err & ios_base::failbit)
				return in;
		}
		val = bcd.to_long_double();
		if (minus)
			val = -val;
		return in;
	}

#endif  // _MSL_NO_FLOATING_POINT

#ifndef _MSL_NO_LOCALE

template <class charT, class InputIterator>
typename num_get<charT, InputIterator>::iter_type
num_get<charT, InputIterator>::do_get(iter_type in, iter_type end, ios_base& str, ios_base::iostate& err, void*& val) const

#else  // _MSL_NO_LOCALE

template <class InputIterator>
InputIterator
numget(InputIterator in, InputIterator end, ios_base& str, ios_base::iostate& err, void*& val)

#endif  // _MSL_NO_LOCALE
{
	_SaveFlags save_flags(str);
	hex(str);
	long i;
#ifndef _MSL_NO_LOCALE
	iter_type result = do_get(in, end, str, err, i);
#else
	InputIterator result = numget(in, end, str, err, i);
#endif
	if (!(err & ios_base::failbit))
		val = (void*)i;
	return result;
}

#ifndef _MSL_NO_LOCALE

template <class charT, class OutputIterator = ostreambuf_iterator<charT> >
class num_put
	: public locale::facet
{
public:
	typedef charT            char_type;
	typedef OutputIterator   iter_type;

	explicit num_put(size_t refs = 0)
	             : locale::facet(refs) {}

	iter_type put(iter_type out, ios_base& str, char_type fill, bool val) const
	              {return do_put(out, str, fill, val);}
	iter_type put(iter_type out, ios_base& str, char_type fill, long val) const
	              {return do_put(out, str, fill, val);}
	iter_type put(iter_type out, ios_base& str, char_type fill, unsigned long val) const
	              {return do_put(out, str, fill, val);}
#if _MSL_LONGLONG
	iter_type put(iter_type out, ios_base& str, char_type fill, long long val) const
	              {return do_put(out, str, fill, val);}
	iter_type put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const
	              {return do_put(out, str, fill, val);}
#endif  // _MSL_LONGLONG
#ifndef _MSL_NO_FLOATING_POINT
	iter_type put(iter_type out, ios_base& str, char_type fill, double val) const
	              {return do_put(out, str, fill, val);}
	iter_type put(iter_type out, ios_base& str, char_type fill, long double val) const
	              {return do_put(out, str, fill, val);}
#endif  // _MSL_NO_FLOATING_POINT
	iter_type put(iter_type out, ios_base& str, char_type fill, const void* val) const
	              {return do_put(out, str, fill, val);}

	static locale::id id;

protected:
	virtual ~num_put() {}
	virtual iter_type do_put(iter_type out, ios_base& str, char_type fill, bool val) const;
	virtual iter_type do_put(iter_type out, ios_base& str, char_type fill, long val) const;
	virtual iter_type do_put(iter_type out, ios_base& str, char_type fill, unsigned long) const;
#if _MSL_LONGLONG
	virtual iter_type do_put(iter_type out, ios_base& str, char_type fill, long long val) const;
	virtual iter_type do_put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const;
#endif  // _MSL_LONGLONG
#ifndef _MSL_NO_FLOATING_POINT
	virtual iter_type do_put(iter_type out, ios_base& str, char_type fill, double val) const;
	virtual iter_type do_put(iter_type out, ios_base& str, char_type fill, long double val) const;
#endif  // _MSL_NO_FLOATING_POINT
	virtual iter_type do_put(iter_type out, ios_base& str, char_type fill, const void* val) const;
};

template <class charT, class OutputIterator> struct __facet_traits<num_put<charT, OutputIterator> >
	{static const bool is_standard = true;};

template <class charT, class OutputIterator>
locale::id num_put<charT, OutputIterator>::id;

#endif  // _MSL_NO_LOCALE

#ifndef _MSL_NO_LOCALE

template <class charT, class T>
inline
charT
__hextoa(bool uppercase, const ctype<charT>& ct, T c)
{
	if (c < 10)
		return ct.widen(char(c + '0'));
	if (uppercase)
		return ct.widen(char(c - 10 + 'A'));
	return ct.widen(char(c - 10 + 'a'));
}

#else  // _MSL_NO_LOCALE

template <class charT, class T>
inline
charT
__hextoa(bool uppercase, charT, T c)
{
	if (c < 10)
		return charT(c + '0');
	if (uppercase)
		return charT(c - 10 + 'A');
	return charT(c - 10 + 'a');
}

#endif  // _MSL_NO_LOCALE

template <class charT, class T>
int
#ifndef _MSL_NO_LOCALE
__putdigits(ios_base& str, T val, charT* digits, const ctype<charT>& ct, bool no_grouping = false)
#else
__putdigits(ios_base& str, T val, charT* digits)
#endif
{
#ifndef _MSL_NO_LOCALE
	locale loc = str.getloc();
#endif
	// Pick off 0 as special case
	if (val == 0)
	{
	#ifndef _MSL_NO_LOCALE
		*digits = ct.widen('0');
	#else
		*digits = charT('0');
	#endif
		return 1;
	}
#ifndef _MSL_NO_LOCALE
	const numpunct<charT>& np = _USE_FACET(numpunct<charT>, loc);
#endif
	unsigned int base = 10;
	switch (str.flags() & ios_base::basefield)
	{
	case ios_base::oct:
		base = 8;
		break;
	case ios_base::hex:
		base = 16;
		break;
	default:
		break;
	}
	// Print digits (in reverse order)
	charT* d = digits;
#ifndef _MSL_NO_LOCALE
	string allowed_grouping = np.grouping();
	bool might_group = static_cast<bool>(allowed_grouping.size() > 0);
	size_t ng = 0;
	unsigned char ig = 0;
	unsigned char g = 0;
	if (might_group)
	{
		g = (unsigned char)allowed_grouping[ng];
		if (g == 0)
			might_group = false;
	}
	if (no_grouping)
		might_group = false;
	charT thousands_sep = might_group ? np.thousands_sep() : charT();
#endif  // _MSL_NO_LOCALE
	bool uppercase = static_cast<bool>(str.flags() & ios_base::uppercase);
	while (val != 0)
	{
	#ifndef _MSL_NO_LOCALE
		*d++ = __hextoa(uppercase, ct, val % base);
	#else
		*d++ = __hextoa(uppercase, charT(), val % base);
	#endif
		val /= base;
	#ifndef _MSL_NO_LOCALE
		if (val != 0 && might_group)
		{
			if (++ig == g)
			{
				*d++ = thousands_sep;
				if (++ng < allowed_grouping.size())
				{
					g = (unsigned char)allowed_grouping[ng];
					if (g == 0)
						might_group = false;
				}
				ig = 0;
			}
		}
	#endif  // _MSL_NO_LOCALE
	}
	// Fix reverse order
	_STD::reverse(digits, d);
	return int(d - digits);
}

template <class charT, class OutputIterator, class T>
OutputIterator
__putoct(OutputIterator out, ios_base& str, charT fill, T val, bool no_grouping = false)
{
#ifndef _MSL_NO_LOCALE
	const ctype<charT>& ct = _USE_FACET(ctype<charT>, str.getloc());
#endif
	int plen = 0;
	charT prefix;
	charT digits[44];
	charT* d = digits;
	int count = 0;
	if (val == 0 || str.flags() & ios_base::showbase)
	{
	#ifndef _MSL_NO_LOCALE
		*d++ = ct.widen('0');
	#else
		*d++ = charT('0');
	#endif
		count++;
	}
	if (val != 0)
	#ifndef _MSL_NO_LOCALE
		count += __putdigits(str, val, d, ct, no_grouping);
	#else
		count += __putdigits(str, val, d);
		(void)no_grouping;
	#endif  // _MSL_NO_LOCALE
	return __putnumber(out, str, fill, &prefix, plen, digits, count);
}

template <class charT, class OutputIterator, class T>
OutputIterator
__putdec(OutputIterator out, ios_base& str, charT fill, T val, bool no_grouping = false)
{
#ifndef _MSL_NO_LOCALE
	const ctype<charT>& ct = _USE_FACET(ctype<charT>, str.getloc());
#endif
	int plen = 0;
	charT prefix;
	if (numeric_limits<T>::is_signed)
	{
		if (val >= 0 && str.flags() & ios_base::showpos)
		{
		#ifndef _MSL_NO_LOCALE
			prefix = ct.widen('+');
		#else
			prefix = charT('+');
		#endif
			plen = 1;
		}
		else if (val < 0)
		{
			plen = 1;
		#ifndef _MSL_NO_LOCALE
			prefix = ct.widen('-');
		#else
			prefix = charT('-');
		#endif
			val = -val;
		}
	}
	charT digits[39];
#ifndef _MSL_NO_LOCALE
	int count = __putdigits(str, (typename Metrowerks::to_unsigned<T>::type)val, digits, ct, no_grouping);
#else
	int count = __putdigits(str, (typename Metrowerks::to_unsigned<T>::type)val, digits);
	(void)no_grouping;
#endif  // _MSL_NO_LOCALE
	return __putnumber(out, str, fill, &prefix, plen, digits, count);
}

template <class charT, class OutputIterator, class T>
OutputIterator
__puthex(OutputIterator out, ios_base& str, charT fill, T val, bool no_grouping = false)
{
	int plen = 0;
	charT prefix[3];
	charT* p = prefix;
#ifndef _MSL_NO_LOCALE
	const ctype<charT>& ct = _USE_FACET(ctype<charT>, str.getloc());
#endif
	if (str.flags() & ios_base::showbase)
	{
	#ifndef _MSL_NO_LOCALE
		*p++ = ct.widen('0');
		if (str.flags() & ios_base::uppercase)
			*p++ = ct.widen('X');
		else
			*p++ = ct.widen('x');
	#else  // _MSL_NO_LOCALE
		*p++ = charT('0');
		if (str.flags() & ios_base::uppercase)
			*p++ = charT('X');
		else
			*p++ = charT('x');
	#endif  // _MSL_NO_LOCALE
		plen += 2;
	}
	charT digits[31];
#ifndef _MSL_NO_LOCALE
	int count = __putdigits(str, val, digits, ct, no_grouping);
#else
	int count = __putdigits(str, val, digits);
	(void)no_grouping;
#endif  // _MSL_NO_LOCALE
	return __putnumber(out, str, fill, prefix, plen, digits, count);
}

#ifndef _MSL_NO_LOCALE

template <class charT, class OutputIterator>
typename num_put<charT, OutputIterator>::iter_type
num_put<charT, OutputIterator>::do_put(iter_type out, ios_base& str, char_type fill, bool val) const

#else  // _MSL_NO_LOCALE

template <class charT, class OutputIterator>
OutputIterator
numput(OutputIterator out, ios_base& str, charT fill, bool val)

#endif  // _MSL_NO_LOCALE
{
	if (str.flags() & ios_base::boolalpha)
	{
	#ifndef _MSL_NO_LOCALE
		const numpunct<charT>& np = _USE_FACET(numpunct<charT>, str.getloc());
		typedef typename numpunct<charT>::string_type string_type;
		string_type s = val ? np.truename() : np.falsename();
	#else  // _MSL_NO_LOCALE
		typedef basic_string<charT> string_type;
		string_type s;
		if (val)
			__true_name(&s);
		else
			__false_name(&s);
	#endif  // _MSL_NO_LOCALE
		return __putnumber(out, str, fill, (const charT*)0, 0, s.c_str(), int(s.size()));
	}
#ifndef _MSL_NO_LOCALE
	return do_put(out, str, fill, long(val));
#else
	return numput(out, str, fill, long(val));
#endif
}

#ifndef _MSL_NO_LOCALE

template <class charT, class OutputIterator>
typename num_put<charT, OutputIterator>::iter_type
num_put<charT, OutputIterator>::do_put(iter_type out, ios_base& str, char_type fill, long val) const

#else  // _MSL_NO_LOCALE

template <class charT, class OutputIterator>
OutputIterator
numput(OutputIterator out, ios_base& str, charT fill, long val)

#endif  // _MSL_NO_LOCALE
{
	switch (str.flags() & ios_base::basefield)
	{
	case ios_base::oct:
		return __putoct(out, str, fill, (unsigned long)val);
	case ios_base::hex:
		return __puthex(out, str, fill, (unsigned long)val);
	default:
		break;
	}
	return __putdec(out, str, fill, val);
}

#ifndef _MSL_NO_LOCALE

template <class charT, class OutputIterator>
typename num_put<charT, OutputIterator>::iter_type
num_put<charT, OutputIterator>::do_put(iter_type out, ios_base& str, char_type fill, unsigned long val) const

#else  // _MSL_NO_LOCALE

template <class charT, class OutputIterator>
OutputIterator
numput(OutputIterator out, ios_base& str, charT fill, unsigned long val)

#endif  // _MSL_NO_LOCALE
{
	switch (str.flags() & ios_base::basefield)
	{
	case ios_base::oct:
		return __putoct(out, str, fill, val);
	case ios_base::hex:
		return __puthex(out, str, fill, val);
	default:
		break;
	}
	return __putdec(out, str, fill, val);
}

#if _MSL_LONGLONG

#ifndef _MSL_NO_LOCALE
	template <class charT, class OutputIterator>
	typename num_put<charT, OutputIterator>::iter_type
	num_put<charT, OutputIterator>::do_put(iter_type out, ios_base& str, charT fill, long long val) const
#else  // _MSL_NO_LOCALE
	template <class charT, class OutputIterator>
	OutputIterator
	numput(OutputIterator out, ios_base& str, charT fill, long long val)
#endif  // _MSL_NO_LOCALE
	{
		switch (str.flags() & ios_base::basefield)
		{
		case ios_base::oct:
			return __putoct(out, str, fill, (unsigned long long)val);
		case ios_base::hex:
			return __puthex(out, str, fill, (unsigned long long)val);
		default:
			break;
		}
		return __putdec(out, str, fill, val);
	}

#ifndef _MSL_NO_LOCALE
	template <class charT, class OutputIterator>
	typename num_put<charT, OutputIterator>::iter_type
	num_put<charT, OutputIterator>::do_put(iter_type out, ios_base& str, char_type fill, unsigned long long val) const
#else  // _MSL_NO_LOCALE
	template <class charT, class OutputIterator>
	OutputIterator
	numput(OutputIterator out, ios_base& str, charT fill, unsigned long long val)
#endif  // _MSL_NO_LOCALE
	{
		switch (str.flags() & ios_base::basefield)
		{
		case ios_base::oct:
			return __putoct(out, str, fill, val);
		case ios_base::hex:
			return __puthex(out, str, fill, val);
		default:
			break;
		}
		return __putdec(out, str, fill, val);
	}

#endif  // _MSL_LONGLONG

#ifndef _MSL_NO_LOCALE

	template <class charT, class String>
	void
	__put_grouping_float(charT decimal_point, charT thousands_sep, const string& allowed_grouping, String& digits)
	{
		if (allowed_grouping.size() > 0 && digits.size() > 1)
		{
			size_t i = digits.find(decimal_point);
			if (i == String::npos)
				i = digits.size();
			size_t ng = 0;
			unsigned char g = (unsigned char)allowed_grouping[ng];
			size_t ig = 0;
			while (--i > 0)
			{
				if (++ig == g)
				{
					digits.insert(i, 1, thousands_sep);
					if (++ng < allowed_grouping.size())
						g = (unsigned char)allowed_grouping[ng];
					ig = 0;
				}
			}
		}
	}

#endif  // _MSL_NO_LOCALE

#ifndef _MSL_NO_FLOATING_POINT

	template <class charT, class String>
	void
	__put_f_zero(ios_base& str, charT zero, charT decimal_point, String& digits)
	{
		streamsize precision = str.precision();
		digits = zero;
		if (str.flags() & ios_base::showpoint || precision > 0)
			digits += decimal_point;
		digits.append((size_t)precision, zero);
	}

	template <class T, class String>
	void
	__put_f_digits(ios_base& str, T val, String& digits)
	{
		typedef typename String::value_type charT;
	#ifndef _MSL_NO_LOCALE
		locale loc = str.getloc();
		const ctype<charT>& ct = _USE_FACET(ctype<charT>, loc);
		const numpunct<charT>& np = _USE_FACET(numpunct<charT>, loc);
		charT zero = ct.widen('0');
		charT one = ct.widen('1');
		charT decimal_point = np.decimal_point();
	#else  // _MSL_NO_LOCALE
		charT zero = charT('0');
		charT one = charT('1');
		charT decimal_point = charT('.');
	#endif  // _MSL_NO_LOCALE
		streamsize precision = str.precision();
		// Pick off 0 as special case
		if (val == 0)
		{
			__put_f_zero(str, zero, decimal_point, digits);
			return;
		}
		_BCD bcd(val);
		int exponent = bcd.exponent();
		int significant_digits = int(precision + exponent + 1);
		if (significant_digits < 0)
		{
			__put_f_zero(str, zero, decimal_point, digits);
			return;
		}
		else if (significant_digits == 0)
		{
			if (exponent == -1)  // precision == 0, result is either 0 or 1, optionally followed by '.'
			{
				if (bcd.must_round() == 1)  // round to even
					digits = one;
				else
					digits = zero;
				if (str.flags() & ios_base::showpoint)
					digits += decimal_point;
			}
			else  // exponent < -1, result is 0.0...0 or 0.0...1
			{
				digits = zero;
				digits += decimal_point;
				if (exponent < -2)
					digits.append((size_t)(-exponent - 2), zero);
				if (bcd.must_round() == 1)  // round to even
					digits += one;
				else
					digits += zero;
			}
			return;
		}
		// significant_digits > 0
	#ifndef _MSL_NO_LOCALE
		digits = ct.widen(bcd.to_string(significant_digits, exponent));  // exponent may increase by 1 due to rounding
	#else
		string tmp = bcd.to_string(significant_digits, exponent);
		digits.assign(tmp.begin(), tmp.end());
	#endif  // _MSL_NO_LOCALE
		significant_digits = int(precision + exponent + 1);
		if (exponent < 0)
		{
			String tmp;
			tmp = zero;
			tmp += decimal_point;
			if (exponent < -1)
				tmp.append((size_t)(-exponent - 1), zero);
			tmp += digits;
			digits = tmp;
			if (precision + 2 - tmp.size() == 1)
				digits += zero;
			return;
		}
		// exponent >= 0
		digits.append((size_t)(significant_digits - digits.size()), zero);
		if (str.flags() & ios_base::showpoint || precision > 0)
			digits.insert(size_t(exponent+1), 1, decimal_point);
	#ifndef _MSL_NO_LOCALE
		// grouping for floating point currently under debate (12/7/00)
		__put_grouping_float(decimal_point, np.thousands_sep(), np.grouping(), digits);
	#endif  // _MSL_NO_LOCALE
	}

	template <class T, class String>
	int
	__put_e_digits(ios_base& str, T val, String& digits)
	{
		typedef typename String::value_type charT;
	#ifndef _MSL_NO_LOCALE
		locale loc = str.getloc();
		const ctype<charT>& ct = _USE_FACET(ctype<charT>, loc);
		const numpunct<charT>& np = _USE_FACET(numpunct<charT>, loc);
		charT zero = ct.widen('0');
		charT decimal_point = np.decimal_point();
		charT exp = str.flags() & ios_base::uppercase ? ct.widen('E') : ct.widen('e');
	#else  // _MSL_NO_LOCALE
		charT zero = charT('0');
		charT decimal_point = charT('.');
		charT exp = str.flags() & ios_base::uppercase ? charT('E') : charT('e');
	#endif  // _MSL_NO_LOCALE
		streamsize precision = str.precision();
		// Pick off 0 as special case
		if (val == 0)
		{
			digits = zero;
			if (str.flags() & ios_base::showpoint || precision > 0)
				digits += decimal_point;
			if (precision > 0)
				digits.append(size_t(precision), zero);
			digits += exp;
		#ifndef _MSL_NO_LOCALE
			digits += ct.widen('+');
		#else
			digits += charT('+');
		#endif
			digits.append(2, zero);
			return 0;
		}
		_BCD bcd(val);
		int exponent;
	#ifndef _MSL_NO_LOCALE
		digits = ct.widen(bcd.to_string(int(precision+1), exponent));
	#else
		string tmp = bcd.to_string(int(precision+1), exponent);
		digits.assign(tmp.begin(), tmp.end());
	#endif  // _MSL_NO_LOCALE
		int result = exponent;
		// Pad with zeroes as necessary and add decimal point
		bool dp = false;  // hh 980903
		if (str.flags() & ios_base::showpoint || precision > 0)
		{
			digits.insert(digits.begin()+1, decimal_point);
			dp = true;
		}
		if (precision + 1 + dp > (streamsize)digits.size())
			digits.append((typename String::size_type)(precision + 1 + dp - digits.size()), zero);
		// Print exponent
		digits += exp;
		if (exponent < 0)
		{
		#ifndef _MSL_NO_LOCALE
			digits += ct.widen('-');
		#else
			digits += charT('-');
		#endif
			exponent = -exponent;
		}
		else
		#ifndef _MSL_NO_LOCALE
			digits += ct.widen('+');
		#else
			digits += charT('+');
		#endif
		// Exponent must have at least 2 digits (standard)
		if (exponent < 10)
		{
		#ifndef _MSL_NO_LOCALE
			digits += ct.widen('0');
			digits += ct.widen(char(exponent + '0'));
		#else  // _MSL_NO_LOCALE
			digits += charT('0');
			digits += charT(exponent + '0');
		#endif  // _MSL_NO_LOCALE
		}
		else {
			size_t oldlen = digits.size();
			while (exponent > 0)
			{
			#ifndef _MSL_NO_LOCALE
				digits += ct.widen(char(exponent % 10 + '0'));
			#else
				digits += charT(exponent % 10 + '0');
			#endif
				exponent /= 10;
			}
			_STD::reverse(digits.begin() + typename String::difference_type(oldlen), digits.end());
		}
		return result;
	}

	template <class T, class String>
	void
	__put_g_digits(ios_base& str, T val, String& digits)
	{
		// If precision is 0, make it 1 (standard)
		_SaveFlags save_flags(str);
		streamsize prec = str.precision();  // hh 980825
		if (prec == 0)
			prec = 1;
		--prec;
		str.precision(prec);
		int exponent = __put_e_digits(str, val, digits);
		++prec;
		typedef typename String::value_type charT;
	#ifndef _MSL_NO_LOCALE
		locale loc = str.getloc();
		const ctype<charT>& ct = _USE_FACET(ctype<charT>, loc);
		const numpunct<charT>& np = _USE_FACET(numpunct<charT>, loc);
		charT zero = ct.widen('0');
		charT decimal_point = np.decimal_point();
	#else  // _MSL_NO_LOCALE
		charT zero = charT('0');
		charT decimal_point = charT('.');
	#endif  // _MSL_NO_LOCALE
		if (-4 <= exponent && exponent < prec)  // convert to %f
		{
			// erase exponent
			if (digits[1] == decimal_point)
				digits.erase(size_t(prec+1));
			else
				digits.erase(1);
			if (exponent < 0)
			{
				// erase decimal_point
				if (digits[1] == decimal_point)
					digits.erase(digits.begin()+1);
				// prepend zeroes
				digits.insert(size_t(0), size_t(-exponent), zero);
				// insert decimal_point
				digits.insert(1, 1, decimal_point);
			}
			else if (exponent > 0)
			{
				// erase decimal_point (prec must be > 1, else we wouldn't be here)
				digits.erase(digits.begin()+1);
				// optionally put decimal_point back in
				if (exponent < prec-1 || str.flags() & ios_base::showpoint)
					digits.insert(size_t(exponent+1), 1, decimal_point);
			}
			// else exponsent == 0 and don't need to move it
			// Optionally remove trailing zeroes after decimal point
			if (!(str.flags() & ios_base::showpoint))
			{
				size_t e = digits.find(decimal_point);
				if (e != String::npos)
				{
					typename String::iterator i = digits.end();
					typename String::iterator j = i;
					for (--i; *i == zero; --i)
						{}
					++i;
					if (i != j)
						digits.erase(i, j);
					if (digits[digits.size()-1] == decimal_point)
						digits.pop_back();
				}
			}
		#ifndef _MSL_NO_LOCALE
			// grouping for floating point currently under debate (12/7/00)
			__put_grouping_float(decimal_point, np.thousands_sep(), np.grouping(), digits);
		#endif  // _MSL_NO_LOCALE
			return;
		}
		// Using %e format
		// Optionally remove trailing zero's and decimal point
		if (!(str.flags() & ios_base::showpoint))
		{
			if (digits[1] == decimal_point)
			{
			#ifndef _MSL_NO_LOCALE
				charT exp = str.flags() & ios_base::uppercase ? ct.widen('E') : ct.widen('e');
			#else
				charT exp = str.flags() & ios_base::uppercase ? charT('E') : charT('e');
			#endif
				size_t e = digits.find(exp);
				typename String::iterator i = digits.begin() + typename String::difference_type(e);
				typename String::iterator j = i;
				for (--i; *i == zero; --i)
					{}
				++i;
				if (i != j)
					digits.erase(i, j);
				if (digits[2] == exp)
					digits.erase(1, 1);
			}
		}
	}

	template <class T, class String>
	void
	__put_nan_digits(ios_base& str, T val, String& digits)
	{
		if (isnan(val))
			__nan_name(&digits);
		else
			__inf_name(&digits);
		if (str.flags() & ios_base::uppercase)
		{
			typedef typename String::value_type charT;
		#ifndef _MSL_NO_LOCALE
			const ctype<charT>& ct = _USE_FACET(ctype<charT>, str.getloc());
			ct.toupper(const_cast<typename String::pointer>(digits.data()), digits.data() + digits.size());
		#else  // _MSL_NO_LOCALE
			for (typename String::iterator i = digits.begin(); i < digits.end(); ++i)
				*i = charT(toupper(*i));
		#endif  // _MSL_NO_LOCALE
		}
	}

#ifndef _MSL_NO_LOCALE
	template <class charT, class OutputIterator>
	typename num_put<charT, OutputIterator>::iter_type
	num_put<charT, OutputIterator>::do_put(iter_type out, ios_base& str, char_type fill, double val) const

	{
		return do_put(out, str, fill, (long double)val);
	}
#else  // _MSL_NO_LOCALE
	template <class charT, class OutputIterator>
	OutputIterator
	numput(OutputIterator out, ios_base& str, charT fill, double val)

	{
		return numput(out, str, fill, (long double)val);
	}
#endif  // _MSL_NO_LOCALE

#ifndef _MSL_NO_LOCALE
	template <class charT, class OutputIterator>
	typename num_put<charT, OutputIterator>::iter_type
	num_put<charT, OutputIterator>::do_put(iter_type out, ios_base& str, char_type fill, long double val) const
#else  // _MSL_NO_LOCALE
	template <class charT, class OutputIterator>
	OutputIterator
	numput(OutputIterator out, ios_base& str, charT fill, long double val)
#endif  // _MSL_NO_LOCALE
	{
	#ifndef _MSL_NO_LOCALE
		const ctype<charT>& ct = _USE_FACET(ctype<charT>, str.getloc());
	#endif
		int plen = 0;
		charT prefix;
		bool minus = static_cast<bool>(signbit(val));
		if (!minus && str.flags() & ios_base::showpos)
		{
			plen = 1;
		#ifndef _MSL_NO_LOCALE
			prefix = ct.widen('+');
		#else
			prefix = charT('+');
		#endif
		}
		else if (minus)
		{
			plen = 1;
		#ifndef _MSL_NO_LOCALE
			prefix = ct.widen('-');
		#else
			prefix = charT('-');
		#endif
			val = -val;
		}
	#ifndef _MSL_NO_LOCALE
		typedef typename numpunct<charT>::string_type string_type;
	#else
		typedef basic_string<charT> string_type;
	#endif
		string_type digits;
		if (isfinite(val))
		{
			switch (str.flags() & ios_base::floatfield)
			{
			case ios_base::fixed:
				__put_f_digits(str, val, digits);
				break;
			case ios_base::scientific:
				__put_e_digits(str, val, digits);
				break;
			default:
				__put_g_digits(str, val, digits);
				break;
			}
		} else
			__put_nan_digits(str, val, digits);
		return __putnumber(out, str, fill, &prefix, plen, digits.c_str(), (int)digits.size());
	}

#endif  // _MSL_NO_FLOATING_POINT

#ifndef _MSL_NO_LOCALE

template <class charT, class OutputIterator>
typename num_put<charT, OutputIterator>::iter_type
num_put<charT, OutputIterator>::do_put(iter_type out, ios_base& str, char_type fill, const void* val) const

#else  // _MSL_NO_LOCALE

template <class charT, class OutputIterator>
OutputIterator
numput(OutputIterator out, ios_base& str, charT fill, const void* val)

#endif  // _MSL_NO_LOCALE
{
	charT tmp[sizeof(void*)*__char<>::bits/4 + 2];
	{
		_SaveFlags save_flags(str);
		hex(str);
		showbase(str);
		internal(str);
		str.width(sizeof(tmp)/sizeof(charT));
	#ifndef _MSL_NO_LOCALE
		const ctype<charT>& ct = _USE_FACET(ctype<charT>, str.getloc());
		__puthex(tmp, str, ct.widen('0'), (unsigned long)val);
	#else  // _MSL_NO_LOCALE
		__puthex(tmp, str, charT('0'), (unsigned long)val);
	#endif
	}
	return __putnumber(out, str, fill, (const charT*)0, 0, tmp, sizeof(tmp)/sizeof(charT));
}

template <class charT, class traits>
basic_istream<charT, traits>&
__read_grouping(basic_istream<charT, traits>& is, string& str)
{
	while (true)
	{
		unsigned int i;
		is >> i;
		if (is.fail())
			_MSL_ERROR(runtime_error, "syntax error reading grouping");
		str.push_back(char(i));
		ws(is);
		if (is.peek() != charT('|'))
			break;
		charT sep = (charT)is.get();
	}
	return is;
}

#ifndef _MSL_NO_CPP_NAMESPACE
	} // namespace std
#endif

#ifdef _MSL_FORCE_ENUMS_ALWAYS_INT
	#pragma enumsalwaysint reset
#endif

#ifdef _MSL_FORCE_ENABLE_BOOL_SUPPORT
	#pragma bool reset
#endif

#ifdef __MWERKS__
#pragma options align=reset
#endif

#endif // RC_INVOKED

#endif  // _MSL_NO_IO

#endif  // _NUMFACET

// hh 010228 Created
// hh 010402 Removed 68K CMF support
// hh 010725 Fixed __parseFloatDigits to check for decimal point being first character
// hh 010727 Removed dependence on CHAR_BIT
// hh 010727 Fixed but in reading floating point with no digits before decimal point
// hh 011015 Modified __parseDigits to parse octal contants more flexibly wrt thousands seps
// hh 011030 Fixed range checking bug in integral parsing
// hh 011107 LWG issue 338:  whitespace no longer allowed after sign
// hh 020529 Changed <limits> to <msl_int_limits>
// JWW 030224 Changed __MSL_LONGLONG_SUPPORT__ flag into the new more configurable _MSL_LONGLONG
// hh 030711 Added support for lack of C99 isnan-like macros
// hh 031218 Checked for decimal pointer eariler in __parseFloatDigits
// hh 040217 Changed _No_Floating_Point to _MSL_NO_FLOATING_POINT
