⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abdfdec.pas

📁 Lazarus is a free and open source development tool for the FreePascal Compiler. The purpose of the p
💻 PAS
📖 第 1 页 / 共 2 页
字号:
(* ***** 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 + -