// xlocale internal header (from <locale>)
#ifndef _XLOCALE_
#define _XLOCALE_
#include <use_ansi.h>
#include <climits>
#include <cstring>
#include <stdexcept>
#include <typeinfo>
#include <xlocinfo>

#ifdef  _MSC_VER
/*
 * Currently, all MS C compilers for Win32 platforms default to 8 byte
 * alignment.
 */
#pragma pack(push,8)
#endif  /* _MSC_VER */

		// CLASS locale
class locale {
public:
	enum _Category {collate = _M_COLLATE, ctype = _M_CTYPE,
		monetary = _M_MONETARY, numeric = _M_NUMERIC,
		time = _M_TIME, messages = _M_MESSAGE,
		all = _M_ALL, none = 0};
	typedef int category;
			// CLASS id
	class id {
	public:
		operator size_t()
			{_Lockit _Lk;
			if (_Id == 0)
				_Id = ++_Id_cnt;
			return (_Id); }
	private:
		size_t _Id;
		static int _Id_cnt;
		};
	class _Locimp;
			// class facet
	class facet {
		friend class locale;
		friend class _Locimp;
	public:
		static size_t _Getcat()
			{return (0); }
		void _Incref()
			{_Lockit _Lk;
			if (_Refs < (size_t)(-1))
				++_Refs; }
	_PROTECTED:
		virtual ~facet()
			{}
	protected:
		explicit facet(size_t _R = 0)
			: _Refs(_R) {}
	private:
		facet(const facet&);	// undefined
		const facet& operator=(const facet&);	// undefined
		facet *_Decref()
			{_Lockit _Lk;
			if (0 < _Refs && _Refs < (size_t)(-1))
				--_Refs;
			return (_Refs == 0 ? this : 0); }
		size_t _Refs;
		};
			// CLASS _Locimp
	class _Locimp : public facet {
	_PROTECTED:
		~_Locimp();
	private:
		friend class locale;
		_Locimp(bool _Xp = false);
		_Locimp(const _Locimp&);
		void _Addfac(facet *, size_t);
		static _Locimp * __cdecl _Makeloc(const _Locinfo&,
			category, _Locimp *, const locale *);
		static void __cdecl _Makewloc(const _Locinfo&,
			category, _Locimp *, const locale *);
		static void __cdecl _Makexloc(const _Locinfo&,
			category, _Locimp *, const locale *);
		facet **_Fv;
		size_t _Nfv;
		category _Cat;
		bool _Xpar;
		string _Name;
		static _Locimp *_Clocptr, *_Global;
		};
	locale& _Addfac(facet *, size_t, size_t);
	bool operator()(const string&, const string&) const;
	locale() _THROW0()
		: _Ptr(_Init())
		{_Locimp::_Global->_Incref(); }
	locale(_Uninitialized)
		{}
	locale(const locale& _X) _THROW0()
		: _Ptr(_X._Ptr)
		{_Ptr->_Incref(); }
	locale(const locale&, const locale&, category);
	explicit locale(const char *, category = all);
	locale(const locale&, const char *, category);
	~locale() _THROW0()
		{if (_Ptr != 0)
			delete _Ptr->_Decref(); }
	locale& operator=(const locale& _X) _THROW0()
		{if (_Ptr != _X._Ptr)
			{delete _Ptr->_Decref();
			_Ptr = _X._Ptr;
			_Ptr->_Incref(); }
		return (*this); }
	string name() const
		{return (_Ptr->_Name); }
	const facet *_Getfacet(size_t _Id, bool _Xp = false) const;
	bool _Iscloc() const;
	bool operator==(const locale& _X) const;
	static const locale& __cdecl classic();
	static locale __cdecl global(const locale&);
	static locale __cdecl empty();
private:
	locale(_Locimp *_P)
		: _Ptr(_P) {}
	static _Locimp *__cdecl _Init();
	_Locimp *_Ptr;
	};
_BITMASK_OPS(locale::_Category);
		// SUPPORT TEMPLATES
 #define _ADDFAC(loc, pfac) _Addfac(loc, pfac)
 #define _USEFAC(loc, fac)	use_facet(loc, (fac *)0)
 #define _USE(loc, fac)		use_facet(loc, (fac *)0, true)
