sp; to the end of InStr, placing the compressed output in OutStr starting at OutStr''''s current position. If you need the entirety of InStr compressed you''''ll need to set InStr.Position := 0 before calling. *) procedure LHAExpand(InStr, OutStr: TStream); (* LHAExpand starts expanding at InStr''''s current position and continues to the end of InStr, placing the expanded output in OutStr starting at OutStr''''s current position. If you need the entirety of InStr expanded you''''ll need to set InStr.Position := 0 before calling. *)
implementation
TYPE {$IFDEF WIN32} TwoByteInt = SmallInt; {$ELSE} TwoByteInt = Integer; {$ENDIF} PWord=^TWord; TWord=ARRAY[0..32759]OF TwoByteInt; PByte=^TByte; TByte=ARRAY[0..65519]OF Byte;
CONST (* NOTE : The following constants are set to the values used by LHArc. You can change three of them as follows :
DICBIT : Lempel-Ziv dictionnary size. Lowering this constant can lower the compression efficiency a lot ! But increasing it (on a 32 bit platform only, i.e. Delphi 2) will not yield noticeably better results. If you set DICBIT to 15 or more, set PBIT to 5; and if you set DICBIT to 19 or more, set NPT to NP, too.
WINBIT : Sliding window size. The compression ratio depends a lot of this value. You can increase it to 15 to get better results on large files. I recommend doing this if you have enough memory, except if you want that your compressed data remain compatible with LHArc. On a 32 bit platform, you can increase it to 16. Using a larger value will only waste time and memory.
BUFBIT : I/O Buffer size. You can lower it to save memory, or increase it to reduce disk access. *)
BITBUFSIZ=16; UCHARMAX=255;
DICBIT=13; DICSIZ=1 SHL DICBIT;
MATCHBIT=8; MAXMATCH=1 SHL MATCHBIT; THRESHOLD=3; PERCFLAG=$8000;
NC=(UCHARMAX+MAXMATCH+2-THRESHOLD); CBIT=9; CODEBIT=16;
NP=DICBIT+1; NT=CODEBIT+3; PBIT=4; {Log2(NP)} TBIT=5; {Log2(NT)} NPT=NT; {Greater from NP and NT}
NUL=0; MAXHASHVAL=(3*DICSIZ+(DICSIZ SHR 9+1)*UCHARMAX);
WINBIT=14; WINDOWSIZE=1 SHL WINBIT;
BUFBIT=13; BUFSIZE=1 SHL BUFBIT;
TYPE BufferArray = ARRAY[0..PRED(BUFSIZE)]OF Byte; LeftRightArray = ARRAY[0..2*(NC-1)]OF Word; CTableArray = ARRAY[0..4095]OF Word; CLenArray = ARRAY[0..PRED(NC)]OF Byte; HeapArray = ARRAY[0..NC]OF Word;
VAR OrigSize,CompSize:Longint; InFile,OutFile:TStream;
BitBuf:Word; n,HeapSize:TwoByteInt; SubBitBuf,BitCount:Word;
Buffer:^BufferArray; BufPtr:Word;
Left,Right:^LeftRightArray;
PtTable:ARRAY[0..255]OF Word; PtLen:ARRAY[0..PRED(NPT)]OF Byte; CTable:^CTableArray; CLen:^CLenArray;
BlockSize:Word;
{ The following variables are used by the compression engine only }
Heap:^HeapArray; LenCnt:ARRAY[0..16]OF Word;
Freq,SortPtr:PWord; Len:PByte; Depth:Word;
Buf:PByte;
CFreq:ARRAY[0..2*(NC-1)]OF Word; PFreq:ARRAY[0..2*(NP-1)]OF Word; TFreq:ARRAY[0..2*(NT-1)]OF Word;
CCode:ARRAY[0..PRED(NC)]OF Word; PtCode:ARRAY[0..PRED(NPT)]OF Word;
CPos,OutputPos,OutputMask:Word; Text,ChildCount:PByte;
Pos,MatchPos,Avail:Word; Position,Parent,Prev,Next:PWord;
Remainder,MatchLen:TwoByteInt; Level:PByte;
{********************************** File I/O **********************************}
FUNCTION GetC:Byte; BEGIN IF BufPtr=0 THEN InFile.Read(Buffer^,BUFSIZE); GetC:=Buffer^[BufPtr];BufPtr:=SUCC(BufPtr)AND PRED(BUFSIZE); END;
PROCEDURE PutC(c:Byte); BEGIN IF BufPtr=BUFSIZE THEN BEGIN OutFile.Write(Buffer^,BUFSIZE);BufPtr:=0; END; Buffer^[BufPtr]:=C;INC(BufPtr); END;
FUNCTION BRead(p:POINTER;n:TwoByteInt):TwoByteInt; BEGIN BRead := InFile.Read(p^,n); END;
PROCEDURE BWrite(p:POINTER;n:TwoByteInt); BEGIN OutFile.Write(p^,n); END;
{**************************** Bit handling routines ***************************}
PROCEDURE FillBuf(n:TwoByteInt); BEGIN BitBuf:=(BitBuf SHL n); WHILE n>BitCount DO BEGIN DEC(n,BitCount); BitBuf:=BitBuf OR (SubBitBuf SHL n); IF (CompSize<>0) THEN BEGIN DEC(CompSize);SubBitBuf:=GetC; END ELSE SubBitBuf:=0; BitCount:=8; END; DEC(BitCount,n); BitBuf:=BitBuf OR (SubBitBuf SHR BitCount); END;
FUNCTION GetBits(n:TwoByteInt):Word; BEGIN GetBits:=BitBuf SHR (BITBUFSIZ-n); FillBuf(n); END;
PROCEDURE PutBits(n:TwoByteInt;x:Word); BEGIN IF n<BitCount THEN BEGIN DEC(BitCount,n); SubBitBuf:=SubBitBuf OR (x SHL BitCount); END ELSE BEGIN DEC(n,BitCount); PutC(SubBitBuf OR (x SHR n));INC(CompSize); IF n<8 THEN BEGIN BitCount:=8-n;SubBitBuf:=x SHL BitCount; END ELSE BEGIN PutC(x SHR (n-8));INC(CompSize); BitCount:=16-n;SubBitBuf:=x SHL BitCount; END; END; END;
PROCEDURE InitGetBits; BEGIN BitBuf:=0;SubBitBuf:=0;BitCount:=0;FillBuf(BITBUFSIZ); END;
PROCEDURE InitPutBits; BEGIN BitCount:=8;SubBitBuf:=0; END;
{******************************** Decompression *******************************}
PROCEDURE MakeTable(nchar:TwoByteInt;BitLen:PByte;TableBits:TwoByteInt;Table:PWord); VAR count,weight:ARRAY[1..16]OF Word; start:ARRAY[1..17]OF Word; p:PWord; i,k,Len,ch,jutbits,Avail,nextCode,mask:TwoByteInt; BEGIN FOR i:=1 TO 16 DO count[i]:=0; FOR i:=0 TO PRED(nchar) DO INC(count[BitLen^[i]]); start[1]:=0; FOR i:=1 TO 16 DO start[SUCC(i)]:=start[i]+(count[i] SHL (16-i)); IF start[17]<>0 THEN HALT(1); jutbits:=16-TableBits; FOR i:=1 TO TableBits DO BEGIN start[i]:=start[i] SHR jutbits;weight[i]:=1 SHL (TableBits-i); END; i:=SUCC(TableBits); WHILE (i<=16) DO BEGIN weight[i]:=1 SHL (16-i);INC(i); END; i:=start[SUCC(TableBits)] SHR jutbits; IF i<>0 THEN BEGIN k:=1 SHL TableBits; WHILE i<>k DO BEGIN Table^[i]:=0;INC(i); END; END; Avail:=nchar;mask:=1 SHL (15-TableBits); FOR ch:=0 TO PRED(nchar) DO BEGIN Len:=BitLen^[ch]; IF Len=0 THEN   上一页 [1] [2] [3] [4] [5] [6] [7] 下一页 |