Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π€ΡƒΠ½Π΄Π°ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Π΅ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡ‹ ΠΈ структуры Π΄Π°Π½Π½Ρ‹Ρ… Π² DelphiΒ». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 106

Автор Π”ΠΆΡƒΠ»ΠΈΠ°Π½ Π‘Π°ΠΊΠ½Π΅Π»Π»

FStart : PAnsiChar;{Π½Π°Ρ‡Π°Π»ΠΎ ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π³ΠΎ ΠΎΠΊΠ½Π°}

FStartOffset : longint;{смСщСниС ΠΏΠΎΡ‚ΠΎΠΊΠ° для FStart}

FStream : TStream;{Π±Π°Π·ΠΎΠ²Ρ‹ΠΉ ΠΏΠΎΡ‚ΠΎΠΊ}

protected


procedure swAdvanceAfterAdd(aCount : integer);

procedure swReadFromStream;

procedure swSetCapacity(aValue : longint);

procedure swWriteToStream(aFinalBlock : boolean);

public


constructor Create(aStream : TStream;

aCompressing : boolean);

destructor Destroy; override;

{ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ ΠΊΠ°ΠΊ Π²ΠΎ врСмя сТатия, Ρ‚Π°ΠΊ ΠΈ Π²ΠΎ врСмя восстановлСния}

procedure Clear;

{ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Π²ΠΎ врСмя сТатия}

procedure Advance(aCount : integer);

function Compare(aOffset : longint;

var aDistance : integer): integer;

procedure GetNextSignature(var aMS : TtdLZSignature;

varaOffset : longint);

{ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅ Π²ΠΎ врСмя восстановлСния}

procedure AddChar(aCh : AnsiChar);

procedureAddCode(aDistance : integer;

aLength : integer);

property Name : TtdNameString read FName write FName;

end;

constructor TtdLZSlidingWindow.Create(aStream : TStream;

aCompressing : boolean);

begin

inherited Create;

{ΡΠΎΡ…Ρ€Π°Π½ΠΈΡ‚ΡŒ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹}

FCompressing := aCompressing;

FStream := aStream;

{ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Ρ€Π°Π·ΠΌΠ΅Ρ€ ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π³ΠΎ ΠΎΠΊΠ½Π°: согласно принятого опрСдСлСния Ρ€Π°Π·ΠΌΠ΅Ρ€ ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π³ΠΎ ΠΎΠΊΠ½Π° Ρ€Π°Π²Π΅Π½ 8192 Π±Π°ΠΉΡ‚Π°ΠΌ плюс 10 Π±Π°ΠΉΡ‚ΠΎΠ² для ΡƒΠΏΡ€Π΅ΠΆΠ΄Π°ΡŽΡ‰Π΅Π³ΠΎ просмотра}

swSetCapacity(tdcLZSlidingWindowSize + tdcLZLookAheadSize);

{ΡΠ±Ρ€ΠΎΡΠΈΡ‚ΡŒ Π±ΡƒΡ„Π΅Ρ€ ΠΈ, Ссли выполняСтся сТатиС, ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ ΠΈΠ· сТимаСмого ΠΏΠΎΡ‚ΠΎΠΊΠ°}

Clear;

if aCompressing then

swReadFromStream;

end;

destructor TtdLZSlidingWindow.Destroy;

begin

if Assigned(FBuffer) then begin

{Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡŒ запись Π² Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ, Ссли выполняСтся сТатиС}

if not FCompressing then

swWriteToStream(true);

{ΠΎΡΠ²ΠΎΠ±ΠΎΠ΄ΠΈΡ‚ΡŒ Π±ΡƒΡ„Π΅Ρ€}

FreeMem(FBuffer, FBufferEnd - FBuffer);

end;

inherited Destroy;

end;


procedure TtdLZSlidingWindow.AddChar(aCh : AnsiChar);

begin

{Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ символ Π² Π±ΡƒΡ„Π΅Ρ€}

FCurrent^ :=aCh;

{ΡΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π΅ ΠΎΠΊΠ½ΠΎ Π½Π° ΠΎΠ΄ΠΈΠ½ символ}

swAdvanceAfterAdd(1);

end;


procedure TtdLZSlidingWindow.AddCode(aDistance : integer;

aLength : integer);

var

FromChar : PAnsiChar;

ToChar : PAnsiChar;

i : integer;

begin

{ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ для выполнСния копирования Π΄Π°Π½Π½Ρ‹Ρ…; ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ Π² Π΄Π°Π½Π½ΠΎΠΌ случаС нСльзя ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρƒ Move, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‡Π°ΡΡ‚ΡŒ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌΡ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π° Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹ΠΌ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ Π΄Π°Π½Π½Ρ‹Ρ…}

FromChar := FCurrent - aDistance;

ToChar := FCurrent;

for i := 1 to aLength do

begin

ToChar^ := FromChar^;

inc(FromChar);

inc(ToChar);

end;

{ΡΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ Π½Π°Ρ‡Π°Π»ΠΎ ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π³ΠΎ ΠΎΠΊΠ½Π°}

swAdvanceAfterAdd(aLength);

end;


procedure TtdLZSlidingWindow.swAdvanceAfterAdd(aCount : integer);

begin

{ΠΏΡ€ΠΈ нСобходимости ΡΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ Π½Π°Ρ‡Π°Π»ΠΎ ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π³ΠΎ ΠΎΠΊΠ½Π°}

if ( (FCurrent - FStart) >= tdcLZSlidingWindowSize) then begin

inc(FStart, aCount);

inc(FStartOffset, aCount);

end;

{ΡΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ}

inc(FCurrent, aCount);

{ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ смСщСниС Π² Π·ΠΎΠ½Ρƒ пСрСполнСния}

if (FStart >= FMidPoint) then begin

{Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅ Π² ΠΏΠΎΡ‚ΠΎΠΊ (ΠΎΡ‚ ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ FBuffer Π΄ΠΎ ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ FStart)}

swWriteToStream(false);

{ΠΏΠ΅Ρ€Π΅ΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Π΅ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ Π² Π½Π°Ρ‡Π°Π»ΠΎ Π±ΡƒΡ„Π΅Ρ€Π°}

Move(FStart^, FBuffer^, FCurrent - FStart );

{ΡΠ±Ρ€ΠΎΡΠΈΡ‚ΡŒ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ}

dec(FCurrent, FStart - FBuffer);

FStart := FBuffer;

end;

end;


procedure TtdLZSlidingWindow.swSetCapacity(aValue : longint);

var

NewQueue : PAnsiChar;

begin

{ΠΎΠΊΡ€ΡƒΠ³Π»ΠΈΡ‚ΡŒ Π·Π°ΠΏΡ€ΠΎΡˆΠ΅Π½Π½Ρ‹ΠΉ объСм Π΄ΠΎ блиТайшСго значСния, ΠΊΡ€Π°Ρ‚Π½ΠΎΠ³ΠΎ 64 Π±Π°ΠΉΡ‚Π°ΠΌ}

aValue := (aValue + 63) and $7FFFFFC0;

{Ρ€Π°ΡΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Π½ΠΎΠ²Ρ‹ΠΉ Π±ΡƒΡ„Π΅Ρ€}

GetMem(NewQueue, aValue * 2);

{ΡƒΠ½ΠΈΡ‡Ρ‚ΠΎΠΆΠΈΡ‚ΡŒ старый Π±ΡƒΡ„Π΅Ρ€}

if ( FBuffer <> nil ) then

FreeMem(FBuffer, FBufferEnd - FBuffer);

{ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΉ/ΠΊΠΎΠ½Π΅Ρ‡Π½Ρ‹ΠΉ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ}

FBuffer := NewQueue;

FStart := NewQueue;

FCurrent := NewQueue;

FLookAheadEnd := NewQueue;

FBufferEnd := NewQueue + (aValue * 2);

