* Allow termination of lengthy operations

git-svn-id: trunk@35517 -
This commit is contained in:
michael 2017-03-04 14:01:36 +00:00
parent 236e56dee0
commit f2f2e02b06

View File

@ -198,6 +198,7 @@ Const
Type
TProgressEvent = Procedure(Sender : TObject; Const Pct : Double) of object;
TProgressEventEx = Procedure(Sender : TObject; Const ATotPos, ATotSize: Int64) of object;
TOnEndOfFileEvent = Procedure(Sender : TObject; Const Ratio : Double) of object;
TOnStartFileEvent = Procedure(Sender : TObject; Const AFileName : String) of object;
@ -205,6 +206,8 @@ Type
{ TCompressor }
TCompressor = Class(TObject)
private
FTerminated: Boolean;
Protected
FInFile : TStream; { I/O file variables }
FOutFile : TStream;
@ -219,10 +222,12 @@ Type
Class Function ZipID : Word; virtual; Abstract;
Class Function ZipVersionReqd: Word; virtual; Abstract;
Function ZipBitFlag: Word; virtual; Abstract;
Procedure Terminate;
Property BufferSize : LongWord read FBufferSize;
Property OnPercent : Integer Read FOnPercent Write FOnPercent;
Property OnProgress : TProgressEvent Read FOnProgress Write FOnProgress;
Property Crc32Val : LongWord Read FCrc32Val Write FCrc32Val;
Property Terminated : Boolean Read FTerminated;
end;
{ TDeCompressor }
@ -234,15 +239,22 @@ Type
FBufferSize : LongWord;
FOnPercent : Integer;
FOnProgress : TProgressEvent;
FOnProgressEx: TProgressEventEx;
FTotPos : Int64;
FTotSize : Int64;
FTerminated : Boolean;
Procedure UpdC32(Octet: Byte);
Public
Constructor Create(AInFile, AOutFile : TStream; ABufSize : LongWord); virtual;
Procedure DeCompress; Virtual; Abstract;
Procedure Terminate;
Class Function ZipID : Word; virtual; Abstract;
Property BufferSize : LongWord read FBufferSize;
Property OnPercent : Integer Read FOnPercent Write FOnPercent;
Property OnProgress : TProgressEvent Read FOnProgress Write FOnProgress;
Property OnProgressEx : TProgressEventEx Read FOnProgressEx Write FOnProgressEx;
Property Crc32Val : LongWord Read FCrc32Val Write FCrc32Val;
Property Terminated : Boolean Read FTerminated;
end;
{ TShrinker }
@ -401,6 +413,7 @@ Type
TZipper = Class(TObject)
Private
FEntries : TZipFileEntries;
FTerminated: Boolean;
FZipping : Boolean;
FBufSize : LongWord;
FFileName : RawByteString; { Name of resulting Zip file }
@ -419,6 +432,7 @@ Type
FOnProgress : TProgressEvent;
FOnEndOfFile : TOnEndOfFileEvent;
FOnStartFile : TOnStartFileEvent;
FCurrentCompressor : TCompressor;
function CheckEntries: Integer;
procedure SetEntries(const AValue: TZipFileEntries);
Protected
@ -449,6 +463,7 @@ Type
Procedure ZipFiles(AFileName : RawByteString; Entries : TZipFileEntries);
Procedure ZipFiles(Entries : TZipFileEntries);
Procedure Clear;
Procedure Terminate;
Public
Property BufferSize : LongWord Read FBufSize Write SetBufSize;
Property OnPercent : Integer Read FOnPercent Write FOnPercent;
@ -461,6 +476,7 @@ Type
Property Files : TStrings Read FFiles; deprecated;
Property InMemSize : Int64 Read FInMemSize Write FInMemSize;
Property Entries : TZipFileEntries Read FEntries Write SetEntries;
Property Terminated : Boolean Read FTerminated;
end;
{ TFullZipFileEntry }
@ -511,11 +527,17 @@ Type
LocalHdr : Local_File_Header_Type; //Local header, before compressed file data
LocalZip64Fld : Zip64_Extended_Info_Field_Type; //header is in LocalZip64ExtHdr
CentralHdr : Central_File_Header_Type;
FTotPos : Int64;
FTotSize : Int64;
FTerminated: Boolean;
FOnPercent : LongInt;
FOnProgress : TProgressEvent;
FOnProgressEx : TProgressEventEx;
FOnEndOfFile : TOnEndOfFileEvent;
FOnStartFile : TOnStartFileEvent;
FCurrentDecompressor: TDecompressor;
function CalcTotalSize(AllFiles: Boolean): Int64;
function IsMatch(I: TFullZipFileEntry): Boolean;
Protected
Procedure OpenInput;
Procedure CloseOutput(Item : TFullZipFileEntry; var OutStream: TStream);
@ -543,6 +565,7 @@ Type
Procedure UnZipAllFiles(AFileName : RawByteString);
Procedure Clear;
Procedure Examine;
Procedure Terminate;
Public
Property BufferSize : LongWord Read FBufSize Write SetBufSize;
Property OnOpenInputStream: TCustomInputStreamEvent read FOnOpenInputStream write FOnOpenInputStream;
@ -551,6 +574,7 @@ Type
Property OnDoneStream : TOnCustomStreamEvent Read FOnDoneStream Write FOnDoneStream;
Property OnPercent : Integer Read FOnPercent Write FOnPercent;
Property OnProgress : TProgressEvent Read FOnProgress Write FOnProgress;
Property OnProgressEx : TProgressEventEx Read FOnProgressEx Write FOnProgressEx;
Property OnStartFile : TOnStartFileEvent Read FOnStartFile Write FOnStartFile;
Property OnEndFile : TOnEndOfFileEvent Read FOnEndOfFile Write FOnEndOfFile;
Property FileName : RawByteString Read FFileName Write SetFileName;
@ -559,6 +583,7 @@ Type
Property Files : TStrings Read FFiles;
Property Entries : TFullZipFileEntries Read FEntries;
Property UseUTF8 : Boolean Read FUseUTF8 Write FUseUTF8;
Property Terminated : Boolean Read FTerminated;
end;
EZipError = Class(Exception);
@ -849,6 +874,11 @@ begin
CRC32Val:=$FFFFFFFF;
end;
procedure TDeCompressor.Terminate;
begin
FTerminated:=True;
end;
{ ---------------------------------------------------------------------
TCompressor
@ -869,6 +899,11 @@ begin
CRC32Val:=$FFFFFFFF;
end;
procedure TCompressor.Terminate;
begin
FTerminated:=True;
end;
{ ---------------------------------------------------------------------
TDeflater
@ -918,7 +953,7 @@ begin
FOnProgress(self,100 * ( BytesNow / FSize));
inc(NextMark,OnBytes);
end;
Until (Count=0);
Until (Count=0) or Terminated;
Finally
C.Free;
end;
@ -998,9 +1033,12 @@ begin
begin
if (FSize>0) and assigned(FOnProgress) Then
FOnProgress(self,100 * ( BytesNow / FSize));
if assigned(FOnProgressEx) Then
FOnProgressEx(Self, FTotPos + BytesNow, FTotSize);
inc(NextMark,OnBytes);
end;
Until (Count=0);
Until (Count=0) or Terminated;
FTotPos := FTotPos + FOutFile.Size;
Finally
C.Free;
end;
@ -1009,6 +1047,8 @@ begin
end;
if assigned(FOnProgress) then
fOnProgress(self,100.0);
if assigned(FOnProgressEx) then
FOnProgressEx(Self, FTotPos, FTotSize);
Crc32Val:=NOT Crc32Val;
end;
@ -1797,6 +1837,7 @@ Function TZipper.CreateCompressor(Item : TZipFileEntry; AInFile,AZipStream : TSt
begin
Result:=TDeflater.Create(AinFile,AZipStream,FBufSize);
(Result as TDeflater).CompressionLevel:=Item.CompressionLevel;
FCurrentCompressor:=Result;
end;
Procedure TZipper.ZipOneFile(Item : TZipFileEntry);
@ -1833,6 +1874,7 @@ Begin
ZVersionReqd:=ZipVersionReqd;
ZBitFlag:=ZipBitFlag;
Finally
FCurrentCompressor:=Nil;
Free;
end;
If UpdateZipHeader(Item,ZipStream,CRC,ZMethod,ZVersionReqd,ZBitFlag) then
@ -1877,15 +1919,20 @@ procedure TZipper.SaveToStream(AStream: TStream);
Var
I : integer; //could be qword but limited by FEntries.Count
begin
FTerminated:=False;
FOutStream := AStream;
If CheckEntries=0 then
Exit;
FZipping:=True;
Try
GetFileInfo; //get info on file entries in zip
for I:=0 to FEntries.Count-1 do
I:=0;
While (I<FEntries.Count) and not Terminated do
begin
ZipOneFile(FEntries[i]);
if FEntries.Count>0 then
Inc(I);
end;
if (FEntries.Count>0) and not Terminated then
BuildZipDirectory;
finally
FZipping:=False;
@ -2005,6 +2052,13 @@ begin
FFiles.Clear;
end;
procedure TZipper.Terminate;
begin
FTerminated:=True;
if Assigned(FCurrentCompressor) then
FCurrentCompressor.Terminate;
end;
Destructor TZipper.Destroy;
begin
@ -2475,6 +2529,7 @@ begin
else
raise EZipError.CreateFmt(SErrUnsupportedCompressionFormat,[AMethod]);
end;
FCurrentDecompressor:=Result;
end;
procedure TUnZipper.UnZipOneFile(Item: TFullZipFileEntry);
@ -2536,12 +2591,19 @@ Var
else
With CreateDecompressor(Item, ZMethod, FZipStream, Dest) do
Try
FTotPos := Self.FTotPos;
FTotSize := Self.FTotSize;
OnProgress:=Self.OnProgress;
OnProgressEx := Self.OnProgressEx;
OnPercent:=Self.OnPercent;
OnProgress:=Self.OnProgress;
OnPercent:=Self.OnPercent;
DeCompress;
Self.FTotPos := FTotPos;
if Item.CRC32 <> Crc32Val then
raise EZipError.CreateFmt(SErrInvalidCRC,[Item.ArchiveFileName]);
Finally
FCurrentDecompressor:=Nil;
Free;
end;
end;
@ -2631,17 +2693,33 @@ Begin
end;
end;
Function TUnZipper.IsMatch(I : TFullZipFileEntry) : Boolean;
begin
if UseUTF8 then
Result:=(FFiles.IndexOf(I.UTF8ArchiveFileName)<>-1)
else
Result:=(FFiles.IndexOf(I.ArchiveFileName)<>-1)
end;
Function TUnZipper.CalcTotalSize(AllFiles : Boolean) : Int64;
Var
I : Integer;
Item : TFullZipFileEntry;
begin
Result:=0;
for i:=0 to FEntries.Count-1 do
begin
Item := FEntries[i];
if AllFiles or IsMatch(Item) then
Result := Result + TZipFileEntry(Item).Size;
end;
end;
procedure TUnZipper.UnZipAllFiles;
Function IsMatch(I : TFullZipFileEntry) : Boolean;
begin
if UseUTF8 then
Result:=(FFiles.IndexOf(I.UTF8ArchiveFileName)<>-1)
else
Result:=(FFiles.IndexOf(I.ArchiveFileName)<>-1)
end;
Var
Item : TFullZipFileEntry;
@ -2649,18 +2727,25 @@ Var
AllFiles : Boolean;
Begin
FTerminated:=False;
FUnZipping:=True;
Try
AllFiles:=(FFiles.Count=0);
OpenInput;
Try
ReadZipDirectory;
for i:=0 to FEntries.Count-1 do
FTotPos := 0;
FTotSize := CalcTotalSize(AllFiles);
i:=0;
While (I<FEntries.Count) and not Terminated do
begin
Item:=FEntries[i];
if AllFiles or IsMatch(Item) then
UnZipOneFile(Item);
inc(I);
end;
if Assigned(FOnProgressEx) and not Terminated then
FOnProgressEx(Self, FTotPos, FTotSize);
Finally
CloseInput;
end;
@ -2784,6 +2869,13 @@ begin
end;
end;
procedure TUnZipper.Terminate;
begin
FTerminated:=True;
if Assigned(FCurrentDecompressor) then
FCurrentDecompressor.Terminate;
end;
destructor TUnZipper.Destroy;
begin