diff --git a/inc/hgl/type/ConstStringSet.h b/inc/hgl/type/ConstStringSet.h new file mode 100644 index 0000000..701f295 --- /dev/null +++ b/inc/hgl/type/ConstStringSet.h @@ -0,0 +1,194 @@ +#pragma once + +#include +#include +#include + +namespace hgl +{ + template class ConstString + { + const SC *str; + int length; + + public: + + ConstString(const SC *s,int l) + { + str=s; + length=l; + } + + const SC *c_str()const{return str;} + + const SC *GetString()const{return str;} + const int GetLength()const{return length;} + + const int Comp(const ConstString &cs)const + { + if(lengthcs.length)return( 1); + + return memcmp(str,cs.str,length); + } + + CompOperator(const ConstString &,Comp) + }; + + template struct ConstStringView + { + DataArray *str_data; + + int id; ///<顺序号 + int length; ///<字符串长度 + + union + { + size_t offset; ///<字符串在整个数据中的偏移(id>=0插入合集时使用) + const SC *str; ///<字符串指针(id为-1,未插入合集时使用) + }; + + public: + + const SC *GetString()const + { + if(id==-1) + return str; + else + return str_data->GetData()+offset; + } + + int Comp(const ConstStringView &csv)const + { + if(length!=csv.length)return(length-csv.length); + + return hgl::strcmp(GetString(),csv.GetString(),length); + } + + CompOperator(const ConstStringView &,Comp) + }; + + template class ConstStringSet + { + private: + + DataArray str_data; ///<字符串数据 + + SortedSets> str_set; ///<字符串集合 + + List> str_list; ///<字符串列表 + Map str_offset_map; ///<字符串映射 + + public: + + const int GetCount ()const{return str_list.GetCount();} ///<取得字符串数量 + const int GetTotalLength()const{return str_data.GetCount();} ///<取得字符串总长度 + const int GetTotalBytes ()const{return str_data.GetCount()*sizeof(SC);} ///<取得字符串总字节数 + + const DataArray &GetStringData()const{return str_data;} ///<取得字符串数据 + + const List> &GetConstStringList()const{return str_list;} ///<取得字符串列表 + + public: + + const bool IsMember(const SC *str,int length)const ///<判断字符串是否为合集成员 + { + if(!str||!*str||length<=0)return(-1); + + ConstStringView csv; + + csv.length=length; + csv.str=str; + + return(str_set.FindPos(csv)!=-1); + } + + const int GetID(const SC *str,int length)const ///<取得字符串ID + { + if(!str||!*str||length<=0)return(-1); + + ConstStringView csv; + + csv.id =-1; + csv.length =length; + csv.str =str; + + int64 index=str_set.Find(csv); + if(index>=0) + { + str_set.Get(index,csv); + return csv.id; + } + + return -1; + } + + const SC *GetString(const int id)const ///<根据ID取得字符串 + { + if(id<0||id>=count)return(nullptr); + + size_t offset; + + if(str_offset_map.Get(id,offset)) + return str_data.GetData()+offset; + else + return nullptr; + } + + const ConstStringView *GetStringView(const int id)const ///<根据ID取得字符串视图 + { + return str_list.GetPointer(id); + } + + public: + + ConstStringSet(){} + + virtual ~ConstStringSet()=default; + + int AddString(ConstStringView &csv,const SC *str,int length) ///<添加一个字符串 + { + if(!str||!*str||length<=0) + return(-1); + + csv.id=GetID(str,length); + + if(csv.id>=0) + return csv.id; + + csv.str_data=&str_data; + csv.id =str_set.GetCount(); + csv.length =length; + csv.offset =str_data.GetCount(); + + { + str_data.AddCount(length+1); + + SC *save_str=str_data.GetData()+csv.offset; + + hgl_cpy(save_str,str,length); + + save_str[length]=0; + } + + str_set.Add(csv); + + str_list.Add(csv); + str_offset_map.Add(csv.id,csv.offset); + + return csv.id; + } + };//class ConstStringSet + + using ConstAnsiStringSet =ConstStringSet; + using ConstWideStringSet =ConstStringSet; + using ConstUTF8StringSet =ConstStringSet; + using ConstUTF16StringSet =ConstStringSet; +// using ConstUTF32StringSet =ConstStringSet; + using ConstOSStringSet =ConstStringSet; + + template bool SaveToTextStream(hgl::io::TextOutputStream *tos,const ConstStringSet *css,bool output_id=false); + template bool SaveToTextFile(const OSString &filename,const ConstStringSet *css,bool output_id=false,bool output_bom=true); + + //template bool SaveToDataStream(hgl::io::DataOutputStream *dos,const ConstStringSet *css); +}//namespace hgl diff --git a/inc/hgl/type/List.h b/inc/hgl/type/List.h index e429574..0085e25 100644 --- a/inc/hgl/type/List.h +++ b/inc/hgl/type/List.h @@ -202,7 +202,7 @@ namespace hgl virtual bool GetLast (T &data)const{return data_array.ReadAt(data,GetCount()-1);} ///<取最后一个数据 };//template class List - template T *GetListObject(const List &list,const int index) + template T *GetObjectFromList(const List &list,const int index) { T *obj; diff --git a/inc/hgl/type/Map.cpp b/inc/hgl/type/Map.cpp index 9ce953a..23e5acf 100644 --- a/inc/hgl/type/Map.cpp +++ b/inc/hgl/type/Map.cpp @@ -192,7 +192,7 @@ namespace hgl if(index==-1) return(nullptr); - KVData *obj=GetListObject(data_list,index); + KVData *obj=GetObjectFromList(data_list,index); if(!obj)return(nullptr); return &(obj->value); @@ -209,7 +209,7 @@ namespace hgl { int index=Find(flag); - KVData *obj=GetListObject(data_list,index); + KVData *obj=GetObjectFromList(data_list,index); if(!obj) return(-1); @@ -224,7 +224,7 @@ namespace hgl { int index=Find(key); - KVData *obj=GetListObject(data_list,index); + KVData *obj=GetObjectFromList(data_list,index); if(!obj) return(false); @@ -323,7 +323,7 @@ namespace hgl { int index=Find(flag); - KVData *dp=GetListObject(data_list,index); + KVData *dp=GetObjectFromList(data_list,index); if(!dp) return(false); @@ -394,7 +394,7 @@ namespace hgl if(index<0 ||index>=data_list.GetCount())return(false); - data_pool.Release(GetListObject(data_list,index)); + data_pool.Release(GetObjectFromList(data_list,index)); data_list.DeleteMove(index); return(true); @@ -433,7 +433,7 @@ namespace hgl if(FindPos(flag,result)) { - dp=GetListObject(data_list,result); + dp=GetObjectFromList(data_list,result); if(dp) { @@ -469,7 +469,7 @@ namespace hgl template bool _Map::Change(const K &flag,const V &data) { - KVData *dp=GetListObject(data_list,Find(flag)); + KVData *dp=GetObjectFromList(data_list,Find(flag)); if(!dp) return(false); diff --git a/inc/hgl/type/Map.h b/inc/hgl/type/Map.h index 9792bbc..aecc9a0 100644 --- a/inc/hgl/type/Map.h +++ b/inc/hgl/type/Map.h @@ -125,7 +125,7 @@ namespace hgl return count; } - KVData *GetItem(int n){return GetListObject(data_list,n);} ///<取指定序号的数据 + KVData *GetItem(int n){return GetObjectFromList(data_list,n);} ///<取指定序号的数据 bool GetBySerial(int,K &,V &) const; ///<取指定序号的数据 bool GetKey(int,K &); ///<取指定序号的索引 bool GetValue(int,V &); ///<取指定序号的数据 @@ -151,7 +151,7 @@ namespace hgl virtual ~Map()=default; };//class Map - template T_U *GetListObject(Map &list,const T_ID &id) + template T_U *GetObjectFromList(Map &list,const T_ID &id) { T_U *result; @@ -180,7 +180,7 @@ namespace hgl void DeleteObject(int index) { - DeleteObject(GetListObject(this->data_list,index)); + DeleteObject(GetObjectFromList(this->data_list,index)); } public: @@ -301,7 +301,7 @@ namespace hgl { DeleteObject(index); - KVData *dp=GetListObject(this->data_list,index); + KVData *dp=GetObjectFromList(this->data_list,index); if(dp) dp->value=data; @@ -326,7 +326,7 @@ namespace hgl { DeleteObject(index); - KVData *dp=GetListObject(this->data_list,index); + KVData *dp=GetObjectFromList(this->data_list,index); if(!dp) return(false); @@ -342,7 +342,7 @@ namespace hgl V *operator[](const K &index)const { - auto *obj=GetListObject(this->data_list,this->Find(index)); + auto *obj=GetObjectFromList(this->data_list,this->Find(index)); if(obj) return obj->value; diff --git a/inc/hgl/type/SortedSets.h b/inc/hgl/type/SortedSets.h index f0f779a..ea2d68d 100644 --- a/inc/hgl/type/SortedSets.h +++ b/inc/hgl/type/SortedSets.h @@ -156,7 +156,7 @@ namespace hgl void Free (){data_list.Free();} ///<清除数据,并释放内存 void Clear (){data_list.Clear();} ///<清除数据,但不释放内存 - bool Get (const int64 index,T &data) ///<根据序列号取得指定数据 + bool Get (const int64 index,T &data) const ///<根据序列号取得指定数据 { if(index<0||index>=data_list.GetCount()) return(false); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 31487fb..9aa32b5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -73,7 +73,9 @@ SET(STRING_HEADER_FILES ${TYPE_INCLUDE_PATH}/String.h ${TYPE_INCLUDE_PATH}/StringList.h ${TYPE_INCLUDE_PATH}/SplitString.h ${TYPE_INCLUDE_PATH}/MergeString.h - ${TYPE_INCLUDE_PATH}/StdString.h) + ${TYPE_INCLUDE_PATH}/StdString.h + ${TYPE_INCLUDE_PATH}/ConstStringSet.h +) SET(TEXT_HEADER_FILES ${CMCORE_ROOT_INCLUDE_PATH}/hgl/Endian.h ${CMCORE_ROOT_INCLUDE_PATH}/hgl/CodePage.h @@ -83,7 +85,8 @@ SET(TEXT_HEADER_FILES ${CMCORE_ROOT_INCLUDE_PATH}/hgl/Endian.h SET(TEXT_SOURCE_FILES Text/Endian.cpp Text/CodePage.cpp - Text/UnicodeBlocks.cpp) + Text/UnicodeBlocks.cpp + Text/ConstStringSetSaveToTextStream.cpp) SOURCE_GROUP("Text\\String" FILES ${STRING_HEADER_FILES} Text/StringList.cpp) diff --git a/src/Text/ConstStringSetSaveToTextStream.cpp b/src/Text/ConstStringSetSaveToTextStream.cpp new file mode 100644 index 0000000..ae8b9aa --- /dev/null +++ b/src/Text/ConstStringSetSaveToTextStream.cpp @@ -0,0 +1,90 @@ +#include +#include +#include + +namespace hgl +{ + template bool SaveToTextStream(io::TextOutputStream *tos,const ConstStringSet *css,bool output_id) + { + if(!tos||!css) + return(false); + + if(css->GetCount()<=0) + return(true); + + if(output_id) + { + SC id_str[16]; + const SC gap_str[4]={SC(' '),SC(':'),SC(' '),0}; + + const List> &csv_list=css->GetConstStringList(); + + for(auto &csv:csv_list) + { + utos(id_str,sizeof(id_str),csv.id); + + tos->WriteChars(id_str,hgl::strlen(id_str)); + tos->WriteChars(gap_str,3); + tos->WriteChars(csv.GetString(),csv.length); + tos->WriteLineEnd(); + } + + return(true); + } + else + { + const DataArray &data_array=css->GetStringData(); + + int length=data_array.GetCount(); + + AutoDeleteArray text(length); + + hgl_cpy(text,data_array.data(),length); + + for(int i=0;iWriteChars(text,length); + return(true); + } + } + + template bool SaveToTextFile(const OSString &filename,const ConstStringSet *css,bool output_id,bool output_bom) + { + if(!css) + return(false); + + if(filename.IsEmpty()) + return(false); + + if(css->GetCount()<=0) + return(true); + + io::OpenFileOutputStream fos(filename,io::FileOpenMode::CreateTrunc); + + if(!fos) + return(false); + + AutoDelete tos=io::CreateTextOutputStream(&fos); + + if(output_bom) + tos->WriteBOM(); + + return SaveToTextStream(tos,css,output_id); + } + + //下面这些定义是为了实例化上面的函数,所以不要删掉 + + bool SaveToAnsiTextStream(hgl::io::TextOutputStream *tos,const ConstAnsiStringSet *css,bool output_id){return SaveToTextStream(tos,css,output_id);} + bool SaveToWideTextStream(hgl::io::TextOutputStream *tos,const ConstWideStringSet *css,bool output_id){return SaveToTextStream(tos,css,output_id);} + bool SaveToUTF8TextStream(hgl::io::TextOutputStream *tos,const ConstUTF8StringSet *css,bool output_id){return SaveToTextStream(tos,css,output_id);} + bool SaveToUTF16TextStream(hgl::io::TextOutputStream *tos,const ConstUTF16StringSet *css,bool output_id){return SaveToTextStream(tos,css,output_id);} + + bool SaveToAnsiTextFile(const OSString &filename,const ConstAnsiStringSet *css,bool output_id,bool output_bom){return SaveToTextFile(filename,css,output_id,output_bom);} + bool SaveToWideTextFile(const OSString &filename,const ConstWideStringSet *css,bool output_id,bool output_bom){return SaveToTextFile(filename,css,output_id,output_bom);} + bool SaveToUTF8TextFile(const OSString &filename,const ConstUTF8StringSet *css,bool output_id,bool output_bom){return SaveToTextFile(filename,css,output_id,output_bom);} + bool SaveToUTF16TextFile(const OSString &filename,const ConstUTF16StringSet *css,bool output_id,bool output_bom){return SaveToTextFile(filename,css,output_id,output_bom);} +}//namespace hgl