Added ConstStringSet<>, first test OK.
This commit is contained in:
parent
dcbb9ed7a2
commit
0c90f638de
194
inc/hgl/type/ConstStringSet.h
Normal file
194
inc/hgl/type/ConstStringSet.h
Normal 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
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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)
|
||||||
|
90
src/Text/ConstStringSetSaveToTextStream.cpp
Normal file
90
src/Text/ConstStringSetSaveToTextStream.cpp
Normal 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
|
Loading…
x
Reference in New Issue
Block a user