198 lines
5.9 KiB
ObjectPascal
198 lines
5.9 KiB
ObjectPascal
(* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is TurboPower Abbrevia
|
|
*
|
|
* The Initial Developer of the Original Code is Craig Peterson
|
|
*
|
|
* Portions created by the Initial Developer are Copyright (C) 2011
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Craig Peterson <capeterson@users.sourceforge.net>
|
|
*
|
|
* ***** END LICENSE BLOCK ***** *)
|
|
|
|
{*********************************************************}
|
|
{* ABBREVIA: AbUnzOutStm.pas *}
|
|
{*********************************************************}
|
|
{* ABBREVIA: UnZip output stream; progress and CRC32 *}
|
|
{*********************************************************}
|
|
|
|
unit AbUnzOutStm;
|
|
|
|
{$I AbDefine.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, Classes, AbArcTyp;
|
|
|
|
type
|
|
// Fixed-length read-only stream, limits reads to the range between
|
|
// the input stream's starting position and a specified size. Seek/Position
|
|
// are adjusted to be 0 based.
|
|
TAbUnzipSubsetStream = class( TStream )
|
|
private
|
|
FStream : TStream;
|
|
FStartPos: Int64;
|
|
FCurPos: Int64;
|
|
FEndPos: Int64;
|
|
|
|
public
|
|
constructor Create(aStream: TStream; aStreamSize: Int64);
|
|
|
|
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;
|
|
|
|
|
|
// Write-only output stream, computes CRC32 and calls progress event
|
|
TAbUnzipOutputStream = class( TStream )
|
|
private
|
|
FBytesWritten : Int64;
|
|
FCRC32 : LongInt;
|
|
FCurrentProgress : Byte;
|
|
FStream : TStream;
|
|
FUncompressedSize : Int64;
|
|
FOnProgress : TAbProgressEvent;
|
|
|
|
function GetCRC32 : LongInt;
|
|
|
|
public
|
|
constructor Create(aStream : TStream);
|
|
|
|
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;
|
|
|
|
property CRC32 : LongInt
|
|
read GetCRC32;
|
|
property Stream : TStream
|
|
read FStream
|
|
write FStream;
|
|
property UncompressedSize : Int64
|
|
read FUncompressedSize
|
|
write FUncompressedSize;
|
|
property OnProgress : TAbProgressEvent
|
|
read FOnProgress
|
|
write FOnProgress;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
Math, AbExcept, AbUtils;
|
|
|
|
{ TAbUnzipSubsetStream implementation ====================================== }
|
|
|
|
{ -------------------------------------------------------------------------- }
|
|
constructor TAbUnzipSubsetStream.Create(aStream: TStream; aStreamSize: Int64);
|
|
begin
|
|
inherited Create;
|
|
FStream := aStream;
|
|
FStartPos := FStream.Position;
|
|
FCurPos := FStartPos;
|
|
FEndPos := FStartPos + aStreamSize;
|
|
end;
|
|
{ -------------------------------------------------------------------------- }
|
|
function TAbUnzipSubsetStream.Read(var Buffer; Count: Longint): Longint;
|
|
begin
|
|
if Count > FEndPos - FCurPos then
|
|
Count := FEndPos - FCurPos;
|
|
if Count > 0 then begin
|
|
Result := FStream.Read(Buffer, Count);
|
|
Inc(FCurPos, Result);
|
|
end
|
|
else
|
|
Result := 0;
|
|
end;
|
|
{ -------------------------------------------------------------------------- }
|
|
function TAbUnzipSubsetStream.Write(const Buffer; Count: Longint): Longint;
|
|
begin
|
|
raise EAbException.Create('TAbUnzipSubsetStream.Write not supported');
|
|
end;
|
|
{ -------------------------------------------------------------------------- }
|
|
function TAbUnzipSubsetStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
|
|
var
|
|
OldPos: Int64;
|
|
begin
|
|
OldPos := FCurPos;
|
|
case Origin of
|
|
soBeginning: FCurPos := FStartPos + Offset;
|
|
soCurrent: FCurPos := FCurPos + Offset;
|
|
soEnd: FCurPos := FEndPos + Offset;
|
|
end;
|
|
if FCurPos < FStartPos then
|
|
FCurPos := FStartPos;
|
|
if FCurPos > FEndPos then
|
|
FCurPos := FEndPos;
|
|
if OldPos <> FCurPos then
|
|
FStream.Position := FCurPos;
|
|
Result := FCurPos - FStartPos;
|
|
end;
|
|
{ -------------------------------------------------------------------------- }
|
|
|
|
|
|
{ TAbUnzipOutputStream implementation ====================================== }
|
|
|
|
{ -------------------------------------------------------------------------- }
|
|
constructor TAbUnzipOutputStream.Create(aStream: TStream);
|
|
begin
|
|
inherited Create;
|
|
FStream := aStream;
|
|
FCRC32 := -1;
|
|
end;
|
|
{ -------------------------------------------------------------------------- }
|
|
function TAbUnzipOutputStream.Read(var Buffer; Count: Integer): Longint;
|
|
begin
|
|
raise EAbException.Create('TAbUnzipOutputStream.Read not supported');
|
|
end;
|
|
{ -------------------------------------------------------------------------- }
|
|
function TAbUnzipOutputStream.Write(const Buffer; Count: Longint): Longint;
|
|
var
|
|
Abort : Boolean;
|
|
NewProgress : Byte;
|
|
begin
|
|
AbUpdateCRC( FCRC32, Buffer, Count );
|
|
|
|
Result := FStream.Write(Buffer, Count);
|
|
|
|
Inc( FBytesWritten, Result );
|
|
if Assigned( FOnProgress ) then begin
|
|
Abort := False;
|
|
NewProgress := AbPercentage(FBytesWritten, FUncompressedSize);
|
|
if (NewProgress <> FCurrentProgress) then begin
|
|
FOnProgress( NewProgress, Abort );
|
|
FCurrentProgress := NewProgress;
|
|
end;
|
|
if Abort then
|
|
raise EAbUserAbort.Create;
|
|
end;
|
|
end;
|
|
{ -------------------------------------------------------------------------- }
|
|
function TAbUnzipOutputStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
|
|
begin
|
|
Result := FStream.Seek(Offset, Origin);
|
|
end;
|
|
{ -------------------------------------------------------------------------- }
|
|
function TAbUnzipOutputStream.GetCRC32: LongInt;
|
|
begin
|
|
Result := not FCRC32;
|
|
end;
|
|
|
|
end.
|
|
|