Subversion Repositories autosfx

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 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.