Browse Source

+ Initial implementation

michael 26 years ago
parent
commit
d9e8ae68aa
2 changed files with 595 additions and 0 deletions
  1. 207 0
      fcl/inc/zlib.pp
  2. 388 0
      fcl/inc/zstream.pp

+ 207 - 0
fcl/inc/zlib.pp

@@ -0,0 +1,207 @@
+unit zlib;
+
+interface
+  
+{ Needed for array of const }
+{$mode objfpc}
+{$PACKRECORDS 4}
+
+const
+  SZLIB_VERSION = '1.1.3';
+
+type
+
+  { Compatibility types }
+  Uint = cardinal;
+  Ulong = Cardinal;
+  Ulongf = Cardinal;
+  Pulongf = ^Ulongf;
+  z_off_t = longint;  
+
+  TAllocfunc = function (opaque:pointer; items:uInt; size:uInt):pointer;cdecl;
+  TFreeFunc = procedure (opaque:pointer; address:pointer);cdecl;
+
+  TInternalState = record
+    end;
+  PInternalState = ^TInternalstate;
+  
+  TZStream = record
+    next_in : pchar;
+    avail_in : uInt;
+    total_in : uLong;
+    next_out : pchar;
+    avail_out : uInt;
+    total_out : uLong;
+    msg : pchar;
+    state : PInternalState;
+    zalloc : TAllocFunc;
+    zfree : TFreeFunc;
+    opaque : pointer;
+    data_type : longint;
+    adler : uLong;
+    reserved : uLong;
+  end;
+  PZstream = ^TZStream;
+  gzFile = pointer;
+
+
+const
+  Z_NO_FLUSH = 0;
+
+  Z_PARTIAL_FLUSH = 1;
+  Z_SYNC_FLUSH = 2;
+  Z_FULL_FLUSH = 3;
+  Z_FINISH = 4;
+
+  Z_OK = 0;
+  Z_STREAM_END = 1;
+  Z_NEED_DICT = 2;
+  Z_ERRNO = -(1);
+  Z_STREAM_ERROR = -(2);
+  Z_DATA_ERROR = -(3);
+  Z_MEM_ERROR = -(4);
+  Z_BUF_ERROR = -(5);
+  Z_VERSION_ERROR = -(6);
+
+  Z_NO_COMPRESSION = 0;
+  Z_BEST_SPEED = 1;
+  Z_BEST_COMPRESSION = 9;
+  Z_DEFAULT_COMPRESSION = -(1);
+
+  Z_FILTERED = 1;
+  Z_HUFFMAN_ONLY = 2;
+  Z_DEFAULT_STRATEGY = 0;
+
+  Z_BINARY = 0;
+  Z_ASCII = 1;
+  Z_UNKNOWN = 2;
+
+  Z_DEFLATED = 8;
+
+  Z_NULL = 0;
+
+  function zlibVersion:pchar;cdecl;
+  function deflate(var strm:TZstream; flush:longint):longint;cdecl;
+  function deflateEnd(var strm:TZstream):longint;cdecl;
+  function inflate(var strm:TZstream; flush:longint):longint;cdecl;
+  function inflateEnd(var strm:TZstream):longint;cdecl;
+  function deflateSetDictionary(var strm:TZstream;dictionary : pchar; dictLength:uInt):longint;cdecl;
+  function deflateCopy(var dest,source:TZstream):longint;cdecl;
+  function deflateReset(var strm:TZstream):longint;cdecl;
+  function deflateParams(var strm:TZstream; level:longint; strategy:longint):longint;cdecl;
+  function inflateSetDictionary(var strm:TZStream;dictionary : pchar; dictLength:uInt):longint;cdecl;
+  function inflateSync(var strm:TZStream):longint;cdecl;
+  function inflateReset(var strm:TZStream):longint;cdecl;
+  function compress(dest:pchar;destLen:uLongf; source : pchar; sourceLen:uLong):longint;cdecl;
+  function compress2(dest:pchar;destLen:uLongf; source : pchar; sourceLen:uLong; level:longint):longint;cdecl;
+  function uncompress(dest:pchar;destLen:uLongf; source : pchar; sourceLen:uLong):longint;cdecl;
+  function gzopen(path:pchar; mode:pchar):gzFile;cdecl;
+  function gzdopen(fd:longint; mode:pchar):gzFile;cdecl;
+  function gzsetparams(Thefile:gzFile; level:longint; strategy:longint):longint;cdecl;
+  function gzread(thefile:gzFile; buf : pointer; len:cardinal):longint;cdecl;
+  function gzwrite(thefile:gzFile; buf: pointer; len:cardinal):longint;cdecl;
+  function gzprintf(thefile:gzFile; format:pchar; args:array of const):longint;cdecl;
+  function gzputs(thefile:gzFile; s:pchar):longint;cdecl;
+  function gzgets(thefile:gzFile; buf:pchar; len:longint):pchar;cdecl;
+  function gzputc(thefile:gzFile; c:longint):longint;cdecl;
+  function gzgetc(thefile:gzFile):longint;cdecl;
+  function gzflush(thefile:gzFile; flush:longint):longint;cdecl;
+  function gzseek(thefile:gzFile; offset:z_off_t; whence:longint):z_off_t;cdecl;
+  function gzrewind(thefile:gzFile):longint;cdecl;
+  function gztell(thefile:gzFile):z_off_t;cdecl;
+  function gzeof(thefile:gzFile):longint;cdecl;
+  function gzclose(thefile:gzFile):longint;cdecl;
+  function gzerror(thefile:gzFile; var errnum:longint):pchar;cdecl;
+  function adler32(adler:uLong;buf : pchar; len:uInt):uLong;cdecl;
+  function crc32(crc:uLong;buf : pchar; len:uInt):uLong;cdecl;
+  function deflateInit_(var strm:TZStream; level:longint; version:pchar; stream_size:longint):longint;cdecl;
+  function inflateInit_(var strm:TZStream; version:pchar; stream_size:longint):longint;cdecl;
+  function deflateInit2_(var strm:TZStream; level:longint; method:longint; windowBits:longint; memLevel:longint; 
+             strategy:longint; version:pchar; stream_size:longint):longint;cdecl;
+  function inflateInit2_(var strm:TZStream; windowBits:longint; version:pchar; stream_size:longint):longint;cdecl;
+  function deflateInit(var strm:TZStream;level : longint) : longint;
+  function inflateInit(var strm:TZStream) : longint;
+  function deflateInit2(var strm:TZStream;level,method,windowBits,memLevel,strategy : longint) : longint;
+  function inflateInit2(var strm:TZStream; windowBits : longint) : longint;
+  function zError(err:longint):pchar;cdecl;
+  function inflateSyncPoint(z:PZstream):longint;cdecl;
+  function get_crc_table:puLongf;cdecl;
+
+implementation
+
+{$ifndef win32}
+const External_library='z';
+{$else}
+const External_library='z';
+{$endif}
+
+
+function zlibVersion:pchar;cdecl;external External_library name 'zlibVersion';
+function deflate(var strm:TZStream; flush:longint):longint;cdecl;external External_library name 'deflate';
+function deflateEnd(var strm:TZStream):longint;cdecl;external External_library name 'deflateEnd';
+function inflate(var strm:TZStream; flush:longint):longint;cdecl;external External_library name 'inflate';
+function inflateEnd(var strm:TZStream):longint;cdecl;external External_library name 'inflateEnd';
+function deflateSetDictionary(var strm:TZStream;dictionary : pchar; dictLength:uInt):longint;cdecl;external External_library name 'deflateSetDictionary';
+function deflateCopy(var dest,source:TZstream):longint;cdecl;external External_library name 'deflateCopy';
+function deflateReset(var strm:TZStream):longint;cdecl;external External_library name 'deflateReset';
+function deflateParams(var strm:TZStream; level:longint; strategy:longint):longint;cdecl;external External_library name 'deflateParams';
+function inflateSetDictionary(var strm:TZStream;dictionary : pchar; dictLength:uInt):longint;cdecl;external External_library name 'inflateSetDictionary';
+function inflateSync(var strm:TZStream):longint;cdecl;external External_library name 'inflateSync';
+function inflateReset(var strm:TZStream):longint;cdecl;external External_library name 'inflateReset';
+function compress(dest:pchar;destLen:uLongf; source : pchar; sourceLen:uLong):longint;cdecl;external External_library name 'compress';
+function compress2(dest:pchar;destLen:uLongf; source : pchar; sourceLen:uLong; level:longint):longint;cdecl;external External_library name 'compress2';
+function uncompress(dest:pchar;destLen:uLongf; source : pchar; sourceLen:uLong):longint;cdecl;external External_library name 'uncompress';
+function gzopen(path:pchar; mode:pchar):gzFile;cdecl;external External_library name 'gzopen';
+function gzdopen(fd:longint; mode:pchar):gzFile;cdecl;external External_library name 'gzdopen';
+function gzsetparams(thefile:gzFile; level:longint; strategy:longint):longint;cdecl;external External_library name 'gzsetparams';
+function gzread(thefile:gzFile; buf:pointer; len:cardinal):longint;cdecl;external External_library name 'gzread';
+function gzwrite(thefile:gzFile; buf:pointer; len:cardinal):longint;cdecl;external External_library name 'gzwrite';
+function gzprintf(thefile:gzFile; format:pchar; args:array of const):longint;cdecl;external External_library name 'gzprintf';
+function gzputs(thefile:gzFile; s:pchar):longint;cdecl;external External_library name 'gzputs';
+function gzgets(thefile:gzFile; buf:pchar; len:longint):pchar;cdecl;external External_library name 'gzgets';
+function gzputc(thefile:gzFile; c:longint):longint;cdecl;external External_library name 'gzputc';
+function gzgetc(thefile:gzFile):longint;cdecl;external External_library name 'gzgetc';
+function gzflush(thefile:gzFile; flush:longint):longint;cdecl;external External_library name 'gzflush';
+function gzseek(thefile:gzFile; offset:z_off_t; whence:longint):z_off_t;cdecl;external External_library name 'gzseek';
+function gzrewind(thefile:gzFile):longint;cdecl;external External_library name 'gzrewind';
+function gztell(thefile:gzFile):z_off_t;cdecl;external External_library name 'gztell';
+function gzeof(thefile:gzFile):longint;cdecl;external External_library name 'gzeof';
+function gzclose(thefile:gzFile):longint;cdecl;external External_library name 'gzclose';
+function gzerror(thefile:gzFile; var errnum:longint):pchar;cdecl;external External_library name 'gzerror';
+function adler32(adler:uLong;buf : pchar; len:uInt):uLong;cdecl;external External_library name 'adler32';
+function crc32(crc:uLong;buf : pchar; len:uInt):uLong;cdecl;external External_library name 'crc32';
+function deflateInit_(var strm:TZStream; level:longint; version:pchar; stream_size:longint):longint;cdecl;external External_library name 'deflateInit_';
+function inflateInit_(var strm:TZStream; version:pchar; stream_size:longint):longint;cdecl;external External_library name 'inflateInit_';
+function deflateInit2_(var strm:TZStream; level:longint; method:longint; windowBits:longint; memLevel:longint; 
+           strategy:longint; version:pchar; stream_size:longint):longint;cdecl;external External_library name 'deflateInit2_';
+function inflateInit2_(var strm:TZStream; windowBits:longint; version:pchar; stream_size:longint):longint;cdecl;external External_library name 'inflateInit2_';
+function zError(err:longint):pchar;cdecl;external External_library name 'zError';
+function inflateSyncPoint(z:PZstream):longint;cdecl;external External_library name 'inflateSyncPoint';
+function get_crc_table:puLongf;cdecl;external External_library name 'get_crc_table';
+
+function zlib_version : pchar;
+  begin
+     zlib_version:=zlibVersion;
+  end;
+
+function deflateInit(var strm:TZStream;level : longint) : longint;
+  begin
+     deflateInit:=deflateInit_(strm,level,ZLIB_VERSION,sizeof(TZStream));
+  end;
+
+function inflateInit(var strm:TZStream) : longint;
+  begin
+     inflateInit:=inflateInit_(strm,ZLIB_VERSION,sizeof(TZStream));
+  end;
+
+function deflateInit2(var strm:TZStream;level,method,windowBits,memLevel,strategy : longint) : longint;
+  begin
+     deflateInit2:=deflateInit2_(strm,level,method,windowBits,memLevel,strategy,ZLIB_VERSION,sizeof(TZStream));
+  end;
+
+function inflateInit2(var strm:TZStream;windowBits : longint) : longint;
+  begin
+     inflateInit2:=inflateInit2_(strm,windowBits,ZLIB_VERSION,sizeof(TZStream));
+  end;
+
+end.

