xtool/contrib/CoreCipher/Source/TextDataEngine.pas

811 lines
23 KiB
ObjectPascal

{ ****************************************************************************** }
{ * ini text library,writen by QQ 600585@qq.com * }
{ * https://zpascal.net * }
{ * https://github.com/PassByYou888/zAI * }
{ * https://github.com/PassByYou888/ZServer4D * }
{ * https://github.com/PassByYou888/PascalString * }
{ * https://github.com/PassByYou888/zRasterization * }
{ * https://github.com/PassByYou888/CoreCipher * }
{ * https://github.com/PassByYou888/zSound * }
{ * https://github.com/PassByYou888/zChinese * }
{ * https://github.com/PassByYou888/zExpression * }
{ * https://github.com/PassByYou888/zGameWare * }
{ * https://github.com/PassByYou888/zAnalysis * }
{ * https://github.com/PassByYou888/FFMPEG-Header * }
{ * https://github.com/PassByYou888/zTranslate * }
{ * https://github.com/PassByYou888/InfiniteIoT * }
{ * https://github.com/PassByYou888/FastMD5 * }
{ ****************************************************************************** }
(*
update history
2017-12-6
performance optimization
*)
unit TextDataEngine;
{$INCLUDE zDefine.inc}
interface
uses SysUtils, Variants,
CoreClasses,
UnicodeMixedLib,
PascalStrings,
ListEngine,
MemoryStream64;
type
THashTextEngine = class(TCoreClassObject)
private
FComment: TCoreClassStrings;
FSectionList, FSectionHashVariantList, FSectionHashStringList: THashObjectList;
FAutoUpdateDefaultValue: Boolean;
FSectionPoolSize, FListPoolSize: Integer;
function GetNames(n: SystemString): TCoreClassStrings;
procedure SetNames(n: SystemString; const Value: TCoreClassStrings);
function GetHitVariant(SName, VName: SystemString): Variant;
procedure SetHitVariant(SName, VName: SystemString; const Value: Variant);
function GetHitString(SName, VName: SystemString): SystemString;
procedure SetHitString(SName, VName: SystemString; const Value: SystemString);
// return override state
function GetHVariantList(n: SystemString): THashVariantList;
function GetHStringList(n: SystemString): THashStringList;
procedure AddDataSection(aSection: SystemString; TextList: TCoreClassStrings);
public
constructor Create; overload;
constructor Create(SectionPoolSize_: Integer); overload;
constructor Create(SectionPoolSize_, ListPoolSize_: Integer); overload;
destructor Destroy; override;
procedure Rebuild;
procedure Clear;
procedure Delete(n: SystemString);
function Exists(n: SystemString): Boolean;
function GetDefaultValue(const SectionName, KeyName: SystemString; const DefaultValue: Variant): Variant;
procedure SetDefaultValue(const SectionName, KeyName: SystemString; const Value: Variant);
function GetDefaultText(const SectionName, KeyName: SystemString; const DefaultValue: SystemString): SystemString;
procedure SetDefaultText(const SectionName, KeyName: SystemString; const Value: SystemString);
// import section
function DataImport(TextList: TCoreClassStrings): Boolean; overload;
function DataImport(TextList: TListPascalString): Boolean; overload;
// export section
procedure DataExport(TextList: TCoreClassStrings); overload;
procedure DataExport(TextList: TListPascalString); overload;
procedure Merge(sour: THashTextEngine);
procedure Assign(sour: THashTextEngine);
function Same(sour: THashTextEngine): Boolean;
procedure LoadFromStream(stream: TCoreClassStream);
procedure SaveToStream(stream: TCoreClassStream);
procedure LoadFromFile(FileName: SystemString);
procedure SaveToFile(FileName: SystemString);
function TotalCount: NativeInt;
function MaxSectionNameLen: Integer;
function MinSectionNameLen: Integer;
function GetAsText: SystemString;
procedure SetAsText(const Value: SystemString);
property AsText: SystemString read GetAsText write SetAsText;
procedure GetSectionList(dest: TCoreClassStrings); overload;
procedure GetSectionList(dest: TListString); overload;
procedure GetSectionList(dest: TListPascalString); overload;
function GetSectionObjectName(_Obj: THashVariantList): SystemString; overload;
function GetSectionObjectName(_Obj: THashStringList): SystemString; overload;
property AutoUpdateDefaultValue: Boolean read FAutoUpdateDefaultValue write FAutoUpdateDefaultValue;
property Comment: TCoreClassStrings read FComment write FComment;
property Hit[SName, VName: SystemString]: Variant read GetHitVariant write SetHitVariant; default;
property HitVariant[SName, VName: SystemString]: Variant read GetHitVariant write SetHitVariant;
property HitString[SName, VName: SystemString]: SystemString read GetHitString write SetHitString;
property Names[n: SystemString]: TCoreClassStrings read GetNames write SetNames;
property Strings[n: SystemString]: TCoreClassStrings read GetNames write SetNames;
property VariantList[n: SystemString]: THashVariantList read GetHVariantList;
property HVariantList[n: SystemString]: THashVariantList read GetHVariantList;
property StringList[n: SystemString]: THashStringList read GetHStringList;
property HStringList[n: SystemString]: THashStringList read GetHStringList;
end;
TTextDataEngine = THashTextEngine;
TSectionTextData = THashTextEngine;
implementation
function THashTextEngine.GetNames(n: SystemString): TCoreClassStrings;
var
h: THashVariantTextStream;
begin
if not FSectionList.Exists(n) then
FSectionList[n] := TCoreClassStringList.Create;
if FSectionHashVariantList.Exists(n) then
begin
Result := TCoreClassStringList.Create;
h := THashVariantTextStream.Create(THashVariantList(FSectionHashVariantList[n]));
h.DataExport(Result);
DisposeObject(h);
FSectionList[n] := Result;
end;
Result := TCoreClassStrings(FSectionList[n]);
end;
procedure THashTextEngine.SetNames(n: SystemString; const Value: TCoreClassStrings);
var
ns: TCoreClassStrings;
begin
ns := TCoreClassStringList.Create;
ns.Assign(Value);
FSectionList[n] := ns;
FSectionHashVariantList.Delete(n);
end;
function THashTextEngine.GetHitVariant(SName, VName: SystemString): Variant;
var
nsl: TCoreClassStrings;
vl: THashVariantList;
vt: THashVariantTextStream;
begin
Result := Null;
vl := THashVariantList(FSectionHashVariantList[SName]);
if vl = nil then
begin
nsl := Names[SName];
if nsl = nil then
Exit;
if nsl.Count = 0 then
Exit;
vl := THashVariantList.CustomCreate(FListPoolSize);
vl.AutoUpdateDefaultValue := AutoUpdateDefaultValue;
vt := THashVariantTextStream.Create(vl);
vt.DataImport(nsl);
DisposeObject(vt);
FSectionHashVariantList[SName] := vl;
end;
Result := vl[VName];
end;
procedure THashTextEngine.SetHitVariant(SName, VName: SystemString; const Value: Variant);
var
nsl: TCoreClassStrings;
vl: THashVariantList;
vt: THashVariantTextStream;
begin
vl := THashVariantList(FSectionHashVariantList[SName]);
if vl = nil then
begin
vl := THashVariantList.CustomCreate(FListPoolSize);
vl.AutoUpdateDefaultValue := AutoUpdateDefaultValue;
nsl := Names[SName];
if nsl <> nil then
begin
vt := THashVariantTextStream.Create(vl);
vt.DataImport(nsl);
DisposeObject(vt);
end;
FSectionHashVariantList[SName] := vl;
end;
vl[VName] := Value;
end;
function THashTextEngine.GetHitString(SName, VName: SystemString): SystemString;
var
nsl: TCoreClassStrings;
sl: THashStringList;
st: THashStringTextStream;
begin
Result := '';
sl := THashStringList(FSectionHashStringList[SName]);
if sl = nil then
begin
nsl := Names[SName];
if nsl = nil then
Exit;
if nsl.Count = 0 then
Exit;
sl := THashStringList.CustomCreate(FListPoolSize);
sl.AutoUpdateDefaultValue := AutoUpdateDefaultValue;
st := THashStringTextStream.Create(sl);
st.DataImport(nsl);
DisposeObject(st);
FSectionHashStringList[SName] := sl;
end;
Result := sl[VName];
end;
procedure THashTextEngine.SetHitString(SName, VName: SystemString; const Value: SystemString);
var
nsl: TCoreClassStrings;
sl: THashStringList;
st: THashStringTextStream;
begin
sl := THashStringList(FSectionHashStringList[SName]);
if sl = nil then
begin
sl := THashStringList.CustomCreate(FListPoolSize);
sl.AutoUpdateDefaultValue := AutoUpdateDefaultValue;
nsl := Names[SName];
if nsl <> nil then
begin
st := THashStringTextStream.Create(sl);
st.DataImport(nsl);
DisposeObject(st);
end;
FSectionHashStringList[SName] := sl;
end;
sl[VName] := Value;
end;
function THashTextEngine.GetHVariantList(n: SystemString): THashVariantList;
var
nsl: TCoreClassStrings;
vt: THashVariantTextStream;
begin
Result := THashVariantList(FSectionHashVariantList[n]);
if Result = nil then
begin
Result := THashVariantList.CustomCreate(FListPoolSize);
Result.AutoUpdateDefaultValue := FAutoUpdateDefaultValue;
nsl := Names[n];
if nsl <> nil then
begin
vt := THashVariantTextStream.Create(Result);
vt.DataImport(nsl);
DisposeObject(vt);
end;
FSectionHashVariantList[n] := Result;
end;
end;
function THashTextEngine.GetHStringList(n: SystemString): THashStringList;
var
nsl: TCoreClassStrings;
st: THashStringTextStream;
begin
Result := THashStringList(FSectionHashStringList[n]);
if Result = nil then
begin
Result := THashStringList.CustomCreate(FListPoolSize);
Result.AutoUpdateDefaultValue := FAutoUpdateDefaultValue;
nsl := Names[n];
if nsl <> nil then
begin
st := THashStringTextStream.Create(Result);
st.DataImport(nsl);
DisposeObject(st);
end;
FSectionHashStringList[n] := Result;
end;
end;
procedure THashTextEngine.AddDataSection(aSection: SystemString; TextList: TCoreClassStrings);
begin
while (TextList.Count > 0) and (TextList[0] = '') do
TextList.Delete(0);
while (TextList.Count > 0) and (TextList[TextList.Count - 1] = '') do
TextList.Delete(TextList.Count - 1);
FSectionList.Add(aSection, TextList);
end;
constructor THashTextEngine.Create;
begin
Create(10, 10);
end;
constructor THashTextEngine.Create(SectionPoolSize_: Integer);
begin
Create(SectionPoolSize_, 16);
end;
constructor THashTextEngine.Create(SectionPoolSize_, ListPoolSize_: Integer);
begin
inherited Create;
FSectionPoolSize := SectionPoolSize_;
FListPoolSize := ListPoolSize_;
FComment := TCoreClassStringList.Create;
FSectionList := THashObjectList.CustomCreate(True, FSectionPoolSize);
FSectionHashVariantList := THashObjectList.CustomCreate(True, FSectionPoolSize);
FSectionHashStringList := THashObjectList.CustomCreate(True, FSectionPoolSize);
FAutoUpdateDefaultValue := False;
end;
destructor THashTextEngine.Destroy;
begin
Clear;
DisposeObject(FSectionList);
DisposeObject(FSectionHashVariantList);
DisposeObject(FSectionHashStringList);
DisposeObject(FComment);
inherited Destroy;
end;
procedure THashTextEngine.Rebuild;
var
i: Integer;
tmpSecLst: TListPascalString;
nsl: TCoreClassStrings;
hv: THashVariantTextStream;
hs: THashStringTextStream;
begin
tmpSecLst := TListPascalString.Create;
if FSectionHashVariantList.Count > 0 then
begin
FSectionHashVariantList.GetListData(tmpSecLst);
for i := 0 to tmpSecLst.Count - 1 do
begin
nsl := TCoreClassStringList.Create;
hv := THashVariantTextStream.Create(THashVariantList(tmpSecLst.Objects[i]));
hv.DataExport(nsl);
DisposeObject(hv);
FSectionList[tmpSecLst[i]] := nsl;
end;
FSectionHashVariantList.Clear;
end;
if FSectionHashStringList.Count > 0 then
begin
FSectionHashStringList.GetListData(tmpSecLst);
for i := 0 to tmpSecLst.Count - 1 do
begin
nsl := TCoreClassStringList.Create;
hs := THashStringTextStream.Create(THashStringList(tmpSecLst.Objects[i]));
hs.DataExport(nsl);
DisposeObject(hs);
FSectionList[tmpSecLst[i]] := nsl;
end;
FSectionHashStringList.Clear;
end;
DisposeObject(tmpSecLst);
end;
procedure THashTextEngine.Clear;
begin
FSectionList.Clear;
FSectionHashVariantList.Clear;
FSectionHashStringList.Clear;
FComment.Clear;
end;
procedure THashTextEngine.Delete(n: SystemString);
begin
FSectionList.Delete(n);
FSectionHashVariantList.Delete(n);
FSectionHashStringList.Delete(n);
end;
function THashTextEngine.Exists(n: SystemString): Boolean;
begin
Result := FSectionList.Exists(n) or FSectionHashVariantList.Exists(n) or FSectionHashStringList.Exists(n);
end;
function THashTextEngine.GetDefaultValue(const SectionName, KeyName: SystemString; const DefaultValue: Variant): Variant;
begin
Result := VariantList[SectionName].GetDefaultValue(KeyName, DefaultValue);
end;
procedure THashTextEngine.SetDefaultValue(const SectionName, KeyName: SystemString; const Value: Variant);
begin
Hit[SectionName, KeyName] := Value;
end;
function THashTextEngine.GetDefaultText(const SectionName, KeyName: SystemString; const DefaultValue: SystemString): SystemString;
begin
Result := HStringList[SectionName].GetDefaultValue(KeyName, DefaultValue);
end;
procedure THashTextEngine.SetDefaultText(const SectionName, KeyName: SystemString; const Value: SystemString);
begin
HitString[SectionName, KeyName] := Value;
end;
function THashTextEngine.DataImport(TextList: TCoreClassStrings): Boolean;
var
i: Integer;
ln: U_String;
nsect: SystemString;
ntLst: TCoreClassStrings;
begin
// merge section
Rebuild;
// import new section
ntLst := nil;
nsect := '';
Result := False;
if Assigned(TextList) then
begin
if TextList.Count > 0 then
begin
i := 0;
while i < TextList.Count do
begin
ln := umlTrimChar(TextList[i], ' ');
if (ln.Len > 0) and (ln.First = '[') and (ln.Last = ']') then
begin
if Result then
AddDataSection(nsect, ntLst);
ntLst := TCoreClassStringList.Create;
nsect := umlGetFirstStr(ln, '[]').Text;
Result := True;
end
else if Result then
begin
ntLst.Append(ln);
end
else
begin
if (ln.Len > 0) and (not CharIn(ln.First, [';'])) then
FComment.Append(ln);
end;
inc(i);
end;
if Result then
AddDataSection(nsect, ntLst);
end;
while (FComment.Count > 0) and (FComment[0] = '') do
FComment.Delete(0);
while (FComment.Count > 0) and (FComment[FComment.Count - 1] = '') do
FComment.Delete(FComment.Count - 1);
end;
end;
function THashTextEngine.DataImport(TextList: TListPascalString): Boolean;
var
i: Integer;
ln: U_String;
nsect: SystemString;
ntLst: TCoreClassStrings;
begin
// merge section
Rebuild;
// import new section
ntLst := nil;
nsect := '';
Result := False;
if Assigned(TextList) then
begin
if TextList.Count > 0 then
begin
i := 0;
while i < TextList.Count do
begin
ln := TextList[i].TrimChar(' ');
if (ln.Len > 0) and (ln.First = '[') and (ln.Last = ']') then
begin
if Result then
AddDataSection(nsect, ntLst);
ntLst := TCoreClassStringList.Create;
nsect := umlGetFirstStr(ln, '[]').Text;
Result := True;
end
else if Result then
begin
ntLst.Append(ln);
end
else
begin
if (ln.Len > 0) and (not CharIn(ln.First, [';'])) then
FComment.Append(ln);
end;
inc(i);
end;
if Result then
AddDataSection(nsect, ntLst);
end;
while (FComment.Count > 0) and (FComment[0] = '') do
FComment.Delete(0);
while (FComment.Count > 0) and (FComment[FComment.Count - 1] = '') do
FComment.Delete(FComment.Count - 1);
end;
end;
procedure THashTextEngine.DataExport(TextList: TCoreClassStrings);
var
i: Integer;
tmpSecLst: TListPascalString;
nsl: TCoreClassStrings;
begin
Rebuild;
TextList.AddStrings(FComment);
if FComment.Count > 0 then
TextList.Append('');
tmpSecLst := TListPascalString.Create;
FSectionList.GetListData(tmpSecLst);
if tmpSecLst.Count > 0 then
for i := 0 to tmpSecLst.Count - 1 do
if (tmpSecLst.Objects[i] is TCoreClassStrings) then
begin
nsl := TCoreClassStrings(tmpSecLst.Objects[i]);
if nsl <> nil then
begin
TextList.Append('[' + tmpSecLst[i] + ']');
TextList.AddStrings(nsl);
TextList.Append('');
end;
end;
DisposeObject(tmpSecLst);
end;
procedure THashTextEngine.DataExport(TextList: TListPascalString);
var
i: Integer;
tmpSecLst: TListPascalString;
nsl: TCoreClassStrings;
begin
Rebuild;
TextList.AddStrings(FComment);
if FComment.Count > 0 then
TextList.Append('');
tmpSecLst := TListPascalString.Create;
FSectionList.GetListData(tmpSecLst);
if tmpSecLst.Count > 0 then
for i := 0 to tmpSecLst.Count - 1 do
if (tmpSecLst.Objects[i] is TCoreClassStrings) then
begin
nsl := TCoreClassStrings(tmpSecLst.Objects[i]);
if nsl <> nil then
begin
TextList.Append('[' + tmpSecLst[i].Text + ']');
TextList.AddStrings(nsl);
TextList.Append('');
end;
end;
DisposeObject(tmpSecLst);
end;
procedure THashTextEngine.Merge(sour: THashTextEngine);
var
ns: TCoreClassStringList;
begin
try
Rebuild;
ns := TCoreClassStringList.Create;
sour.Rebuild;
sour.DataExport(ns);
DataImport(ns);
DisposeObject(ns);
Rebuild;
except
end;
end;
procedure THashTextEngine.Assign(sour: THashTextEngine);
var
ns: TCoreClassStringList;
begin
try
ns := TCoreClassStringList.Create;
sour.Rebuild;
sour.DataExport(ns);
Clear;
DataImport(ns);
DisposeObject(ns);
except
end;
end;
function THashTextEngine.Same(sour: THashTextEngine): Boolean;
var
i: Integer;
ns: TCoreClassStringList;
n: SystemString;
begin
Result := False;
Rebuild;
sour.Rebuild;
// if Comment.Text <> sour.Comment.Text then
// Exit;
if FSectionList.Count <> sour.FSectionList.Count then
Exit;
ns := TCoreClassStringList.Create;
for i := 0 to ns.Count - 1 do
begin
n := ns[i];
if not sour.Exists(n) then
begin
DisposeObject(ns);
Exit;
end;
end;
for i := 0 to ns.Count - 1 do
begin
n := ns[i];
if not SameText(Strings[n].Text, sour.Strings[n].Text) then
begin
DisposeObject(ns);
Exit;
end;
end;
DisposeObject(ns);
Result := True;
end;
procedure THashTextEngine.LoadFromStream(stream: TCoreClassStream);
var
n: TListPascalString;
begin
Clear;
n := TListPascalString.Create;
n.LoadFromStream(stream);
DataImport(n);
DisposeObject(n);
end;
procedure THashTextEngine.SaveToStream(stream: TCoreClassStream);
var
n: TListPascalString;
begin
n := TListPascalString.Create;
DataExport(n);
n.SaveToStream(stream);
DisposeObject(n);
end;
procedure THashTextEngine.LoadFromFile(FileName: SystemString);
var
m64: TMemoryStream64;
begin
m64 := TMemoryStream64.Create;
try
m64.LoadFromFile(FileName);
except
DisposeObject(m64);
Exit;
end;
try
LoadFromStream(m64);
finally
DisposeObject(m64);
end;
end;
procedure THashTextEngine.SaveToFile(FileName: SystemString);
var
m64: TMemoryStream64;
begin
m64 := TMemoryStream64.Create;
try
SaveToStream(m64);
m64.SaveToFile(FileName);
finally
DisposeObject(m64);
end;
end;
function THashTextEngine.TotalCount: NativeInt;
var
i: Integer;
tmpSecLst: TListPascalString;
begin
Result := 0;
tmpSecLst := TListPascalString.Create;
FSectionList.GetListData(tmpSecLst);
if tmpSecLst.Count > 0 then
for i := 0 to tmpSecLst.Count - 1 do
if (not FSectionHashVariantList.Exists(tmpSecLst[i])) and (not FSectionHashStringList.Exists(tmpSecLst[i])) then
inc(Result, TCoreClassStrings(tmpSecLst.Objects[i]).Count);
FSectionHashVariantList.GetListData(tmpSecLst);
if tmpSecLst.Count > 0 then
for i := 0 to tmpSecLst.Count - 1 do
inc(Result, THashVariantList(tmpSecLst.Objects[i]).Count);
FSectionHashStringList.GetListData(tmpSecLst);
if tmpSecLst.Count > 0 then
for i := 0 to tmpSecLst.Count - 1 do
inc(Result, THashStringList(tmpSecLst.Objects[i]).Count);
DisposeObject(tmpSecLst);
end;
function THashTextEngine.MaxSectionNameLen: Integer;
begin
Result := umlMax(FSectionList.HashList.MaxNameLen,
umlMax(FSectionHashVariantList.HashList.MaxNameLen, FSectionHashStringList.HashList.MaxNameLen));
end;
function THashTextEngine.MinSectionNameLen: Integer;
begin
Result := umlMin(FSectionList.HashList.MinNameLen,
umlMin(FSectionHashVariantList.HashList.MinNameLen, FSectionHashStringList.HashList.MinNameLen));
end;
function THashTextEngine.GetAsText: SystemString;
var
ns: TCoreClassStringList;
begin
ns := TCoreClassStringList.Create;
DataExport(ns);
Result := ns.Text;
DisposeObject(ns);
end;
procedure THashTextEngine.SetAsText(const Value: SystemString);
var
ns: TListPascalString;
begin
Clear;
ns := TListPascalString.Create;
ns.Text := Value;
DataImport(ns);
DisposeObject(ns);
end;
procedure THashTextEngine.GetSectionList(dest: TCoreClassStrings);
begin
Rebuild;
FSectionList.GetListData(dest);
end;
procedure THashTextEngine.GetSectionList(dest: TListString);
begin
Rebuild;
FSectionList.GetListData(dest);
end;
procedure THashTextEngine.GetSectionList(dest: TListPascalString);
begin
Rebuild;
FSectionList.GetListData(dest);
end;
function THashTextEngine.GetSectionObjectName(_Obj: THashVariantList): SystemString;
begin
Result := FSectionHashVariantList.GetObjAsName(_Obj);
end;
function THashTextEngine.GetSectionObjectName(_Obj: THashStringList): SystemString;
begin
Result := FSectionHashStringList.GetObjAsName(_Obj);
end;
end.