#ifndef _xbBASE_
#define _xbBASE_
/*<<<***************************************************************************
The MIT License (MIT)

Copyright(C) 2013 - 2015 Marc Mirti Mancinelli, Christophe Lardau and Philippe Pamart (xdcube.org)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
////////////////////////////////////////////////////////////////////////////////
#Title: xbBase
#Project: xdcBase
////////////////////////////////////////////////////////////////////////////////
#Author: Marc MIRTI MANCINELLI
#History:
<28/12/2013: creation.
12/02/2014: this notice inserted.
***************************************************************************>>>*/

#define _xbOBSOLETE_ //Obsolete stuff to remove
#define xbnetEPRO_SUPPORT //protocol epro support

#define xbNOEXPORT

#ifdef XDCBASE_EXPORTS
#	define xbEXPORT __declspec(dllexport)
#else
#	ifdef XDCBASE_EMBED
#		define xbEXPORT
#	else
#		define xbEXPORT __declspec(dllimport)
#	endif
#endif

#ifdef _MSC_VER
#	define xbOS_MSWIN
#	if _MSC_VER > 1000
#		pragma once
#	endif // _MSC_VER > 1000

#	include "osdep/mswin/xbODbase.h"
#else
#	pragma error("XDCBASE: ERROR: platform not supported")
#endif

#ifdef xbLITTLEENDIAN
#	pragma message("XDCBASE: storage type defined for integers = xbLITTLEENDIAN")
#else
#	ifdef xbBIGENDIAN
#		pragma message("XDCBASE: storage type defined for integers = xbBIGENDIAN")
#	else
#		pragma error("XDCBASE: ERROR: no storage type defined for integers (xbLITTLEENDIAN or xbBIGENDIAN)")
#	endif
#endif
#define xbLITTLEENDIAN
//#define xbBIGENDIAN

#if defined(_DEBUG) || defined(_RELDBG)
#	define _xbHEAPDEBUG						//Check des blocks 
#	define _xbALLOCDEBUG					//Reperage des zones alloues dans les sources
#	define _xbALLOCDEBUG_OVERFLOW			//mode "bac a sable"...
//#	define _xbALLOCDEBUG_CHECKSTEP	5000	//Check regulier du heap
#	define _xbSTRINGDEBUG					//Check des strings et des utilisations inter thread
#endif

#define xbUSE_HEAP	//Instead of crt heap

xbEXPORT extern const char *g_pxbLogFileName;
xbEXPORT extern long		g_xbLogFile_MaxCount;
xbEXPORT extern long		g_xbLogFile_MaxKBsize;

#define g_xbLogFile_MaxCount_DFLT	10	//files
#define g_xbLogFile_MaxKBsize_DFLT	200 //KBytes

#if defined(_DEBUG) && !defined(_RELDBG)
#	define _RELDBG
#endif

#if defined(_RELDBG)
xbEXPORT extern bool _xbCrtDbgReport(bool &bIgnore,
        const char * szFile,
        int nLine,
        const char * szFormat
        );

inline bool _xbCrtDbgReport(
        const char * szFile,
        int nLine,
        const char * szFormat
        )
{
	static bool bIgnoreMsg = false;
	return _xbCrtDbgReport(bIgnoreMsg,szFile,nLine,szFormat);
}
#endif

