📄 abdfdec.pas
字号:
(* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is TurboPower Abbrevia * * The Initial Developer of the Original Code is * TurboPower Software * * Portions created by the Initial Developer are Copyright (C) 1997-2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * ***** END LICENSE BLOCK ***** *){*********************************************************}{* ABBREVIA: AbDfDec.pas 3.05 *}{*********************************************************}{* Deflate decoding unit *}{*********************************************************}unit AbDfDec;{$I AbDefine.inc}interfaceuses SysUtils, Classes, AbDfBase;function Inflate(aSource : TStream; aDest : TStream; aHelper : TAbDeflateHelper) : longint;implementationuses AbDfStrm, AbDfHufD, AbDfOutW, AbDfCryS;{===Helper routines==================================================}procedure ReadLitDistCodeLengths(aInStrm : TAbDfInBitStream; aCodeLenTree : TAbDfDecodeHuffmanTree; var aCodeLens : array of integer; aCount : integer; var aTotalBits : integer);var i : integer; SymbolCount : integer; LookupValue : integer; EncodedSymbol : longint; Symbol : integer; SymbolCodeLen : integer; RepeatCount : integer; BitBuffer : TAb32bit; BitCount : integer;begin {$IFDEF UseLogging} {we need to calculate the total number of bits in the code lengths for reporting purposes, so zero the count} aTotalBits := 0; {$ENDIF} {clear the code lengths array} FillChar(aCodeLens, sizeof(aCodeLens), 0); {read all the Symbols required in the bit stream} SymbolCount := 0; while (SymbolCount < aCount) do begin {grab the lookup set of bits} BitCount := aCodeLenTree.LookupBitLength + 7; {$IFOPT C+} BitBuffer := aInStrm.PeekBits(BitCount); {$ELSE} if (aInStrm.BitsLeft < BitCount) then BitBuffer := aInStrm.PeekMoreBits(BitCount) else BitBuffer := aInStrm.BitBuffer and AbExtractMask[BitCount]; {$ENDIF} LookupValue := BitBuffer and AbExtractMask[aCodeLenTree.LookupBitLength]; {get the encoded Symbol} {$IFOPT C+} {if Assertions are on} EncodedSymbol := aCodeLenTree.Decode(LookupValue); {$ELSE} EncodedSymbol := aCodeLenTree.Decodes^[LookupValue]; {$ENDIF} {extract the data} Symbol := EncodedSymbol and $FFFF; SymbolCodeLen := (EncodedSymbol shr 16) and $FF; {$IFDEF UseLogging} {keep count of the total number of bits read} inc(aTotalBits, SymbolCodeLen); {$ENDIF} {check that the symbol is between 0 and 18} if not ((0 <= Symbol) and (Symbol <= 18)) then raise EAbInternalInflateError.Create( 'decoded a symbol not between 0 and 18 {ReadLitDistCodeLengths}'); {check that the codelength is in range} if not ((0 < SymbolCodeLen) and (SymbolCodeLen <= aCodeLenTree.LookupBitLength)) then raise EAbInternalInflateError.Create( 'decoded a code length out of range {ReadLitDistCodeLengths}'); {for a Symbol of 0..15, just save the value} if (Symbol <= 15) then begin aCodeLens[SymbolCount] := Symbol; inc(SymbolCount); {$IFOPT C+} aInStrm.DiscardBits(SymbolCodeLen); {$ELSE} if (aInStrm.BitsLeft < SymbolCodeLen) then aInStrm.DiscardMoreBits(SymbolCodeLen) else begin aInStrm.BitBuffer := aInStrm.BitBuffer shr SymbolCodeLen; aInStrm.BitsLeft := aInStrm.BitsLeft - SymbolCodeLen; end; {$ENDIF} end {for a Symbol of 16, get two more bits and copy the previous code length that many times + 3} else if (Symbol = 16) then begin RepeatCount := 3 + ((BitBuffer shr SymbolCodeLen) and $3); Symbol := aCodeLens[SymbolCount-1]; for i := 0 to pred(RepeatCount) do aCodeLens[SymbolCount+i] := Symbol; inc(SymbolCount, RepeatCount); BitCount := SymbolCodeLen + 2; {$IFOPT C+} aInStrm.DiscardBits(BitCount); {$ELSE} if (aInStrm.BitsLeft < BitCount) then aInStrm.DiscardMoreBits(BitCount) else begin aInStrm.BitBuffer := aInStrm.BitBuffer shr BitCount; aInStrm.BitsLeft := aInStrm.BitsLeft - BitCount; end; {$ENDIF} {$IFDEF UseLogging} inc(aTotalBits, 2); {$ENDIF} end {for a Symbol of 17, get three more bits and copy a zero code length that many times + 3} else if (Symbol = 17) then begin RepeatCount := 3 + ((BitBuffer shr SymbolCodeLen) and $7); {note: the codelengths array was aet to zeros at the start so the following two lines are not needed for i := 0 to pred(RepeatCount) do aCodeLens[SymbolCount+i] := 0;} inc(SymbolCount, RepeatCount); BitCount := SymbolCodeLen + 3; {$IFOPT C+} aInStrm.DiscardBits(BitCount); {$ELSE} if (aInStrm.BitsLeft < BitCount) then aInStrm.DiscardMoreBits(BitCount) else begin aInStrm.BitBuffer := aInStrm.BitBuffer shr BitCount; aInStrm.BitsLeft := aInStrm.BitsLeft - BitCount; end; {$ENDIF} {$IFDEF UseLogging} inc(aTotalBits, 3); {$ENDIF} end {for a Symbol of 18, get seven more bits and copy a zero code length that many times + 11} else if (Symbol = 18) then begin RepeatCount := 11 + ((BitBuffer shr SymbolCodeLen) and $7F); {note: the codelengths array was aet to zeros at the start so the following two lines are not needed for i := 0 to pred(RepeatCount) do aCodeLens[SymbolCount+i] := 0;} inc(SymbolCount, RepeatCount); BitCount := SymbolCodeLen + 7; {$IFOPT C+} aInStrm.DiscardBits(BitCount); {$ELSE} if (aInStrm.BitsLeft < BitCount) then aInStrm.DiscardMoreBits(BitCount) else begin aInStrm.BitBuffer := aInStrm.BitBuffer shr BitCount; aInStrm.BitsLeft := aInStrm.BitsLeft - BitCount; end; {$ENDIF} {$IFDEF UseLogging} inc(aTotalBits, 7); {$ENDIF} end; end;end;{--------}procedure DecodeData(aInStrm : TAbDfInBitStream; aOutWindow : TAbDfOutputWindow; aLiteralTree : TAbDfDecodeHuffmanTree; aDistanceTree : TAbDfDecodeHuffmanTree; aDeflate64 : boolean);var LookupValue : integer; EncodedSymbol : longint; Symbol : integer; SymbolCodeLen : integer; ExtraBitCount : integer; Length : integer; Distance : integer; BitBuffer : TAb32bit; BitCount : integer;begin {extract the first symbol (it's got to be a literal/length symbol)} {..grab the lookup set of bits} if aDeflate64 then BitCount := aLiteralTree.LookupBitLength + 16 else BitCount := aLiteralTree.LookupBitLength + 5; {$IFOPT C+} BitBuffer := aInStrm.PeekBits(BitCount); {$ELSE} if (aInStrm.BitsLeft < BitCount) then BitBuffer := aInStrm.PeekMoreBits(BitCount) else BitBuffer := aInStrm.BitBuffer and AbExtractMask[BitCount]; {$ENDIF} LookupValue := BitBuffer and AbExtractMask[aLiteralTree.LookupBitLength]; {..get the encoded symbol} {$IFOPT C+} {if Assertions are on} EncodedSymbol := aLiteralTree.Decode(LookupValue); {$ELSE} EncodedSymbol := aLiteralTree.Decodes^[LookupValue]; {$ENDIF} {..extract the data} Symbol := EncodedSymbol and $FFFF; SymbolCodeLen := (EncodedSymbol shr 16) and $FF; {repeat until we get the end-of-block symbol} while (Symbol <> 256) do begin {for a literal, just output it to the sliding window} if (Symbol < 256) then begin aOutWindow.AddLiteral(AnsiChar(Symbol)); {$IFOPT C+} aInStrm.DiscardBits(SymbolCodeLen); {$ELSE} if (aInStrm.BitsLeft < SymbolCodeLen) then aInStrm.DiscardMoreBits(SymbolCodeLen) else begin aInStrm.BitBuffer := aInStrm.BitBuffer shr SymbolCodeLen; aInStrm.BitsLeft := aInStrm.BitsLeft - SymbolCodeLen; end; {$ENDIF} end {for a length value, we need to get any extra bits, and then the distance (plus any extra bits for that), and then add the duplicated characters to the sliding window} else begin {check that the length symbol is less than or equal to 285} if (Symbol > 285) then raise EAbInternalInflateError.Create( 'decoded an invalid length symbol: greater than 285 [DecodeData]'); {calculate the length (if need be, by calculating the number of extra bits that encode the length)} if (not aDeflate64) and (Symbol = 285) then begin Length := 258; {$IFOPT C+} aInStrm.DiscardBits(SymbolCodeLen); {$ELSE} if (aInStrm.BitsLeft < SymbolCodeLen) then aInStrm.DiscardMoreBits(SymbolCodeLen) else begin aInStrm.BitBuffer := aInStrm.BitBuffer shr SymbolCodeLen; aInStrm.BitsLeft := aInStrm.BitsLeft - SymbolCodeLen; end; {$ENDIF} end else begin ExtraBitCount := EncodedSymbol shr 24; if (ExtraBitCount = 0) then begin Length := dfc_LengthBase[Symbol - 257]; {$IFOPT C+} aInStrm.DiscardBits(SymbolCodeLen); {$ELSE} if (aInStrm.BitsLeft < SymbolCodeLen) then aInStrm.DiscardMoreBits(SymbolCodeLen) else begin aInStrm.BitBuffer := aInStrm.BitBuffer shr SymbolCodeLen; aInStrm.BitsLeft := aInStrm.BitsLeft - SymbolCodeLen; end; {$ENDIF} end else begin Length := dfc_LengthBase[Symbol - 257] + ((BitBuffer shr SymbolCodeLen) and AbExtractMask[ExtraBitCount]); BitCount := SymbolCodeLen + ExtraBitCount; {$IFOPT C+} aInStrm.DiscardBits(BitCount); {$ELSE} if (aInStrm.BitsLeft < BitCount) then aInStrm.DiscardMoreBits(BitCount) else begin aInStrm.BitBuffer := aInStrm.BitBuffer shr BitCount; aInStrm.BitsLeft := aInStrm.BitsLeft - BitCount; end; {$ENDIF} end; end; {extract the distance} {..grab the lookup set of bits} BitCount := aDistanceTree.LookupBitLength + 14; {$IFOPT C+} BitBuffer := aInStrm.PeekBits(BitCount); {$ELSE} if (aInStrm.BitsLeft < BitCount) then BitBuffer := aInStrm.PeekMoreBits(BitCount) else BitBuffer := aInStrm.BitBuffer and AbExtractMask[BitCount]; {$ENDIF} LookupValue := BitBuffer and AbExtractMask[aDistanceTree.LookupBitLength]; {..get the encoded symbol} {$IFOPT C+} {if Assertions are on} EncodedSymbol := aDistanceTree.Decode(LookupValue); {$ELSE} EncodedSymbol := aDistanceTree.Decodes^[LookupValue]; {$ENDIF} {..extract the data} Symbol := EncodedSymbol and $FFFF; SymbolCodeLen := (EncodedSymbol shr 16) and $FF; {check that the distance symbol is less than or equal to 29} if (not aDeflate64) and (Symbol > 29) then raise EAbInternalInflateError.Create( 'decoded an invalid distance symbol: greater than 29 [DecodeData]'); {..calculate the extra bits for the distance} ExtraBitCount := EncodedSymbol shr 24; {..calculate the distance} if (ExtraBitCount = 0) then begin Distance := dfc_DistanceBase[Symbol]; {$IFOPT C+} aInStrm.DiscardBits(SymbolCodeLen); {$ELSE} if (aInStrm.BitsLeft < SymbolCodeLen) then aInStrm.DiscardMoreBits(SymbolCodeLen) else begin aInStrm.BitBuffer := aInStrm.BitBuffer shr SymbolCodeLen; aInStrm.BitsLeft := aInStrm.BitsLeft - SymbolCodeLen; end; {$ENDIF} end else begin Distance := dfc_DistanceBase[Symbol] + ((BitBuffer shr SymbolCodeLen) and AbExtractMask[ExtraBitCount]); BitCount := SymbolCodeLen + ExtraBitCount; {$IFOPT C+} aInStrm.DiscardBits(BitCount); {$ELSE} if (aInStrm.BitsLeft < BitCount) then aInStrm.DiscardMoreBits(BitCount) else begin aInStrm.BitBuffer := aInStrm.BitBuffer shr BitCount; aInStrm.BitsLeft := aInStrm.BitsLeft - BitCount; end; {$ENDIF} end; {duplicate the characters in the sliding window} aOutWindow.AddLenDist(Length, Distance); end; {extract the next symbol} {..grab the lookup set of bits} if aDeflate64 then BitCount := aLiteralTree.LookupBitLength + 16 else BitCount := aLiteralTree.LookupBitLength + 5; {$IFOPT C+} BitBuffer := aInStrm.PeekBits(BitCount); {$ELSE} if (aInStrm.BitsLeft < BitCount) then BitBuffer := aInStrm.PeekMoreBits(BitCount) else BitBuffer := aInStrm.BitBuffer and AbExtractMask[BitCount]; {$ENDIF} LookupValue := BitBuffer and AbExtractMask[aLiteralTree.LookupBitLength]; {..get the encoded symbol} {$IFOPT C+} {if Assertions are on} EncodedSymbol := aLiteralTree.Decode(LookupValue); {$ELSE} EncodedSymbol := aLiteralTree.Decodes^[LookupValue]; {$ENDIF} {..extract the data} Symbol := EncodedSymbol and $FFFF; SymbolCodeLen := (EncodedSymbol shr 16) and $FF;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -