// xlocnum internal header (from <locale>)
#pragma once
#ifndef _XLOCNUM_
#define _XLOCNUM_
#ifndef RC_INVOKED
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <streambuf>

#ifdef  _MSC_VER
#pragma pack(push,_CRT_PACKING)
#pragma warning(push,3)
#endif  /* _MSC_VER */


		// TEXT-TO-NUMERIC CONVERSION FUNCTIONS
_C_STD_BEGIN
#if defined(__cplusplus) && !defined(MRTDLL) && !defined(_M_CEE_PURE)
_C_LIB_DECL
#endif
extern _MRTIMP2_NCEEPURE long __CLRCALL_PURE_OR_CDECL _Stolx(const char *, __deref_opt_out_opt char **,
	int, int *);
extern _MRTIMP2_NCEEPURE unsigned long __CLRCALL_PURE_OR_CDECL _Stoulx(const char *, 
	__deref_opt_out_opt char **, int, int *);
extern _MRTIMP2_NCEEPURE float __CLRCALL_PURE_OR_CDECL _Stofx(const char *, __deref_opt_out_opt char **,
	long, int *);
extern _MRTIMP2_NCEEPURE double __CLRCALL_PURE_OR_CDECL _Stodx(const char *, __deref_opt_out_opt char **,
	long, int *);
extern _MRTIMP2_NCEEPURE long double __CLRCALL_PURE_OR_CDECL _Stoldx(const char *, 
	__deref_opt_out_opt char **, long, int *);
#if defined(__cplusplus) && !defined(MRTDLL) && !defined(_M_CEE_PURE)
_END_C_LIB_DECL
#endif
_C_STD_END


  #ifdef _LONGLONG
   #define _STOLL(buf, ptr, base, perr)		_strtoi64(buf, ptr, base)
   #define _STOULL(buf, ptr, base, perr)	_strtoui64(buf, ptr, base)
  #endif /* _LONGLONG */

#if defined(_WIN32_WCE)

// For CE we don't support xlocale but we needed this subset
#include "locale.h"

		// TEMPLATE FUNCTION _Maklocbyte
#define _MAKLOCBYTE(Elem, chr, cvt) \
	_Maklocbyte((_Elem)chr)	/* convert Elem to char */

template<class _Elem> inline
	char __CRTDECL _Maklocbyte(_Elem _Char)
	{	// convert _Elem to char
	return ((char)(unsigned char)_Char);
	}

template<> inline
	char __CRTDECL _Maklocbyte(wchar_t _Char)
	{	// convert wchar_t to char 
	char _Byte = '\0';
	size_t _mbSize = wcstombs(&_Byte, &_Char, 1);
	if (_mbSize != 1) // For CE we have to check here rather then before hand, as wcstombs runs incorrect value (7 in one case) when NULL is passed as first parm, when it should return 1.
	{
		return '\0';
	}
	return (_Byte);
	}

 #ifdef _CRTBLD_NATIVE_WCHAR_T
template<> inline
	char __CRTDECL _Maklocbyte(unsigned short _Char)
	{	// convert unsigned short to char 
	return _Maklocbyte((wchar_t) _Char);
	}
 #endif /* _CRTBLD_NATIVE_WCHAR_T */

#define _MAKLOCCHR(Elem, chr, cvt) \
	_Maklocchr(chr, (Elem *)0)	/* convert char to Elem */

template<class _Elem> inline
	_Elem __CRTDECL _Maklocchr(char _Byte, _Elem *)
	{	// convert char to _Elem
	return ((_Elem)(unsigned char)_Byte);
	}

template<> inline
	wchar_t __CRTDECL _Maklocchr(char _Byte, wchar_t *)
	{	// convert char to wchar_t
	wchar_t _Wc = L'\0';
	mbstowcs(&_Wc, &_Byte,1);
	return (_Wc);
	}

 #ifdef _CRTBLD_NATIVE_WCHAR_T
template<> inline
	unsigned short __CRTDECL _Maklocchr(char _Byte, unsigned short *)
	{	// convert char to unsigned short using 
	unsigned short _Wc = (unsigned short)0;
	mbstowcs((wchar_t *)&_Wc, &_Byte,1);
	return (_Wc);
	}
 #endif /* _CRTBLD_NATIVE_WCHAR_T */

		// TEMPLATE FUNCTION _Maklocstr

#define _MAKLOCSTR(_Elem, _Str, _Cvt)	\
	_Maklocstr(_Str, (_Elem *)0)	// convert C string to _Elem sequence

template<class _Elem> inline
	_Elem *__CRTDECL _Maklocstr(const char *_Ptr, _Elem *)
	{	// convert C string to _Elem
	size_t _Count = ::strlen(_Ptr) + 1;
	_Elem *_Ptrdest = _NEW_CRT _Elem[_Count];

	for (_Elem *_Ptrnext = _Ptrdest; 0 < _Count; --_Count, ++_Ptrnext, ++_Ptr)
		*_Ptrnext = (_Elem)(unsigned char)*_Ptr;
	return (_Ptrdest);
	}

_C_LIB_DECL
// We need these locale functions implemented for CE targets
_MRTIMP2 float __cdecl _Stof(const char *, char **, long);
_MRTIMP2 double __cdecl _Stod(const char *, char **, long);
_MRTIMP2 long double __cdecl _Stold(const char *, char **, long);
_END_C_LIB_DECL
#endif

_STD_BEGIN
	
 #define _VIRTUAL	virtual

	
#if defined(_WIN32_WCE)
	
// We need these locale function for CE targets as well.
template<class _Elem,
	class _InIt> inline
	int __CRTDECL _Getloctxt(_InIt& _First, _InIt& _Last, size_t _Numfields,
		const _Elem *_Ptr)
	{	// find field at _Ptr that matches longest in [_First, _Last)
	for (size_t _Off = 0; _Ptr[_Off] != (_Elem)0; ++_Off)
		if (_Ptr[_Off] == _Ptr[0])
			++_Numfields;	// add fields with leading mark to initial count
	string _Str(_Numfields, '\0');	// one column counter for each field

	int _Ans = -2;	// no candidates so far
	for (size_t _Column = 1; ; ++_Column, ++_First, _Ans = -1)
		{	// test each element against all viable fields
		bool  _Prefix = false;	// seen at least one valid prefix
		size_t _Off = 0;	// offset into fields
		size_t _Field = 0;	// current field number

		for (; _Field < _Numfields; ++_Field)
			{	// test element at _Column in field _Field
			for (; _Ptr[_Off] != (_Elem)0 && _Ptr[_Off] != _Ptr[0]; ++_Off)
				;	// find beginning of field

			if (_Str[_Field] != '\0')
				_Off += _Str[_Field];	// skip tested columns in field
			else if (_Ptr[_Off += _Column] == _Ptr[0]
				|| _Ptr[_Off] == (_Elem)0)
				{	// matched all of field, save as possible answer
				_Str[_Field] = (char)(_Column < 127
					? _Column : 127);	// save skip count if small enough
				_Ans = (int)_Field;	// save answer
				}
			else if (_First == _Last || _Ptr[_Off] != *_First)
				_Str[_Field] = (char)(_Column < 127
					? _Column : 127);	// no match, just save skip count
			else
				_Prefix = true;	// still a valid prefix
			}

		if (!_Prefix || _First == _Last)
			break;	// no pending prefixes or no input, give up
		}
	return (_Ans);	// return field number or negative value on failure
	}
#endif
	
		// TEMPLATE CLASS numpunct
template<class _Elem>
	class numpunct
#if !defined(_WIN32_WCE)
		: public locale::facet