FMidPoint := NewQueue + aValue;

end;


procedure TtdLZSlidingWindow.swWriteToStream(aFinalBlock : boolean);

var

BytesToWrite : longint;

begin

{Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠ΅Ρ€Π΅Π΄ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰ΠΈΠΌ ΠΎΠΊΠ½ΠΎΠΌ}

if aFinalBlock then

BytesToWrite := FCurrent - Fbuffer else

BytesToWrite := FStart - FBuffer;

FStream.WriteBuffer(FBuffer^, BytesToWrite);

end;


ΠœΠ΅Ρ‚ΠΎΠ΄ AddChar добавляСт ΠΎΠ΄ΠΈΠ½ΠΎΡ‡Π½Ρ‹ΠΉ Π»ΠΈΡ‚Π΅Ρ€Π°Π»ΡŒΠ½Ρ‹ΠΉ символ Π² ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π΅ ΠΎΠΊΠ½ΠΎ ΠΈ сдвигаСт это ΠΎΠΊΠ½ΠΎ Π²ΠΏΠ΅Ρ€Π΅Π΄ Π½Π° ΠΎΠ΄ΠΈΠ½ Π±Π°ΠΉΡ‚. Π’Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΉ ΠΌΠ΅Ρ‚ΠΎΠ΄ swAdvanceAfterAdd выполняСт Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹ΠΉ сдвиг ΠΈ послС сдвига ΠΎΠΊΠ½Π° провСряСт, ΠΌΠΎΠΆΠ΅Ρ‚ Π»ΠΈ Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ Π±Π»ΠΎΠΊ Π±Ρ‹Ρ‚ΡŒ записан Π² Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ. ΠœΠ΅Ρ‚ΠΎΠ΄ AddCode добавляСт ΠΏΠ°Ρ€Ρƒ расстояниС/Π΄Π»ΠΈΠ½Π° Π² ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π΅ ΠΎΠΊΠ½ΠΎ, ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΌΡƒ копируя символы ΠΈΠ· ΡƒΠΆΠ΅ Π΄Π΅ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ части ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π³ΠΎ ΠΎΠΊΠ½Π° Π² Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ ΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ. Π—Π°Ρ‚Π΅ΠΌ ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π΅ ΠΎΠΊΠ½ΠΎ сдвигаСтся Π²ΠΏΠ΅Ρ€Π΅Π΄.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ достаточно Π»Π΅Π³ΠΊΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΊΠΎΠ΄ восстановлСния. (Π‘ΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΊΠΎΠ΄ восстановлСния Ρ€Π°Π½ΡŒΡˆΠ΅ ΠΊΠΎΠ΄Π° сТатия каТСтся нСсколько нССстСствСнным, Π½ΠΎ Π² Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ сТатых Π΄Π°Π½Π½Ρ‹Ρ… Π½Π°ΡΡ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½, Ρ‡Ρ‚ΠΎ это ΠΌΠΎΠΆΠ½ΠΎ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, это ΠΏΡ€ΠΎΡ‰Π΅!) ΠœΡ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ основной Ρ†ΠΈΠΊΠ» Π² Π²ΠΈΠ΄Π΅ ΠΌΠ°ΡˆΠΈΠ½Ρ‹ состояний с трСмя состояниями: считываниС ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π±Π°ΠΉΡ‚Π° Ρ„Π»Π°Π³Π°, считываниС ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° символа ΠΈ, Π½Π°ΠΊΠΎΠ½Π΅Ρ†, считываниС ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΊΠΎΠ΄Π° расстояния/Π΄Π»ΠΈΠ½Ρ‹. Код ΠΏΠΎΠΊΠ°Π·Π°Π½ Π² листингС 11.24. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ восстановлСния осущСствляСтся ΠΏΠΎ количСству Π±Π°ΠΉΡ‚ΠΎΠ² Π² нСсТатом ΠΏΠΎΡ‚ΠΎΠΊΠ΅, записанному ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΎΠΉ сТатия Π² Π½Π°Ρ‡Π°Π»ΠΎ сТатого ΠΏΠΎΡ‚ΠΎΠΊΠ°.

ПослС ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π²Ρ…ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ являСтся Π·Π°ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌ с ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠ° LZ77, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° считываСт количСство нСсТатых Π΄Π°Π½Π½Ρ‹Ρ…. Π—Π°Ρ‚Π΅ΠΌ осущСствляСтся Π²Ρ…ΠΎΠ΄ Π² ΠΏΡ€ΠΎΡΡ‚ΡƒΡŽ ΠΌΠ°ΡˆΠΈΠ½Ρƒ состояний, состояния ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ΡΡ Π±Π°ΠΉΡ‚ΠΎΠΌ Ρ„Π»Π°Π³Π°, считываСмого ΠΈΠ· Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°. Если Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ состояниС -dsGetFlagByte, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° считываСт ΠΈΠ· Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Π±Π°ΠΉΡ‚ Ρ„Π»Π°Π³Π°. Если состояниС - dsGetChar, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° считываСт ΠΈΠ· Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° Π»ΠΈΡ‚Π΅Ρ€Π°Π»ΡŒΠ½Ρ‹ΠΉ символ ΠΈ добавляСт Π΅Π³ΠΎ Π² ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π΅ ΠΎΠΊΠ½ΠΎ. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС состояниСм Π±ΡƒΠ΄Π΅Ρ‚ dsGetDistLen, ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° считываСт ΠΈΠ· Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΏΠ°Ρ€Ρƒ расстояниС/ Π΄Π»ΠΈΠ½Π° ΠΈ добавляСт Π΅Π΅ Π² ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π΅ ΠΎΠΊΠ½ΠΎ. Π­Ρ‚ΠΎΡ‚ процСсс продолТаСтся Π΄ΠΎ Ρ‚Π΅Ρ… ΠΏΠΎΡ€, ΠΏΠΎΠΊΠ° Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ восстановлСны всС Π΄Π°Π½Π½Ρ‹Π΅ Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°.

Листинг 11.24. Основной ΠΊΠΎΠ΄ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ сТатия, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰Π΅ΠΉ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ LZ77


procedure TDLZDecompress(aInStream, aOutStream : TStream);

type

TDecodeState = (dsGetFlagByte, dsGetChar, dsGetDistLen);

var

SlideWin : TtdLZSlidingWindow;

BytesUnpacked : longint;

TotalSize : longint;

LongValue : longint;

DecodeState : TDecodeState;

FlagByte : byte;

FlagMask : byte;

NextChar : AnsiChar;

NextDistLen : longint;

CodeCount : integer;

Len : integer;

begin

SlideWin := TtdLZSlidingWindow.Create(aOutStream, false);

try

SlideWin.Name := 'LZ77 Decompress sliding window';

{ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΈΠ· ΠΏΠΎΡ‚ΠΎΠΊΠ° Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ: символы 'TDLZ', Π·Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ слСдуСт Ρ€Π°Π·ΠΌΠ΅Ρ€ Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°}

aInStream.ReadBuffer(LongValue, sizeof(LongValue));

if (LongValue <> TDLZHeader) then

RaiseError(tdeLZBadEncodedStream, 'TDLZDecompress');

aInStream.ReadBuffer(TotalSize, sizeof(TotalSize));

{ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΈΡ‚ΡŒΡΡ ΠΊ Π²ΠΎΡΡΡ‚Π°Π½ΠΎΠ²Π»Π΅Π½ΠΈΡŽ}

BytesUnpacked := 0;

NextDistLen := 0;

DecodeState := dsGetFlagByte;

CodeCount := 0;

FlagMask := 1;

{Π΄ΠΎ Ρ‚Π΅Ρ… nop, ΠΏΠΎΠΊΠ° ΠΎΡΡ‚Π°ΡŽΡ‚ΡΡ Π±Π°ΠΉΡ‚Ρ‹ для восстановлСния...}

while (BytesUnpacked < TotalSize) do

