📄 compressionstreamunit.pas
字号:
{
ZLIB Compression Streams for Delphi by Aphex
http://www.iamaphex.cjb.net
unremote@knology.net
Originally based on delphi fast zlib
http://www.dellapasqua.com/delphizlib
}
unit CompressionStreamUnit;
interface
{$WARNINGS OFF}
uses
Windows;
const
ZLIB_VERSION = '1.1.4';
WM_USER = $0400;
MaxListSize = Maxint div 16;
soFromBeginning = 0;
soFromCurrent = 1;
soFromEnd = 2;
type
TNotifyEvent = procedure(Sender: TObject) of object;
TSeekOrigin = (soBeginning, soCurrent, soEnd);
TStream = class(TObject)
private
function GetPosition: Int64;
procedure SetPosition(const Pos: Int64);
function GetSize: Int64;
procedure SetSize64(const NewSize: Int64);
protected
procedure SetSize(NewSize: Longint); overload; virtual;
procedure SetSize(const NewSize: Int64); overload; virtual;
public
function Read(var Buffer; Count: Longint): Longint; virtual; abstract;
function Write(const Buffer; Count: Longint): Longint; virtual; abstract;
function Seek(Offset: Longint; Origin: Word): Longint; overload; virtual;
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; virtual;
procedure ReadBuffer(var Buffer; Count: Longint);
procedure WriteBuffer(const Buffer; Count: Longint);
function CopyFrom(Source: TStream; Count: Int64): Int64;
property Position: Int64 read GetPosition write SetPosition;
property Size: Int64 read GetSize write SetSize64;
end;
TCustomMemoryStream = class(TStream)
private
FMemory: Pointer;
FData: Pointer;
FSize, FPosition: Longint;
protected
procedure SetPointer(Ptr: Pointer; Size: Longint);
public
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
procedure SaveToStream(Stream: TStream);
procedure SaveToFile(const FileName: string);
property Memory: Pointer read FMemory;
property Data: Pointer read FData write FData;
end;
TMemoryStream = class(TCustomMemoryStream)
private
FCapacity: Longint;
procedure SetCapacity(NewCapacity: Longint);
protected
function Realloc(var NewCapacity: Longint): Pointer; virtual;
property Capacity: Longint read FCapacity write SetCapacity;
public
destructor Destroy; override;
procedure Clear;
procedure LoadFromStream(Stream: TStream);
procedure LoadFromFile(const FileName: string);
procedure SetSize(NewSize: Longint); override;
function Write(const Buffer; Count: Longint): Longint; override;
end;
THandleStream = class(TStream)
protected
FHandle: Integer;
procedure SetSize(NewSize: Longint); override;
procedure SetSize(const NewSize: Int64); override;
public
constructor Create(AHandle: Integer);
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 Handle: Integer read FHandle;
end;
TFileStream = class(THandleStream)
public
constructor Create(const FileName: string; Mode: Word); overload;
constructor Create(const FileName: string; Mode: Word; Rights: Cardinal); overload;
destructor Destroy; override;
end;
TAlloc = function(Opaque: Pointer; Items, Size: Integer): Pointer;
TFree = procedure(Opaque, Block: Pointer);
TCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax);
TCompressionStreamRecord = packed record
NextIn: PChar;
AvailableIn: dword;
TotalIn: dword;
NextOut: PChar;
AvailableOut: dword;
TotalOut: dword;
Msg: PChar;
State: Pointer;
AllocProc: TAlloc;
FreeProc: TFree;
Opaque: Pointer;
DataType: dword;
Adler: dword;
Reserved: dword;
end;
TCustomCompressionStream = class(TStream)
private
FStream: TStream;
FStreamPos: Integer;
FOnProgress: TNotifyEvent;
FStreamRecord: TCompressionStreamRecord;
FBuffer: array [Word] of Char;
protected
constructor Create(stream: TStream);
procedure DoProgress; dynamic;
property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
end;
TCompressionStream = class(TCustomCompressionStream)
private
function GetCompressionRate: Single;
public
constructor Create(dest: TStream; CompressionLevel: TCompressionLevel = zcDefault);
destructor Destroy; override;
function Read(var Buffer; Count: longint): longint; override;
function Write(const Buffer; Count: longint): longint; override;
function Seek(Offset: longint; Origin: Word): longint; override;
property CompressionRate: Single read GetCompressionRate;
property OnProgress;
end;
TDecompressionStream = class(TCustomCompressionStream)
public
constructor Create(source: TStream);
destructor Destroy; override;
function Read(var Buffer; Count: longint): longint; override;
function Write(const Buffer; Count: longint): longint; override;
function Seek(Offset: longint; Origin: Word): longint; override;
property OnProgress;
end;
function adler32(adler: LongInt; const buf: PChar; len: Integer): LongInt;
function crc32(crc: LongInt; const buf: PChar; len: Integer): LongInt;
function compressBound(sourceLen: LongInt): LongInt;
implementation
{$L adler32.obj}
{$L compress.obj}
{$L crc32.obj}
{$L deflate.obj}
{$L infback.obj}
{$L inffast.obj}
{$L inflate.obj}
{$L inftrees.obj}
{$L trees.obj}
{$L uncompr.obj}
const
Levels: array[TCompressionLevel] of Shortint = (0, 1, (-1), 9);
_z_errmsg: array[0..9] of PChar = ('', '', '', '', '', '', '', '', '', '');
fmCreate = $FFFF;
fmOpenRead = $0000;
fmOpenWrite = $0001;
fmOpenReadWrite = $0002;
fmShareCompat = $0000;
fmShareExclusive = $0010;
fmShareDenyWrite = $0020;
fmShareDenyRead = $0030;
fmShareDenyNone = $0040;
function deflateInit_(var strm: TCompressionStreamRecord; level: Integer; version: PChar; recsize: Integer): Integer; external;
function DeflateInit2_(var strm: TCompressionStreamRecord; level: integer; method: integer; windowBits: integer; memLevel: integer; strategy: integer; version: PChar; recsize: integer): integer; external;
function deflate(var strm: TCompressionStreamRecord; flush: Integer): Integer; external;
function deflateEnd(var strm: TCompressionStreamRecord): Integer; external;
function inflateInit_(var strm: TCompressionStreamRecord; version: PChar; recsize: Integer): Integer; external;
function inflateInit2_(var strm: TCompressionStreamRecord; windowBits: integer; version: PChar; recsize: integer): integer; external;
function inflate(var strm: TCompressionStreamRecord; flush: Integer): Integer; external;
function inflateEnd(var strm: TCompressionStreamRecord): Integer; external;
function inflateReset(var strm: TCompressionStreamRecord): Integer; external;
function adler32; external;
function crc32; external;
function compressBound; external;
function FileOpen(const FileName: string; Mode: LongWord): Integer;
const
AccessMode: array[0..2] of LongWord = (
GENERIC_READ,
GENERIC_WRITE,
GENERIC_READ or GENERIC_WRITE);
ShareMode: array[0..4] of LongWord = (
0,
0,
FILE_SHARE_READ,
FILE_SHARE_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE);
begin
Result := -1;
if ((Mode and 3) <= $0002) and
(((Mode and $F0) shr 4) <= $0040) then
Result := Integer(CreateFile(PChar(FileName), AccessMode[Mode and 3],
ShareMode[(Mode and $F0) shr 4], nil, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0));
end;
procedure FileClose(Handle: Integer);
begin
CloseHandle(THandle(Handle));
end;
function FileCreate(const FileName: string): Integer;
begin
Result := Integer(CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE,
0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));
end;
function FileRead(Handle: Integer; var Buffer; Count: LongWord): Integer;
begin
if not ReadFile(THandle(Handle), Buffer, Count, LongWord(Result), nil) then
Result := -1;
end;
function FileWrite(Handle: Integer; const Buffer; Count: LongWord): Integer;
begin
if not WriteFile(THandle(Handle), Buffer, Count, LongWord(Result), nil) then
Result := -1;
end;
function FileSeek(Handle, Offset, Origin: Integer): Integer;
begin
Result := SetFilePointer(THandle(Handle), Offset, nil, Origin);
end;
function zcalloc(opaque: Pointer; items, size: Integer): Pointer;
begin
GetMem(Result, items * size);
end;
procedure zcfree(opaque, block: Pointer);
begin
FreeMem(block);
end;
procedure _memset(p: Pointer; b: Byte; Count: Integer); cdecl;
begin
FillChar(p^, Count, b);
end;
procedure _memcpy(dest, source: Pointer; Count: Integer); cdecl;
begin
move(source^, dest^, Count);
end;
function DeflateInit(var stream: TCompressionStreamRecord; level: Integer): Integer;
begin
Result := DeflateInit_(stream, level, ZLIB_VERSION, SizeOf(TCompressionStreamRecord));
end;
function DeflateInit2(var stream: TCompressionStreamRecord; level, method, windowBits,
memLevel, strategy: Integer): Integer;
begin
Result := DeflateInit2_(stream, level, method, windowBits, memLevel, strategy, ZLIB_VERSION, SizeOf(TCompressionStreamRecord));
end;
function InflateInit(var stream: TCompressionStreamRecord): Integer;
begin
Result := InflateInit_(stream, ZLIB_VERSION, SizeOf(TCompressionStreamRecord));
end;
function InflateInit2(var stream: TCompressionStreamRecord; windowBits: Integer): Integer;
begin
Result := InflateInit2_(stream, windowBits, ZLIB_VERSION, SizeOf(TCompressionStreamRecord));
end;
function TStream.GetPosition: Int64;
begin
Result := Seek(0, soCurrent);
end;
procedure TStream.SetPosition(const Pos: Int64);
begin
Seek(Pos, soBeginning);
end;
function TStream.GetSize: Int64;
var
Pos: Int64;
begin
Pos := Seek(0, soCurrent);
Result := Seek(0, soEnd);
Seek(Pos, soBeginning);
end;
procedure TStream.SetSize(NewSize: Longint);
begin
SetSize(NewSize);
end;
procedure TStream.SetSize64(const NewSize: Int64);
begin
SetSize(NewSize);
end;
procedure TStream.SetSize(const NewSize: Int64);
begin
if (NewSize < Low(Longint)) or (NewSize > High(Longint)) then
Exit;
SetSize(Longint(NewSize));
end;
function TStream.Seek(Offset: Longint; Origin: Word): Longint;
type
TSeek64 = function (const Offset: Int64; Origin: TSeekOrigin): Int64 of object;
var
Impl: TSeek64;
Base: TSeek64;
ClassTStream: TClass;
begin
Impl := Seek;
ClassTStream := Self.ClassType;
while (ClassTStream <> nil) and (ClassTStream <> TStream) do
ClassTStream := ClassTStream.ClassParent;
Base := TStream(@ClassTStream).Seek;
Result := Seek(Int64(Offset), TSeekOrigin(Origin));
end;
function TStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
begin
Result := 0;
if (Offset < Low(Longint)) or (Offset > High(Longint)) then
Exit;
Result := Seek(Longint(Offset), Ord(Origin));
end;
procedure TStream.ReadBuffer(var Buffer; Count: Longint);
begin
if (Count <> 0) and (Read(Buffer, Count) <> Count) then
Exit;
end;
procedure TStream.WriteBuffer(const Buffer; Count: Longint);
begin
if (Count <> 0) and (Write(Buffer, Count) <> Count) then
Exit;
end;
function TStream.CopyFrom(Source: TStream; Count: Int64): Int64;
const
MaxBufSize = $F000;
var
BufSize, N: Integer;
Buffer: PChar;
begin
if Count = 0 then
begin
Source.Position := 0;
Count := Source.Size;
end;
Result := Count;
if Count > MaxBufSize then BufSize := MaxBufSize else BufSize := Count;
GetMem(Buffer, BufSize);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -