Added ConstStringSet<>, first test OK.

This commit is contained in:
hyzboy 2024-07-11 01:19:27 +08:00
parent dcbb9ed7a2
commit 0c90f638de
7 changed files with 304 additions and 17 deletions

View File

@ -0,0 +1,194 @@
#pragma once
#include<hgl/type/SortedSets.h>
#include<hgl/type/Map.h>
#include<hgl/io/TextOutputStream.h>
namespace hgl
{
template<typename SC> 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(length<cs.length)return(-1);
if(length>cs.length)return( 1);
return memcmp(str,cs.str,length);
}
CompOperator(const ConstString &,Comp)
};
template<typename SC> struct ConstStringView
{
DataArray<SC> *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<SC> &csv)const
{
if(length!=csv.length)return(length-csv.length);
return hgl::strcmp(GetString(),csv.GetString(),length);
}
CompOperator(const ConstStringView &,Comp)
};
template<typename SC> class ConstStringSet
{
private:
DataArray<SC> str_data; ///<字符串数据
SortedSets<ConstStringView<SC>> str_set; ///<字符串集合
List<ConstStringView<SC>> str_list; ///<字符串列表
Map<int,size_t> 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<SC> &GetStringData()const{return str_data;} ///<取得字符串数据
const List<ConstStringView<SC>> &GetConstStringList()const{return str_list;} ///<取得字符串列表
public:
const bool IsMember(const SC *str,int length)const ///<判断字符串是否为合集成员
{
if(!str||!*str||length<=0)return(-1);
ConstStringView<SC> 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<SC> 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<SC> *GetStringView(const int id)const ///<根据ID取得字符串视图
{
return str_list.GetPointer(id);
}
public:
ConstStringSet(){}
virtual ~ConstStringSet()=default;
int AddString(ConstStringView<SC> &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<SC>(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<char>;
using ConstWideStringSet =ConstStringSet<wchar_t>;
using ConstUTF8StringSet =ConstStringSet<u8char>;
using ConstUTF16StringSet =ConstStringSet<u16char>;
// using ConstUTF32StringSet =ConstStringSet<u32char>;
using ConstOSStringSet =ConstStringSet<os_char>;
template<typename SC> bool SaveToTextStream(hgl::io::TextOutputStream *tos,const ConstStringSet<SC> *css,bool output_id=false);
template<typename SC> bool SaveToTextFile(const OSString &filename,const ConstStringSet<SC> *css,bool output_id=false,bool output_bom=true);
//template<typename SC> bool SaveToDataStream(hgl::io::DataOutputStream *dos,const ConstStringSet<SC> *css);
}//namespace hgl

View File

@ -202,7 +202,7 @@ namespace hgl
virtual bool GetLast (T &data)const{return data_array.ReadAt(data,GetCount()-1);} ///<取最后一个数据 virtual bool GetLast (T &data)const{return data_array.ReadAt(data,GetCount()-1);} ///<取最后一个数据
};//template <typename T> class List };//template <typename T> class List
template<typename T> T *GetListObject(const List<T *> &list,const int index) template<typename T> T *GetObjectFromList(const List<T *> &list,const int index)
{ {
T *obj; T *obj;

View File

@ -192,7 +192,7 @@ namespace hgl
if(index==-1) if(index==-1)
return(nullptr); return(nullptr);
KVData *obj=GetListObject(data_list,index); KVData *obj=GetObjectFromList(data_list,index);
if(!obj)return(nullptr); if(!obj)return(nullptr);
return &(obj->value); return &(obj->value);
@ -209,7 +209,7 @@ namespace hgl
{ {
int index=Find(flag); int index=Find(flag);
KVData *obj=GetListObject(data_list,index); KVData *obj=GetObjectFromList(data_list,index);
if(!obj) if(!obj)
return(-1); return(-1);
@ -224,7 +224,7 @@ namespace hgl
{ {
int index=Find(key); int index=Find(key);
KVData *obj=GetListObject(data_list,index); KVData *obj=GetObjectFromList(data_list,index);
if(!obj) if(!obj)
return(false); return(false);
@ -323,7 +323,7 @@ namespace hgl
{ {
int index=Find(flag); int index=Find(flag);
KVData *dp=GetListObject(data_list,index); KVData *dp=GetObjectFromList(data_list,index);
if(!dp) if(!dp)
return(false); return(false);
@ -394,7 +394,7 @@ namespace hgl
if(index<0 if(index<0
||index>=data_list.GetCount())return(false); ||index>=data_list.GetCount())return(false);
data_pool.Release(GetListObject(data_list,index)); data_pool.Release(GetObjectFromList(data_list,index));
data_list.DeleteMove(index); data_list.DeleteMove(index);
return(true); return(true);
@ -433,7 +433,7 @@ namespace hgl
if(FindPos(flag,result)) if(FindPos(flag,result))
{ {
dp=GetListObject(data_list,result); dp=GetObjectFromList(data_list,result);
if(dp) if(dp)
{ {
@ -469,7 +469,7 @@ namespace hgl
template<typename K,typename V,typename KVData> template<typename K,typename V,typename KVData>
bool _Map<K,V,KVData>::Change(const K &flag,const V &data) bool _Map<K,V,KVData>::Change(const K &flag,const V &data)
{ {
KVData *dp=GetListObject(data_list,Find(flag)); KVData *dp=GetObjectFromList(data_list,Find(flag));
if(!dp) if(!dp)
return(false); return(false);

View File

@ -125,7 +125,7 @@ namespace hgl
return count; 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 GetBySerial(int,K &,V &) const; ///<取指定序号的数据
bool GetKey(int,K &); ///<取指定序号的索引 bool GetKey(int,K &); ///<取指定序号的索引
bool GetValue(int,V &); ///<取指定序号的数据 bool GetValue(int,V &); ///<取指定序号的数据
@ -151,7 +151,7 @@ namespace hgl
virtual ~Map()=default; virtual ~Map()=default;
};//class Map };//class Map
template<typename T_ID,typename T_U> T_U *GetListObject(Map<T_ID,T_U *> &list,const T_ID &id) template<typename T_ID,typename T_U> T_U *GetObjectFromList(Map<T_ID,T_U *> &list,const T_ID &id)
{ {
T_U *result; T_U *result;
@ -180,7 +180,7 @@ namespace hgl
void DeleteObject(int index) void DeleteObject(int index)
{ {
DeleteObject(GetListObject(this->data_list,index)); DeleteObject(GetObjectFromList(this->data_list,index));
} }
public: public:
@ -301,7 +301,7 @@ namespace hgl
{ {
DeleteObject(index); DeleteObject(index);
KVData *dp=GetListObject(this->data_list,index); KVData *dp=GetObjectFromList(this->data_list,index);
if(dp) if(dp)
dp->value=data; dp->value=data;
@ -326,7 +326,7 @@ namespace hgl
{ {
DeleteObject(index); DeleteObject(index);
KVData *dp=GetListObject(this->data_list,index); KVData *dp=GetObjectFromList(this->data_list,index);
if(!dp) if(!dp)
return(false); return(false);
@ -342,7 +342,7 @@ namespace hgl
V *operator[](const K &index)const 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) if(obj)
return obj->value; return obj->value;

View File

@ -156,7 +156,7 @@ namespace hgl
void Free (){data_list.Free();} ///<清除数据,并释放内存 void Free (){data_list.Free();} ///<清除数据,并释放内存
void Clear (){data_list.Clear();} ///<清除数据,但不释放内存 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()) if(index<0||index>=data_list.GetCount())
return(false); return(false);

View File

@ -73,7 +73,9 @@ SET(STRING_HEADER_FILES ${TYPE_INCLUDE_PATH}/String.h
${TYPE_INCLUDE_PATH}/StringList.h ${TYPE_INCLUDE_PATH}/StringList.h
${TYPE_INCLUDE_PATH}/SplitString.h ${TYPE_INCLUDE_PATH}/SplitString.h
${TYPE_INCLUDE_PATH}/MergeString.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 SET(TEXT_HEADER_FILES ${CMCORE_ROOT_INCLUDE_PATH}/hgl/Endian.h
${CMCORE_ROOT_INCLUDE_PATH}/hgl/CodePage.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 SET(TEXT_SOURCE_FILES Text/Endian.cpp
Text/CodePage.cpp Text/CodePage.cpp
Text/UnicodeBlocks.cpp) Text/UnicodeBlocks.cpp
Text/ConstStringSetSaveToTextStream.cpp)
SOURCE_GROUP("Text\\String" FILES ${STRING_HEADER_FILES} SOURCE_GROUP("Text\\String" FILES ${STRING_HEADER_FILES}
Text/StringList.cpp) Text/StringList.cpp)

View File

@ -0,0 +1,90 @@
#include<hgl/type/ConstStringSet.h>
#include<hgl/io/TextOutputStream.h>
#include<hgl/io/FileOutputStream.h>
namespace hgl
{
template<typename SC> bool SaveToTextStream(io::TextOutputStream *tos,const ConstStringSet<SC> *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<ConstStringView<SC>> &csv_list=css->GetConstStringList();
for(auto &csv:csv_list)
{
utos<SC>(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<SC> &data_array=css->GetStringData();
int length=data_array.GetCount();
AutoDeleteArray<SC> text(length);
hgl_cpy<SC>(text,data_array.data(),length);
for(int i=0;i<length;i++)
{
if(text[i]==0)
text[i]=SC('\n');
}
tos->WriteChars(text,length);
return(true);
}
}
template<typename SC> bool SaveToTextFile(const OSString &filename,const ConstStringSet<SC> *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<io::TextOutputStream> tos=io::CreateTextOutputStream<SC>(&fos);
if(output_bom)
tos->WriteBOM();
return SaveToTextStream<SC>(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