#ifdef _DEBUG
#	define xbDebug(m)		m
#	define xbMustBe(expr) \
			((expr)?true:_xbCrtDbgReport(__FILE__, __LINE__, #expr))
#	define xbAssert(expr) \
			if (!(expr)) _xbCrtDbgReport(__FILE__, __LINE__, #expr);
#	define xbDbgOutput(s) xbRelOutput(s)
#	define xbDbgOutputLow(s) xbRelOutputLow(s)
#else
#	define xbMustBe(expr) ((expr)?true:false)
#	define xbAssert(expr)
#	define xbDebug(m)
#	define xbDbgOutput(s)
#	define xbDbgOutputLow(s)
#endif

#ifdef _RELDBG
#	define xbRelDebug(m)		m
#	define xbRdbgMustBe(expr) \
			((expr)?true:_xbCrtDbgReport(__FILE__, __LINE__, #expr))
#	define xbRdbgAssert(expr) \
			if (!(expr)) _xbCrtDbgReport(__FILE__, __LINE__, #expr);
#	define xbRdbgOutput(s) xbRelOutput(s)
#	define xbRdbgLowOutput(s) xbRelOutputLow(s)
#else
#	define xbRdbgMustBe(expr) ((expr)?true:false)
#	define xbRdbgAssert(expr)
#	define xbRelDebug(m)
#	define xbRdbgOutput(s)
#	define xbRdbgLowOutput(s)
#endif

void xbEXPORT xbRelOutputLow(LPCSTR pMsg);
void xbEXPORT xbRelOutputLowFmtV(LPCSTR pMsg, va_list ap);

inline void xbDbgOutputLowFmt(LPCSTR pMsg, ...)
{
#ifdef _DEBUG
	va_list ap;
	va_start(ap,pMsg);
	xbRelOutputLowFmtV(pMsg,ap);
	va_end(ap);
#endif
}

inline void xbRdbgLowOutputFmt(LPCSTR pMsg, ...)
{
#ifdef _RELDBG
	va_list ap;
	va_start(ap,pMsg);
	xbRelOutputLowFmtV(pMsg,ap);
	va_end(ap);
#endif
}

inline void xbRelOutputLowFmt(LPCSTR pMsg, ...)
{
#ifdef _DEBUG
	va_list ap;
	va_start(ap,pMsg);
	xbRelOutputLowFmtV(pMsg,ap);
	va_end(ap);
#endif
}

class xbBase;
class xbObjectBase;
template <class t_CBbase,class t_CBobj> class xbCB
{
public:
	xbCB() 
	{
		m_pPbase = NULL; m_pCBbase = NULL;
		m_pPobj = NULL; m_pCBobj = NULL;
	}
	xbCB(xbBase *pParent,t_CBbase pCB)
	{
		m_pPbase = pParent; m_pCBbase = pCB;
		m_pPobj = NULL; m_pCBobj = NULL;
	}
	xbCB(xbObjectBase *pParent,t_CBobj pCB)
	{
		m_pPbase = NULL; m_pCBbase = NULL;
		m_pPobj = pParent; m_pCBobj = pCB;
	}
	bool IsEmpty() const
	{
		return (m_pPbase == NULL || m_pCBbase == NULL) 
			&& (m_pPobj == NULL || m_pCBobj == NULL);
	}

	bool IsValid() const
	{
		return (m_pPbase != NULL && m_pCBbase != NULL) 
			|| (m_pPobj != NULL && m_pCBobj != NULL);
	}
	bool operator==(const xbCB<t_CBbase,t_CBobj> &cb) const
	{
		if (IsEmpty() || cb.IsEmpty())
		{
			return (IsEmpty() == cb.IsEmpty());
		}
		return m_pPbase == cb.m_pPbase && m_pCBbase == cb.m_pCBbase 
			&& m_pPobj == cb.m_pPobj && m_pCBobj == cb.m_pCBobj;
	}
	bool operator!=(const xbCB<t_CBbase,t_CBobj> &cb) const
	{
		if (IsEmpty() || cb.IsEmpty())
		{
			return (IsEmpty() != cb.IsEmpty());
		}
		return m_pPbase != cb.m_pPbase || m_pCBbase != cb.m_pCBbase 
			|| m_pPobj != cb.m_pPobj || m_pCBobj != cb.m_pCBobj;
	}
protected:
	xbBase			*m_pPbase;
	t_CBbase		m_pCBbase;
	xbObjectBase	*m_pPobj;
	t_CBobj			m_pCBobj;
};

#define xbCb(d_name,d_pObj,d_pFct) d_name ## CB(d_pObj,(d_name ## ebcb)&d_pFct)
#define xbCbCast(d_name,d_cast,d_arg,d_pObj,d_pFct) d_name ## CB((d_cast*)d_pObj,(d_name ## ebcb)(void (d_cast::*)d_arg)&d_pFct)

#define xboCb(d_name,d_pObj,d_pFct) d_name ## CB(d_pObj,(d_name ## eocb)d_pFct)
#define xboCbCast(d_name,d_cast,d_arg,d_pObj,d_pFct) d_name ## CB((d_cast*)d_pObj,(d_name ## eocb)(void (d_cast::*)d_arg)d_pFct)

//#define xbNOEXP

#define xbDclCb(d_exp,d_name,d_cbArgs,d_cbCallArgs) \
	typedef void (xbBase::*d_name ## ebcb)d_cbArgs; \
	typedef void (xbObjectBase::*d_name ## eocb)d_cbArgs; \
class d_exp d_name ## CB:public xbCB<d_name ## ebcb,d_name ## eocb> \
{ \
public: \
	d_name ## CB() {} \
	d_name ## CB(xbBase *p,d_name ## ebcb cb) \
		:xbCB<d_name ## ebcb,d_name ## eocb>(p,cb) {} \
	d_name ## CB(xbObjectBase *p,d_name ## eocb cb) \
		:xbCB<d_name ## ebcb,d_name ## eocb>(p,cb) {} \
 \
	void Call d_cbArgs \
	{ \
		if (m_pPbase != NULL && m_pCBbase != NULL) (m_pPbase->*m_pCBbase)d_cbCallArgs; \
		else if (m_pPobj != NULL && m_pCBobj != NULL) (m_pPobj->*m_pCBobj)d_cbCallArgs; \
	} \
}; 

/* compiler Internal error when this is include in macro on projects using lot of xbBase' includes
\
 \
template<class t_class,class t_cast = d_baseclass> class d_name ## CBT:public d_name ## CB \
{ \
public: \
	d_name ## CBT(t_class *p,void (t_class::*cb)d_cbArgs) \
	{ \
		m_pParent = (t_cast*)p; \
		void (t_cast::*pf)d_cbArgs = (void (t_cast::*)d_cbArgs)cb; \
		m_pCB = (d_name ## cb)pf; \
	} \
};
*/

//	on templates callbacks	(xbXDCMSGcb)(t_cbt2)cb; : bug compilo : doesn't work

#define xbDclRetCb(d_exp,d_name,d_typeRet,d_dfltRet,d_cbArgs,d_cbCallArgs)\
	typedef d_typeRet (xbBase::*d_name ## ebcb)d_cbArgs; \
	typedef d_typeRet (xbObjectBase::*d_name ## eocb)d_cbArgs; \
class d_exp d_name ## CB:public xbCB<d_name ## ebcb,d_name ## eocb> \
{ \
public: \
	d_name ## CB() {} \
	d_name ## CB(xbBase *p,d_name ## ebcb cb) \
		:xbCB<d_name ## ebcb,d_name ## eocb>(p,cb) {} \
	d_name ## CB(xbObjectBase *p,d_name ## eocb cb) \
		:xbCB<d_name ## ebcb,d_name ## eocb>(p,cb) {} \
 \
	d_typeRet Call d_cbArgs \
	{ \
		if (m_pPbase != NULL && m_pCBbase != NULL) \
			return (m_pPbase->*m_pCBbase)d_cbCallArgs; \
		if (m_pPobj != NULL && m_pCBobj != NULL) \
			return (m_pPobj->*m_pCBobj)d_cbCallArgs; \
		return d_dfltRet; \
	} \
}; 

/* compiler Internal error when this is include in macro on projects using lot of xbBase' includes

\
 \
template<class t_class,class t_cast = d_baseclass> class d_name ## CBT:public d_name ## CB \
{ \
public: \
	typedef d_typeRet (t_class::*t_cbt)d_cbArgs; \
	typedef d_typeRet (t_cast::*t_cbt2)d_cbArgs; \
	d_name ## CBT(t_class *p,t_cbt cb) \
		:d_name ## CB((t_cast*)p,NULL)  \
	{ \
		t_cbt2 pf = (t_cbt2)cb; \
		m_pCB = (d_name ## cb)pf; \
	} \
};
*/

#ifdef _DEBUG //version debug (D)
#	define xbCodeModeStr(str)	 (str "D")
#else
#	ifdef _RELDBG  //version release dbg (T) 
#		define xbCodeModeStr(str)	 (str "T")
#	else
#		ifdef _RELALT //version release alternative (X)
#			define xbCodeModeStr(str)	 (str "X")
#		else
#			define xbCodeModeStr(str)	 (str)
#		endif
#	endif
#endif

class xbEbase;
extern xbEXPORT xbHR		xbGetHR(const xbEbase *pE);

inline bool xbIsEmemory(const xbEbase *pE)
{
	return xbIsHRmemory(xbGetHR(pE));
}

xbEXPORT extern bool xbIsSysDebug();

////////////////////////////////////////////////////////////////////////////////////////
//Basics interfaces :
//Streamable object interface :
interface IxbStreamMode;
interface IxbInputStream;
interface IxbOutputStream;
interface __declspec(uuid("{288BF3D5-F1C2-4cdd-BCEB-4B9C38E3EA52}")) 
	xbEXPORT sIxbStreamable
{
	virtual void ReadFromStream(IxbStreamMode *pMode,IxbInputStream *pStream) = 0;
	virtual void WriteToStream(IxbStreamMode *pMode,IxbOutputStream *pStream) const = 0;
};


interface xbEXPORT __declspec(uuid("{8B1A16F9-0C3A-403d-922F-896790603E60}"))
	sIxbBase
{
	virtual bool GetInterface(REFIID riid, void ** ppInterf) = 0;
	virtual bool GetInterface(REFIID riid, const void ** ppInterf) const
	{
		return ((sIxbBase*)this)->GetInterface(riid,(void**)ppInterf);
	}
};

interface xbEXPORT __declspec(uuid("{B8609710-EC74-4810-9691-DF40D176943B}"))
	sIxbLock
{
	virtual void				Lock() const = 0;
	virtual void				Unlock() const = 0;
};

#define xbImplInterface(interf) \
		if (riid == __uuidof(interf)) \
		{ \
			*ppInterf = static_cast<interf*>(this); \
			return true; \
		}
#define xbImplCastInterface(interf,cast) \
		if (riid == __uuidof(interf)) \
		{ \
			*ppInterf = static_cast<interf*>((cast)this); \
			return true; \
		}
#define xbImplAggregInterface(interf,pAgreg) \
		if (riid == __uuidof(interf)) \
		{ \
			*ppInterf = static_cast<interf*>(pAgreg); \
			return pAgreg!=NULL; \
		}

#define xbDclNoCopyForObject(obj) \
	private:\
	obj(const obj &); \
	obj &operator=(const obj &); \

enum xbCtorMode
{
	xbCtor_NoOp,
	xbCtor_CallCreate
};

enum xbOpMode
{
	xbOp_Optional,
	xbOp_Required
};


//See also xbCastInReq for exception version
template<class interf> inline bool xbCastIn(sIxbBase *piBase, interf **ppInterf)
{
	if (!piBase) return false;
	return piBase->GetInterface(__uuidof(interf),(void**)ppInterf);
}

//See also xbCastInReq for exception version (xbPtr.h)
template<class interf> inline bool xbCastIn(const sIxbBase *piBase, const interf **ppInterf)
{
	if (!piBase) return false;
	return piBase->GetInterface(__uuidof(interf),(const void**)ppInterf);
}

xbEXPORT extern void xbThrowEsys(xbHR hr,LPCSTR pMsg);
xbEXPORT extern void xbThrowEsys(LPCSTR pMsg);
xbEXPORT extern void xbThrowEsysFmt(LPCSTR pMsg,...);
xbEXPORT extern void xbThrowEsysFmt(xbHR hr,LPCSTR pMsg,...);

xbEXPORT extern void xbThrowEsysLow(xbHR hr,LPCSTR pMsg);
xbEXPORT extern void xbThrowEsysLow(LPCSTR pMsg);
xbEXPORT extern void xbThrowEsysLowFmt(LPCSTR pMsg,...);
xbEXPORT extern void xbThrowEsysLowFmt(xbHR hr,LPCSTR pMsg,...);

xbEXPORT extern void xbThrowEmem(LPCSTR pMsg);
xbEXPORT extern void xbThrowEmemFmt(LPCSTR pMsg,...);

xbEXPORT extern void xbThrowElock(xbHR hr,LPCSTR pMsg,LPCSTR pCtx = NULL);
xbEXPORT extern void xbThrowElock(LPCSTR pMsg,LPCSTR pCtx = NULL);
xbEXPORT extern void xbThrowElockFmt(LPCSTR pMsg,...);

xbEXPORT extern void xbThrowEsehFmt(LPCSTR pMsg,...);

#define xbSIZE_LIMIT	0x07FFFFFF	//134217727 bytes
xbEXPORT extern void xbThrowEsizeLimitFmt(LPCSTR pMsg,...);

xbEXPORT extern void xbThrowEarg(LPCSTR pMsg,LPCSTR pCtx = NULL); //E_INVALIDARG/xbHR_INVALIDARG
xbEXPORT extern void xbThrowEargFmt(LPCSTR pMsg,...);

#define xbResetstkoflw _resetstkoflw
//int xbEXPORT __cdecl xbResetstkoflw(void);
//inline int xbResetstkoflw() {return 1;}


xbMBretType xbEXPORT xbShowException(xbEbase *e,bool bDel = true,LPCSTR pFile = NULL,int nFileLine = -1,LPCSTR pBeforeMsg = NULL,LPCSTR pAfterMsg = NULL,xbMBbtnType mboxMode = xbMBbtn_Default,bool bResumeStack = false);

void xbEXPORT xbTraceException(xbEbase *e,bool bDel = true,LPCSTR pFile = NULL,int nFileLine = -1,bool bResumeStack = false);
void xbEXPORT xbProcessException(xbEbase *e,bool bDel,bool bResumeStack);

inline void xbDbgShowException(xbEbase *e,bool bDel = true,LPCSTR pFile = NULL,int nFileLine = -1,bool bResumeStack = false)
{
#ifdef _DEBUG
	xbShowException(e,bDel,pFile,nFileLine,NULL,NULL,xbMBbtn_Default,bResumeStack);
#else
	xbProcessException(e,bDel,bResumeStack);
#endif
}

inline void xbDbgTraceException(xbEbase *e,bool bDel = true,LPCSTR pFile = NULL,int nFileLine = -1,bool bResumeStack = false)
{
#ifdef _DEBUG
	xbTraceException(e,bDel,pFile,nFileLine,bResumeStack);
#else
	xbProcessException(e,bDel,bResumeStack);
#endif
}

inline void xbRdbgShowException(xbEbase *e,bool bDel = true,LPCSTR pFile = NULL,int nFileLine = -1,bool bResumeStack = false)
{
#if defined(_DEBUG) || defined(_RELDBG)
	xbShowException(e,bDel,pFile,nFileLine,NULL,NULL,xbMBbtn_Default,bResumeStack);
#else
	xbProcessException(e,bDel,bResumeStack);
#endif
}

inline void xbRdbgTraceException(xbEbase *e,bool bDel = true,LPCSTR pFile = NULL,int nFileLine = -1,bool bResumeStack = false)
{
#if defined(_DEBUG) || defined(_RELDBG)
	xbTraceException(e,bDel,pFile,nFileLine,bResumeStack);
#else
	xbProcessException(e,bDel,bResumeStack);
#endif
}

xbEXPORT bool xbIsDebuggerPresent();
xbEXPORT void xbDebugBreak(bool bForce = false);

xbEXPORT void xbBeep(xbMBiconType beepType = xbMBicon_Default);

#define eProtectBegin() \
	{ \
	xbEbase *__xb__pE = NULL; \
	try \
	{

#define eProtectEnd() \
	} \
	catch(xbEbase *__e) \
	{ \
		__xb__pE = __e; \
	} \
	if (__xb__pE) \
		xbShowException(__xb__pE,true,__FILE__,__LINE__,NULL,NULL,xbMBbtn_Default,true); \
	}

#define eProtectEndTrace() \
	} \
	catch(xbEbase *__e) \
	{ \
		__xb__pE = __e; \
	} \
	if (__xb__pE) \
		xbTraceException(__xb__pE,true,__FILE__,__LINE__,true); \
	}

/*	catch(...) \
	{ \
		xbTraceException(NULL,true,__FILE__,__LINE__); \
	}
*/

#define eProtectEndDbgTrace() \
	} \
	catch(xbEbase *__e) \
	{ \
		__xb__pE = __e; \
	} \
	if (__xb__pE) \
		xbDbgTraceException(__xb__pE,true,__FILE__,__LINE__,true); \
	}

/*
	catch(...) \
	{ \
		xbDbgTraceException(NULL,true,__FILE__,__LINE__); \
	}
*/

#define eProtectEndRdbgTrace() \
	} \
	catch(xbEbase *__e) \
	{ \
		__xb__pE = __e; \
	} \
	if (__xb__pE) \
		xbRdbgTraceException(__xb__pE,true,__FILE__,__LINE__,true); \
	}

/*	catch(...) \
	{ \
		xbRdbgTraceException(NULL,true,__FILE__,__LINE__); \
	}
*/

#define eProtect(expr) \
	{eProtectBegin(); \
	expr; \
	eProtectEnd();}
#define eProtectTrace(expr) \
	{eProtectBegin(); \
	expr; \
	eProtectEndTrace();}
#define eProtectDbgTrace(expr) \
	{eProtectBegin(); \
	expr; \
	eProtectEndDbgTrace();}
#define eProtectRdbgTrace(expr) \
	{eProtectBegin(); \
	expr; \
	eProtectEndRdbgTrace();}

#define eToHRbegin() \
	try \
	{

#define eToHRend() \
	} \
	catch(xbEbase *__e) \
	{ \
		xbHR __hr = xbGetHR(__e); \
		xbDbgShowException(__e,true,__FILE__,__LINE__); \
		return __hr; \
	} \
	catch(...) \
	{ \
		xbDbgShowException(NULL,true,__FILE__,__LINE__); \
		return E_POINTER; \
	}

#define eToHRendRel() \
	} \
	catch(xbEbase *__e) \
	{ \
		xbHR __hr = xbGetHR(__e); \
		xbShowException(__e,true,__FILE__,__LINE__); \
		return __hr; \
	} \
	catch(...) \
	{ \
		xbShowException(NULL,true,__FILE__,__LINE__); \
		return E_POINTER; \
	}

#define eToHRendTrace() \
	} \
	catch(xbEbase *__e) \
	{ \
		xbHR __hr = xbGetHR(__e); \
		xbTraceException(__e,true,__FILE__,__LINE__); \
		return __hr; \
	} \
	catch(...) \
	{ \
		xbTraceException(NULL,true,__FILE__,__LINE__); \
		return E_POINTER; \
	}

#define eToHR(expr) \
	{eToHRbegin(); \
	expr; \
	eToHRend();}

#define eToHRrel(expr) \
	{eToHRbegin(); \
	expr; \
	eToHRendRel();}

#define eToHRtrace(expr) \
	{eToHRbegin(); \
	expr; \
	eToHRendTrace();}

#define HRtoE(expr) \
	{ \
		xbHR __hr = expr; \
		if (FAILED(__hr)) xbThrowEsys(__hr,"Instruction '" #expr "' failed !"); \
	}
#define HRtoEmsg(expr,msg) \
	{ \
		xbHR __hr = expr; \
		if (FAILED(__hr)) \
		{ \
			xbEapp *pE = new xbEapp(__hr,msg); \
			pE->AddCtx("Instruction '" #expr "' failed !"); \
			throw pE; \
		} \
	}

enum xbAllocMode
{
	xbAlloc_Init,
		xbAlloc_Default
};

#ifdef _xbALLOCDEBUG
#	define xbAlloc(cByte) Alloc(cByte,xbAlloc_Default,__FILE__,__LINE__)
#	define xbAllocEx(cByte,AllocMode) Alloc(cByte,AllocMode,__FILE__,__LINE__)
#	define xbAllocInit(cByte) Alloc(cByte,xbAlloc_Init,__FILE__,__LINE__)
#	define xbReAlloc(ptr,cByte) ReAlloc(ptr,cByte,xbAlloc_Default,__FILE__,__LINE__)
#	define xbReAllocEx(ptr,cByte,AllocMode) ReAlloc(ptr,cByte,AllocMode,__FILE__,__LINE__)
#	define xbReAllocInit(ptr,cByte) ReAlloc(ptr,cByte,xbAlloc_Init,__FILE__,__LINE__)
#	define xbAllocString(pszStr) AllocString(pszStr,__FILE__,__LINE__)
#else
#	define xbAlloc(cByte) Alloc(cByte,xbAlloc_Default)
#	define xbAllocEx(cByte,AllocMode) Alloc(cByte,AllocMode)
#	define xbAllocInit(cByte) Alloc(cByte,xbAlloc_Init)
#	define xbReAlloc(ptr,cByte) ReAlloc(ptr,cByte,xbAlloc_Default)
#	define xbReAllocEx(ptr,cByte,AllocMode) ReAlloc(ptr,cByte,AllocMode)
#	define xbReAllocInit(ptr,cByte) ReAlloc(ptr,cByte,xbAlloc_Init)
#	define xbAllocString(pszStr) AllocString(pszStr)
#endif

#ifdef xbUSE_HEAP
#ifdef _xbALLOCDEBUG
#		define xbGlobalAlloc(cByte) ::_xbAlloc(cByte,xbAlloc_Default,__FILE__,__LINE__)
#		define xbGlobalReAlloc(ptr,cByte) ::_xbReAlloc(ptr,cByte,xbAlloc_Default,__FILE__,__LINE__)
#	define xbHeapNewImpl(classname) \
		void *operator new(size_t sz,const char *pfile,long line) \
		{ \
			return _xbAlloc(sz,xbAlloc_Default,pfile,line); \
		} \
		void operator delete(void *ptr) \
		{ \
			if (!ptr) return; \
			_xbFree(ptr); \
		} \
		void operator delete[](void *pt) {operator delete(pt);} \
		void operator delete(void *ptr,const char *,long) {operator delete(ptr);} \
		void operator delete[](void *ptr,const char *,long) {operator delete(ptr);}
#	else
#		define xbGlobalAlloc(cByte) ::_xbAlloc(cByte,xbAlloc_Default)
#		define xbGlobalReAlloc(ptr,cByte) ::_xbReAlloc(ptr,cByte,xbAlloc_Default)
#	define xbHeapNewImpl(classname) \
		void *operator new(size_t sz) \
		{ \
			return _xbAlloc(sz,xbAlloc_Default); \
		} \
		void operator delete(void *ptr) \
		{ \
			if (!ptr) return; \
			_xbFree(ptr); \
		} \
		void operator delete[](void *pt) {operator delete(pt);} \
		void operator delete(void *ptr,const char *,long) {operator delete(ptr);} \
		void operator delete[](void *ptr,const char *,long) {operator delete(ptr);}
#	endif
#	define xbGlobalFree(ptr) ::_xbFree(ptr)
	xbEXPORT extern void	*_xbAlloc(size_t cByte,xbAllocMode AllocMode
#ifdef _xbALLOCDEBUG
		,const char *pszFile,int nLine
#endif
		);
	xbEXPORT extern void	*_xbReAlloc(void *ptr,size_t cByte,xbAllocMode AllocMode
#ifdef _xbALLOCDEBUG
		,const char *pszFile,int nLine
#endif
		);
	xbEXPORT extern void	_xbFree(void *ptr);
#else
#	define xbGlobalAlloc(cByte) ::malloc(cByte)
#	define xbGlobalReAlloc(ptr,cByte) ::realloc(ptr,cByte)
#	define xbGlobalFree(ptr) ::free(ptr)

#	define xbHeapNewImpl(classname) \
		void *operator new(size_t sz) \
		{ \
			return :malloc(sz); \
			if (!ptr) \
				xbThrowEmem(#classname "::operator new() : not enougth memory"); \
			return ptr; \
		} \
		void operator delete(void *ptr) \
		{ \
			if (!ptr) return; \
			::free(ptr); \
		} \
		void operator delete[](void *pt) {operator delete(pt);}
#endif



#ifdef _xbALLOCDEBUG
#	define xbDclNoNewForObject(obj) \
	private:\
	void *operator new(size_t) \
		{ \
			xbThrowEsys("Do not use operator void *" #obj \
			"::operator new(size_t sz) !"); \
			return NULL; \
		} \
	void *operator new(size_t sz,const char *pfile,long line) \
		{ \
			xbThrowEsys("Do not use operator void *" #obj \
			"::operator new(size_t sz) !");  \
			return NULL; \
		} \
	void operator delete(void *ptr) \
		{ \
			xbThrowEsys("Do not use operator void *" #obj \
			"::operator delete() !"); \
		} \
	void operator delete[](void *pt) \
		{ \
			xbThrowEsys("Do not use operator void *" #obj \
			"::operator delete() !"); \
		} \
	void operator delete(void *ptr,const char *,long) \
		{ \
			xbThrowEsys("Do not use operator void *" #obj \
			"::operator delete() !"); \
		} \
	void operator delete[](void *ptr,const char *,long) \
		{ \
			xbThrowEsys("Do not use operator void *" #obj \
			"::operator delete() !"); \
		}
#else
#	define xbDclNoNewForObject(obj) \
	private:\
	void *operator new(size_t) \
		{ \
			xbThrowEsys("Do not use operator void *" #obj \
			"::operator new(size_t sz) !"); return NULL;\
		} \
	void operator delete(void *ptr) \
		{ \
			xbThrowEsys("Do not use operator void *" #obj \
			"::operator delete() !"); \
		} \
	void operator delete[](void *pt) \
		{ \
			xbThrowEsys("Do not use operator void *" #obj \
			"::operator delete() !"); \
		}
#endif

class xbEXPORT xbBase:public sIxbBase
{
public:
	xbBase() {}
	virtual ~xbBase() {};
	virtual bool GetInterface(REFIID riid, void ** ppInterf)
	{
		xbImplInterface(sIxbBase);
		return false;
	}
	virtual bool GetInterface(REFIID riid, const void ** ppInterf) const
	{
		return ((xbBase*)this)->GetInterface(riid,(void**)ppInterf);
	}

	xbHeapNewImpl(xbBase);

	xbDclNoCopyForObject(xbBase);
};

class xbEXPORT xbLock
{
public:
	xbLock()
	{
		m_pObj = NULL;
	}
	xbLock(const sIxbLock *pObj)
	{
		m_pObj = NULL;
		if (pObj) Lock(pObj);
	}
	~xbLock()
	{
		eProtect(Unlock());
	}
	void Lock(const sIxbLock *pObj)
	{
		if (m_pObj) Unlock();
		pObj->Lock();
		m_pObj = pObj;
	}
	void Unlock()
	{
		if (!m_pObj) return;
		const sIxbLock	*pObj = m_pObj;
		m_pObj = NULL;
		pObj->Unlock();
	}
	bool IsLocked() const {return m_pObj != NULL;}
protected:
	const sIxbLock	*m_pObj;
	xbDclNoCopyForObject(xbLock);
	xbDclNoNewForObject(xbLock);
};

template<class interf> inline bool xbCastIn(xbBase *piBase, interf **ppInterf)
{
	if (!piBase) return false;
	return piBase->GetInterface(__uuidof(interf),(void**)ppInterf);
}

template<class interf> inline bool xbCastIn(const xbBase *piBase, const interf **ppInterf)
{
	if (!piBase) return false;
	return piBase->GetInterface(__uuidof(interf),(const void**)ppInterf);
}


#	ifdef _xbSTRING_UNICODE
#		pragma message("XDCBASE: default string=UNICODE")
#		define tchar		wchar
#		define xbString		xbStringW
#		define xbStrExp		xbStrExpW
#		define xbCHAR		wchar
#		define xbPSTR		wchar *
#		define xbPCSTR		const wchar *
#		define AsString		AsStringW
#		define xbStrToInt64		xbStrToInt64W
#		define xbStrToUint64	xbStrToUint64W
#		define xbStrToLong		xbStrToLongW
#		define xbStrToUlong		xbStrToUlongW
#		define xbStrToDouble	xbStrToDoubleW
#		define xbStrToGuid		xbStrToGuidW
#		define xbStrFromInt64	xbStrFromInt64W
#		define xbStrFromUint64	xbStrFromUint64W
#		define xbStrFromLong	xbStrFromLongW
#		define xbStrFromUlong	xbStrFromUlongW
#		define xbStrFromDouble	xbStrFromDoubleW
#		define xbStrFromGuid	xbStrFromGuidW
#		define xbStrToBool		xbStrToBoolW
#		define xbStrToInt		xbStrToIntW
#		define xbStrToUint		xbStrToUintW
#		define xbStrFromPtr		xbStrFromPtrW
#		define xbIsSpace		xbIsSpaceW
#		define GetAsString		GetAsStringW
#		define AsString			AsStringW
#		define ReadString		ReadStringW
#		define WriteString		WriteStringW
#		define xbStringPad		xbStringPadW
#		define xbBase64decode	xbBase64decodeW
#		define xbBase64encode	xbBase64encodeW
#	else
#		pragma message("XDCBASE: default string=ANSI")
#		define tchar		char
#		define xbString		xbStringA
#		define xbStrExp		xbStrExpA
#		define xbCHAR		char
#		define xbPSTR		char *
#		define xbPCSTR		const char *
#		define AsString		AsStringA
#		define xbStrToInt64		xbStrToInt64A
#		define xbStrToUint64	xbStrToUint64A
#		define xbStrToLong		xbStrToLongA
#		define xbStrToUlong		xbStrToUlongA
#		define xbStrToDouble	xbStrToDoubleA
#		define xbStrToGuid		xbStrToGuidA
#		define xbStrFromInt64	xbStrFromInt64A
#		define xbStrFromUint64	xbStrFromUint64A
#		define xbStrFromLong	xbStrFromLongA
#		define xbStrFromUlong	xbStrFromUlongA
#		define xbStrFromDouble	xbStrFromDoubleA
#		define xbStrFromGuid	xbStrFromGuidA
#		define xbStrToBool		xbStrToBoolA
#		define xbStrToInt		xbStrToIntA
#		define xbStrToUint		xbStrToUintA
#		define xbStrFromPtr		xbStrFromPtrA
#		define xbIsSpace		xbIsSpaceA
#		define GetAsString		GetAsStringA
#		define AsString			AsStringA
#		define ReadString		ReadStringA
#		define WriteString		WriteStringA
#		define xbStringPad		xbStringPadA
#		define xbBase64decode	xbBase64decodeA
#		define xbBase64encode	xbBase64encodeA
#	endif
class xbStringW;
class xbStrExpW;
class xbStringA;
class xbStrExpA;

extern xbEXPORT xbString	xbGetMsg(LPCSTR pFmt,const xbEbase *pE);
extern xbEXPORT xbString	xbGetCtx(LPCSTR pFmt,const xbEbase *pE,bool bAddEname=false,bool bAddHR=true);
extern xbEXPORT xbString	xbGetMsgFull(LPCSTR pFmt,const xbEbase *pE,bool bAddEname=false,bool bAddHR=true);
extern xbEXPORT xbHR		xbGetHR(const xbEbase *pE);
//extern xbEXPORT ushort		xbGetHRcode(const xbEbase *pE);
//extern xbEXPORT ulong		xbGetHRfacCode(const xbEbase *pE);
extern xbEXPORT xbString	xbGetHRmsg(const xbEbase *pE);
extern xbEXPORT xbString	xbGetEname(const xbEbase *pE);
extern xbEXPORT LPCSTR		_xbGetEname(const xbEbase *pE);
extern xbEXPORT LPCSTR		xbGetFullEname(const xbEbase *pE);

#define xbEdebug(msg) \
	"${if cppdebug}" msg "${endif}"
#define xbEdebugElse(msg,msgElse) \
	"${if cppdebug}" msg "${else}" msgElse "${endif}"

uint64 xbEXPORT xbGetTimeSpentInMicroSec();
uint64 xbEXPORT xbGetTimeInMicroSec();

//cf xbEngine.cpp
bool xbEXPORT xbIsNTos();
bool xbEXPORT xbIs95os();

DWORD xbEXPORT xbGetOSver();
DWORD xbEXPORT xbGetOSminorVer();

xbString xbEXPORT xbGetOSlabel();

inline ulong xbDiffTime(ulong tiEnd,ulong tiStart)
{
	// GetTickCount valable sur 49,71026962962962962962962962963 jours.... avant de revenir ŕ zero
	// Decalage interthread toléré (<=1s)
	ulong tiDiff = tiEnd - tiStart; 
	xbRdbgAssert(tiDiff <=ulong(0xFFFFFFFF-1000)); 
	if(tiDiff>ulong(0xFFFFFFFF-1000))
		return 0;
	return tiDiff; //( valable pour (41 jours - 1s) )
}

inline ulong xbCmpTime(ulong tiEnd,ulong tiStart,ulong maxDiff = 0x00FFFFFF)
{
	// TickCount valable sur 49,71026962962962962962962962963 jours.... avant de revenir ŕ zero
	// Decalage interthread toléré (<= ~4h)
//	xbRdbgAssert((tiEnd - tiStart)<=ulong(maxDiff)); 
	if((tiEnd-tiStart)>ulong(maxDiff))
		return 0;
	return (tiEnd-tiStart); //( valable pour (41 jours - 1s) )
}

#define xbXDCSYSPATH	"c:\\XDCUBEsys"
#endif
