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