home *** CD-ROM | disk | FTP | other *** search
- 'Huffman decoder
- 'by Rich Geldreich May 29th, 1992
- 'This program is in the public domain.
- DEFINT A-Z
-
- DECLARE FUNCTION GetBit ()
- DECLARE SUB FillBuff ()
-
- CONST True = -1, False = 0
- CONST Null = -2
- CONST BufferLength = 10000
-
- DIM SHARED Bits(8)
- DIM SHARED Father(512)
- DIM SHARED LeftSon(512)
- DIM SHARED RightSon(512)
-
- DIM SHARED Buffer$, Address, EndAddress, CurrentByte, BitsIn, BufferSeg
-
- Bits:
- DATA 1,2,4,8,16,32,64,128,256
-
- RESTORE Bits
- FOR A = 0 TO 8: READ Bits(A): NEXT
- 'disk buffer
- Buffer$ = STRING$(BufferLength, 0): EndAddress = 1: Address = 0: BitsIn = -1
- 'turn on cursor
- LOCATE , , 1
- 'open the compressed file
- OPEN "output.huf" FOR BINARY AS #1
- 'get the header
- GET #1, , FileLength&
- GET #1, , RealIndex
- GET #1, , TopOfTree
- 'read in the tree
- FOR A = 0 TO RealIndex
- IF GetBit THEN
- Father = 0
- FOR C = 0 TO 7
- IF GetBit THEN Father = Father + Bits(C)
- NEXT
- Father(A) = Father
- RightSon(A) = Null
- LeftSon(A) = Null
- ELSE
- Father(A) = 256
- IF GetBit THEN
- Son = 0
- FOR C = 0 TO 8
- IF GetBit THEN Son = Son + Bits(C)
- NEXT
- LeftSon(A) = Son
- ELSE
- LeftSon(A) = Null
- END IF
- IF GetBit THEN
- Son = 0
- FOR C = 0 TO 8
- IF GetBit THEN Son = Son + Bits(C)
- NEXT
- RightSon(A) = Son
- ELSE
- RightSon(A) = Null
- END IF
- END IF
- NEXT
- 'when PrintCounter=1024 then screen is updated
- PrintCounter = 0
- 'A$ is the output buffer
- A$ = STRING$(5000, 0)
- A& = SADD(A$)
- A& = A& - 65536 * (A& < 0)
- OutputSeg = VARSEG(A$) + (A& \ 16)
- OAddress = (A& MOD 16)
- OEndAddress = OAddress + 5000
- OStart = OAddress
- 'start decoding
- PRINT "Decoding:";
- Xpos = POS(0): Ypos = CSRLIN
- 'open output file
- OPEN COMMAND$ FOR BINARY AS #2
- 'decode each byte
- FOR CurrentByte& = 1 TO FileLength&
- DEF SEG = BufferSeg
- 'start at top of tree
- A = TopOfTree
- 'keep on getting bits until a character is found
- DO
- 'if BitsIn<0 then time to fill byte buffer
- IF BitsIn < 0 THEN
- Address = Address + 1
- 'if Address=EndBuffer then time to fill disk buffer
- IF Address = EndAddress THEN
- FillBuff
- END IF
- CurrentByte = PEEK(Address): BitsIn = 7
- END IF
- 'see if we go left or right
- IF (CurrentByte AND Bits(BitsIn)) THEN A = LeftSon(A) ELSE A = RightSon(A)
- BitsIn = BitsIn - 1
- F = Father(A)
- 'loop until an ascii character is found
- LOOP UNTIL F < 256
- 'put byte into output buffer
- DEF SEG = OutputSeg
- POKE OAddress, F
- OAddress = OAddress + 1
- IF OAddress = OEndAddress THEN
- PUT #2, , A$
- A& = SADD(A$)
- A& = A& - 65536 * (A& < 0)
- OutputSeg = VARSEG(A$) + (A& \ 16)
- OAddress = (A& MOD 16)
- OEndAddress = OAddress + 5000
- OStart = OAddress
- END IF
- 'see if time to update the screen
- PrintCounter = PrintCounter + 1
- IF PrintCounter = 1024 THEN
- PrintCounter = 0
- LOCATE Ypos, Xpos
- PRINT (CurrentByte& * 100) \ FileLength&; "%";
- END IF
- 'loop until all of the characters have been restored
- NEXT
- 'save whatever is currently in the output buffer
- A$ = LEFT$(A$, OAddress - OStart)
- PUT #2, , A$
- CLOSE
- 'all done
- LOCATE Ypos, Xpos
- PRINT " done."
-
- END
-
- 'fills the input buffer
- SUB FillBuff
- GET #1, , Buffer$
- A& = SADD(Buffer$)
- A& = A& - 65536 * (A& < 0)
- BufferSeg = VARSEG(Buffer$) + (A& \ 16)
- Address = (A& MOD 16)
- EndAddress = Address + BufferLength
- DEF SEG = BufferSeg
- END SUB
-
- 'gets one bit from the input file(only used when the tree
- 'is read in)
- FUNCTION GetBit STATIC
- IF BitsIn < 0 THEN
- Address = Address + 1
- IF Address = EndAddress THEN
- FillBuff
- END IF
- CurrentByte = PEEK(Address): BitsIn = 7
- END IF
- GetBit = (CurrentByte AND Bits(BitsIn)): BitsIn = BitsIn - 1
- END FUNCTION
-
-