CMUtil/inc/hgl/util/xml/XMLParse.h

211 lines
7.2 KiB
C
Raw Normal View History

2019-11-29 11:58:31 +08:00
#ifndef HGL_XML_PARSE_INCLUDE
#define HGL_XML_PARSE_INCLUDE
#include<hgl/type/BaseString.h>
2020-08-20 21:26:49 +08:00
#include<hgl/type/Map.h>
#include<hgl/type/StrChar.h>
#include<hgl/CodePage.h>
2019-11-29 11:58:31 +08:00
extern "C"
{
/**
* XML解晰器使用Expat实现,MIT协议取得免费授权, doc/license/MIT.txt
* Expat官方网站http://expat.sourceforge.net/
*/
struct XML_ParserStruct;
2019-11-29 18:20:19 +08:00
using XML_Parser=struct XML_ParserStruct *;
2019-11-29 11:58:31 +08:00
}
namespace hgl
{
namespace io
{
class InputStream;
}//namespace io
/**
2020-08-20 21:26:49 +08:00
* XML节点解析器
*/
class XMLElementParse
{
public:
virtual bool StartElement(const char *element_name)=0;
virtual void Attr(const char *flag,const char *info){};
virtual void CharData(const char *str,int str_length){};
virtual void EndElement(const char *element_name){};
};//class XMLElementParse
class XMLElementParseKV:public XMLElementParse
2019-11-29 11:58:31 +08:00
{
protected:
2020-08-20 21:26:49 +08:00
using AttrsMap=Map<AnsiString,AnsiString>;
using AttrItem=Pair<AnsiString,AnsiString>;
2019-11-29 11:58:31 +08:00
2020-08-20 21:26:49 +08:00
AttrsMap attrs_map;
2019-11-29 18:20:19 +08:00
2020-08-20 21:26:49 +08:00
protected:
const AttrItem *GetAttrItem(const AnsiString &name);
template<typename T> const bool GetInteger (const AnsiString &name,T &value){const AttrItem *ai=GetAttrItem(name);return(ai?stoi(ai->right.c_str(),value):false);}
template<typename T> const bool GetUInteger (const AnsiString &name,T &value){const AttrItem *ai=GetAttrItem(name);return(ai?stou(ai->right.c_str(),value):false);}
template<typename T> const bool GetFloat (const AnsiString &name,T &value){const AttrItem *ai=GetAttrItem(name);return(ai?stof(ai->right.c_str(),value):false);}
2019-11-29 11:58:31 +08:00
public:
2020-08-20 21:26:49 +08:00
virtual void Attr(const char *flag,const char *info) override;
2019-11-29 11:58:31 +08:00
public:
2020-08-20 21:26:49 +08:00
const bool IsExist (const AnsiString &name)const{return attrs_map.KeyExist(name);}
2019-11-29 11:58:31 +08:00
2020-08-20 21:26:49 +08:00
const char * ToCString (const AnsiString &name){const AttrItem *ai=GetAttrItem(name);return(ai?ai->right.c_str():nullptr);}
const char * operator[] (const AnsiString &name){return ToCString(name);}
2019-11-29 11:58:31 +08:00
2020-08-20 21:26:49 +08:00
public:
const bool Get(const AnsiString &name,AnsiString &str)
{
const AttrItem *ai=GetAttrItem(name);
if(!ai)return(false);
str=ai->right;
return(true);
}
const bool Get(const AnsiString &name,UTF16String &str)
{
const AttrItem *ai=GetAttrItem(name);
if(!ai)return(false);
str=to_u16(ai->right);
return(true);
}
const bool Get(const AnsiString &name,char &ch)
{
const AttrItem *ai=GetAttrItem(name);
if(!ai)return(false);
ch=ai->right.GetBeginChar();
return(true);
}
const bool Get(const AnsiString &name,bool &value)
{
const AttrItem *ai=GetAttrItem(name);
return(ai?stob<char>(ai->right.c_str(),value):false);
}
const bool Get(const AnsiString &name, int8 &value){return GetInteger < int8 >(name,value);}
const bool Get(const AnsiString &name,uint8 &value){return GetUInteger<uint8 >(name,value);}
const bool Get(const AnsiString &name, int16 &value){return GetInteger < int16>(name,value);}
const bool Get(const AnsiString &name,uint16 &value){return GetUInteger<uint16>(name,value);}
const bool Get(const AnsiString &name, int32 &value){return GetInteger < int32>(name,value);}
const bool Get(const AnsiString &name,uint32 &value){return GetUInteger<uint32>(name,value);}
const bool Get(const AnsiString &name, int64 &value){return GetInteger < int64>(name,value);}
const bool Get(const AnsiString &name,uint64 &value){return GetUInteger<uint64>(name,value);}
const bool GetHexStr(const AnsiString &name,uint8 *data)
{
const AttrItem *ai=GetAttrItem(name);
if(!ai)return(false);
ParseHexStr(data,ai->right.c_str(),ai->right.Length());
return(true);
}
};//class XMLElementParseKV:public XMLElementParse
2019-11-29 11:58:31 +08:00
2020-08-20 21:56:02 +08:00
constexpr int XML_PARSE_BUFFER_SIZE=HGL_SIZE_1KB*128; ///<XML解析缓冲区大小
2019-11-29 11:58:31 +08:00
/**
2020-08-20 21:26:49 +08:00
* XML解析器<br>
2019-11-29 11:58:31 +08:00
*/
2020-08-20 21:26:49 +08:00
class XMLParse
2019-11-29 11:58:31 +08:00
{
protected:
2020-08-20 21:26:49 +08:00
XML_Parser xml;
int buffer_size;
char *buffer;
protected:
XMLElementParse *element_parse;
2019-11-29 11:58:31 +08:00
virtual void StartParse();
public:
2020-08-20 21:56:02 +08:00
XMLParse(XMLElementParse *,const int size=XML_PARSE_BUFFER_SIZE);
2020-08-20 21:26:49 +08:00
virtual ~XMLParse();
2019-11-29 11:58:31 +08:00
2020-08-20 21:26:49 +08:00
virtual void Start(const char *charset="utf-8");
virtual bool Parse(const char *buf,int len,bool isFin);
virtual bool Parse(io::InputStream *,bool isFin=true);
};//class XMLParse
2019-11-29 11:58:31 +08:00
2020-08-20 21:26:49 +08:00
bool XMLParseFile(XMLParse *xml,const OSString &filename);
2019-11-29 11:58:31 +08:00
#define XML_START_PARSE(name) while(*name) \
{ \
const char *flag=*name;++name; \
const char *info=*name;++name;
#define XML_END_PARSE() LOG_ERROR(UTF8String(__FILE__)+U8_TEXT(":")+UTF8String(__LINE__)+U8_TEXT(" can't parse atts \"")+UTF8String(flag)+U8_TEXT("\" , info \"")+UTF8String(info)+U8_TEXT("\".")); \
}
#define XML_END_PARSE_SKIP() ;}
#define xml_parse_skip(name) if(hgl::strcmp(flag,#name)==0)continue;else
#define xml_parse_string_u16(name) if(hgl::strcmp(flag,#name)==0)name=to_u16(info);else
#define xml_parse_string_u8(name) if(hgl::strcmp(flag,#name)==0)name=info;else
#define xml_parse_int(name) if(hgl::strcmp(flag,#name)==0)hgl::stoi(info,name);else
#define xml_parse_uint(name) if(hgl::strcmp(flag,#name)==0)hgl::stou(info,name);else
#define xml_parse_float(name) if(hgl::strcmp(flag,#name)==0)hgl::stof(info,name);else
#define xml_parse_bool(name) if(hgl::strcmp(flag,#name)==0)hgl::stob(info,name);else
#define xml_parse_hexstr(name) if(hgl::strcmp(flag,#name)==0)hgl::ParseHexStr(name,info);else
#define xml_parse_to_string_u8(name,value) if(hgl::strcmp(flag,name)==0)value=info;else
#define xml_parse_to_int(name,value) if(hgl::strcmp(flag,name)==0)hgl::stoi(info,value);else
#define xml_parse_to_uint(name,value) if(hgl::strcmp(flag,name)==0)hgl::stou(info,value);else
#define xml_parse_to_float(name,value) if(hgl::strcmp(flag,name)==0)hgl::stof(info,value);else
#define xml_parse_to_bool(name,value) if(hgl::strcmp(flag,name)==0)hgl::stob(info,value);else
/** 使用范例:
<root>
<role name="Bill" sex="true" age="18"/>
<role name="Lucy" sex="false" age="17"/>
</root>
void StartElement(const char *element_name,const char **atts) override
{
if(strcmp(element_name,"role")==0)
{
std::string name;
bool sex;
int age;
XML_START_PARSE(atts)
xml_parse_string_u8(name)
xml_parse_bool(sex)
xml_parse_int(age)
XML_END_PARSE
}
}
*/
}//namespace hgl
#endif//HGL_XML_PARSE_INCLUDE