annotate src/zlib-1.2.7/contrib/delphi/ZLib.pas @ 4:e13257ea84a4

Add bzip2, zlib, liblo, portaudio sources
author Chris Cannam
date Wed, 20 Mar 2013 13:59:52 +0000
parents
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.