xref: /netbsd-src/external/gpl3/gdb/dist/zlib/contrib/delphi/ZLib.pas (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
1212397c6Schristos {*******************************************************}
2212397c6Schristos {                                                       }
3212397c6Schristos {       Borland Delphi Supplemental Components          }
4212397c6Schristos {       ZLIB Data Compression Interface Unit            }
5212397c6Schristos {                                                       }
6212397c6Schristos {       Copyright (c) 1997,99 Borland Corporation       }
7212397c6Schristos {                                                       }
8212397c6Schristos {*******************************************************}
9212397c6Schristos 
10212397c6Schristos { Updated for zlib 1.2.x by Cosmin Truta <cosmint@cs.ubbcluj.ro> }
11212397c6Schristos 
12212397c6Schristos unit ZLib;
13212397c6Schristos 
14212397c6Schristos interface
15212397c6Schristos 
16212397c6Schristos uses SysUtils, Classes;
17212397c6Schristos 
18212397c6Schristos type
ppData()19212397c6Schristos   TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
20212397c6Schristos   TFree = procedure (AppData, Block: Pointer); cdecl;
21212397c6Schristos 
22212397c6Schristos   // Internal structure.  Ignore.
23212397c6Schristos   TZStreamRec = packed record
24212397c6Schristos     next_in: PChar;       // next input byte
25212397c6Schristos     avail_in: Integer;    // number of bytes available at next_in
26212397c6Schristos     total_in: Longint;    // total nb of input bytes read so far
27212397c6Schristos 
28212397c6Schristos     next_out: PChar;      // next output byte should be put here
29212397c6Schristos     avail_out: Integer;   // remaining free space at next_out
30212397c6Schristos     total_out: Longint;   // total nb of bytes output so far
31212397c6Schristos 
32212397c6Schristos     msg: PChar;           // last error message, NULL if no error
33212397c6Schristos     internal: Pointer;    // not visible by applications
34212397c6Schristos 
35212397c6Schristos     zalloc: TAlloc;       // used to allocate the internal state
36212397c6Schristos     zfree: TFree;         // used to free the internal state
37212397c6Schristos     AppData: Pointer;     // private data object passed to zalloc and zfree
38212397c6Schristos 
39212397c6Schristos     data_type: Integer;   // best guess about the data type: ascii or binary
40212397c6Schristos     adler: Longint;       // adler32 value of the uncompressed data
41212397c6Schristos     reserved: Longint;    // reserved for future use
42212397c6Schristos   end;
43212397c6Schristos 
44212397c6Schristos   // Abstract ancestor class
45212397c6Schristos   TCustomZlibStream = class(TStream)
46212397c6Schristos   private
47212397c6Schristos     FStrm: TStream;
48212397c6Schristos     FStrmPos: Integer;
49212397c6Schristos     FOnProgress: TNotifyEvent;
50212397c6Schristos     FZRec: TZStreamRec;
51212397c6Schristos     FBuffer: array [Word] of Char;
52212397c6Schristos   protected
53212397c6Schristos     procedure Progress(Sender: TObject); dynamic;
54212397c6Schristos     property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
55212397c6Schristos     constructor Create(Strm: TStream);
56212397c6Schristos   end;
57212397c6Schristos 
58212397c6Schristos { TCompressionStream compresses data on the fly as data is written to it, and
59212397c6Schristos   stores the compressed data to another stream.
60212397c6Schristos 
61212397c6Schristos   TCompressionStream is write-only and strictly sequential. Reading from the
62212397c6Schristos   stream will raise an exception. Using Seek to move the stream pointer
63212397c6Schristos   will raise an exception.
64212397c6Schristos 
65212397c6Schristos   Output data is cached internally, written to the output stream only when
66212397c6Schristos   the internal output buffer is full.  All pending output data is flushed
67212397c6Schristos   when the stream is destroyed.
68212397c6Schristos 
69212397c6Schristos   The Position property returns the number of uncompressed bytes of
70212397c6Schristos   data that have been written to the stream so far.
71212397c6Schristos 
72212397c6Schristos   CompressionRate returns the on-the-fly percentage by which the original
73212397c6Schristos   data has been compressed:  (1 - (CompressedBytes / UncompressedBytes)) * 100
74212397c6Schristos   If raw data size = 100 and compressed data size = 25, the CompressionRate
75212397c6Schristos   is 75%
76212397c6Schristos 
77212397c6Schristos   The OnProgress event is called each time the output buffer is filled and
78212397c6Schristos   written to the output stream.  This is useful for updating a progress
79212397c6Schristos   indicator when you are writing a large chunk of data to the compression
80212397c6Schristos   stream in a single call.}
81212397c6Schristos 
82212397c6Schristos 
83212397c6Schristos   TCompressionLevel = (clNone, clFastest, clDefault, clMax);
84212397c6Schristos 
85212397c6Schristos   TCompressionStream = class(TCustomZlibStream)
86212397c6Schristos   private
GetCompressionRate()87212397c6Schristos     function GetCompressionRate: Single;
88212397c6Schristos   public
89212397c6Schristos     constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
90212397c6Schristos     destructor Destroy; override;
Read(var Buffer; Count: Longint)91212397c6Schristos     function Read(var Buffer; Count: Longint): Longint; override;
Write(const Buffer; Count: Longint)92212397c6Schristos     function Write(const Buffer; Count: Longint): Longint; override;
Seek(Offset: Longint; Origin: Word)93212397c6Schristos     function Seek(Offset: Longint; Origin: Word): Longint; override;
94212397c6Schristos     property CompressionRate: Single read GetCompressionRate;
95212397c6Schristos     property OnProgress;
96212397c6Schristos   end;
97212397c6Schristos 
98212397c6Schristos { TDecompressionStream decompresses data on the fly as data is read from it.
99212397c6Schristos 
100212397c6Schristos   Compressed data comes from a separate source stream.  TDecompressionStream
101212397c6Schristos   is read-only and unidirectional; you can seek forward in the stream, but not
102212397c6Schristos   backwards.  The special case of setting the stream position to zero is
103212397c6Schristos   allowed.  Seeking forward decompresses data until the requested position in
104212397c6Schristos   the uncompressed data has been reached.  Seeking backwards, seeking relative
105212397c6Schristos   to the end of the stream, requesting the size of the stream, and writing to
106212397c6Schristos   the stream will raise an exception.
107212397c6Schristos 
108212397c6Schristos   The Position property returns the number of bytes of uncompressed data that
109212397c6Schristos   have been read from the stream so far.
110212397c6Schristos 
111212397c6Schristos   The OnProgress event is called each time the internal input buffer of
112212397c6Schristos   compressed data is exhausted and the next block is read from the input stream.
113212397c6Schristos   This is useful for updating a progress indicator when you are reading a
114212397c6Schristos   large chunk of data from the decompression stream in a single call.}
115212397c6Schristos 
116212397c6Schristos   TDecompressionStream = class(TCustomZlibStream)
117212397c6Schristos   public
118212397c6Schristos     constructor Create(Source: TStream);
119212397c6Schristos     destructor Destroy; override;
Read(var Buffer; Count: Longint)120212397c6Schristos     function Read(var Buffer; Count: Longint): Longint; override;
Write(const Buffer; Count: Longint)121212397c6Schristos     function Write(const Buffer; Count: Longint): Longint; override;
Seek(Offset: Longint; Origin: Word)122212397c6Schristos     function Seek(Offset: Longint; Origin: Word): Longint; override;
123212397c6Schristos     property OnProgress;
124212397c6Schristos   end;
125212397c6Schristos 
126212397c6Schristos 
127212397c6Schristos 
128212397c6Schristos { CompressBuf compresses data, buffer to buffer, in one call.
129212397c6Schristos    In: InBuf = ptr to compressed data
130212397c6Schristos        InBytes = number of bytes in InBuf
131212397c6Schristos   Out: OutBuf = ptr to newly allocated buffer containing decompressed data
132212397c6Schristos        OutBytes = number of bytes in OutBuf   }
133212397c6Schristos procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
134212397c6Schristos                       out OutBuf: Pointer; out OutBytes: Integer);
135212397c6Schristos 
136212397c6Schristos 
137212397c6Schristos { DecompressBuf decompresses data, buffer to buffer, in one call.
138212397c6Schristos    In: InBuf = ptr to compressed data
139212397c6Schristos        InBytes = number of bytes in InBuf
140212397c6Schristos        OutEstimate = zero, or est. size of the decompressed data
141212397c6Schristos   Out: OutBuf = ptr to newly allocated buffer containing decompressed data
142212397c6Schristos        OutBytes = number of bytes in OutBuf   }
143212397c6Schristos procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
144212397c6Schristos  OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
145212397c6Schristos 
146212397c6Schristos { DecompressToUserBuf decompresses data, buffer to buffer, in one call.
147212397c6Schristos    In: InBuf = ptr to compressed data
148212397c6Schristos        InBytes = number of bytes in InBuf
149212397c6Schristos   Out: OutBuf = ptr to user-allocated buffer to contain decompressed data
150212397c6Schristos        BufSize = number of bytes in OutBuf   }
151212397c6Schristos procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
152212397c6Schristos   const OutBuf: Pointer; BufSize: Integer);
153212397c6Schristos 
154212397c6Schristos const
155*4b169a6bSchristos   zlib_version = '1.2.12';
156212397c6Schristos 
157212397c6Schristos type
158212397c6Schristos   EZlibError = class(Exception);
159212397c6Schristos   ECompressionError = class(EZlibError);
160212397c6Schristos   EDecompressionError = class(EZlibError);
161212397c6Schristos 
162212397c6Schristos implementation
163212397c6Schristos 
164212397c6Schristos uses ZLibConst;
165212397c6Schristos 
166212397c6Schristos const
167212397c6Schristos   Z_NO_FLUSH      = 0;
168212397c6Schristos   Z_PARTIAL_FLUSH = 1;
169212397c6Schristos   Z_SYNC_FLUSH    = 2;
170212397c6Schristos   Z_FULL_FLUSH    = 3;
171212397c6Schristos   Z_FINISH        = 4;
172212397c6Schristos 
173212397c6Schristos   Z_OK            = 0;
174212397c6Schristos   Z_STREAM_END    = 1;
175212397c6Schristos   Z_NEED_DICT     = 2;
176212397c6Schristos   Z_ERRNO         = (-1);
177212397c6Schristos   Z_STREAM_ERROR  = (-2);
178212397c6Schristos   Z_DATA_ERROR    = (-3);
179212397c6Schristos   Z_MEM_ERROR     = (-4);
180212397c6Schristos   Z_BUF_ERROR     = (-5);
181212397c6Schristos   Z_VERSION_ERROR = (-6);
182212397c6Schristos 
183212397c6Schristos   Z_NO_COMPRESSION       =   0;
184212397c6Schristos   Z_BEST_SPEED           =   1;
185212397c6Schristos   Z_BEST_COMPRESSION     =   9;
186212397c6Schristos   Z_DEFAULT_COMPRESSION  = (-1);
187212397c6Schristos 
188212397c6Schristos   Z_FILTERED            = 1;
189212397c6Schristos   Z_HUFFMAN_ONLY        = 2;
190212397c6Schristos   Z_RLE                 = 3;
191212397c6Schristos   Z_DEFAULT_STRATEGY    = 0;
192212397c6Schristos 
193212397c6Schristos   Z_BINARY   = 0;
194212397c6Schristos   Z_ASCII    = 1;
195212397c6Schristos   Z_UNKNOWN  = 2;
196212397c6Schristos 
197212397c6Schristos   Z_DEFLATED = 8;
198212397c6Schristos 
199212397c6Schristos 
200212397c6Schristos {$L adler32.obj}
201212397c6Schristos {$L compress.obj}
202212397c6Schristos {$L crc32.obj}
203212397c6Schristos {$L deflate.obj}
204212397c6Schristos {$L infback.obj}
205212397c6Schristos {$L inffast.obj}
206212397c6Schristos {$L inflate.obj}
207212397c6Schristos {$L inftrees.obj}
208212397c6Schristos {$L trees.obj}
209212397c6Schristos {$L uncompr.obj}
210212397c6Schristos {$L zutil.obj}
211212397c6Schristos 
212212397c6Schristos procedure adler32; external;
213212397c6Schristos procedure compressBound; external;
214212397c6Schristos procedure crc32; external;
215212397c6Schristos procedure deflateInit2_; external;
216212397c6Schristos procedure deflateParams; external;
217212397c6Schristos 
_malloc(Size: Integer)218212397c6Schristos function _malloc(Size: Integer): Pointer; cdecl;
219212397c6Schristos begin
220212397c6Schristos   Result := AllocMem(Size);
221212397c6Schristos end;
222212397c6Schristos 
223212397c6Schristos procedure _free(Block: Pointer); cdecl;
224212397c6Schristos begin
225212397c6Schristos   FreeMem(Block);
226212397c6Schristos end;
227212397c6Schristos 
228212397c6Schristos procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl;
229212397c6Schristos begin
230212397c6Schristos   FillChar(P^, count, B);
231212397c6Schristos end;
232212397c6Schristos 
233212397c6Schristos procedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
234212397c6Schristos begin
235212397c6Schristos   Move(source^, dest^, count);
236212397c6Schristos end;
237212397c6Schristos 
238212397c6Schristos 
239212397c6Schristos 
240212397c6Schristos // deflate compresses data
deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;241212397c6Schristos function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;
242212397c6Schristos   recsize: Integer): Integer; external;
deflate(var strm: TZStreamRec; flush: Integer)243212397c6Schristos function deflate(var strm: TZStreamRec; flush: Integer): Integer; external;
deflateEnd(var strm: TZStreamRec)244212397c6Schristos function deflateEnd(var strm: TZStreamRec): Integer; external;
245212397c6Schristos 
246212397c6Schristos // inflate decompresses data
inflateInit_(var strm: TZStreamRec; version: PChar;247212397c6Schristos function inflateInit_(var strm: TZStreamRec; version: PChar;
248212397c6Schristos   recsize: Integer): Integer; external;
inflate(var strm: TZStreamRec; flush: Integer)249212397c6Schristos function inflate(var strm: TZStreamRec; flush: Integer): Integer; external;
inflateEnd(var strm: TZStreamRec)250212397c6Schristos function inflateEnd(var strm: TZStreamRec): Integer; external;
inflateReset(var strm: TZStreamRec)251212397c6Schristos function inflateReset(var strm: TZStreamRec): Integer; external;
252212397c6Schristos 
253212397c6Schristos 
zlibAllocMem(AppData: Pointer; Items, Size: Integer)254212397c6Schristos function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
255212397c6Schristos begin
256212397c6Schristos //  GetMem(Result, Items*Size);
257212397c6Schristos   Result := AllocMem(Items * Size);
258212397c6Schristos end;
259212397c6Schristos 
260212397c6Schristos procedure zlibFreeMem(AppData, Block: Pointer); cdecl;
261212397c6Schristos begin
262212397c6Schristos   FreeMem(Block);
263212397c6Schristos end;
264212397c6Schristos 
265212397c6Schristos {function zlibCheck(code: Integer): Integer;
266212397c6Schristos begin
267212397c6Schristos   Result := code;
268212397c6Schristos   if code < 0 then
269212397c6Schristos     raise EZlibError.Create('error');    //!!
270212397c6Schristos end;}
271212397c6Schristos 
CCheck(code: Integer)272212397c6Schristos function CCheck(code: Integer): Integer;
273212397c6Schristos begin
274212397c6Schristos   Result := code;
275212397c6Schristos   if code < 0 then
276212397c6Schristos     raise ECompressionError.Create('error'); //!!
277212397c6Schristos end;
278212397c6Schristos 
DCheck(code: Integer)279212397c6Schristos function DCheck(code: Integer): Integer;
280212397c6Schristos begin
281212397c6Schristos   Result := code;
282212397c6Schristos   if code < 0 then
283212397c6Schristos     raise EDecompressionError.Create('error');  //!!
284212397c6Schristos end;
285212397c6Schristos 
286212397c6Schristos procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
287212397c6Schristos                       out OutBuf: Pointer; out OutBytes: Integer);
288212397c6Schristos var
289212397c6Schristos   strm: TZStreamRec;
290212397c6Schristos   P: Pointer;
291212397c6Schristos begin
292212397c6Schristos   FillChar(strm, sizeof(strm), 0);
293212397c6Schristos   strm.zalloc := zlibAllocMem;
294212397c6Schristos   strm.zfree := zlibFreeMem;
295212397c6Schristos   OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
296212397c6Schristos   GetMem(OutBuf, OutBytes);
297212397c6Schristos   try
298212397c6Schristos     strm.next_in := InBuf;
299212397c6Schristos     strm.avail_in := InBytes;
300212397c6Schristos     strm.next_out := OutBuf;
301212397c6Schristos     strm.avail_out := OutBytes;
302212397c6Schristos     CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)));
303212397c6Schristos     try
304212397c6Schristos       while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
305212397c6Schristos       begin
306212397c6Schristos         P := OutBuf;
307212397c6Schristos         Inc(OutBytes, 256);
308212397c6Schristos         ReallocMem(OutBuf, OutBytes);
309212397c6Schristos         strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
310212397c6Schristos         strm.avail_out := 256;
311212397c6Schristos       end;
312212397c6Schristos     finally
313212397c6Schristos       CCheck(deflateEnd(strm));
314212397c6Schristos     end;
315212397c6Schristos     ReallocMem(OutBuf, strm.total_out);
316212397c6Schristos     OutBytes := strm.total_out;
317212397c6Schristos   except
318212397c6Schristos     FreeMem(OutBuf);
319212397c6Schristos     raise
320212397c6Schristos   end;
321212397c6Schristos end;
322212397c6Schristos 
323212397c6Schristos 
324212397c6Schristos procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
325212397c6Schristos   OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
326212397c6Schristos var
327212397c6Schristos   strm: TZStreamRec;
328212397c6Schristos   P: Pointer;
329212397c6Schristos   BufInc: Integer;
330212397c6Schristos begin
331212397c6Schristos   FillChar(strm, sizeof(strm), 0);
332212397c6Schristos   strm.zalloc := zlibAllocMem;
333212397c6Schristos   strm.zfree := zlibFreeMem;
334212397c6Schristos   BufInc := (InBytes + 255) and not 255;
335212397c6Schristos   if OutEstimate = 0 then
336212397c6Schristos     OutBytes := BufInc
337212397c6Schristos   else
338212397c6Schristos     OutBytes := OutEstimate;
339212397c6Schristos   GetMem(OutBuf, OutBytes);
340212397c6Schristos   try
341212397c6Schristos     strm.next_in := InBuf;
342212397c6Schristos     strm.avail_in := InBytes;
343212397c6Schristos     strm.next_out := OutBuf;
344212397c6Schristos     strm.avail_out := OutBytes;
345212397c6Schristos     DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
346212397c6Schristos     try
347212397c6Schristos       while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do
348212397c6Schristos       begin
349212397c6Schristos         P := OutBuf;
350212397c6Schristos         Inc(OutBytes, BufInc);
351212397c6Schristos         ReallocMem(OutBuf, OutBytes);
352212397c6Schristos         strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
353212397c6Schristos         strm.avail_out := BufInc;
354212397c6Schristos       end;
355212397c6Schristos     finally
356212397c6Schristos       DCheck(inflateEnd(strm));
357212397c6Schristos     end;
358212397c6Schristos     ReallocMem(OutBuf, strm.total_out);
359212397c6Schristos     OutBytes := strm.total_out;
360212397c6Schristos   except
361212397c6Schristos     FreeMem(OutBuf);
362212397c6Schristos     raise
363212397c6Schristos   end;
364212397c6Schristos end;
365212397c6Schristos 
366212397c6Schristos procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
367212397c6Schristos   const OutBuf: Pointer; BufSize: Integer);
368212397c6Schristos var
369212397c6Schristos   strm: TZStreamRec;
370212397c6Schristos begin
371212397c6Schristos   FillChar(strm, sizeof(strm), 0);
372212397c6Schristos   strm.zalloc := zlibAllocMem;
373212397c6Schristos   strm.zfree := zlibFreeMem;
374212397c6Schristos   strm.next_in := InBuf;
375212397c6Schristos   strm.avail_in := InBytes;
376212397c6Schristos   strm.next_out := OutBuf;
377212397c6Schristos   strm.avail_out := BufSize;
378212397c6Schristos   DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
379212397c6Schristos   try
380212397c6Schristos     if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then
381212397c6Schristos       raise EZlibError.CreateRes(@sTargetBufferTooSmall);
382212397c6Schristos   finally
383212397c6Schristos     DCheck(inflateEnd(strm));
384212397c6Schristos   end;
385212397c6Schristos end;
386212397c6Schristos 
387212397c6Schristos // TCustomZlibStream
388212397c6Schristos 
389212397c6Schristos constructor TCustomZLibStream.Create(Strm: TStream);
390212397c6Schristos begin
391212397c6Schristos   inherited Create;
392212397c6Schristos   FStrm := Strm;
393212397c6Schristos   FStrmPos := Strm.Position;
394212397c6Schristos   FZRec.zalloc := zlibAllocMem;
395212397c6Schristos   FZRec.zfree := zlibFreeMem;
396212397c6Schristos end;
397212397c6Schristos 
398212397c6Schristos procedure TCustomZLibStream.Progress(Sender: TObject);
399212397c6Schristos begin
400212397c6Schristos   if Assigned(FOnProgress) then FOnProgress(Sender);
401212397c6Schristos end;
402212397c6Schristos 
403212397c6Schristos 
404212397c6Schristos // TCompressionStream
405212397c6Schristos 
406212397c6Schristos constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
407212397c6Schristos   Dest: TStream);
408212397c6Schristos const
409212397c6Schristos   Levels: array [TCompressionLevel] of ShortInt =
410212397c6Schristos     (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
411212397c6Schristos begin
412212397c6Schristos   inherited Create(Dest);
413212397c6Schristos   FZRec.next_out := FBuffer;
414212397c6Schristos   FZRec.avail_out := sizeof(FBuffer);
415212397c6Schristos   CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec)));
416212397c6Schristos end;
417212397c6Schristos 
418212397c6Schristos destructor TCompressionStream.Destroy;
419212397c6Schristos begin
420212397c6Schristos   FZRec.next_in := nil;
421212397c6Schristos   FZRec.avail_in := 0;
422212397c6Schristos   try
423212397c6Schristos     if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
424212397c6Schristos     while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
425212397c6Schristos       and (FZRec.avail_out = 0) do
426212397c6Schristos     begin
427212397c6Schristos       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
428212397c6Schristos       FZRec.next_out := FBuffer;
429212397c6Schristos       FZRec.avail_out := sizeof(FBuffer);
430212397c6Schristos     end;
431212397c6Schristos     if FZRec.avail_out < sizeof(FBuffer) then
432212397c6Schristos       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
433212397c6Schristos   finally
434212397c6Schristos     deflateEnd(FZRec);
435212397c6Schristos   end;
436212397c6Schristos   inherited Destroy;
437212397c6Schristos end;
438212397c6Schristos 
Readnull439212397c6Schristos function TCompressionStream.Read(var Buffer; Count: Longint): Longint;
440212397c6Schristos begin
441212397c6Schristos   raise ECompressionError.CreateRes(@sInvalidStreamOp);
442212397c6Schristos end;
443212397c6Schristos 
Writenull444212397c6Schristos function TCompressionStream.Write(const Buffer; Count: Longint): Longint;
445212397c6Schristos begin
446212397c6Schristos   FZRec.next_in := @Buffer;
447212397c6Schristos   FZRec.avail_in := Count;
448212397c6Schristos   if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
449212397c6Schristos   while (FZRec.avail_in > 0) do
450212397c6Schristos   begin
451212397c6Schristos     CCheck(deflate(FZRec, 0));
452212397c6Schristos     if FZRec.avail_out = 0 then
453212397c6Schristos     begin
454212397c6Schristos       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
455212397c6Schristos       FZRec.next_out := FBuffer;
456212397c6Schristos       FZRec.avail_out := sizeof(FBuffer);
457212397c6Schristos       FStrmPos := FStrm.Position;
458212397c6Schristos       Progress(Self);
459212397c6Schristos     end;
460212397c6Schristos   end;
461212397c6Schristos   Result := Count;
462212397c6Schristos end;
463212397c6Schristos 
TCompressionStream.Seek(Offset: Longint; Origin: Word)464212397c6Schristos function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
465212397c6Schristos begin
466212397c6Schristos   if (Offset = 0) and (Origin = soFromCurrent) then
467212397c6Schristos     Result := FZRec.total_in
468212397c6Schristos   else
469212397c6Schristos     raise ECompressionError.CreateRes(@sInvalidStreamOp);
470212397c6Schristos end;
471212397c6Schristos 
TCompressionStream.GetCompressionRate()472212397c6Schristos function TCompressionStream.GetCompressionRate: Single;
473212397c6Schristos begin
474212397c6Schristos   if FZRec.total_in = 0 then
475212397c6Schristos     Result := 0
476212397c6Schristos   else
477212397c6Schristos     Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0;
478212397c6Schristos end;
479212397c6Schristos 
480212397c6Schristos 
481212397c6Schristos // TDecompressionStream
482212397c6Schristos 
483212397c6Schristos constructor TDecompressionStream.Create(Source: TStream);
484212397c6Schristos begin
485212397c6Schristos   inherited Create(Source);
486212397c6Schristos   FZRec.next_in := FBuffer;
487212397c6Schristos   FZRec.avail_in := 0;
488212397c6Schristos   DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec)));
489212397c6Schristos end;
490212397c6Schristos 
491212397c6Schristos destructor TDecompressionStream.Destroy;
492212397c6Schristos begin
493212397c6Schristos   FStrm.Seek(-FZRec.avail_in, 1);
494212397c6Schristos   inflateEnd(FZRec);
495212397c6Schristos   inherited Destroy;
496212397c6Schristos end;
497212397c6Schristos 
Readnull498212397c6Schristos function TDecompressionStream.Read(var Buffer; Count: Longint): Longint;
499212397c6Schristos begin
500212397c6Schristos   FZRec.next_out := @Buffer;
501212397c6Schristos   FZRec.avail_out := Count;
502212397c6Schristos   if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
503212397c6Schristos   while (FZRec.avail_out > 0) do
504212397c6Schristos   begin
505212397c6Schristos     if FZRec.avail_in = 0 then
506212397c6Schristos     begin
507212397c6Schristos       FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer));
508212397c6Schristos       if FZRec.avail_in = 0 then
509212397c6Schristos       begin
510212397c6Schristos         Result := Count - FZRec.avail_out;
511212397c6Schristos         Exit;
512212397c6Schristos       end;
513212397c6Schristos       FZRec.next_in := FBuffer;
514212397c6Schristos       FStrmPos := FStrm.Position;
515212397c6Schristos       Progress(Self);
516212397c6Schristos     end;
517212397c6Schristos     CCheck(inflate(FZRec, 0));
518212397c6Schristos   end;
519212397c6Schristos   Result := Count;
520212397c6Schristos end;
521212397c6Schristos 
Writenull522212397c6Schristos function TDecompressionStream.Write(const Buffer; Count: Longint): Longint;
523212397c6Schristos begin
524212397c6Schristos   raise EDecompressionError.CreateRes(@sInvalidStreamOp);
525212397c6Schristos end;
526212397c6Schristos 
Seeknull527212397c6Schristos function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
528212397c6Schristos var
529212397c6Schristos   I: Integer;
530212397c6Schristos   Buf: array [0..4095] of Char;
531212397c6Schristos begin
532212397c6Schristos   if (Offset = 0) and (Origin = soFromBeginning) then
533212397c6Schristos   begin
534212397c6Schristos     DCheck(inflateReset(FZRec));
535212397c6Schristos     FZRec.next_in := FBuffer;
536212397c6Schristos     FZRec.avail_in := 0;
537212397c6Schristos     FStrm.Position := 0;
538212397c6Schristos     FStrmPos := 0;
539212397c6Schristos   end
540212397c6Schristos   else if ( (Offset >= 0) and (Origin = soFromCurrent)) or
541212397c6Schristos           ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then
542212397c6Schristos   begin
543212397c6Schristos     if Origin = soFromBeginning then Dec(Offset, FZRec.total_out);
544212397c6Schristos     if Offset > 0 then
545212397c6Schristos     begin
546212397c6Schristos       for I := 1 to Offset div sizeof(Buf) do
547212397c6Schristos         ReadBuffer(Buf, sizeof(Buf));
548212397c6Schristos       ReadBuffer(Buf, Offset mod sizeof(Buf));
549212397c6Schristos     end;
550212397c6Schristos   end
551212397c6Schristos   else
552212397c6Schristos     raise EDecompressionError.CreateRes(@sInvalidStreamOp);
553212397c6Schristos   Result := FZRec.total_out;
554212397c6Schristos end;
555212397c6Schristos 
556212397c6Schristos 
557212397c6Schristos end.
558