unit Sparkle.ZLib;

interface

uses
  System.SysUtils, System.Classes, System.ZLib;

type
  ByteArray = TBytes;

  TSparkleZLib = class
  strict private
//    Deflater: TZCompressionStream;
//    FAdler: UInt32;
//    const BASE = $FFF1;  //extract addler sum and header.
//
//
//    const Header: Array[0..1] of Byte = ($78, $9C);
//    class function Adler32(const adler: UInt32; const buf: ByteArray; const first: Int32; len: Int32): UInt32; static;
//    class procedure WriteAdler32(const InputData: ByteArray; const Offset: Int32; const OutStream: TStream); overload; static;
//    class procedure WriteAdler32(const OutStream: TStream; const adl: UInt32); overload; static;
//
  public
//    constructor Create;
//    destructor Destroy; override;
//    procedure Deflate(const InputData: ByteArray; const Offset: Int32; const OutStream: TStream);
    procedure Inflate(const InputData: ByteArray; const Offset: Int32; const OutStream: TStream);
//    procedure BeginDeflate;
//    procedure IncDeflate(const Data: ByteArray; const Offset: Int32; const OutStream: TStream); overload;
//    procedure IncDeflate(const InData: ByteArray; const Offset: Int32; const Length: Int32; const OutStream: TStream); overload;
//    procedure EndDeflate(const OutStream: TStream);
  end;

implementation

{ TSparkleZLib }

function ZDecompressCheck(code: Integer): Integer;
begin
  Result := code;

  if code < 0 then
    raise EZDecompressionError.Create(string(_z_errmsg[2 - code]));
end;

procedure TSparkleZLib.Inflate(const InputData: ByteArray; const Offset: Int32;
  const OutStream: TStream);
var
  FZStream: TZStreamRec;
  OutBuffer: ByteArray;
  zResult: Integer;
  Written: Cardinal;
begin
  FillChar(FZStream, SizeOf(TZStreamRec), 0);
  SetLength(OutBuffer, 4192);
  FZStream.next_in := @(InputData[Offset + 2]);
  FZStream.avail_in := ((Length(InputData) - Offset) - 2) - 4;
  FZStream.next_out := @(OutBuffer[0]);
  FZStream.avail_out := Length(OutBuffer);
  ZDecompressCheck(InflateInit2(FZStream, -15));

  zResult := 0; Written := 0;
  while zResult <> Z_STREAM_END do
  begin
    zResult := ZDecompressCheck(System.ZLib.inflate(FZStream, Z_NO_FLUSH));
    OutStream.Write(OutBuffer[0], FZStream.total_out - Written);
    Written := FZStream.total_out;
    FZStream.next_out := @(OutBuffer[0]);
    FZStream.avail_out := Length(OutBuffer);
  end;

  ZDecompressCheck(inflateEnd(FZStream));
  OutStream.Write(OutBuffer[0], FZStream.total_out - Written);
end;

end.