xref: /netbsd-src/external/gpl3/gdb.old/dist/zlib/contrib/delphi/ZLib.pas (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
14e00368fSchristos {*******************************************************}
24e00368fSchristos {                                                       }
34e00368fSchristos {       Borland Delphi Supplemental Components          }
44e00368fSchristos {       ZLIB Data Compression Interface Unit            }
54e00368fSchristos {                                                       }
64e00368fSchristos {       Copyright (c) 1997,99 Borland Corporation       }
74e00368fSchristos {                                                       }
84e00368fSchristos {*******************************************************}
94e00368fSchristos 
104e00368fSchristos { Updated for zlib 1.2.x by Cosmin Truta <cosmint@cs.ubbcluj.ro> }
114e00368fSchristos 
124e00368fSchristos unit ZLib;
134e00368fSchristos 
144e00368fSchristos interface
154e00368fSchristos 
164e00368fSchristos uses SysUtils, Classes;
174e00368fSchristos 
184e00368fSchristos type
194e00368fSchristos   TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
204e00368fSchristos   TFree = procedure (AppData, Block: Pointer); cdecl;
214e00368fSchristos 
224e00368fSchristos   // Internal structure.  Ignore.
234e00368fSchristos   TZStreamRec = packed record
244e00368fSchristos     next_in: PChar;       // next input byte
254e00368fSchristos     avail_in: Integer;    // number of bytes available at next_in
264e00368fSchristos     total_in: Longint;    // total nb of input bytes read so far
274e00368fSchristos 
284e00368fSchristos     next_out: PChar;      // next output byte should be put here
294e00368fSchristos     avail_out: Integer;   // remaining free space at next_out
304e00368fSchristos     total_out: Longint;   // total nb of bytes output so far
314e00368fSchristos 
324e00368fSchristos     msg: PChar;           // last error message, NULL if no error
334e00368fSchristos     internal: Pointer;    // not visible by applications
344e00368fSchristos 
354e00368fSchristos     zalloc: TAlloc;       // used to allocate the internal state
364e00368fSchristos     zfree: TFree;         // used to free the internal state
374e00368fSchristos     AppData: Pointer;     // private data object passed to zalloc and zfree
384e00368fSchristos 
394e00368fSchristos     data_type: Integer;   // best guess about the data type: ascii or binary
404e00368fSchristos     adler: Longint;       // adler32 value of the uncompressed data
414e00368fSchristos     reserved: Longint;    // reserved for future use
424e00368fSchristos   end;
434e00368fSchristos 
444e00368fSchristos   // Abstract ancestor class
454e00368fSchristos   TCustomZlibStream = class(TStream)
464e00368fSchristos   private
474e00368fSchristos     FStrm: TStream;
484e00368fSchristos     FStrmPos: Integer;
494e00368fSchristos     FOnProgress: TNotifyEvent;
504e00368fSchristos     FZRec: TZStreamRec;
514e00368fSchristos     FBuffer: array [Word] of Char;
524e00368fSchristos   protected
534e00368fSchristos     procedure Progress(Sender: TObject); dynamic;
544e00368fSchristos     property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
554e00368fSchristos     constructor Create(Strm: TStream);
564e00368fSchristos   end;
574e00368fSchristos 
584e00368fSchristos { TCompressionStream compresses data on the fly as data is written to it, and
594e00368fSchristos   stores the compressed data to another stream.
604e00368fSchristos 
614e00368fSchristos   TCompressionStream is write-only and strictly sequential. Reading from the
624e00368fSchristos   stream will raise an exception. Using Seek to move the stream pointer
634e00368fSchristos   will raise an exception.
644e00368fSchristos 
654e00368fSchristos   Output data is cached internally, written to the output stream only when
664e00368fSchristos   the internal output buffer is full.  All pending output data is flushed
674e00368fSchristos   when the stream is destroyed.
684e00368fSchristos 
694e00368fSchristos   The Position property returns the number of uncompressed bytes of
704e00368fSchristos   data that have been written to the stream so far.
714e00368fSchristos 
724e00368fSchristos   CompressionRate returns the on-the-fly percentage by which the original
734e00368fSchristos   data has been compressed:  (1 - (CompressedBytes / UncompressedBytes)) * 100
744e00368fSchristos   If raw data size = 100 and compressed data size = 25, the CompressionRate
754e00368fSchristos   is 75%
764e00368fSchristos 
774e00368fSchristos   The OnProgress event is called each time the output buffer is filled and
784e00368fSchristos   written to the output stream.  This is useful for updating a progress
794e00368fSchristos   indicator when you are writing a large chunk of data to the compression
804e00368fSchristos   stream in a single call.}
814e00368fSchristos 
824e00368fSchristos 
834e00368fSchristos   TCompressionLevel = (clNone, clFastest, clDefault, clMax);
844e00368fSchristos 
854e00368fSchristos   TCompressionStream = class(TCustomZlibStream)
864e00368fSchristos   private
874e00368fSchristos     function GetCompressionRate: Single;
884e00368fSchristos   public
894e00368fSchristos     constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
904e00368fSchristos     destructor Destroy; override;
914e00368fSchristos     function Read(var Buffer; Count: Longint): Longint; override;
924e00368fSchristos     function Write(const Buffer; Count: Longint): Longint; override;
934e00368fSchristos     function Seek(Offset: Longint; Origin: Word): Longint; override;
944e00368fSchristos     property CompressionRate: Single read GetCompressionRate;
954e00368fSchristos     property OnProgress;
964e00368fSchristos   end;
974e00368fSchristos 
984e00368fSchristos { TDecompressionStream decompresses data on the fly as data is read from it.
994e00368fSchristos 
1004e00368fSchristos   Compressed data comes from a separate source stream.  TDecompressionStream
1014e00368fSchristos   is read-only and unidirectional; you can seek forward in the stream, but not
1024e00368fSchristos   backwards.  The special case of setting the stream position to zero is
1034e00368fSchristos   allowed.  Seeking forward decompresses data until the requested position in
1044e00368fSchristos   the uncompressed data has been reached.  Seeking backwards, seeking relative
1054e00368fSchristos   to the end of the stream, requesting the size of the stream, and writing to
1064e00368fSchristos   the stream will raise an exception.
1074e00368fSchristos 
1084e00368fSchristos   The Position property returns the number of bytes of uncompressed data that
1094e00368fSchristos   have been read from the stream so far.
1104e00368fSchristos 
1114e00368fSchristos   The OnProgress event is called each time the internal input buffer of
1124e00368fSchristos   compressed data is exhausted and the next block is read from the input stream.
1134e00368fSchristos   This is useful for updating a progress indicator when you are reading a
1144e00368fSchristos   large chunk of data from the decompression stream in a single call.}
1154e00368fSchristos 
1164e00368fSchristos   TDecompressionStream = class(TCustomZlibStream)
1174e00368fSchristos   public
1184e00368fSchristos     constructor Create(Source: TStream);
1194e00368fSchristos     destructor Destroy; override;
1204e00368fSchristos     function Read(var Buffer; Count: Longint): Longint; override;
1214e00368fSchristos     function Write(const Buffer; Count: Longint): Longint; override;
1224e00368fSchristos     function Seek(Offset: Longint; Origin: Word): Longint; override;
1234e00368fSchristos     property OnProgress;
1244e00368fSchristos   end;
1254e00368fSchristos 
1264e00368fSchristos 
1274e00368fSchristos 
1284e00368fSchristos { CompressBuf compresses data, buffer to buffer, in one call.
1294e00368fSchristos    In: InBuf = ptr to compressed data
1304e00368fSchristos        InBytes = number of bytes in InBuf
1314e00368fSchristos   Out: OutBuf = ptr to newly allocated buffer containing decompressed data
1324e00368fSchristos        OutBytes = number of bytes in OutBuf   }
1334e00368fSchristos procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
1344e00368fSchristos                       out OutBuf: Pointer; out OutBytes: Integer);
1354e00368fSchristos 
1364e00368fSchristos 
1374e00368fSchristos { DecompressBuf decompresses data, buffer to buffer, in one call.
1384e00368fSchristos    In: InBuf = ptr to compressed data
1394e00368fSchristos        InBytes = number of bytes in InBuf
1404e00368fSchristos        OutEstimate = zero, or est. size of the decompressed data
1414e00368fSchristos   Out: OutBuf = ptr to newly allocated buffer containing decompressed data
1424e00368fSchristos        OutBytes = number of bytes in OutBuf   }
1434e00368fSchristos procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
1444e00368fSchristos  OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
1454e00368fSchristos 
1464e00368fSchristos { DecompressToUserBuf decompresses data, buffer to buffer, in one call.
1474e00368fSchristos    In: InBuf = ptr to compressed data
1484e00368fSchristos        InBytes = number of bytes in InBuf
1494e00368fSchristos   Out: OutBuf = ptr to user-allocated buffer to contain decompressed data
1504e00368fSchristos        BufSize = number of bytes in OutBuf   }
1514e00368fSchristos procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
1524e00368fSchristos   const OutBuf: Pointer; BufSize: Integer);
1534e00368fSchristos 
1544e00368fSchristos const
155*6881a400Schristos   zlib_version = '1.2.12';
1564e00368fSchristos 
1574e00368fSchristos type
1584e00368fSchristos   EZlibError = class(Exception);
1594e00368fSchristos   ECompressionError = class(EZlibError);
1604e00368fSchristos   EDecompressionError = class(EZlibError);
1614e00368fSchristos 
1624e00368fSchristos implementation
1634e00368fSchristos 
1644e00368fSchristos uses ZLibConst;
1654e00368fSchristos 
1664e00368fSchristos const
1674e00368fSchristos   Z_NO_FLUSH      = 0;
1684e00368fSchristos   Z_PARTIAL_FLUSH = 1;
1694e00368fSchristos   Z_SYNC_FLUSH    = 2;
1704e00368fSchristos   Z_FULL_FLUSH    = 3;
1714e00368fSchristos   Z_FINISH        = 4;
1724e00368fSchristos 
1734e00368fSchristos   Z_OK            = 0;
1744e00368fSchristos   Z_STREAM_END    = 1;
1754e00368fSchristos   Z_NEED_DICT     = 2;
1764e00368fSchristos   Z_ERRNO         = (-1);
1774e00368fSchristos   Z_STREAM_ERROR  = (-2);
1784e00368fSchristos   Z_DATA_ERROR    = (-3);
1794e00368fSchristos   Z_MEM_ERROR     = (-4);
1804e00368fSchristos   Z_BUF_ERROR     = (-5);
1814e00368fSchristos   Z_VERSION_ERROR = (-6);
1824e00368fSchristos 
1834e00368fSchristos   Z_NO_COMPRESSION       =   0;
1844e00368fSchristos   Z_BEST_SPEED           =   1;
1854e00368fSchristos   Z_BEST_COMPRESSION     =   9;
1864e00368fSchristos   Z_DEFAULT_COMPRESSION  = (-1);
1874e00368fSchristos 
1884e00368fSchristos   Z_FILTERED            = 1;
1894e00368fSchristos   Z_HUFFMAN_ONLY        = 2;
1904e00368fSchristos   Z_RLE                 = 3;
1914e00368fSchristos   Z_DEFAULT_STRATEGY    = 0;
1924e00368fSchristos 
1934e00368fSchristos   Z_BINARY   = 0;
1944e00368fSchristos   Z_ASCII    = 1;
1954e00368fSchristos   Z_UNKNOWN  = 2;
1964e00368fSchristos 
1974e00368fSchristos   Z_DEFLATED = 8;
1984e00368fSchristos 
1994e00368fSchristos 
2004e00368fSchristos {$L adler32.obj}
2014e00368fSchristos {$L compress.obj}
2024e00368fSchristos {$L crc32.obj}
2034e00368fSchristos {$L deflate.obj}
2044e00368fSchristos {$L infback.obj}
2054e00368fSchristos {$L inffast.obj}
2064e00368fSchristos {$L inflate.obj}
2074e00368fSchristos {$L inftrees.obj}
2084e00368fSchristos {$L trees.obj}
2094e00368fSchristos {$L uncompr.obj}
2104e00368fSchristos {$L zutil.obj}
2114e00368fSchristos 
2124e00368fSchristos procedure adler32; external;
2134e00368fSchristos procedure compressBound; external;
2144e00368fSchristos procedure crc32; external;
2154e00368fSchristos procedure deflateInit2_; external;
2164e00368fSchristos procedure deflateParams; external;
2174e00368fSchristos 
2184e00368fSchristos function _malloc(Size: Integer): Pointer; cdecl;
2194e00368fSchristos begin
2204e00368fSchristos   Result := AllocMem(Size);
2214e00368fSchristos end;
2224e00368fSchristos 
2234e00368fSchristos procedure _free(Block: Pointer); cdecl;
2244e00368fSchristos begin
2254e00368fSchristos   FreeMem(Block);
2264e00368fSchristos end;
2274e00368fSchristos 
2284e00368fSchristos procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl;
2294e00368fSchristos begin
2304e00368fSchristos   FillChar(P^, count, B);
2314e00368fSchristos end;
2324e00368fSchristos 
2334e00368fSchristos procedure _memcpy(dest, source: Pointer; count: Integer); cdecl;
2344e00368fSchristos begin
2354e00368fSchristos   Move(source^, dest^, count);
2364e00368fSchristos end;
2374e00368fSchristos 
2384e00368fSchristos 
2394e00368fSchristos 
2404e00368fSchristos // deflate compresses data
2414e00368fSchristos function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar;
2424e00368fSchristos   recsize: Integer): Integer; external;
2434e00368fSchristos function deflate(var strm: TZStreamRec; flush: Integer): Integer; external;
2444e00368fSchristos function deflateEnd(var strm: TZStreamRec): Integer; external;
2454e00368fSchristos 
2464e00368fSchristos // inflate decompresses data
2474e00368fSchristos function inflateInit_(var strm: TZStreamRec; version: PChar;
2484e00368fSchristos   recsize: Integer): Integer; external;
2494e00368fSchristos function inflate(var strm: TZStreamRec; flush: Integer): Integer; external;
2504e00368fSchristos function inflateEnd(var strm: TZStreamRec): Integer; external;
2514e00368fSchristos function inflateReset(var strm: TZStreamRec): Integer; external;
2524e00368fSchristos 
2534e00368fSchristos 
2544e00368fSchristos function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl;
2554e00368fSchristos begin
2564e00368fSchristos //  GetMem(Result, Items*Size);
2574e00368fSchristos   Result := AllocMem(Items * Size);
2584e00368fSchristos end;
2594e00368fSchristos 
2604e00368fSchristos procedure zlibFreeMem(AppData, Block: Pointer); cdecl;
2614e00368fSchristos begin
2624e00368fSchristos   FreeMem(Block);
2634e00368fSchristos end;
2644e00368fSchristos 
2654e00368fSchristos {function zlibCheck(code: Integer): Integer;
2664e00368fSchristos begin
2674e00368fSchristos   Result := code;
2684e00368fSchristos   if code < 0 then
2694e00368fSchristos     raise EZlibError.Create('error');    //!!
2704e00368fSchristos end;}
2714e00368fSchristos 
2724e00368fSchristos function CCheck(code: Integer): Integer;
2734e00368fSchristos begin
2744e00368fSchristos   Result := code;
2754e00368fSchristos   if code < 0 then
2764e00368fSchristos     raise ECompressionError.Create('error'); //!!
2774e00368fSchristos end;
2784e00368fSchristos 
2794e00368fSchristos function DCheck(code: Integer): Integer;
2804e00368fSchristos begin
2814e00368fSchristos   Result := code;
2824e00368fSchristos   if code < 0 then
2834e00368fSchristos     raise EDecompressionError.Create('error');  //!!
2844e00368fSchristos end;
2854e00368fSchristos 
2864e00368fSchristos procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
2874e00368fSchristos                       out OutBuf: Pointer; out OutBytes: Integer);
2884e00368fSchristos var
2894e00368fSchristos   strm: TZStreamRec;
2904e00368fSchristos   P: Pointer;
2914e00368fSchristos begin
2924e00368fSchristos   FillChar(strm, sizeof(strm), 0);
2934e00368fSchristos   strm.zalloc := zlibAllocMem;
2944e00368fSchristos   strm.zfree := zlibFreeMem;
2954e00368fSchristos   OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
2964e00368fSchristos   GetMem(OutBuf, OutBytes);
2974e00368fSchristos   try
2984e00368fSchristos     strm.next_in := InBuf;
2994e00368fSchristos     strm.avail_in := InBytes;
3004e00368fSchristos     strm.next_out := OutBuf;
3014e00368fSchristos     strm.avail_out := OutBytes;
3024e00368fSchristos     CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm)));
3034e00368fSchristos     try
3044e00368fSchristos       while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
3054e00368fSchristos       begin
3064e00368fSchristos         P := OutBuf;
3074e00368fSchristos         Inc(OutBytes, 256);
3084e00368fSchristos         ReallocMem(OutBuf, OutBytes);
3094e00368fSchristos         strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
3104e00368fSchristos         strm.avail_out := 256;
3114e00368fSchristos       end;
3124e00368fSchristos     finally
3134e00368fSchristos       CCheck(deflateEnd(strm));
3144e00368fSchristos     end;
3154e00368fSchristos     ReallocMem(OutBuf, strm.total_out);
3164e00368fSchristos     OutBytes := strm.total_out;
3174e00368fSchristos   except
3184e00368fSchristos     FreeMem(OutBuf);
3194e00368fSchristos     raise
3204e00368fSchristos   end;
3214e00368fSchristos end;
3224e00368fSchristos 
3234e00368fSchristos 
3244e00368fSchristos procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
3254e00368fSchristos   OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
3264e00368fSchristos var
3274e00368fSchristos   strm: TZStreamRec;
3284e00368fSchristos   P: Pointer;
3294e00368fSchristos   BufInc: Integer;
3304e00368fSchristos begin
3314e00368fSchristos   FillChar(strm, sizeof(strm), 0);
3324e00368fSchristos   strm.zalloc := zlibAllocMem;
3334e00368fSchristos   strm.zfree := zlibFreeMem;
3344e00368fSchristos   BufInc := (InBytes + 255) and not 255;
3354e00368fSchristos   if OutEstimate = 0 then
3364e00368fSchristos     OutBytes := BufInc
3374e00368fSchristos   else
3384e00368fSchristos     OutBytes := OutEstimate;
3394e00368fSchristos   GetMem(OutBuf, OutBytes);
3404e00368fSchristos   try
3414e00368fSchristos     strm.next_in := InBuf;
3424e00368fSchristos     strm.avail_in := InBytes;
3434e00368fSchristos     strm.next_out := OutBuf;
3444e00368fSchristos     strm.avail_out := OutBytes;
3454e00368fSchristos     DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
3464e00368fSchristos     try
3474e00368fSchristos       while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do
3484e00368fSchristos       begin
3494e00368fSchristos         P := OutBuf;
3504e00368fSchristos         Inc(OutBytes, BufInc);
3514e00368fSchristos         ReallocMem(OutBuf, OutBytes);
3524e00368fSchristos         strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
3534e00368fSchristos         strm.avail_out := BufInc;
3544e00368fSchristos       end;
3554e00368fSchristos     finally
3564e00368fSchristos       DCheck(inflateEnd(strm));
3574e00368fSchristos     end;
3584e00368fSchristos     ReallocMem(OutBuf, strm.total_out);
3594e00368fSchristos     OutBytes := strm.total_out;
3604e00368fSchristos   except
3614e00368fSchristos     FreeMem(OutBuf);
3624e00368fSchristos     raise
3634e00368fSchristos   end;
3644e00368fSchristos end;
3654e00368fSchristos 
3664e00368fSchristos procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer;
3674e00368fSchristos   const OutBuf: Pointer; BufSize: Integer);
3684e00368fSchristos var
3694e00368fSchristos   strm: TZStreamRec;
3704e00368fSchristos begin
3714e00368fSchristos   FillChar(strm, sizeof(strm), 0);
3724e00368fSchristos   strm.zalloc := zlibAllocMem;
3734e00368fSchristos   strm.zfree := zlibFreeMem;
3744e00368fSchristos   strm.next_in := InBuf;
3754e00368fSchristos   strm.avail_in := InBytes;
3764e00368fSchristos   strm.next_out := OutBuf;
3774e00368fSchristos   strm.avail_out := BufSize;
3784e00368fSchristos   DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
3794e00368fSchristos   try
3804e00368fSchristos     if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then
3814e00368fSchristos       raise EZlibError.CreateRes(@sTargetBufferTooSmall);
3824e00368fSchristos   finally
3834e00368fSchristos     DCheck(inflateEnd(strm));
3844e00368fSchristos   end;
3854e00368fSchristos end;
3864e00368fSchristos 
3874e00368fSchristos // TCustomZlibStream
3884e00368fSchristos 
3894e00368fSchristos constructor TCustomZLibStream.Create(Strm: TStream);
3904e00368fSchristos begin
3914e00368fSchristos   inherited Create;
3924e00368fSchristos   FStrm := Strm;
3934e00368fSchristos   FStrmPos := Strm.Position;
3944e00368fSchristos   FZRec.zalloc := zlibAllocMem;
3954e00368fSchristos   FZRec.zfree := zlibFreeMem;
3964e00368fSchristos end;
3974e00368fSchristos 
3984e00368fSchristos procedure TCustomZLibStream.Progress(Sender: TObject);
3994e00368fSchristos begin
4004e00368fSchristos   if Assigned(FOnProgress) then FOnProgress(Sender);
4014e00368fSchristos end;
4024e00368fSchristos 
4034e00368fSchristos 
4044e00368fSchristos // TCompressionStream
4054e00368fSchristos 
4064e00368fSchristos constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
4074e00368fSchristos   Dest: TStream);
4084e00368fSchristos const
4094e00368fSchristos   Levels: array [TCompressionLevel] of ShortInt =
4104e00368fSchristos     (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
4114e00368fSchristos begin
4124e00368fSchristos   inherited Create(Dest);
4134e00368fSchristos   FZRec.next_out := FBuffer;
4144e00368fSchristos   FZRec.avail_out := sizeof(FBuffer);
4154e00368fSchristos   CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec)));
4164e00368fSchristos end;
4174e00368fSchristos 
4184e00368fSchristos destructor TCompressionStream.Destroy;
4194e00368fSchristos begin
4204e00368fSchristos   FZRec.next_in := nil;
4214e00368fSchristos   FZRec.avail_in := 0;
4224e00368fSchristos   try
4234e00368fSchristos     if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
4244e00368fSchristos     while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
4254e00368fSchristos       and (FZRec.avail_out = 0) do
4264e00368fSchristos     begin
4274e00368fSchristos       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
4284e00368fSchristos       FZRec.next_out := FBuffer;
4294e00368fSchristos       FZRec.avail_out := sizeof(FBuffer);
4304e00368fSchristos     end;
4314e00368fSchristos     if FZRec.avail_out < sizeof(FBuffer) then
4324e00368fSchristos       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
4334e00368fSchristos   finally
4344e00368fSchristos     deflateEnd(FZRec);
4354e00368fSchristos   end;
4364e00368fSchristos   inherited Destroy;
4374e00368fSchristos end;
4384e00368fSchristos 
4394e00368fSchristos function TCompressionStream.Read(var Buffer; Count: Longint): Longint;
4404e00368fSchristos begin
4414e00368fSchristos   raise ECompressionError.CreateRes(@sInvalidStreamOp);
4424e00368fSchristos end;
4434e00368fSchristos 
4444e00368fSchristos function TCompressionStream.Write(const Buffer; Count: Longint): Longint;
4454e00368fSchristos begin
4464e00368fSchristos   FZRec.next_in := @Buffer;
4474e00368fSchristos   FZRec.avail_in := Count;
4484e00368fSchristos   if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
4494e00368fSchristos   while (FZRec.avail_in > 0) do
4504e00368fSchristos   begin
4514e00368fSchristos     CCheck(deflate(FZRec, 0));
4524e00368fSchristos     if FZRec.avail_out = 0 then
4534e00368fSchristos     begin
4544e00368fSchristos       FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
4554e00368fSchristos       FZRec.next_out := FBuffer;
4564e00368fSchristos       FZRec.avail_out := sizeof(FBuffer);
4574e00368fSchristos       FStrmPos := FStrm.Position;
4584e00368fSchristos       Progress(Self);
4594e00368fSchristos     end;
4604e00368fSchristos   end;
4614e00368fSchristos   Result := Count;
4624e00368fSchristos end;
4634e00368fSchristos 
4644e00368fSchristos function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
4654e00368fSchristos begin
4664e00368fSchristos   if (Offset = 0) and (Origin = soFromCurrent) then
4674e00368fSchristos     Result := FZRec.total_in
4684e00368fSchristos   else
4694e00368fSchristos     raise ECompressionError.CreateRes(@sInvalidStreamOp);
4704e00368fSchristos end;
4714e00368fSchristos 
4724e00368fSchristos function TCompressionStream.GetCompressionRate: Single;
4734e00368fSchristos begin
4744e00368fSchristos   if FZRec.total_in = 0 then
4754e00368fSchristos     Result := 0
4764e00368fSchristos   else
4774e00368fSchristos     Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0;
4784e00368fSchristos end;
4794e00368fSchristos 
4804e00368fSchristos 
4814e00368fSchristos // TDecompressionStream
4824e00368fSchristos 
4834e00368fSchristos constructor TDecompressionStream.Create(Source: TStream);
4844e00368fSchristos begin
4854e00368fSchristos   inherited Create(Source);
4864e00368fSchristos   FZRec.next_in := FBuffer;
4874e00368fSchristos   FZRec.avail_in := 0;
4884e00368fSchristos   DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec)));
4894e00368fSchristos end;
4904e00368fSchristos 
4914e00368fSchristos destructor TDecompressionStream.Destroy;
4924e00368fSchristos begin
4934e00368fSchristos   FStrm.Seek(-FZRec.avail_in, 1);
4944e00368fSchristos   inflateEnd(FZRec);
4954e00368fSchristos   inherited Destroy;
4964e00368fSchristos end;
4974e00368fSchristos 
4984e00368fSchristos function TDecompressionStream.Read(var Buffer; Count: Longint): Longint;
4994e00368fSchristos begin
5004e00368fSchristos   FZRec.next_out := @Buffer;
5014e00368fSchristos   FZRec.avail_out := Count;
5024e00368fSchristos   if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
5034e00368fSchristos   while (FZRec.avail_out > 0) do
5044e00368fSchristos   begin
5054e00368fSchristos     if FZRec.avail_in = 0 then
5064e00368fSchristos     begin
5074e00368fSchristos       FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer));
5084e00368fSchristos       if FZRec.avail_in = 0 then
5094e00368fSchristos       begin
5104e00368fSchristos         Result := Count - FZRec.avail_out;
5114e00368fSchristos         Exit;
5124e00368fSchristos       end;
5134e00368fSchristos       FZRec.next_in := FBuffer;
5144e00368fSchristos       FStrmPos := FStrm.Position;
5154e00368fSchristos       Progress(Self);
5164e00368fSchristos     end;
5174e00368fSchristos     CCheck(inflate(FZRec, 0));
5184e00368fSchristos   end;
5194e00368fSchristos   Result := Count;
5204e00368fSchristos end;
5214e00368fSchristos 
5224e00368fSchristos function TDecompressionStream.Write(const Buffer; Count: Longint): Longint;
5234e00368fSchristos begin
5244e00368fSchristos   raise EDecompressionError.CreateRes(@sInvalidStreamOp);
5254e00368fSchristos end;
5264e00368fSchristos 
5274e00368fSchristos function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
5284e00368fSchristos var
5294e00368fSchristos   I: Integer;
5304e00368fSchristos   Buf: array [0..4095] of Char;
5314e00368fSchristos begin
5324e00368fSchristos   if (Offset = 0) and (Origin = soFromBeginning) then
5334e00368fSchristos   begin
5344e00368fSchristos     DCheck(inflateReset(FZRec));
5354e00368fSchristos     FZRec.next_in := FBuffer;
5364e00368fSchristos     FZRec.avail_in := 0;
5374e00368fSchristos     FStrm.Position := 0;
5384e00368fSchristos     FStrmPos := 0;
5394e00368fSchristos   end
5404e00368fSchristos   else if ( (Offset >= 0) and (Origin = soFromCurrent)) or
5414e00368fSchristos           ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then
5424e00368fSchristos   begin
5434e00368fSchristos     if Origin = soFromBeginning then Dec(Offset, FZRec.total_out);
5444e00368fSchristos     if Offset > 0 then
5454e00368fSchristos     begin
5464e00368fSchristos       for I := 1 to Offset div sizeof(Buf) do
5474e00368fSchristos         ReadBuffer(Buf, sizeof(Buf));
5484e00368fSchristos       ReadBuffer(Buf, Offset mod sizeof(Buf));
5494e00368fSchristos     end;
5504e00368fSchristos   end
5514e00368fSchristos   else
5524e00368fSchristos     raise EDecompressionError.CreateRes(@sInvalidStreamOp);
5534e00368fSchristos   Result := FZRec.total_out;
5544e00368fSchristos end;
5554e00368fSchristos 
5564e00368fSchristos 
5574e00368fSchristos end.
558