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