home *** CD-ROM | disk | FTP | other *** search
-
- Unit LZSSUnit;
- {
- LZSSUNIT - Compress and uncompress unit using LZ77 algorithm for
- Borland (Turbo) Pascal version 7.0.
-
- Assembler Programmer: Andy Tam, Pascal Conversion: Douglas Webb,
- Unit Conversion and Dynamic Memory Allocation: Andrew Eigus.
-
- Public Domain version 1.02, last changed on 30.11.94.
- Target platforms: DOS, DPMI, Windows.
-
- Written by Andrew Eigus (aka: Mr. Byte) of:
- Fidonet: 2:5100/33,
- Internet: aeigus@fgate.castle.riga.lv, aeigus@kristin.cclu.lv.
- }
-
- interface
-
- {#Z+}
- { This unit is ready for use with Dj. Murdoch's ScanHelp utility which
- will make a Borland .TPH file for it. }
- {#Z-}
-
- const
- LZRWBufSize = 8192; { Read buffer size }
-
- {#Z+}
- N = 4096; { Bigger N -> Better compression on big files only. }
- F = 18;
- Threshold = 2;
- Nul = N * 2;
- InBufPtr : word = LZRWBufSize;
- InBufSize : word = LZRWBufSize;
- OutBufPtr : word = 0;
- {#Z-}
-
- type
- {#X TWriteProc}{#X LZSquash}{#X LZUnsquash}
-
- TReadProc = function(var ReadBuf; var NumRead : word) : word;
- { This is declaration for custom read function. It should read
- #LZRWBufSize# bytes from ReadBuf. The return value is ignored. }
-
- {#X TReadProc}{#X LZSquash}{#X LZUnsquash}
- TWriteProc = function(var WriteBuf; Count : word; var NumWritten : word) :
- word; { This is declaration for custom write function. It should write
- Count bytes into WriteBuf and return number of actual bytes written
- into NumWritten variable. The return value is ignored. }
-
- {#Z+}
- PLZRWBuffer = ^TLZRWBuffer;
- TLZRWBuffer = array[0..LZRWBufSize - 1] of Byte; { file buffers }
-
- PLZTextBuf = ^TLZTextBuf;
- TLZTextBuf = array[0..N + F - 2] of Byte;
-
- PLeftMomTree = ^TLeftMomTree;
- TLeftMomTree = array[0..N] of Word;
- PRightTree = ^TRightTree;
- TRightTree = array[0..N + 256] of Word;
-
- const
- LZSSMemRequired = SizeOf(TLZRWBuffer) * 2 +
- SizeOf(TLZTextBuf) + SizeOf(TLeftMomTree) * 2 + SizeOf(TRightTree);
- {#Z-}
-
- function LZInit : boolean;
- { This function should be called before any other compression routines
- from this unit - it allocates memory and initializes all internal
- variables required by compression procedures. If allocation fails,
- LZInit returns False, this means that there isn't enough memory for
- compression or decompression process. It returns True if initialization
- was successful. }
- {#X LZDone}{#X LZSquash}{#X LZUnsquash}
-
- procedure LZSquash(ReadProc : TReadProc; WriteProc : TWriteProc);
- { This procedure is used for compression. ReadProc specifies custom
- read function that reads data, and WriteProc specifies custom write
- function that writes compressed data. }
- {#X LZUnsquash}{#X LZInit}{#X LZDone}
-
- procedure LZUnSquash(ReadProc : TReadProc; WriteProc : TWriteProc);
- { This procedure is used for decompression. ReadProc specifies custom
- read function that reads compressed data, and WriteProc specifies
- custom write function that writes decompressed data. }
- {#X LZSquash}{#X LZInit}{#X LZDone}
-
- procedure LZDone;
- { This procedure should be called after you finished compression or
- decompression. It deallocates (frees) all memory allocated by LZInit.
- Note: You should always call LZDone after you finished using compression
- routines from this unit. }
- {#X LZInit}{#X LZSquash}{#X LZUnsquash}
-
- implementation
-
- var
- Height, MatchPos, MatchLen, LastLen : word;
- TextBufP : PLZTextBuf;
- LeftP, MomP : PLeftMomTree;
- RightP : PRightTree;
- CodeBuf : array[0..16] of Byte;
- LZReadProc : TReadProc;
- LZWriteProc : TWriteProc;
- InBufP, OutBufP : PLZRWBuffer;
- Bytes : word;
- Initialized : boolean;
-
- Function LZSS_Read : word; { Returns # of bytes read }
- Begin
- LZReadProc(InBufP^, Bytes);
- LZSS_Read := Bytes;
- End; { LZSS_Read }
-
- Function LZSS_Write : word; { Returns # of bytes written }
- Begin
- LZWriteProc(OutBufP^, OutBufPtr, Bytes);
- LZSS_Write := Bytes
- End; { LZSS_Write }
-
- Procedure Getc; assembler;
- Asm
- {
- getc : return a character from the buffer
- RETURN : AL = input char
- Carry set when EOF
- }
- push bx
- mov bx, inBufPtr
- cmp bx, inBufSize
- jb @getc1
- push cx
- push dx
- push di
- push si
- call LZSS_Read
- pop si
- pop di
- pop dx
- pop cx
- mov inBufSize, ax
- or ax, ax
- jz @getc2 { ; EOF }
- xor bx, bx
- @getc1:
- PUSH DI
- LES DI,[InBufP]
- MOV AL,BYTE PTR [ES:DI+BX]
- POP DI
- inc bx
- mov inBufPtr, bx
- pop bx
- clc { ; clear the carry flag }
- jmp @end
- @getc2: pop bx
- stc { ; set carry to indicate EOF }
- @end:
- End; { Getc }
-
- Procedure Putc; assembler;
- {
- putc : put a character into the output buffer
- Entry : AL = output char
- }
- Asm
- push bx
- mov bx, outBufPtr
- PUSH DI
- LES DI,[OutBufP]
- MOV BYTE PTR [ES:DI+BX],AL
- POP DI
- inc bx
- cmp bx, LZRWBufSize
- jb @putc1
- mov OutBufPtr,LZRWBufSize { Just so the flush will work. }
- push cx
- push dx
- push di
- push si
- call LZSS_Write
- pop si
- pop di
- pop dx
- pop cx
- xor bx, bx
- @putc1: mov outBufPtr, bx
- pop bx
- End; { Putc }
-
- Procedure InitTree; assembler;
- {
- initTree : initialize all binary search trees. There are 256 BST's, one
- for all strings started with a particular character. The
- parent is tree K is the node N + K + 1 and it has only a
- right child
- }
- Asm
- cld
- push ds
- pop es
- LES DI,[RightP]
- { mov di,offset right}
- add di, (N + 1) * 2
- mov cx, 256
- mov ax, NUL
- rep stosw
- LES DI,[MomP]
- { mov di, offset mom}
- mov cx, N
- rep stosw
- End; { InitTree }
-
- Procedure Splay; assembler;
- {
- splay : use splay tree operations to move the node to the 'top' of
- tree. Note that it will not actual become the root of the tree
- because the root of each tree is a special node. Instead, it
- will become the right child of this special node.
-
- ENTRY : di = the node to be rotated
- }
- Asm
- @Splay1:
- PUSH BX
- LES BX,[MomP]
- MOV SI,[ES:BX+DI]
- POP BX
- { mov si, [Offset Mom + di]}
- cmp si, NUL { ; exit if its parent is a special
- node } ja @Splay4
- PUSH DI
- LES DI,[MomP]
- ADD DI,SI
- MOV BX,[ES:DI]
- { mov bx, [Offset Mom + si]}
- POP DI
- cmp bx, NUL { ; check if its grandparent is special
- } jbe @Splay5 { ; if not then skip }
- PUSH BX
- LES BX,[LeftP]
- CMP DI,[ES:BX+SI]
- POP BX
- { cmp di, [Offset Left + si]} { ; is the current node is a
- left child ? } jne @Splay2
- PUSH BX
- LES BX,[RightP]
- MOV DX,[ES:BX+DI]
- { mov dx, [Offset Right + di]} { ; perform a left zig
- operation } LES BX,[LeftP]
- MOV [ES:BX+SI],DX
- { mov [Offset Left + si], dx}
- LES BX,[RightP]
- MOV [ES:BX+DI],SI
- POP BX
- { mov [Offset Right + di], si}
- jmp @Splay3
- @Splay2:
- PUSH BX
- LES BX,[LeftP]
- MOV DX,[ES:BX+DI]
- { mov dx, [Offset Left + di]} { ; perform a right zig }
- LES BX,[RightP]
- MOV [ES:BX+SI],DX
- { mov [Offset Right + si], dx}
- LES BX,[LeftP]
- MOV [ES:BX+DI],SI
- POP BX
- { mov [Offset Left + di], si}
- @Splay3:
- PUSH SI
- LES SI,[RightP]
- MOV [ES:SI+BX],DI
- POP SI
- { mov [Offset Right + bx], di}
- xchg bx, dx
- PUSH AX
- MOV AX,BX
- LES BX,[MomP]
- ADD BX,AX
- MOV [ES:BX],SI
- LES BX,[MomP]
- MOV [ES:BX+SI],DI
- LES BX,[MomP]
- MOV [ES:BX+DI],DX
- MOV BX,AX
- POP AX
- { mov [Offset Mom + bx], si
- mov [Offset Mom + si], di
- mov [Offset Mom + di], dx}
- @Splay4: jmp @end
- @Splay5:
- PUSH DI
- LES DI,[MomP]
- MOV CX,[ES:DI+BX]
- POP DI
- { mov cx, [Offset Mom + bx]}
- PUSH BX
- LES BX,[LeftP]
- CMP DI,[ES:BX+SI]
- POP BX
- { cmp di, [Offset Left + si]}
- jne @Splay7
- PUSH DI
- LES DI,[LeftP]
- CMP SI,[ES:DI+BX]
- POP DI
- { cmp si, [Offset Left + bx]}
- jne @Splay6
- PUSH AX
- MOV AX,DI
- LES DI,[RightP]
- ADD DI,SI
- MOV DX,[ES:DI]
- { mov dx, [Offset Right + si] } { ; perform a left zig-zig
- operation } LES DI,[LeftP]
- MOV [ES:DI+BX],DX
- { mov [Offset Left + bx], dx}
- xchg bx, dx
- LES DI,[MomP]
- MOV [ES:DI+BX],DX
- { mov [Offset Mom + bx], dx}
- LES DI,[RightP]
- ADD DI,AX
- MOV BX,[ES:DI]
- { mov bx, [Offset Right + di]}
- LES DI,[LeftP]
- ADD DI,SI
- MOV [ES:DI],BX
- LES DI,[MomP]
- MOV [ES:DI+BX],SI
- { mov [Offset Left +si], bx
- mov [Offset Mom + bx], si}
- mov bx, dx
- LES DI,[RightP]
- ADD DI,SI
- MOV [ES:DI],BX
- LES DI,[RightP]
- ADD DI,AX
- MOV [ES:DI],SI
- { mov [Offset Right + si], bx
- mov [Offset Right + di], si}
- LES DI,[MomP]
- MOV [ES:DI+BX],SI
- LES DI,[MomP]
- ADD DI,SI
- STOSW
- MOV DI,AX
- POP AX
- { mov [Offset Mom + bx], si
- mov [Offset Mom + si], di}
- jmp @Splay9
- @Splay6:
- PUSH AX
- MOV AX,SI
- LES SI,[LeftP]
- ADD SI,DI
- MOV DX,[ES:SI]
- { mov dx, [Offset Left + di]} { ; perform a left zig-zag
- operation } LES SI,[RightP]
- MOV [ES:SI+BX],DX
- { mov [Offset Right + bx], dx}
- xchg bx, dx
- LES SI,[MomP]
- MOV [ES:SI+BX],DX
- { mov [Offset Mom + bx], dx}
- LES SI,[RightP]
- ADD SI,DI
- MOV BX,[ES:SI]
- { mov bx, [Offset Right + di]}
- LES SI,[LeftP]
- ADD SI,AX
- MOV [ES:SI],BX
- { mov [Offset Left + si], bx}
- LES SI,[MomP]
- MOV [ES:SI+BX],AX
- { mov [Offset Mom + bx], si}
- mov bx, dx
- LES SI,[LeftP]
- ADD SI,DI
- MOV [ES:SI],BX
- { mov [Offset Left + di], bx}
- LES SI,[RightP]
- ADD SI,DI
- MOV [ES:SI],AX
- { mov [Offset Right + di], si}
- LES SI,[MomP]
- ADD SI,AX
- MOV [ES:SI],DI
- { mov [Offset Mom + si], di}
- LES SI,[MomP]
- MOV [ES:SI+BX],DI
- MOV SI,AX
- POP AX
- { mov [Offset Mom + bx], di}
- jmp @Splay9
- @Splay7:
- PUSH DI
- LES DI,[RightP]
- CMP SI,[ES:DI+BX]
- POP DI
- { cmp si, [Offset Right + bx]}
- jne @Splay8
- PUSH AX
- MOV AX,SI
- LES SI,[LeftP]
- ADD SI,AX
- MOV DX,[ES:SI]
- { mov dx, [Offset Left + si]} { ; perform a right zig-zig
- } LES SI,[RightP]
- MOV [ES:SI+BX],DX
- { mov [Offset Right + bx], dx}
- xchg bx, dx
- LES SI,[MomP]
- MOV [ES:SI+BX],DX
- { mov [Offset Mom + bx], dx}
- LES SI,[LeftP]
- ADD SI,DI
- MOV BX,[ES:SI]
- { mov bx, [Offset Left + di]}
- LES SI,[RightP]
- ADD SI,AX
- MOV [ES:SI],BX
- { mov [Offset Right + si], bx}
- LES SI,[MomP]
- MOV [ES:SI+BX],AX
- { mov [Offset Mom + bx], si}
- mov bx, dx
- LES SI,[LeftP]
- ADD SI,AX
- MOV [ES:SI],BX
- { mov [Offset Left + si], bx}
- LES SI,[LeftP]
- ADD SI,DI
- MOV [ES:SI],AX
- { mov [Offset Left + di], si}
- LES SI,[MomP]
- MOV [ES:SI+BX],AX
- { mov [Offset Mom + bx], si}
- LES SI,[MomP]
- ADD SI,AX
- MOV [ES:SI],DI
- { mov [Offset Mom + si], di}
- MOV SI,AX
- POP AX
- jmp @Splay9
- @Splay8:
- PUSH AX
- MOV AX,SI
- LES SI,[RightP]
- ADD SI,DI
- MOV DX,[ES:SI]
- { mov dx, [Offset Right + di]} { ; perform a right zig-zag
- } LES SI,[LeftP]
- MOV [ES:SI+BX],DX
- { mov [Offset Left + bx], dx}
- xchg bx, dx
- LES SI,[MomP]
- MOV [ES:SI+BX],DX
- { mov [Offset Mom + bx], dx}
- LES SI,[LeftP]
- ADD SI,DI
- MOV BX,[ES:SI]
- { mov bx, [Offset Left + di]}
- LES SI,[RightP]
- ADD SI,AX
- MOV [ES:SI],BX
- { mov [Offset Right + si], bx}
- LES SI,[MomP]
- MOV [ES:SI+BX],AX
- { mov [Offset Mom + bx], si}
- mov bx, dx
- LES SI,[RightP]
- ADD SI,DI
- MOV [ES:SI],BX
- { mov [Offset Right + di], bx}
- LES SI,[LeftP]
- ADD SI,DI
- MOV [ES:SI],AX
- { mov [Offset Left + di], si}
- LES SI,[MomP]
- ADD SI,AX
- MOV [ES:SI],DI
- LES SI,[MomP]
- MOV [ES:SI+BX],DI
- { mov [Offset Mom + si], di
- mov [Offset Mom + bx], di}
- MOV SI,AX
- POP AX
- @Splay9: mov si, cx
- cmp si, NUL
- ja @Splay10
- PUSH DI
- LES DI,[LeftP]
- ADD DI,SI
- CMP BX,[ES:DI]
- POP DI
- { cmp bx, [Offset Left + si]}
- jne @Splay10
- PUSH BX
- LES BX,[LeftP]
- MOV [ES:BX+SI],DI
- POP BX
- { mov [Offset Left + si], di}
- jmp @Splay11
- @Splay10:
- PUSH BX
- LES BX,[RightP]
- MOV [ES:BX+SI],DI
- POP BX
- { mov [Offset Right + si], di}
- @Splay11:
- PUSH BX
- LES BX,[MomP]
- MOV [ES:BX+DI],SI
- POP BX
- { mov [Offset Mom + di], si}
- jmp @Splay1
- @end:
- End; { SPlay }
-
- Procedure InsertNode; assembler;
- {
- insertNode : insert the new node to the corresponding tree. Note that the
- position of a string in the buffer also served as the node
- number.
- ENTRY : di = position in the buffer
- }
- Asm
- push si
- push dx
- push cx
- push bx
- mov dx, 1
- xor ax, ax
- mov matchLen, ax
- mov height, ax
- LES SI,[TextBufP]
- ADD SI,DI
- MOV AL,BYTE PTR [ES:SI]
- { mov al, byte ptr [Offset TextBuf + di]}
- shl di, 1
- add ax, N + 1
- shl ax, 1
- mov si, ax
- mov ax, NUL
- PUSH BX
- LES BX,[RightP]
- MOV WORD PTR [ES:BX+DI],AX
- { mov word ptr [Offset Right + di], ax}
- LES BX,[LeftP]
- MOV WORD PTR [ES:BX+DI],AX
- POP BX
- { mov word ptr [Offset Left + di], ax}
- @Ins1:inc height
- cmp dx, 0
- jl @Ins3
- PUSH DI
- LES DI,[RightP]
- ADD DI,SI
- MOV AX,WORD PTR [ES:DI]
- POP DI
- { mov ax, word ptr [Offset Right + si]}
- cmp ax, NUL
- je @Ins2
- mov si, ax
- jmp @Ins5
- @Ins2:
- PUSH BX
- LES BX,[RightP]
- MOV WORD PTR [ES:BX+SI],DI
- { mov word ptr [Offset Right + si], di}
- LES BX,[MomP]
- MOV WORD PTR [ES:BX+DI],SI
- POP BX
- { mov word ptr [Offset Mom + di], si}
- jmp @Ins11
- @Ins3:
- PUSH BX
- LES BX,[LeftP]
- ADD BX,SI
- MOV AX,WORD PTR [ES:BX]
- POP BX
- { mov ax, word ptr [Offset Left + si]}
- cmp ax, NUL
- je @Ins4
- mov si, ax
- jmp @Ins5
- @Ins4:
- PUSH BX
- LES BX,[LeftP]
- ADD BX,SI
- MOV WORD PTR [ES:BX],DI
- { mov word ptr [Offset Left + si], di}
- LES BX,[MomP]
- ADD BX,DI
- MOV WORD PTR [ES:BX],SI
- POP BX
- { mov word ptr [Offset Mom + di], si}
- jmp @Ins11
- @Ins5: mov bx, 1
- shr si, 1
- shr di, 1
- xor ch, ch
- xor dh, dh
- @Ins6:
- PUSH SI
- LES SI,[TextBufP]
- ADD SI,DI
- MOV DL,BYTE PTR [ES:SI+BX]
- POP SI
- PUSH DI
- LES DI,[TextBufP]
- ADD DI,SI
- MOV CL,BYTE PTR [ES:DI+BX]
- POP DI
- { mov dl, byte ptr [Offset Textbuf + di + bx]
- mov cl, byte ptr [Offset TextBuf + si + bx]}
- sub dx, cx
- jnz @Ins7
- inc bx
- cmp bx, F
- jb @Ins6
- @Ins7: shl si, 1
- shl di, 1
- cmp bx, matchLen
- jbe @Ins1
- mov ax, si
- shr ax, 1
- mov matchPos, ax
- mov matchLen, bx
- cmp bx, F
- jb @Ins1
- @Ins8:
- PUSH CX
- LES BX,[MomP]
- MOV AX,WORD PTR [ES:BX+SI]
- { mov ax, word ptr [Offset Mom + si]}
- LES BX,[MomP]
- MOV WORD PTR [ES:BX+DI],AX
- { mov word ptr [Offset Mom + di], ax}
- LES BX,[LeftP]
- MOV CX,WORD PTR [ES:BX+SI]
- { mov bx, word ptr [Offset Left + si]}
- LES BX,[LeftP]
- MOV WORD PTR [ES:BX+DI],CX
- { mov word ptr [Offset Left + di], bx}
- LES BX,[MomP]
- ADD BX,CX
- MOV WORD PTR [ES:BX],DI
- { mov word ptr [Offset Mom + bx], di}
- LES BX,[RightP]
- MOV CX,WORD PTR [ES:BX+SI]
- { mov bx, word ptr [Offset Right + si]}
- LES BX,[RightP]
- MOV WORD PTR [ES:BX+DI],CX
- { mov word ptr [Offset Right + di], bx}
- LES BX,[MomP]
- ADD BX,CX
- MOV WORD PTR [ES:BX],DI
- { mov word ptr [Offset Mom + bx], di}
- LES BX,[MomP]
- MOV CX,WORD PTR [ES:BX+SI]
- { mov bx, word ptr [Offset Mom + si]}
- MOV BX,CX
- POP CX
- PUSH DI
- LES DI,[RightP]
- CMP SI,WORD PTR [ES:DI+BX]
- POP DI
- { cmp si, word ptr [Offset Right + bx]}
- jne @Ins9
- PUSH SI
- LES SI,[RightP]
- MOV WORD PTR [ES:SI+BX],DI
- POP SI
- { mov word ptr [Offset Right + bx], di}
- jmp @Ins10
- @Ins9:
- PUSH SI
- LES SI,[LeftP]
- MOV WORD PTR [ES:SI+BX],DI
- POP SI
- { mov word ptr [Offset Left + bx], di}
- @Ins10:
- PUSH DI
- LES DI,[MomP]
- ADD DI,SI
- MOV WORD PTR [ES:DI],NUL
- POP DI
- { mov word ptr [Offset Mom + si], NUL}
- @Ins11: cmp height, 30
- jb @Ins12
- call Splay
- @Ins12: pop bx
- pop cx
- pop dx
- pop si
- shr di, 1
- End; { InsertNode }
-
-
- Procedure DeleteNode; assembler;
- {
- deleteNode : delete the node from the tree
-
- ENTRY : SI = position in the buffer
- }
- Asm
- push di
- push bx
- shl si, 1
- PUSH DI
- LES DI,[MomP]
- ADD DI,SI
- CMP WORD PTR [ES:DI],NUL
- POP DI
- { cmp word ptr [Offset Mom + si], NUL} { ; if it has no
- parent then exit } je @del7
- PUSH DI
- LES DI,[RightP]
- ADD DI,SI
- CMP WORD PTR [ES:DI],NUL
- POP DI
- { cmp word ptr [Offset Right + si], NUL} { ; does it have
- right child ? } je @del8
- PUSH BX
- LES BX,[LeftP]
- MOV DI,WORD PTR [ES:BX+SI]
- POP BX
- { mov di, word ptr [Offset Left + si] } { ; does it have left
- child ? } cmp di, NUL
- je @del9
- PUSH SI
- LES SI,[RightP]
- ADD SI,DI
- MOV AX,WORD PTR [ES:SI]
- POP SI
- { mov ax, word ptr [Offset Right + di]} { ; does it have
- right grandchild ? } cmp ax, NUL
- je @del2 { ; if no then skip }
- @del1: mov di, ax { ; find the rightmost
- node in } PUSH SI
- LES SI,[RightP]
- ADD SI,DI
- MOV AX,WORD PTR [ES:SI]
- POP SI
- { mov ax, word ptr [Offset Right + di] } { ; the right
- subtree } cmp ax, NUL
- jne @del1
- PUSH CX
- MOV CX,SI
- LES SI,[MomP]
- ADD SI,DI
- MOV BX,WORD PTR [ES:SI]
- { mov bx, word ptr [Offset Mom + di] } { ; move this node as
- the root of } LES SI,[LeftP]
- ADD SI,DI
- MOV AX,WORD PTR [ES:SI]
- { mov ax, word ptr [Offset Left + di]} { ; the subtree }
- LES SI,[RightP]
- MOV WORD PTR [ES:SI+BX],AX
- { mov word ptr [Offset Right + bx], ax}
- xchg ax, bx
- LES SI,[MomP]
- MOV WORD PTR [ES:SI+BX],AX
- { mov word ptr [Offset Mom + bx], ax}
- LES SI,[LeftP]
- ADD SI,CX
- MOV BX,WORD PTR [ES:SI]
- { mov bx, word ptr [Offset Left + si]}
- LES SI,[LeftP]
- ADD SI,DI
- MOV WORD PTR [ES:SI],BX
- { mov word ptr [Offset Left + di], bx}
- LES SI,[MomP]
- MOV WORD PTR [ES:SI+BX],DI
- { mov word ptr [Offset Mom + bx], di}
- MOV SI,CX
- POP CX
- @del2:
- PUSH CX
- MOV CX,SI
- LES SI,[RightP]
- ADD SI,CX
- MOV BX,WORD PTR [ES:SI]
- { mov bx, word ptr [Offset Right + si]}
- LES SI,[RightP]
- ADD SI,DI
- MOV WORD PTR [ES:SI],BX
- { mov word ptr [Offset Right + di], bx}
- LES SI,[MomP]
- MOV WORD PTR [ES:SI+BX],DI
- MOV SI,CX
- POP CX
- { mov word ptr [Offset Mom + bx], di}
- @del3:
- PUSH CX
- MOV CX,DI
- LES DI,[MomP]
- ADD DI,SI
- MOV BX,WORD PTR [ES:DI]
- { mov bx, word ptr [Offset Mom + si]}
- LES DI,[MomP]
- ADD DI,CX
- MOV WORD PTR [ES:DI],BX
- { mov word ptr [Offset Mom + di], bx}
- MOV DI,CX
- POP CX
- PUSH DI
- LES DI,[RightP]
- CMP SI,WORD PTR [ES:DI+BX]
- POP DI
- { cmp si, word ptr [Offset Right + bx]}
- jne @del4
- PUSH SI
- LES SI,[RightP]
- MOV WORD PTR [ES:SI+BX],DI
- POP SI
- { mov word ptr [Offset Right + bx], di}
- jmp @del5
- @del4:
- PUSH SI
- LES SI,[LeftP]
- MOV WORD PTR [ES:SI+BX],DI
- POP SI
- { mov word ptr [Offset Left + bx], di}
- @del5:
- PUSH DI
- LES DI,[MomP]
- ADD DI,SI
- MOV WORD PTR [ES:DI],NUL
- POP DI
- { mov word ptr [Offset Mom + si], NUL}
- @del7: pop bx
- pop di
- shr si, 1
- jmp @end;
- @del8:
- PUSH BX
- LES BX,[LeftP]
- MOV DI,WORD PTR [ES:BX+SI]
- POP BX
- { mov di, word ptr [Offset Left + si]}
- jmp @del3
- @del9:
- PUSH BX
- LES BX,[RightP]
- MOV DI,WORD PTR [ES:BX+SI]
- POP BX
- { mov di, word ptr [Offset Right + si]}
- jmp @del3
- @end:
- End; { DeleteNode }
-
- Procedure Encode; assembler;
- Asm
- call initTree
- xor bx, bx
- mov [Offset CodeBuf + bx], bl
- mov dx, 1
- mov ch, dl
- xor si, si
- mov di, N - F
- @Encode2: call getc
- jc @Encode3
- PUSH SI
- LES SI,[TextBufP]
- ADD SI,DI
- MOV BYTE PTR [ES:SI+BX],AL
- POP SI
- { mov byte ptr [Offset TextBuf +di + bx], al}
- inc bx
- cmp bx, F
- jb @Encode2
- @Encode3: or bx, bx
- jne @Encode4
- jmp @Encode19
- @Encode4: mov cl, bl
- mov bx, 1
- push di
- sub di, 1
- @Encode5: call InsertNode
- inc bx
- dec di
- cmp bx, F
- jbe @Encode5
- pop di
- call InsertNode
- @Encode6: mov ax, matchLen
- cmp al, cl
- jbe @Encode7
- mov al, cl
- mov matchLen, ax
- @Encode7: cmp al, THRESHOLD
- ja @Encode8
- mov matchLen, 1
- or byte ptr codeBuf, ch
- mov bx, dx
- PUSH SI
- LES SI,[TextBufP]
- ADD SI,DI
- MOV AL,BYTE PTR [ES:SI]
- POP SI
- { mov al, byte ptr [Offset TextBuf + di]}
- mov byte ptr [Offset CodeBuf + bx], al
- inc dx
- jmp @Encode9
- @Encode8: mov bx, dx
- mov al, byte ptr matchPos
- mov byte ptr [Offset Codebuf + bx], al
- inc bx
- mov al, byte ptr (matchPos + 1)
- push cx
- mov cl, 4
- shl al, cl
- pop cx
- mov ah, byte ptr matchLen
- sub ah, THRESHOLD + 1
- add al, ah
- mov byte ptr [Offset Codebuf + bx], al
- inc bx
- mov dx, bx
- @Encode9: shl ch, 1
- jnz @Encode11
- xor bx, bx
- @Encode10: mov al, byte ptr [Offset CodeBuf + bx]
- call putc
- inc bx
- cmp bx, dx
- jb @Encode10
- mov dx, 1
- mov ch, dl
- mov byte ptr codeBuf, dh
- @Encode11: mov bx, matchLen
- mov lastLen, bx
- xor bx, bx
- @Encode12: call getc
- { jc @Encode14}
- jc @Encode15
- push ax
- call deleteNode
- pop ax
- PUSH DI
- LES DI,[TextBufP]
- ADD DI,SI
- stosb
- POP DI
- { mov byte ptr [Offset TextBuf + si], al}
- cmp si, F - 1
- jae @Encode13
- PUSH DI
- LES DI,[TextBufP]
- ADD DI,SI
- MOV BYTE PTR [ES:DI+N],AL
- POP DI
- { mov byte ptr [Offset TextBuf + si + N], al}
- @Encode13: inc si
- and si, N - 1
- inc di
- and di, N - 1
- call insertNode
- inc bx
- cmp bx, lastLen
- jb @Encode12
- (* @Encode14: sub printCount, bx
- jnc @Encode15
- mov ax, printPeriod
- mov printCount, ax
- push dx { Print out a period as a sign. }
- mov dl, DBLARROW
- mov ah, 2
- int 21h
- pop dx *)
- @Encode15: cmp bx, lastLen
- jae @Encode16
- inc bx
- call deleteNode
- inc si
- and si, N - 1
- inc di
- and di, N - 1
- dec cl
- jz @Encode15
- call insertNode
- jmp @Encode15
- @Encode16: cmp cl, 0
- jbe @Encode17
- jmp @Encode6
- @Encode17: cmp dx, 1
- jb @Encode19
- xor bx, bx
- @Encode18: mov al, byte ptr [Offset Codebuf + bx]
- call putc
- inc bx
- cmp bx, dx
- jb @Encode18
- @Encode19:
- End; { Encode }
-
- Procedure Decode; assembler;
- Asm
- xor dx, dx
- mov di, N - F
- @Decode2: shr dx, 1
- or dh, dh
- jnz @Decode3
- call getc
- jc @Decode9
- mov dh, 0ffh
- mov dl, al
- @Decode3: test dx, 1
- jz @Decode4
- call getc
- jc @Decode9
- PUSH SI
- LES SI,[TextBufP]
- ADD SI,DI
- MOV BYTE PTR [ES:SI],AL
- POP SI
- { mov byte ptr [Offset TextBuf + di], al}
- inc di
- and di, N - 1
- call putc
- jmp @Decode2
- @Decode4: call getc
- jc @Decode9
- mov ch, al
- call getc
- jc @Decode9
- mov bh, al
- mov cl, 4
- shr bh, cl
- mov bl, ch
- mov cl, al
- and cl, 0fh
- add cl, THRESHOLD
- inc cl
- @Decode5: and bx, N - 1
- PUSH SI
- LES SI,[TextBufP]
- MOV AL,BYTE PTR [ES:SI+BX]
- ADD SI,DI
- MOV BYTE PTR [ES:SI],AL
- POP SI
- { mov al, byte ptr [Offset TextBuf + bx]
- mov byte ptr [Offset TextBuf + di], al}
- inc di
- and di, N - 1
- call putc
- inc bx
- dec cl
- jnz @Decode5
- jmp @Decode2
- @Decode9:
- End; { Decode }
-
- Function LZInit : boolean;
- Begin
- if Initialized then Exit;
- LZInit := False;
- New(InBufP);
- New(OutBufP);
- New(TextBufP);
- New(LeftP);
- New(MomP);
- New(RightP);
- Initialized := (InBufP <> nil) and (OutBufP <> nil) and
- (TextBufP <> nil) and (LeftP <> nil) and (MomP <> nil) and (RightP <> nil);
- if Initialized then LZInit := True else
- begin
- Initialized := True;
- LZDone
- end
- End; { LZInit }
-
- Procedure LZDone;
- Begin
- if Initialized then
- begin
- Dispose(InBufP);
- Dispose(OutBufP);
- Dispose(RightP);
- Dispose(MomP);
- Dispose(LeftP);
- Dispose(TextBufP);
- Initialized := False
- end
- End; { LZDone }
-
- Procedure LZSquash;
- Begin
- if Initialized then
- begin
- InBufPtr := LZRWBufSize;
- InBufSize := LZRWBufSize;
- OutBufPtr := 0;
- Height := 0;
- MatchPos := 0;
- MatchLen := 0;
- LastLen := 0;
-
- FillChar(TextBufP^, SizeOf(TLZTextBuf), 0);
- FillChar(LeftP^, SizeOf(TLeftMomTree), 0);
- FillChar(MomP^, SizeOf(TLeftMomTree), 0);
- FillChar(RightP^, SizeOf(TRightTree), 0);
- FillChar(CodeBuf, SizeOf(CodeBuf), 0);
-
- LZReadProc := ReadProc;
- LZWriteProc := WriteProc;
-
- Encode;
- LZSS_Write
- end
- End; { LZSquash }
-
- Procedure LZUnSquash;
- Begin
- if Initialized then
- begin
- InBufPtr := LZRWBufSize;
- InBufSize := LZRWBufSize;
- OutBufPtr := 0;
- FillChar(TextBufP^, SizeOf(TLZTextBuf), 0);
-
- LZReadProc := ReadProc;
- LZWriteProc := WriteProc;
-
- Decode;
- LZSS_Write
- end
- End; { LZUnSquash }
-
- {$IFDEF Windows}
- Function HeapFunc(Size : word) : integer; far; assembler;
- Asm
- MOV AX,1
- End; { HeapFunc }
- {$ENDIF}
-
- Begin
- {$IFDEF Windows}
- HeapError := @HeapFunc;
- {$ENDIF}
- Initialized := False
- End. { LZSSUNIT }
-
- { ------------------------- DEMO ---------------------------------}
-
- Program LZSSDemo;
- { Copyright (c) 1994 by Andrew Eigus Fidonet: 2:5100/33 }
- { Demonstrates the use of LZSSUnit (LZSSUNIT.PAS), Public Domain }
-
- uses LZSSUnit;
-
- var InFile, OutFile : file;
-
- Function ToUpper(S : string) : string; assembler;
- Asm
- PUSH DS
- CLD
- LDS SI,S
- LES DI,@Result
- LODSB
- STOSB
- XOR AH,AH
- XCHG AX,CX
- JCXZ @@3
- @@1:
- LODSB
- CMP AL,'a'
- JB @@2
- CMP AL,'z'
- JA @@2
- SUB AL,20h
- @@2:
- STOSB
- LOOP @@1
- @@3:
- POP DS
- End; { ToUpper }
-
- Function ReadProc(var ReadBuf; var NumRead : word) : word; far;
- Begin
- BlockRead(InFile, ReadBuf, LZRWBufSize, NumRead);
- Write(#13, FilePos(InFile), ' -> ')
- End; { ReadProc }
-
- Function WriteProc(var WriteBuf; Count : word; var NumWritten : word) : word;
- far;Begin
- BlockWrite(OutFile, WriteBuf, Count, NumWritten);
- Write(FilePos(OutFile), #13)
- End; { WriteProc }
-
- Begin
- if ParamCount < 2 then
- begin
- WriteLn('Usage: LZSSDEMO <inputfile> <outputfile> [unsquash]');
- Halt(1)
- end;
- if not LZInit then
- begin
- WriteLn('Not enough memory');
- Halt(8)
- end;
- Assign(InFile, ParamStr(1));
- Reset(InFile, 1);
- if IOResult = 0 then
- begin
- Assign(OutFile, ParamStr(2));
- Rewrite(OutFile, 1);
- if IOResult = 0 then
- begin
- if ToUpper(ParamStr(3)) = 'UNSQUASH' then
- LZUnSquash(ReadProc, WriteProc)
- else
- LZSquash(ReadProc, WriteProc);
- Close(OutFile)
- end else WriteLn('Cannot create output file');
- Close(InFile)
- end else WriteLn('Cannot open input file');
- LZDone;
- WriteLn
- End.