template<class _F> inline
	locale _Addfac(locale _X, _F *_Fac)
		{return (_X._Addfac(_Fac, _F::id, _F::_Getcat())); }
template<class _F> inline
	const _F& __cdecl use_facet(const locale& _L, const _F *,
		bool _Cfacet = false)
	{static const locale::facet *_Psave = 0;
	size_t _Id = _F::id;
	const locale::facet *_Pf = _L._Getfacet(_Id, true);
	if (_Pf != 0)
		;
	else if (!_Cfacet || !_L._Iscloc())
		_THROW(bad_cast("missing locale facet"));
	else if (_Psave == 0)
		_Pf = _Psave = new _F, ((locale::facet *)_Pf)->_Incref();
	else
		_Pf = _Psave;
	return (*(const _F *)_Pf); }
		// TEMPLATE FUNCTION _Narrow
#define _NARROW(T, V)	_Narrow((T)(V))
template<class _E> inline
	int _Narrow(_E _C)	// needs _E::operator char()
	{return ((unsigned char)(char)_C); }
inline int _Narrow(wchar_t _C)
	{return (wctob(_C)); }
		// TEMPLATE FUNCTION _Widen
#define _WIDEN(T, V)	_Widen(V, (T *)0)
template<class _E> inline
	_E _Widen(char _Ch, _E *)	// needs _E(char)
	{return (_Ch); }
inline wchar_t _Widen(char _Ch, wchar_t *)
	{return (btowc(_Ch)); }
		// TEMPLATE FUNCTION _Getloctxt
template<class _E, class _II> inline
	int __cdecl _Getloctxt(_II& _F, _II& _L, size_t _N, const _E *_S)
	{for (size_t _I = 0; _S[_I] != (_E)0; ++_I)
		if (_S[_I] == _S[0])
			++_N;
	string _Str(_N, '\0');
	int _Ans = -2;
	for (size_t _J = 1; ; ++_J, ++_F, _Ans = -1)
		{bool  _Pfx;
		size_t _I, _K;
		for (_I = 0, _K = 0, _Pfx = false; _K < _N; ++_K)
			{for (; _S[_I] != (_E)0 && _S[_I] != _S[0]; ++_I)
				;
			if (_Str[_K] != '\0')
				_I += _Str[_K];
			else if (_S[_I += _J] == _S[0] || _S[_I] == (_E)0)
				{_Str[_K] = _J < 127 ? _J : 127;
				_Ans = _K; }
			else if (_F == _L || _S[_I] != *_F)
				_Str[_K] = _J < 127 ? _J : 127;
			else
				_Pfx = true; }
		if (!_Pfx || _F == _L)
			break; }
	return (_Ans); }
		// TEMPLATE FUNCTION _Maklocstr
#define _MAKLOCSTR(T, S)	_Maklocstr(S, (T *)0)
template<class _E> inline
	_E * __cdecl _Maklocstr(const char *_S, _E *)
	{size_t _L = strlen(_S) + 1;
	_E *_X = new _E[_L];
	for (_E *_P = _X; 0 < _L; --_L, ++_P, ++_S)
		*_P = _WIDEN(_E, *_S);
	return (_X); }
		// STRUCT codecvt_base
class codecvt_base : public locale::facet {
public:
	enum _Result {ok, partial, error, noconv};
	_BITMASK(_Result, result);
	codecvt_base(size_t _R = 0)
		: locale::facet(_R) {}
	bool always_noconv() const _THROW0()
		{return (do_always_noconv()); }
	int max_length() const _THROW0()
		{return (do_max_length()); }
protected:
	virtual bool do_always_noconv() const _THROW0()
		{return (true); }
	virtual int do_max_length() const _THROW0()
		{return (1); }
	};
_BITMASK_OPS(codecvt_base::_Result);
		// TEMPLATE CLASS codecvt
