BSOne.SFC/EM.Lib/ImageEn_SRC/Source/iezlib.pas

1027 lines
25 KiB
Plaintext

(* ImageEn Build 7.0.0.06.2637 @ 7-4-17 14:58:42.679 *)
(*
Copyright (c) 1998-2017 by Carlotta Calandra. All rights reserved.
Copyright (c) 2011-2017 by Xequte Software.
This software comes without express or implied warranty.
In no case shall the author be liable for any damage or unwanted behavior of any
computer hardware and/or software.
Author grants you the right to include the component
in your application, whether COMMERCIAL, SHAREWARE, or FREEWARE.
ImageEn, IEvolution and ImageEn ActiveX may not be included in any
commercial, shareware or freeware libraries or components.
www.ImageEn.com
*)
(*
File version 1005
*)
unit iezlib;
{$R-}
{$Q-}
{$I ie.inc}
{$IFNDEF IEUSEVCLZLIB}
{$IFDEF IEINCLUDEZLIB}
interface
uses
Windows, Graphics, classes, sysutils, ImageEnProc, ImageEnIO, hyiedefs;
type
// portions of ZLib
EZLibError = class(Exception);
EZCompressionError = class(EZLibError);
EZDecompressionError = class(EZLibError);
TZAlloc = function(opaque: Pointer; items, size: Integer): Pointer;
TZFree = procedure(opaque, block: Pointer);
TZCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax);
TZStreamRec = packed record
next_in: PAnsiChar; // next input byte
avail_in: Longint; // number of bytes available at next_in
total_in: Longint; // total nb of input bytes read so far
next_out: PAnsiChar; // next output byte should be put here
avail_out: Longint; // remaining free space at next_out
total_out: Longint; // total nb of bytes output so far
msg: PAnsiChar; // last error message, NULL if no error
state: Pointer; // not visible by applications
zalloc: TZAlloc; // used to allocate the internal state
zfree: TZFree; // used to free the internal state
opaque: Pointer; // private data object passed to zalloc and zfree
data_type: Integer; // best guess about the data type: ascii or binary
adler: Longint; // adler32 value of the uncompressed data
reserved: Longint; // reserved for future use
end;
TCustomZStream = class(TStream)
private
FStream: TStream;
FStreamPos: Int64;
FOnProgress: TNotifyEvent;
FZStream: TZStreamRec;
FBuffer: array[Word] of AnsiChar;
protected
constructor Create(stream: TStream);
procedure DoProgress; dynamic;
property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
end;
TZCompressionStream = class(TCustomZStream)
private
function GetCompressionRate: Single;
public
constructor Create(dest: TStream; compressionLevel: TZCompressionLevel; windowBits: integer = 15);
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;
TZDecompressionStream = class(TCustomZStream)
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;
procedure ZCompress(const inBuffer: Pointer; inSize: Integer; out outBuffer: Pointer; out outSize: Integer; level: TZCompressionLevel);
procedure ZDecompress(const inBuffer: Pointer; inSize: Integer; out outBuffer: Pointer; out outSize: Integer; outEstimate: Integer);
function ZCompressStr(const s: AnsiString; level: TZCompressionLevel): AnsiString;
function ZDecompressStr(const s: AnsiString): AnsiString;
procedure ZCompressStream(inStream, outStream: TStream; level: TZCompressionLevel);
procedure ZDecompressStream(inStream, outStream: TStream);
procedure IEZDecompress(const inBuffer: Pointer; inSize: Integer; out outBuffer: Pointer; out outSize: Integer; outEstimate: Integer);
procedure _abort; cdecl; forward;
function _memcmp(buf1, buf2: pbyte; count: integer): integer; cdecl; forward;
procedure memset(P: Pointer; B: Byte; count: Integer); cdecl; forward;
procedure memcpy(dest, source: Pointer; count: Integer); cdecl; forward;
function _malloc(size: Integer): Pointer; cdecl; forward;
procedure _free(P: Pointer); cdecl; forward;
function _fabs(v: double): double; cdecl; forward;
function _pow(Base, Exponent: double): double; cdecl; forward;
function __ftol: Integer; cdecl; forward;
function _strlen(s: PAnsiChar): cardinal; cdecl; forward;
function _strtod(s: PAnsiChar; var vp: PAnsiChar): double; cdecl;
procedure crc32; cdecl; external;
function deflateInit_(var strm: TZStreamRec; level: Integer; version: PAnsiChar; recsize: Integer): Integer; cdecl; external;
function deflate(var strm: TZStreamRec; flush: Integer): Integer; cdecl; external;
function deflateEnd(var strm: TZStreamRec): Integer; cdecl; external;
function inflateInit_(var strm: TZStreamRec; version: PAnsiChar; recsize: Integer): Integer; cdecl; external;
function inflate(var strm: TZStreamRec; flush: Integer): Integer; cdecl; external;
function inflateEnd(var strm: TZStreamRec): Integer; cdecl; external;
function inflateReset(var strm: TZStreamRec): Integer; cdecl; external;
procedure deflateInit2_; cdecl; external;
procedure deflateReset; cdecl; external;
implementation
uses
math, hyieutils;
{$R-}
const
ZLIB_VERSION: AnsiString = '1.2.3';
const
Z_NO_FLUSH = 0;
Z_PARTIAL_FLUSH = 1;
Z_SYNC_FLUSH = 2;
Z_FULL_FLUSH = 3;
Z_FINISH = 4;
Z_OK = 0;
Z_STREAM_END = 1;
Z_NEED_DICT = 2;
Z_ERRNO = (-1);
Z_STREAM_ERROR = (-2);
Z_DATA_ERROR = (-3);
Z_MEM_ERROR = (-4);
Z_BUF_ERROR = (-5);
Z_VERSION_ERROR = (-6);
Z_NO_COMPRESSION = 0;
Z_BEST_SPEED = 1;
Z_BEST_COMPRESSION = 9;
Z_DEFAULT_COMPRESSION = (-1);
Z_FILTERED = 1;
Z_HUFFMAN_ONLY = 2;
Z_DEFAULT_STRATEGY = 0;
Z_BINARY = 0;
Z_ASCII = 1;
Z_UNKNOWN = 2;
Z_DEFLATED = 8;
z_errmsg: array[0..9] of PWideChar = (
'need dictionary', // Z_NEED_DICT (2)
'stream end', // Z_STREAM_END (1)
'', // Z_OK (0)
'file error', // Z_ERRNO (-1)
'stream error', // Z_STREAM_ERROR (-2)
'data error', // Z_DATA_ERROR (-3)
'insufficient memory', // Z_MEM_ERROR (-4)
'buffer error', // Z_BUF_ERROR (-5)
'incompatible version', // Z_VERSION_ERROR (-6)
''
);
// Compatibility with ZipForge (3.0.4)
_z_errmsg: array[0..9] of PAnsiChar = (
'need dictionary', // Z_NEED_DICT (2)
'stream end', // Z_STREAM_END (1)
'', // Z_OK (0)
'file error', // Z_ERRNO (-1)
'stream error', // Z_STREAM_ERROR (-2)
'data error', // Z_DATA_ERROR (-3)
'insufficient memory', // Z_MEM_ERROR (-4)
'buffer error', // Z_BUF_ERROR (-5)
'incompatible version', // Z_VERSION_ERROR (-6)
''
);
ZLevels: array[TZCompressionLevel] of Shortint = (
Z_NO_COMPRESSION,
Z_BEST_SPEED,
Z_DEFAULT_COMPRESSION,
Z_BEST_COMPRESSION
);
SZInvalid = 'Invalid ZStream operation!';
(*
{$L deflate.obj}
{$L inflate.obj}
{$L infblock.obj}
{$L inftrees.obj}
{$L infcodes.obj}
{$L infutil.obj}
{$L inffast.obj}
{$L trees.obj}
{$L adler32.obj}
{$L crc32.obj}
*)
{$L deflate.obj}
{$L inflate.obj}
{$L inftrees.obj}
{$L infback.obj}
{$L inffast.obj}
{$L trees.obj}
{$L adler32.obj}
{$L crc32.obj}
{$L compress.obj}
function zcalloc(opaque: Pointer; items, size: Integer): Pointer; cdecl;
begin
GetMem(result, items * size);
end;
procedure zcfree(opaque, block: Pointer); cdecl;
begin
FreeMem(block);
end;
function DeflateInit(var stream: TZStreamRec; level: Integer): Integer; cdecl;
begin
result := DeflateInit_(stream, level, PAnsiChar(ZLIB_VERSION), SizeOf(TZStreamRec));
end;
function InflateInit(var stream: TZStreamRec): Integer; cdecl;
begin
result := InflateInit_(stream, PAnsiChar(ZLIB_VERSION), SizeOf(TZStreamRec));
end;
procedure memset(P: Pointer; B: Byte; count: Integer); cdecl;
begin
FillChar(P^, count, B);
end;
// compatibility with ZipForge (3.0.4)
procedure _memset(P: Pointer; B: byte; Count: integer); cdecl;
begin
FillChar(P^, Count, B);
end;
function _memcmp(buf1, buf2: pbyte; count: integer): integer; cdecl;
begin
if count = 0 then
result := 0
else
begin
while true do
begin
dec(count);
if (count=0) or (buf1^<>buf2^) then
break;
inc(buf1);
inc(buf2);
end;
result := buf1^ - buf2^;
end;
end;
function _strtod(s: PAnsiChar; var vp: PAnsiChar): double; cdecl;
begin
vp := @s[IEStrLen(s) - 1]; // !!
result := IEStrToFloatDefA(s, 0);
end;
procedure _abort; cdecl;
begin
end;
procedure memcpy(dest, source: Pointer; count: Integer); cdecl;
begin
Move(source^, dest^, count);
end;
// Compatibility with ZipForge (3.0.4)
procedure _memcpy(dest, Source: Pointer; Count: integer); cdecl;
begin
Move(Source^, dest^, Count);
end;
function _malloc(size: Integer): Pointer; cdecl;
begin
GetMem(Result, size);
end;
procedure _free(P: Pointer); cdecl;
begin
FreeMem(P);
end;
function _fabs(v: double): double; cdecl;
begin
result := abs(v);
end;
function _pow(Base, Exponent: double): double; cdecl;
begin
if Exponent = 0.0 then
Result := 1.0 { n**0 = 1 }
else
if (Base = 0.0) and (Exponent > 0.0) then
Result := 0.0 { 0**n = 0, n > 0 }
else
if (Frac(Exponent) = 0.0) and (Abs(Exponent) <= MaxInt) then
Result := IntPower(Base, Trunc(Exponent))
else
Result := Exp(Exponent * Ln(Base))
end;
function __ftol: Integer; cdecl;
var
f: double;
begin
asm
lea eax, f // BC++ passes floats on the FPU stack
fstp qword ptr [eax] // Delphi passes floats on the CPU stack
end;
Result := Trunc(f);
end;
function _strlen(s: PAnsiChar): cardinal; cdecl;
begin
result := IEStrLen(s);
end;
var
__turboFloat: LongBool = False;
function ZCompressCheck(code: Integer): Integer;
begin
result := code;
if code < 0 then
begin
raise EZCompressionError.Create(z_errmsg[2 - code]);
end;
end;
function ZDecompressCheck(code: Integer): Integer;
begin
Result := code;
if code < 0 then
begin
raise EZDecompressionError.Create(z_errmsg[2 - code]);
end;
end;
procedure ZCompress(const inBuffer: Pointer; inSize: Integer;
out outBuffer: Pointer; out outSize: Integer;
level: TZCompressionLevel);
const
delta = 256;
var
zstream: TZStreamRec;
begin
FillChar(zstream, SizeOf(TZStreamRec), 0);
outSize := ((inSize + (inSize div 10) + 12) + 255) and not 255;
GetMem(outBuffer, outSize);
try
zstream.next_in := inBuffer;
zstream.avail_in := inSize;
zstream.next_out := outBuffer;
zstream.avail_out := outSize;
ZCompressCheck(DeflateInit(zstream, ZLevels[level]));
try
while ZCompressCheck(deflate(zstream, Z_FINISH)) <> Z_STREAM_END do
begin
Inc(outSize, delta);
ReallocMem(outBuffer, outSize);
zstream.next_out := PAnsiChar(uint64(outBuffer) + zstream.total_out);
zstream.avail_out := delta;
end;
finally
ZCompressCheck(deflateEnd(zstream));
end;
ReallocMem(outBuffer, zstream.total_out);
outSize := zstream.total_out;
except
FreeMem(outBuffer);
raise;
end;
end;
procedure IEZDecompress(const inBuffer: Pointer; inSize: Integer; out outBuffer: Pointer; out outSize: Integer; outEstimate: Integer);
begin
ZDecompress(inBuffer, inSize, outBuffer, outSize, outEstimate);
end;
procedure ZDecompress(const inBuffer: Pointer; inSize: Integer; out outBuffer: Pointer; out outSize: Integer; outEstimate: Integer);
var
zstream: TZStreamRec;
delta: Integer;
chk: Integer;
begin
FillChar(zstream, SizeOf(TZStreamRec), 0);
delta := (inSize + 255) and not 255;
if outEstimate = 0 then
outSize := delta
else
outSize := outEstimate;
GetMem(outBuffer, outSize);
try
zstream.next_in := inBuffer;
zstream.avail_in := inSize;
zstream.next_out := outBuffer;
zstream.avail_out := outSize;
ZDecompressCheck(InflateInit(zstream));
try
while true do
begin
chk := inflate(zstream, Z_NO_FLUSH);
if (chk = Z_STREAM_END) or (chk = Z_DATA_ERROR) or (chk = Z_NEED_DICT) or (chk = Z_MEM_ERROR) then
break;
ZDecompressCheck(chk); // may raise exception for the cases not covered by previous check
Inc(outSize, delta);
ReallocMem(outBuffer, outSize);
zstream.next_out := PAnsiChar(uint64(outBuffer) + zstream.total_out);
zstream.avail_out := delta;
end;
finally
ZDecompressCheck(inflateEnd(zstream));
end;
ReallocMem(outBuffer, zstream.total_out);
outSize := zstream.total_out;
except
FreeMem(outBuffer);
raise;
end;
end;
{** string routines *********************************************************}
function ZCompressStr(const s: AnsiString; level: TZCompressionLevel): AnsiString;
var
buffer: Pointer;
size: Integer;
begin
ZCompress(PAnsiChar(s), Length(s), buffer, size, level);
SetLength(result, size);
Move(buffer^, result[1], size);
FreeMem(buffer);
end;
function ZDecompressStr(const s: AnsiString): AnsiString;
var
buffer: Pointer;
size: Integer;
begin
ZDecompress(PAnsiChar(s), Length(s), buffer, size, 0);
SetLength(result, size);
Move(buffer^, result[1], size);
FreeMem(buffer);
end;
{** stream routines *********************************************************}
procedure ZCompressStream(inStream, outStream: TStream;
level: TZCompressionLevel);
const
bufferSize = 32768;
var
zstream: TZStreamRec;
zresult: Integer;
inBuffer: array[0..bufferSize - 1] of AnsiChar;
outBuffer: array[0..bufferSize - 1] of AnsiChar;
inSize: Integer;
outSize: Integer;
begin
FillChar(zstream, SizeOf(TZStreamRec), 0);
ZCompressCheck(DeflateInit(zstream, ZLevels[level]));
inSize := inStream.Read(inBuffer, bufferSize);
while inSize > 0 do
begin
zstream.next_in := inBuffer;
zstream.avail_in := inSize;
repeat
zstream.next_out := outBuffer;
zstream.avail_out := bufferSize;
ZCompressCheck(deflate(zstream, Z_NO_FLUSH));
// outSize := zstream.next_out - outBuffer;
outSize := bufferSize - zstream.avail_out;
outStream.Write(outBuffer, outSize);
until (zstream.avail_in = 0) and (zstream.avail_out > 0);
inSize := inStream.Read(inBuffer, bufferSize);
end;
repeat
zstream.next_out := outBuffer;
zstream.avail_out := bufferSize;
zresult := ZCompressCheck(deflate(zstream, Z_FINISH));
// outSize := zstream.next_out - outBuffer;
outSize := bufferSize - zstream.avail_out;
outStream.Write(outBuffer, outSize);
until (zresult = Z_STREAM_END) and (zstream.avail_out > 0);
ZCompressCheck(deflateEnd(zstream));
end;
procedure ZDecompressStream(inStream, outStream: TStream);
const
bufferSize = 32768;
var
zstream: TZStreamRec;
zresult: Integer;
inBuffer: array[0..bufferSize - 1] of AnsiChar;
outBuffer: array[0..bufferSize - 1] of AnsiChar;
inSize: Integer;
outSize: Integer;
begin
FillChar(zstream, SizeOf(TZStreamRec), 0);
ZCompressCheck(InflateInit(zstream));
inSize := inStream.Read(inBuffer, bufferSize);
while inSize > 0 do
begin
zstream.next_in := inBuffer;
zstream.avail_in := inSize;
repeat
zstream.next_out := outBuffer;
zstream.avail_out := bufferSize;
ZCompressCheck(inflate(zstream, Z_NO_FLUSH));
// outSize := zstream.next_out - outBuffer;
outSize := bufferSize - zstream.avail_out;
outStream.Write(outBuffer, outSize);
until (zstream.avail_in = 0) and (zstream.avail_out > 0);
inSize := inStream.Read(inBuffer, bufferSize);
end;
repeat
zstream.next_out := outBuffer;
zstream.avail_out := bufferSize;
zresult := ZCompressCheck(inflate(zstream, Z_FINISH));
// outSize := zstream.next_out - outBuffer;
outSize := bufferSize - zstream.avail_out;
outStream.Write(outBuffer, outSize);
until (zresult = Z_STREAM_END) and (zstream.avail_out > 0);
ZCompressCheck(inflateEnd(zstream));
end;
{** TCustomZStream **********************************************************}
constructor TCustomZStream.Create(stream: TStream);
begin
inherited Create;
FStream := stream;
FStreamPos := stream.Position;
end;
procedure TCustomZStream.DoProgress;
begin
if Assigned(FOnProgress) then
FOnProgress(Self);
end;
{** TZCompressionStream *****************************************************}
// windowBits = not used
constructor TZCompressionStream.Create(dest: TStream; compressionLevel: TZCompressionLevel; windowBits: integer);
begin
inherited Create(dest);
FZStream.next_out := FBuffer;
FZStream.avail_out := SizeOf(FBuffer);
ZCompressCheck(DeflateInit(FZStream, ZLevels[compressionLevel]));
end;
destructor TZCompressionStream.Destroy;
begin
FZStream.next_in := nil;
FZStream.avail_in := 0;
try
if FStream.Position <> FStreamPos then
FStream.Position := FStreamPos;
while ZCompressCheck(deflate(FZStream, Z_FINISH)) <> Z_STREAM_END do
begin
FStream.WriteBuffer(FBuffer, SizeOf(FBuffer) - FZStream.avail_out);
FZStream.next_out := FBuffer;
FZStream.avail_out := SizeOf(FBuffer);
end;
if FZStream.avail_out < SizeOf(FBuffer) then
begin
FStream.WriteBuffer(FBuffer, SizeOf(FBuffer) - FZStream.avail_out);
end;
finally
deflateEnd(FZStream);
end;
inherited Destroy;
end;
function TZCompressionStream.Read(var buffer; count: Longint): Longint;
begin
raise EZCompressionError.Create(SZInvalid);
end;
function TZCompressionStream.Write(const buffer; count: Longint): Longint;
begin
FZStream.next_in := @buffer;
FZStream.avail_in := count;
if FStream.Position <> FStreamPos then
FStream.Position := FStreamPos;
while FZStream.avail_in > 0 do
begin
ZCompressCheck(deflate(FZStream, Z_NO_FLUSH));
if FZStream.avail_out = 0 then
begin
FStream.WriteBuffer(FBuffer, SizeOf(FBuffer));
FZStream.next_out := FBuffer;
FZStream.avail_out := SizeOf(FBuffer);
FStreamPos := FStream.Position;
DoProgress;
end;
end;
result := Count;
end;
// 3.0.1
function TZCompressionStream.Seek(offset: Longint; origin: Word): Longint;
begin
result := FZStream.total_in;
end;
function TZCompressionStream.GetCompressionRate: Single;
begin
if FZStream.total_in = 0 then
result := 0
else
result := (1.0 - (FZStream.total_out / FZStream.total_in)) * 100.0;
end;
{** TZDecompressionStream ***************************************************}
constructor TZDecompressionStream.Create(source: TStream);
begin
inherited Create(source);
FZStream.next_in := FBuffer;
FZStream.avail_in := 0;
ZDecompressCheck(InflateInit(FZStream));
end;
destructor TZDecompressionStream.Destroy;
begin
inflateEnd(FZStream);
inherited Destroy;
end;
function TZDecompressionStream.Read(var buffer; count: Longint): Longint;
var
zresult: Integer;
begin
FZStream.next_out := @buffer;
FZStream.avail_out := count;
if FStream.Position <> FStreamPos then
FStream.Position := FStreamPos;
zresult := Z_OK;
while (FZStream.avail_out > 0) and (zresult <> Z_STREAM_END) do
begin
if FZStream.avail_in = 0 then
begin
FZStream.avail_in := FStream.Read(FBuffer, SizeOf(FBuffer));
if FZStream.avail_in = 0 then
begin
result := count - FZStream.avail_out;
Exit;
end;
FZStream.next_in := FBuffer;
FStreamPos := FStream.Position;
DoProgress;
end;
zresult := ZDecompressCheck(inflate(FZStream, Z_NO_FLUSH));
end;
if (zresult = Z_STREAM_END) and (FZStream.avail_in > 0) then
begin
FStream.Position := FStream.Position - FZStream.avail_in;
FStreamPos := FStream.Position;
FZStream.avail_in := 0;
end;
result := count - FZStream.avail_out;
end;
function TZDecompressionStream.Write(const Buffer; Count: Longint): Longint;
begin
raise EZDecompressionError.Create(SZInvalid);
end;
function TZDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
var
buf: array[0..8191] of AnsiChar;
i: Integer;
begin
if (offset = 0) and (origin = soFromBeginning) then
begin
ZDecompressCheck(inflateReset(FZStream));
FZStream.next_in := FBuffer;
FZStream.avail_in := 0;
FStream.Position := 0;
FStreamPos := 0;
end
else
if ((offset >= 0) and (origin = soFromCurrent)) or
(((offset - FZStream.total_out) > 0) and (origin = soFromBeginning)) then
begin
if origin = soFromBeginning then
Dec(offset, FZStream.total_out);
if offset > 0 then
begin
for i := 1 to offset div SizeOf(buf) do
ReadBuffer(buf, SizeOf(buf));
ReadBuffer(buf, offset mod SizeOf(buf));
end;
end
else
if (offset = 0) and (origin = soFromEnd) then
begin
while Read(buf, SizeOf(buf)) > 0 do
;
end
else
raise EZDecompressionError.Create(SZInvalid);
result := FZStream.total_out;
end;
{$else} // IEINCLUDEZLIB
interface
uses
Windows, Graphics, classes, sysutils, ImageEnProc, ImageEnIO, hyiedefs, hyieutils;
type
TZCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax);
TZCompressionStream = class(TStream)
private
fDest: TStream;
public
constructor Create(dest: TStream; compressionLevel: TZCompressionLevel; windowBits: integer = 15);
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;
end;
TZDecompressionStream = class(TStream)
private
fSource: TStream;
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;
end;
implementation
constructor TZCompressionStream.Create(dest: TStream; compressionLevel: TZCompressionLevel; windowBits: integer = 15);
begin
inherited Create;
fDest := dest;
end;
destructor TZCompressionStream.Destroy;
begin
inherited;
end;
function TZCompressionStream.Read(var buffer; count: Longint): Longint;
begin
result := fDest.Read(buffer, count);
end;
function TZCompressionStream.Write(const buffer; count: Longint): Longint;
begin
result := fDest.Write(buffer, count);
end;
function TZCompressionStream.Seek(offset: Longint; origin: Word): Longint;
begin
result := fDest.Seek(offset, origin);
end;
///////////////////
constructor TZDecompressionStream.Create(source: TStream);
begin
inherited Create;
fSource := source;
end;
destructor TZDecompressionStream.Destroy;
begin
inherited;
end;
function TZDecompressionStream.Read(var buffer; count: Longint): Longint;
begin
result := fSource.Read(buffer, count);
end;
function TZDecompressionStream.Write(const buffer; count: Longint): Longint;
begin
result := fSource.Write(buffer, count);
end;
function TZDecompressionStream.Seek(offset: Longint; origin: Word): Longint;
begin
result := fSource.Seek(offset, origin);
end;
{$endif} // IEINCLUDEZLIB
{$else} // IEUSEVCLZLIB
interface
procedure IEZDecompress(const inBuffer: Pointer; inSize: Integer; out outBuffer: Pointer; out outSize: Integer; outEstimate: Integer);
implementation
uses zlib;
function ZDecompressCheck(code: Integer): Integer;
begin
Result := code;
if code < 0 then
begin
raise EZDecompressionError.Create('Error');
end;
end;
procedure IEZDecompress(const inBuffer: Pointer; inSize: Integer; out outBuffer: Pointer; out outSize: Integer; outEstimate: Integer);
var
zstream: TZStreamRec;
delta: Integer;
chk: Integer;
begin
FillChar(zstream, SizeOf(TZStreamRec), 0);
delta := (inSize + 255) and not 255;
if outEstimate = 0 then
outSize := delta
else
outSize := outEstimate;
GetMem(outBuffer, outSize);
try
zstream.next_in := inBuffer;
zstream.avail_in := inSize;
zstream.next_out := outBuffer;
zstream.avail_out := outSize;
ZDecompressCheck(InflateInit(zstream));
try
while true do
begin
chk := inflate(zstream, Z_NO_FLUSH);
if (chk = Z_STREAM_END) or (chk = Z_DATA_ERROR) or (chk = Z_NEED_DICT) or (chk = Z_MEM_ERROR) then
break;
ZDecompressCheck(chk); // may raise exception for the cases not covered by previous check
Inc(outSize, delta);
ReallocMem(outBuffer, outSize);
zstream.next_out := PByte(uint64(outBuffer) + zstream.total_out);
zstream.avail_out := delta;
end;
finally
ZDecompressCheck(inflateEnd(zstream));
end;
ReallocMem(outBuffer, zstream.total_out);
outSize := zstream.total_out;
except
FreeMem(outBuffer);
raise;
end;
end;
{$endif} // IEUSEVCLZLIB
end.