(* ***** 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: AbDfXlat.pas *} {*********************************************************} {* Deflate length/dist to symbol translator *} {*********************************************************} unit AbDfXlat; {$I AbDefine.inc} interface uses SysUtils; type TAbDfTranslator = class private FBuffer : PAnsiChar; FLenSymbols : PByteArray; {for lengths 3..258} FLongDistSymbols : PByteArray; {for distances 32769..65536 (deflate64)} FMediumDistSymbols : PByteArray; {for distances 257..32768} FShortDistSymbols : PByteArray; {for distances 1..256} protected procedure trBuild; public constructor Create; destructor Destroy; override; function TranslateLength(aLen : integer): integer; function TranslateDistance(aDist : integer) : integer; property LenSymbols : PByteArray read FLenSymbols; property LongDistSymbols : PByteArray read FLongDistSymbols; property MediumDistSymbols : PByteArray read FMediumDistSymbols; property ShortDistSymbols : PByteArray read FShortDistSymbols; end; var AbSymbolTranslator : TAbDfTranslator; implementation uses AbDfBase; {====================================================================} constructor TAbDfTranslator.Create; begin {create the ancestor} inherited Create; {allocate the translation arrays (the buffer *must* be zeroed)} FBuffer := AllocMem(256 + 2 + 256 + 256); FLenSymbols := PByteArray(FBuffer); FLongDistSymbols := PByteArray(FBuffer + 256); FMediumDistSymbols := PByteArray(FBuffer + 256 + 2); FShortDistSymbols := PByteArray(FBuffer + 256 + 2 + 256); {build the translation arrays} trBuild; end; {--------} destructor TAbDfTranslator.Destroy; begin if (FBuffer <> nil) then FreeMem(FBuffer); inherited Destroy; end; {--------} function TAbDfTranslator.TranslateDistance(aDist : integer) : integer; begin {save against dumb programming mistakes} Assert((1 <= aDist) and (aDist <= 65536), 'TAbDfTranslator.Translate: distance should be 1..65536'); {translate the distance} if (aDist <= 256) then Result := FShortDistSymbols[aDist - 1] else if (aDist <= 32768) then Result := FMediumDistSymbols[((aDist - 1) div 128) - 2] else Result := FLongDistSymbols[((aDist - 1) div 16384) - 2]; end; {--------} function TAbDfTranslator.TranslateLength(aLen : integer): integer; begin {save against dumb programming mistakes} Assert((3 <= aLen) and (aLen <= 65536), 'TAbDfTranslator.Translate: length should be 3..65536'); {translate the length} dec(aLen, 3); if (0 <= aLen) and (aLen <= 255) then Result := FLenSymbols[aLen] + 257 else Result := 285; end; {--------} procedure TAbDfTranslator.trBuild; var i : integer; Len : integer; Dist : integer; Value : integer; begin {initialize the length translation array; elements will contain (Symbol - 257) for a given (length - 3)} for i := low(dfc_LengthBase) to pred(high(dfc_LengthBase)) do begin Len := dfc_LengthBase[i] - 3; FLenSymbols[Len] := i; end; FLenSymbols[255] := 285 - 257; Value := -1; for i := 0 to 255 do begin if (Value < FLenSymbols[i]) then Value := FLenSymbols[i] else FLenSymbols[i] := Value; end; {initialize the short distance translation array: it will contain the Symbol for a given (distance - 1) where distance <= 256} for i := 0 to 15 do begin Dist := dfc_DistanceBase[i] - 1; FShortDistSymbols[Dist] := i; end; Value := -1; for i := 0 to 255 do begin if (Value < FShortDistSymbols[i]) then Value := FShortDistSymbols[i] else FShortDistSymbols[i] := Value; end; {initialize the medium distance translation array: it will contain the Symbol for a given (((distance - 1) div 128) - 2) where distance is in the range 256..32768} for i := 16 to 29 do begin Dist := ((dfc_DistanceBase[i] - 1) div 128) - 2; FMediumDistSymbols[Dist] := i; end; Value := -1; for i := 0 to 255 do begin if (Value < FMediumDistSymbols[i]) then Value := FMediumDistSymbols[i] else FMediumDistSymbols[i] := Value; end; {initialize the long distance translation array: it will contain the Symbol for a given ((distance - 1) div 16384) - 2) for distances over 32768 in deflate64} FLongDistSymbols[0] := 30; FLongDistSymbols[1] := 31; end; {====================================================================} initialization AbSymbolTranslator := TAbDfTranslator.Create; finalization AbSymbolTranslator.Free; end.