new XML Parse tools

This commit is contained in:
2020-08-21 21:11:07 +08:00
parent 2c06e4ae35
commit 505560d95e
10 changed files with 564 additions and 344 deletions

View File

@@ -5,4 +5,13 @@ project(CMUtil)
include(path_config.cmake) include(path_config.cmake)
CMUtilSetup(${CMAKE_CURRENT_SOURCE_DIR}) CMUtilSetup(${CMAKE_CURRENT_SOURCE_DIR})
if(CM_UTIL_SUPPORT_XML)
add_definitions(-DXML_STATIC)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdpty/expat/expat)
endif()
if(CM_UTIL_SUPPORT_JSON)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdpty/jsoncpp)
endif()
add_subdirectory(${CMUTIL_ROOT_SOURCE_PATH}) add_subdirectory(${CMUTIL_ROOT_SOURCE_PATH})

View File

@@ -0,0 +1,24 @@
#ifndef HGL_UTIL_XML_ELEMENT_PARSE_INCLUDE
#define HGL_UTIL_XML_ELEMENT_PARSE_INCLUDE
namespace hgl
{
namespace xml
{
/**
* XML节点解析器
*/
class ElementParse
{
public:
virtual ~ElementParse()=default;
virtual bool Start (const char *element_name) {return(true);}
virtual void Attr (const char *flag,const char *info) {}
virtual void CharData (const char *str,const int str_length) {}
virtual void End (const char *element_name) {}
};//class ElementParse
}//namespace xml
}//namespace hgl
#endif//HGL_UTIL_XML_ELEMENT_PARSE_INCLUDE

View File

@@ -0,0 +1,73 @@
#ifndef HGL_UTIL_XML_ELEMENT_PARSE_CREATER_INCLUDE
#define HGL_UTIL_XML_ELEMENT_PARSE_CREATER_INCLUDE
#include<hgl/util/xml/ElementParse.h>
#include<hgl/type/BaseString.h>
#include<hgl/type/Stack.h>
#include<hgl/type/Map.h>
namespace hgl
{
namespace xml
{
class ElementCreater
{
friend class ElementParseCreater;
AnsiString element_name;
protected:
Map<AnsiString,ElementCreater *> ecs_map;
virtual ElementCreater *GetSubElementCreater(const AnsiString &sub_name);
public:
const AnsiString &GetElementName()const{return element_name;}
public:
ElementCreater(const AnsiString &en){element_name=en;}
virtual ~ElementCreater()=default;
bool Registry(const AnsiString &name,ElementCreater *ec);
public:
virtual bool Start (){return true;}
virtual void Attr (const char *flag,const char *info){}
virtual void CharData (const char *str,const int str_length){}
virtual void End (){}
};//class ElementCreater
/**
* Creater模式XML节点解析器
*/
class ElementParseCreater:public ElementParse
{
Stack<ElementCreater *> ecs_stack;
ElementCreater *root_ec;
ElementCreater *cur_ec;
public:
ElementParseCreater(ElementCreater *rec)
{
root_ec=rec;
cur_ec=rec;
}
virtual ~ElementParseCreater()=default;
public:
bool Start (const char *element_name) override;
void Attr (const char *flag,const char *info) override;
void CharData (const char *str,const int str_length) override;
void End (const char *element_name) override;
};//class ElementParseCreater:public ElementParse
}//namespace xml
}//namespace hgl
#endif//HGL_UTIL_XML_ELEMENT_PARSE_CREATER_INCLUDE

View File

