xref: /netbsd-src/external/gpl3/binutils.old/dist/zlib/contrib/delphi/ZLib.pas (revision e992f068c547fd6e84b3f104dc2340adcc955732)
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