+ 388 - 0
fcl/inc/zstream.pp

@@ -0,0 +1,388 @@
+unit zstream;
+
+interface
+
+uses Sysutils, Classes,zlib;
+
+type
+  // Error reporting.
+
+  EZlibError = class(Exception);
+  ECompressionError = class(EZlibError);
+  EDecompressionError = class(EZlibError);
+
+  TCustomZlibStream = class(TStream)
+  private
+    FStrm: TStream;
+    FStrmPos: Integer;
+    FOnProgress: TNotifyEvent;
+    FZRec: TZStream;
+    FBuffer: array [Word] of Char;
+  protected
+    procedure Progress(Sender: TObject); dynamic;
+    property OnProgress: TNotifyEvent read FOnProgress write FOnProgress;
+    constructor Create(Strm: TStream);
+  end;
+
+  TCompressionLevel = (clNone, clFastest, clDefault, clMax);
+
+  TCompressionStream = class(TCustomZlibStream)
+  private
+    function GetCompressionRate: extended;
+  public
+    constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream);
+    destructor Destroy; override;
+    function CompressionCheck(code: Integer): Integer;
+    procedure CompressBuf(const InBuf: Pointer; InBytes: Integer;
+                          var OutBuf: Pointer; var OutBytes: Integer);
+    function Read(var Buffer; Count: Longint): Longint; override;
+    function Write(const Buffer; Count: Longint): Longint; override;
+    function Seek(Offset: Longint; Origin: Word): Longint; override;
+    property CompressionRate: extended read GetCompressionRate;
+    property OnProgress;
+  end;
+
+  TDecompressionStream = class(TCustomZlibStream)
+  public
+    constructor Create(Source: TStream);
+    destructor Destroy; override;
+    function DecompressionCheck(code: Integer): Integer;
+    procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
+    OutEstimate: Integer; var OutBuf: Pointer; var OutBytes: Integer);
+    function Read(var Buffer; Count: Longint): Longint; override;
+    function Write(const Buffer; Count: Longint): Longint; override;
+    function Seek(Offset: Longint; Origin: Word): Longint; override;
+    property OnProgress;
+  end;
+
+
+implementation
+
+Const 
+  ErrorStrings : array [0..6] of string = 
+    ('Unknown error %d','Z_ERRNO','Z_STREAM_ERROR',
+     'Z_DATA_ERROR','Z_MEM_ERROR','Z_BUF_ERROR','Z_VERSION_ERROR');
+
+Type PLongint = ^Longint;
+
+Function DGetmem (Size : Longint) : pointer;
+begin
+  Inc(Size,SizeOf(Longint));
+  GetMem(Result,Size);
+  If Result<>Nil then 
+    begin
+    Plongint(Result)^:=Size;
+    Inc(Result,SizeOf(Integer));
+    end;
+end;
+
+Procedure DFreeMem(P : Pointer);
+begin
+  // Get Stored length
+  Dec(P,SizeOf(Integer));
+  FreeMem(P,Plongint(P)^);
+end;
+
+Procedure DReallocMem (var P : Pointer; NewSize : Longint);
+  // Reallocates memory pointed to by P.
+Var T : pointer;
+    OldSize : longint;
+begin
+  // Should raise an exception if no memory.
+  T:=DGetMem(NewSize);
+  OldSize:=PLongint(P-SizeOf(Integer))^;
+  If oldSize<NewSize then
+    Move(P^,T^,OldSize)
+  else
+    Move(P^,T^,NewSize);
+  DFreeMem(P);
+end;
+
+function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer;cdecl;
+begin
+  Result:=DGetMem(Items*Size);
+end;
+
+procedure zlibFreeMem(AppData, Block: Pointer);cdecl;
+begin
+  DFreeMem(Block);
+end;
+
+
+procedure TCompressionStream.CompressBuf(const InBuf: Pointer; InBytes: Integer;
+                      var OutBuf: Pointer; var OutBytes: Integer);
+var
+  strm: TZStream;
+  P: Pointer;
+  oldout : longint;
+begin
+  FillChar(strm, sizeof(strm), 0);
+  strm.zalloc := @zlibAllocMem;
+  strm.zfree := @zlibFreeMem;
+  OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255;
+  OutBuf:=DGetMem(OutBytes);
+  try
+    strm.next_in := InBuf;
+    strm.avail_in := InBytes;
+    strm.next_out := OutBuf;
+    strm.avail_out := OutBytes;
+    CompressionCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlibversion, sizeof(strm)));
+    try
+      while CompressionCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do
+      begin
+        P := OutBuf;
+        Inc(OutBytes, 256);
+        DReallocMem(OutBuf,OutBytes);
+        strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
+        strm.avail_out := 256;
+      end;
+    finally
+      CompressionCheck(deflateEnd(strm));
+    end;
+    DReallocMem(OutBuf,strm.total_out);
+    OutBytes := strm.total_out;
+  except
+    DFreeMem(OutBuf);
+    raise;
+  end;
+end;
+
+
+procedure TDecompressionStream.DecompressBuf(const InBuf: Pointer; InBytes: Integer;
+       OutEstimate: Integer; var OutBuf: Pointer; var OutBytes: Integer);
+var
+  strm: TZStream;
+  P: Pointer;
+  BufInc: Integer;
+begin
+  FillChar(strm, sizeof(strm), 0);
+  strm.zalloc := @zlibAllocMem;
+  strm.zfree := @zlibFreeMem;
+  BufInc := (InBytes + 255) and not 255;
+  if OutEstimate = 0 then
+    OutBytes := BufInc
+  else
+    OutBytes := OutEstimate;
+  OutBuf:=DGetMem(OutBytes);
+  try
+    strm.next_in := InBuf;
+    strm.avail_in := InBytes;
+    strm.next_out := OutBuf;
+    strm.avail_out := OutBytes;
+    DecompressionCheck(inflateInit_(strm, zlibversion, sizeof(strm)));
+    try
+      while DecompressionCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END do
+      begin
+        P := OutBuf;
+        Inc(OutBytes, BufInc);
+        DReallocMem(OutBuf, OutBytes);
+        strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
+        strm.avail_out := BufInc;
+      end;
+    finally
+      DecompressionCheck(inflateEnd(strm));
+    end;
+    DReallocMem(OutBuf, strm.total_out);
+    OutBytes := strm.total_out;
+  except
+    DFreeMem(OutBuf);
+    raise;
+  end;
+end;
+
+
+// TCustomZlibStream
+
+constructor TCustomZLibStream.Create(Strm: TStream);
+begin
+  inherited Create;
+  FStrm := Strm;
+  FStrmPos := Strm.Position;
+  FZRec.zalloc := @zlibAllocMem;
+  FZRec.zfree := @zlibFreeMem;
+end;
+
+procedure TCustomZLibStream.Progress(Sender: TObject);
+begin
+  if Assigned(FOnProgress) then FOnProgress(Sender);
+end;
+
+
+// TCompressionStream
+
+constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel;
+  Dest: TStream);
+const
+  Levels: array [TCompressionLevel] of ShortInt =
+    (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION);
+begin
+  inherited Create(Dest);
+  FZRec.next_out := FBuffer;
+  FZRec.avail_out := sizeof(FBuffer);
+  CompressionCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlibversion, sizeof(FZRec)));
+end;
+
+destructor TCompressionStream.Destroy;
+begin
+  FZRec.next_in := nil;
+  FZRec.avail_in := 0;
+  try
+    if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
+    while (CompressionCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END)
+      and (FZRec.avail_out = 0) do
+    begin
+      FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
+      FZRec.next_out := FBuffer;
+      FZRec.avail_out := sizeof(FBuffer);
+    end;
+    if FZRec.avail_out < sizeof(FBuffer) then
+      FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out);
+  finally
+    deflateEnd(FZRec);
+  end;
+  inherited Destroy;
+end;
+
+function TCompressionStream.CompressionCheck(code: Integer): Integer;
+begin
+  Result := code;
+  if (code < 0) then
+    if code < -6 then
+      raise ECompressionError.CreateFmt(Errorstrings[0],[Code])
+    else
+      raise ECompressionError.Create(ErrorStrings[Abs(Code)]);
+end;
+
+
+function TCompressionStream.Read(var Buffer; Count: Longint): Longint;
+begin
+  raise ECompressionError.Create('Invalid stream operation');
+end;
+
+function TCompressionStream.Write(const Buffer; Count: Longint): Longint;
+begin
+  FZRec.next_in := @Buffer;
+  FZRec.avail_in := Count;
+  if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
+  while (FZRec.avail_in > 0) do
+  begin
+    CompressionCheck(deflate(FZRec, 0));
+    if FZRec.avail_out = 0 then
+    begin
+      FStrm.WriteBuffer(FBuffer, sizeof(FBuffer));
+      FZRec.next_out := FBuffer;
+      FZRec.avail_out := sizeof(FBuffer);
+      FStrmPos := FStrm.Position;
+      Progress(Self);
+    end;
+  end;
+  Result := Count;
+end;
+
+function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
+begin
+  if (Offset = 0) and (Origin = soFromCurrent) then
+    Result := FZRec.total_in
+  else
+    raise ECompressionError.Create('Invalid stream operation');
+end;
+
+function TCompressionStream.GetCompressionRate: extended;
+begin
+  Result:=0.0;
+{  With FZrec do
+    if total_in = 0 then
+      GetCompressionRate:=0.0
+    else
+      GetCompressionRate:=1.0E2*(1.0E0-(total_out/total_in));
+}
+end;
+
+
+// TDecompressionStream
+
+constructor TDecompressionStream.Create(Source: TStream);
+begin
+  inherited Create(Source);
+  FZRec.next_in := FBuffer;
+  FZRec.avail_in := 0;
+  DecompressionCheck(inflateInit_(FZRec, zlibversion, sizeof(FZRec)));
+end;
+
+destructor TDecompressionStream.Destroy;
+begin
+  inflateEnd(FZRec);
+  inherited Destroy;
+end;
+
+function TDecompressionStream.DecompressionCheck(code: Integer): Integer;
+begin
+  Result := code;
+  If Code<0 then
+    if code < -6 then
+      raise EDecompressionError.CreateFmt(Errorstrings[0],[Code])
+    else
+      raise EDecompressionError.Create(ErrorStrings[Abs(Code)]);
+end;
+
+function TDecompressionStream.Read(var Buffer; Count: Longint): Longint;
+begin
+  FZRec.next_out := @Buffer;
+  FZRec.avail_out := Count;
+  if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos;
+  while (FZRec.avail_out > 0) do
+  begin
+    if FZRec.avail_in = 0 then
+    begin
+      FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer));
+      if FZRec.avail_in = 0 then
+        begin
+          Result := Count - FZRec.avail_out;
+          Exit;
+        end;
+      FZRec.next_in := FBuffer;
+      FStrmPos := FStrm.Position;
+      Progress(Self);
+    end;
+    DeCompressionCheck(inflate(FZRec, 0));
+  end;
+  Result := Count;
+end;
+
+function TDecompressionStream.Write(const Buffer; Count: Longint): Longint;
+begin
+  raise EDecompressionError.Create('Invalid stream operation');
+end;
+
+function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint;
+var
+  I: Integer;
+  Buf: array [0..4095] of Char;
+begin
+  if (Offset = 0) and (Origin = soFromBeginning) then
+  begin
+    DecompressionCheck(inflateReset(FZRec));
+    FZRec.next_in := FBuffer;
+    FZRec.avail_in := 0;
+    FStrm.Position := 0;
+    FStrmPos := 0;
+  end
+  else if ( (Offset >= 0) and (Origin = soFromCurrent)) or
+          ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then
+  begin
+    if Origin = soFromBeginning then Dec(Offset, FZRec.total_out);
+    if Offset > 0 then
+    begin
+      for I := 1 to Offset div sizeof(Buf) do
+        ReadBuffer(Buf, sizeof(Buf));
+      ReadBuffer(Buf, Offset mod sizeof(Buf));
+    end;
+  end
+  else
+    raise EDecompressionError.Create('Invalid stream operation');
+  Result := FZRec.total_out;
+end;
+
+
+
+end.