1275793eaSopenharmony_ci{*******************************************************}
2275793eaSopenharmony_ci{                                                       }
3275793eaSopenharmony_ci{       Borland Delphi Supplemental Components          }
4275793eaSopenharmony_ci{       ZLIB Data Compression Interface Unit            }
5275793eaSopenharmony_ci{                                                       }
6275793eaSopenharmony_ci{       Copyright (c) 1997,99 Borland Corporation       }
7275793eaSopenharmony_ci{                                                       }
8275793eaSopenharmony_ci{*******************************************************}
9275793eaSopenharmony_ci
10275793eaSopenharmony_ci{ Updated for zlib 1.2.x by Cosmin Truta <cosmint@cs.ubbcluj.ro> }
11275793eaSopenharmony_ci
12275793eaSopenharmony_ciunit ZLib;
13275793eaSopenharmony_ci
14275793eaSopenharmony_ciinterface
15275793eaSopenharmony_ci
16275793eaSopenharmony_ciuses SysUtils, Classes;
17275793eaSopenharmony_ci
18275793eaSopenharmony_citype
19275793eaSopenharmony_ci  TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
20275793eaSopenharmony_ci  TFree = procedure (AppData, Block: Pointer); cdecl;
21275793eaSopenharmony_ci
22275793eaSopenharmony_ci  // Internal structure.  Ignore.
23275793eaSopenharmony_ci  TZStreamRec = packed record
24275793eaSopenharmony_ci    next_in: PChar;       // next input byte
25275793eaSopenharmony_ci    avail_in: Integer;    // number of bytes available at next_in
26275793eaSopenharmony_ci    total_in: Longint;    // total nb of input bytes read so far
27275793eaSopenharmony_ci
28275793eaSopenharmony_ci    next_out: PChar;      // next output byte should be put here
29275793eaSopenharmony_ci    avail_out: Integer;   // remaining free space at next_out
30275793eaSopenharmony_ci    total_out: Longint;   // total nb of bytes output so far
31275793eaSopenharmony_ci
32275793eaSopenharmony_ci    msg: PChar;           // last error message, NULL if no error
33275793eaSopenharmony_ci    internal: Pointer;    // not visible by applications
34275793eaSopenharmony_ci
35275793eaSopenharmony_ci    zalloc: TAlloc;       // used to allocate the internal state
36275793eaSopenharmony_ci    zfree: TFree;         // used to free the internal state
37275793eaSopenharmony_ci    AppData: Pointer;     // private data object passed to zalloc and zfree
38275793eaSopenharmony_ci
39275793eaSopenharmony_ci    data_type: Integer;   // best guess about the data type: ascii or binary
40275793eaSopenharmony_ci    adler: Longint;       // adler32 value of the uncompressed data
41275793eaSopenharmony_ci    reserved: Longint;    // reserved for future use
42275793eaSopenharmony_ci  end;
43275793eaSopenharmony_ci
44275793eaSopenharmony_ci  // Abstract ancestor class
45275793eaSopenharmony_ci  TCustomZlibStream = class(TStream)
46275793eaSopenharmony_ci  private
47275793eaSopenharmony_ci    FStrm: TStream;
48275793eaSopenharmony_ci    FStrmPos: Integer;
49275793eaSopenharmony_ci    FOnProgress: TNotifyEvent;
50275793eaSopenharmony_ci    FZRec: TZStreamRec;
51275793eaSopenharmony_ci    FBuffer: array [Word] of Char;
52275793eaSopenharmony_ci  protected
53275793eaSopenharmony_ci    procedure Progress(Sender: TObject); dynamic;
54275793eaSopenharmony_ci    property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
55275793eaSopenharmony_ci    constructor Create(Strm: TStream);
56275793eaSopenharmony_ci  end;
57275793eaSopenharmony_ci
58275793eaSopenharmony_ci{ TCompressionStream compresses data on the fly as data is written to it, and
59275793eaSopenharmony_ci  stores the compressed data to another stream.
60275793eaSopenharmony_ci
61275793eaSopenharmony_ci  TCompressionStream is write-only and strictly sequential. Reading from the
62275793eaSopenharmony_ci  stream will raise an exception. Using Seek to move the stream pointer
63275793eaSopenharmony_ci  will raise an exception.
64275793eaSopenharmony_ci
65275793eaSopenharmony_ci  Output data is cached internally, written to the output stream only when
66275793eaSopenharmony_ci  the internal output buffer is full.  All pending output data is flushed
67275793eaSopenharmony_ci  when the stream is destroyed.
68275793eaSopenharmony_ci
69275793eaSopenharmony_ci  The Position property returns the number of uncompressed bytes of
70275793eaSopenharmony_ci  data that have been written to the stream so far.
71275793eaSopenharmony_ci
72275793eaSopenharmony_ci  CompressionRate returns the on-the-fly percentage by which the original
73275793eaSopenharmony_ci  data has been compressed:  (1 - (CompressedBytes / UncompressedBytes)) * 100
74275793eaSopenharmony_ci  If raw data size = 100 and compressed data size = 25, the CompressionRate
75275793eaSopenharmony_ci  is 75%
76275793eaSopenharmony_ci
77275793eaSopenharmony_ci  The OnProgress event is called each time the output buffer is filled and
78275793eaSopenharmony_ci  written to the output stream.  This is useful for updating a progress
79275793eaSopenharmony_ci  indicator when you are writing a large chunk of data to the compression
80275793eaSopenharmony_ci  stream in a single call.}
81275793eaSopenharmony_ci
82275793eaSopenharmony_ci
83275793eaSopenharmony_ci  TCompressionLevel = (clNone, clFastest, clDefault, clMax);
84275793eaSopenharmony_ci
85275793eaSopenharmony_ci  TCompressionStream = class(TCustomZlibStream)
86275793eaSopenharmony_ci  private
87275793eaSopenharmony_ci    function GetCompressionRate: Single;
88275793eaSopenharmony_ci  public
89275793eaSopenharmony_ci    constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
90275793eaSopenharmony_ci    destructor Destroy; override;
91275793eaSopenharmony_ci    function Read(var Buffer; Count: Longint): Longint; override;
92275793eaSopenharmony_ci    function Write(const Buffer; Count: Longint): Longint; override;
93275793eaSopenharmony_ci    function Seek(Offset: Longint; Origin: Word): Longint; override;
94275793eaSopenharmony_ci    property CompressionRate: Single read GetCompressionRate;
95275793eaSopenharmony_ci    property OnProgress;
96275793eaSopenharmony_ci  end;
97275793eaSopenharmony_ci
98275793eaSopenharmony_ci{ TDecompressionStream decompresses data on the fly as data is read from it.
99275793eaSopenharmony_ci
100275793eaSopenharmony_ci  Compressed data comes from a separate source stream.  TDecompressionStream
101275793eaSopenharmony_ci  is read-only and unidirectional; you can seek forward in the stream, but not
102275793eaSopenharmony_ci  backwards.  The special case of setting the stream position to zero is
103275793eaSopenharmony_ci  allowed.  Seeking forward decompresses data until the requested position in
104275793eaSopenharmony_ci  the uncompressed data has been reached.  Seeking backwards, seeking relative
105275793eaSopenharmony_ci  to the end of the stream, requesting the size of the stream, and writing to
106275793eaSopenharmony_ci  the stream will raise an exception.
107275793eaSopenharmony_ci
108275793eaSopenharmony_ci  The Position property returns the number of bytes of uncompressed data that
109275793eaSopenharmony_ci  have been read from the stream so far.
110275793eaSopenharmony_ci
111275793eaSopenharmony_ci  The OnProgress event is called each time the internal input buffer of
112275793eaSopenharmony_ci  compressed data is exhausted and the next block is read from the input stream.
113275793eaSopenharmony_ci  This is useful for updating a progress indicator when you are reading a
114275793eaSopenharmony_ci  large chunk of data from the decompression stream in a single call.}
115275793eaSopenharmony_ci
116275793eaSopenharmony_ci  TDecompressionStream = class(TCustomZlibStream)
117275793eaSopenharmony_ci  public
118275793eaSopenharmony_ci    constructor Create(Source: TStream);
119275793eaSopenharmony_ci    destructor Destroy; override;
120275793eaSopenharmony_ci    function Read(var Buffer; Count: Longint): Longint; override;
121275793eaSopenharmony_ci    function Write(const Buffer; Count: Longint): Longint; override;
122275793eaSopenharmony_ci    function Seek(Offset: Longint; Origin: Word): Longint; override;
123275793eaSopenharmony_ci    property OnProgress;
124275793eaSopenharmony_ci  end;
125275793eaSopenharmony_ci
126275793eaSopenharmony_ci
127275793eaSopenharmony_ci
128275793eaSopenharmony_ci{ CompressBuf compresses data, buffer to buffer, in one call.
129275793eaSopenharmony_ci   In: InBuf = ptr to compressed data
130275793eaSopenharmony_ci       InBytes = number of bytes in InBuf
131275793eaSopenharmony_ci  Out: OutBuf = ptr to newly allocated buffer containing decompressed data
132275793eaSopenharmony_ci       OutBytes = number of bytes in OutBuf   }
133275793eaSopenharmony_ciprocedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
134275793eaSopenharmony_ci                      out OutBuf: Pointer; out OutBytes: Integer);
135275793eaSopenharmony_ci
136275793eaSopenharmony_ci
137275793eaSopenharmony_ci{ DecompressBuf decompresses data, buffer to buffer, in one call.
138275793eaSopenharmony_ci   In: InBuf = ptr to compressed data
139275793eaSopenharmony_ci       InBytes = number of bytes in InBuf
140275793eaSopenharmony_ci       OutEstimate = zero, or est. size of the decompressed data
141275793eaSopenharmony_ci  Out: OutBuf = ptr to newly allocated buffer containing decompressed data
142275793eaSopenharmony_ci       OutBytes = number of bytes in OutBuf   }
143275793eaSopenharmony_ciprocedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
144275793eaSopenharmony_ci OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
145275793eaSopenharmony_ci
146275793eaSopenharmony_ci{ DecompressToUserBuf decompresses data, buffer to buffer, in one call.
147275793eaSopenharmony_ci   In: InBuf = ptr to compressed data
148275793eaSopenharmony_ci       InBytes = number of bytes in InBuf
149275793eaSopenharmony_ci  Out: OutBuf = ptr to user-allocated buffer to contain decompressed data
150275793eaSopenharmony_ci       BufSize = number of bytes in OutBuf   }
151275793eaSopenharmony_ciprocedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
152275793eaSopenharmony_ci  const OutBuf: Pointer; BufSize: Integer);
153275793eaSopenharmony_ci
154275793eaSopenharmony_ciconst
155275793eaSopenharmony_ci  zlib_version = '1.3.1';
156275793eaSopenharmony_ci
157275793eaSopenharmony_citype
158275793eaSopenharmony_ci  EZlibError = class(Exception);
159275793eaSopenharmony_ci  ECompressionError = class(EZlibError);
160275793eaSopenharmony_ci  EDecompressionError = class(EZlibError);
161275793eaSopenharmony_ci
162275793eaSopenharmony_ciimplementation
163275793eaSopenharmony_ci
164275793eaSopenharmony_ciuses ZLibConst;
165275793eaSopenharmony_ci
166275793eaSopenharmony_ciconst
167275793eaSopenharmony_ci  Z_NO_FLUSH      = 0;
168275793eaSopenharmony_ci  Z_PARTIAL_FLUSH = 1;
169275793eaSopenharmony_ci  Z_SYNC_FLUSH    = 2;
170275793eaSopenharmony_ci  Z_FULL_FLUSH    = 3;
171275793eaSopenharmony_ci  Z_FINISH        = 4;
172275793eaSopenharmony_ci
173275793eaSopenharmony_ci  Z_OK            = 0;
174275793eaSopenharmony_ci  Z_STREAM_END    = 1;
175275793eaSopenharmony_ci  Z_NEED_DICT     = 2;
176275793eaSopenharmony_ci  Z_ERRNO         = (-1);
177275793eaSopenharmony_ci  Z_STREAM_ERROR  = (-2);
178275793eaSopenharmony_ci  Z_DATA_ERROR    = (-3);
179275793eaSopenharmony_ci  Z_MEM_ERROR     = (-4);
180275793eaSopenharmony_ci  Z_BUF_ERROR     = (-5);
181275793eaSopenharmony_ci  Z_VERSION_ERROR = (-6);
182275793eaSopenharmony_ci
183275793eaSopenharmony_ci  Z_NO_COMPRESSION       =   0;
184275793eaSopenharmony_ci  Z_BEST_SPEED           =   1;
185275793eaSopenharmony_ci  Z_BEST_COMPRESSION     =   9;
186275793eaSopenharmony_ci  Z_DEFAULT_COMPRESSION  = (-1);
187275793eaSopenharmony_ci
188275793eaSopenharmony_ci  Z_FILTERED            = 1;
189275793eaSopenharmony_ci  Z_HUFFMAN_ONLY        = 2;
190275793eaSopenharmony_ci  Z_RLE                 = 3;
191275793eaSopenharmony_ci  Z_DEFAULT_STRATEGY    = 0;
192275793eaSopenharmony_ci
193275793eaSopenharmony_ci  Z_BINARY   = 0;
194275793eaSopenharmony_ci  Z_ASCII    = 1;
195275793eaSopenharmony_ci  Z_UNKNOWN  = 2;
196275793eaSopenharmony_ci
197275793eaSopenharmony_ci  Z_DEFLATED = 8;
198275793eaSopenharmony_ci
199275793eaSopenharmony_ci
200275793eaSopenharmony_ci{$L adler32.obj}
201275793eaSopenharmony_ci{$L compress.obj}
202275793eaSopenharmony_ci{$L crc32.obj}
203275793eaSopenharmony_ci{$L deflate.obj}
204275793eaSopenharmony_ci{$L infback.obj}
205275793eaSopenharmony_ci{$L inffast.obj}
206275793eaSopenharmony_ci{$L inflate.obj}
207275793eaSopenharmony_ci{$L inftrees.obj}
208275793eaSopenharmony_ci{$L trees.obj}
209275793eaSopenharmony_ci{$L uncompr.obj}
210275793eaSopenharmony_ci{$L zutil.obj}
211275793eaSopenharmony_ci
212275793eaSopenharmony_ciprocedure adler32; external;
213275793eaSopenharmony_ciprocedure compressBound; external;
214275793eaSopenharmony_ciprocedure crc32; external;
215275793eaSopenharmony_ciprocedure deflateInit2_; external;
216275793eaSopenharmony_ciprocedure deflateParams; external;
217275793eaSopenharmony_ci
218275793eaSopenharmony_cifunction _malloc(Size: Integer): Pointer; cdecl;
219275793eaSopenharmony_cibegin
220275793eaSopenharmony_ci  Result := AllocMem(Size);
221275793eaSopenharmony_ciend;
222275793eaSopenharmony_ci
223275793eaSopenharmony_ciprocedure _free(Block: Pointer); cdecl;
224275793eaSopenharmony_cibegin
225275793eaSopenharmony_ci  FreeMem(Block);
226275793eaSopenharmony_ciend;
227275793eaSopenharmony_ci
228275793eaSopenharmony_ciprocedure _memset(P: Pointer; B: Byte; count: Integer); cdecl;
229275793eaSopenharmony_cibegin
230275793eaSopenharmony_ci  FillChar(P^, count, B);
231275793eaSopenharmony_ciend;
232275793eaSopenharmony_ci
233275793eaSopenharmony_ciprocedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
234275793eaSopenharmony_cibegin
235275793eaSopenharmony_ci  Move(source^, dest^, count);
236275793eaSopenharmony_ciend;
237275793eaSopenharmony_ci
238275793eaSopenharmony_ci
239275793eaSopenharmony_ci
240275793eaSopenharmony_ci// deflate compresses data
241275793eaSopenharmony_cifunction deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;
242275793eaSopenharmony_ci  recsize: Integer): Integer; external;
243275793eaSopenharmony_cifunction deflate(var strm: TZStreamRec; flush: Integer): Integer; external;
244275793eaSopenharmony_cifunction deflateEnd(var strm: TZStreamRec): Integer; external;
245275793eaSopenharmony_ci
246275793eaSopenharmony_ci// inflate decompresses data
247275793eaSopenharmony_cifunction inflateInit_(var strm: TZStreamRec; version: PChar;
248275793eaSopenharmony_ci  recsize: Integer): Integer; external;
249275793eaSopenharmony_cifunction inflate(var strm: TZStreamRec; flush: Integer): Integer; external;
250275793eaSopenharmony_cifunction inflateEnd(var strm: TZStreamRec): Integer; external;
251275793eaSopenharmony_cifunction inflateReset(var strm: TZStreamRec): Integer; external;
252275793eaSopenharmony_ci
253275793eaSopenharmony_ci
254275793eaSopenharmony_cifunction zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
255275793eaSopenharmony_cibegin
256275793eaSopenharmony_ci//  GetMem(Result, Items*Size);
257275793eaSopenharmony_ci  Result := AllocMem(Items * Size);
258275793eaSopenharmony_ciend;
259275793eaSopenharmony_ci
260275793eaSopenharmony_ciprocedure zlibFreeMem(AppData, Block: Pointer); cdecl;
261275793eaSopenharmony_cibegin
262275793eaSopenharmony_ci  FreeMem(Block);
263275793eaSopenharmony_ciend;
264275793eaSopenharmony_ci
265275793eaSopenharmony_ci{function zlibCheck(code: Integer): Integer;
266275793eaSopenharmony_cibegin
267275793eaSopenharmony_ci  Result := code;
268275793eaSopenharmony_ci  if code < 0 then
269275793eaSopenharmony_ci    raise EZlibError.Create('error');    //!!
270275793eaSopenharmony_ciend;}
271275793eaSopenharmony_ci
272275793eaSopenharmony_cifunction CCheck(code: Integer): Integer;
273275793eaSopenharmony_cibegin
274275793eaSopenharmony_ci  Result := code;
275275793eaSopenharmony_ci  if code < 0 then
276275793eaSopenharmony_ci    raise ECompressionError.Create('error'); //!!
277275793eaSopenharmony_ciend;
278275793eaSopenharmony_ci
279275793eaSopenharmony_cifunction DCheck(code: Integer): Integer;
280275793eaSopenharmony_cibegin
281275793eaSopenharmony_ci  Result := code;
282275793eaSopenharmony_ci  if code < 0 then
283275793eaSopenharmony_ci    raise EDecompressionError.Create('error');  //!!
284275793eaSopenharmony_ciend;
285275793eaSopenharmony_ci
286275793eaSopenharmony_ciprocedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
287275793eaSopenharmony_ci                      out OutBuf: Pointer; out OutBytes: Integer);
288275793eaSopenharmony_civar
289275793eaSopenharmony_ci  strm: TZStreamRec;
290275793eaSopenharmony_ci  P: Pointer;
291275793eaSopenharmony_cibegin
292275793eaSopenharmony_ci  FillChar(strm, sizeof(strm), 0);
293275793eaSopenharmony_ci  strm.zalloc := zlibAllocMem;
294275793eaSopenharmony_ci  strm.zfree := zlibFreeMem;
295275793eaSopenharmony_ci  OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
296275793eaSopenharmony_ci  GetMem(OutBuf, OutBytes);
297275793eaSopenharmony_ci  try
298275793eaSopenharmony_ci    strm.next_in := InBuf;
299275793eaSopenharmony_ci    strm.avail_in := InBytes;
300275793eaSopenharmony_ci    strm.next_out := OutBuf;
301275793eaSopenharmony_ci    strm.avail_out := OutBytes;
302275793eaSopenharmony_ci    CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)));
303275793eaSopenharmony_ci    try
304275793eaSopenharmony_ci      while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
305275793eaSopenharmony_ci      begin
306275793eaSopenharmony_ci        P := OutBuf;
307275793eaSopenharmony_ci        Inc(OutBytes, 256);
308275793eaSopenharmony_ci        ReallocMem(OutBuf, OutBytes);
309275793eaSopenharmony_ci        strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
310275793eaSopenharmony_ci        strm.avail_out := 256;
311275793eaSopenharmony_ci      end;
312275793eaSopenharmony_ci    finally
313275793eaSopenharmony_ci      CCheck(deflateEnd(strm));
314275793eaSopenharmony_ci    end;
315275793eaSopenharmony_ci    ReallocMem(OutBuf, strm.total_out);
316275793eaSopenharmony_ci    OutBytes := strm.total_out;
317275793eaSopenharmony_ci  except
318275793eaSopenharmony_ci    FreeMem(OutBuf);
319275793eaSopenharmony_ci    raise
320275793eaSopenharmony_ci  end;
321275793eaSopenharmony_ciend;
322275793eaSopenharmony_ci
323275793eaSopenharmony_ci
324275793eaSopenharmony_ciprocedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
325275793eaSopenharmony_ci  OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
326275793eaSopenharmony_civar
327275793eaSopenharmony_ci  strm: TZStreamRec;
328275793eaSopenharmony_ci  P: Pointer;
329275793eaSopenharmony_ci  BufInc: Integer;
330275793eaSopenharmony_cibegin
331275793eaSopenharmony_ci  FillChar(strm, sizeof(strm), 0);
332275793eaSopenharmony_ci  strm.zalloc := zlibAllocMem;
333275793eaSopenharmony_ci  strm.zfree := zlibFreeMem;
334275793eaSopenharmony_ci  BufInc := (InBytes + 255) and not 255;
335275793eaSopenharmony_ci  if OutEstimate = 0 then
336275793eaSopenharmony_ci    OutBytes := BufInc
337275793eaSopenharmony_ci  else
338275793eaSopenharmony_ci    OutBytes := OutEstimate;
339275793eaSopenharmony_ci  GetMem(OutBuf, OutBytes);
340275793eaSopenharmony_ci  try
341275793eaSopenharmony_ci    strm.next_in := InBuf;
342275793eaSopenharmony_ci    strm.avail_in := InBytes;
343275793eaSopenharmony_ci    strm.next_out := OutBuf;
344275793eaSopenharmony_ci    strm.avail_out := OutBytes;
345275793eaSopenharmony_ci    DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
346275793eaSopenharmony_ci    try
347275793eaSopenharmony_ci      while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do
348275793eaSopenharmony_ci      begin
349275793eaSopenharmony_ci        P := OutBuf;
350275793eaSopenharmony_ci        Inc(OutBytes, BufInc);
351275793eaSopenharmony_ci        ReallocMem(OutBuf, OutBytes);
352275793eaSopenharmony_ci        strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
353275793eaSopenharmony_ci        strm.avail_out := BufInc;
354275793eaSopenharmony_ci      end;
355275793eaSopenharmony_ci    finally
356275793eaSopenharmony_ci      DCheck(inflateEnd(strm));
357275793eaSopenharmony_ci    end;
358275793eaSopenharmony_ci    ReallocMem(OutBuf, strm.total_out);
359275793eaSopenharmony_ci    OutBytes := strm.total_out;
360275793eaSopenharmony_ci  except
361275793eaSopenharmony_ci    FreeMem(OutBuf);
362275793eaSopenharmony_ci    raise
363275793eaSopenharmony_ci  end;
364275793eaSopenharmony_ciend;
365275793eaSopenharmony_ci
366275793eaSopenharmony_ciprocedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
367275793eaSopenharmony_ci  const OutBuf: Pointer; BufSize: Integer);
368275793eaSopenharmony_civar
369275793eaSopenharmony_ci  strm: TZStreamRec;
370275793eaSopenharmony_cibegin
371275793eaSopenharmony_ci  FillChar(strm, sizeof(strm), 0);
372275793eaSopenharmony_ci  strm.zalloc := zlibAllocMem;
373275793eaSopenharmony_ci  strm.zfree := zlibFreeMem;
374275793eaSopenharmony_ci  strm.next_in := InBuf;
375275793eaSopenharmony_ci  strm.avail_in := InBytes;
376275793eaSopenharmony_ci  strm.next_out := OutBuf;
377275793eaSopenharmony_ci  strm.avail_out := BufSize;
378275793eaSopenharmony_ci  DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
379275793eaSopenharmony_ci  try
380275793eaSopenharmony_ci    if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then
381275793eaSopenharmony_ci      raise EZlibError.CreateRes(@sTargetBufferTooSmall);
382275793eaSopenharmony_ci  finally
383275793eaSopenharmony_ci    DCheck(inflateEnd(strm));
384275793eaSopenharmony_ci  end;
385275793eaSopenharmony_ciend;
386275793eaSopenharmony_ci
387275793eaSopenharmony_ci// TCustomZlibStream
388275793eaSopenharmony_ci
389275793eaSopenharmony_ciconstructor TCustomZLibStream.Create(Strm: TStream);
390275793eaSopenharmony_cibegin
391275793eaSopenharmony_ci  inherited Create;
392275793eaSopenharmony_ci  FStrm := Strm;
393275793eaSopenharmony_ci  FStrmPos := Strm.Position;
394275793eaSopenharmony_ci  FZRec.zalloc := zlibAllocMem;
395275793eaSopenharmony_ci  FZRec.zfree := zlibFreeMem;
396275793eaSopenharmony_ciend;
397275793eaSopenharmony_ci
398275793eaSopenharmony_ciprocedure TCustomZLibStream.Progress(Sender: TObject);
399275793eaSopenharmony_cibegin
400275793eaSopenharmony_ci  if Assigned(FOnProgress) then FOnProgress(Sender);
401275793eaSopenharmony_ciend;
402275793eaSopenharmony_ci
403275793eaSopenharmony_ci
404275793eaSopenharmony_ci// TCompressionStream
405275793eaSopenharmony_ci
406275793eaSopenharmony_ciconstructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
407275793eaSopenharmony_ci  Dest: TStream);
408275793eaSopenharmony_ciconst
409275793eaSopenharmony_ci  Levels: array [TCompressionLevel] of ShortInt =
410275793eaSopenharmony_ci    (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
411275793eaSopenharmony_cibegin
412275793eaSopenharmony_ci  inherited Create(Dest);
413275793eaSopenharmony_ci  FZRec.next_out := FBuffer;
414275793eaSopenharmony_ci  FZRec.avail_out := sizeof(FBuffer);
415275793eaSopenharmony_ci  CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec)));
416275793eaSopenharmony_ciend;
417275793eaSopenharmony_ci
418275793eaSopenharmony_cidestructor TCompressionStream.Destroy;
419275793eaSopenharmony_cibegin
420275793eaSopenharmony_ci  FZRec.next_in := nil;
421275793eaSopenharmony_ci  FZRec.avail_in := 0;
422275793eaSopenharmony_ci  try
423275793eaSopenharmony_ci    if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
424275793eaSopenharmony_ci    while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
425275793eaSopenharmony_ci      and (FZRec.avail_out = 0) do
426275793eaSopenharmony_ci    begin
427275793eaSopenharmony_ci      FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
428275793eaSopenharmony_ci      FZRec.next_out := FBuffer;
429275793eaSopenharmony_ci      FZRec.avail_out := sizeof(FBuffer);
430275793eaSopenharmony_ci    end;
431275793eaSopenharmony_ci    if FZRec.avail_out < sizeof(FBuffer) then
432275793eaSopenharmony_ci      FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
433275793eaSopenharmony_ci  finally
434275793eaSopenharmony_ci    deflateEnd(FZRec);
435275793eaSopenharmony_ci  end;
436275793eaSopenharmony_ci  inherited Destroy;
437275793eaSopenharmony_ciend;
438275793eaSopenharmony_ci
439275793eaSopenharmony_cifunction TCompressionStream.Read(var Buffer; Count: Longint): Longint;
440275793eaSopenharmony_cibegin
441275793eaSopenharmony_ci  raise ECompressionError.CreateRes(@sInvalidStreamOp);
442275793eaSopenharmony_ciend;
443275793eaSopenharmony_ci
444275793eaSopenharmony_cifunction TCompressionStream.Write(const Buffer; Count: Longint): Longint;
445275793eaSopenharmony_cibegin
446275793eaSopenharmony_ci  FZRec.next_in := @Buffer;
447275793eaSopenharmony_ci  FZRec.avail_in := Count;
448275793eaSopenharmony_ci  if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
449275793eaSopenharmony_ci  while (FZRec.avail_in > 0) do
450275793eaSopenharmony_ci  begin
451275793eaSopenharmony_ci    CCheck(deflate(FZRec, 0));
452275793eaSopenharmony_ci    if FZRec.avail_out = 0 then
453275793eaSopenharmony_ci    begin
454275793eaSopenharmony_ci      FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
455275793eaSopenharmony_ci      FZRec.next_out := FBuffer;
456275793eaSopenharmony_ci      FZRec.avail_out := sizeof(FBuffer);
457275793eaSopenharmony_ci      FStrmPos := FStrm.Position;
458275793eaSopenharmony_ci      Progress(Self);
459275793eaSopenharmony_ci    end;
460275793eaSopenharmony_ci  end;
461275793eaSopenharmony_ci  Result := Count;
462275793eaSopenharmony_ciend;
463275793eaSopenharmony_ci
464275793eaSopenharmony_cifunction TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
465275793eaSopenharmony_cibegin
466275793eaSopenharmony_ci  if (Offset = 0) and (Origin = soFromCurrent) then
467275793eaSopenharmony_ci    Result := FZRec.total_in
468275793eaSopenharmony_ci  else
469275793eaSopenharmony_ci    raise ECompressionError.CreateRes(@sInvalidStreamOp);
470275793eaSopenharmony_ciend;
471275793eaSopenharmony_ci
472275793eaSopenharmony_cifunction TCompressionStream.GetCompressionRate: Single;
473275793eaSopenharmony_cibegin
474275793eaSopenharmony_ci  if FZRec.total_in = 0 then
475275793eaSopenharmony_ci    Result := 0
476275793eaSopenharmony_ci  else
477275793eaSopenharmony_ci    Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0;
478275793eaSopenharmony_ciend;
479275793eaSopenharmony_ci
480275793eaSopenharmony_ci
481275793eaSopenharmony_ci// TDecompressionStream
482275793eaSopenharmony_ci
483275793eaSopenharmony_ciconstructor TDecompressionStream.Create(Source: TStream);
484275793eaSopenharmony_cibegin
485275793eaSopenharmony_ci  inherited Create(Source);
486275793eaSopenharmony_ci  FZRec.next_in := FBuffer;
487275793eaSopenharmony_ci  FZRec.avail_in := 0;
488275793eaSopenharmony_ci  DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec)));
489275793eaSopenharmony_ciend;
490275793eaSopenharmony_ci
491275793eaSopenharmony_cidestructor TDecompressionStream.Destroy;
492275793eaSopenharmony_cibegin
493275793eaSopenharmony_ci  FStrm.Seek(-FZRec.avail_in, 1);
494275793eaSopenharmony_ci  inflateEnd(FZRec);
495275793eaSopenharmony_ci  inherited Destroy;
496275793eaSopenharmony_ciend;
497275793eaSopenharmony_ci
498275793eaSopenharmony_cifunction TDecompressionStream.Read(var Buffer; Count: Longint): Longint;
499275793eaSopenharmony_cibegin
500275793eaSopenharmony_ci  FZRec.next_out := @Buffer;
501275793eaSopenharmony_ci  FZRec.avail_out := Count;
502275793eaSopenharmony_ci  if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
503275793eaSopenharmony_ci  while (FZRec.avail_out > 0) do
504275793eaSopenharmony_ci  begin
505275793eaSopenharmony_ci    if FZRec.avail_in = 0 then
506275793eaSopenharmony_ci    begin
507275793eaSopenharmony_ci      FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer));
508275793eaSopenharmony_ci      if FZRec.avail_in = 0 then
509275793eaSopenharmony_ci      begin
510275793eaSopenharmony_ci        Result := Count - FZRec.avail_out;
511275793eaSopenharmony_ci        Exit;
512275793eaSopenharmony_ci      end;
513275793eaSopenharmony_ci      FZRec.next_in := FBuffer;
514275793eaSopenharmony_ci      FStrmPos := FStrm.Position;
515275793eaSopenharmony_ci      Progress(Self);
516275793eaSopenharmony_ci    end;
517275793eaSopenharmony_ci    CCheck(inflate(FZRec, 0));
518275793eaSopenharmony_ci  end;
519275793eaSopenharmony_ci  Result := Count;
520275793eaSopenharmony_ciend;
521275793eaSopenharmony_ci
522275793eaSopenharmony_cifunction TDecompressionStream.Write(const Buffer; Count: Longint): Longint;
523275793eaSopenharmony_cibegin
524275793eaSopenharmony_ci  raise EDecompressionError.CreateRes(@sInvalidStreamOp);
525275793eaSopenharmony_ciend;
526275793eaSopenharmony_ci
527275793eaSopenharmony_cifunction TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
528275793eaSopenharmony_civar
529275793eaSopenharmony_ci  I: Integer;
530275793eaSopenharmony_ci  Buf: array [0..4095] of Char;
531275793eaSopenharmony_cibegin
532275793eaSopenharmony_ci  if (Offset = 0) and (Origin = soFromBeginning) then
533275793eaSopenharmony_ci  begin
534275793eaSopenharmony_ci    DCheck(inflateReset(FZRec));
535275793eaSopenharmony_ci    FZRec.next_in := FBuffer;
536275793eaSopenharmony_ci    FZRec.avail_in := 0;
537275793eaSopenharmony_ci    FStrm.Position := 0;
538275793eaSopenharmony_ci    FStrmPos := 0;
539275793eaSopenharmony_ci  end
540275793eaSopenharmony_ci  else if ( (Offset >= 0) and (Origin = soFromCurrent)) or
541275793eaSopenharmony_ci          ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then
542275793eaSopenharmony_ci  begin
543275793eaSopenharmony_ci    if Origin = soFromBeginning then Dec(Offset, FZRec.total_out);
544275793eaSopenharmony_ci    if Offset > 0 then
545275793eaSopenharmony_ci    begin
546275793eaSopenharmony_ci      for I := 1 to Offset div sizeof(Buf) do
547275793eaSopenharmony_ci        ReadBuffer(Buf, sizeof(Buf));
548275793eaSopenharmony_ci      ReadBuffer(Buf, Offset mod sizeof(Buf));
549275793eaSopenharmony_ci    end;
550275793eaSopenharmony_ci  end
551275793eaSopenharmony_ci  else
552275793eaSopenharmony_ci    raise EDecompressionError.CreateRes(@sInvalidStreamOp);
553275793eaSopenharmony_ci  Result := FZRec.total_out;
554275793eaSopenharmony_ciend;
555275793eaSopenharmony_ci
556275793eaSopenharmony_ci
557275793eaSopenharmony_ciend.
558