Răsfoiți Sursa

ADD: Zip - show bzip2/zstd/xz compression/decompression progress

Alexander Koblov 3 ani în urmă
părinte
comite
c3f0f99774

+ 17 - 11
plugins/wcx/zip/src/fparchive/abbzip2typ.pas

@@ -119,7 +119,7 @@ uses
   Windows, // Fix inline warnings
 {$ENDIF}
   StrUtils, SysUtils,
-  AbBzip2, AbExcept, AbVMStrm, AbBitBkt, DCOSUtils, DCClassesUtf8;
+  AbBzip2, AbExcept, AbVMStrm, AbBitBkt, AbProgress, DCOSUtils, DCClassesUtf8;
 
 { ****************** Helper functions Not from Classes Above ***************** }
 function VerifyHeader(const Header : TAbBzip2Header) : Boolean;
@@ -326,7 +326,7 @@ var
   CurItem: TAbBzip2Item;
   UpdateArchive: Boolean;
   TempFileName: String;
-  InputFileStream: TStream;
+  InputFileStream: TAbProgressFileStream;
 begin
   if IsBzippedTar and TarAutoHandle then
   begin
@@ -338,7 +338,7 @@ begin
       FreeAndNil(FBzip2Stream);
       TempFileName := GetTempName(FArchiveName + ExtensionSeparator);
       { Create new archive with temporary name }
-      FBzip2Stream := TFileStreamEx.Create(TempFileName, fmCreate or fmShareDenyWrite);
+      FBzip2Stream := TAbProgressFileStream.Create(TempFileName, fmCreate or fmShareDenyWrite, OnProgress);
     end;
     FTarStream.Position := 0;
     CompStream := TBZCompressionStream.Create(bs9, FBzip2Stream);
@@ -377,7 +377,7 @@ begin
             if CurItem.Action = aaStreamAdd then
               CompStream.CopyFrom(InStream, 0){ Copy/compress entire Instream to FBzip2Stream }
             else begin
-              InputFileStream := TFileStreamEx.Create(CurItem.DiskFileName, fmOpenRead or fmShareDenyWrite );
+              InputFileStream := TAbProgressFileStream.Create(CurItem.DiskFileName, fmOpenRead or fmShareDenyWrite, OnProgress);
               try
                 CompStream.CopyFrom(InputFileStream, 0);{ Copy/compress entire Instream to FBzip2Stream }
               finally
@@ -408,23 +408,29 @@ const
   BufSize = $F000;
 var
   DecompStream: TBZDecompressionStream;
+  ProxyStream: TAbProgressStream;
   Buffer: PByte;
   N: Integer;
 begin
-  DecompStream := TBZDecompressionStream.Create(FBzip2Stream);
+  ProxyStream:= TAbProgressStream.Create(FBzip2Stream, OnProgress);
   try
-    GetMem(Buffer, BufSize);
+    DecompStream := TBZDecompressionStream.Create(ProxyStream);
     try
-      N := DecompStream.Read(Buffer^, BufSize);
-      while N > 0 do begin
-        aStream.WriteBuffer(Buffer^, N);
+      GetMem(Buffer, BufSize);
+      try
         N := DecompStream.Read(Buffer^, BufSize);
+        while N > 0 do begin
+          aStream.WriteBuffer(Buffer^, N);
+          N := DecompStream.Read(Buffer^, BufSize);
+        end;
+      finally
+        FreeMem(Buffer, BufSize);
       end;
     finally
-      FreeMem(Buffer, BufSize);
+      DecompStream.Free;
     end;
   finally
-    DecompStream.Free;
+    ProxyStream.Free;
   end;
 end;
 { -------------------------------------------------------------------------- }

+ 109 - 0
plugins/wcx/zip/src/fparchive/abprogress.pas