#endif
	{	// facet for defining numeric punctuation text
public:
	typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> >
		string_type;
	typedef _Elem char_type;

#if !defined(_WIN32_WCE)
	__PURE_APPDOMAIN_GLOBAL static locale::id id;	// unique facet id
#endif

	_Elem __CLR_OR_THIS_CALL decimal_point() const
		{	// return decimal point
		return (do_decimal_point());
		}

	_Elem __CLR_OR_THIS_CALL thousands_sep() const
		{	// return thousands separator
		return (do_thousands_sep());
		}

	string __CLR_OR_THIS_CALL grouping() const
		{	// return grouping string
		return (do_grouping());
		}

	string_type __CLR_OR_THIS_CALL falsename() const
		{	// return name for false
		return (do_falsename());
		}

	string_type __CLR_OR_THIS_CALL truename() const
		{	// return name for true
		return (do_truename());
		}

	explicit __CLR_OR_THIS_CALL numpunct(size_t _Refs = 0)
#if !defined(_WIN32_WCE)
		: locale::facet(_Refs)
#endif
		{	// construct from current locale
#ifndef _WIN32_WCE
		_Locinfo _Lobj;

		_Init(_Lobj);
		if (_Kseparator == 0)
			_Kseparator =	// NB: differs from "C" locale
				_MAKLOCCHR(_Elem, ',', _Lobj._Getcvt());
#else
		_Init();
#endif
		}

#if !defined(_WIN32_WCE)
	__CLR_OR_THIS_CALL numpunct(const _Locinfo& _Lobj, size_t _Refs = 0)
		: locale::facet(_Refs)
		{	// construct from specified locale
		_Init(_Lobj);
		}

	static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet **_Ppf = 0)
		{	// return locale category mask and construct standard facet
		if (_Ppf != 0 && *_Ppf == 0)
			*_Ppf = _NEW_CRT numpunct<_Elem>;
		return (_X_NUMERIC);
		}
#endif

#if !defined(_WIN32_WCE)
_PROTECTED:
#endif
	_VIRTUAL __CLR_OR_THIS_CALL ~numpunct()
		{	// destroy the object
		_Tidy();
		}

protected:
#if defined(_WIN32_WCE)
	void __CLR_OR_THIS_CALL _Init()
		{	// initialize from _Lobj
		_Grouping = 0;
		_Falsename = 0;
		_Truename = 0;

		_TRY_BEGIN
		_Grouping = _MAKLOCSTR(char, "", _Lobj._Getcvt());
		_Falsename = _MAKLOCSTR(_Elem, "false", _Lobj._Getcvt());
		_Truename = _MAKLOCSTR(_Elem, "true", _Lobj._Getcvt());
		_CATCH_ALL
		_Tidy();
		_RERAISE;
		_CATCH_END

		_Dp = _MAKLOCCHR(_Elem, '.', _Lobj._Getcvt());
		_Kseparator =
			_MAKLOCCHR(_Elem, '\0', _Lobj._Getcvt());
		}
#else
	void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj)
		{	// initialize from _Lobj
		const lconv *_Ptr = _Lobj._Getlconv();

		_Grouping = 0;
		_Falsename = 0;
		_Truename = 0;

		_TRY_BEGIN
		_Grouping = _MAKLOCSTR(char, _Ptr->grouping, _Lobj._Getcvt());
		_Falsename = _MAKLOCSTR(_Elem, _Lobj._Getfalse(), _Lobj._Getcvt());
		_Truename = _MAKLOCSTR(_Elem, _Lobj._Gettrue(), _Lobj._Getcvt());
		_CATCH_ALL
		_Tidy();
		_RERAISE;
		_CATCH_END

		_Dp = _MAKLOCCHR(_Elem, _Ptr->decimal_point[0], _Lobj._Getcvt());
		_Kseparator =
			_MAKLOCCHR(_Elem, _Ptr->thousands_sep[0], _Lobj._Getcvt());
		}
#endif

	_VIRTUAL _Elem __CLR_OR_THIS_CALL do_decimal_point() const
		{	// return decimal point
		return (_Dp);
		}

	_VIRTUAL _Elem __CLR_OR_THIS_CALL do_thousands_sep() const
		{	// return thousands separator
		return (_Kseparator);
		}

	_VIRTUAL string __CLR_OR_THIS_CALL do_grouping() const
		{	// return grouping string
		return (string(_Grouping));
		}

	_VIRTUAL string_type __CLR_OR_THIS_CALL do_falsename() const
		{	// return name for false
		return (string_type(_Falsename));
		}

	_VIRTUAL string_type __CLR_OR_THIS_CALL do_truename() const
		{	// return name for true
		return (string_type(_Truename));
		}

private:
	void __CLR_OR_THIS_CALL _Tidy()
		{	// free all storage
		_DELETE_CRT_VEC((void *)_Grouping);
		_DELETE_CRT_VEC((void *)_Falsename);
		_DELETE_CRT_VEC((void *)_Truename);
		}

	const char *_Grouping;	// grouping string, "" for "C" locale
	_Elem _Dp;	// decimal point, '.' for "C" locale
	_Elem _Kseparator;	// thousands separator, '\0' for "C" locale
	const _Elem *_Falsename;	// name for false, "false" for "C" locale
	const _Elem *_Truename;	// name for true, "true" for "C" locale
	};

typedef numpunct<char> _Npc;
typedef numpunct<wchar_t> _Npwc;

		// TEMPLATE CLASS numpunct_byname
template<class _Elem>
	class numpunct_byname
		: public numpunct<_Elem>
	{	// numpunct for named locale
public:
	explicit __CLR_OR_THIS_CALL numpunct_byname(const char *_Locname, size_t _Refs = 0)
		: numpunct<_Elem>(_Locinfo(_Locname), _Refs)
		{	// construct for named locale
		}

_PROTECTED:
	_VIRTUAL __CLR_OR_THIS_CALL ~numpunct_byname()
		{	// destroy the object
		}
	};

		// STATIC numpunct::id OBJECT
#if !defined(_WIN32_WCE)
template<class _Elem>
	__PURE_APPDOMAIN_GLOBAL locale::id numpunct<_Elem>::id;
#endif

		// TEMPLATE CLASS num_get
template<class _Elem,
	class _InIt = istreambuf_iterator<_Elem, char_traits<_Elem> > >
	class num_get
#if !defined(_WIN32_WCE)
		: public locale::facet
#endif
	{	// facet for converting text to encoded numbers
public:
	typedef numpunct<_Elem> _Mypunct;
	typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> >
		_Mystr;

#if !defined(_WIN32_WCE)
	static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet **_Ppf = 0)
		{	// return locale category mask and construct standard facet
		if (_Ppf != 0 && *_Ppf == 0)
			*_Ppf = _NEW_CRT num_get<_Elem, _InIt>;
		return (_X_NUMERIC);
		}

	__PURE_APPDOMAIN_GLOBAL static locale::id id;	// unique facet id
#endif

#if !defined(_WIN32_WCE)
_PROTECTED:
#endif
	_VIRTUAL __CLR_OR_THIS_CALL ~num_get()
		{	// destroy the object
		}

protected:
#if !defined(_WIN32_WCE)
	void _Init(const _Locinfo& _Lobj)
		{	// initialize from _Locinfo object
		_Cvt = _Lobj._Getcvt();
		}

	_Locinfo::_Cvtvec _Cvt;		// conversion information
#endif

public:
	explicit __CLR_OR_THIS_CALL num_get(size_t _Refs = 0)
#if !defined(_WIN32_WCE)
		: locale::facet(_Refs)
#endif
		{	// construct from current locale
#if !defined(_WIN32_WCE)
		_Init(_Locinfo());
#endif
		}

#if !defined(_WIN32_WCE)
	__CLR_OR_THIS_CALL num_get(const _Locinfo& _Lobj, size_t _Refs = 0)
		: locale::facet(_Refs)
		{	// construct from specified locale
		_Init(_Lobj);
		}
#endif

	typedef _Elem char_type;
	typedef _InIt iter_type;

	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase,	ios_base::iostate& _State,
			_Bool& _Val) const
		{	// get bool from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}

	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase,	ios_base::iostate& _State,
			unsigned short& _Val) const
		{	// get unsigned short from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}

	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase,	ios_base::iostate& _State,
			unsigned int& _Val) const
		{	// get unsigned int from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}

	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			long& _Val) const
		{	// get long from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}

	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			unsigned long& _Val) const
		{	// get unsigned long from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}

 #ifdef _LONGLONG
	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			_LONGLONG& _Val) const
		{	// get long long from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}

	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			_ULONGLONG& _Val) const
		{	// get unsigned long long from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}
 #endif /* _LONGLONG */

	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			float& _Val) const
		{	// get float from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}

	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			double& _Val) const
		{	// get double from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}

	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			long double& _Val) const
		{	// get long double from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}

	_InIt __CLR_OR_THIS_CALL get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			void *& _Val) const
		{	// get void pointer from [_First, _Last) into _Val
		return (do_get(_First, _Last, _Iosbase, _State, _Val));
		}

protected:
	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			_Bool& _Val) const
		{	// get bool from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		int _Ans = -1;	// negative answer indicates failure

		if (_Iosbase.flags() & ios_base::boolalpha)
			{	// get false name or true name
			typedef typename _Mystr::size_type _Mystrsize;
#if defined(_WIN32_WCE)
			const _Mypunct _Punct_fac;
#else
			const _Mypunct& _Punct_fac = _USE(_Iosbase.getloc(), _Mypunct);
#endif
			_Mystr _Str((_Mystrsize)1, (char_type)0);
			_Str += _Punct_fac.falsename();
			_Str += (char_type)0;
			_Str += _Punct_fac.truename();	// construct "\0false\0true"
			_Ans = _Getloctxt(_First, _Last, (size_t)2, _Str.c_str());
			}
		else
			{	// get zero or nonzero integer
			char _Ac[_MAX_INT_DIG], *_Ep;
			int _Errno = 0;
			const unsigned long _Ulo = ::_Stoulx(_Ac, &_Ep,
				_Getifld(_Ac, _First, _Last, _Iosbase.flags()
#if !defined(_WIN32_WCE)
					, _Iosbase.getloc() 
#endif
					), &_Errno);

			if (_Ep != _Ac && _Errno == 0 && _Ulo <= 1)
				_Ans = _Ulo;
			}

		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ans < 0)
			_State |= ios_base::failbit;
		else
			_Val = _Ans != 0;	// deliver value
		return (_First);
		}

	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			unsigned short& _Val) const
		{	// get unsigned short from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		char _Ac[_MAX_INT_DIG], *_Ep;
		int _Errno = 0;
		int _Base = _Getifld(_Ac, _First, _Last, _Iosbase.flags()
#if !defined(_WIN32_WCE)
				, _Iosbase.getloc()
#endif
				);	// gather field into _Ac

		char *_Ptr = _Ac[0] == '-' ? _Ac + 1 : _Ac;	// point past any sign
		const unsigned long _Ans =
			::_Stoulx(_Ptr, &_Ep, _Base, &_Errno);	// convert

		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ep == _Ptr || _Errno != 0 || USHRT_MAX < _Ans)
			_State |= ios_base::failbit;
		else
			_Val = (unsigned short)(_Ac[0] == '-'
				? 0 -_Ans : _Ans);	// deliver value
		return (_First);
		}

	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			unsigned int& _Val) const
		{	// get unsigned int from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		char _Ac[_MAX_INT_DIG], *_Ep;
		int _Errno = 0;
		int _Base = _Getifld(_Ac, _First, _Last, _Iosbase.flags()
#if !defined(_WIN32_WCE)
				, _Iosbase.getloc()
#endif
				);	// gather field into _Ac
		char *_Ptr = _Ac[0] == '-' ? _Ac + 1 : _Ac;	// point past any sign
		const unsigned long _Ans =
			::_Stoulx(_Ptr, &_Ep, _Base, &_Errno);	// convert

		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ep == _Ptr || _Errno != 0 || UINT_MAX < _Ans)
			_State |= ios_base::failbit;
		else
			_Val = _Ac[0] == '-' ? 0 -_Ans : _Ans;	// deliver value
		return (_First);
		}

	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			long& _Val) const
		{	// get long from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		char _Ac[_MAX_INT_DIG], *_Ep;
		int _Errno = 0;
		const long _Ans = ::_Stolx(_Ac, &_Ep,
			_Getifld(_Ac, _First, _Last, _Iosbase.flags()
#if !defined(_WIN32_WCE)
				, _Iosbase.getloc()
#endif
				), &_Errno);	// gather field, convert

		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ep == _Ac || _Errno != 0)
			_State |= ios_base::failbit;
		else
			_Val = _Ans;	// deliver value
		return (_First);
		}

	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			unsigned long& _Val) const
		{	// get unsigned long from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		char _Ac[_MAX_INT_DIG], *_Ep;
		int _Errno = 0;
		const unsigned long _Ans = ::_Stoulx(_Ac, &_Ep,
			_Getifld(_Ac, _First, _Last, _Iosbase.flags()
#if !defined(_WIN32_WCE)
				, _Iosbase.getloc()
#endif
				), &_Errno);	// gather field, convert

		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ep == _Ac || _Errno != 0)
			_State |= ios_base::failbit;
		else
			_Val = _Ans;	// deliver value
		return (_First);
		}

 #ifdef _LONGLONG
	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			_LONGLONG& _Val) const
		{	// get long long from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		char _Ac[_MAX_INT_DIG], *_Ep;
		int _Errno = 0;
#if defined(_WIN32_WCE)
		const _LONGLONG _Ans = ::_STOLL(_Ac, &_Ep,
			_Getifld(_Ac, _First, _Last, _Iosbase.flags()),
				&_Errno);	// gather field, convert
#else
		const _LONGLONG _Ans = ::_STOLL(_Ac, &_Ep,
			_Getifld(_Ac, _First, _Last, _Iosbase.flags(),
				_Iosbase.getloc()), &_Errno);	// gather field, convert
#endif

		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ep == _Ac || _Errno != 0)
			_State |= ios_base::failbit;
		else
			_Val = _Ans;	// deliver value
		return (_First);
		}

	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			_ULONGLONG& _Val) const
		{	// get unsigned long long from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		char _Ac[_MAX_INT_DIG], *_Ep;
		int _Errno = 0;

#if defined(_WIN32_WCE)
		const _ULONGLONG _Ans = ::_STOULL(_Ac, &_Ep,
			_Getifld(_Ac, _First, _Last, _Iosbase.flags()),
				&_Errno);	// gather field, convert
#else
		const _ULONGLONG _Ans = ::_STOULL(_Ac, &_Ep,
			_Getifld(_Ac, _First, _Last, _Iosbase.flags(),
				_Iosbase.getloc()), &_Errno);	// gather field, convert
#endif


		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ep == _Ac || _Errno != 0)
			_State |= ios_base::failbit;
		else
			_Val = _Ans;	// deliver value
		return (_First);
		}
 #endif /* _LONGLONG */

	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			float& _Val) const
		{	// get float from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		char _Ac[_MAX_EXP_DIG + _MAX_SIG_DIG + 16], *_Ep;
		int _Errno = 0;
		const float _Ans = ::_Stofx(_Ac, &_Ep,
			_Getffld(_Ac, _First, _Last
#if !defined(_WIN32_WCE)
				, _Iosbase.getloc()
#endif
				), &_Errno);	// gather field, convert

		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ep == _Ac || _Errno != 0)
			_State |= ios_base::failbit;
		else
			_Val = _Ans;	// deliver value
		return (_First);
		}

	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			double& _Val) const
		{	// get double from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		char _Ac[_MAX_EXP_DIG + _MAX_SIG_DIG + 16], *_Ep;
		int _Errno = 0;
		const double _Ans = ::_Stodx(_Ac, &_Ep,
			_Getffld(_Ac, _First, _Last
#if !defined(_WIN32_WCE)
				, _Iosbase.getloc()
#endif
				), &_Errno);	// gather field, convert

		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ep == _Ac || _Errno != 0)
			_State |= ios_base::failbit;
		else
			_Val = _Ans;	// deliver value
		return (_First);
		}

	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			long double& _Val) const
		{	// get long double from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		char _Ac[_MAX_EXP_DIG + _MAX_SIG_DIG + 16], *_Ep;
		int _Errno = 0;
		const long double _Ans = ::_Stoldx(_Ac, &_Ep,
			_Getffld(_Ac, _First, _Last
#if !defined(_WIN32_WCE)
				, _Iosbase.getloc()
#endif
				), &_Errno);	// gather field, convert

		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ep == _Ac || _Errno != 0)
			_State |= ios_base::failbit;
		else
			_Val = _Ans;	// deliver value
		return (_First);
		}

	_VIRTUAL _InIt __CLR_OR_THIS_CALL do_get(_InIt _First, _InIt _Last,
		ios_base& _Iosbase, ios_base::iostate& _State,
			void *& _Val) const
		{	// get void pointer from [_First, _Last) into _Val
		_DEBUG_RANGE(_First, _Last);
		char _Ac[_MAX_INT_DIG], *_Ep;
		int _Errno = 0;
 #ifdef _LONGLONG
		int _Base = _Getifld(_Ac, _First, _Last, ios_base::hex
  #if !defined(_WIN32_WCE)
			, _Iosbase.getloc()
  #endif
			);	// gather field
		const _ULONGLONG _Ans =
			(sizeof (void *) == sizeof (unsigned long))
				? (_ULONGLONG)::_Stoulx(_Ac, &_Ep, _Base, &_Errno)
				: ::_STOULL(_Ac, &_Ep, _Base, &_Errno);
 #else /* _LONGLONG */
		const unsigned long _Ans = ::_Stoulx(_Ac, &_Ep,
			_Getifld(_Ac, _First, _Last, ios_base::hex
  #if !defined(_WIN32_WCE)
				, _Iosbase.getloc()
  #endif
				), &_Errno);	// gather field, convert
 #endif /* _LONGLONG */

		if (_First == _Last)
			_State |= ios_base::eofbit;
		if (_Ep == _Ac || _Errno != 0)
			_State |= ios_base::failbit;
		else
			_Val = (void *)(uintptr_t)_Ans;	// deliver value
		return (_First);
		}

