From 15db8e01c7a84d2b23a95a5aaaf3e61d72397e2e Mon Sep 17 00:00:00 2001 From: hyzboy Date: Fri, 29 Nov 2019 11:58:31 +0800 Subject: [PATCH] first add files --- .gitmodules | 6 ++ 3rdpty/expat | 1 + 3rdpty/jsoncpp | 1 + CMakeLists.txt | 8 ++ inc/hgl/util/cmd/CmdParse.h | 28 ++++++ inc/hgl/util/json/JsonTool.h | 19 ++++ inc/hgl/util/time/Timer.h | 38 +++++++ inc/hgl/util/xml/XMLParse.h | 123 +++++++++++++++++++++++ path_config.cmake | 11 ++ src/CMakeLists.txt | 3 + src/cmd/CmdParse.cpp | 77 ++++++++++++++ src/json/CMakeLists.txt | 22 ++++ src/json/JsonTool.cpp | 92 +++++++++++++++++ src/time/Timer.cpp | 38 +++++++ src/xml/CMakeLists.txt | 22 ++++ src/xml/XMLParseClass.cpp | 188 +++++++++++++++++++++++++++++++++++ 16 files changed, 677 insertions(+) create mode 100644 .gitmodules create mode 160000 3rdpty/expat create mode 160000 3rdpty/jsoncpp create mode 100644 CMakeLists.txt create mode 100644 inc/hgl/util/cmd/CmdParse.h create mode 100644 inc/hgl/util/json/JsonTool.h create mode 100644 inc/hgl/util/time/Timer.h create mode 100644 inc/hgl/util/xml/XMLParse.h create mode 100644 path_config.cmake create mode 100644 src/CMakeLists.txt create mode 100644 src/cmd/CmdParse.cpp create mode 100644 src/json/CMakeLists.txt create mode 100644 src/json/JsonTool.cpp create mode 100644 src/time/Timer.cpp create mode 100644 src/xml/CMakeLists.txt create mode 100644 src/xml/XMLParseClass.cpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..61d6bc2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "3rdpty/expat"] + path = 3rdpty/expat + url = https://github.com/libexpat/libexpat.git +[submodule "3rdpty/jsoncpp"] + path = 3rdpty/jsoncpp + url = https://github.com/open-source-parsers/jsoncpp.git diff --git a/3rdpty/expat b/3rdpty/expat new file mode 160000 index 0000000..83e1688 --- /dev/null +++ b/3rdpty/expat @@ -0,0 +1 @@ +Subproject commit 83e1688c74ef4d9034e6b47a6595dee480be6147 diff --git a/3rdpty/jsoncpp b/3rdpty/jsoncpp new file mode 160000 index 0000000..9e0d70a --- /dev/null +++ b/3rdpty/jsoncpp @@ -0,0 +1 @@ +Subproject commit 9e0d70aa66e6ba993dd05723ca64c26ab00f3572 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..faa3ff9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.0) + +project(CMUtil) + +include(path_config.cmake) +CMUtilSetup(${CMAKE_CURRENT_SOURCE_DIR}) + +add_subdirectory(${CMUTIL_ROOT_SOURCE_PATH}) diff --git a/inc/hgl/util/cmd/CmdParse.h b/inc/hgl/util/cmd/CmdParse.h new file mode 100644 index 0000000..509e0d8 --- /dev/null +++ b/inc/hgl/util/cmd/CmdParse.h @@ -0,0 +1,28 @@ +#ifndef HGL_COMMAND_LINE_PARSE_INCLUDE +#define HGL_COMMAND_LINE_PARSE_INCLUDE + +#include +namespace hgl +{ + namespace util + { + /** + * 命令行参数解晰辅助类 + */ + class CmdParse ///命令行参数解晰辅助类 + { + OSStringList args; + + public: + + CmdParse(const OSStringList &); + virtual ~CmdParse(); + + int Find(const OSString &)const; ///<查找一个指定字串开头的参数是否存在 + + bool GetInteger(const OSString &,int *)const; ///<取得一个数值参数 + bool GetString(const OSString &,OSString &)const; ///<取得一个字符串参数 + };//class CmdParse + }//namespace util +}//namespace hgl +#endif//HGL_COMMAND_LINE_PARSE_INCLUDE diff --git a/inc/hgl/util/json/JsonTool.h b/inc/hgl/util/json/JsonTool.h new file mode 100644 index 0000000..9a9f2c3 --- /dev/null +++ b/inc/hgl/util/json/JsonTool.h @@ -0,0 +1,19 @@ +#pragma once +#include +#include + +namespace hgl +{ + /** + * 转换Json数据类型到普通UTF8字符串 + */ + bool JsonToString(const Json::Value &jv_root,UTF8String &str,OSString &error_info); + + /** + * 解释一个json数据流 + */ + bool ParseJson(Json::Value &root,const char *str,const int size,OSString &error_info); + + bool LoadJson(Json::Value &,const hgl::OSString &filename,OSString &error_info); + bool SaveJson(Json::Value &,const hgl::OSString &filename,OSString &error_info); +};// diff --git a/inc/hgl/util/time/Timer.h b/inc/hgl/util/time/Timer.h new file mode 100644 index 0000000..3fda8ee --- /dev/null +++ b/inc/hgl/util/time/Timer.h @@ -0,0 +1,38 @@ +#ifndef HGL_TIMER_INCLUDE +#define HGL_TIMER_INCLUDE + +#include +#include +namespace hgl +{ + /** + * 计时器是一个简单封装的组件。通过操作OnTimer事件通知应用程序时间到了! + * 注意如果间隔时间为0那表示不使用定时器,但这样不如将Enable设为false更为高效。 + */ + class Timer:public Object ///计时器类 + { + protected: + + double inter; + double next; + + double GetInterval(){return inter;} + void SetInterval(double); + + public: //属性 + + Property Interval; ///<间隔时间虚拟变量,单位秒 + + public: //事件 + + DefEvent(void,OnTimer,(Object *)); ///<时间到了事件 + + public: + + Timer(double=0); + virtual ~Timer()=default; + + virtual void Update(); + };//class Timer:public Object +}//namespace hgl +#endif//HGL_TIMER_INCLUDE diff --git a/inc/hgl/util/xml/XMLParse.h b/inc/hgl/util/xml/XMLParse.h new file mode 100644 index 0000000..205febf --- /dev/null +++ b/inc/hgl/util/xml/XMLParse.h @@ -0,0 +1,123 @@ +#ifndef HGL_XML_PARSE_INCLUDE +#define HGL_XML_PARSE_INCLUDE + +#include +extern "C" +{ + /** + * 该XML解晰器使用Expat实现,根据MIT协议取得免费授权,授权协议参见 doc/license/MIT.txt + * Expat官方网站:http://expat.sourceforge.net/ + */ + + struct XML_ParserStruct; + typedef struct XML_ParserStruct *XML_Parser; +} + +namespace hgl +{ + namespace io + { + class InputStream; + }//namespace io + + /** + * XML解析器(虚拟函数版)
+ */ + class XMLParse + { + protected: + + XML_Parser xml; + + virtual void StartParse(); + + public: + + virtual void StartElement(const char *element_name,const char **atts)=0; + virtual void CharData(const char *str,int str_length){}; + virtual void EndElement(const char *element_name){}; + + public: + + XMLParse(); + virtual ~XMLParse(); + + virtual void Start(); + virtual bool Parse(const char *buf,int len,bool isFin); + virtual bool Parse(io::InputStream *,bool isFin=true); + };//class XMLParse + + bool XMLParseFile(XMLParse *xml,const OSString &filename); + + /** + * XML解析器(回调函数版) + */ + class XMLParseCB:public XMLParse + { + protected: + + virtual void StartParse(); + + public: + + DefEvent(void,OnStartElement,(const char *,const char **)); + DefEvent(void,OnCharData,(const char *,int)); + DefEvent(void,OnEndElement,(const char *)); + + public: + + XMLParseCB(); + virtual ~XMLParseCB()=default; + };//class XMLParseCB + +#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 + +/** 使用范例: + + + + + + + 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 diff --git a/path_config.cmake b/path_config.cmake new file mode 100644 index 0000000..d1e7d81 --- /dev/null +++ b/path_config.cmake @@ -0,0 +1,11 @@ +macro(CMUtilSetup source_path) + + message("CMUTIL_ROOT_PATH: " ${source_path}) + + set(CMUTIL_ROOT_INCLUDE_PATH ${source_path}/inc) + set(CMUTIL_ROOT_SOURCE_PATH ${source_path}/src) + + set(CMUTIL_ROOT_3RDPTY_PATH ${source_path}/3rdpty) + + include_directories(${CMUTIL_ROOT_INCLUDE_PATH}) +endmacro() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..81de99c --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(xml) +add_subdirectory(json) + diff --git a/src/cmd/CmdParse.cpp b/src/cmd/CmdParse.cpp new file mode 100644 index 0000000..580038a --- /dev/null +++ b/src/cmd/CmdParse.cpp @@ -0,0 +1,77 @@ +#include +#include + +namespace hgl +{ + namespace util + { + CmdParse::CmdParse(const OSStringList &_args) + { + args=_args; + } + + CmdParse::~CmdParse() + { + } + + int CmdParse::Find(const OSString &flag)const + { + return args.Find(flag,flag.Length()); + } + + bool CmdParse::GetInteger(const OSString &flag,int *result)const + { + int index=Find(flag); + + if(index==-1)return(false); + + const OSString &str=args[index]; + + if(str.Length()>flag.Length()) + { + stoi(str.c_str()+flag.Length(),*result); + } + else + { + stoi(str.c_str(),*result); + } + + return(true); + } + + bool CmdParse::GetString(const OSString &flag,OSString &result)const + { + int index=Find(flag); + os_char *p=nullptr; + + if(index==-1)return(false); + + const OSString &str=args[index]; + + if(str.Length()>flag.Length()) + { + p=str.c_str()+flag.Length(); + } + else + { + p=args[index+1]; + } + + if(*p=='"') //有引号 + { + int len=strchr(p+1,L'"')-p; + + if(len>1) + result.Strcpy(p+1,len-1); + else + result=p+1; + } + else //无引号 + { + result=p; + } + + return(true); + } + }//namespace util +}//namespace hgl diff --git a/src/json/CMakeLists.txt b/src/json/CMakeLists.txt new file mode 100644 index 0000000..56150c9 --- /dev/null +++ b/src/json/CMakeLists.txt @@ -0,0 +1,22 @@ +set(JSON_TOOL_HEADER_FILES ${CMUTIL_ROOT_INCLUDE_PATH}/hgl/util/json/JsonTool.h) + +set(JSON_TOOL_SOURCE_FILES JsonTool.cpp) +SOURCE_GROUP("JSON" FILES JsonTool.cpp) + +IF(WIN32) + SET(JSONCPP_PATH ${CMUTIL_ROOT_3RDPTY_PATH}/jsoncpp) + + include_directories(${JSONCPP_PATH}/include) + include_directories(${JSONCPP_PATH}/src/lib_json) + + SET(JSONCPP_SOURCE ${JSONCPP_PATH}/src/lib_json/json_reader.cpp + ${JSONCPP_PATH}/src/lib_json/json_value.cpp + ${JSONCPP_PATH}/src/lib_json/json_writer.cpp) + + SET(JSON_TOOL_SOURCE_FILES ${JSON_TOOL_SOURCE_FILES} ${JSONCPP_SOURCE}) + + SOURCE_GROUP("JSON\\jsoncpp" FILES ${JSONCPP_SOURCE}) +ENDIF(WIN32) + +add_cm_library(CMUtil.JSON "CM/Util" ${JSON_TOOL_HEADER_FILES} + ${JSON_TOOL_SOURCE_FILES}) diff --git a/src/json/JsonTool.cpp b/src/json/JsonTool.cpp new file mode 100644 index 0000000..615e6a0 --- /dev/null +++ b/src/json/JsonTool.cpp @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include + +using namespace hgl::filesystem; +using namespace std; + +namespace hgl +{ + bool JsonToString(const Json::Value &jv_root,UTF8String &str,OSString &error_info) + { + Json::StreamWriterBuilder builder; + Json::StreamWriter *writer=builder.newStreamWriter(); + + JSONCPP_OSTRINGSTREAM json_result; + + bool result; + + try + { + writer->write(jv_root,&json_result); + result=true; + + str=std_to_u8(json_result.str()); + } + catch(std::exception &e) + { + error_info=OS_TEXT("[C++ Exception][Json::StreamWriter::write] ")+std_to_os(e.what()); + result=false; + } + + delete writer; + return result; + } + + bool ParseJson(Json::Value &root,const char *txt,const int size,OSString &error_str) + { + Json::CharReaderBuilder builder; + Json::CharReader *reader=builder.newCharReader(); + + Json::String errs; + + const bool result=reader->parse(txt,txt+size,&root,&errs); + + delete reader; + + error_str=std_to_os(errs); + + return result; + } + + bool LoadJson(Json::Value &root,const OSString &filename,OSString &error_info) + { + char *txt; + int size; + + size=LoadFileToMemory(filename,(void **)&txt); + + if(size<=0) + { + error_info=OS_TEXT("[ERROR][LoadJson] Load file failed, filename: ")+filename; + return(false); + } + + bool result; + + result=ParseJson(root,txt,size,error_info); + delete[] txt; + + return(result); + } + + int SaveJson(Json::Value &root,const OSString &filename,OSString &error_info) + { + UTF8String txt; + + if(!JsonToString(root,txt,error_info)) + return(false); + + const int64 result=SaveMemoryToFile(filename,txt.c_str(),txt.Length()); + + if(result!=txt.Length()) + { + error_info=OS_TEXT("[ERROR][SaveJson] Save file failed, only write ")+OSString(result)+OS_TEXT("/")+OSString(txt.Length()); + return(false); + } + + return(true); + } +}//namespace hgl diff --git a/src/time/Timer.cpp b/src/time/Timer.cpp new file mode 100644 index 0000000..af735c0 --- /dev/null +++ b/src/time/Timer.cpp @@ -0,0 +1,38 @@ +#include +#include + +namespace hgl +{ + Timer::Timer(double t) + { + hglSetProperty(Interval,this,Timer::GetInterval,Timer::SetInterval); + + if(t) + Interval=t; + else + SetEnabled(false); + + OnTimer=nullptr; + } + + void Timer::SetInterval(double t) + { + inter=t; + next=GetDoubleTime()+t; + } + + void Timer::Update() + { + if(OnTimer==nullptr) //没有设置事件函数 + SetEnabled(false); + + double cur_time=GetDoubleTime(); + + if(inter&&cur_time>=next) //间隔大于0,且时间到了 + { + SafeCallEvent(OnTimer,(this)); + + next=cur_time+inter; + } + } +}//namespace hgl diff --git a/src/xml/CMakeLists.txt b/src/xml/CMakeLists.txt new file mode 100644 index 0000000..cda3cf9 --- /dev/null +++ b/src/xml/CMakeLists.txt @@ -0,0 +1,22 @@ +SET(XML_PARSE_SOURCE XMLParseClass.cpp) + +SOURCE_GROUP("XML" FILES XMLParseClass.cpp) + +IF(WIN32) + SET(EXPAT_SOURCE_PATH ${CMUTIL_ROOT_3RDPTY_PATH}/expat/expat/lib) + + include_directories(${EXPAT_SOURCE_PATH}) + + SET(EXPAT_SOURCE + ${EXPAT_SOURCE_PATH}/xmlparse.c + ${EXPAT_SOURCE_PATH}/xmlrole.c + ${EXPAT_SOURCE_PATH}/xmltok.c + ${EXPAT_SOURCE_PATH}/xmltok_impl.c + ${EXPAT_SOURCE_PATH}/xmltok_ns.c) + + SET(XML_PARSE_SOURCE ${XML_PARSE_SOURCE} ${EXPAT_SOURCE}) + + SOURCE_GROUP("XML\\Expat" FILES ${EXPAT_SOURCE}) +ENDIF(WIN32) + +add_cm_library(CMUtil.XML "CM/Util" ${XML_PARSE_SOURCE}) diff --git a/src/xml/XMLParseClass.cpp b/src/xml/XMLParseClass.cpp new file mode 100644 index 0000000..8053b75 --- /dev/null +++ b/src/xml/XMLParseClass.cpp @@ -0,0 +1,188 @@ +//取名为XMLParseClass是为了避免与expat的xmlparse.c编译造成obj冲突 + +#include +#include +#include +#include + +namespace hgl +{ + namespace + { + constexpr uint HGL_XML_PARSE_MAX_SIZE=HGL_SIZE_1KB*128; //最大一次解晰长度 + + void XMLStartElement(XMLParse *xml,const XML_Char *name,const XML_Char **atts) + { + xml->StartElement(name,atts); + } + + void XMLCharData(XMLParse *xml,const XML_Char *str,int len) + { + xml->CharData(str,len); + } + + void XMLEndElement(XMLParse *xml,const XML_Char *name) + { + xml->EndElement(name); + } + } + + XMLParse::XMLParse() + { + xml=nullptr; + } + + XMLParse::~XMLParse() + { + if(!xml)return; + + XML_ParserFree(xml); + } + + void XMLParse::StartParse() + { + XML_SetElementHandler(xml,(XML_StartElementHandler)XMLStartElement,(XML_EndElementHandler)XMLEndElement); + XML_SetCharacterDataHandler(xml,(XML_CharacterDataHandler)XMLCharData); + } + + /** + * 重新开始一次解晰 + */ + void XMLParse::Start() + { + if(xml) + { + XML_ParserReset(xml,"utf-8"); + } + else + { + xml=XML_ParserCreate("utf-8"); + + XML_SetUserData(xml,this); + + StartParse(); + } + } + + /** + * 解晰一段xml文本 + * @param buf 文本缓冲区 + * @param len 文本长度 + * @param isFin 是否结束 + * @return 此次解晰是否成功 + */ + bool XMLParse::Parse(const char *buf,int len,bool isFin) + { + if(!xml)return(false); + + return XML_Parse(xml,buf,len,isFin); + } + + bool hgl::XMLParse::Parse(io::InputStream *is, bool isFin) + { + if(!is)return(false); + + if(is->CanSize()&&is->GetSize()<=HGL_XML_PARSE_MAX_SIZE) //可以取长度的,并且<=指定长度的一次读完 + { + int full_size=is->Available(); + + char *data=new char[full_size]; + + int pos=0; + int size; + + bool result; + + while(posReadFully(data,full_size); + + if(size<0) + return(false); + + result=Parse(data,size,pos+size>=full_size); + + if(!result) + return(false); + + pos+=size; + } + + return(true); + } + else //不能取长度或是大于指定长度的 + { + char data[HGL_XML_PARSE_MAX_SIZE]; + + int size; + bool result; + + for(;;) + { + size=is->Available(); + + if(size<=0)break; + + if(size>HGL_XML_PARSE_MAX_SIZE) + { + size=is->Read(data,HGL_XML_PARSE_MAX_SIZE); + result=Parse(data,HGL_XML_PARSE_MAX_SIZE,false); + } + else + { + size=is->Read(data,size); + result=Parse(data,size,true); + } + + if(!result)return(false); + } + + return(true); + } + } + + /** + * 解晰一个XML文件 + */ + bool XMLParseFile(XMLParse *xml,const OSString &filename) + { + if(!xml)return(false); + if(filename.IsEmpty())return(false); + if(!filesystem::FileCanRead(filename))return(false); + + io::OpenFileInputStream fis(filename); + + return xml->Parse(&fis); + } + + namespace + { + void StartElementCB(XMLParseCB *xml,const XML_Char *name,const XML_Char **atts) + { + SafeCallEvent(xml->OnStartElement,(name,atts)); + } + + void CharDataCB(XMLParseCB *xml,const XML_Char *str,int len) + { + SafeCallEvent(xml->OnCharData,(str,len)); + } + + void EndElementCB(XMLParseCB *xml,const XML_Char *name) + { + SafeCallEvent(xml->OnEndElement,(name)); + } + } + + XMLParseCB::XMLParseCB() + { + OnStartElement=nullptr; + OnCharData=nullptr; + OnEndElement=nullptr; + } + + void XMLParseCB::StartParse() + { + XML_SetElementHandler(xml,(XML_StartElementHandler)StartElementCB,(XML_EndElementHandler)EndElementCB); + XML_SetCharacterDataHandler(xml,(XML_CharacterDataHandler)CharDataCB); + } +}//namespace hgl