diff --git a/inc/hgl/util/plist/PAttrib.h b/inc/hgl/util/plist/PAttrib.h new file mode 100644 index 0000000..4fa5c2a --- /dev/null +++ b/inc/hgl/util/plist/PAttrib.h @@ -0,0 +1,282 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace hgl +{ + using namespace io; + + template class PAttribBase + { + public: + + PAttribBase()=default; + virtual ~PAttribBase()=default; + + virtual const bool ParseFromString(const BaseString &str)=0; + virtual BaseString MakeToString()const=0; + }; + + template class PAttrib:public PAttribBase + { + protected: + + BaseString name; + T value; + T default_value; + + public: + + PAttrib(const BaseString &n,const T &v) + { + name=n; + value=v; + default_value=v; + } + + virtual ~PAttrib()=default; + + virtual const bool ParseFromString(const BaseString &str)=0; + virtual BaseString MakeToString()const=0; + + virtual const T &Get(){return value;} + virtual void Set(const T &v){value=v;} + };//template class PAttrib + + template class PNumberAttrib:public PAttrib + { + protected: + + T min_value,max_value; + + public: + + PNumberAttrib(const BaseString &n,const T &dv,const T &min_v,const T &max_v):PAttrib(n,dv) + { + min_value=min_v; + max_value=max_v; + } + + virtual ~PNumberAttrib()=default; + + const bool ParseFromString(const BaseString &str) override + { + if(ToNumber(str,this->value)) + { + if(this->value>=min_value&&this->value<=max_value) + return(true); + } + + this->value=this->default_value; + return(false); + } + + BaseString MakeToString() const override + { + return BaseString(this->value); + } + };//class PNumberAttrib:public PAttrib + + template using PIntAttrib =PNumberAttrib; + template using PUintAttrib =PNumberAttrib; + template using PFloatAttrib =PNumberAttrib; + template using PDoubleAttrib=PNumberAttrib; + + template class PBoolAttrib:public PAttrib + { + public: + + using PAttrib::PAttrib; + + const bool ParseFromString(const BaseString &str) + { + if(str.ToBool(this->value)) + return(true); + + this->value=this->default_value; + return(false); + } + + BaseString MakeToString() const override + { + return(this->value?"true":"false"); + } + }; + + template class PStringAttrib:public PAttrib> + { + public: + + using PAttrib>::PAttrib; + + const bool ParseFromString(const BaseString &str) override + { + this->value=str; + return(true); + } + + BaseString MakeToString() const override + { + return this->value; + } + }; + + template class PAttribSet + { + using PString=BaseString; + using PStringList=StringList; + + Map,PAttribBase *> pa_map; + + public: + + template + PNumberAttrib *CreateNumberAttrib(const PString &name,const T &dv,const T &min_v,const T &max_v) + { + PNumberAttrib *obj=new PNumberAttrib(name,dv,min_v,max_v); + + pa_map.Add(name,obj); + + return obj; + } + + PBoolAttrib *CreateBoolAttrib(const PString &name,const bool &dv) + { + PBoolAttrib *obj=new PBoolAttrib(name,dv); + + pa_map.Add(name,obj); + + return obj; + } + + PStringAttrib *CreateStringAttrib(const PString &name,const PString &dv) + { + PStringAttrib *obj=new PStringAttrib(name,dv); + + pa_map.Add(name,obj); + + return obj; + } + + public: + + bool Add(const PString &name,PAttribBase *attr) + { + return pa_map.Add(name,attr); + } + + PAttribBase *Get(const PString &name){return GetObject(pa_map,name);} + + void Delete(const PString &name){pa_map.DeleteByKey(name);} + + void Clear(){pa_map.Clear();} + void ClearData(){pa_map.ClearData();} + + void Enum(void (*enum_func)(const BaseString &key,PAttribBase *value)) + { + pa_map.Enum(enum_func); + }; + + public: + + /** + * 保存到文本文件中 + */ + template + bool SaveToTextFile(const OSString &filename,const PString &gap_ch=PString("\t")) ///<保存列表到文件 + { + FileOutputStream fos; + EndianTextOutputStream tos(&fos); + + if(!fos.CreateTrunc(filename))return(false); + + tos.WriteBOM(); + + const int count=pa_map.GetCount(); + auto **pa_obj=pa_map.GetDataList(); + for(int i=0;ileft); + tos.WriteString(gap_ch); + tos.WriteString((*pa_obj)->right->MakeToString()); + tos.WriteLineEnd(); + + ++pa_obj; + } + + return(true); + } + + private: + + bool Add(const PString &str) ///<向列表中增加一项 + { + PString name; + C *value; + int off; + + if(str.Length()<2)return(false); + + if(((off=str.FindChar(C('\t')))==-1) + &&((off=str.FindChar(C(' '))) ==-1) + &&((off=str.FindChar(C('='))) ==-1) + &&((off=str.FindChar(C(':'))) ==-1)) + return(false); + + name.Strcpy(str,off); + off++; + + value=str.c_str()+off; + + while(true) + { + if(*value == C('\t') + ||*value == C('=') + ||*value == C(' ') + ||*value == C(':')) + { + value++; + continue; + } + + break; + } + + PAttribBase *attr=Get(name); + + if(attr) + attr->ParseFromString(value); + + return(true); + } + + public: + + /** + * 从文本文件中加载 + */ + virtual bool LoadFromTextFile(const OSString &filename) ///<从文件中加载列表 + { + PStringList sl; + + if(LoadStringListFromTextFile(sl,filename)<=0) + return(false); + + int n=sl.GetCount(); + + while(n--) + Add(sl[n]); + + return(true); + } + };//template class PAttribSet + + using UTF8PAttribSet =PAttribSet; + using UTF16PAttribSet =PAttribSet; + using WidePAttribSet =PAttribSet; + using OSPAttribSet =PAttribSet; +}//namespace hgl diff --git a/inc/hgl/util/plist/PList.h b/inc/hgl/util/plist/PList.h new file mode 100644 index 0000000..1117e71 --- /dev/null +++ b/inc/hgl/util/plist/PList.h @@ -0,0 +1,126 @@ +#ifndef HGL_PLIST_INCLUDE +#define HGL_PLIST_INCLUDE + +#include +#include +#include +#include +namespace hgl +{ + using namespace io; + + /** + * 属性列表,类似INI的管理类 + */ + template class PList:public Map,BaseString> ///属性列表 + { + public: + + using PString=BaseString; + using PStringList=StringList; + using PMap=Map; + + protected: + + void ReadData(const PStringList &sl) + { + int n=sl.GetCount(); + + while(n--) + Add(sl[n]); + } + + public: + + virtual ~PList()=default; + + virtual bool Add(const PString &key) ///<向列表中增加一项 + { + PString name; + C *value; + int off; + + if(key.Length()<2)return(false); + + if(((off=key.FindChar(C('\t')))==-1) + &&((off=key.FindChar(C(' '))) ==-1) + &&((off=key.FindChar(C('='))) ==-1) + &&((off=key.FindChar(C(':'))) ==-1)) + return(false); + + name.Strcpy(key,off); + off++; + + value=key.c_str()+off; + + while(true) + { + if(*value == C('\t') + ||*value == C('=') + ||*value == C(' ') + ||*value == C(':')) + value++; + else + { + PString str=value; + + PMap::Add(name,str); + + return(true); + } + } + }//bool PList::Add + + virtual bool Add(const PString &key,const PString &value) ///<向列表中增加一项 + { + return PMap::Add(key,value); + } + + /** + * 从文本文件中加载 + */ + virtual bool LoadFromTextFile(const OSString &filename) ///<从文件中加载列表 + { + PStringList sl; + + if(LoadStringListFromTextFile(sl,filename)<=0) + return(false); + + ReadData(sl); + + return(true); + } + + /** + * 保存到文本文件中 + */ + template + bool SaveToTextFile(const OSString &filename,const PString &gap_ch=PString("\t")) ///<保存列表到文件 + { + FileOutputStream fos; + EndianTextOutputStream tos(&fos); + + if(!fos.CreateTrunc(filename))return(false); + + int n=this->data_list.GetCount(); + + tos.WriteBOM(); + + while(n--) + { + PString f,s; + + if(Get(n,f,s)) + tos.WriteLine(f+gap_ch+s); + } + + return(true); + } + };//class PList + + using UTF8PList =PList; + using UTF16PList=PList; + using WidePList =PList; + using OSPList =PList; +}//namespace hgl +#endif//HGL_PLIST_INCLUDE