template<class _E, class _To, class _St>
	class codecvt : public codecvt_base {
public:
	typedef _E from_type;
	typedef _To to_type;
	typedef _St state_type;
	result convert(_St& _State,
		const _E *_F1, const _E *_L1, const _E *& _M01,
		_To *_F2, _To *_L2, _To *& _M02) const
		{return (do_convert(_State,
			_F1, _L1, _M01, _F2, _L2, _M02)); }
	int length(_St& _State, const _E *_F1,
		const _E *_L1, size_t _N2) const _THROW0()
		{return (do_length(_State, _F1, _L1, _N2)); }
	static locale::id id;
	explicit codecvt(size_t _R = 0)
		: codecvt_base(_R) {_Init(_Locinfo()); }
	codecvt(const _Locinfo& _Lobj, size_t _R = 0)
		: codecvt_base(_R) {_Init(_Lobj); }
	static size_t _Getcat()
		{return (_LC_CTYPE); }
_PROTECTED:
	virtual ~codecvt()
		{};
protected:
	void _Init(const _Locinfo& _Lobj)
		{_Cvt = _Lobj._Getcvt(); }
	virtual result do_convert(_St& _State,
		const _E *_F1, const _E *, const _E *& _M01,
		_To *_F2, _To *, _To *& _M02) const
		{_M01 = _F1, _M02 = _F2;
		return (noconv); }
	virtual int do_length(_St& _State, const _E *_F1,
		const _E *_L1, size_t _N2) const _THROW0()
		{return (_N2 < _L1 - _F1 ? _N2 : _L1 - _F1); }
private:
	_Locinfo::_Cvtvec _Cvt;
	};
template<class _E, class _To, class _St>
	locale::id codecvt<_E, _To, _St>::id;
		// CLASS codecvt<char, wchar_t, mbstate_t>
class codecvt<char, wchar_t, mbstate_t> : public codecvt_base {
public:
	typedef char _E;
	typedef wchar_t _To;
	typedef mbstate_t _St;
	typedef _E from_type;
	typedef _To to_type;
	typedef _St state_type;
	result convert(_St& _State,
		const _E *_F1, const _E *_L1, const _E *& _M01,
		_To *_F2, _To *_L2, _To *& _M02) const
		{return (do_convert(_State,
			_F1, _L1, _M01, _F2, _L2, _M02)); }
	int length(_St& _State, const _E *_F1,
		const _E *_L1, size_t _N2) const _THROW0()
		{return (do_length(_State, _F1, _L1, _N2)); }
	static locale::id id;
	explicit codecvt(size_t _R = 0)
		: codecvt_base(_R) {_Init(_Locinfo()); }
	codecvt(const _Locinfo& _Lobj, size_t _R = 0)
		: codecvt_base(_R) {_Init(_Lobj); }
	static size_t _Getcat()
		{return (_LC_CTYPE); }
_PROTECTED:
	virtual ~codecvt()
		{};
protected:
	void _Init(const _Locinfo& _Lobj)
		{_Cvt = _Lobj._Getcvt(); }
	virtual result do_convert(_St& _State,
		const _E *_F1, const _E *_L1, const _E *& _M01,
		_To *_F2, _To *_L2, _To *& _M02) const
		{_M01 = _F1, _M02 = _F2;
		result _Ans = _M01 == _L1 ? ok : partial;
		int _N;
		while (_M01 != _L1 && _M02 != _L2)
			switch (_N =
				_Mbrtowc(_M02, _M01, _L1 - _M01, &_State, &_Cvt))
			{case -2:
				_M01 = _L1;
				return (_Ans);
			case -1:
				return (error);
			case 0:
				_N = strlen(_M01) + 1;
			default:	// fall through
				_M01 += _N, ++_M02, _Ans = ok; }
		return (_Ans); }
	virtual int do_length(_St& _State, const _E *_F1,
		const _E *_L1, size_t _N2) const _THROW0()
		{const _E *_M01;
		int _N;
		for (_M01 = _F1; _M01 != _L1 && 0 < _N2; _M01 += _N, --_N2)
			if ((_N =
				_Mbrtowc(0, _M01, _L1 - _M01, &_State, &_Cvt)) < 0)
				break;
			else if (_N == 0)
				_N = 1;
		return (_M01 - _F1); }
	virtual bool do_always_noconv() const _THROW0()
		{return (false); }
private:
	_Locinfo::_Cvtvec _Cvt;
	};
		// CLASS codecvt<wchar_t, char, mbstate_t>
