// xlocale internal header (from <locale>)
#pragma once
#ifndef _XLOCALE_
#define _XLOCALE_
#include <climits>
#include <cstring>
#include <stdexcept>
#include <typeinfo>
#include <xlocinfo>
#include <xdebug>

#pragma pack(push,8)
#pragma warning(push,3)

_STD_BEGIN

		// TEMPLATE CLASS _Locbase
template<class _Dummy>
	class _Locbase
	{	// define templatized category constants, instantiate on demand
public:
	static const int collate = _M_COLLATE;
	static const int ctype = _M_CTYPE;
	static const int monetary = _M_MONETARY;
	static const int numeric = _M_NUMERIC;
	static const int time = _M_TIME;
	static const int messages = _M_MESSAGE;
	static const int all = _M_ALL;
	static const int none = 0;
	};

template<class _Dummy>
	const int _Locbase<_Dummy>::collate;
template<class _Dummy>
	const int _Locbase<_Dummy>::ctype;
template<class _Dummy>
	const int _Locbase<_Dummy>::monetary;
template<class _Dummy>
	const int _Locbase<_Dummy>::numeric;
template<class _Dummy>
	const int _Locbase<_Dummy>::time;
template<class _Dummy>
	const int _Locbase<_Dummy>::messages;
template<class _Dummy>
	const int _Locbase<_Dummy>::all;
template<class _Dummy>
	const int _Locbase<_Dummy>::none;

		// CLASS locale
class _CRTIMP2 locale
	: public _Locbase<int>
	{	// nonmutable collection of facets that describe a locale
public:
	typedef int category;

			// CLASS id
	class _CRTIMP2 id
		{	// identifier stamp, unique for each distinct kind of facet
	public:
		id(size_t _Val = 0)
			: _Id(_Val)
			{	// construct with specified stamp value
			}

		operator size_t()
			{	// get stamp, with lazy allocation
			if (_Id == 0)
				{	// still zero, allocate stamp
				_Lockit _Lock(_LOCK_LOCALE);
				if (_Id == 0)
					_Id = ++_Id_cnt;
				}
			return (_Id);
			}

	private:
		id(const id&);	// not defined
		id& operator=(const id&);	// not defined

		size_t _Id;	// the identifier stamp
		static int _Id_cnt;	// static source of unique stamps
		};

	class _Locimp;

			// class facet
	class _CRTIMP2 facet
		{	// base class for all locale facets, performs reference counting
		friend class locale;
		friend class _Locimp;

	public:
		static size_t __cdecl _Getcat(const facet ** = 0)
			{	// get category value, or -1 if no corresponding C category
			return ((size_t)(-1));
			}

		void _Incref()
			{	// safely increment the reference count
			_Lockit _Lock(_LOCK_LOCALE);

			if (_Refs < (size_t)(-1))
				++_Refs;
			}

		facet *_Decref()
			{	// safely decrement the reference count, return this when dead
			_Lockit _Lock(_LOCK_LOCALE);

			if (0 < _Refs && _Refs < (size_t)(-1))
				--_Refs;
			return (_Refs == 0 ? this : 0);
			}

		void _Register();	// queue up lazy facet for destruction

//	_PROTECTED:
		virtual ~facet()
			{	// destroy the object
			}

	protected:
		explicit facet(size_t _Initrefs = 0)
			: _Refs(_Initrefs)
			{	// construct with initial reference count
			}

	private:
		facet(const facet&);	// not defined
		facet& operator=(const facet&);	// not defined

		size_t _Refs;	// the reference count
		};

			// CLASS _Locimp
	class _Locimp
		: public facet
		{	// reference-counted actual implementation of a locale
	_PROTECTED:
		~_Locimp();	// destroy the object

	private:
		friend class locale;

		_Locimp(bool _Transparent = false);	// construct from current locale

		_CRTIMP2 _Locimp(const _Locimp&);	// copy a _Locimp

		_CRTIMP2 void _Addfac(facet *, size_t);	// add a facet

		static _Locimp *__cdecl _Makeloc(const _Locinfo&,
			category, _Locimp *, const locale *);	// make essential facets

		static void __cdecl _Makewloc(const _Locinfo&,
			category, _Locimp *, const locale *);	// make wchar_t facets
#ifdef _CRTBLD_NATIVE_WCHAR_T
		static void __cdecl _Makeushloc(const _Locinfo&,
			category, _Locimp *, const locale *);	// make unsigned short facets
#endif

		static void __cdecl _Makexloc(const _Locinfo&,
			category, _Locimp *, const locale *);	// make remaining facets

		facet **_Facetvec;	// pointer to vector of facets
		size_t _Facetcount;	// size of vector of facets
		category _Catmask;	// mask describing implemented categories
		bool _Xparent;	// true if locale is transparent
		_STRING_CRT _Name;	// locale name, or "*" if not known
		static _CRTIMP2 _Locimp *_Clocptr;	// pointer to "C" locale object
		};

	_DEPRECATED locale& _Addfac(facet *, size_t,
		size_t);	// add a facet, copying on write

	template<class _Elem,
		class _Traits,
		class _Alloc>
		bool operator()(const basic_string<_Elem, _Traits, _Alloc>& _Left,
			const basic_string<_Elem, _Traits, _Alloc>& _Right) const
		{	// compare _Left and _Right strings using collate facet in locale
		const std::collate<_Elem>& _Fac =
			std::use_facet<std::collate<_Elem> >(*this);

		return (_Fac.compare(_Left.c_str(), _Left.c_str() + _Left.size(),
			_Right.c_str(), _Right.c_str() + _Right.size()) < 0);
		}

	template<class _Facet>
		locale combine(const locale& _Loc) const
		{	// combine two locales
		_Facet *_Facptr;

		_TRY_BEGIN
			_Facptr = (_Facet *)&std::use_facet<_Facet>(_Loc);
		_CATCH_ALL
			_THROW(runtime_error, "locale::combine facet missing");
		_CATCH_END

		_Locimp *_Newimp = _NEW_CRT _Locimp(*_Ptr);
		_Newimp->_Addfac(_Facptr, _Facet::id);
		if (_Facet::_Getcat() != (size_t)(-1))
			{	// not a standard facet, result has no name
			_Newimp->_Catmask = 0;
			_Newimp->_Name = "*";
			}
		return (locale(_Newimp));
		}

	template<class _Facet>
		locale(const locale& _Loc, _Facet *_Facptr)
			: _Ptr(_NEW_CRT _Locimp(*_Loc._Ptr))
		{	// construct from _Loc, replacing facet with *_Facptr
		if (_Facptr != 0)
			{	// replace facet
			_Ptr->_Addfac(_Facptr, _Facet::id);
			if (_Facet::_Getcat() != (size_t)(-1))
				_Ptr->_Catmask = 0, _Ptr->_Name = "*";	// no C category
			}
		}


	locale() _THROW0();	// construct from current locale

	locale(_Uninitialized)
		{	// defer construction
		}

	locale(const locale& _Right) _THROW0()
		: _Ptr(_Right._Ptr)
		{	// construct by copying
		_Ptr->_Incref();
		}

	locale(const locale&, const locale&,
		category);	// construct from locale and category in another locale

	explicit locale(const char *,
		category = all);	// construct from named locale for category

	locale(const locale&, const char *,
		category);	// construct from locale and category in named locale

	~locale() _THROW0()
		{	// destroy the object
		if (_Ptr != 0)
			_DELETE_CRT(_Ptr->_Decref());
		}

	locale& operator=(const locale& _Right) _THROW0()
		{	// assign a locale
		if (_Ptr != _Right._Ptr)
			{	// different implementation, point at new one
			_DELETE_CRT(_Ptr->_Decref());
			_Ptr = _Right._Ptr;
			_Ptr->_Incref();
			}
		return (*this);
		}

	string name() const
		{	// return locale name
		return (_Ptr->_Name);
		}

	const facet *_Getfacet(size_t) const;	// get facet by id

	bool operator==(const locale&) const;	// test for locale equality

	bool operator!=(const locale& _Right) const
		{	// test for locale inequality
		return (!(*this == _Right));
		}

	static const locale& __cdecl classic();	// return classic "C" locale

	static locale __cdecl global(const locale&);	// return current locale

	static locale __cdecl empty();	// return empty (transparent) locale

private:
	locale(_Locimp *_Ptrimp)
		: _Ptr(_Ptrimp)
		{	// construct from _Locimp pointer
		}

	static _Locimp *__cdecl _Init();	// initialize locale

	_Locimp *_Ptr;	// pointer to locale implementation object
	};

		// SUPPORT TEMPLATES
