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