begin

{ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ элСмСнт Π² Π΄Π°Π½Π½ΠΎΠΌ состоянии дСкодирования}

case DecodeState of

dsGetFlagByte : begin

aInStream.ReadBuffer(FlagByte, 1);

CodeCount := 0;

FlagMask := 1;

end;

dsGetChar : begin

aInStream.ReadBuffer(NextChar, 1);

SlideWin.AddChar(NextChar);

inc(BytesUnpacked);

end;

dsGetDistLen : begin

aInStream.ReadBuffer(NextDistLen, 2);

Len := (NextDistLen and tdcLZLengthMask) + 3;

SlideWin.AddCode( (NextDistLen shr tdcLZDistanceShift) + 1, Len);

inc(BytesUnpacked, Len);

end;

end;

{Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ состояниС дСкодирования}

inc(CodeCount);

if (CodeCount > 8) then

DecodeState := dsGetFlagByte else begin

if ((FlagByte and FlagMask) = 0) then

DecodeState := dsGetChar

else

DecodeState := dsGetDistLen;

FlagMask := FlagMask shl 1;

end;

end;

finally

SlideWin.Free;

end;

{try.. finally}

end;


Π‘ΠΆΠ°Ρ‚ΠΈΠ΅ LZ77

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΠΎΡ€Π° Ρ€Π°ΡΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ сТатия. ΠŸΡ€ΠΈ этом ΠΎΡ‡Π΅Π½ΡŒ быстро ΠΌΡ‹ сталкиваСмся со ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ: поиском Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ Π΄Π»ΠΈΠ½Π½ΠΎΠ³ΠΎ соотвСтствия ΠΌΠ΅ΠΆΠ΄Ρƒ строкой Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ ΠΈ ΠΏΡ€Π΅Π΄ΡˆΠ΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ 8192 Π±Π°ΠΉΡ‚Π°ΠΌΠΈ. ΠžΡ‚ ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠ³ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° - поиска Π²ΠΎ всСм Π±ΡƒΡ„Π΅Ρ€Π΅ - придСтся ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ ΠΎΡ‚ΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ ΠΈΠ·-Π·Π° Π΅Π³ΠΎ слишком Π½ΠΈΠ·ΠΊΠΎΠΉ эффСктивности.

Π’ своСй ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Π΅ Π—ΠΈΠ² ΠΈ Π›Π΅ΠΌΠΏΠ΅Π»ΡŒ Π½Π΅ ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠΈΠ»ΠΈ ΠΏΠΎΡ‡Ρ‚ΠΈ Π½ΠΈΠΊΠ°ΠΊΠΈΡ… Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΉ. КоС-ΠΊΡ‚ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π΄Π΅Ρ€Π΅Π²ΠΎ Π±ΠΈΠ½Π°Ρ€Π½ΠΎΠ³ΠΎ поиска, построСнноС ΠΏΠΎΠ²Π΅Ρ€Ρ… ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π³ΠΎ ΠΎΠΊΠ½Π°, для хранСния ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹Ρ… Π²ΡΡ‚Ρ€Π΅Ρ‡Π°Π²ΡˆΠΈΡ…ΡΡ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΡ… строк (ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠ»ΡƒΠΆΠΈΡ‚ΡŒ рСализация, созданная ΠœΠ°Ρ€ΠΊΠΎΠΌ НСльсоном (Mark Nelson) [15]). Однако ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ этого ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ возникновСнию ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ, связанных с Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ Π½ΡƒΠΆΠ½ΠΎ Π±Π΅ΡΠΏΠΎΠΊΠΎΠΈΡ‚ΡŒΡΡ ΠΎ балансировкС Π΄Π΅Ρ€Π΅Π²Π° ΠΈ ΠΎΠ± ΠΈΠ·Π±Π°Π²Π»Π΅Π½ΠΈΠΈ ΠΎΡ‚ строк, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ ΡƒΠ΄Π°Π»Π΅Π½Ρ‹ ΠΈΠ· ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π³ΠΎ ΠΎΠΊΠ½Π°. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ ΠΌΡ‹ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ совСтом, ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹ΠΌ Π² ΠΎΠ½Π»Π°ΠΉΠ½ΠΎΠ²ΠΎΠΌ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π΅ Deflate Compressed

Data Format Specification (БпСцификация Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Π΄Π°Π½Π½Ρ‹Ρ…, сТатых ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠΌ Deflate) (RFC 1951) ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌ Ρ…Π΅Ρˆ-Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ.

Алгоритм выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ: ΠΌΡ‹ просматриваСм Ρ‚Ρ€ΠΈ символа Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ - Π±ΡƒΠ΄Π΅ΠΌ Π½Π°Π·Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΡ… сигнатурой (signature). Π‘ΠΈΠ³Π½Π°Ρ‚ΡƒΡ€Π° Ρ…Π΅ΡˆΠΈΡ€ΡƒΠ΅Ρ‚ΡΡ с ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ², Π° Π·Π°Ρ‚Π΅ΠΌ Ρ…Π΅Ρˆ-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для доступа ΠΊ элСмСнту Π² Ρ…Π΅Ρˆ-Ρ‚Π°Π±Π»ΠΈΡ†Π΅, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰Π΅ΠΌΡƒ связываниС. Π¦Π΅ΠΏΠΎΡ‡ΠΊΠΈ ΠΈΠ»ΠΈ связныС списки Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ элСмСнтС Ρ…Π΅Ρˆ-Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ Π±ΡƒΠ΄ΡƒΡ‚ ΡΠΎΡΡ‚ΠΎΡΡ‚ΡŒ ΠΈΠ· ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚Π΅ΠΉ элСмСнтов, ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… состоит ΠΈΠ· Ρ‚Ρ€Π΅Ρ…ΡΠΈΠΌΠ²ΠΎΠ»ΡŒΠ½Ρ‹Ρ… сигнатур ΠΈ значСния смСщСния сигнатуры Π²ΠΎ Π²Ρ…ΠΎΠ΄Π½ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅.

Π˜Ρ‚Π°ΠΊ, ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ сигнатуру Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ ΠΈ Ρ…Π΅ΡˆΠΈΡ€ΡƒΠ΅ΠΌ Π΅Π΅ Π² связный список, ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΉ собой - ΠΎΠ΄Π½Ρƒ ΠΈΠ· Ρ†Π΅ΠΏΠΎΡ‡Π΅ΠΊ Π² Ρ…Π΅Ρˆ-Ρ‚Π°Π±Π»ΠΈΡ†Π΅. Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ просматриваСм связный список ΠΈ сравниваСм Ρ…Ρ€Π°Π½ΡΡ‰ΡƒΡŽΡΡ Π² Π½Π΅ΠΌ сигнатуру ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ элСмСнта с ΠΈΠΌΠ΅ΡŽΡ‰ΠΈΠΌΠΈΡΡ сигнатурами. ΠŸΡ€ΠΈ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠΈ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰Π΅ΠΉ сигнатуры ΠΌΡ‹ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΠΌ Π² ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π΅ ΠΎΠΊΠ½ΠΎ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ смСщСния элСмСнта, Π° Π·Π°Ρ‚Π΅ΠΌ сравниваСм символы Π² ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅ΠΌ ΠΎΠΊΠ½Π΅ с символами Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΏΠΎΠ·ΠΈΡ†ΠΈΠΈ. ΠœΡ‹ повторяСм этот процСсс для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ элСмСнта Π² связном спискС, ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‰Π΅Π³ΠΎ с Π΄Π°Π½Π½ΠΎΠΉ сигнатурой, ΠΈ Π·Π°ΠΏΠΎΠΌΠΈΠ½Π°Π΅ΠΌ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ Π΄Π»ΠΈΠ½Π½ΠΎΠ΅ Π½Π°ΠΉΠ΄Π΅Π½Π½ΠΎΠ΅ соотвСтствиС.