procedure CRC16Process(var CRC16: TCRC16; const Data; const Size: Cardinal); var DataPtr : PChar; Index : Integer; begin DataPtr := @Data; for Index := 0 to Size-1 do CRC16 := CRC16Table[(Ord(DataPtr[Index]) xor CRC16) and 255] xor (CRC16 shr 8); end;
procedure CRC16Done(var CRC16: TCRC16); begin // Nothing to do here end;
procedure CRC32Init(out CRC32: TCRC32); begin CRC32 := $FFFFFFFF; end;
procedure CRC32Process(var CRC32: TCRC32; const Data; const Size: Cardinal); var DataPtr : PChar; Index : Integer; begin DataPtr := @Data; for Index := 0 to Size-1 do CRC32 := ((CRC32 shr 8) and $FFFFFF) xor CRC32Table[(CRC32 xor Ord(DataPtr[Index])) and 255]; end;
procedure TCRCThread.DoBegin; begin with FOwner do if Assigned(FOnBegin) then FOnBegin(FStream.Size); end;
procedure TCRCThread.DoEnd; begin with FOwner do if Assigned(FOnEnd) and not (csDestroying in ComponentState) then begin if FMode = cm16 then FOnEnd(FValue16, not Terminated) else if FMode = cm32 then FOnEnd(FValue32, not Terminated); end; end;
procedure TCRCThread.DoProcess; begin with FOwner do if Assigned(FOnProcess) and not (csDestroying in ComponentState) then FOnProcess(FHasDone); end;
procedure TCRCThread.Execute; var nBuffer: PChar; nNeedDo: Integer; begin Synchronize(DoBegin);
with FOwner do begin if FMode = cm16 then CRC16Init(FValue16) else if FMode = cm32 then CRC32Init(FValue32);
FStream.Position := 0; GetMem(nBuffer, FBufSize);
nNeedDo := 0; FHasDone := 0; try repeat if Terminated then Break; nNeedDo := FStream.Read(nBuffer^, FBufSize);
if nNeedDo > 0 then begin if FMode = cm16 then CRC16Process(FValue16, nBuffer^, nNeedDo) else if FMode = cm32 then CRC32Process(FValue32, nBuffer^, nNeedDo);
Inc(FHasDone, nNeedDo); Synchronize(DoProcess); end; until nNeedDo = 0; finally FreeMem(nBuffer);
if FAutoFree then FStream.Free; FStream := nil;
if Terminated then FreeOnTerminate := False else FThread := nil; end;
if not Terminated then begin if FMode = cm16 then CRC16Done(FValue16) else if FMode = cm32 then CRC32Done(FValue32); end; end;
Synchronize(DoEnd); end;
{********************************* TZnCRC *************************************} constructor TZnCRC.Create(AOwner: TComponent); begin inherited Create(AOwner);
destructor TZnCRC.Destroy; begin StopCRC; inherited; end;
procedure TZnCRC.ShowMsg(const nMsg: string); begin if Assigned(FOnMsg) then FOnMsg(nMsg); end;
function TZnCRC.GetStatus: boolean; begin Result := Assigned(FThread); end;
procedure TZnCRC.SetBuffSize(const nSize: integer); begin if IsBusy then ShowMsg('提示: 操作正在进行,请稍后...') else if (nSize < 1) or (nSize > 32768) then begin if csDesigning in ComponentState then raise Exception.Create('请输入0至32768之间的数值') else ShowMsg('提示: 请输入1至32768之间的数值'); end else FBufSize := nSize; end;
procedure TZnCRC.CRC_File(const nFile: string); begin if IsBusy then ShowMsg('提示: 操作正在进行,请稍后...') else if FileExists(nFile) then begin FAutoFree := True; FStream := TFileStream.Create(nFile, fmOpenRead or fmShareDenyWrite); FThread := TCRCThread.Create(Self); end else ShowMsg('错误: 无效的文件名称'); end;
procedure TZnCRC.CRC_Stream(const nStream: TStream); begin if IsBusy then ShowMsg('提示: 操作正在进行,请稍后...') else if Assigned(nStream) then begin FAutoFree := False; FStream := nStream; FThread := TCRCThread.Create(Self); end else ShowMsg('错误: 无效的数据流'); end;
procedure TZnCRC.StopCRC; begin if IsBusy then begin FThread.Terminate; FThread.WaitFor; FreeAndNil(FThread); end; end;