#ifndef _xbXMLITF_
#define _xbXMLITF_
/*<<<***************************************************************************
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: xbXmlItf
#Project: xdcBase
////////////////////////////////////////////////////////////////////////////////
#Author: Marc MIRTI MANCINELLI
#History:
<15/09/2013: creation.
12/02/2014: this notice inserted.
***************************************************************************>>>*/

#ifndef _xbPTR_
#	include "xbPtr.h"
#endif

#ifndef _xbBOOL_
#	include "xbBool.h"
#endif

#ifndef _xbCOLOR_
#	include "xbColor.h"
#endif

#ifndef _xbEXCEPTION_
#	include "xbException.h"
#endif

//Exception xbExmlParser: used by xml parser to signal syntax errors or unexpected context of parser
xbEdclStart(xbExmlParser,xbEadv,{60667BE9-BE4B-4aba-A35D-7C40E9A87A89},xbEXPORT)
	virtual xbMBiconType GetMBoxIcon() const {return xbMBicon_Exclamation;}
	virtual const char *GetMBoxTitle() const {return "XML parser error";} 
xbEdclEnd(xbExmlParser);

//Unicode - xbBSTR
extern xbEXPORT bool xbEscape(LPCWSTR pStr,int lg,xbBSTR *pbstr,LPCWSTR pEncodeInclude,LPCWSTR pEncodeExclude,ulong cp = CP_ACP,bool bUnicodeExt = false);
extern xbEXPORT bool xbUnescape(LPCWSTR pStr,int lg,xbBSTR *pbstr,ulong cp = CP_ACP,xbOpMode opm =xbOp_Optional);

extern xbEXPORT bool xbUrlEscape(LPCWSTR pStr,int lg,xbBSTR *pbstr,LPCWSTR pEncodeInclude,LPCWSTR pEncodeExclude,ulong cp = CP_ACP,bool bUnicodeExt = false,bool bPlusEncoded = false,wchar escapeChar = L'%');
extern xbEXPORT bool xbUrlUnescape(LPCWSTR pStr,int lg,xbBSTR *pbstr,ulong cp = CP_ACP,bool bPlusEncoded = false,wchar escapeChar = L'%');

extern xbEXPORT bool xbHtmlEscape(LPCWSTR pStr,int lg,xbBSTR *pbstr,LPCWSTR pEncodeInclude,LPCWSTR pEncodeExclude,bool bLFtoo);
extern xbEXPORT bool xbHtmlUnescape(LPCWSTR pStr,int lg,xbBSTR *pbstr,bool bLFtoo);

//Unicode - xbStringW
extern xbEXPORT bool xbEscape(LPCWSTR pStr,int lg,xbStringW *pbstr,LPCWSTR pEncodeInclude,LPCWSTR pEncodeExclude,ulong cp = CP_ACP,bool bUnicodeExt = false);
extern xbEXPORT bool xbUnescape(LPCWSTR pStr,int lg,xbStringW *pbstr,ulong cp = CP_ACP,xbOpMode opm =xbOp_Optional);

extern xbEXPORT bool xbUrlEscape(LPCWSTR pStr,int lg,xbStringW *pbstr,LPCWSTR pEncodeInclude,LPCWSTR pEncodeExclude,ulong cp = CP_ACP,bool bUnicodeExt = false,bool bPlusEncoded = false,wchar escapeChar = L'%');
extern xbEXPORT bool xbUrlUnescape(LPCWSTR pStr,int lg,xbStringW *pbstr,ulong cp = CP_ACP,bool bPlusEncoded = false,wchar escapeChar = L'%');

extern xbEXPORT bool xbHtmlEscape(LPCWSTR pStr,int lg,xbStringW *pbstr,LPCWSTR pEncodeInclude,LPCWSTR pEncodeExclude,bool bLFtoo);
extern xbEXPORT bool xbHtmlUnescape(LPCWSTR pStr,int lg,xbStringW *pbstr,bool bLFtoo);

//Mbcs
extern xbEXPORT bool xbEscape(const char *pStr,int lg,xbStringA *pBuffer,LPCSTR pEncodeInclude,LPCSTR pEncodeExclude,ulong cp = CP_ACP,bool bUnicodeExt = false);
extern xbEXPORT bool xbUnescape(const char *pStr,int lg,xbStringA *pBuffer,ulong cp = CP_ACP,xbOpMode opm =xbOp_Optional);

extern xbEXPORT bool xbUrlEscape(const char *pStr,int lg,xbStringA *pBuffer,LPCSTR pEncodeInclude,LPCSTR pEncodeExclude,ulong cp = CP_ACP,bool bUnicodeExt = false,bool bPlusEncoded = false,char escapeChar = '%');
extern xbEXPORT bool xbUrlUnescape(const char *pStr,int lg,xbStringA *pBuffer,ulong cp = CP_ACP,bool bPlusEncoded = false,char escapeChar = '%');