@@ -0,0 +1,64 @@
#ifndef HGL_UTIL_XML_ELEMENT_PARSE_KV_INCLUDE
#define HGL_UTIL_XML_ELEMENT_PARSE_KV_INCLUDE
#include<hgl/util/xml/ElementParse.h>
#include<hgl/type/BaseString.h>
#include<hgl/type/Map.h>
namespace hgl
{
namespace xml
{
/**
* KV模式XML节点解析器
*/
class ElementParseKV:public ElementParse
{
protected:
using AttrsMap=Map<AnsiString,AnsiString>;
using AttrItem=Pair<AnsiString,AnsiString>;
AttrsMap attrs_map;
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);}
public:
virtual ~ElementParseKV()=default;
virtual void Attr(const char *flag,const char *info) override;
public:
const bool IsExist (const AnsiString &name)const{return attrs_map.KeyExist(name);}
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);}
public:
const bool Get(const AnsiString &name,AnsiString &str);
const bool Get(const AnsiString &name,UTF16String &str);
const bool Get(const AnsiString &name,char &ch);
const bool Get(const AnsiString &name,bool &value);
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);
};//class ElementParseKV:public ElementParse
}//namespace xml
}//namespace hgl
#endif//HGL_UTIL_XML_ELEMENT_PARSE_KV_INCLUDE

View File

@@ -2,9 +2,7 @@
#define HGL_XML_PARSE_INCLUDE #define HGL_XML_PARSE_INCLUDE
#include<hgl/type/BaseString.h> #include<hgl/type/BaseString.h>
#include<hgl/type/Map.h> #include<hgl/util/xml/ElementParse.h>
#include<hgl/type/StrChar.h>
#include<hgl/CodePage.h>
extern "C" extern "C"
{ {
@@ -25,106 +23,8 @@ namespace hgl
class InputStream; class InputStream;
}//namespace io }//namespace io
/** namespace xml
* 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
{
protected:
using AttrsMap=Map<AnsiString,AnsiString>;
using AttrItem=Pair<AnsiString,AnsiString>;
AttrsMap attrs_map;
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);}
public:
virtual void Attr(const char *flag,const char *info) override;
public:
const bool IsExist (const AnsiString &name)const{return attrs_map.KeyExist(name);}
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);}
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
constexpr int XML_PARSE_BUFFER_SIZE=HGL_SIZE_1KB*128; ///<XML解析缓冲区大小 constexpr int XML_PARSE_BUFFER_SIZE=HGL_SIZE_1KB*128; ///<XML解析缓冲区大小
/** /**
@@ -141,13 +41,13 @@ namespace hgl
protected: protected:
XMLElementParse *element_parse; ElementParse *element_parse;
virtual void StartParse(); virtual void StartParse();
public: public:
XMLParse(XMLElementParse *,const int size=XML_PARSE_BUFFER_SIZE); XMLParse(ElementParse *,const int size=XML_PARSE_BUFFER_SIZE);
virtual ~XMLParse(); virtual ~XMLParse();
virtual void Start(const char *charset="utf-8"); virtual void Start(const char *charset="utf-8");
@@ -157,31 +57,31 @@ namespace hgl
bool XMLParseFile(XMLParse *xml,const OSString &filename); bool XMLParseFile(XMLParse *xml,const OSString &filename);
#define XML_START_PARSE(name) while(*name) \ #define XML_START_PARSE(name) while(*name) \
{ \ { \
const char *flag=*name;++name; \ const char *flag=*name;++name; \
const char *info=*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() 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_END_PARSE_SKIP() ;}
#define xml_parse_skip(name) if(hgl::strcmp(flag,#name)==0)continue;else #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_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_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_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_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_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_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_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_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_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_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_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 #define xml_parse_to_bool(name,value) if(hgl::strcmp(flag,name)==0)hgl::stob(info,value);else
/** 使用范例: /** 使用范例:
<root> <root>
<role name="Bill" sex="true" age="18"/> <role name="Bill" sex="true" age="18"/>
@@ -205,6 +105,7 @@ namespace hgl
XML_END_PARSE XML_END_PARSE
} }
} }
*/ */
}//namespace xml
}//namespace hgl }//namespace hgl
#endif//HGL_XML_PARSE_INCLUDE #endif//HGL_XML_PARSE_INCLUDE

