ZLib.pas revision 1.1.1.1 1 1.1 christos {*******************************************************}
2 1.1 christos { }
3 1.1 christos { Borland Delphi Supplemental Components }
4 1.1 christos { ZLIB Data Compression Interface Unit }
5 1.1 christos { }
6 1.1 christos { Copyright (c) 1997,99 Borland Corporation }
7 1.1 christos { }
8 1.1 christos {*******************************************************}
9 1.1 christos
10 1.1 christos { Updated for zlib 1.2.x by Cosmin Truta <cosmint (a] cs.ubbcluj.ro> }
11 1.1 christos
12 1.1 christos unit ZLib;
13 1.1 christos
14 1.1 christos interface
15 1.1 christos
16 1.1 christos uses SysUtils, Classes;
17 1.1 christos
18 1.1 christos type
19 1.1 christos TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
20 1.1 christos TFree = procedure (AppData, Block: Pointer); cdecl;
21 1.1 christos
22 1.1 christos // Internal structure. Ignore.
23 1.1 christos TZStreamRec = packed record
24 1.1 christos next_in: PChar; // next input byte
25 1.1 christos avail_in: Integer; // number of bytes available at next_in
26 1.1 christos total_in: Longint; // total nb of input bytes read so far
27 1.1 christos
28 1.1 christos next_out: PChar; // next output byte should be put here
29 1.1 christos avail_out: Integer; // remaining free space at next_out
30 1.1 christos total_out: Longint; // total nb of bytes output so far
31 1.1 christos
32 1.1 christos msg: PChar; // last error message, NULL if no error
33 1.1 christos internal: Pointer; // not visible by applications
34 1.1 christos
35 1.1 christos zalloc: TAlloc; // used to allocate the internal state
36 1.1 christos zfree: TFree; // used to free the internal state
37 1.1 christos AppData: Pointer; // private data object passed to zalloc and zfree
38 1.1 christos
39 1.1 christos data_type: Integer; // best guess about the data type: ascii or binary
40 1.1 christos adler: Longint; // adler32 value of the uncompressed data
41 1.1 christos reserved: Longint; // reserved for future use
42 1.1 christos end;
43 1.1 christos
44 1.1 christos // Abstract ancestor class
45 1.1 christos TCustomZlibStream = class(TStream)
46 1.1 christos private
47 1.1 christos FStrm: TStream;
48 1.1 christos FStrmPos: Integer;
49 1.1 christos FOnProgress: TNotifyEvent;
50 1.1 christos FZRec: TZStreamRec;
51 1.1 christos FBuffer: array [Word] of Char;
52 1.1 christos protected
53 1.1 christos procedure Progress(Sender: TObject); dynamic;
54 1.1 christos property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
55 1.1 christos constructor Create(Strm: TStream);
56 1.1 christos end;
57 1.1 christos
58 1.1 christos { TCompressionStream compresses data on the fly as data is written to it, and
59 1.1 christos stores the compressed data to another stream.
60 1.1 christos
61 1.1 christos TCompressionStream is write-only and strictly sequential. Reading from the
62 1.1 christos stream will raise an exception. Using Seek to move the stream pointer
63 1.1 christos will raise an exception.
64 1.1 christos
65 1.1 christos Output data is cached internally, written to the output stream only when
66 1.1 christos the internal output buffer is full. All pending output data is flushed
67 1.1 christos when the stream is destroyed.
68 1.1 christos
69 1.1 christos The Position property returns the number of uncompressed bytes of
70 1.1 christos data that have been written to the stream so far.
71 1.1 christos
72 1.1 christos CompressionRate returns the on-the-fly percentage by which the original
73 1.1 christos data has been compressed: (1 - (CompressedBytes / UncompressedBytes)) * 100
74 1.1 christos If raw data size = 100 and compressed data size = 25, the CompressionRate
75 1.1 christos is 75%
76 1.1 christos
77 1.1 christos The OnProgress event is called each time the output buffer is filled and
78 1.1 christos written to the output stream. This is useful for updating a progress
79 1.1 christos indicator when you are writing a large chunk of data to the compression
80 1.1 christos stream in a single call.}
81 1.1 christos
82 1.1 christos
83 1.1 christos TCompressionLevel = (clNone, clFastest, clDefault, clMax);
84 1.1 christos
85 1.1 christos TCompressionStream = class(TCustomZlibStream)
86 1.1 christos private
87 1.1 christos function GetCompressionRate: Single;
88 1.1 christos public
89 1.1 christos constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
90 1.1 christos destructor Destroy; override;
91 1.1 christos function Read(var Buffer; Count: Longint): Longint; override;
92 1.1 christos function Write(const Buffer; Count: Longint): Longint; override;
93 1.1 christos function Seek(Offset: Longint; Origin: Word): Longint; override;
94 1.1 christos property CompressionRate: Single read GetCompressionRate;
95 1.1 christos property OnProgress;
96 1.1 christos end;
97 1.1 christos
98 1.1 christos { TDecompressionStream decompresses data on the fly as data is read from it.
99 1.1 christos
100 1.1 christos Compressed data comes from a separate source stream. TDecompressionStream
101 1.1 christos is read-only and unidirectional; you can seek forward in the stream, but not
102 1.1 christos backwards. The special case of setting the stream position to zero is
103 1.1 christos allowed. Seeking forward decompresses data until the requested position in
104 1.1 christos the uncompressed data has been reached. Seeking backwards, seeking relative
105 1.1 christos to the end of the stream, requesting the size of the stream, and writing to
106 1.1 christos the stream will raise an exception.
107 1.1 christos
108 1.1 christos The Position property returns the number of bytes of uncompressed data that
109 1.1 christos have been read from the stream so far.
110 1.1 christos
111 1.1 christos The OnProgress event is called each time the internal input buffer of
112 1.1 christos compressed data is exhausted and the next block is read from the input stream.
113 1.1 christos This is useful for updating a progress indicator when you are reading a
114 1.1 christos large chunk of data from the decompression stream in a single call.}
115 1.1 christos
116 1.1 christos TDecompressionStream = class(TCustomZlibStream)
117 1.1 christos public
118 1.1 christos constructor Create(Source: TStream);
119 1.1 christos destructor Destroy; override;
120 1.1 christos function Read(var Buffer; Count: Longint): Longint; override;
121 1.1 christos function Write(const Buffer; Count: Longint): Longint; override;
122 1.1 christos function Seek(Offset: Longint; Origin: Word): Longint; override;
123 1.1 christos property OnProgress;
124 1.1 christos end;
125 1.1 christos
126 1.1 christos
127 1.1 christos
128 1.1 christos { CompressBuf compresses data, buffer to buffer, in one call.
129 1.1 christos In: InBuf = ptr to compressed data
130 1.1 christos InBytes = number of bytes in InBuf
131 1.1 christos Out: OutBuf = ptr to newly allocated buffer containing decompressed data
132 1.1 christos OutBytes = number of bytes in OutBuf }
133 1.1 christos procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
134 1.1 christos out OutBuf: Pointer; out OutBytes: Integer);
135 1.1 christos
136 1.1 christos
137 1.1 christos { DecompressBuf decompresses data, buffer to buffer, in one call.
138 1.1 christos In: InBuf = ptr to compressed data
139 1.1 christos InBytes = number of bytes in InBuf
140 1.1 christos OutEstimate = zero, or est. size of the decompressed data
141 1.1 christos Out: OutBuf = ptr to newly allocated buffer containing decompressed data
142 1.1 christos OutBytes = number of bytes in OutBuf }
143 1.1 christos procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
144 1.1 christos OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
145 1.1 christos
146 1.1 christos { DecompressToUserBuf decompresses data, buffer to buffer, in one call.
147 1.1 christos In: InBuf = ptr to compressed data
148 1.1 christos InBytes = number of bytes in InBuf
149 1.1 christos Out: OutBuf = ptr to user-allocated buffer to contain decompressed data
150 1.1 christos BufSize = number of bytes in OutBuf }
151 1.1 christos procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
152 1.1 christos const OutBuf: Pointer; BufSize: Integer);
153 1.1 christos
154 1.1 christos const
155 1.1 christos zlib_version = '1.2.3';
156 1.1 christos
157 1.1 christos type
158 1.1 christos EZlibError = class(Exception);
159 1.1 christos ECompressionError = class(EZlibError);
160 1.1 christos EDecompressionError = class(EZlibError);
161 1.1 christos
162 1.1 christos implementation
163 1.1 christos
164 1.1 christos uses ZLibConst;
165 1.1 christos
166 1.1 christos const
167 1.1 christos Z_NO_FLUSH = 0;
168 1.1 christos Z_PARTIAL_FLUSH = 1;
169 1.1 christos Z_SYNC_FLUSH = 2;
170 1.1 christos Z_FULL_FLUSH = 3;
171 1.1 christos Z_FINISH = 4;
172 1.1 christos
173 1.1 christos Z_OK = 0;
174 1.1 christos Z_STREAM_END = 1;
175 1.1 christos Z_NEED_DICT = 2;
176 1.1 christos Z_ERRNO = (-1);
177 1.1 christos Z_STREAM_ERROR = (-2);
178 1.1 christos Z_DATA_ERROR = (-3);
179 1.1 christos Z_MEM_ERROR = (-4);
180 1.1 christos Z_BUF_ERROR = (-5);
181 1.1 christos Z_VERSION_ERROR = (-6);
182 1.1 christos
183 1.1 christos Z_NO_COMPRESSION = 0;
184 1.1 christos Z_BEST_SPEED = 1;
185 1.1 christos Z_BEST_COMPRESSION = 9;
186 1.1 christos Z_DEFAULT_COMPRESSION = (-1);
187 1.1 christos
188 1.1 christos Z_FILTERED = 1;
189 1.1 christos Z_HUFFMAN_ONLY = 2;
190 1.1 christos Z_RLE = 3;
191 1.1 christos Z_DEFAULT_STRATEGY = 0;
192 1.1 christos
193 1.1 christos Z_BINARY = 0;
194 1.1 christos Z_ASCII = 1;
195 1.1 christos Z_UNKNOWN = 2;
196 1.1 christos
197 1.1 christos Z_DEFLATED = 8;
198 1.1 christos
199 1.1 christos
200 1.1 christos {$L adler32.obj}
201 1.1 christos {$L compress.obj}
202 1.1 christos {$L crc32.obj}
203 1.1 christos {$L deflate.obj}
204 1.1 christos {$L infback.obj}
205 1.1 christos {$L inffast.obj}
206 1.1 christos {$L inflate.obj}
207 1.1 christos {$L inftrees.obj}
208 1.1 christos {$L trees.obj}
209 1.1 christos {$L uncompr.obj}
210 1.1 christos {$L zutil.obj}
211 1.1 christos
212 1.1 christos procedure adler32; external;
213 1.1 christos procedure compressBound; external;
214 1.1 christos procedure crc32; external;
215 1.1 christos procedure deflateInit2_; external;
216 1.1 christos procedure deflateParams; external;
217 1.1 christos
218 1.1 christos function _malloc(Size: Integer): Pointer; cdecl;
219 1.1 christos begin
220 1.1 christos Result := AllocMem(Size);
221 1.1 christos end;
222 1.1 christos
223 1.1 christos procedure _free(Block: Pointer); cdecl;
224 1.1 christos begin
225 1.1 christos FreeMem(Block);
226 1.1 christos end;
227 1.1 christos
228 1.1 christos procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl;
229 1.1 christos begin
230 1.1 christos FillChar(P^, count, B);
231 1.1 christos end;
232 1.1 christos
233 1.1 christos procedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
234 1.1 christos begin
235 1.1 christos Move(source^, dest^, count);
236 1.1 christos end;
237 1.1 christos
238 1.1 christos
239 1.1 christos
240 1.1 christos // deflate compresses data
241 1.1 christos function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;
242 1.1 christos recsize: Integer): Integer; external;
243 1.1 christos function deflate(var strm: TZStreamRec; flush: Integer): Integer; external;
244 1.1 christos function deflateEnd(var strm: TZStreamRec): Integer; external;
245 1.1 christos
246 1.1 christos // inflate decompresses data
247 1.1 christos function inflateInit_(var strm: TZStreamRec; version: PChar;
248 1.1 christos recsize: Integer): Integer; external;
249 1.1 christos function inflate(var strm: TZStreamRec; flush: Integer): Integer; external;
250 1.1 christos function inflateEnd(var strm: TZStreamRec): Integer; external;
251 1.1 christos function inflateReset(var strm: TZStreamRec): Integer; external;
252 1.1 christos
253 1.1 christos
254 1.1 christos function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
255 1.1 christos begin
256 1.1 christos // GetMem(Result, Items*Size);
257 1.1 christos Result := AllocMem(Items * Size);
258 1.1 christos end;
259 1.1 christos
260 1.1 christos procedure zlibFreeMem(AppData, Block: Pointer); cdecl;
261 1.1 christos begin
262 1.1 christos FreeMem(Block);
263 1.1 christos end;
264 1.1 christos
265 1.1 christos {function zlibCheck(code: Integer): Integer;
266 1.1 christos begin
267 1.1 christos Result := code;
268 1.1 christos if code < 0 then
269 1.1 christos raise EZlibError.Create('error'); //!!
270 1.1 christos end;}
271 1.1 christos
272 1.1 christos function CCheck(code: Integer): Integer;
273 1.1 christos begin
274 1.1 christos Result := code;
275 1.1 christos if code < 0 then
276 1.1 christos raise ECompressionError.Create('error'); //!!
277 1.1 christos end;
278 1.1 christos
279 1.1 christos function DCheck(code: Integer): Integer;
280 1.1 christos begin
281 1.1 christos Result := code;
282 1.1 christos if code < 0 then
283 1.1 christos raise EDecompressionError.Create('error'); //!!
284 1.1 christos end;
285 1.1 christos
286 1.1 christos procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
287 1.1 christos out OutBuf: Pointer; out OutBytes: Integer);
288 1.1 christos var
289 1.1 christos strm: TZStreamRec;
290 1.1 christos P: Pointer;
291 1.1 christos begin
292 1.1 christos FillChar(strm, sizeof(strm), 0);
293 1.1 christos strm.zalloc := zlibAllocMem;
294 1.1 christos strm.zfree := zlibFreeMem;
295 1.1 christos OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
296 1.1 christos GetMem(OutBuf, OutBytes);
297 1.1 christos try
298 1.1 christos strm.next_in := InBuf;
299 1.1 christos strm.avail_in := InBytes;
300 1.1 christos strm.next_out := OutBuf;
301 1.1 christos strm.avail_out := OutBytes;
302 1.1 christos CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)));
303 1.1 christos try
304 1.1 christos while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
305 1.1 christos begin
306 1.1 christos P := OutBuf;
307 1.1 christos Inc(OutBytes, 256);
308 1.1 christos ReallocMem(OutBuf, OutBytes);
309 1.1 christos strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
310 1.1 christos strm.avail_out := 256;
311 1.1 christos end;
312 1.1 christos finally
313 1.1 christos CCheck(deflateEnd(strm));
314 1.1 christos end;
315 1.1 christos ReallocMem(OutBuf, strm.total_out);
316 1.1 christos OutBytes := strm.total_out;
317 1.1 christos except
318 1.1 christos FreeMem(OutBuf);
319 1.1 christos raise
320 1.1 christos end;
321 1.1 christos end;
322 1.1 christos
323 1.1 christos
324 1.1 christos procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
325 1.1 christos OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
326 1.1 christos var
327 1.1 christos strm: TZStreamRec;
328 1.1 christos P: Pointer;
329 1.1 christos BufInc: Integer;
330 1.1 christos begin
331 1.1 christos FillChar(strm, sizeof(strm), 0);
332 1.1 christos strm.zalloc := zlibAllocMem;
333 1.1 christos strm.zfree := zlibFreeMem;
334 1.1 christos BufInc := (InBytes + 255) and not 255;
335 1.1 christos if OutEstimate = 0 then
336 1.1 christos OutBytes := BufInc
337 1.1 christos else
338 1.1 christos OutBytes := OutEstimate;
339 1.1 christos GetMem(OutBuf, OutBytes);
340 1.1 christos try
341 1.1 christos strm.next_in := InBuf;
342 1.1 christos strm.avail_in := InBytes;
343 1.1 christos strm.next_out := OutBuf;
344 1.1 christos strm.avail_out := OutBytes;
345 1.1 christos DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
346 1.1 christos try
347 1.1 christos while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do
348 1.1 christos begin
349 1.1 christos P := OutBuf;
350 1.1 christos Inc(OutBytes, BufInc);
351 1.1 christos ReallocMem(OutBuf, OutBytes);
352 1.1 christos strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
353 1.1 christos strm.avail_out := BufInc;
354 1.1 christos end;
355 1.1 christos finally
356 1.1 christos DCheck(inflateEnd(strm));
357 1.1 christos end;
358 1.1 christos ReallocMem(OutBuf, strm.total_out);
359 1.1 christos OutBytes := strm.total_out;
360 1.1 christos except
361 1.1 christos FreeMem(OutBuf);
362 1.1 christos raise
363 1.1 christos end;
364 1.1 christos end;
365 1.1 christos
366 1.1 christos procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
367 1.1 christos const OutBuf: Pointer; BufSize: Integer);
368 1.1 christos var
369 1.1 christos strm: TZStreamRec;
370 1.1 christos begin
371 1.1 christos FillChar(strm, sizeof(strm), 0);
372 1.1 christos strm.zalloc := zlibAllocMem;
373 1.1 christos strm.zfree := zlibFreeMem;
374 1.1 christos strm.next_in := InBuf;
375 1.1 christos strm.avail_in := InBytes;
376 1.1 christos strm.next_out := OutBuf;
377 1.1 christos strm.avail_out := BufSize;
378 1.1 christos DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
379 1.1 christos try
380 1.1 christos if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then
381 1.1 christos raise EZlibError.CreateRes(@sTargetBufferTooSmall);
382 1.1 christos finally
383 1.1 christos DCheck(inflateEnd(strm));
384 1.1 christos end;
385 1.1 christos end;
386 1.1 christos
387 1.1 christos // TCustomZlibStream
388 1.1 christos
389 1.1 christos constructor TCustomZLibStream.Create(Strm: TStream);
390 1.1 christos begin
391 1.1 christos inherited Create;
392 1.1 christos FStrm := Strm;
393 1.1 christos FStrmPos := Strm.Position;
394 1.1 christos FZRec.zalloc := zlibAllocMem;
395 1.1 christos FZRec.zfree := zlibFreeMem;
396 1.1 christos end;
397 1.1 christos
398 1.1 christos procedure TCustomZLibStream.Progress(Sender: TObject);
399 1.1 christos begin
400 1.1 christos if Assigned(FOnProgress) then FOnProgress(Sender);
401 1.1 christos end;
402 1.1 christos
403 1.1 christos
404 1.1 christos // TCompressionStream
405 1.1 christos
406 1.1 christos constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
407 1.1 christos Dest: TStream);
408 1.1 christos const
409 1.1 christos Levels: array [TCompressionLevel] of ShortInt =
410 1.1 christos (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
411 1.1 christos begin
412 1.1 christos inherited Create(Dest);
413 1.1 christos FZRec.next_out := FBuffer;
414 1.1 christos FZRec.avail_out := sizeof(FBuffer);
415 1.1 christos CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec)));
416 1.1 christos end;
417 1.1 christos
418 1.1 christos destructor TCompressionStream.Destroy;
419 1.1 christos begin
420 1.1 christos FZRec.next_in := nil;
421 1.1 christos FZRec.avail_in := 0;
422 1.1 christos try
423 1.1 christos if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
424 1.1 christos while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
425 1.1 christos and (FZRec.avail_out = 0) do
426 1.1 christos begin
427 1.1 christos FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
428 1.1 christos FZRec.next_out := FBuffer;
429 1.1 christos FZRec.avail_out := sizeof(FBuffer);
430 1.1 christos end;
431 1.1 christos if FZRec.avail_out < sizeof(FBuffer) then
432 1.1 christos FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
433 1.1 christos finally
434 1.1 christos deflateEnd(FZRec);
435 1.1 christos end;
436 1.1 christos inherited Destroy;
437 1.1 christos end;
438 1.1 christos
439 1.1 christos function TCompressionStream.Read(var Buffer; Count: Longint): Longint;
440 1.1 christos begin
441 1.1 christos raise ECompressionError.CreateRes(@sInvalidStreamOp);
442 1.1 christos end;
443 1.1 christos
444 1.1 christos function TCompressionStream.Write(const Buffer; Count: Longint): Longint;
445 1.1 christos begin
446 1.1 christos FZRec.next_in := @Buffer;
447 1.1 christos FZRec.avail_in := Count;
448 1.1 christos if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
449 1.1 christos while (FZRec.avail_in > 0) do
450 1.1 christos begin
451 1.1 christos CCheck(deflate(FZRec, 0));
452 1.1 christos if FZRec.avail_out = 0 then
453 1.1 christos begin
454 1.1 christos FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
455 1.1 christos FZRec.next_out := FBuffer;
456 1.1 christos FZRec.avail_out := sizeof(FBuffer);
457 1.1 christos FStrmPos := FStrm.Position;
458 1.1 christos Progress(Self);
459 1.1 christos end;
460 1.1 christos end;
461 1.1 christos Result := Count;
462 1.1 christos end;
463 1.1 christos
464 1.1 christos function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
465 1.1 christos begin
466 1.1 christos if (Offset = 0) and (Origin = soFromCurrent) then
467 1.1 christos Result := FZRec.total_in
468 1.1 christos else
469 1.1 christos raise ECompressionError.CreateRes(@sInvalidStreamOp);
470 1.1 christos end;
471 1.1 christos
472 1.1 christos function TCompressionStream.GetCompressionRate: Single;
473 1.1 christos begin
474 1.1 christos if FZRec.total_in = 0 then
475 1.1 christos Result := 0
476 1.1 christos else
477 1.1 christos Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0;
478 1.1 christos end;
479 1.1 christos
480 1.1 christos
481 1.1 christos // TDecompressionStream
482 1.1 christos
483 1.1 christos constructor TDecompressionStream.Create(Source: TStream);
484 1.1 christos begin
485 1.1 christos inherited Create(Source);
486 1.1 christos FZRec.next_in := FBuffer;
487 1.1 christos FZRec.avail_in := 0;
488 1.1 christos DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec)));
489 1.1 christos end;
490 1.1 christos
491 1.1 christos destructor TDecompressionStream.Destroy;
492 1.1 christos begin
493 1.1 christos FStrm.Seek(-FZRec.avail_in, 1);
494 1.1 christos inflateEnd(FZRec);
495 1.1 christos inherited Destroy;
496 1.1 christos end;
497 1.1 christos
498 1.1 christos function TDecompressionStream.Read(var Buffer; Count: Longint): Longint;
499 1.1 christos begin
500 1.1 christos FZRec.next_out := @Buffer;
501 1.1 christos FZRec.avail_out := Count;
502 1.1 christos if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
503 1.1 christos while (FZRec.avail_out > 0) do
504 1.1 christos begin
505 1.1 christos if FZRec.avail_in = 0 then
506 1.1 christos begin
507 1.1 christos FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer));
508 1.1 christos if FZRec.avail_in = 0 then
509 1.1 christos begin
510 1.1 christos Result := Count - FZRec.avail_out;
511 1.1 christos Exit;
512 1.1 christos end;
513 1.1 christos FZRec.next_in := FBuffer;
514 1.1 christos FStrmPos := FStrm.Position;
515 1.1 christos Progress(Self);
516 1.1 christos end;
517 1.1 christos CCheck(inflate(FZRec, 0));
518 1.1 christos end;
519 1.1 christos Result := Count;
520 1.1 christos end;
521 1.1 christos
522 1.1 christos function TDecompressionStream.Write(const Buffer; Count: Longint): Longint;
523 1.1 christos begin
524 1.1 christos raise EDecompressionError.CreateRes(@sInvalidStreamOp);
525 1.1 christos end;
526 1.1 christos
527 1.1 christos function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
528 1.1 christos var
529 1.1 christos I: Integer;
530 1.1 christos Buf: array [0..4095] of Char;
531 1.1 christos begin
532 1.1 christos if (Offset = 0) and (Origin = soFromBeginning) then
533 1.1 christos begin
534 1.1 christos DCheck(inflateReset(FZRec));
535 1.1 christos FZRec.next_in := FBuffer;
536 1.1 christos FZRec.avail_in := 0;
537 1.1 christos FStrm.Position := 0;
538 1.1 christos FStrmPos := 0;
539 1.1 christos end
540 1.1 christos else if ( (Offset >= 0) and (Origin = soFromCurrent)) or
541 1.1 christos ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then
542 1.1 christos begin
543 1.1 christos if Origin = soFromBeginning then Dec(Offset, FZRec.total_out);
544 1.1 christos if Offset > 0 then
545 1.1 christos begin
546 1.1 christos for I := 1 to Offset div sizeof(Buf) do
547 1.1 christos ReadBuffer(Buf, sizeof(Buf));
548 1.1 christos ReadBuffer(Buf, Offset mod sizeof(Buf));
549 1.1 christos end;
550 1.1 christos end
551 1.1 christos else
552 1.1 christos raise EDecompressionError.CreateRes(@sInvalidStreamOp);
553 1.1 christos Result := FZRec.total_out;
554 1.1 christos end;
555 1.1 christos
556 1.1 christos
557 1.1 christos end.
558