annotate src/zlib-1.2.7/contrib/delphi/ZLib.pas @ 83:ae30d91d2ffe

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