template<class _Facet> inline _DEPRECATED
	locale _Addfac(locale _Loc, _Facet *_Fac)
		{	// add facet to locale -- retained
		return (_Loc._Addfac(_Fac, _Facet::id, _Facet::_Getcat()));
		}

  #define _ADDFAC(loc, pfac)	locale(loc, pfac)	/* add facet to locale */

  #define _USE(loc, fac)	\
	use_facet<fac >(loc)	/* get facet reference from locale */

template<class _Facet> inline
	const _Facet& __cdecl use_facet(const locale& _Loc)
	{	// get facet reference from locale
	_Lockit _Lock(_LOCK_LOCALE);	// the thread lock, make get atomic
	static const locale::facet *_Psave;	// static pointer to lazy facet

	size_t _Id = _Facet::id;
	const locale::facet *_Pf = _Loc._Getfacet(_Id);

	if (_Pf != 0)
		;	// got facet from locale
	else if (_Psave != 0)
		_Pf = _Psave;	// lazy facet already allocated
	else if (_Facet::_Getcat(&_Psave) == (size_t)(-1))
 #if _HAS_EXCEPTIONS
		throw bad_cast();	// lazy disallowed
 #else /* _HAS_EXCEPTIONS */
		abort();	// lazy disallowed
 #endif /* _HAS_EXCEPTIONS */
	else
		{	// queue up lazy facet for destruction
		_Pf = _Psave;

		locale::facet *_Pfmod = (_Facet *)_Psave;
		_Pfmod->_Incref();
		_Pfmod->_Register();
		}

	return ((const _Facet&)(*_Pf));	// should be dynamic_cast
	}

template<class _Facet> inline _DEPRECATED
	const _Facet& __cdecl use_facet(const locale& _Loc, const _Facet *,
		bool = false)
	{	// get facet reference from locale -- retained, 2/3 arg versions
	return use_facet<_Facet>(_Loc);
	}

		// TEMPLATE FUNCTION _Narrow
#define _NARROW(T, V)	_Narrow(static_cast<T>(V))	/* convert T to char */

template<class _Elem> inline
	char _Narrow(_Elem _Ch)
	{	// convert _Elem to char
	return ((char)_Ch);	// needs _Elem::operator char()
	}

template<> inline
	char _Narrow(wchar_t _Ch)
	{	// convert wchar_t to char (using current locale, no state)
	return ((char)wctob(_Ch));
	}
#ifdef _CRTBLD_NATIVE_WCHAR_T
template<> inline
	char _Narrow(unsigned short _Ch)
	{	// convert unsigned short to char (using current locale, no state)
	return ((char)wctob(_Ch));
	}
#endif

		// TEMPLATE FUNCTION _Widen
#define _WIDEN(T, V)	_Widen(V, (T *)0)	/* convert char to T */

template<class _Elem> inline
	_Elem _Widen(char _Ch, _Elem *)
	{	// convert char to _Elem
	return ((_Elem)(unsigned char)_Ch);	// needs _Elem(char)
	}

template<> inline
	wchar_t _Widen(char _Ch, wchar_t *)
	{	// convert char to wchar_t (using current locale, no state)
	return (btowc(_Ch));
	}
#ifdef _CRTBLD_NATIVE_WCHAR_T
template<> inline
	unsigned short _Widen(char _Ch, unsigned short *)
	{	// convert char to unsigned short (using current locale, no state)
	return (btowc(_Ch));
	}
#endif

		// TEMPLATE FUNCTION _Getloctxt
template<class _Elem,
	class _InIt> inline
	int __cdecl _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
	}

		// TEMPLATE FUNCTION _Maklocstr
#define _MAKLOCSTR(_Elem, _Str, _Cvt)	\
	_Maklocstr(_Str, (_Elem *)0, _Cvt)	// convert C string to _Elem sequence

template<class _Elem> inline
	_Elem *__cdecl _Maklocstr(const char *_Ptr, _Elem *,
		const _Locinfo::_Cvtvec &)
	{	// convert C string to _Elem sequence
	size_t _Count = ::strlen(_Ptr) + 1;
	_Elem *_Ptrdest = _NEW_CRT _Elem[_Count];

	for (_Elem *_Ptrnext = _Ptrdest; 0 < _Count; --_Count, ++_Ptrnext, ++_Ptr)
		*_Ptrnext = _WIDEN(_Elem, *_Ptr);
	return (_Ptrdest);
	}

template<> inline
	wchar_t *__cdecl _Maklocstr(const char *_Ptr, wchar_t *,
		const _Locinfo::_Cvtvec &_Cvt)
	{	// convert C string to wchar_t sequence
	size_t _Count, _Count1;
	size_t _Wchars;
	const char *_Ptr1;
	wchar_t *_Ptrdest, *_Ptrnext;

	_Mbstinit(_Mbst1);
	_Count = _Count1 = ::strlen(_Ptr) + 1;
	for (_Wchars = 0, _Ptr1 = _Ptr; 0 < _Count; ++_Wchars)
		{	// determine length of wide string
		int _Bytes;
		if ((_Bytes = _Mbrtowc(0, _Ptr1, _Count, &_Mbst1, &_Cvt)) <= 0)
			break;
		_Ptr1 += _Bytes;
		_Count -= _Bytes;
		}
	++_Wchars;

	_Ptrdest = _NEW_CRT wchar_t[_Wchars];
	_Mbstinit(_Mbst2);
	for (_Ptrnext = _Ptrdest; 0 < _Wchars; --_Wchars, ++_Ptrnext)
		{	// widen string
		int _Bytes;
		if ((_Bytes = _Mbrtowc(_Ptrnext, _Ptr, _Count1, &_Mbst1, &_Cvt)) <= 0)
			break;
		_Ptr += _Bytes;
		_Count1 -= _Bytes;
		}
	*_Ptrnext = 0;
	return (_Ptrdest);
	}
#ifdef _CRTBLD_NATIVE_WCHAR_T
template<> inline
	unsigned short *__cdecl _Maklocstr(const char *_Ptr, unsigned short *,
		const _Locinfo::_Cvtvec &_Cvt)
	{	// convert C string to unsigned short sequence
	size_t _Count, _Count1;
	size_t _Wchars;
	const char *_Ptr1;
	wchar_t *_Ptrdest, *_Ptrnext;

	_Mbstinit(_Mbst1);
	_Count = _Count1 = ::strlen(_Ptr) + 1;
	for (_Wchars = 0, _Ptr1 = _Ptr; 0 < _Count; ++_Wchars)
		{	// determine length of wide string
		int _Bytes;
		if ((_Bytes = _Mbrtowc(0, _Ptr1, _Count, &_Mbst1, &_Cvt)) <= 0)
			break;
		_Ptr1 += _Bytes;
		_Count -= _Bytes;
		}
	++_Wchars;

	_Ptrdest = _NEW_CRT wchar_t[_Wchars];
	_Mbstinit(_Mbst2);
	for (_Ptrnext = _Ptrdest; 0 < _Wchars; --_Wchars, ++_Ptrnext)
		{	// widen string
		int _Bytes;
		if ((_Bytes = _Mbrtowc(_Ptrnext, _Ptr, _Count1, &_Mbst1, &_Cvt)) <= 0)
			break;
		_Ptr += _Bytes;
		_Count1 -= _Bytes;
		}
	*_Ptrnext = 0;
	return ((unsigned short *)_Ptrdest);
	}
