unit uZipTools;

///2013年5月27日 15:26:37
///  加入对XE支持

///2013年5月27日 09:35:03
///  加入对流的压缩函数

interface

uses
  ZLib, Windows, Classes, SysUtils;

{$if CompilerVersion>= 21}
  {$define NEWZLib}
{$IFEND}

type
//2007以上直接=TBytes
{$if CompilerVersion< 18.5}
  TMyBytes = array of Byte;
{$IFEND}

  TZipTools = class(TObject)
  public
    //压缩字符串(与JAVA兼容)
    class function compressStr(pvData: string): TBytes;

    //解压字符串(与JAVA兼容)
    class function unCompressStr(pvData: TBytes; pvDataSize: Integer = 0): string;

    //压缩(与JAVA兼容)
    class procedure compressStreamEX(const pvStream:TStream);

    //解压(与JAVA兼容)
    class procedure unCompressStreamEX(const pvStream:TStream);

    //压缩(与JAVA兼容)
    class function compressStream(const pvStream, pvZipStream:TStream): Boolean;

    //解压(与JAVA兼容)
    class function unCompressStream(const pvZipStream, pvStream:TStream): Boolean;


    //压缩(与JAVA兼容)
    class function compressBuf(const Buffer; Count: Longint): TBytes;

    //解压(与JAVA兼容)
    class function unCompressBuf(const zipBuffer; Count: Longint): TBytes;

    class function verifyData(const buf; len:Cardinal):Cardinal;

    class function verifyStream(pvStream:TStream; len:Cardinal): Cardinal;
  end;

implementation

class function TZipTools.compressBuf(const Buffer; Count: Longint): TBytes;
var
  OutBuf: Pointer;
  OutBytes: Integer;
begin
  {$if defined(NEWZLib)}
    ZLib.ZCompress(@Buffer, Count, OutBuf, OutBytes);
  {$ELSE}
    ZLib.CompressBuf(@Buffer, Count, OutBuf, OutBytes);
  {$ifend}
    try
      SetLength(Result, OutBytes);
      CopyMemory(@Result[0], OutBuf, OutBytes);
    finally
      FreeMem(OutBuf, OutBytes);
    end;
end;

class function TZipTools.unCompressBuf(const zipBuffer; Count: Longint): TBytes;
var
  lvSize:Cardinal;
  OutBuf: Pointer;
  OutBytes: Integer;
begin
  lvSize := Count;
  {$if defined(NEWZLib)}
    Zlib.ZDecompress(@zipBuffer, lvSize, OutBuf, OutBytes);
  {$ELSE}
    Zlib.DecompressBuf(@zipBuffer, lvSize, 0, OutBuf, OutBytes);
  {$ifend}
    try
      SetLength(Result, OutBytes);
      CopyMemory(@Result[0], OutBuf, OutBytes);
    finally
      FreeMem(OutBuf, OutBytes);
    end;

end;

class function TZipTools.compressStr(pvData: string): TBytes;
begin
  result := compressBuf(PAnsiChar(AnsiString(pvData))^, Length(AnsiString(pvData)));
end;

class procedure TZipTools.compressStreamEX(const pvStream:TStream);
begin
  compressStream(pvStream, pvStream);
end;


class function TZipTools.compressStream(const pvStream, pvZipStream:TStream):
    Boolean;
var
  lvBytes: TBytes;
  OutBuf: Pointer;
  OutBytes: Integer;
  l: Integer;
begin
  Result := False;
  if pvStream= nil then exit;

  l := pvStream.Size;

  if l = 0 then Exit;

  setLength(lvBytes, l);
  pvStream.Position := 0;
  pvStream.ReadBuffer(lvBytes[0], l);

  {$if defined(NEWZLib)}
    ZLib.ZCompress(@lvBytes[0], l, OutBuf, OutBytes);
  {$ELSE}
    ZLib.CompressBuf(@lvBytes[0], l, OutBuf, OutBytes);
  {$ifend}
    try
      pvZipStream.Size := OutBytes;
      pvZipStream.Position := 0;
      pvZipStream.WriteBuffer(OutBuf^, OutBytes);
      Result := true;
    finally
      FreeMem(OutBuf, OutBytes);
    end;

end;

class procedure TZipTools.unCompressStreamEX(const pvStream:TStream);
begin
  unCompressStream(pvStream, pvStream)
end;



class function TZipTools.verifyData(const buf; len: Cardinal): Cardinal;
var
  i:Cardinal;
  p:PByte;
begin
  i := 0;
  Result := 0;
  p := PByte(@buf);
  while i < len do
  begin
    Result := Result + p^;
    Inc(p);
    Inc(i);
  end;
end;

class function TZipTools.unCompressStream(const pvZipStream, pvStream:TStream):
    Boolean;
var
  l:Integer;
  lvBytes: TBytes;
  OutBuf: Pointer;
  OutBytes: Integer;

begin
  Result := false;
  if pvZipStream= nil then exit;
  l := pvZipStream.Size;
  if l = 0 then Exit;

  setLength(lvBytes, l);
  pvZipStream.Position := 0;
  pvZipStream.ReadBuffer(lvBytes[0], l);

  {$if defined(NEWZLib)}
    ZLib.ZDecompress(@lvBytes[0], l, OutBuf, OutBytes);
  {$ELSE}
    Zlib.DecompressBuf(@lvBytes[0], l, 0, OutBuf, OutBytes);
  {$ifend}
    try
      pvStream.Size := OutBytes;
      pvStream.Position := 0;
      pvStream.WriteBuffer(OutBuf^, OutBytes);
      Result := true;
    finally
      FreeMem(OutBuf, OutBytes);
    end;

end;

class function TZipTools.unCompressStr(pvData: TBytes; pvDataSize: Integer =
    0): string;
var
  lvSize:Cardinal;
  lvOutBytes:TBytes;

  s:AnsiString;
begin
  lvSize := pvDataSize;
  if lvSize = 0 then lvSize := Length(AnsiString(pvData));

  lvOutBytes := self.unCompressBuf(pvData[0], lvSize);
  SetLength(s, Length(lvOutBytes));
  CopyMemory(@s[1], @lvOutBytes[0], Length(lvOutBytes));
  Result := s;

end;

class function TZipTools.verifyStream(pvStream:TStream; len:Cardinal): Cardinal;
var
  l, j:Cardinal;
  lvBytes:TBytes;
begin
  SetLength(lvBytes, 1024);

  if len = 0 then
  begin
    j := pvStream.Size - pvStream.Position;
  end else
  begin
    j := len;
  end;

  Result := 0;

  while j > 0 do
  begin
    if j <1024 then l := j else l := 1024;
    
    pvStream.ReadBuffer(lvBytes[0], l);

    Result := verifyData(lvBytes[0], l);
    Dec(j, l);
  end;
end;


end.