extern xbEXPORT bool xbHtmlEscape(const char *pStr,int lg,xbStringA *pBuffer,LPCSTR pEncodeInclude,LPCSTR pEncodeExclude,bool bLFtoo);
extern xbEXPORT bool xbHtmlUnescape(const char *pStr,int lg,xbStringA *pBuffer,bool bLFtoo,ulong cp = CP_ACP);

//extern xbEXPORT xbString xbEscape(const xbString &str,bool *pbEscaped = NULL);
//extern xbEXPORT xbString xbUnescape(const xbString &str);

inline xbStringA xbEscape(const xbStringA &str,LPCSTR pEncodeInclude = NULL,LPCSTR pEncodeExclude = NULL,ulong cp = CP_ACP,bool bUnicodeExt = false)
{
	xbStringA ret;
	if (!::xbEscape(str,str.Length,&ret,pEncodeInclude,pEncodeExclude,cp,bUnicodeExt))
		return str;
	return ret;
}

inline xbStringW xbEscape(const xbStringW &str,LPCWSTR pEncodeInclude = NULL,LPCWSTR pEncodeExclude = NULL,ulong cp = CP_ACP,bool bUnicodeExt = false)
{
	xbStringW ret;
	if (!::xbEscape(str,str.Length,&ret,pEncodeInclude,pEncodeExclude,cp,bUnicodeExt))
		return str;
	return ret;
}

inline xbStringA xbEscapeExt(const xbStringA &str,LPCSTR pEncodeInclude = NULL,LPCSTR pEncodeExclude = NULL,ulong cp = CP_ACP)
{
	xbStringA ret;
	if (!::xbEscape(str,str.Length,&ret,pEncodeInclude,pEncodeExclude,cp,true))
		return str;
	return ret;
}

inline xbStringW xbEscapeExt(const xbStringW &str,LPCWSTR pEncodeInclude = NULL,LPCWSTR pEncodeExclude = NULL,ulong cp = CP_ACP)
{
	xbStringW ret;
	if (!::xbEscape(str,str.Length,&ret,pEncodeInclude,pEncodeExclude,cp,true))
		return str;
	return ret;
}

inline xbStringA xbUnescape(const xbStringA &str,ulong cp = CP_ACP,xbOpMode opm =xbOp_Optional)
{
	xbStringA ret;
	if (!::xbUnescape(str,str.Length,&ret,cp,opm))
		return str;
	return ret;
}

inline xbStringW xbUnescape(const xbStringW &str,ulong cp = CP_ACP,xbOpMode opm =xbOp_Optional)
{
	xbStringW ret;
	if (!::xbUnescape(str,str.Length,&ret,cp,opm))
		return str;
	return ret;
}

inline xbStringA xbUrlEscape(const xbStringA &str,LPCSTR pEncodeInclude = NULL,LPCSTR pEncodeExclude = NULL,ulong cp = CP_ACP,bool bUnicodeExt = false)
{
	xbStringA ret;
	if (!::xbUrlEscape(str,str.Length,&ret,pEncodeInclude,pEncodeExclude,cp,bUnicodeExt))
		return str;
	return ret;
}

inline xbStringW xbUrlEscape(const xbStringW &str,LPCWSTR pEncodeInclude = NULL,LPCWSTR pEncodeExclude = NULL,ulong cp = CP_ACP,bool bUnicodeExt = false)
{
	xbStringW ret;
	if (!::xbUrlEscape(str,str.Length,&ret,pEncodeInclude,pEncodeExclude,cp,bUnicodeExt))
		return str;
	return ret;
}

inline xbStringA xbUrlUnescape(const xbStringA &str,ulong cp = CP_ACP)
{
	xbStringA ret;
	if (!::xbUrlUnescape(str,str.Length,&ret,cp))
		return str;
	return ret;
}

inline xbStringW xbUrlUnescape(const xbStringW &str,ulong cp = CP_ACP)
{
	xbStringW ret;
	if (!::xbUrlUnescape(str,str.Length,&ret,cp))
		return str;
	return ret;
}

inline xbStringA xbHtmlEscape(const xbStringA &str,LPCSTR pEncodeInclude = NULL,LPCSTR pEncodeExclude = NULL)
{
	xbStringA ret;
	if (!::xbHtmlEscape(str,str.Length,&ret,pEncodeInclude,pEncodeExclude,false))
		return str;
	return ret;
}

inline xbStringW xbHtmlEscape(const xbStringW &str,LPCWSTR pEncodeInclude = NULL,LPCWSTR pEncodeExclude = NULL)
{
	xbStringW ret;
	if (!::xbHtmlEscape(str,str.Length,&ret,pEncodeInclude,pEncodeExclude,false))
		return str;
	return ret;
}

inline xbStringA xbHtmlUnescape(const xbStringA &str,ulong cp = CP_ACP)
{
	xbStringA ret;
	if (!::xbHtmlUnescape(str,str.Length,&ret,false,cp))
		return str;
	return ret;
}

inline xbStringW xbHtmlUnescape(const xbStringW &str)
{
	xbStringW ret;
	if (!::xbHtmlUnescape(str,str.Length,&ret,false))
		return str;
	return ret;
}

inline xbStringA xbHtmlEscapeLf(const xbStringA &str,LPCSTR pEncodeInclude = NULL,LPCSTR pEncodeExclude = NULL)
{
	xbStringA ret;
	if (!::xbHtmlEscape(str,str.Length,&ret,pEncodeInclude,pEncodeExclude,true))
		return str;
	return ret;
}

inline xbStringW xbHtmlEscapeLf(const xbStringW &str,LPCWSTR pEncodeInclude = NULL,LPCWSTR pEncodeExclude = NULL)
{
	xbStringW ret;
	if (!::xbHtmlEscape(str,str.Length,&ret,pEncodeInclude,pEncodeExclude,true))
		return str;
	return ret;
}

inline xbStringA xbHtmlUnescapeLf(const xbStringA &str,ulong cp = CP_ACP)
{
	xbStringA ret;
	if (!::xbHtmlUnescape(str,str.Length,&ret,true,cp))
		return str;
	return ret;
}

inline xbStringW xbHtmlUnescapeLf(const xbStringW &str)
{
	xbStringW ret;
	if (!::xbHtmlUnescape(str,str.Length,&ret,true))
		return str;
	return ret;
}

struct xbEXPORT xbXmlPos
{
	int		m_line;
	int		m_col;
	ulong	m_offsInFile;
	ulong	m_lgInFile;
	xbXmlPos()
	{
		init();
	}
	xbXmlPos(int col,int line,ulong offsInFile, ulong lgInFile)
		:m_line(line),m_col(col),m_offsInFile(offsInFile),m_lgInFile(lgInFile)
	{
	}
	void init()
	{
		m_line = -1;
		m_col = -1;
		m_offsInFile = 0;
		m_lgInFile = -1;
	}
	bool IsValid() const {return m_col >= 0;}
	bool IsEmpty() const {return m_col < 0;}
};

struct xbEXPORT xbXmlFlag
{
	xbXmlPos	m_posName,m_posValue;
	xbString	m_name,m_value;
	char		m_nameChStr,m_valueChStr;
	bool		m_bValue;

	xbXmlFlag()
	{
		m_nameChStr = m_valueChStr = 0;
		m_bValue = false;
		m_bUnescValue = false;
		m_bUnescName = false;
	}
	void Clear()
	{
		m_name.Empty();
		m_value.Empty();
		m_nameChStr = m_valueChStr = 0;
		m_bValue = false;
		m_posName.init();
		m_posValue.init();
		m_unescValue.Empty();
		m_bUnescValue = false;
		m_unescName.Empty();
		m_bUnescName = false;
	}
	xbString GetUnescValue(ulong cp = CP_ACP,xbOpMode opm =xbOp_Optional) const
	{
		if (m_bUnescValue) return m_unescValue;
		m_unescValue = ::xbUnescape(m_value,cp,opm);
		m_bUnescValue = true;
		return m_unescValue;
	}
	xbString GetUnescName(ulong cp = CP_ACP,xbOpMode opm =xbOp_Optional) const
	{
		if (m_bUnescName) return m_unescName;
		m_unescName = ::xbUnescape(m_name,cp,opm);
		m_bUnescName = true;
		return m_unescName;
	}
	xbStringW GetUnescValueW(ulong cp = CP_ACP,xbOpMode opm =xbOp_Optional) const
	{
		return ::xbUnescape(xbStringW(cp,m_value),cp,opm);
	}
	xbStringW GetUnescNameW(ulong cp = CP_ACP,xbOpMode opm =xbOp_Optional) const
	{
		return ::xbUnescape(xbStringW(cp,m_name),cp,opm);
	}

	void	NameChange()
	{
		m_bUnescName = false;
	}
	void	ValueChange()
	{
		m_bUnescValue = false;
	}
	bool HasValue() const {return m_bValue;}
protected:
	mutable bool		m_bUnescValue;
	mutable xbString	m_unescValue;

	mutable bool		m_bUnescName;
	mutable xbString	m_unescName;
};

interface xbEXPORT IxbXmlTarget;