#endif

		// STRUCT codecvt_base
class _CRTIMP2 codecvt_base
	: public locale::facet
	{	// base class for codecvt
public:
	enum
		{	// constants for different parse states
		ok, partial, error, noconv};
	typedef int result;

	codecvt_base(size_t _Refs = 0)
		: locale::facet(_Refs)
		{	// default constructor
		}

	bool always_noconv() const _THROW0()
		{	// return true if conversions never change input (from codecvt)
		return (do_always_noconv());
		}

	int max_length() const _THROW0()
		{	// return maximum length required for a conversion (from codecvt)
		return (do_max_length());
		}

	int encoding() const _THROW0()
		{	// return length of code sequence (from codecvt)
		return (do_encoding());
		}

	~codecvt_base()
		{	// destroy the object
		}

protected:
	virtual bool do_always_noconv() const _THROW0()
		{	// return true if conversions never change input (from codecvt)
		return (true);
		}

	virtual int do_max_length() const _THROW0()
		{	// return maximum length required for a conversion (from codecvt)
		return (1);
		}

	virtual int do_encoding() const _THROW0()
		{	// return length of code sequence (from codecvt)
		return (1);	// -1 ==> state dependent, 0 ==> varying length
		}
	};

		// TEMPLATE CLASS codecvt
