Browse Source

* Allow termination of lengthy operations

git-svn-id: trunk@35517 -
michael 8 years ago
parent
commit
f2f2e02b06
1 changed files with 106 additions and 14 deletions
  1. 106 14
      packages/paszlib/src/zipper.pp

+ 106 - 14
packages/paszlib/src/zipper.pp

@@ -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;
 
 
-procedure TUnZipper.UnZipAllFiles;
+begin
+  if UseUTF8 then
+    Result:=(FFiles.IndexOf(I.UTF8ArchiveFileName)<>-1)
+  else
+    Result:=(FFiles.IndexOf(I.ArchiveFileName)<>-1)
+end;
 
 
-  Function IsMatch(I : TFullZipFileEntry) : Boolean;
+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;
 
 
-  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