Subversion Repositories autosfx

Rev

Blame | Last modification | View Log | RSS feed

  1. unit ZMExtrLZ7719;
  2.  
  3. (*
  4.   ZMExtrLZ7719.pas - LZ77 stream expander
  5.     Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht,
  6.       Eric W. Engler and Chris Vleghert.
  7.  
  8.         This file is part of TZipMaster Version 1.9.
  9.  
  10.     TZipMaster is free software: you can redistribute it and/or modify
  11.     it under the terms of the GNU Lesser General Public License as published by
  12.     the Free Software Foundation, either version 3 of the License, or
  13.     (at your option) any later version.
  14.  
  15.     TZipMaster is distributed in the hope that it will be useful,
  16.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.     GNU Lesser General Public License for more details.
  19.  
  20.     You should have received a copy of the GNU Lesser General Public License
  21.     along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
  22.  
  23.     contact: problems@delphizip.org (include ZipMaster in the subject).
  24.     updates: http://www.delphizip.org
  25.     DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
  26.  
  27.   modified 2007-11-05
  28. ---------------------------------------------------------------------------*)
  29.  
  30. interface
  31.  
  32. uses
  33.   Classes;
  34.  
  35. // expects src at orig_size (integer), data (bytes)
  36. function LZ77Extract(dst, src: TStream; size: integer): integer;
  37.  
  38. implementation
  39.    
  40. const
  41.   N = 4096;
  42.   NMask = $FFF; //(N-1)
  43.   F = 16;
  44.                  
  45. function GetByte(var bytes: Integer; Src: TStream): Integer;
  46. var
  47.   cb: Byte;
  48. begin
  49.   Result := -1;
  50.   if (bytes > 4) and (Src.Size > Src.Position) then
  51.   begin
  52.     dec(bytes);
  53.     if Src.Read(cb, 1) = 1 then
  54.       Result := Integer(cb)
  55.     else
  56.       bytes := 0;
  57.   end;
  58. end;
  59.  
  60. function LZ77Extract(dst, src: TStream; size: integer): integer;
  61. var
  62.   bits: Integer;
  63.   Buffer: array of Byte;
  64.   bytes: integer;
  65.   ch: Integer;
  66.   File_Size: integer;
  67.   i: Integer;
  68.   j: Integer;
  69.   len: Integer;
  70.   mask: Integer;
  71.   written: integer;
  72. begin
  73.   bytes := size;
  74.   if bytes < 0 then
  75.     bytes := HIGH(Integer);
  76.   src.ReadBuffer(File_Size, sizeof(integer));
  77.   written := 0;
  78.  
  79.   SetLength(Buffer, N);
  80.   i := N - F;
  81.   while True do
  82.   begin
  83.     bits := GetByte(bytes, src);
  84.     if (bits < 0) then
  85.       break;
  86.  
  87.     mask := 1;
  88.     while mask < 256 do
  89.     begin
  90.       if (bits and mask) = 0 then
  91.       begin
  92.         j := GetByte(bytes, src);
  93.         if j < 0 then
  94.           break;
  95.         len := GetByte(bytes, src);
  96.         inc(j, (len and $F0) shl 4);
  97.         len := (len and 15) + 3;
  98.         while len > 0 do
  99.         begin
  100.           Buffer[i] := Buffer[j];
  101.           dst.WriteBuffer(Buffer[i], 1);
  102.           inc(written);
  103.           j := succ(j) and NMask;
  104.           i := succ(i) and NMask;
  105.           dec(len);
  106.         end;
  107.       end
  108.       else
  109.       begin
  110.         ch := GetByte(bytes, src);
  111.         if ch < 0 then
  112.           break;
  113.         Buffer[i] := Byte(ch {and 255});
  114.         dst.WriteBuffer(ch, 1);
  115.         inc(written);
  116.         i := succ(i) and NMask;
  117.       end;
  118.       inc(mask, mask);
  119.     end;
  120.   end;
  121.   if (File_Size = written) and (bytes = 4) then
  122.     Result := 0   // good
  123.   else
  124.     if bytes = 4 then
  125.       Result := -2   // wrong length
  126.     else
  127.       Result := -1; // invalid data
  128.   Buffer := nil;
  129. end;
  130.  
  131. end.
  132.