class codecvt<wchar_t, char, mbstate_t> : public codecvt_base {
public:
	typedef wchar_t _E;
	typedef char _To;
	typedef mbstate_t _St;
	typedef _E from_type;
	typedef _To to_type;
	typedef _St state_type;
	result convert(_St& _State,
		const _E *_F1, const _E *_L1, const _E *& _M01,
		_To *_F2, _To *_L2, _To *& _M02) const
		{return (do_convert(_State,
			_F1, _L1, _M01, _F2, _L2, _M02)); }
	int length(_St& _State, const _E *_F1,
		const _E *_L1, size_t _N2) const _THROW0()
		{return (do_length(_State, _F1, _L1, _N2)); }
	static locale::id id;
	explicit codecvt(size_t _R = 0)
		: codecvt_base(_R) {_Init(_Locinfo()); }
	codecvt(const _Locinfo& _Lobj, size_t _R = 0)
		: codecvt_base(_R) {_Init(_Lobj); }
	static size_t _Getcat()
		{return (_LC_CTYPE); }
_PROTECTED:
	virtual ~codecvt()
		{};
protected:
	void _Init(const _Locinfo& _Lobj)
		{_Cvt = _Lobj._Getcvt(); }
	virtual result do_convert(_St& _State,
		const _E *_F1, const _E *_L1, const _E *& _M01,
		_To *_F2, _To *_L2, _To *& _M02) const
		{_M01 = _F1, _M02 = _F2;
		result _Ans = _M01 == _L1 ? ok : partial;
		int _N;
		while (_M01 != _L1 && _M02 != _L2)
			if (MB_CUR_MAX <= _L2 - _M02)
				if ((_N =
					_Wcrtomb(_M02, *_M01, &_State, &_Cvt)) <= 0)
					return (error);
				else
					++_M01, _M02 += _N, _Ans = ok;
			else
				{_To _Buf[MB_LEN_MAX];
				_St _Stsave = _State;
				if ((_N =
					_Wcrtomb(_Buf, *_M01, &_State, &_Cvt)) <= 0)
					return (error);
				else if (_L2 - _M02 < _N)
					{_State = _Stsave;
					return (_Ans); }
				else
					{memcpy(_M02, _Buf, _N);
					++_M01, _M02 += _N, _Ans = ok; }}
		return (_Ans); }
	virtual int do_length(_St& _State, const _E *_F1,
		const _E *_L1, size_t _N2) const _THROW0()
		{const _E *_M01;
		_To _Buf[MB_LEN_MAX];
		int _N;
		for (_M01 = _F1; _M01 != _L1 && 0 < _N2; ++_M01, _N2 -= _N)
			if ((_N =
				_Wcrtomb(_Buf, *_M01, &_State, &_Cvt)) <= 0
					|| _N2 < _N)
				break;
		return (_M01 - _F1); }
	virtual bool do_always_noconv() const _THROW0()
		{return (false); }
	virtual int do_max_length() const _THROW0()
		{return (MB_LEN_MAX); }
private:
	_Locinfo::_Cvtvec _Cvt;
	};
		// TEMPLATE CLASS codecvt_byname
template<class _E, class _TYPE, class _St>
	class codecvt_byname : public codecvt<_E, _TYPE, _St> {
public:
	explicit codecvt_byname(const char *_S, size_t _R = 0)
		: codecvt<_E, _TYPE, _St>(_Locinfo(_S), _R) {}
_PROTECTED:
	virtual ~codecvt_byname()
		{}
	};
		// STRUCT ctype_base
struct ctype_base : public locale::facet {
	enum _Mask {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, punct = _PU,
		space = _CN|_SP|_XS, upper = _UP, xdigit = _XD};
//	_BITMASK(_Mask, mask);
	typedef short mask;	// to match <ctype.h>
	ctype_base(size_t _R = 0)
		: locale::facet(_R) {}
	};
_BITMASK_OPS(ctype_base::_Ctype);
		// TEMPLATE CLASS ctype
