unit Arc;

interface

uses
  windows, messages, sysutils, classes, bZip2;

const
  ARC_EXTENSION = '.dat';

procedure DoCompress(const ASource, ADest: TFileName);
procedure DoCompressStream(ASource, ADest: TStream);
procedure DoUncompress(const ASource, ADest: TFileName);
procedure DoUncompressStream(ASource, ADest: TStream);
function ArchiveExists(filename: string): boolean;

implementation

var
  FSource: TStream;

function ArchiveExists(filename: string): boolean;
var
  f: File;
begin
  ArchiveExists := true;
  AssignFile(f, filename + ARC_EXTENSION);

  {$I-}
    Reset(f);
  {$I+}

  if IOResult = 0 then
    CloseFile(f)
  else
    ArchiveExists := false;
end;

procedure DoCompress(const ASource, ADest: TFileName);
var
  Source, Dest: TStream;
begin
  Source := TFileStream.Create(ASource, fmOpenRead + fmShareDenyWrite);
  try
    Dest := TFileStream.Create(ADest, fmCreate);
    try
      DoCompressStream(Source, Dest);
    finally
      Dest.Free;
    end;
  finally
    Source.Free;
  end;
end;

procedure DoCompressStream(ASource, ADest: TStream);
var
  Comp: TBZCompressionStream;
begin
  FSource := ASource;
  Comp := TBZCompressionStream.Create(bs9, ADest);
  try
    Comp.CopyFrom(ASource, 0);
  finally
    Comp.Free;
    FSource := nil;
  end;
end;

procedure DoUncompress(const ASource, ADest: TFileName);
var
  Source, Dest: TStream;
begin
  Source := TFileStream.Create(ASource, fmOpenRead + fmShareDenyWrite);
  try
    Dest := TFileStream.Create(ADest, fmCreate);
    try
      DoUncompressStream(Source, Dest);
    finally
      Dest.Free;
    end;
  finally
    Source.Free;
  end;
end;

procedure DoUncompressStream(ASource, ADest: TStream);
const
  BufferSize = 65536;
var
  Count: Integer;
  Decomp: TBZDecompressionStream;
  Buffer: array[0..BufferSize - 1] of Byte;
begin
  FSource := ASource;
  Decomp := TBZDecompressionStream.Create(ASource);
  try
    while True do
    begin
      Count := Decomp.Read(Buffer, BufferSize);
      if Count <> 0 then ADest.WriteBuffer(Buffer, Count) else Break;
    end;
  finally
    Decomp.Free;
    FSource := nil;
  end;
end;

end.