View File

@@ -1,10 +1,31 @@
option(CM_UTIL_SUPPORT_XML "Build XML Parse module." ON) option(CM_UTIL_SUPPORT_XML "Build XML Parse module." ON)
SET(CM_XML_INCLUDE_PATH ${CMUTIL_ROOT_INCLUDE_PATH}/hgl/util/xml)
if(CM_UTIL_SUPPORT_XML) if(CM_UTIL_SUPPORT_XML)
SET(XML_PARSE_SOURCE ${CMUTIL_ROOT_INCLUDE_PATH}/hgl/util/xml/XMLParse.h
SET(XML_ELEMENT_PARSE_KV ${CM_XML_INCLUDE_PATH}/ElementParseKV.h
xml/ElementParseKV.cpp)
SET(XML_ELEMENT_PARSE_CREATER ${CM_XML_INCLUDE_PATH}/ElementParseCreater.h
xml/ElementParseCreater.cpp
xml/ElementCreater.cpp)
SET(XML_ELEMENT_PARSE_SOURCE ${CM_XML_INCLUDE_PATH}/ElementParse.h)
SET(XML_PARSE_CLASS_SOURCE ${CMUTIL_ROOT_INCLUDE_PATH}/hgl/util/xml/XMLParse.h
xml/XMLParseClass.cpp) xml/XMLParseClass.cpp)
SOURCE_GROUP("XML" FILES ${XML_PARSE_SOURCE}) SET(XML_PARSE_SOURCE ${XML_ELEMENT_PARSE_KV}
${XML_ELEMENT_PARSE_CREATER}
${XML_ELEMENT_PARSE_SOURCE}
${XML_PARSE_CLASS_SOURCE})
SOURCE_GROUP("XML\\ElementParse\\KV" FILES ${XML_ELEMENT_PARSE_KV})
SOURCE_GROUP("XML\\ElementParse\\Creater" FILES ${XML_ELEMENT_PARSE_CREATER})
SOURCE_GROUP("XML\\ElementParse" FILES ${XML_ELEMENT_PARSE_SOURCE})
SOURCE_GROUP("XML" FILES ${XML_PARSE_CLASS_SOURCE})
IF(WIN32) IF(WIN32)
SET(EXPAT_SOURCE_PATH ${CMUTIL_ROOT_3RDPTY_PATH}/expat/expat/lib) SET(EXPAT_SOURCE_PATH ${CMUTIL_ROOT_3RDPTY_PATH}/expat/expat/lib)

View File

@@ -0,0 +1,28 @@
#include<hgl/util/xml/ElementParseCreater.h>
namespace hgl
{
namespace xml
{
bool ElementCreater::Registry(const AnsiString &name,ElementCreater *ec)
{
if(name.Length()<=0||!ec)return(false);
if(ecs_map.KeyExist(name))return(false);
ecs_map.Add(name,ec);
return(true);
}
ElementCreater *ElementCreater::GetSubElementCreater(const AnsiString &sub_name)
{
if(sub_name.IsEmpty())return(nullptr);
ElementCreater *ec;
if(!ecs_map.Get(sub_name,ec))
return(nullptr);
return ec;
}
}//namespace xml
}//namespace hgl

View File

@@ -0,0 +1,42 @@
#include<hgl/util/xml/ElementParseCreater.h>
namespace hgl
{
namespace xml
{
bool ElementParseCreater::Start (const char *element_name)
{
if(!element_name||!*element_name)return(false);
if(!cur_ec)
return(false);
ElementCreater *ec=cur_ec->GetSubElementCreater(element_name);
ecs_stack.Push(cur_ec);
cur_ec=ec;
return(cur_ec);
}
void ElementParseCreater::Attr(const char *flag,const char *info)
{
if(!cur_ec)return;
cur_ec->Attr(flag,info);
}
void ElementParseCreater::CharData(const char *str,const int str_length)
{
if(!cur_ec)return;
cur_ec->CharData(str,str_length);
}
void ElementParseCreater::End(const char *element_name)
{
cur_ec->End();
cur_ec=nullptr;
ecs_stack.Pop(cur_ec);
}
}//namespace xml
}//namespace hgl