template<class _E>
	class ctype : public ctype_base {
public:
	typedef _E char_type;
	bool is(mask _M, _E _C) const
		{return (do_is(_M, _C)); }
	const _E *is(const _E *_F, const _E *_L, mask *_V) const
		{return (do_is(_F, _L, _V)); }
	const _E *scan_is(mask _M, const _E *_F,
		const _E *_L) const
		{return (do_scan_is(_M, _F, _L)); }
	const _E *scan_not(mask _M, const _E *_F,
		const _E *_L) const
		{return (do_scan_not(_M, _F, _L)); }
	_E tolower(_E _C) const
		{return (do_tolower(_C)); }
	const _E *tolower(_E *_F, const _E *_L) const
		{return (do_tolower(_F, _L)); }
	_E toupper(_E _C) const
		{return (do_toupper(_C)); }
	const _E *toupper(_E *_F, const _E *_L) const
		{return (do_toupper(_F, _L)); }
	_E widen(char _X) const
		{return (do_widen(_X)); }
	const char *widen(const char *_F, const char *_L,
		_E *_V) const
		{return (do_widen(_F, _L, _V)); }
	char narrow(_E _C, char _D = '\0') const
		{return (do_narrow(_C, _D)); }
	const _E *narrow(const _E *_F, const _E *_L, char _D,
		char *_V) const
		{return (do_narrow(_F, _L, _D, _V)); }
	static locale::id id;
	explicit ctype(size_t _R = 0)
		: ctype_base(_R) {_Init(_Locinfo()); }
	ctype(const _Locinfo& _Lobj, size_t _R = 0)
		: ctype_base(_R) {_Init(_Lobj); }
	static size_t _Getcat()
		{return (_LC_CTYPE); }
_PROTECTED:
	virtual ~ctype()
		{if (_Ctype._Delfl)
			free((void *)_Ctype._Table); }
protected:
	void _Init(const _Locinfo& _Lobj)
		{_Ctype = _Lobj._Getctype(); }
	virtual bool do_is(mask _M, _E _C) const
		{return (_Ctype._Table[narrow(_C)] & _M); }
	virtual const _E *do_is(const _E *_F, const _E *_L,
		mask *_V) const
		{for (; _F != _L; ++_F, ++_V)
			*_V = _Ctype._Table[narrow(*_F)];
		return (_F); }
	virtual const _E *do_scan_is(mask _M, const _E *_F,
		const _E *_L) const
		{for (; _F != _L && !is(_M, *_F); ++_F)
			;
		return (_F); }
	virtual const _E *do_scan_not(mask _M, const _E *_F,
		const _E *_L) const
		{for (; _F != _L && is(_M, *_F); ++_F)
			;
		return (_F); }
	virtual _E do_tolower(_E _C) const
		{return (widen(_Tolower(narrow(_C), &_Ctype))); }
	virtual const _E *do_tolower(_E *_F, const _E *_L) const
		{for (; _F != _L; ++_F)
			*_F = _Tolower(*_F, &_Ctype);
		return ((const _E *)_F); }
	virtual _E do_toupper(_E _C) const
		{return (widen(_Toupper(narrow(_C), &_Ctype))); }
	virtual const _E *do_toupper(_E *_F, const _E *_L) const
		{for (; _F != _L; ++_F)
			*_F = _Toupper(*_F, &_Ctype);
		return ((const _E *)_F); }
	virtual _E do_widen(char _X) const
		{return (_WIDEN(_E, _X)); }
	virtual const char *do_widen(const char *_F, const char *_L,
		_E *_V) const
		{for (; _F != _L; ++_F, ++_V)
			*_V = _WIDEN(_E, *_F);
		return (_F); }
	virtual char do_narrow(_E _C, char) const
		{return (_NARROW(_E, _C)); }
	virtual const _E *do_narrow(const _E *_F, const _E *_L,
		char, char *_V) const
		{for (; _F != _L; ++_F, ++_V)
			*_V = _NARROW(_E, *_F);
		return (_F); }
private:
	_Locinfo::_Ctypevec _Ctype;
	};
template<class _E>
	locale::id ctype<_E>::id;
		// CLASS ctype<char>