@@ -0,0 +1,109 @@
+unit AbProgress;
+
+{$mode ObjFPC}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, AbArcTyp, DCClassesUtf8;
+
+type
+
+  { TAbProgress }
+
+  TAbProgress = object
+    DoneSize: Int64;
+    FileSize: Int64;
+    OnProgress: TAbProgressEvent;
+    procedure DoProgress(Result: Integer);
+  end;
+
+  { TAbProgressStream }
+
+  TAbProgressStream = class(TStream)
+  private
+    FSource: TStream;
+    FProgress: TAbProgress;
+  public
+    constructor Create(ASource : TStream; AEvent: TAbProgressEvent); reintroduce;
+    function Read(var Buffer; Count: Longint): Longint; override;
+    function Write(const Buffer; Count: Longint): Longint; override;
+    function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
+  end;
+
+  { TAbProgressFileStream }
+
+  TAbProgressFileStream = class(TFileStreamEx)
+  private
+    FProgress: TAbProgress;
+  public
+    constructor Create(const AFileName: String; Mode: LongWord; AEvent: TAbProgressEvent); reintroduce;
+    function Read(var Buffer; Count: Longint): Longint; override;
+  end;
+
+implementation
+
+uses
+  AbExcept, DCOSUtils;
+
+{ TAbProgress }
+
+procedure TAbProgress.DoProgress(Result: Integer);
+var
+  Percent: Byte;
+  Abort: Boolean = False;
+begin
+  if (FileSize > 0) then
+  begin
+    DoneSize += Result;
+    Percent:= Byte(DoneSize * 100 div FileSize);
+
+    OnProgress(Percent, Abort);
+
+    if Abort then raise EAbUserAbort.Create;
+  end;
+end;
+
+{ TAbProgressStream }
+
+constructor TAbProgressStream.Create(ASource: TStream; AEvent: TAbProgressEvent);
+begin
+  FSource:= ASource;
+  FProgress.OnProgress:= AEvent;
+  FProgress.FileSize:= FSource.Size;
+end;
+
+function TAbProgressStream.Read(var Buffer; Count: Longint): Longint;
+begin
+  Result:= FSource.Read(Buffer, Count);
+  if Assigned(FProgress.OnProgress) then FProgress.DoProgress(Result);
+end;
+
+function TAbProgressStream.Write(const Buffer; Count: Longint): Longint;
+begin
+  Result:= FSource.Write(Buffer, Count);
+end;
+
+function TAbProgressStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
+begin
+  Result:= FSource.Seek(Offset, Origin);
+end;
+
+{ TAbProgressFileStream }
+
+constructor TAbProgressFileStream.Create(const AFileName: String;
+  Mode: LongWord; AEvent: TAbProgressEvent);
+begin
+  FProgress.OnProgress:= AEvent;
+  inherited Create(AFileName, Mode);
+  FProgress.FileSize:= FileGetSize(Handle);
+end;
+
+function TAbProgressFileStream.Read(var Buffer; Count: Longint): Longint;
+begin
+  Result:= inherited Read(Buffer, Count);
+  if Assigned(FProgress.OnProgress) then FProgress.DoProgress(Result);
+end;
+
+end.
+

+ 13 - 7
plugins/wcx/zip/src/fparchive/abxztyp.pas

@@ -114,7 +114,7 @@ uses
   Windows, // Fix inline warnings
 {$ENDIF}
   StrUtils, SysUtils,
-  AbXz, AbExcept, AbVMStrm, AbBitBkt, CRC, DCOSUtils, DCClassesUtf8;
+  AbXz, AbExcept, AbVMStrm, AbBitBkt, AbProgress, CRC, DCOSUtils, DCClassesUtf8;
 
 { ****************** Helper functions Not from Classes Above ***************** }
 function VerifyHeader(const Header : TAbXzHeader) : Boolean;
@@ -317,8 +317,8 @@ var
   CurItem: TAbXzItem;
   UpdateArchive: Boolean;
   TempFileName: String;
-  InputFileStream: TStream;
   LzmaCompression: TLzmaCompression;
+  InputFileStream: TAbProgressFileStream;
 begin
   if IsXzippedTar and TarAutoHandle then
   begin
@@ -330,7 +330,7 @@ begin
       FreeAndNil(FXzStream);
       TempFileName := GetTempName(FArchiveName + ExtensionSeparator);
       { Create new archive with temporary name }
-      FXzStream := TFileStreamEx.Create(TempFileName, fmCreate or fmShareDenyWrite);
+      FXzStream := TAbProgressFileStream.Create(TempFileName, fmCreate or fmShareDenyWrite, OnProgress);
     end;
     FTarStream.Position := 0;
     LzmaCompression := TLzmaCompression.Create(FTarStream, FXzStream);
@@ -374,7 +374,7 @@ begin
             end;
           end
           else begin
-            InputFileStream := TFileStreamEx.Create(CurItem.DiskFileName, fmOpenRead or fmShareDenyWrite);
+            InputFileStream := TAbProgressFileStream.Create(CurItem.DiskFileName, fmOpenRead or fmShareDenyWrite, OnProgress);
             try
               LzmaCompression := TLzmaCompression.Create(InputFileStream, FXzStream);
               try
@@ -404,13 +404,19 @@ end;
 { -------------------------------------------------------------------------- }
 procedure TAbXzArchive.DecompressToStream(aStream: TStream);
 var
+  ProxyStream: TAbProgressStream;
   LzmaDecompression: TLzmaDecompression;
 begin
-  LzmaDecompression := TLzmaDecompression.Create(FXzStream, aStream);
+  ProxyStream:= TAbProgressStream.Create(FXzStream, OnProgress);
   try
-    LzmaDecompression.Code
+    LzmaDecompression := TLzmaDecompression.Create(ProxyStream, aStream);
+    try
+      LzmaDecompression.Code
+    finally
+      LzmaDecompression.Free;
+    end;
   finally
-    LzmaDecompression.Free;
+    ProxyStream.Free;
   end;
 end;
 { -------------------------------------------------------------------------- }

+ 17 - 11
plugins/wcx/zip/src/fparchive/abzstdtyp.pas

@@ -109,7 +109,7 @@ implementation
 
 uses
   SysUtils,
-  AbZstd, AbExcept, AbVMStrm, AbBitBkt, DCOSUtils, DCClassesUtf8;
+  AbZstd, AbExcept, AbVMStrm, AbBitBkt, AbProgress, DCOSUtils, DCClassesUtf8;
 
 { ****************** Helper functions Not from Classes Above ***************** }
 function VerifyHeader(const Header : TAbZstdHeader) : Boolean;
@@ -313,7 +313,7 @@ var
   CurItem: TAbZstdItem;
   UpdateArchive: Boolean;
   TempFileName: String;
-  InputFileStream: TStream;
+  InputFileStream: TAbProgressFileStream;
 begin
   if IsZstdTar and TarAutoHandle then
   begin
@@ -325,7 +325,7 @@ begin
       FreeAndNil(FZstdStream);
       TempFileName := GetTempName(FArchiveName + ExtensionSeparator);
       { Create new archive with temporary name }
-      FZstdStream := TFileStreamEx.Create(TempFileName, fmCreate or fmShareDenyWrite);
+      FZstdStream := TAbProgressFileStream.Create(TempFileName, fmCreate or fmShareDenyWrite, OnProgress);
     end;
     FTarStream.Position := 0;
     CompStream := TZSTDCompressionStream.Create(FZstdStream, 5, FTarStream.Size);
@@ -369,7 +369,7 @@ begin
             if CurItem.Action = aaStreamAdd then
               CompStream.CopyFrom(InStream, 0){ Copy/compress entire Instream to FZstdStream }
             else begin
-              InputFileStream := TFileStreamEx.Create(CurItem.DiskFileName, fmOpenRead or fmShareDenyWrite );
+              InputFileStream := TAbProgressFileStream.Create(CurItem.DiskFileName, fmOpenRead or fmShareDenyWrite, OnProgress);
               try
                 CompStream.CopyFrom(InputFileStream, 0);{ Copy/compress entire Instream to FZstdStream }
               finally
@@ -400,23 +400,29 @@ const
   BufSize = $F000;
 var
   DecompStream: TZSTDDecompressionStream;
+  ProxyStream: TAbProgressStream;
   Buffer: PByte;
   N: Integer;
 begin
-  DecompStream := TZSTDDecompressionStream.Create(FZstdStream);
+  ProxyStream:= TAbProgressStream.Create(FZstdStream, OnProgress);
   try
-    GetMem(Buffer, BufSize);
+    DecompStream := TZSTDDecompressionStream.Create(ProxyStream);
     try
-      N := DecompStream.Read(Buffer^, BufSize);
-      while N > 0 do begin
-        aStream.WriteBuffer(Buffer^, N);
+      GetMem(Buffer, BufSize);
+      try
         N := DecompStream.Read(Buffer^, BufSize);
+        while N > 0 do begin
+          aStream.WriteBuffer(Buffer^, N);
+          N := DecompStream.Read(Buffer^, BufSize);
+        end;
+      finally
+        FreeMem(Buffer, BufSize);
       end;
     finally
-      FreeMem(Buffer, BufSize);
+      DecompStream.Free;
     end;
   finally
-    DecompStream.Free;
+    ProxyStream.Free;
   end;
 end;
 { -------------------------------------------------------------------------- }