private:
	int __CLRCALL_OR_CDECL _Getifld(__out_z char *_Ac,
		_InIt& _First, _InIt& _Last, ios_base::fmtflags _Basefield
#if !defined(_WIN32_WCE)
			, const locale& _Loc
#endif
			) const
		{	// get integer field from [_First, _Last) into _Ac
#if defined(_WIN32_WCE)
		const _Mypunct _Punct_fac;
#else
		const _Mypunct& _Punct_fac = _USE(_Loc, _Mypunct);
#endif
		const string _Grouping = _Punct_fac.grouping();
		const _Elem _Kseparator = _Punct_fac.thousands_sep();
		const _Elem _E0 = _MAKLOCCHR(_Elem, '0', _Cvt);
		char *_Ptr = _Ac;

		if (_First == _Last)
			;	// empty field
		else if (*_First == _MAKLOCCHR(_Elem, '+', _Cvt))
			*_Ptr++ = '+', ++_First;	// gather plus sign
		else if (*_First == _MAKLOCCHR(_Elem, '-', _Cvt))
			*_Ptr++ = '-', ++_First;	// gather minus sign

		_Basefield &= ios_base::basefield;
		int _Base = _Basefield == ios_base::oct ? 8
			: _Basefield == ios_base::hex ? 16
			: _Basefield == ios_base::_Fmtzero ? 0 : 10;

		bool _Seendigit = false;	// seen a digit in input
		bool _Nonzero = false;	// seen a nonzero digit in input

		if (_First != _Last && *_First == _E0)
			{	// leading zero, look for 0x, 0X
			_Seendigit = true, ++_First;
			if (_First != _Last && (*_First == _MAKLOCCHR(_Elem, 'x', _Cvt)
					|| *_First == _MAKLOCCHR(_Elem, 'X', _Cvt))
				&& (_Base == 0 || _Base == 16))
				_Base = 16, _Seendigit = false, ++_First;
			else if (_Base == 0)
				_Base = 8;
			}

		int _Dlen = _Base == 0 || _Base == 10 ? 10
			: _Base == 8 ? 8 : 16 + 6;
		string _Groups((size_t)1, (char)_Seendigit);
		size_t _Group = 0;

		for (char *const _Pe = &_Ac[_MAX_INT_DIG - 1];
			_First != _Last; ++_First)
			if (::memchr("0123456789abcdefABCDEF",
				*_Ptr = _MAKLOCBYTE(_Elem, *_First, _Cvt), _Dlen) != 0)
				{	// got a digit, characterize it and add to group size
				if ((_Nonzero || *_Ptr != '0') && _Ptr < _Pe)
					++_Ptr, _Nonzero = true;
				_Seendigit = true;
				if (_Groups[_Group] != CHAR_MAX)
					++_Groups[_Group];
				}
			else if (_Groups[_Group] == '\0'
				|| _Kseparator == (_Elem)0
				|| *_First != _Kseparator)
				break;	// not a group separator, done
			else
				{	// add a new group to _Groups string
				_Groups.append((string::size_type)1, '\0');
				++_Group;
				}

		if (_Group == 0)
			;	// no thousands separators seen
		else if ('\0' < _Groups[_Group])
			++_Group;	// add trailing group to group count
		else
			_Seendigit = false;	// trailing separator, fail

		for (const char *_Pg = _Grouping.c_str(); _Seendigit && 0 < _Group; )
			if (*_Pg == CHAR_MAX)
				break;	// end of grouping constraints to check
			else if (0 < --_Group && *_Pg != _Groups[_Group]
				|| 0 == _Group && *_Pg < _Groups[_Group])
				_Seendigit = false;	// bad group size, fail
			else if ('\0' < _Pg[1])
				++_Pg;	// group size okay, advance to next test

		if (_Seendigit && !_Nonzero)
			*_Ptr++ = '0';	// zero field, replace stripped zero(s)
		else if (!_Seendigit)
			_Ptr = _Ac;	// roll back pointer to indicate failure
		*_Ptr = '\0';
		return (_Base);
		}

	int __CLRCALL_OR_CDECL _Getffld(__out_z char *_Ac,
		_InIt& _First, _InIt &_Last
#if !defined(_WIN32_WCE)
		, const locale& _Loc
#endif
		) const
		{	// get floating-point field from [_First, _Last) into _Ac
#if defined(_WIN32_WCE)
		const _Mypunct _Punct_fac;
#else
		const _Mypunct& _Punct_fac = _USE(_Loc, _Mypunct);
#endif
		const string _Grouping = _Punct_fac.grouping();
		const _Elem _E0 = _MAKLOCCHR(_Elem, '0', _Cvt);
		char *_Ptr = _Ac;
		bool _Bad = false;

		if (_First == _Last)
			;	// empty field
		else if (*_First == _MAKLOCCHR(_Elem, '+', _Cvt))
			*_Ptr++ = '+', ++_First;	// gather plus sign
		else if (*_First == _MAKLOCCHR(_Elem, '-', _Cvt))
			*_Ptr++ = '-', ++_First;	// gather minus sign

		bool _Seendigit = false;	// seen a digit in input
		int _Significant = 0;	// number of significant digits
		int _Pten = 0;	// power of 10 multiplier

		if (*_Grouping.c_str() == CHAR_MAX || *_Grouping.c_str() <= '\0')
			for (; _First != _Last
				&& _E0 <= *_First && *_First <= _E0 + 9;
					_Seendigit = true, ++_First)
				if (_MAX_SIG_DIG <= _Significant)
					++_Pten;	// just scale by 10
				else if (*_First == _E0 && _Significant == 0)
					;	// drop leading zeros
				else
					{	// save a significant digit
					*_Ptr++ = (char)((*_First - _E0) + '0');
					++_Significant;
					}
		else
			{	// grouping specified, gather digits and group sizes
			const _Elem _Kseparator = _Punct_fac.thousands_sep();
			string _Groups((size_t)1, '\0');
			size_t _Group = 0;

			for (; _First != _Last; ++_First)
				if (_E0 <= *_First && *_First <= _E0 + 9)
					{	// got a digit, add to group size
					_Seendigit = true;
					if (_MAX_SIG_DIG <= _Significant)
						++_Pten;	// just scale by 10
					else if (*_First == _E0 && _Significant == 0)
						;	// drop leading zeros
					else
						{	// save a significant digit
						*_Ptr++ = (char)((*_First - _E0) + '0');
						++_Significant;
						}
					if (_Groups[_Group] != CHAR_MAX)
						++_Groups[_Group];
					}
				else if (_Groups[_Group] == '\0'
					|| _Kseparator == (_Elem)0
					|| *_First != _Kseparator)
					break;	// not a group separator, done
				else
					{	// add a new group to _Groups string
					_Groups.append((size_t)1, '\0');
					++_Group;
					}
			if (_Group == 0)
				;	// no thousands separators seen
			else if ('\0' < _Groups[_Group])
				++_Group;	// add trailing group to group count
			else
				_Bad = true;	// trailing separator, fail

			for (const char *_Pg = _Grouping.c_str();
				!_Bad && 0 < _Group; )
				if (*_Pg == CHAR_MAX)
					break;	// end of grouping constraints to check
				else if (0 < --_Group && *_Pg != _Groups[_Group]
					|| 0 == _Group && *_Pg < _Groups[_Group])
					_Bad = true;	// bad group size, fail
				else if ('\0' < _Pg[1])
					++_Pg;	// group size okay, advance to next test
			}

		if (_Seendigit && _Significant == 0)
			*_Ptr++ = '0';	// save at least one leading digit

		if (_First != _Last && *_First == _Punct_fac.decimal_point())
#if defined(_WIN32_WCE)
			*_Ptr++ = '.', ++_First;	// add .
#else
			*_Ptr++ = localeconv()->decimal_point[0], ++_First;	// add .
#endif

		if (_Significant == 0)
			{	// 0000. so far
			for (; _First != _Last && *_First == _E0;
				_Seendigit = true, ++_First)
				--_Pten;	// just count leading fraction zeros
			if (_Pten < 0)
				*_Ptr++ = '0', ++_Pten;	// put one back
			}

		for (; _First != _Last
				&& _E0 <= *_First && *_First <= _E0 + 9;
				_Seendigit = true, ++_First)
			if (_Significant < _MAX_SIG_DIG)
				{	// save a significant fraction digit
				*_Ptr++ = (char)((*_First - _E0) + '0');
				++_Significant;
				}

		if (_Seendigit && _First != _Last
			&& (*_First == _MAKLOCCHR(_Elem, 'e', _Cvt)
				|| *_First == _MAKLOCCHR(_Elem, 'E', _Cvt)))
			{	// 'e' or 'E', collect exponent
			*_Ptr++ = 'e', ++_First;
			_Seendigit = false, _Significant = 0;

			if (_First == _Last)
				;	// 'e' or 'E' is last element
			else if (*_First == _MAKLOCCHR(_Elem, '+', _Cvt))
				*_Ptr++ = '+', ++_First;	// gather plus sign
			else if (*_First == _MAKLOCCHR(_Elem, '-', _Cvt))
				*_Ptr++ = '-', ++_First;	// gather minus sign
			for (; _First != _Last && *_First == _E0; )
				_Seendigit = true, ++_First;	// strip leading zeros
			if (_Seendigit)
				*_Ptr++ = '0';	// put one back
			for (; _First != _Last
				&& _E0 <= *_First && *_First <= _E0 + 9;
				_Seendigit = true, ++_First)
				if (_Significant < _MAX_EXP_DIG)
					{	// save a significant exponent digit
					*_Ptr++ = (char)((*_First - _E0) + '0');
					++_Significant;
					}
			}

		if (_Bad || !_Seendigit)
			_Ptr = _Ac;	// roll back pointer to indicate failure
		*_Ptr = '\0';
		return (_Pten);
		}
	};