class ctype<char> : public ctype_base {
public:
	typedef char _E;
	typedef _E char_type;
	bool is(mask _M, _E _C) const
		{return (_Ctype._Table[(unsigned char)_C] & _M); }
	const _E *is(const _E *_F, const _E *_L, mask *_V) const
		{for (; _F != _L; ++_F, ++_V)
			*_V = _Ctype._Table[(unsigned char)*_F];
		return (_F); }
	const _E *scan_is(mask _M, const _E *_F,
		const _E *_L) const
		{for (; _F != _L && !is(_M, *_F); ++_F)
			;
		return (_F); }
	const _E *scan_not(mask _M, const _E *_F,
		const _E *_L) const
		{for (; _F != _L && is(_M, *_F); ++_F)
			;
		return (_F); }
	_E tolower(_E _C) const
		{return (do_tolower(_C)); }
	const _E *tolower(_E *_F, const _E *_L) const
		{return (do_tolower(_F, _L)); }
	_E toupper(_E _C) const
		{return (do_toupper(_C)); }
	const _E *toupper(_E *_F, const _E *_L) const
		{return (do_toupper(_F, _L)); }
	_E widen(char _X) const
		{return (_X); }
	const _E *widen(const char *_F, const char *_L, _E *_V) const
		{memcpy(_V, _F, _L - _F);
		return (_L); }
	_E narrow(_E _C, char _D = '\0') const
		{return (_C); }
	const _E *narrow(const _E *_F, const _E *_L, char _D,
		char *_V) const
		{memcpy(_V, _F, _L - _F);
		return (_L); }
	static locale::id id;
	explicit ctype(const mask *_Tab = 0, bool _Df = false,
		size_t _R = 0)
		: ctype_base(_R)
		{_Init(_Locinfo());
		if (_Ctype._Delfl)
			free((void *)_Ctype._Table), _Ctype._Delfl = false;
		if (_Tab == 0)
			_Ctype._Table = _Cltab;
		else
			_Ctype._Table = _Tab, _Ctype._Delfl = _Df; }
	ctype(const _Locinfo& _Lobj, size_t _R = 0)
		: ctype_base(_R) {_Init(_Lobj); }
	static size_t _Getcat()
		{return (_LC_CTYPE); }
	static const size_t table_size;
_PROTECTED:
	virtual ~ctype()
		{if (_Ctype._Delfl)
			free((void *)_Ctype._Table); }
protected:
	void _Init(const _Locinfo& _Lobj)
		{_Ctype = _Lobj._Getctype();
		if (_Cltab == 0)
			_Cltab = _Ctype._Table, _Ctype._Delfl = false; }
	virtual _E do_tolower(_E _C) const
		{return (_Tolower((unsigned char)_C, &_Ctype)); }
	virtual const _E *do_tolower(_E *_F, const _E *_L) const
		{for (; _F != _L; ++_F)
			*_F = _Tolower(*_F, &_Ctype);
		return ((const _E *)_F); }
	virtual _E do_toupper(_E _C) const
		{return (_Toupper((unsigned char)_C, &_Ctype)); }
	virtual const _E *do_toupper(_E *_F, const _E *_L) const
		{for (; _F != _L; ++_F)
			*_F = _Toupper(*_F, &_Ctype);
		return ((const _E *)_F); }
	const mask *table() const _THROW0()
		{return (_Ctype._Table); }
	static const mask *classic_table() _THROW0()
		{if (_Cltab == 0)
			locale::classic();	// force locale::_Init() call
		return (_Cltab); }
private:
	_Locinfo::_Ctypevec _Ctype;
	static const mask *_Cltab;
	};
		// TEMPLATE CLASS ctype_byname
template<class _E>
	class ctype_byname : public ctype<_E> {
public:
	explicit ctype_byname(const char *_S, size_t _R = 0)
		: ctype<_E>(_Locinfo(_S), _R) {}
_PROTECTED:
	virtual ~ctype_byname()
		{}
	};

#ifdef  _MSC_VER
#pragma pack(pop)
#endif  /* _MSC_VER */

#endif /* _XLOCALE_ */

/*
 * Copyright (c) 1995 by P.J. Plauger.  ALL RIGHTS RESERVED. 
 * Consult your license regarding permissions and restrictions.
 */