?? vs_compress.pas
字號:
{ TDecompressionStream decompresses data on the fly as data is read from it.
Compressed data comes from a separate source stream. TDecompressionStream
is read-only and unidirectional; you can seek forward in the stream, but not
backwards. The special case of setting the stream position to zero is
allowed. Seeking forward decompresses data until the requested position in
the uncompressed data has been reached. Seeking backwards, seeking relative
to the end of the stream, requesting the size of the stream, and writing to
the stream will raise an exception.
The Position property returns the number of bytes of uncompressed data that
have been read from the stream so far.
The OnProgress event is called each time the internal input buffer of
compressed data is exhausted and the next block is read from the input stream.
This is useful for updating a progress indicator when you are reading a
large chunk of data from the decompression stream in a single call.}
TDecompressionStream = class(TCustomZlibStream)
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;
{ CompressBuf compresses data, buffer to buffer, in one call.
In: InBuf = ptr to compressed data
InBytes = number of bytes in InBuf
Out: OutBuf = ptr to newly allocated buffer containing decompressed data
OutBytes = number of bytes in OutBuf }
procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
out OutBuf: Pointer; out OutBytes: Integer);
{ DecompressBuf decompresses data, buffer to buffer, in one call.
In: InBuf = ptr to compressed data
InBytes = number of bytes in InBuf
OutEstimate = zero, or est. size of the decompressed data
Out: OutBuf = ptr to newly allocated buffer containing decompressed data
OutBytes = number of bytes in OutBuf }
procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
type
EZlibError = class(Exception);
ECompressionError = class(EZlibError);
EDecompressionError = class(EZlibError);
implementation {===============================================================}
{ZKsUtil}
{$IFDEF CALLDOS}
{ reduce your application memory footprint with $M before using this }
function dosAlloc (Size : Longint) : Pointer;
var
regs: TRegisters;
begin
regs.bx := (Size + 15) div 16; { number of 16-bytes-paragraphs }
regs.ah := $48; { Allocate memory block }
msdos(regs);
if regs.Flags and FCarry <> 0 then
DosAlloc := NIL
else
DosAlloc := Ptr(regs.ax, 0);
end;
function dosFree(P : pointer) : boolean;
var
regs: TRegisters;
begin
dosFree := FALSE;
regs.bx := Seg(P^); { segment }
if Ofs(P) <> 0 then
exit;
regs.ah := $49; { Free memory block }
msdos(regs);
dosFree := (regs.Flags and FCarry = 0);
end;
{$ENDIF}
type
LH = record
L, H : word;
end;
{$IFDEF HugeMem}
{$define HEAP_LIST}
{$endif}
{$IFDEF HEAP_LIST} {--- to avoid Mark and Release --- }
const
MaxAllocEntries = 50;
type
TMemRec = record
orgvalue,
value : pointer;
size: longint;
end;
const
allocatedCount : 0..MaxAllocEntries = 0;
var
allocatedList : array[0..MaxAllocEntries-1] of TMemRec;
function NewAllocation(ptr0, ptr : pointer; memsize : longint) : boolean;
begin
if (allocatedCount < MaxAllocEntries) and (ptr0 <> NIL) then
begin
with allocatedList[allocatedCount] do
begin
orgvalue := ptr0;
value := ptr;
size := memsize;
end;
Inc(allocatedCount); { we don't check for duplicate }
NewAllocation := TRUE;
end
else
NewAllocation := FALSE;
end;
{$ENDIF}
{$IFDEF HugeMem}
{ The code below is extremely version specific to the TP 6/7 heap manager!!}
type
PFreeRec = ^TFreeRec;
TFreeRec = record
next: PFreeRec;
size: Pointer;
end;
type
HugePtr = voidpf;
procedure IncPtr(var p:pointer;count:word);
{ Increments pointer }
begin
inc(LH(p).L,count);
if LH(p).L < count then
inc(LH(p).H,SelectorInc); { $1000 }
end;
procedure DecPtr(var p:pointer;count:word);
{ decrements pointer }
begin
if count > LH(p).L then
dec(LH(p).H,SelectorInc);
dec(LH(p).L,Count);
end;
procedure IncPtrLong(var p:pointer;count:longint);
{ Increments pointer; assumes count > 0 }
begin
inc(LH(p).H,SelectorInc*LH(count).H);
inc(LH(p).L,LH(Count).L);
if LH(p).L < LH(count).L then
inc(LH(p).H,SelectorInc);
end;
procedure DecPtrLong(var p:pointer;count:longint);
{ Decrements pointer; assumes count > 0 }
begin
if LH(count).L > LH(p).L then
dec(LH(p).H,SelectorInc);
dec(LH(p).L,LH(Count).L);
dec(LH(p).H,SelectorInc*LH(Count).H);
end;
{ The next section is for real mode only }
function Normalized(p : pointer) : pointer;
var
count : word;
begin
count := LH(p).L and $FFF0;
Normalized := Ptr(LH(p).H + (count shr 4), LH(p).L and $F);
end;
procedure FreeHuge(var p:HugePtr; size : longint);
const
blocksize = $FFF0;
var
block : word;
begin
while size > 0 do
begin
{ block := minimum(size, blocksize); }
if size > blocksize then
block := blocksize
else
block := size;
dec(size,block);
freemem(p,block);
IncPtr(p,block); { we may get ptr($xxxx, $fff8) and 31 bytes left }
p := Normalized(p); { to free, so we must normalize }
end;
end;
function FreeMemHuge(ptr : pointer) : boolean;
var
i : integer; { -1..MaxAllocEntries }
begin
FreeMemHuge := FALSE;
i := allocatedCount - 1;
while (i >= 0) do
begin
if (ptr = allocatedList[i].value) then
begin
with allocatedList[i] do
FreeHuge(orgvalue, size);
Move(allocatedList[i+1], allocatedList[i],
SizeOf(TMemRec)*(allocatedCount - 1 - i));
Dec(allocatedCount);
FreeMemHuge := TRUE;
break;
end;
Dec(i);
end;
end;
procedure GetMemHuge(var p:HugePtr;memsize:Longint);
const
blocksize = $FFF0;
var
size : longint;
prev,free : PFreeRec;
save,temp : pointer;
block : word;
begin
p := NIL;
{ Handle the easy cases first }
if memsize > maxavail then
exit
else
if memsize <= blocksize then
begin
getmem(p, memsize);
if not NewAllocation(p, p, memsize) then
begin
FreeMem(p, memsize);
p := NIL;
end;
end
else
begin
size := memsize + 15;
{ Find the block that has enough space }
prev := PFreeRec(@freeList);
free := prev^.next;
while (free <> heapptr) and (ptr2int(free^.size) < size) do
begin
prev := free;
free := prev^.next;
end;
{ Now free points to a region with enough space; make it the first one and
multiple allocations will be contiguous. }
save := freelist;
freelist := free;
{ In TP 6, this works; check against other heap managers }
while size > 0 do
begin
{ block := minimum(size, blocksize); }
if size > blocksize then
block := blocksize
else
block := size;
dec(size,block);
getmem(temp,block);
end;
{ We've got what we want now; just sort things out and restore the
free list to normal }
p := free;
if prev^.next <> freelist then
begin
prev^.next := freelist;
freelist := save;
end;
if (p <> NIL) then
begin
{ return pointer with 0 offset }
temp := p;
if Ofs(p^)<>0 Then
p := Ptr(Seg(p^)+1,0); { hack }
if not NewAllocation(temp, p, memsize + 15) then
begin
FreeHuge(temp, size);
p := NIL;
end;
end;
end;
end;
{$ENDIF}
procedure zmemcpy(destp : pBytef; sourcep : pBytef; len : uInt);
begin
Move(sourcep^, destp^, len);
end;
function zmemcmp(s1p, s2p : pBytef; len : uInt) : int;
var
j : uInt;
source,
dest : pBytef;
begin
source := s1p;
dest := s2p;
for j := 0 to pred(len) do
begin
if (source^ <> dest^) then
begin
zmemcmp := 2*Ord(source^ > dest^)-1;
exit;
end;
Inc(source);
Inc(dest);
end;
zmemcmp := 0;
end;
procedure zmemzero(destp : pBytef; len : uInt);
begin
FillChar(destp^, len, 0);
end;
procedure zcfree(opaque : voidpf; ptr : voidpf);
{$ifdef Delphi16}
var
Handle : THand
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -