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