#if !defined(_WIN32_WCE)
		// STATIC num_get::id OBJECT
template<class _Elem,
	class _InIt>
	__PURE_APPDOMAIN_GLOBAL locale::id num_get<_Elem, _InIt>::id;
#endif

		// TEMPLATE CLASS num_put
template<class _Elem,
	class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem> > >
	class num_put
#if !defined(_WIN32_WCE)
		: public locale::facet
#endif
	{	// facet for converting encoded numbers to text
public:
	typedef numpunct<_Elem> _Mypunct;
	typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> >
		_Mystr;

#if !defined(_WIN32_WCE)
	static size_t __CLRCALL_OR_CDECL _Getcat(const locale::facet **_Ppf = 0)
		{	// return locale category mask and construct standard facet
		if (_Ppf != 0 && *_Ppf == 0)
			*_Ppf = _NEW_CRT num_put<_Elem, _OutIt>;
		return (_X_NUMERIC);
		}

	__PURE_APPDOMAIN_GLOBAL static locale::id id;	// unique facet id
#endif

#if !defined(_WIN32_WCE)
_PROTECTED:
#endif
	_VIRTUAL __CLR_OR_THIS_CALL ~num_put()
		{	// destroy the object
		}

protected:
#if !defined(_WIN32_WCE)
	void __CLR_OR_THIS_CALL _Init(const _Locinfo& _Lobj)
		{	// initialize from _Locinfo object
		_Cvt = _Lobj._Getcvt();
		}

	_Locinfo::_Cvtvec _Cvt;		// conversion information
#endif

public:
#if !defined(_WIN32_WCE)
	explicit __CLR_OR_THIS_CALL num_put(size_t _Refs = 0)
		: locale::facet(_Refs)
		{	// construct from current locale
		_Init(_Locinfo());
		}

	__CLR_OR_THIS_CALL num_put(const _Locinfo& _Lobj, size_t _Refs = 0)
		: locale::facet(_Refs)
		{	// construct from specified locale
		_Init(_Lobj);
		}
#endif

	typedef _Elem char_type;
	typedef _OutIt iter_type;

	_OutIt __CLR_OR_THIS_CALL put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, _Bool _Val) const
		{	// put formatted bool to _Dest
		return (do_put(_Dest, _Iosbase, _Fill, _Val));
		}

	_OutIt __CLR_OR_THIS_CALL put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, long _Val) const
		{	// put formatted long to _Dest
		return (do_put(_Dest, _Iosbase, _Fill, _Val));
		}

	_OutIt __CLR_OR_THIS_CALL put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, unsigned long _Val) const
		{	// put formatted unsigned long to _Dest
		return (do_put(_Dest, _Iosbase, _Fill, _Val));
		}

 #ifdef _LONGLONG
	_OutIt __CLR_OR_THIS_CALL put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, _LONGLONG _Val) const
		{	// put formatted long long to _Dest
		return (do_put(_Dest, _Iosbase, _Fill, _Val));
		}

	_OutIt __CLR_OR_THIS_CALL put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, _ULONGLONG _Val) const
		{	// put formatted unsigned long long to _Dest
		return (do_put(_Dest, _Iosbase, _Fill, _Val));
		}
 #endif /* _LONGLONG */

	_OutIt __CLR_OR_THIS_CALL put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, double _Val) const
		{	// put formatted double to _Dest
		return (do_put(_Dest, _Iosbase, _Fill, _Val));
		}

	_OutIt __CLR_OR_THIS_CALL put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, long double _Val) const
		{	// put formatted long double to _Dest
		return (do_put(_Dest, _Iosbase, _Fill, _Val));
		}

	_OutIt __CLR_OR_THIS_CALL put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, const void *_Val) const
		{	// put formatted void pointer to _Dest
		return (do_put(_Dest, _Iosbase, _Fill, _Val));
		}