template<class _Elem,
	class _Byte,
	class _Statype>
	class codecvt
		: public codecvt_base
	{	// facet for converting between _Elem and char (_Byte) sequences
public:
	typedef _Elem intern_type;
	typedef _Byte extern_type;
	typedef _Statype state_type;

	result in(_Statype& _State,
		const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
		_Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
		{	// convert bytes [_First1, _Last1) to [_First2, _Last)
		return (do_in(_State,
			_First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
		}

	result out(_Statype& _State,
		const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
		_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
		{	// convert [_First1, _Last1) to bytes [_First2, _Last2)
		return (do_out(_State,
			_First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
		}

	result unshift(_Statype& _State,
		_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
		{	// generate bytes to return to default shift state
		return (do_unshift(_State, _First2, _Last2, _Mid2));
		}

	int length(const _Statype& _State, const _Byte *_First1,
		const _Byte *_Last1, size_t _Count) const _THROW0()
		{	// return min(_Count, converted length of bytes [_First1, _Last1))
		return (do_length(_State, _First1, _Last1, _Count));
		}

	static locale::id id;	// unique facet id

	explicit codecvt(size_t _Refs = 0)
		: codecvt_base(_Refs)
		{	// construct from current locale
		_Init(_Locinfo());
		}

	codecvt(const _Locinfo& _Lobj, size_t _Refs = 0)
		: codecvt_base(_Refs)
		{	// construct from specified locale
		_Init(_Lobj);
		}

	static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
		{	// return locale category mask and construct standard facet
		if (_Ppf != 0 && *_Ppf == 0)
			*_Ppf = _NEW_CRT codecvt<_Elem, _Byte, _Statype>;
		return (_X_CTYPE);
		}

_PROTECTED:
	virtual ~codecvt()
		{	// destroy the object
		}

protected:
	void _Init(const _Locinfo& _Lobj)
		{	// initialize from _Lobj
		_Cvt = _Lobj._Getcvt();
		}

	virtual result do_in(_Statype&,
		const _Byte *_First1, const _Byte *, const _Byte *& _Mid1,
		_Elem *_First2, _Elem *, _Elem *& _Mid2) const
		{	// convert bytes [_First1, _Last1) to [_First2, _Last)
		_Mid1 = _First1, _Mid2 = _First2;
		return (noconv);	// convert nothing
		}

	virtual result do_out(_Statype&,
		const _Elem *_First1, const _Elem *, const _Elem *& _Mid1,
		_Byte *_First2, _Byte *, _Byte *& _Mid2) const
		{	// convert [_First1, _Last1) to bytes [_First2, _Last)
		_Mid1 = _First1, _Mid2 = _First2;
		return (noconv);	// convert nothing
		}

	virtual result do_unshift(_Statype&,
		_Byte *, _Byte *, _Byte *&) const
		{	// generate bytes to return to default shift state
		return (noconv);	// convert nothing
		}

	virtual int do_length(const _Statype&, const _Byte *_First1,
		const _Byte *_Last1, size_t _Count) const _THROW0()
		{	// return min(_Count, converted length of bytes [_First1, _Last1))
		return (int)(_Count < (size_t)(_Last1 - _First1)
			? _Count : _Last1 - _First1);	// assume one-to-one conversion
		}

private:
	_Locinfo::_Cvtvec _Cvt;	// used by codecvt<wchar_t, char, mbstate_t>
	};

		// STATIC codecvt::id OBJECT
template<class _Elem,
	class _Byte,
	class _Statype>
	locale::id codecvt<_Elem, _Byte, _Statype>::id;

		// CLASS codecvt<wchar_t, char, mbstate_t>
template<> class _CRTIMP2 codecvt<wchar_t, char, mbstate_t>
	: public codecvt_base
	{	// facet for converting between wchar_t and char (_Byte) sequences
public:
	typedef wchar_t _Elem;
	typedef char _Byte;
	typedef mbstate_t _Statype;
	typedef _Elem intern_type;
	typedef _Byte extern_type;
	typedef _Statype state_type;

	result in(_Statype& _State,
		const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
		_Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
		{	// convert bytes [_First1, _Last1) to [_First2, _Last)
		return (do_in(_State,
			_First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
		}

	result out(_Statype& _State,
		const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
		_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
		{	// convert [_First1, _Last1) to bytes [_First2, _Last)
		return (do_out(_State,
			_First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
		}

	result unshift(_Statype& _State,
		_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
		{	// generate bytes to return to default shift state
		return (do_unshift(_State,
			_First2, _Last2, _Mid2));
		}

	int length(const _Statype& _State, const _Byte *_First1,
		const _Byte *_Last1, size_t _N2) const _THROW0()
		{	// return min(_Count, converted length of bytes [_First1, _Last1))
		return (do_length(_State, _First1, _Last1, _N2));
		}

	static locale::id id;	// unique facet id

	explicit codecvt(size_t _Refs = 0)
		: codecvt_base(_Refs)
		{	// construct from current locale
		_Init(_Locinfo());
		}

	codecvt(const _Locinfo& _Lobj, size_t _Refs = 0)
		: codecvt_base(_Refs)
		{	// construct from specified locale
		_Init(_Lobj);
		}

	static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
		{	// return locale category mask and construct standard facet
		if (_Ppf != 0 && *_Ppf == 0)
			*_Ppf = _NEW_CRT codecvt<_Elem, _Byte, _Statype>;
		return (_X_CTYPE);
		}

_PROTECTED:
	virtual ~codecvt()
		{	// destroy the object
		}

protected:
	void _Init(const _Locinfo& _Lobj)
		{	// initialize from _Lobj
		_Cvt = _Lobj._Getcvt();
		}

	virtual result do_in(_Statype& _State,
		const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
		_Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
		{	// convert bytes [_First1, _Last1) to [_First2, _Last)
		_Mid1 = _First1, _Mid2 = _First2;
		result _Ans = _Mid1 == _Last1 ? ok : partial;
		int _Bytes;

		while (_Mid1 != _Last1 && _Mid2 != _Last2)
			switch (_Bytes = _Mbrtowc(_Mid2, _Mid1, _Last1 - _Mid1,
				&_State, &_Cvt))
			{	// test result of locale-specific mbrtowc call
			case -2:	// partial conversion
				_Mid1 = _Last1;
				return (_Ans);

			case -1:	// failed conversion
				return (error);

			case 0:	// converted null character
				_Bytes = (int)::strlen(_Mid1) + 1;
				// fall through

			default:	// converted _Bytes bytes to a wchar_t
				_Mid1 += _Bytes, ++_Mid2, _Ans = ok;
			}
		return (_Ans);
		}

	virtual result do_out(_Statype& _State,
		const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
		_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
		{	// convert [_First1, _Last1) to bytes [_First2, _Last)
		_Mid1 = _First1, _Mid2 = _First2;
		result _Ans = _Mid1 == _Last1 ? ok : partial;
		int _Bytes;

		while (_Mid1 != _Last1 && _Mid2 != _Last2)
			if (___mb_cur_max_func() <= _Last2 - _Mid2)
				if ((_Bytes = _Wcrtomb(_Mid2, *_Mid1,
					&_State, &_Cvt)) <= 0)
					return (error);	// locale-specific wcrtomb failed
				else
					++_Mid1, _Mid2 += _Bytes, _Ans = ok;
			else
				{	// destination too small, convert into buffer
				_Byte _Buf[MB_LEN_MAX];
				_Statype _Stsave = _State;

				if ((_Bytes = _Wcrtomb(_Buf, *_Mid1,
					&_State, &_Cvt)) <= 0)
					return (error);	// locale-specific wcrtomb failed
				else if (_Last2 - _Mid2 < _Bytes)
					{	// converted too many, roll back and return previous
					_State = _Stsave;
					return (_Ans);
					}
				else
					{	// copy converted bytes from buffer
					memcpy(_Mid2, _Buf, _Bytes);
					++_Mid1, _Mid2 += _Bytes, _Ans = ok;
					}
				}
		return (_Ans);
		}

	virtual result do_unshift(_Statype& _State,
		_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
		{	// generate bytes to return to default shift state
		_Mid2 = _First2;
		result _Ans = ok;
		int _Bytes;
		_Byte _Buf[MB_LEN_MAX];
		_Statype _Stsave = _State;

		if ((_Bytes = _Wcrtomb(_Buf, L'\0', &_State, &_Cvt)) <= 0)
			_Ans = error;	// locale-specific wcrtomb failed
		else if (_Last2 - _Mid2 < --_Bytes)
			{	// converted too many, roll back and return
			_State = _Stsave;
			_Ans = partial;
			}
		else if (0 < _Bytes)
			{	// copy converted bytes from buffer
			memcpy(_Mid2, _Buf, _Bytes);
			_Mid2 += _Bytes;
			}
		return (_Ans);
		}

	virtual int do_length(const _Statype& _State, const _Byte *_First1,
		const _Byte *_Last1, size_t _Count) const _THROW0()
		{	// return min(_Count, converted length of bytes [_First1, _Last1))
		int _Wchars;
		const _Byte *_Mid1;
		_Statype _Mystate = _State;

		for (_Wchars = 0, _Mid1 = _First1;
			(size_t)_Wchars < _Count && _Mid1 != _Last1; )
			{	// convert another wchar_t
			int _Bytes;
			_Elem _Ch;

			switch (_Bytes = _Mbrtowc(&_Ch, _Mid1, _Last1 - _Mid1,
				&_Mystate, &_Cvt))
				{	// test result of locale-specific mbrtowc call
			case -2:	// partial conversion
				return (_Wchars);

			case -1:	// failed conversion
				return (_Wchars);

			case 0:	// converted null character
				_Bytes = (int)::strlen(_Mid1) + 1;
				// fall through

			default:	// converted _Bytes bytes to a wchar_t
				_Mid1 += _Bytes, ++_Wchars;
				}
			}
		return (_Wchars);
		}

	virtual bool do_always_noconv() const _THROW0()
		{	// return true if conversions never change input
		return (false);
		}

	virtual int do_max_length() const _THROW0()
		{	// return maximum length required for a conversion (from codecvt)
		return (MB_LEN_MAX);
		}

	virtual int do_encoding() const _THROW0()
		{	// return length of code sequence (from codecvt)
		return (0);
		}

private:
	_Locinfo::_Cvtvec _Cvt;	// locale info passed to _Mbrtowc, _Wcrtomb
	};
#ifdef _CRTBLD_NATIVE_WCHAR_T
		// CLASS codecvt<unsigned short, char, mbstate_t>
template<> class _CRTIMP2 codecvt<unsigned short, char, mbstate_t>
	: public codecvt_base
	{	// facet for converting between unsigned short and char (_Byte) sequences
public:
	typedef unsigned short _Elem;
	typedef char _Byte;
	typedef mbstate_t _Statype;
	typedef _Elem intern_type;
	typedef _Byte extern_type;
	typedef _Statype state_type;

	result in(_Statype& _State,
		const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
		_Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
		{	// convert bytes [_First1, _Last1) to [_First2, _Last)
		return (do_in(_State,
			_First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
		}

	result out(_Statype& _State,
		const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
		_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
		{	// convert [_First1, _Last1) to bytes [_First2, _Last)
		return (do_out(_State,
			_First1, _Last1, _Mid1, _First2, _Last2, _Mid2));
		}

	result unshift(_Statype& _State,
		_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
		{	// generate bytes to return to default shift state
		return (do_unshift(_State,
			_First2, _Last2, _Mid2));
		}

	int length(const _Statype& _State, const _Byte *_First1,
		const _Byte *_Last1, size_t _N2) const _THROW0()
		{	// return min(_Count, converted length of bytes [_First1, _Last1))
		return (do_length(_State, _First1, _Last1, _N2));
		}

	static locale::id id;	// unique facet id

	explicit codecvt(size_t _Refs = 0)
		: codecvt_base(_Refs)
		{	// construct from current locale
		_Init(_Locinfo());
		}

	codecvt(const _Locinfo& _Lobj, size_t _Refs = 0)
		: codecvt_base(_Refs)
		{	// construct from specified locale
		_Init(_Lobj);
		}

	static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
		{	// return locale category mask and construct standard facet
		if (_Ppf != 0 && *_Ppf == 0)
			*_Ppf = _NEW_CRT codecvt<_Elem, _Byte, _Statype>;
		return (_X_CTYPE);
		}

_PROTECTED:
	virtual ~codecvt()
		{	// destroy the object
		}

protected:
	void _Init(const _Locinfo& _Lobj)
		{	// initialize from _Lobj
		_Cvt = _Lobj._Getcvt();
		}

	virtual result do_in(_Statype& _State,
		const _Byte *_First1, const _Byte *_Last1, const _Byte *& _Mid1,
		_Elem *_First2, _Elem *_Last2, _Elem *& _Mid2) const
		{	// convert bytes [_First1, _Last1) to [_First2, _Last)
		_Mid1 = _First1, _Mid2 = _First2;
		result _Ans = _Mid1 == _Last1 ? ok : partial;
		int _Bytes;

		while (_Mid1 != _Last1 && _Mid2 != _Last2)
			switch (_Bytes = _Mbrtowc((wchar_t *)_Mid2, _Mid1, _Last1 - _Mid1,
				&_State, &_Cvt))
			{	// test result of locale-specific mbrtowc call
			case -2:	// partial conversion
				_Mid1 = _Last1;
				return (_Ans);

			case -1:	// failed conversion
				return (error);

			case 0:	// converted null character
				_Bytes = (int)::strlen(_Mid1) + 1;
				// fall through

			default:	// converted _Bytes bytes to an unsigned short
				_Mid1 += _Bytes, ++_Mid2, _Ans = ok;
			}
		return (_Ans);
		}

	virtual result do_out(_Statype& _State,
		const _Elem *_First1, const _Elem *_Last1, const _Elem *& _Mid1,
		_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
		{	// convert [_First1, _Last1) to bytes [_First2, _Last)
		_Mid1 = _First1, _Mid2 = _First2;
		result _Ans = _Mid1 == _Last1 ? ok : partial;
		int _Bytes;

		while (_Mid1 != _Last1 && _Mid2 != _Last2)
			if (___mb_cur_max_func() <= _Last2 - _Mid2)
				if ((_Bytes = _Wcrtomb(_Mid2, *_Mid1,
					&_State, &_Cvt)) <= 0)
					return (error);	// locale-specific wcrtomb failed
				else
					++_Mid1, _Mid2 += _Bytes, _Ans = ok;
			else
				{	// destination too small, convert into buffer
				_Byte _Buf[MB_LEN_MAX];
				_Statype _Stsave = _State;

				if ((_Bytes = _Wcrtomb(_Buf, *_Mid1,
					&_State, &_Cvt)) <= 0)
					return (error);	// locale-specific wcrtomb failed
				else if (_Last2 - _Mid2 < _Bytes)
					{	// converted too many, roll back and return previous
					_State = _Stsave;
					return (_Ans);
					}
				else
					{	// copy converted bytes from buffer
					memcpy(_Mid2, _Buf, _Bytes);
					++_Mid1, _Mid2 += _Bytes, _Ans = ok;
					}
				}
		return (_Ans);
		}

	virtual result do_unshift(_Statype& _State,
		_Byte *_First2, _Byte *_Last2, _Byte *& _Mid2) const
		{	// generate bytes to return to default shift state
		_Mid2 = _First2;
		result _Ans = ok;
		int _Bytes;
		_Byte _Buf[MB_LEN_MAX];
		_Statype _Stsave = _State;

		if ((_Bytes = _Wcrtomb(_Buf, L'\0', &_State, &_Cvt)) <= 0)
			_Ans = error;	// locale-specific wcrtomb failed
		else if (_Last2 - _Mid2 < --_Bytes)
			{	// converted too many, roll back and return
			_State = _Stsave;
			_Ans = partial;
			}
		else if (0 < _Bytes)
			{	// copy converted bytes from buffer
			memcpy(_Mid2, _Buf, _Bytes);
			_Mid2 += _Bytes;
			}
		return (_Ans);
		}

	virtual int do_length(const _Statype& _State, const _Byte *_First1,
		const _Byte *_Last1, size_t _Count) const _THROW0()
		{	// return min(_Count, converted length of bytes [_First1, _Last1))
		int _Wchars;
		const _Byte *_Mid1;
		_Statype _Mystate = _State;

		for (_Wchars = 0, _Mid1 = _First1;
			(size_t)_Wchars < _Count && _Mid1 != _Last1; )
			{	// convert another unsigned short
			int _Bytes;
			_Elem _Ch;

			switch (_Bytes = _Mbrtowc((wchar_t *)&_Ch, _Mid1, _Last1 - _Mid1,
				&_Mystate, &_Cvt))
				{	// test result of locale-specific mbrtowc call
			case -2:	// partial conversion
				return (_Wchars);

			case -1:	// failed conversion
				return (_Wchars);

			case 0:	// converted null character
				_Bytes = (int)::strlen(_Mid1) + 1;
				// fall through

			default:	// converted _Bytes bytes to an unsigned short
				_Mid1 += _Bytes, ++_Wchars;
				}
			}
		return (_Wchars);
		}

	virtual bool do_always_noconv() const _THROW0()
		{	// return true if conversions never change input
		return (false);
		}

	virtual int do_max_length() const _THROW0()
		{	// return maximum length required for a conversion (from codecvt)
		return (MB_LEN_MAX);
		}

	virtual int do_encoding() const _THROW0()
		{	// return length of code sequence (from codecvt)
		return (0);
		}

private:
	_Locinfo::_Cvtvec _Cvt;	// locale info passed to _Mbrtowc, _Wcrtomb
	};
#endif

		// TEMPLATE CLASS codecvt_byname
template<class _Elem,
	class _Byte,
	class _Statype>
	class codecvt_byname
		: public codecvt<_Elem, _Byte, _Statype>
	{	// codecvt for named locale
public:
	explicit codecvt_byname(const char *_Locname, size_t _Refs = 0)
		: codecvt<_Elem, _Byte, _Statype>(_Locinfo(_Locname), _Refs)
		{	// construct for named locale
		}

_PROTECTED:
	virtual ~codecvt_byname()
		{	// destroy the object
		}
	};

		// STRUCT ctype_base
struct _CRTIMP2 ctype_base
	: public locale::facet
	{	// base for ctype
	enum
		{	// constants for character classifications
		alnum = _DI|_LO|_UP|_XA, alpha = _LO|_UP|_XA,
		cntrl = _BB, digit = _DI, graph = _DI|_LO|_PU|_UP|_XA,
		lower = _LO, print = _DI|_LO|_PU|_SP|_UP|_XA|_XD,
		punct = _PU, space = _CN|_SP|_XS, upper = _UP,
		xdigit = _XD};
	typedef short mask;	// to match <ctype.h>

	ctype_base(size_t _Refs = 0)
		: locale::facet(_Refs)
		{	// default constructor
		}

	~ctype_base()
		{	// destroy the object
		}
	};

		// TEMPLATE CLASS ctype
template<class _Elem>
	class ctype
		: public ctype_base
	{	// facet for classifying elements, converting cases
public:
	typedef _Elem char_type;

	bool is(mask _Maskval, _Elem _Ch) const
		{	// test if element fits any mask classifications
		return (do_is(_Maskval, _Ch));
		}

	const _Elem *is(const _Elem *_First, const _Elem *_Last,
		mask *_Dest) const
		{	// get mask sequence for elements in [_First, _Last)
		return (do_is(_First, _Last, _Dest));
		}

	const _Elem *scan_is(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) that fits mask classification
		return (do_scan_is(_Maskval, _First, _Last));
		}

	const _Elem *scan_not(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) not fitting mask classification
		return (do_scan_not(_Maskval, _First, _Last));
		}

	_Elem tolower(_Elem _Ch) const
		{	// convert element to lower case
		return (do_tolower(_Ch));
		}

	const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to lower case
		return (do_tolower(_First, _Last));
		}

	_Elem toupper(_Elem _Ch) const
		{	// convert element to upper case
		return (do_toupper(_Ch));
		}

	const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to upper case
		return (do_toupper(_First, _Last));
		}

	_Elem widen(char _Byte) const
		{	// widen char
		return (do_widen(_Byte));
		}

	const char *widen(const char *_First, const char *_Last,
		_Elem *_Dest) const
		{	// widen chars in [_First, _Last)
		return (do_widen(_First, _Last, _Dest));
		}

	char narrow(_Elem _Ch, char _Dflt = '\0') const
		{	// narrow element to char
		return (do_narrow(_Ch, _Dflt));
		}

	const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
		char _Dflt, char *_Dest) const
		{	// narrow elements in [_First, _Last) to chars
		return (do_narrow(_First, _Last, _Dflt, _Dest));
		}

	static locale::id id;	// unique facet id

	explicit ctype(size_t _Refs = 0)
		: ctype_base(_Refs)
		{	// construct from current locale
		_Init(_Locinfo());
		}

	ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
		: ctype_base(_Refs)
		{	// construct from specified locale
		_Init(_Lobj);
		}

	static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
		{	// return locale category mask and construct standard facet
		if (_Ppf != 0 && *_Ppf == 0)
			*_Ppf = _NEW_CRT ctype<_Elem>;
		return (_X_CTYPE);
		}

_PROTECTED:
	virtual ~ctype()
		{	// destroy the object
		if (_Ctype._Delfl)
			free((void *)_Ctype._Table);
		}

protected:
	void _Init(const _Locinfo& _Lobj)
		{	// initialize from _Lobj
		_Ctype = _Lobj._Getctype();
		}

	virtual bool do_is(mask _Maskval, _Elem _Ch) const
		{	// test if element fits any mask classifications
		return ((_Ctype._Table[(unsigned char)narrow(_Ch)]
			& _Maskval) != 0);
		}

	virtual const _Elem *do_is(const _Elem *_First, const _Elem *_Last,
		mask *_Dest) const
		{	// get mask sequence for elements in [_First, _Last)
		for (; _First != _Last; ++_First, ++_Dest)
			*_Dest = _Ctype._Table[(unsigned char)narrow(*_First)];
		return (_First);
		}

	virtual const _Elem *do_scan_is(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) that fits mask classification
		for (; _First != _Last && !is(_Maskval, *_First); ++_First)
			;
		return (_First);
		}

	virtual const _Elem *do_scan_not(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) not fitting mask classification
		for (; _First != _Last && is(_Maskval, *_First); ++_First)
			;
		return (_First);
		}

	virtual _Elem do_tolower(_Elem _Ch) const
		{	// convert element to lower case
		return (widen((char)_Tolower((unsigned char)narrow(_Ch),
			&_Ctype)));
		}

	virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to lower case
		for (; _First != _Last; ++_First)
			*_First = widen((char)_Tolower((unsigned char)narrow(*_First),
				&_Ctype));
		return ((const _Elem *)_First);
		}

	virtual _Elem do_toupper(_Elem _Ch) const
		{	// convert element to upper case
		return (widen((char)_Toupper((unsigned char)narrow(_Ch),
			&_Ctype)));
		}

	virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to upper case
		for (; _First != _Last; ++_First)
			*_First = widen((char)_Toupper((unsigned char)narrow(*_First),
				&_Ctype));
		return ((const _Elem *)_First);
		}

	virtual _Elem do_widen(char _Byte) const
		{	// widen char
		return (_WIDEN(_Elem, _Byte));
		}

	virtual const char *do_widen(const char *_First, const char *_Last,
		_Elem *_Dest) const
		{	// widen chars in [_First, _Last)
		for (; _First != _Last; ++_First, ++_Dest)
			*_Dest = _WIDEN(_Elem, *_First);
		return (_First);
		}

	virtual char do_narrow(_Elem _Ch, char) const
		{	// narrow element to char
		return (_NARROW(_Elem, _Ch));
		}

	virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
		char, char *_Dest) const
		{	// narrow elements in [_First, _Last) to chars
		for (; _First != _Last; ++_First, ++_Dest)
			*_Dest = _NARROW(_Elem, *_First);
		return (_First);
		}

private:
	_Locinfo::_Ctypevec _Ctype;	// locale info passed to _Tolower, etc.
	};

		// STATIC ctype::id OBJECT
template<class _Elem>
	locale::id ctype<_Elem>::id;

		// CLASS ctype<char>
template<> class _CRTIMP2 ctype<char>
	: public ctype_base
	{	// facet for classifying char elements, converting cases
	typedef ctype<char> _Myt;

public:
	typedef char _Elem;
	typedef _Elem char_type;

	bool is(mask _Maskval, _Elem _Ch) const
		{	// test if element fits any mask classifications
		return ((_Ctype._Table[(unsigned char)_Ch] & _Maskval) != 0);
		}

	const _Elem *is(const _Elem *_First, const _Elem *_Last,
		mask *_Dest) const
		{	// get mask sequence for elements in [_First, _Last)
		for (; _First != _Last; ++_First, ++_Dest)
			*_Dest = _Ctype._Table[(unsigned char)*_First];
		return (_First);
		}

	const _Elem *scan_is(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) that fits mask classification
		for (; _First != _Last && !is(_Maskval, *_First); ++_First)
			;
		return (_First);
		}

	const _Elem *scan_not(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) not fitting mask classification
		for (; _First != _Last && is(_Maskval, *_First); ++_First)
			;
		return (_First);
		}

	_Elem tolower(_Elem _Ch) const
		{	// convert element to lower case
		return (do_tolower(_Ch));
		}

	const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to lower case
		return (do_tolower(_First, _Last));
		}

	_Elem toupper(_Elem _Ch) const
		{	// convert element to upper case
		return (do_toupper(_Ch));
		}

	const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to upper case
		return (do_toupper(_First, _Last));
		}

	_Elem widen(char _Byte) const
		{	// widen char
		return (do_widen(_Byte));
		}

	const _Elem *widen(const char *_First, const char *_Last,
		_Elem *_Dest) const
		{	// widen chars in [_First, _Last)
		return (do_widen(_First, _Last, _Dest));
		}

	_Elem narrow(_Elem _Ch, char _Dflt = '\0') const
		{	// narrow element to char
		return (do_narrow(_Ch, _Dflt));
		}

	const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
		char _Dflt, char *_Dest) const
		{	// narrow elements in [_First, _Last) to chars
		return (do_narrow(_First, _Last, _Dflt, _Dest));
		}

	static locale::id id;	// unique facet id

	explicit ctype(const mask *_Table = 0, bool _Deletetable = false,
		size_t _Refs = 0)
		: ctype_base(_Refs)
		{	// construct with specified table and delete flag for table
		_Init(_Locinfo());
		if (_Table != 0)
			{	// replace existing char to mask table
			_Tidy();
			_Ctype._Table = _Table;
			_Ctype._Delfl = _Deletetable ? -1 : 0;
			}
		}

	ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
		: ctype_base(_Refs)
		{	// construct from current locale
		_Init(_Lobj);
		}

	static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
		{	// construct from specified locale
		if (_Ppf != 0 && *_Ppf == 0)
			*_Ppf = _NEW_CRT ctype<_Elem>;
		return (_X_CTYPE);
		}

	static const size_t table_size;	// size of _Ctype._Table (char to mask)

_PROTECTED:
	virtual ~ctype()
		{	// destroy the object
		_Tidy();
		}

protected:
	void _Init(const _Locinfo& _Lobj)
		{	// initialize from _Lobj
		_Ctype = _Lobj._Getctype();
		}

	void _Tidy()
		{	// free any allocated storage
		if (0 < _Ctype._Delfl)
			free((void *)_Ctype._Table);
		else if (_Ctype._Delfl < 0)
			delete[] (void *)_Ctype._Table;
		}

	virtual _Elem do_tolower(_Elem _Ch) const
		{	// convert element to lower case
		return ((_Elem)_Tolower((unsigned char)_Ch, &_Ctype));
		}

	virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to lower case
		for (; _First != _Last; ++_First)
			*_First = (_Elem)_Tolower((unsigned char)*_First, &_Ctype);
		return ((const _Elem *)_First);
		}

	virtual _Elem do_toupper(_Elem _Ch) const
		{	// convert element to upper case
		return ((_Elem)_Toupper((unsigned char)_Ch, &_Ctype));
		}

	virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to upper case
		for (; _First != _Last; ++_First)
			*_First = (_Elem)_Toupper((unsigned char)*_First, &_Ctype);
		return ((const _Elem *)_First);
		}

	virtual _Elem do_widen(char _Byte) const
		{	// widen char
		return (_Byte);
		}

	virtual const _Elem *do_widen(const char *_First, const char *_Last,
		_Elem *_Dest) const
		{	// widen chars in [_First, _Last)
		memcpy(_Dest, _First, _Last - _First);
		return (_Last);
		}

	virtual _Elem do_narrow(_Elem _Ch, char) const
		{	// narrow char
		return (_Ch);
		}

	virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
		char, char *_Dest) const
		{	// narrow elements in [_First, _Last) to chars
		memcpy(_Dest, _First, _Last - _First);
		return (_Last);
		}

	const mask *table() const _THROW0()
		{	// return address of char to mask table
		return (_Ctype._Table);
		}

	static const mask *__cdecl classic_table() _THROW0()
		{	// return address of char to mask table for "C" locale
		const _Myt& _Fac = _USE(locale::classic(), _Myt);
		return (_Fac.table());
		}

private:
	_Locinfo::_Ctypevec _Ctype;	// information
	};

		// CLASS ctype<wchar_t>
template<> class _CRTIMP2 ctype<wchar_t>
	: public ctype_base
	{	// facet for classifying wchar_t elements, converting cases
	typedef ctype<wchar_t> _Myt;

public:
	typedef wchar_t _Elem;
	typedef _Elem char_type;

	bool is(mask _Maskval, _Elem _Ch) const
		{	// test if element fits any mask classifications
		return (do_is(_Maskval, _Ch));
		}

	const _Elem *is(const _Elem *_First, const _Elem *_Last,
		mask *_Dest) const
		{	// get mask sequence for elements in [_First, _Last)
		return (do_is(_First, _Last, _Dest));
		}

	const _Elem *scan_is(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) that fits mask classification
		return (do_scan_is(_Maskval, _First, _Last));
		}

	const _Elem *scan_not(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) not fitting mask classification
		return (do_scan_not(_Maskval, _First, _Last));
		}

	_Elem tolower(_Elem _Ch) const
		{	// convert element to lower case
		return (do_tolower(_Ch));
		}

	const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to lower case
		return (do_tolower(_First, _Last));
		}

	_Elem toupper(_Elem _Ch) const
		{	// convert element to upper case
		return (do_toupper(_Ch));
		}

	const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to upper case
		return (do_toupper(_First, _Last));
		}

	_Elem widen(char _Byte) const
		{	// widen char
		return (do_widen(_Byte));
		}

	const char *widen(const char *_First, const char *_Last,
		_Elem *_Dest) const
		{	// widen chars in [_First, _Last)
		return (do_widen(_First, _Last, _Dest));
		}

	char narrow(_Elem _Ch, char _Dflt = '\0') const
		{	// narrow element to char
		return (do_narrow(_Ch, _Dflt));
		}

	const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
		char _Dflt, char *_Dest) const
		{	// narrow elements in [_First, _Last) to chars
		return (do_narrow(_First, _Last, _Dflt, _Dest));
		}

	static locale::id id;	// unique facet id

	explicit ctype(size_t _Refs = 0)
		: ctype_base(_Refs)
		{	// construct from current locale
		_Init(_Locinfo());
		}

	ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
		: ctype_base(_Refs)
		{	// construct from specified locale
		_Init(_Lobj);
		}

	static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
		{	// return locale category mask and construct standard facet
		if (_Ppf != 0 && *_Ppf == 0)
			*_Ppf = _NEW_CRT ctype<_Elem>;
		return (_X_CTYPE);
		}

_PROTECTED:
	virtual ~ctype()
		{	// destroy the object
		if (_Ctype._Delfl)
			free((void *)_Ctype._Table);
		}

protected:
	void _Init(const _Locinfo& _Lobj)
		{	// initialize from _Lobj
		_Ctype = _Lobj._Getctype();
		_Cvt = _Lobj._Getcvt();
		}

	virtual bool do_is(mask _Maskval, _Elem _Ch) const
		{	// test if element fits any mask classifications
		return ((_Getwctype(_Ch, &_Ctype) & _Maskval) != 0);
		}

	virtual const _Elem *do_is(const _Elem *_First, const _Elem *_Last,
		mask *_Dest) const
		{	// get mask sequence for elements in [_First, _Last)
		return (_Getwctypes(_First, _Last, _Dest, &_Ctype));
		}

	virtual const _Elem *do_scan_is(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) that fits mask classification
		for (; _First != _Last && !is(_Maskval, *_First); ++_First)
			;
		return (_First);
		}

	virtual const _Elem *do_scan_not(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) not fitting mask classification
		for (; _First != _Last && is(_Maskval, *_First); ++_First)
			;
		return (_First);
		}

	virtual _Elem do_tolower(_Elem _Ch) const
		{	// convert element to lower case
		return (widen((char)_Tolower((unsigned char)narrow(_Ch),
			&_Ctype)));
		}

	virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to lower case
		for (; _First != _Last; ++_First)
			*_First = widen((char)_Tolower((unsigned char)narrow(*_First),
				&_Ctype));
		return ((const _Elem *)_First);
		}

	virtual _Elem do_toupper(_Elem _Ch) const
		{	// convert element to upper case
		return (widen((char)_Toupper((unsigned char)narrow(_Ch),
			&_Ctype)));
		}

	virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to upper case
		for (; _First != _Last; ++_First)
			*_First = widen((char)_Toupper((unsigned char)narrow(*_First),
				&_Ctype));
		return ((const _Elem *)_First);
		}

	virtual _Elem do_widen(char _Byte) const
		{	// widen char
		_Mbstinit(_Mbst);
		wchar_t _Wc;
		return (_Mbrtowc(&_Wc, &_Byte, 1, &_Mbst, &_Cvt) <= 0
			? (wchar_t)(unsigned char)_Byte : _Wc);
		}

	virtual const char *do_widen(const char *_First, const char *_Last,
		_Elem *_Dest) const
		{	// widen chars in [_First, _Last)
		_Mbstinit(_Mbst);
		while (_First != _Last)
			{
			int _Bytes;

			switch (_Bytes = _Mbrtowc(_Dest, _First, _Last - _First,
				&_Mbst, &_Cvt))
				{	// test result of locale-specific mbrtowc call
			case -2:	// partial conversion
			case -1:	// failed conversion
				return (_First);

			case 0:	// converted null character
				_Bytes = (int)::strlen(_First) + 1;
				// fall through

			default:	// converted _Bytes bytes to a wchar_t
				_First += _Bytes, ++_Dest;
				}
			}
		return (_First);
		}

	virtual char do_narrow(_Elem _Ch, char _Dflt) const
		{	// narrow element to char
		char _Buf[MB_LEN_MAX];
		_Mbstinit(_Mbst);
		return (_Wcrtomb(_Buf, _Ch, &_Mbst, &_Cvt) != 1
			? _Dflt : _Buf[0]);
		}

	virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
		char _Dflt, char *_Dest) const
		{	// narrow elements in [_First, _Last) to chars
		_Mbstinit(_Mbst);
		for (; _First != _Last; ++_First)
			{
			int _Bytes;
			if ((_Bytes = _Wcrtomb(_Dest, *_First, &_Mbst, &_Cvt)) <= 0)
				{
				_Bytes = 1;
				*_Dest = _Dflt;
				}
			_Dest += _Bytes;
			}
		return (_First);
		}

