#pragma once

//	スタティックライブラリを指定
#define	XML_STATIC

#include "expat\expat.h"
#include "TypedBuffer.h"

//	バッファ設定
#define	EXPAT_SJIS_STRING_BUF_LEN		256
#define	EXPAT_SJIS_STRING_BUF_COUNT		10
#define	EXPAT_UTF16_STRING_BUF_COUNT	1024

/*!
	例外
*/
class CXMLTextParserException
{
public:
	CXMLTextParserException() {};
	CXMLTextParserException(CString error, int point)
	{
		m_error = error;
		m_point = point;
	};

	CString	m_error;
	int		m_point;
};


/*!
	UTF8->SJISコンバータ

	変換が必要な場合のみ変換され、バッファが自動的に確保される
	関数終了後にCleanupを呼ぶ
*/
class CExpatXmlParserUTF8Convert
{
public:
	CExpatXmlParserUTF8Convert();
	virtual ~CExpatXmlParserUTF8Convert();

	//!	取得
	LPCSTR ConvertToSJIS(LPCSTR utf8)
	{
		int	len = -1;
		return(ConvertToSJIS(utf8, len));
	}

	//!	取得
	LPCSTR ConvertToSJIS(LPCSTR utf8, int &len);

	//!	掃除
	void Cleanup();

	//!	C文字列へ
	LPCSTR ToCString(const CHAR *buf, int len);

protected:
	/////////////////////////////////////////////////////////////////////////////////////
	//	補助
	/////////////////////////////////////////////////////////////////////////////////////
	//!	ASCII以外を含むかチェック
	int CheckUTF8(LPCSTR str, int len=-1);

	//!	確保
	LPSTR AllocString(int len);

	//!	拡張バッファ確保
	LPSTR AllocExtString(int len);

	//!	UTF16バッファ取得
	wchar_t *AllocUTF16Buf(int count);

	/////////////////////////////////////////////////////////////////////////////////////
	//	メンバ変数
	/////////////////////////////////////////////////////////////////////////////////////
	//!	SJISバッファ
	CHAR	m_sjisBuf[EXPAT_SJIS_STRING_BUF_COUNT][EXPAT_SJIS_STRING_BUF_LEN];

	//!	バッファ使用数
	int		m_sjisBufUsing;

	//!	規格外バッファ
	CTypedPtrArray<CPtrArray, char *>	m_extSjisBuf;

	//!	UTF16用バッファ
	wchar_t	m_utf16Buf[EXPAT_UTF16_STRING_BUF_COUNT];

	//!	UTF16拡張バッファ
	CTypedBuffer<wchar_t>	m_extUtf16Buf;

};

/*!
	XMLパーサー
*/
class CExpatXmlParser
{
public:
	CExpatXmlParser(void);
	virtual ~CExpatXmlParser(void);

	/////////////////////////////////////////////////////////////////////////////////////
	//	開始
	/////////////////////////////////////////////////////////////////////////////////////
	//!	スキャン
	void StartScan(CStringA xmlUtf8);

	//!	ファイルから取得
	CString LoadXmlFile(CString path);

	/////////////////////////////////////////////////////////////////////////////////////
	//	実装
	/////////////////////////////////////////////////////////////////////////////////////
	//!	開始タグ
	virtual void OnStartTag(LPCSTR tag, LPCSTR *atts) {/* TRACE(_T("StartTag : %s\n"), tag); */};

	//!	終了タグ
	virtual void OnEndTag(LPCSTR tag) {/* TRACE(_T("EndTag : %s\n"), tag); */};

	//!	データ
	virtual void OnData(const CHAR *data, int len) {/* TRACE(_T("Data : %s\n"), data); */};

protected:
	/////////////////////////////////////////////////////////////////////////////////////
	//	補助
	/////////////////////////////////////////////////////////////////////////////////////
	//!	初期化
	int Init();

	//!	終了
	void Close();

	//!	ASCII以外を含むかチェック
	int CheckUTF8(const XML_Char *str, int len=-1);

	//!	Attr数チェック
	int GetAttrCount(LPCSTR *atts);

private:
	/////////////////////////////////////////////////////////////////////////////////////
	//	コールバック
	/////////////////////////////////////////////////////////////////////////////////////
	//!	開始タグ
	static void StartElementHandler(void *userData, const XML_Char *name, const XML_Char **atts);

	//!	終了タグ
	static void EndElementHandler(void *userData, const XML_Char *name);
	
	//!	データ
	static void CharacterDataHandler(void *userData, const XML_Char *s, int len);

protected:
	/////////////////////////////////////////////////////////////////////////////////////
	//	メンバ変数
	/////////////////////////////////////////////////////////////////////////////////////
	//!	パーサー
	XML_Parser	m_parser;

	//!	初期化フラグ
	int			m_init;

	//!	SJISコンバータ
	CExpatXmlParserUTF8Convert	m_sjis;
};
