kolmck/Addons/ULZInWindow.pas
dkolmck 8a71ebf5bc addons update
git-svn-id: https://svn.code.sf.net/p/kolmck/code@67 91bb2d04-0c0c-4d2d-88a5-bbb6f4c1fa07
2010-10-04 12:58:59 +00:00

171 lines
4.8 KiB
ObjectPascal

unit ULZInWindow;
{$IFDEF FPC}
{$MODE Delphi}
{$ENDIF}
interface
uses KOL;
type TLZInWindow= object(TObj)
public
bufferBase: array of byte;// pointer to buffer with data
stream:PStream;
posLimit:integer; // offset (from _buffer) of first byte when new block reading must be done
streamEndWasReached:boolean; // if (true) then _streamPos shows real end of stream
pointerToLastSafePosition:integer;
bufferOffset:integer;
blockSize:integer; // Size of Allocated memory block
pos:integer; // offset (from _buffer) of curent byte
keepSizeBefore:integer; // how many BYTEs must be kept in buffer before _pos
keepSizeAfter:integer; // how many BYTEs must be kept buffer after _pos
streamPos:integer; // offset (from _buffer) of first not read byte from Stream
procedure MoveBlock;
procedure ReadBlock;
procedure _Free;
procedure _Create(const AkeepSizeBefore, AkeepSizeAfter, AkeepSizeReserv:integer);
procedure SetStream(const Astream:PStream);
procedure ReleaseStream;
procedure _Init;virtual;
procedure MovePos;virtual;
function GetIndexByte(const Aindex:integer):byte;
// index + limit have not to exceed _keepSizeAfter;
function GetMatchLen(const Aindex:integer;Adistance,Alimit:integer):integer;
function GetNumAvailableBytes:integer;
procedure ReduceOffsets(const AsubValue:integer);
end;
implementation
procedure TLZInWindow.MoveBlock;
var offset,numbytes,i:integer;
begin
offset := bufferOffset + pos - keepSizeBefore;
// we need one additional byte, since MovePos moves on 1 byte.
if (offset > 0) then
dec(offset);
numBytes := bufferOffset + streamPos - offset;
// check negative offset ????
for i := 0 to numBytes -1 do
bufferBase[i] := bufferBase[offset + i];
bufferOffset := bufferOffset - offset;
end;
procedure TLZInWindow.ReadBlock;
var size,numreadbytes,pointerToPostion:integer;
begin
if streamEndWasReached then
exit;
while (true) do begin
size := (0 - bufferOffset) + blockSize - streamPos;
if size = 0 then
exit;
numReadBytes := stream.Read(bufferBase[bufferOffset + streamPos], size);
if (numReadBytes = 0) then begin
posLimit := streamPos;
pointerToPostion := bufferOffset + posLimit;
if (pointerToPostion > pointerToLastSafePosition) then
posLimit := pointerToLastSafePosition - bufferOffset;
streamEndWasReached := true;
exit;
end;
streamPos := streamPos + numReadBytes;
if (streamPos >= pos + keepSizeAfter) then
posLimit := streamPos - keepSizeAfter;
end;
end;
procedure TLZInWindow._Free;
begin
setlength(bufferBase,0);
end;
procedure TLZInWindow._Create(const AkeepSizeBefore, AkeepSizeAfter, AkeepSizeReserv:integer);
var _blocksize:integer;
begin
self.keepSizeBefore := AkeepSizeBefore;
self.keepSizeAfter := AkeepSizeAfter;
_blocksize := AkeepSizeBefore + AkeepSizeAfter + AkeepSizeReserv;
if (length(bufferBase) = 0) or (self.blockSize <> _blocksize) then begin
_Free;
self.blockSize := _blocksize;
setlength(bufferBase,self.blockSize);
end;
pointerToLastSafePosition := self.blockSize - AkeepSizeAfter;
end;
procedure TLZInWindow.SetStream(const Astream:PStream);
begin
self.stream:=Astream;
end;
procedure TLZInWindow.ReleaseStream;
begin
stream:=nil;
end;
procedure TLZInWindow._Init;
begin
bufferOffset := 0;
pos := 0;
streamPos := 0;
streamEndWasReached := false;
ReadBlock;
end;
procedure TLZInWindow.MovePos;
var pointerToPostion:integer;
begin
inc(pos);
if pos > posLimit then begin
pointerToPostion := bufferOffset + pos;
if pointerToPostion > pointerToLastSafePosition then
MoveBlock;
ReadBlock;
end;
end;
function TLZInWindow.GetIndexByte(const Aindex:integer):byte;
begin
result:=bufferBase[bufferOffset + pos + Aindex];
end;
function TLZInWindow.GetMatchLen(const Aindex:integer;Adistance,Alimit:integer):integer;
var pby,i:integer;
begin
if streamEndWasReached then
if (pos + Aindex) + Alimit > streamPos then
Alimit := streamPos - (pos + Aindex);
inc(Adistance);
// Byte *pby = _buffer + (size_t)_pos + Aindex;
pby := bufferOffset + pos + Aindex;
i:=0;
while (i<Alimit)and(bufferBase[pby + i] = bufferBase[pby + i - Adistance]) do begin
inc(i);
end;
result:=i;
end;
function TLZInWindow.GetNumAvailableBytes:integer;
begin
result:=streamPos - pos;
end;
procedure TLZInWindow.ReduceOffsets(const Asubvalue:integer);
begin
bufferOffset := bufferOffset + Asubvalue;
posLimit := posLimit - Asubvalue;
pos := pos - Asubvalue;
streamPos := streamPos - Asubvalue;
end;
end.