//========================================================================================
// A light and efficient XML library, with a similar interface to libxml2
//
// AUTHOR:  Gabor Nagy
// DATE:    2018-Apr-01 23:23:01
//
// Copyright (C) 2014-2026 by Gabor Nagy. All rights reserved.
//========================================================================================
#ifndef _EXML_h
#define _EXML_h

#include <ETypes.h>


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif



typedef struct TsXMLTokenID
{
	int    ID;
	char*  Name;
} XMLTokenID;


typedef uint8_t  XmlChar;


#define XmlTAG_NODE_NAME_ALLOCATED  -1
#define XmlTAG_TEXT                 -2

typedef enum
{
	XmlELEMENT_NODE=   1,
	XmlATTRIBUTE_NODE= 2,
	XmlTEXT_NODE=      3,
	XmlCDATA_SECTION_NODE=	4,
	XmlENTITY_REF_NODE=  5,
	XmlENTITY_NODE=      6,
	XmlPI_NODE=          7,
	XmlCOMMENT_NODE=		8,
	XmlDOCUMENT_NODE=		9,
	XmlDOCUMENT_TYPE_NODE=	10,
	XmlDOCUMENT_FRAG_NODE=	11,
	XmlNOTATION_NODE=		12,
	XmlHTML_DOCUMENT_NODE=	13,
	XmlDTD_NODE=		14,
	XmlELEMENT_DECL=		15,
	XmlATTRIBUTE_DECL=		16,
	XmlENTITY_DECL=		17,
	XmlNAMESPACE_DECL=		18,
	XmlXINCLUDE_START=		19,
	XmlXINCLUDE_END=		20
//#ifdef LIBXmlDOCB_ENABLED
 ,XmlDOCB_DOCUMENT_NODE=	21
//#endif
} XmlElementType;



#define EXmlElementCore\
	XmlElementType  Type;\
	int             ID; /* Index of the Name field into the tag id list, XmlTAG_NODE_NAME_ALLOCATED, if Name was dynamically allocated, or XmlTAG_TEXT if this is a text node */\
	XmlChar*        Name;\
	XmlNode*        Parent;\
	XmlNode*        Child


typedef struct XmlElement_S   XmlElement;
typedef struct XmlNode_S      XmlNode;


struct XmlElement_S
{
	EXmlElementCore;
};

typedef struct XmlAttr_S   XmlAttr;

struct XmlNode_S
{
	EXmlElementCore;
	XmlNode*     NextSibling;
	XmlChar*     Content;
	XmlAttr*     Attributes;
	XmlNode*     Next;       // By depth-first...
};


struct XmlAttr_S
{
	EXmlElementCore;    // The Child field is value of the attribute here
	XmlAttr*     NextSibling;
};

typedef struct
{
	int        Result;    // 0 if a load was successful, or an error code, such as XmlMISSING_TAG_NAME
	int        Line;      // Line number, if an error was found, or 0
} XmlTReader;

typedef struct
{
	XmlChar*    Name;
	XmlNode*    Children;
	XmlTReader  Reader;
} XmlDoc;


typedef struct
{
} XmlSchemaValidCtxt;


// Return codes
enum
{
	XmlFILE_ERROR = 1,
	XmlPARSE_ERROR,
	XmlTAG_MISMATCH,
	XmlMISSING_TAG_NAME,
	XmlINVALID_CHARACTER,
	XmlATTRIBUTE_SYNTAX_ERROR
};


#define XMLCONTENT_ALLOCSTEP  256


typedef struct XmlNs_S  XmlNs;
typedef XmlNs*          XmlNsPtr;

struct XmlNs_S
{
};


typedef struct XmlTextReader_S  XmlTextReader;


// Compatibility macros for libXml2
//
#define Xml_Name(m)         (m)->Name
#define Xml_Type(m)         (m)->Type
#define Xml_Content(m)      (m)->Content
#define Xml_Parent(m)       (m)->Parent
#define Xml_Children(m)     (m)->Child
#define Xml_NextSibling(m)  (m)->NextSibling
#define Xml_Attributes(m)   (m)->Attributes
#define XmlDoc_GetRootNode(mDoc)        (mDoc)->Children
#define XmlDoc_SetRootNode(mDoc, mNode) (mDoc)->Children = mNode
#define XmlParser_Init()
#define XmlParser_Cleanup(m) do { } while(0)

extern const char*  XmlUTF8;  // Flyweight string for UTF-8 encoding


//----------------------------------------------------------------
// Function prototypes
//----------------------------------------------------------------
extern void            Xml_StringToEsc(const char* PIn, char* POut, const int PMaxLen);
extern void            Xml_EscToString(char* PStr);

extern XmlDoc*         XmlDoc_New(const XmlChar* PName);
extern void            XmlNode_Free(XmlNode* PNode);

extern XmlDoc*         XmlDoc_LoadFromFile(const char* PFileName, FILE* PFile, int* PResult);
extern void            XmlDoc_Free(XmlDoc* PDoc);
extern XmlNode*        XmlTextNode_New(const XmlChar* PName);
extern XmlNode*        XmlNode_New(XmlNs* PNameSpace, const XmlChar* PName);
extern void            XmlNode_AddChild(XmlNode* PParent, XmlNode* PChild);
extern int             XmlDoc_SaveToFileEnc(const char* PFileName, XmlDoc* PDoc, const char* PEncoding, const int PFormat);

extern void            XmlNode_HrcPrint(XmlNode* PRootNode);

extern XmlTextReader*  XmlTextReader_NewFromFile(const char* PURL, FILE* PFile);
extern void            XmlTextReader_Free(XmlTextReader* PReader);

extern int             XmlTextReader_Read(XmlTextReader* PReader);
extern const XmlChar*  XmlTextReader_ConstName(XmlTextReader* PReader);
extern const XmlChar*  XmlTextReader_ConstValue(XmlTextReader* PReader);
extern XmlChar*        XmlTextReader_Name(XmlTextReader* PReader);
extern int             XmlTextReader_NodeType(XmlTextReader* PReader);
extern int             XmlTextReader_MoveToNextAttribute(XmlTextReader* PReader);
extern XmlNode*        XmlNode_NewChild(XmlNode* PParent, XmlNs* PNs, const XmlChar* PName, const XmlChar* PContent);
extern XmlAttr*        XmlAttr_New(XmlNode* PNode, const XmlChar* PName, const XmlChar* PValue);

#define XmlCAST  (XmlChar*)


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration
#endif

#endif	// _EXML_h
