116dce513Schristos {*******************************************************}
216dce513Schristos { }
316dce513Schristos { Borland Delphi Supplemental Components }
416dce513Schristos { ZLIB Data Compression Interface Unit }
516dce513Schristos { }
616dce513Schristos { Copyright (c) 1997,99 Borland Corporation }
716dce513Schristos { }
816dce513Schristos {*******************************************************}
916dce513Schristos
1016dce513Schristos { Updated for zlib 1.2.x by Cosmin Truta <cosmint@cs.ubbcluj.ro> }
1116dce513Schristos
1216dce513Schristos unit ZLib;
1316dce513Schristos
1416dce513Schristos interface
1516dce513Schristos
1616dce513Schristos uses SysUtils, Classes;
1716dce513Schristos
1816dce513Schristos type
ppData()1916dce513Schristos TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
2016dce513Schristos TFree = procedure (AppData, Block: Pointer); cdecl;
2116dce513Schristos
2216dce513Schristos // Internal structure. Ignore.
2316dce513Schristos TZStreamRec = packed record
2416dce513Schristos next_in: PChar; // next input byte
2516dce513Schristos avail_in: Integer; // number of bytes available at next_in
2616dce513Schristos total_in: Longint; // total nb of input bytes read so far
2716dce513Schristos
2816dce513Schristos next_out: PChar; // next output byte should be put here
2916dce513Schristos avail_out: Integer; // remaining free space at next_out
3016dce513Schristos total_out: Longint; // total nb of bytes output so far
3116dce513Schristos
3216dce513Schristos msg: PChar; // last error message, NULL if no error
3316dce513Schristos internal: Pointer; // not visible by applications
3416dce513Schristos
3516dce513Schristos zalloc: TAlloc; // used to allocate the internal state
3616dce513Schristos zfree: TFree; // used to free the internal state
3716dce513Schristos AppData: Pointer; // private data object passed to zalloc and zfree
3816dce513Schristos
3916dce513Schristos data_type: Integer; // best guess about the data type: ascii or binary
4016dce513Schristos adler: Longint; // adler32 value of the uncompressed data
4116dce513Schristos reserved: Longint; // reserved for future use
4216dce513Schristos end;
4316dce513Schristos
4416dce513Schristos // Abstract ancestor class
4516dce513Schristos TCustomZlibStream = class(TStream)
4616dce513Schristos private
4716dce513Schristos FStrm: TStream;
4816dce513Schristos FStrmPos: Integer;
4916dce513Schristos FOnProgress: TNotifyEvent;
5016dce513Schristos FZRec: TZStreamRec;
5116dce513Schristos FBuffer: array [Word] of Char;
5216dce513Schristos protected
5316dce513Schristos procedure Progress(Sender: TObject); dynamic;
5416dce513Schristos property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
5516dce513Schristos constructor Create(Strm: TStream);
5616dce513Schristos end;
5716dce513Schristos
5816dce513Schristos { TCompressionStream compresses data on the fly as data is written to it, and
5916dce513Schristos stores the compressed data to another stream.
6016dce513Schristos
6116dce513Schristos TCompressionStream is write-only and strictly sequential. Reading from the
6216dce513Schristos stream will raise an exception. Using Seek to move the stream pointer
6316dce513Schristos will raise an exception.
6416dce513Schristos
6516dce513Schristos Output data is cached internally, written to the output stream only when
6616dce513Schristos the internal output buffer is full. All pending output data is flushed
6716dce513Schristos when the stream is destroyed.
6816dce513Schristos
6916dce513Schristos The Position property returns the number of uncompressed bytes of
7016dce513Schristos data that have been written to the stream so far.
7116dce513Schristos
7216dce513Schristos CompressionRate returns the on-the-fly percentage by which the original
7316dce513Schristos data has been compressed: (1 - (CompressedBytes / UncompressedBytes)) * 100
7416dce513Schristos If raw data size = 100 and compressed data size = 25, the CompressionRate
7516dce513Schristos is 75%
7616dce513Schristos
7716dce513Schristos The OnProgress event is called each time the output buffer is filled and
7816dce513Schristos written to the output stream. This is useful for updating a progress
7916dce513Schristos indicator when you are writing a large chunk of data to the compression
8016dce513Schristos stream in a single call.}
8116dce513Schristos
8216dce513Schristos
8316dce513Schristos TCompressionLevel = (clNone, clFastest, clDefault, clMax);
8416dce513Schristos
8516dce513Schristos TCompressionStream = class(TCustomZlibStream)
8616dce513Schristos private
GetCompressionRate()8716dce513Schristos function GetCompressionRate: Single;
8816dce513Schristos public
8916dce513Schristos constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
9016dce513Schristos destructor Destroy; override;
Read(var Buffer; Count: Longint)9116dce513Schristos function Read(var Buffer; Count: Longint): Longint; override;
Write(const Buffer; Count: Longint)9216dce513Schristos function Write(const Buffer; Count: Longint): Longint; override;
Seek(Offset: Longint; Origin: Word)9316dce513Schristos function Seek(Offset: Longint; Origin: Word): Longint; override;
9416dce513Schristos property CompressionRate: Single read GetCompressionRate;
9516dce513Schristos property OnProgress;
9616dce513Schristos end;
9716dce513Schristos
9816dce513Schristos { TDecompressionStream decompresses data on the fly as data is read from it.
9916dce513Schristos
10016dce513Schristos Compressed data comes from a separate source stream. TDecompressionStream
10116dce513Schristos is read-only and unidirectional; you can seek forward in the stream, but not
10216dce513Schristos backwards. The special case of setting the stream position to zero is
10316dce513Schristos allowed. Seeking forward decompresses data until the requested position in
10416dce513Schristos the uncompressed data has been reached. Seeking backwards, seeking relative
10516dce513Schristos to the end of the stream, requesting the size of the stream, and writing to
10616dce513Schristos the stream will raise an exception.
10716dce513Schristos
10816dce513Schristos The Position property returns the number of bytes of uncompressed data that
10916dce513Schristos have been read from the stream so far.
11016dce513Schristos
11116dce513Schristos The OnProgress event is called each time the internal input buffer of
11216dce513Schristos compressed data is exhausted and the next block is read from the input stream.
11316dce513Schristos This is useful for updating a progress indicator when you are reading a
11416dce513Schristos large chunk of data from the decompression stream in a single call.}
11516dce513Schristos
11616dce513Schristos TDecompressionStream = class(TCustomZlibStream)
11716dce513Schristos public
11816dce513Schristos constructor Create(Source: TStream);
11916dce513Schristos destructor Destroy; override;
Read(var Buffer; Count: Longint)12016dce513Schristos function Read(var Buffer; Count: Longint): Longint; override;
Write(const Buffer; Count: Longint)12116dce513Schristos function Write(const Buffer; Count: Longint): Longint; override;
Seek(Offset: Longint; Origin: Word)12216dce513Schristos function Seek(Offset: Longint; Origin: Word): Longint; override;
12316dce513Schristos property OnProgress;
12416dce513Schristos end;
12516dce513Schristos
12616dce513Schristos
12716dce513Schristos
12816dce513Schristos { CompressBuf compresses data, buffer to buffer, in one call.
12916dce513Schristos In: InBuf = ptr to compressed data
13016dce513Schristos InBytes = number of bytes in InBuf
13116dce513Schristos Out: OutBuf = ptr to newly allocated buffer containing decompressed data
13216dce513Schristos OutBytes = number of bytes in OutBuf }
13316dce513Schristos procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
13416dce513Schristos out OutBuf: Pointer; out OutBytes: Integer);
13516dce513Schristos
13616dce513Schristos
13716dce513Schristos { DecompressBuf decompresses data, buffer to buffer, in one call.
13816dce513Schristos In: InBuf = ptr to compressed data
13916dce513Schristos InBytes = number of bytes in InBuf
14016dce513Schristos OutEstimate = zero, or est. size of the decompressed data
14116dce513Schristos Out: OutBuf = ptr to newly allocated buffer containing decompressed data
14216dce513Schristos OutBytes = number of bytes in OutBuf }
14316dce513Schristos procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
14416dce513Schristos OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
14516dce513Schristos
14616dce513Schristos { DecompressToUserBuf decompresses data, buffer to buffer, in one call.
14716dce513Schristos In: InBuf = ptr to compressed data
14816dce513Schristos InBytes = number of bytes in InBuf
14916dce513Schristos Out: OutBuf = ptr to user-allocated buffer to contain decompressed data
15016dce513Schristos BufSize = number of bytes in OutBuf }
15116dce513Schristos procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
15216dce513Schristos const OutBuf: Pointer; BufSize: Integer);
15316dce513Schristos
15416dce513Schristos const
155*e992f068Schristos zlib_version = '1.2.12';
15616dce513Schristos
15716dce513Schristos type
15816dce513Schristos EZlibError = class(Exception);
15916dce513Schristos ECompressionError = class(EZlibError);
16016dce513Schristos EDecompressionError = class(EZlibError);
16116dce513Schristos
16216dce513Schristos implementation
16316dce513Schristos
16416dce513Schristos uses ZLibConst;
16516dce513Schristos
16616dce513Schristos const
16716dce513Schristos Z_NO_FLUSH = 0;
16816dce513Schristos Z_PARTIAL_FLUSH = 1;
16916dce513Schristos Z_SYNC_FLUSH = 2;
17016dce513Schristos Z_FULL_FLUSH = 3;
17116dce513Schristos Z_FINISH = 4;
17216dce513Schristos
17316dce513Schristos Z_OK = 0;
17416dce513Schristos Z_STREAM_END = 1;
17516dce513Schristos Z_NEED_DICT = 2;
17616dce513Schristos Z_ERRNO = (-1);
17716dce513Schristos Z_STREAM_ERROR = (-2);
17816dce513Schristos Z_DATA_ERROR = (-3);
17916dce513Schristos Z_MEM_ERROR = (-4);
18016dce513Schristos Z_BUF_ERROR = (-5);
18116dce513Schristos Z_VERSION_ERROR = (-6);
18216dce513Schristos
18316dce513Schristos Z_NO_COMPRESSION = 0;
18416dce513Schristos Z_BEST_SPEED = 1;
18516dce513Schristos Z_BEST_COMPRESSION = 9;
18616dce513Schristos Z_DEFAULT_COMPRESSION = (-1);
18716dce513Schristos
18816dce513Schristos Z_FILTERED = 1;
18916dce513Schristos Z_HUFFMAN_ONLY = 2;
19016dce513Schristos Z_RLE = 3;
19116dce513Schristos Z_DEFAULT_STRATEGY = 0;
19216dce513Schristos
19316dce513Schristos Z_BINARY = 0;
19416dce513Schristos Z_ASCII = 1;
19516dce513Schristos Z_UNKNOWN = 2;
19616dce513Schristos
19716dce513Schristos Z_DEFLATED = 8;
19816dce513Schristos
19916dce513Schristos
20016dce513Schristos {$L adler32.obj}
20116dce513Schristos {$L compress.obj}
20216dce513Schristos {$L crc32.obj}
20316dce513Schristos {$L deflate.obj}
20416dce513Schristos {$L infback.obj}
20516dce513Schristos {$L inffast.obj}
20616dce513Schristos {$L inflate.obj}
20716dce513Schristos {$L inftrees.obj}
20816dce513Schristos {$L trees.obj}
20916dce513Schristos {$L uncompr.obj}
21016dce513Schristos {$L zutil.obj}
21116dce513Schristos
21216dce513Schristos procedure adler32; external;
21316dce513Schristos procedure compressBound; external;
21416dce513Schristos procedure crc32; external;
21516dce513Schristos procedure deflateInit2_; external;
21616dce513Schristos procedure deflateParams; external;
21716dce513Schristos
_malloc(Size: Integer)21816dce513Schristos function _malloc(Size: Integer): Pointer; cdecl;
21916dce513Schristos begin
22016dce513Schristos Result := AllocMem(Size);
22116dce513Schristos end;
22216dce513Schristos
22316dce513Schristos procedure _free(Block: Pointer); cdecl;
22416dce513Schristos begin
22516dce513Schristos FreeMem(Block);
22616dce513Schristos end;
22716dce513Schristos
22816dce513Schristos procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl;
22916dce513Schristos begin
23016dce513Schristos FillChar(P^, count, B);
23116dce513Schristos end;
23216dce513Schristos
23316dce513Schristos procedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
23416dce513Schristos begin
23516dce513Schristos Move(source^, dest^, count);
23616dce513Schristos end;
23716dce513Schristos
23816dce513Schristos
23916dce513Schristos
24016dce513Schristos // deflate compresses data
deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;24116dce513Schristos function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;
24216dce513Schristos recsize: Integer): Integer; external;
deflate(var strm: TZStreamRec; flush: Integer)24316dce513Schristos function deflate(var strm: TZStreamRec; flush: Integer): Integer; external;
deflateEnd(var strm: TZStreamRec)24416dce513Schristos function deflateEnd(var strm: TZStreamRec): Integer; external;
24516dce513Schristos
24616dce513Schristos // inflate decompresses data
inflateInit_(var strm: TZStreamRec; version: PChar;24716dce513Schristos function inflateInit_(var strm: TZStreamRec; version: PChar;
24816dce513Schristos recsize: Integer): Integer; external;
inflate(var strm: TZStreamRec; flush: Integer)24916dce513Schristos function inflate(var strm: TZStreamRec; flush: Integer): Integer; external;
inflateEnd(var strm: TZStreamRec)25016dce513Schristos function inflateEnd(var strm: TZStreamRec): Integer; external;
inflateReset(var strm: TZStreamRec)25116dce513Schristos function inflateReset(var strm: TZStreamRec): Integer; external;
25216dce513Schristos
25316dce513Schristos
zlibAllocMem(AppData: Pointer; Items, Size: Integer)25416dce513Schristos function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
25516dce513Schristos begin
25616dce513Schristos // GetMem(Result, Items*Size);
25716dce513Schristos Result := AllocMem(Items * Size);
25816dce513Schristos end;
25916dce513Schristos
26016dce513Schristos procedure zlibFreeMem(AppData, Block: Pointer); cdecl;
26116dce513Schristos begin
26216dce513Schristos FreeMem(Block);
26316dce513Schristos end;
26416dce513Schristos
26516dce513Schristos {function zlibCheck(code: Integer): Integer;
26616dce513Schristos begin
26716dce513Schristos Result := code;
26816dce513Schristos if code < 0 then
26916dce513Schristos raise EZlibError.Create('error'); //!!
27016dce513Schristos end;}
27116dce513Schristos
CCheck(code: Integer)27216dce513Schristos function CCheck(code: Integer): Integer;
27316dce513Schristos begin
27416dce513Schristos Result := code;
27516dce513Schristos if code < 0 then
27616dce513Schristos raise ECompressionError.Create('error'); //!!
27716dce513Schristos end;
27816dce513Schristos
DCheck(code: Integer)27916dce513Schristos function DCheck(code: Integer): Integer;
28016dce513Schristos begin
28116dce513Schristos Result := code;
28216dce513Schristos if code < 0 then
28316dce513Schristos raise EDecompressionError.Create('error'); //!!
28416dce513Schristos end;
28516dce513Schristos
28616dce513Schristos procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
28716dce513Schristos out OutBuf: Pointer; out OutBytes: Integer);
28816dce513Schristos var
28916dce513Schristos strm: TZStreamRec;
29016dce513Schristos P: Pointer;
29116dce513Schristos begin
29216dce513Schristos FillChar(strm, sizeof(strm), 0);
29316dce513Schristos strm.zalloc := zlibAllocMem;
29416dce513Schristos strm.zfree := zlibFreeMem;
29516dce513Schristos OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
29616dce513Schristos GetMem(OutBuf, OutBytes);
29716dce513Schristos try
29816dce513Schristos strm.next_in := InBuf;
29916dce513Schristos strm.avail_in := InBytes;
30016dce513Schristos strm.next_out := OutBuf;
30116dce513Schristos strm.avail_out := OutBytes;
30216dce513Schristos CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)));
30316dce513Schristos try
30416dce513Schristos while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
30516dce513Schristos begin
30616dce513Schristos P := OutBuf;
30716dce513Schristos Inc(OutBytes, 256);
30816dce513Schristos ReallocMem(OutBuf, OutBytes);
30916dce513Schristos strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
31016dce513Schristos strm.avail_out := 256;
31116dce513Schristos end;
31216dce513Schristos finally
31316dce513Schristos CCheck(deflateEnd(strm));
31416dce513Schristos end;
31516dce513Schristos ReallocMem(OutBuf, strm.total_out);
31616dce513Schristos OutBytes := strm.total_out;
31716dce513Schristos except
31816dce513Schristos FreeMem(OutBuf);
31916dce513Schristos raise
32016dce513Schristos end;
32116dce513Schristos end;
32216dce513Schristos
32316dce513Schristos
32416dce513Schristos procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
32516dce513Schristos OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
32616dce513Schristos var
32716dce513Schristos strm: TZStreamRec;
32816dce513Schristos P: Pointer;
32916dce513Schristos BufInc: Integer;
33016dce513Schristos begin
33116dce513Schristos FillChar(strm, sizeof(strm), 0);
33216dce513Schristos strm.zalloc := zlibAllocMem;
33316dce513Schristos strm.zfree := zlibFreeMem;
33416dce513Schristos BufInc := (InBytes + 255) and not 255;
33516dce513Schristos if OutEstimate = 0 then
33616dce513Schristos OutBytes := BufInc
33716dce513Schristos else
33816dce513Schristos OutBytes := OutEstimate;
33916dce513Schristos GetMem(OutBuf, OutBytes);
34016dce513Schristos try
34116dce513Schristos strm.next_in := InBuf;
34216dce513Schristos strm.avail_in := InBytes;
34316dce513Schristos strm.next_out := OutBuf;
34416dce513Schristos strm.avail_out := OutBytes;
34516dce513Schristos DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
34616dce513Schristos try
34716dce513Schristos while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do
34816dce513Schristos begin
34916dce513Schristos P := OutBuf;
35016dce513Schristos Inc(OutBytes, BufInc);
35116dce513Schristos ReallocMem(OutBuf, OutBytes);
35216dce513Schristos strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
35316dce513Schristos strm.avail_out := BufInc;
35416dce513Schristos end;
35516dce513Schristos finally
35616dce513Schristos DCheck(inflateEnd(strm));
35716dce513Schristos end;
35816dce513Schristos ReallocMem(OutBuf, strm.total_out);
35916dce513Schristos OutBytes := strm.total_out;
36016dce513Schristos except
36116dce513Schristos FreeMem(OutBuf);
36216dce513Schristos raise
36316dce513Schristos end;
36416dce513Schristos end;
36516dce513Schristos
36616dce513Schristos procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
36716dce513Schristos const OutBuf: Pointer; BufSize: Integer);
36816dce513Schristos var
36916dce513Schristos strm: TZStreamRec;
37016dce513Schristos begin
37116dce513Schristos FillChar(strm, sizeof(strm), 0);
37216dce513Schristos strm.zalloc := zlibAllocMem;
37316dce513Schristos strm.zfree := zlibFreeMem;
37416dce513Schristos strm.next_in := InBuf;
37516dce513Schristos strm.avail_in := InBytes;
37616dce513Schristos strm.next_out := OutBuf;
37716dce513Schristos strm.avail_out := BufSize;
37816dce513Schristos DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
37916dce513Schristos try
38016dce513Schristos if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then
38116dce513Schristos raise EZlibError.CreateRes(@sTargetBufferTooSmall);
38216dce513Schristos finally
38316dce513Schristos DCheck(inflateEnd(strm));
38416dce513Schristos end;
38516dce513Schristos end;
38616dce513Schristos
38716dce513Schristos // TCustomZlibStream
38816dce513Schristos
38916dce513Schristos constructor TCustomZLibStream.Create(Strm: TStream);
39016dce513Schristos begin
39116dce513Schristos inherited Create;
39216dce513Schristos FStrm := Strm;
39316dce513Schristos FStrmPos := Strm.Position;
39416dce513Schristos FZRec.zalloc := zlibAllocMem;
39516dce513Schristos FZRec.zfree := zlibFreeMem;
39616dce513Schristos end;
39716dce513Schristos
39816dce513Schristos procedure TCustomZLibStream.Progress(Sender: TObject);
39916dce513Schristos begin
40016dce513Schristos if Assigned(FOnProgress) then FOnProgress(Sender);
40116dce513Schristos end;
40216dce513Schristos
40316dce513Schristos
40416dce513Schristos // TCompressionStream
40516dce513Schristos
40616dce513Schristos constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
40716dce513Schristos Dest: TStream);
40816dce513Schristos const
40916dce513Schristos Levels: array [TCompressionLevel] of ShortInt =
41016dce513Schristos (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
41116dce513Schristos begin
41216dce513Schristos inherited Create(Dest);
41316dce513Schristos FZRec.next_out := FBuffer;
41416dce513Schristos FZRec.avail_out := sizeof(FBuffer);
41516dce513Schristos CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec)));
41616dce513Schristos end;
41716dce513Schristos
41816dce513Schristos destructor TCompressionStream.Destroy;
41916dce513Schristos begin
42016dce513Schristos FZRec.next_in := nil;
42116dce513Schristos FZRec.avail_in := 0;
42216dce513Schristos try
42316dce513Schristos if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
42416dce513Schristos while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
42516dce513Schristos and (FZRec.avail_out = 0) do
42616dce513Schristos begin
42716dce513Schristos FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
42816dce513Schristos FZRec.next_out := FBuffer;
42916dce513Schristos FZRec.avail_out := sizeof(FBuffer);
43016dce513Schristos end;
43116dce513Schristos if FZRec.avail_out < sizeof(FBuffer) then
43216dce513Schristos FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
43316dce513Schristos finally
43416dce513Schristos deflateEnd(FZRec);
43516dce513Schristos end;
43616dce513Schristos inherited Destroy;
43716dce513Schristos end;
43816dce513Schristos
Readnull43916dce513Schristos function TCompressionStream.Read(var Buffer; Count: Longint): Longint;
44016dce513Schristos begin
44116dce513Schristos raise ECompressionError.CreateRes(@sInvalidStreamOp);
44216dce513Schristos end;
44316dce513Schristos
Writenull44416dce513Schristos function TCompressionStream.Write(const Buffer; Count: Longint): Longint;
44516dce513Schristos begin
44616dce513Schristos FZRec.next_in := @Buffer;
44716dce513Schristos FZRec.avail_in := Count;
44816dce513Schristos if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
44916dce513Schristos while (FZRec.avail_in > 0) do
45016dce513Schristos begin
45116dce513Schristos CCheck(deflate(FZRec, 0));
45216dce513Schristos if FZRec.avail_out = 0 then
45316dce513Schristos begin
45416dce513Schristos FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
45516dce513Schristos FZRec.next_out := FBuffer;
45616dce513Schristos FZRec.avail_out := sizeof(FBuffer);
45716dce513Schristos FStrmPos := FStrm.Position;
45816dce513Schristos Progress(Self);
45916dce513Schristos end;
46016dce513Schristos end;
46116dce513Schristos Result := Count;
46216dce513Schristos end;
46316dce513Schristos
TCompressionStream.Seek(Offset: Longint; Origin: Word)46416dce513Schristos function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
46516dce513Schristos begin
46616dce513Schristos if (Offset = 0) and (Origin = soFromCurrent) then
46716dce513Schristos Result := FZRec.total_in
46816dce513Schristos else
46916dce513Schristos raise ECompressionError.CreateRes(@sInvalidStreamOp);
47016dce513Schristos end;
47116dce513Schristos
TCompressionStream.GetCompressionRate()47216dce513Schristos function TCompressionStream.GetCompressionRate: Single;
47316dce513Schristos begin
47416dce513Schristos if FZRec.total_in = 0 then
47516dce513Schristos Result := 0
47616dce513Schristos else
47716dce513Schristos Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0;
47816dce513Schristos end;
47916dce513Schristos
48016dce513Schristos
48116dce513Schristos // TDecompressionStream
48216dce513Schristos
48316dce513Schristos constructor TDecompressionStream.Create(Source: TStream);
48416dce513Schristos begin
48516dce513Schristos inherited Create(Source);
48616dce513Schristos FZRec.next_in := FBuffer;
48716dce513Schristos FZRec.avail_in := 0;
48816dce513Schristos DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec)));
48916dce513Schristos end;
49016dce513Schristos
49116dce513Schristos destructor TDecompressionStream.Destroy;
49216dce513Schristos begin
49316dce513Schristos FStrm.Seek(-FZRec.avail_in, 1);
49416dce513Schristos inflateEnd(FZRec);
49516dce513Schristos inherited Destroy;
49616dce513Schristos end;
49716dce513Schristos
Readnull49816dce513Schristos function TDecompressionStream.Read(var Buffer; Count: Longint): Longint;
49916dce513Schristos begin
50016dce513Schristos FZRec.next_out := @Buffer;
50116dce513Schristos FZRec.avail_out := Count;
50216dce513Schristos if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
50316dce513Schristos while (FZRec.avail_out > 0) do
50416dce513Schristos begin
50516dce513Schristos if FZRec.avail_in = 0 then
50616dce513Schristos begin
50716dce513Schristos FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer));
50816dce513Schristos if FZRec.avail_in = 0 then
50916dce513Schristos begin
51016dce513Schristos Result := Count - FZRec.avail_out;
51116dce513Schristos Exit;
51216dce513Schristos end;
51316dce513Schristos FZRec.next_in := FBuffer;
51416dce513Schristos FStrmPos := FStrm.Position;
51516dce513Schristos Progress(Self);
51616dce513Schristos end;
51716dce513Schristos CCheck(inflate(FZRec, 0));
51816dce513Schristos end;
51916dce513Schristos Result := Count;
52016dce513Schristos end;
52116dce513Schristos
Writenull52216dce513Schristos function TDecompressionStream.Write(const Buffer; Count: Longint): Longint;
52316dce513Schristos begin
52416dce513Schristos raise EDecompressionError.CreateRes(@sInvalidStreamOp);
52516dce513Schristos end;
52616dce513Schristos
Seeknull52716dce513Schristos function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
52816dce513Schristos var
52916dce513Schristos I: Integer;
53016dce513Schristos Buf: array [0..4095] of Char;
53116dce513Schristos begin
53216dce513Schristos if (Offset = 0) and (Origin = soFromBeginning) then
53316dce513Schristos begin
53416dce513Schristos DCheck(inflateReset(FZRec));
53516dce513Schristos FZRec.next_in := FBuffer;
53616dce513Schristos FZRec.avail_in := 0;
53716dce513Schristos FStrm.Position := 0;
53816dce513Schristos FStrmPos := 0;
53916dce513Schristos end
54016dce513Schristos else if ( (Offset >= 0) and (Origin = soFromCurrent)) or
54116dce513Schristos ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then
54216dce513Schristos begin
54316dce513Schristos if Origin = soFromBeginning then Dec(Offset, FZRec.total_out);
54416dce513Schristos if Offset > 0 then
54516dce513Schristos begin
54616dce513Schristos for I := 1 to Offset div sizeof(Buf) do
54716dce513Schristos ReadBuffer(Buf, sizeof(Buf));
54816dce513Schristos ReadBuffer(Buf, Offset mod sizeof(Buf));
54916dce513Schristos end;
55016dce513Schristos end
55116dce513Schristos else
55216dce513Schristos raise EDecompressionError.CreateRes(@sInvalidStreamOp);
55316dce513Schristos Result := FZRec.total_out;
55416dce513Schristos end;
55516dce513Schristos
55616dce513Schristos
55716dce513Schristos end.
558