protected:
	_VIRTUAL _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, _Bool _Val) const
		{	// put formatted bool to _Dest
		_DEBUG_POINTER(_Dest);
		if (!(_Iosbase.flags() & ios_base::boolalpha))
			return (do_put(_Dest, _Iosbase, _Fill, (long)_Val));
		else
			{	// put "false" or "true"
#if defined(_WIN32_WCE)
			const _Mypunct _Punct_fac;
#else
			const _Mypunct& _Punct_fac = _USE(_Iosbase.getloc(), _Mypunct);
#endif
			_Mystr _Str;
			if (_Val)
				_Str.assign(_Punct_fac.truename());
			else
				_Str.assign(_Punct_fac.falsename());

			size_t _Fillcount = _Iosbase.width() <= 0
				|| (size_t)_Iosbase.width() <= _Str.size()
					? 0 : (size_t)_Iosbase.width() - _Str.size();

			if ((_Iosbase.flags() & ios_base::adjustfield) != ios_base::left)
				{	// put leading fill
				_Dest = _Rep(_Dest, _Fill, _Fillcount);
				_Fillcount = 0;
				}
			_Dest = _Put(_Dest, _Str.c_str(), _Str.size());	// put field
			_Iosbase.width(0);
			return (_Rep(_Dest, _Fill, _Fillcount));	// put trailing fill
			}
		}

	_VIRTUAL _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, long _Val) const
		{	// put formatted long to _Dest
		const size_t _Buf_size = 2 * _MAX_INT_DIG;
		char _Buf[_Buf_size], _Fmt[6];
		return (_Iput(_Dest, _Iosbase, _Fill, _Buf,
#if defined(_WIN32_WCE)
			::sprintf(_Buf, _Ifmt(_Fmt, "ld",
#else
			::sprintf_s(_Buf, _Buf_size, _Ifmt(_Fmt, "ld",
#endif
				_Iosbase.flags()), _Val)));
		}

	_VIRTUAL _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, unsigned long _Val) const
		{	// put formatted unsigned long to _Dest
		const size_t _Buf_size = 2 * _MAX_INT_DIG;
		char _Buf[_Buf_size], _Fmt[6];
		return (_Iput(_Dest, _Iosbase, _Fill, _Buf,
#if defined(_WIN32_WCE)
			::sprintf(_Buf, _Ifmt(_Fmt, "lu",
#else
			::sprintf_s(_Buf, _Buf_size, _Ifmt(_Fmt, "lu",
#endif
				_Iosbase.flags()), _Val)));
		}

 #ifdef _LONGLONG
	_VIRTUAL _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, _LONGLONG _Val) const
		{	// put formatted long long to _Dest
		const size_t _Buf_size = 2 * _MAX_INT_DIG;
		char _Buf[_Buf_size], _Fmt[8];
		return (_Iput(_Dest, _Iosbase, _Fill, _Buf,
#if defined(_WIN32_WCE)
			::sprintf(_Buf, _Ifmt(_Fmt, "Ld",
#else
			::sprintf_s(_Buf, _Buf_size, _Ifmt(_Fmt, "Ld",
#endif
				_Iosbase.flags()), _Val)));
		}

	_VIRTUAL _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, _ULONGLONG _Val) const
		{	// put formatted unsigned long long to _Dest
		const size_t _Buf_size = 2 * _MAX_INT_DIG;
		char _Buf[_Buf_size], _Fmt[8];
		return (_Iput(_Dest, _Iosbase, _Fill, _Buf,
#if defined(_WIN32_WCE)
			::sprintf(_Buf, _Ifmt(_Fmt, "Lu",
#else
			::sprintf_s(_Buf, _Buf_size, _Ifmt(_Fmt, "Lu",
#endif
				_Iosbase.flags()), _Val)));
		}
 #endif /* _LONGLONG */

	_VIRTUAL _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, double _Val) const
		{	// put formatted double to _Dest
		const size_t _Buf_size = _MAX_EXP_DIG + _MAX_SIG_DIG + 64;
		char _Buf[_Buf_size], _Fmt[8];
		streamsize _Precision = _Iosbase.precision() <= 0
			&& !(_Iosbase.flags() & ios_base::fixed)
				? 6 : _Iosbase.precision();	// desired precision
		int _Significance = _MAX_SIG_DIG < _Precision
			? _MAX_SIG_DIG : (int)_Precision;	// actual sprintf precision
		_Precision -= _Significance;
		size_t _Beforepoint = 0;	// zeros to add before decimal point
		size_t _Afterpoint = 0;	// zeros to add after decimal point

		if ((_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed)
			{	// scale silly fixed-point value
			bool _Signed = _Val < 0;
			if (_Signed)
				_Val = -_Val;

			for (; 1e35 <= _Val && _Beforepoint < 5000; _Beforepoint += 10)
				_Val /= 1e10;	// drop 10 zeros before decimal point

			if (0 < _Val)
				for (; 10 <= _Precision && _Val <= 1e-35
					&& _Afterpoint < 5000; _Afterpoint += 10)
					{	// drop 10 zeros after decimal point
					_Val *= 1e10;
					_Precision -= 10;
					}

			if (_Signed)
				_Val = -_Val;
			}

		return (_Fput(_Dest, _Iosbase, _Fill, _Buf,
			_Beforepoint, _Afterpoint, _Precision,
#if defined(_WIN32_WCE)
				::sprintf(_Buf, _Ffmt(_Fmt, 0, _Iosbase.flags()),
#else
				::sprintf_s(_Buf, _Buf_size, _Ffmt(_Fmt, 0, _Iosbase.flags()),
#endif
					_Significance, _Val)));	// convert and put
		}

	_VIRTUAL _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, long double _Val) const
		{	// put formatted long double to _Dest
		const size_t _Buf_size = _MAX_EXP_DIG + _MAX_SIG_DIG + 64;
		char _Buf[_Buf_size], _Fmt[8];
		streamsize _Precision = _Iosbase.precision() <= 0
			&& !(_Iosbase.flags() & ios_base::fixed)
				? 6 : _Iosbase.precision();	// desired precision
		int _Significance = _MAX_SIG_DIG < _Precision
			? _MAX_SIG_DIG : (int)_Precision;	// actual sprintf precision
		_Precision -= _Significance;
		size_t _Beforepoint = 0;	// zeros to add before decimal point
		size_t _Afterpoint = 0;	// zeros to add after decimal point

		if ((_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed)
			{	// scale silly fixed-point value
			bool _Signed = _Val < 0;
			if (_Signed)
				_Val = -_Val;

			for (; 1e35 <= _Val && _Beforepoint < 5000; _Beforepoint += 10)
				_Val /= 1e10;	// drop 10 zeros before decimal point

			if (0 < _Val)
				for (; 10 <= _Precision && _Val <= 1e-35
					&& _Afterpoint < 5000; _Afterpoint += 10)
					{	// drop 10 zeros after decimal point
					_Val *= 1e10;
					_Precision -= 10;
					}

			if (_Signed)
				_Val = -_Val;
			}

		return (_Fput(_Dest, _Iosbase, _Fill, _Buf,
			_Beforepoint, _Afterpoint, _Precision,
#if defined(_WIN32_WCE)
				::sprintf(_Buf, _Ffmt(_Fmt, 'L', _Iosbase.flags()),
#else
				::sprintf_s(_Buf, _Buf_size, _Ffmt(_Fmt, 'L', _Iosbase.flags()),
#endif
					_Significance, _Val)));	// convert and put
		}

	_VIRTUAL _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, const void *_Val) const
		{	// put formatted void pointer to _Dest
		const size_t _Buf_size = 2 * _MAX_INT_DIG;
		char _Buf[_Buf_size];
		return (_Iput(_Dest, _Iosbase, _Fill, _Buf,
#if defined(_WIN32_WCE)
			::sprintf(_Buf, "%p", _Val)));
#else
			::sprintf_s(_Buf, _Buf_size, "%p", _Val)));
#endif
		}

private:
	char *__CLRCALL_OR_CDECL _Ffmt(__out_z char *_Fmt,
		char _Spec, ios_base::fmtflags _Flags) const
		{	// generate sprintf format for floating-point
		char *_Ptr = _Fmt;
		*_Ptr++ = '%';

		if (_Flags & ios_base::showpos)
			*_Ptr++ = '+';
		if (_Flags & ios_base::showpoint)
			*_Ptr++ = '#';
		*_Ptr++ = '.';
		*_Ptr++ = '*';	// for precision argument
		if (_Spec != '\0')
			*_Ptr++ = _Spec;	// 'L' qualifier for long double only

		ios_base::fmtflags _Ffl = _Flags & ios_base::floatfield;
		*_Ptr++ = _Ffl == ios_base::fixed ? 'f'
			: _Ffl == ios_base::scientific ? 'e' : 'g';	// specifier
		*_Ptr = '\0';
		return (_Fmt);
		}

	_OutIt __CLRCALL_OR_CDECL _Fput(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, const char *_Buf,
			size_t _Beforepoint, size_t _Afterpoint,
				size_t _Trailing, size_t _Count) const
		{	// put formatted floating-point to _Dest
		_DEBUG_POINTER(_Dest);
#if defined(_WIN32_WCE)
		const _Mypunct _Punct_fac;
#else
		const _Mypunct& _Punct_fac = _USE(_Iosbase.getloc(), _Mypunct);
#endif
		const string _Grouping = _Punct_fac.grouping();
		const _Elem _Kseparator = _Punct_fac.thousands_sep();
		string _Groupstring;
		const _Elem _E0 = _MAKLOCCHR(_Elem, '0', _Cvt);
		size_t _Prefix = _Buf[0] == '+' || _Buf[0] == '-' ? 1 : 0;

		char _Enders[3];
#if defined(_WIN32_WCE)
		_Enders[0] = '.';
#else
		_Enders[0] = ::localeconv()->decimal_point[0];
#endif
		_Enders[1] = 'e';
		_Enders[2] = '\0';

		const char *_Eptr = (const char *)::memchr(_Buf,
			'e', _Count);	// find exponent
		const char *_Pointptr = (const char *)::memchr(_Buf,
			_Enders[0], _Count);	// find decimal point
		if (_Pointptr == 0)
			_Trailing = 0;

		if (*_Grouping.c_str() != CHAR_MAX && '\0' < *_Grouping.c_str())
			{	// grouping specified, add thousands separators
			_Groupstring.append(_Buf, _Count);	// assemble field into string
			if (_Eptr == 0)
				_Groupstring.append(_Trailing, '0');
			else
				{	/* dispose of any zeros before exponent */
				if (_Pointptr == 0)
					{	/* no point but exponent, put scaling zeros */
					_Groupstring.append(_Beforepoint, '0');
					_Beforepoint = 0;
					}
				_Groupstring.insert(_Eptr - _Buf, _Trailing, '0');
				}
			_Trailing = 0;

			if (_Pointptr == 0)
				_Groupstring.append(_Beforepoint, '0');
			else
				{	// fill in zeros around decimal point
				_Groupstring.insert(_Pointptr - _Buf + 1, _Afterpoint, '0');
				_Groupstring.insert(_Pointptr - _Buf, _Beforepoint, '0');
				_Afterpoint = 0;
				}
			_Beforepoint = 0;

			const char *_Pg = _Grouping.c_str();
			size_t _Off = ::strcspn(&_Groupstring[0], &_Enders[0]);
			while (*_Pg != CHAR_MAX && '\0' < *_Pg
				&& (size_t)*_Pg < _Off - _Prefix)
				{	// add a NUL to mark thousands separator
				_Groupstring.insert(_Off -= *_Pg, (size_t)1, '\0');
				if ('\0' < _Pg[1])
					++_Pg;	// not last group, advance
				}

			_Buf = &_Groupstring[0];
			_Trailing = 0;
			_Count = _Groupstring.size();
			}

		size_t _Fillcount = _Beforepoint + _Afterpoint + _Trailing + _Count;
		_Fillcount = _Iosbase.width() <= 0
			|| (size_t)_Iosbase.width() <= _Fillcount
				? 0 : (size_t)_Iosbase.width() - _Fillcount;
		ios_base::fmtflags _Adjustfield =
			_Iosbase.flags() & ios_base::adjustfield;
		if (_Adjustfield != ios_base::left
			&& _Adjustfield != ios_base::internal)
			{	// put leading fill
			_Dest = _Rep(_Dest, _Fill, _Fillcount);
			_Fillcount = 0;
			}
		else if (_Adjustfield == ios_base::internal)
			{	// put internal fill
			if (0 < _Prefix)
				{	// but first put sign
				_Dest = _Putc(_Dest, _Buf, 1);
				++_Buf, --_Count;
				}
			_Dest = _Rep(_Dest, _Fill, _Fillcount);
			_Fillcount = 0;
			}

		_Pointptr = (const char *)::memchr(_Buf,
			_Enders[0], _Count);	// find decimal point again
		if (_Pointptr != 0)
			{	// has decimal point, put pieces and zero fills
			size_t _Fracoffset = _Pointptr - _Buf + 1;
			_Dest = _Putgrouped(_Dest, _Buf, _Fracoffset - 1, _Kseparator);
			_Dest = _Rep(_Dest, _E0, _Beforepoint);
			_Dest = _Rep(_Dest, _Punct_fac.decimal_point(), 1);
			_Dest = _Rep(_Dest, _E0, _Afterpoint);
			_Buf += _Fracoffset, _Count -= _Fracoffset;
			}

		_Eptr = (const char *)::memchr(_Buf,
			'e', _Count);	// find exponent again
		if (_Eptr != 0)
			{	// has exponent field, put it out
			size_t _Expoffset = _Eptr - _Buf + 1;
			_Dest = _Putgrouped(_Dest, _Buf, _Expoffset - 1, _Kseparator);
			_Dest = _Rep(_Dest, _E0, _Trailing), _Trailing = 0;
			_Dest = _Putc(_Dest, _Iosbase.flags() & ios_base::uppercase
				? "E" : "e", 1);
			_Buf += _Expoffset, _Count -= _Expoffset;
			}

		_Dest = _Putgrouped(_Dest, _Buf, _Count,
			_Kseparator);	// put leftover field
		_Dest = _Rep(_Dest, _E0, _Trailing);	// put trailing zeros
		_Iosbase.width(0);
		return (_Rep(_Dest, _Fill, _Fillcount));	// put trailing fill
		}

	char *__CLRCALL_OR_CDECL _Ifmt(__out_z char *_Fmt,
		const char *_Spec, ios_base::fmtflags _Flags) const
		{	// generate sprintf format for integer
		char *_Ptr = _Fmt;
		*_Ptr++ = '%';

		if (_Flags & ios_base::showpos)
			*_Ptr++ = '+';
		if (_Flags & ios_base::showbase)
			*_Ptr++ = '#';
		if (_Spec[0] != 'L')
			*_Ptr++ = _Spec[0];	// qualifier
		else
			{	/* change L to I64 */
			*_Ptr++ = 'I';
			*_Ptr++ = '6';
			*_Ptr++ = '4';
			}

		ios_base::fmtflags _Basefield = _Flags & ios_base::basefield;
		*_Ptr++ = _Basefield == ios_base::oct ? 'o'
			: _Basefield != ios_base::hex ? _Spec[1]	// 'd' or 'u'
			: _Flags & ios_base::uppercase ? 'X' : 'x';
		*_Ptr = '\0';
		return (_Fmt);
		}

	_OutIt __CLRCALL_OR_CDECL _Iput(_OutIt _Dest,
		ios_base& _Iosbase, _Elem _Fill, __inout_ecount(_Count) char *_Buf, size_t _Count) const
		{	// put formatted integer to _Dest
		_DEBUG_POINTER(_Dest);
#if defined(_WIN32_WCE)
		const _Mypunct _Punct_fac;
#else
		const _Mypunct& _Punct_fac = _USE(_Iosbase.getloc(), _Mypunct);
#endif
		const string _Grouping = _Punct_fac.grouping();
		const size_t _Prefix = *_Buf == '+' || *_Buf == '-' ? 1
			: *_Buf == '0' && (_Buf[1] == 'x' || _Buf[1] == 'X') ? 2
			: 0;

		if (*_Grouping.c_str() != CHAR_MAX && '\0' < *_Grouping.c_str())
			{	// grouping specified, add thousands separators
			const char *_Pg = _Grouping.c_str();
			size_t _Off = _Count;
			while (*_Pg != CHAR_MAX && '\0' < *_Pg
				&& (size_t)*_Pg < _Off - _Prefix)
				{	// add a NUL to mark thousands separator
				_Off -= *_Pg;
				_CRT_SECURE_MEMMOVE(&_Buf[_Off + 1], _Count + 1 - _Off,
					&_Buf[_Off],	 _Count + 1 - _Off);
				_Buf[_Off] = '\0', ++_Count;
				if ('\0' < _Pg[1])
					++_Pg;	// not last group, advance
				}
			}

		size_t _Fillcount = _Iosbase.width() <= 0
			|| (size_t)_Iosbase.width() <= _Count
				? 0 : (size_t)_Iosbase.width() - _Count;

		ios_base::fmtflags _Adjustfield =
			_Iosbase.flags() & ios_base::adjustfield;
		if (_Adjustfield != ios_base::left
			&& _Adjustfield != ios_base::internal)
			{	// put leading fill
			_Dest = _Rep(_Dest, _Fill, _Fillcount);
			_Fillcount = 0;
			}
		else if (_Adjustfield == ios_base::internal)
			{	// put internal fill
			_Dest = _Putc(_Dest, _Buf, _Prefix);	// put prefix
			_Buf += _Prefix, _Count -= _Prefix;
			_Dest = _Rep(_Dest, _Fill, _Fillcount), _Fillcount = 0;
			}

		_Dest = _Putgrouped(_Dest, _Buf, _Count,
			_Punct_fac.thousands_sep());	// put field
		_Iosbase.width(0);
		return (_Rep(_Dest, _Fill, _Fillcount));	// put trailing fill
		}

	_OutIt __CLRCALL_OR_CDECL _Put(_OutIt _Dest,
		const _Elem *_Ptr, size_t _Count) const
		{	// put [_Ptr, _Ptr + _Count) to _Dest
		for (; 0 < _Count; --_Count, ++_Dest, ++_Ptr)
			*_Dest = *_Ptr;
		return (_Dest);
		}

	_OutIt __CLRCALL_OR_CDECL _Putc(_OutIt _Dest,
		const char *_Ptr, size_t _Count) const
		{	// put char sequence [_Ptr, _Ptr + _Count) to _Dest
		for (; 0 < _Count; --_Count, ++_Dest, ++_Ptr)
			*_Dest = _MAKLOCCHR(_Elem, *_Ptr, _Cvt);
		return (_Dest);
		}

	_OutIt __CLRCALL_OR_CDECL _Putgrouped(_OutIt _Dest,
		const char *_Ptr, size_t _Count, _Elem _Kseparator) const
		{	// put char sequence [_Ptr, _Ptr + _Count) to _Dest with commas
		for (; ; ++_Ptr, --_Count)
			{	// put field with thousands separators for NULs
			const char *_Pend =
				(const char *)::memchr(_Ptr, '\0', _Count);
			size_t _Groupsize = _Pend != 0 ? _Pend - _Ptr : _Count;

			_Dest = _Putc(_Dest, _Ptr, _Groupsize);
			_Ptr += _Groupsize, _Count -= _Groupsize;
			if (_Count == 0)
				break;
			if (_Kseparator != (_Elem)0)
				_Dest = _Rep(_Dest, _Kseparator, 1);
			}
		return (_Dest);
		}

	_OutIt __CLRCALL_OR_CDECL _Rep(_OutIt _Dest,
		_Elem _Ch, size_t _Count) const
		{	// put _Count * _Ch to _Dest
		for (; 0 < _Count; --_Count, ++_Dest)
			*_Dest = _Ch;
		return (_Dest);
		}
	};

#if !defined(_WIN32_WCE)
		// STATIC num_put::id OBJECT
template<class _Elem,
	class _OutIt>
	__PURE_APPDOMAIN_GLOBAL locale::id num_put<_Elem, _OutIt>::id;
#endif

 #if defined(_DLL_CPPLIB) && !defined(_M_CEE_PURE)

  #ifdef __FORCE_INSTANCE
template class _CRTIMP2_PURE numpunct<char>;
template class _CRTIMP2_PURE num_get<char,
	istreambuf_iterator<char, char_traits<char> > >;
template class _CRTIMP2_PURE num_put<char,
	ostreambuf_iterator<char, char_traits<char> > >;

template class _CRTIMP2_PURE numpunct<wchar_t>;
template class _CRTIMP2_PURE num_get<wchar_t,
	istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
template class _CRTIMP2_PURE num_put<wchar_t,
	ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;

   #ifdef _CRTBLD_NATIVE_WCHAR_T
template class _CRTIMP2_PURE numpunct<unsigned short>;
template class _CRTIMP2_PURE num_get<unsigned short,
	istreambuf_iterator<unsigned short, char_traits<unsigned short> > >;
template class _CRTIMP2_PURE num_put<unsigned short,
	ostreambuf_iterator<unsigned short, char_traits<unsigned short> > >;
   #endif /* _CRTBLD_NATIVE_WCHAR_T */

  #endif /* __FORCE_INSTANCE */

 #endif /* _DLL_CPPLIB */
_STD_END

#ifdef  _MSC_VER
#pragma warning(pop)
#pragma pack(pop)
#endif  /* _MSC_VER */

#endif /* RC_INVOKED */
#endif /* _XLOCNUM_ */

/*
 * Copyright (c) 1992-2005 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 V4.05:0009 */