private:
	_Locinfo::_Ctypevec _Ctype;	// locale info passed to _Tolower, etc.
	_Locinfo::_Cvtvec _Cvt;		// conversion information
	};
#ifdef _CRTBLD_NATIVE_WCHAR_T
		// CLASS ctype<unsigned short>
template<> class _CRTIMP2 ctype<unsigned short>
	: public ctype_base
	{	// facet for classifying unsigned short elements, converting cases
	typedef ctype<unsigned short> _Myt;

public:
	typedef unsigned short _Elem;
	typedef _Elem char_type;

	bool is(mask _Maskval, _Elem _Ch) const
		{	// test if element fits any mask classifications
		return (do_is(_Maskval, _Ch));
		}

	const _Elem *is(const _Elem *_First, const _Elem *_Last,
		mask *_Dest) const
		{	// get mask sequence for elements in [_First, _Last)
		return (do_is(_First, _Last, _Dest));
		}

	const _Elem *scan_is(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) that fits mask classification
		return (do_scan_is(_Maskval, _First, _Last));
		}

	const _Elem *scan_not(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) not fitting mask classification
		return (do_scan_not(_Maskval, _First, _Last));
		}

	_Elem tolower(_Elem _Ch) const
		{	// convert element to lower case
		return (do_tolower(_Ch));
		}

	const _Elem *tolower(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to lower case
		return (do_tolower(_First, _Last));
		}

	_Elem toupper(_Elem _Ch) const
		{	// convert element to upper case
		return (do_toupper(_Ch));
		}

	const _Elem *toupper(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to upper case
		return (do_toupper(_First, _Last));
		}

	_Elem widen(char _Byte) const
		{	// widen char
		return (do_widen(_Byte));
		}

	const char *widen(const char *_First, const char *_Last,
		_Elem *_Dest) const
		{	// widen chars in [_First, _Last)
		return (do_widen(_First, _Last, _Dest));
		}

	char narrow(_Elem _Ch, char _Dflt = '\0') const
		{	// narrow element to char
		return (do_narrow(_Ch, _Dflt));
		}

	const _Elem *narrow(const _Elem *_First, const _Elem *_Last,
		char _Dflt, char *_Dest) const
		{	// narrow elements in [_First, _Last) to chars
		return (do_narrow(_First, _Last, _Dflt, _Dest));
		}

	static locale::id id;	// unique facet id

	explicit ctype(size_t _Refs = 0)
		: ctype_base(_Refs)
		{	// construct from current locale
		_Init(_Locinfo());
		}

	ctype(const _Locinfo& _Lobj, size_t _Refs = 0)
		: ctype_base(_Refs)
		{	// construct from specified locale
		_Init(_Lobj);
		}

	static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
		{	// return locale category mask and construct standard facet
		if (_Ppf != 0 && *_Ppf == 0)
			*_Ppf = _NEW_CRT ctype<_Elem>;
		return (_X_CTYPE);
		}