interface __declspec(uuid("{24BE6F7E-8A9C-4b8c-8ECC-D06045DA573C}"))
	xbEXPORT sIxbXmlSource:public sIxbBase
{
//	virtual void			SetTarget(IxbXmlTarget *pTarget) = 0;
	virtual IxbXmlTarget	*GetTarget() const = 0;

	virtual void			PushTarget(IxbXmlTarget *pTarget) = 0;
	virtual IxbXmlTarget	*PopTarget(IxbXmlTarget *pTarget,xbOpMode opm =xbOp_Required) = 0;

	virtual void			SetTextIgnore(bool bVal) = 0;
	virtual bool			GetTextIgnore() const = 0;

	virtual void			SetTextTrim(bool bVal) = 0;
	virtual bool			GetTextTrim() const = 0;

	virtual void			SetSectIgnore(bool bVal) = 0;
	virtual bool			GetSectIgnore() const = 0;

	virtual bool			IsSectComment() const = 0; //True if in presence of <!-- ... -->

	virtual void			SetTabSize(int val) = 0;
	virtual int				GetTabSize() const = 0;
	virtual int				TabAlign(int col) const = 0;

	virtual int				GetFlagCount() const = 0;
	virtual bool			GetFlag(int no,xbXmlFlag *pFlg) const = 0;
	virtual bool			EnumFlag(int &idx,xbXmlFlag *pFlg) const = 0;
	virtual bool			EnumFlag(int &idx,xbXmlFlag **ppFlg) const = 0;
	virtual bool			GetFlag(const xbString &name,xbXmlFlag *pFlg) const = 0;
	virtual bool			GetFlagValue(const xbString &name,xbString *pValue,LPCSTR pDfltVal = NULL) const = 0;
	virtual const xbXmlFlag	*GetFlagPtr(int no) const = 0;
	virtual const xbXmlFlag	*GetFlagPtr(const xbString &name) const = 0;

	virtual xbString		GetFlagStr(const xbString &name,LPCSTR pDfltVal = NULL) const = 0;
	virtual long			GetFlagLong(const xbString &name,long dflt = 0) const = 0;
	virtual bool			GetFlagLong(const xbString &name,long *pLong) const = 0;
	virtual bool			GetFlagBool(const xbString &name,bool dflt = false) const = 0;
	virtual bool			GetFlagBool(const xbString &name,bool *pBool) const = 0;
	virtual bool			GetFlagBool(const xbString &name,xbBool *pBool) const = 0;
	virtual bool			GetFlagColor(const xbString &name,xbColor *pColor) const = 0;

	virtual void			SetCaseSensitive(bool bVal) = 0;
	virtual int				Compare(const xbString &name1,const xbString &name2) const = 0;
	virtual int				Compare(const xbString &name1,const xbString &name2,int lg) const = 0;

	virtual xbString		SectionAsText() const = 0;

	virtual void			*GetData() const = 0;

	virtual void warning(const xbString &msg,int col = -1,int line = -1,LPCSTR pCtx = NULL) = 0;
	virtual void error(const xbString &msg,int col = -1,int line = -1,LPCSTR pCtx = NULL) = 0;
	virtual void warning(const xbString &msg,const xbXmlPos &pos,LPCSTR pCtx = NULL) = 0;
	virtual void error(const xbString &msg,const xbXmlPos &pos,LPCSTR pCtx = NULL) = 0;

	virtual xbString GetFileName() const = 0;
	virtual xbXmlPos GetCurrentPosition() const = 0;
};

interface __declspec(uuid("{24BE6F7E-8A9C-4b8c-8ECC-D06045DA573C}"))
xbEXPORT IxbXmlTarget:public IxbObject
{
	virtual void	AddSection(sIxbXmlSource *pSrce,const xbString &name,bool bSectTerminated,const xbXmlPos &sectPos) = 0;
	virtual void	AddSectionEnd(sIxbXmlSource *pSrce,const xbString &name,const xbXmlPos &sectPos) = 0;
	virtual void	AddText(sIxbXmlSource *pSrce,const xbString &text,const xbXmlPos &textPos) = 0;

	virtual int		CutSectionName(sIxbXmlSource *pSrce,const xbString &name,bool bEndSection,bool bSectTerminated) = 0;

	virtual bool	Warning(const xbString &file,int col,int line,const xbString &msg,LPCSTR pCtx) = 0;
	virtual bool	Error(const xbString &file,int col,int line,const xbString &msg,LPCSTR pCtx) = 0;

	virtual void	EndParse(sIxbXmlSource *pSrce,bool bOk) = 0;
	virtual xbString GetXmlLabel(sIxbXmlSource *pSrce) = 0;
};

#endif