View File

@@ -0,0 +1,69 @@
#include<hgl/util/xml/ElementParseKV.h>
#include<hgl/CodePage.h>
namespace hgl
{
namespace xml
{
const ElementParseKV::AttrItem *ElementParseKV::GetAttrItem(const AnsiString &name)
{
const int pos=attrs_map.FindPos(name);
if(pos<0)return(false);
return attrs_map.GetItem(pos);
}
void ElementParseKV::Attr(const char *flag,const char *info)
{
attrs_map.Add(flag,info);
}
const bool ElementParseKV::Get(const AnsiString &name,AnsiString &str)
{
const AttrItem *ai=GetAttrItem(name);
if(!ai)return(false);
str=ai->right;
return(true);
}
const bool ElementParseKV::Get(const AnsiString &name,UTF16String &str)
{
const AttrItem *ai=GetAttrItem(name);
if(!ai)return(false);
str=to_u16(ai->right);
return(true);
}
const bool ElementParseKV::Get(const AnsiString &name,char &ch)
{
const AttrItem *ai=GetAttrItem(name);
if(!ai)return(false);
ch=ai->right.GetBeginChar();
return(true);
}
const bool ElementParseKV::Get(const AnsiString &name,bool &value)
{
const AttrItem *ai=GetAttrItem(name);
return(ai?stob<char>(ai->right.c_str(),value):false);
}
const bool ElementParseKV::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);
}
}//namespace xml
}//namespace hgl

View File

@@ -7,11 +7,13 @@
namespace hgl namespace hgl
{ {
namespace xml
{
namespace namespace
{ {
void XMLStartElement(XMLElementParse *ep,const XML_Char *name,const XML_Char **atts) void XMLStartElement(ElementParse *ep,const XML_Char *name,const XML_Char **atts)
{ {
if(!ep->StartElement(name)) if(!ep->Start(name))
return; return;
const char *flag; const char *flag;
@@ -26,32 +28,18 @@ namespace hgl
} }
} }
void XMLCharData(XMLElementParse *ep,const XML_Char *str,int len) void XMLCharData(ElementParse *ep,const XML_Char *str,int len)
{ {
ep->CharData(str,len); ep->CharData(str,len);
} }
void XMLEndElement(XMLElementParse *ep,const XML_Char *name) void XMLEndElement(ElementParse *ep,const XML_Char *name)
{ {
ep->EndElement(name); ep->End(name);
} }
}//namespace }//namespace
const XMLElementParseKV::AttrItem *XMLElementParseKV::GetAttrItem(const AnsiString &name) XMLParse::XMLParse(ElementParse *ep,const int size)
{
const int pos=attrs_map.FindPos(name);
if(pos<0)return(false);
return attrs_map.GetItem(pos);
}
void XMLElementParseKV::Attr(const char *flag,const char *info)
{
attrs_map.Add(flag,info);
}
XMLParse::XMLParse(XMLElementParse *ep,const int size)
{ {
element_parse=ep; element_parse=ep;
xml=nullptr; xml=nullptr;
@@ -112,7 +100,7 @@ namespace hgl
return XML_Parse(xml,buf,len,isFin); return XML_Parse(xml,buf,len,isFin);
} }
bool hgl::XMLParse::Parse(io::InputStream *is, bool isFin) bool XMLParse::Parse(io::InputStream *is, bool isFin)
{ {
if(!is)return(false); if(!is)return(false);
@@ -184,4 +172,5 @@ namespace hgl
return xml->Parse(&fis); return xml->Parse(&fis);
} }
}//namespace xml
}//namespace hgl }//namespace hgl