_PROTECTED:
	virtual ~ctype()
		{	// destroy the object
		if (_Ctype._Delfl)
			free((void *)_Ctype._Table);
		}

protected:
	void _Init(const _Locinfo& _Lobj)
		{	// initialize from _Lobj
		_Ctype = _Lobj._Getctype();
		_Cvt = _Lobj._Getcvt();
		}

	virtual bool do_is(mask _Maskval, _Elem _Ch) const
		{	// test if element fits any mask classifications
		return ((_Getwctype(_Ch, &_Ctype) & _Maskval) != 0);
		}

	virtual const _Elem *do_is(const _Elem *_First, const _Elem *_Last,
		mask *_Dest) const
		{	// get mask sequence for elements in [_First, _Last)
		return ((const _Elem *)_Getwctypes((const wchar_t *)_First,
			(const wchar_t *)_Last, _Dest, &_Ctype));
		}

	virtual const _Elem *do_scan_is(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) that fits mask classification
		for (; _First != _Last && !is(_Maskval, *_First); ++_First)
			;
		return (_First);
		}

	virtual const _Elem *do_scan_not(mask _Maskval, const _Elem *_First,
		const _Elem *_Last) const
		{	// find first in [_First, _Last) not fitting mask classification
		for (; _First != _Last && is(_Maskval, *_First); ++_First)
			;
		return (_First);
		}

	virtual _Elem do_tolower(_Elem _Ch) const
		{	// convert element to lower case
		return (widen((char)_Tolower((unsigned char)narrow(_Ch),
			&_Ctype)));
		}

	virtual const _Elem *do_tolower(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to lower case
		for (; _First != _Last; ++_First)
			*_First = widen((char)_Tolower((unsigned char)narrow(*_First),
				&_Ctype));
		return ((const _Elem *)_First);
		}

	virtual _Elem do_toupper(_Elem _Ch) const
		{	// convert element to upper case
		return (widen((char)_Toupper((unsigned char)narrow(_Ch),
			&_Ctype)));
		}

	virtual const _Elem *do_toupper(_Elem *_First, const _Elem *_Last) const
		{	// convert [_First, _Last) in place to upper case
		for (; _First != _Last; ++_First)
			*_First = widen((char)_Toupper((unsigned char)narrow(*_First),
				&_Ctype));
		return ((const _Elem *)_First);
		}

	virtual _Elem do_widen(char _Byte) const
		{	// widen char
		_Mbstinit(_Mbst);
		unsigned short _Wc;
		return (_Mbrtowc((wchar_t *)&_Wc, &_Byte, 1, &_Mbst, &_Cvt) <= 0
			? (unsigned short)(unsigned char)_Byte : _Wc);
		}

	virtual const char *do_widen(const char *_First, const char *_Last,
		_Elem *_Dest) const
		{	// widen chars in [_First, _Last)
		_Mbstinit(_Mbst);
		while (_First != _Last)
			{
			int _Bytes;

			switch (_Bytes = _Mbrtowc((wchar_t *)_Dest, _First, _Last - _First,
				&_Mbst, &_Cvt))
				{	// test result of locale-specific mbrtowc call
			case -2:	// partial conversion
			case -1:	// failed conversion
				return (_First);

			case 0:	// converted null character
				_Bytes = (int)::strlen(_First) + 1;
				// fall through

			default:	// converted _Bytes bytes to a wchar_t
				_First += _Bytes, ++_Dest;
				}
			}
		return (_First);
		}

	virtual char do_narrow(_Elem _Ch, char _Dflt) const
		{	// narrow element to char
		char _Buf[MB_LEN_MAX];
		_Mbstinit(_Mbst);
		return (_Wcrtomb(_Buf, _Ch, &_Mbst, &_Cvt) != 1
			? _Dflt : _Buf[0]);
		}

	virtual const _Elem *do_narrow(const _Elem *_First, const _Elem *_Last,
		char _Dflt, char *_Dest) const
		{	// narrow elements in [_First, _Last) to chars
		_Mbstinit(_Mbst);
		for (; _First != _Last; ++_First)
			{
			int _Bytes;
			if ((_Bytes = _Wcrtomb(_Dest, *_First, &_Mbst, &_Cvt)) <= 0)
				{
				_Bytes = 1;
				*_Dest = _Dflt;
				}
			_Dest += _Bytes;
			}
		return (_First);
		}

private:
	_Locinfo::_Ctypevec _Ctype;	// locale info passed to _Tolower, etc.
	_Locinfo::_Cvtvec _Cvt;		// conversion information
	};
#endif

		// TEMPLATE CLASS ctype_byname
template<class _Elem>
	class ctype_byname
	: public ctype<_Elem>
	{	// ctype for named locale
public:
	explicit ctype_byname(const char *_Locname, size_t _Refs = 0)
		: ctype<_Elem>(_Locinfo(_Locname), _Refs)
		{	// construct from named locale
		}

_PROTECTED:
	virtual ~ctype_byname()
		{	// destroy the object
		}
	};

 #ifdef  _DLL_CPPLIB
  #ifdef __FORCE_INSTANCE
template class _CRTIMP2 codecvt<char, char, int>;
  #endif	// __FORCE_INSTANCE
 #endif	// _DLL_CPPLIB
_STD_END
#pragma warning(pop)
#pragma pack(pop)

#endif /* _XLOCALE_ */

/*
* Copyright (c) 1992-2001 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 V3.10:0009 */