Mega Code Archive

 
Categories / Delphi / Algorithm Math
 

Calculating CRCs Effectively

Title: Calculating CRCs Effectively Question: Ever want to use a CRC? Should you use CRC-16, CRC-32 or any one of the other variants out there? Well this handy component will do just about any CRC you can dream up (up to 32 bits wide) and has presets for some of the more popular CRC schemes. Simply drop this on your form and set the properties accordingly. Answer: Drop this on a form, then repeatedly call Update(nextbyte) until your input stream is complete, then access the CRC property for a CRC of the input bytes. unit CCRC; interface uses Classes, SysUtils, DsgnIntf; type TCRCScheme = (crcX25, crcXMODEM, crcARC, crcCRC32, crcPKZIP, crcCustom); TLongHex = LongWord; ECRCException = class(Exception); ECRCBadScheme = class(ECRCException); TLongHexEditor = class(TIntegerProperty) procedure Edit; override; function GetAttributes: TPropertyAttributes; override; function GetValue: string; override; procedure SetValue(const sValue: string); override; end; //class TLongHexEditor TCRC = class(TComponent) private //Private declarations FScheme : TCRCScheme; FWidth : Integer; FReflectInput, FReflectCRC : Boolean; FCRC, FInitialValue, FPolynomial, FXorToCRC : TLongHex; protected //Protected declarations procedure SetScheme(crcNewScheme: TCRCScheme); procedure SetCRCParameters(iNewWidth : Integer; lNewPolynomial, lNewInitialValue: TLongHex; bNewReflectInput, bNewReflectCRC : Boolean; lNewXorToCRC : TLongHex); procedure SetWidth(iNewWidth: Integer); procedure SetPolynomial(lNewPolynomial: TLongHex); procedure SetInitialValue(lNewInitialValue: TLongHex); procedure SetReflectInput(bNewReflectInput: Boolean); procedure SetReflectCRC(bNewReflectCRC: Boolean); procedure SetXorToCRC(lNewXorToCRC: TLongHex); function Reflect(lValue : TLongHex; iBottomBitsToReflect: Integer): TLongHex; function Bitmask(iBits: Integer): TLongHex; function MaskOfWidth: TLongHex; function GetCRC: TLongHex; public //Public declarations constructor Create(AOwner: TComponent); override; procedure Initialize; procedure Update(byNewCharacter: Byte); property CRC : TLongHex read GetCRC; published //Published declarations property Scheme : TCRCScheme read FScheme write SetScheme default crcCRC32; property Width : Integer read FWidth write SetWidth default 32; property Polynomial : TLongHex read FPolynomial write SetPolynomial default $04C11DB7; property InitialValue: TLongHex read FInitialValue write SetInitialValue default $FFFFFFFF; property ReflectInput: Boolean read FReflectInput write SetReflectInput default True; property ReflectCRC : Boolean read FReflectCRC write SetReflectCRC default True; property XorToCRC : TLongHex read FXorToCRC write SetXorToCRC default $FFFFFFFF; end; //class TCRC procedure Register; procedure CustomRegister(const sFolderName: string); implementation {$IFDEF VER100} resourcestring {$ELSE} const {$ENDIF} rsCRCBadScheme = 'Invalid CRC scheme type specified.'; const BITSINABYTE = 8; var sCustomFolderName: string = 'InterVocative Software'; //------------------------------------------------------------------------------ procedure TLongHexEditor.Edit; var ThisComponent: TPersistent; begin //procedure TLongHexEditor.Edit ThisComponent := GetComponent(Pred(PropCount)); if ThisComponent is TCRC then begin //if..then //do it here end; //if..then end; //procedure TLongHexEditor.Edit //------------------------------------------------------------------------------ function TLongHexEditor.GetAttributes: TPropertyAttributes; begin //function TLongHexEditor.GetAttributes Result := inherited GetAttributes + [paRevertable]; end; //function TLongHexEditor.GetAttributes //------------------------------------------------------------------------------ function TLongHexEditor.GetValue: string; begin //function TLongHexEditor.GetValue Result := inherited GetValue; end; //function TLongHexEditor.GetValue //------------------------------------------------------------------------------ procedure TLongHexEditor.SetValue(const sValue: string); begin //procedure TLongHexEditor.SetValue inherited SetValue(sValue); end; //procedure TLongHexEditor.SetValue //------------------------------------------------------------------------------ constructor TCRC.Create(AOwner: TComponent); begin //constructor TCRC.Create inherited Create(AOwner); Scheme := crcCRC32; Initialize; end; //constructor TCRC.Create //------------------------------------------------------------------------------ procedure TCRC.SetScheme(crcNewScheme: TCRCScheme); begin //procedure TCRC.SetScheme if crcNewScheme Scheme then begin //if..then case crcNewScheme of crcX25 : SetCRCParameters(16, $1021, $FFFF, False, False, $0000); crcXMODEM: SetCRCParameters(16, $8408, $0000, True, True, $0000); crcARC : SetCRCParameters(16, $8005, $0000, True, True, $0000); crcCRC32 : SetCRCParameters(32, $04C11DB7, $FFFFFFFF, True, True, $FFFFFFFF); crcPKZIP : SetCRCParameters(32, $EDB88320, $FFFFFFFF, True, True, $FFFFFFFF); crcCustom: ; //deliberate non-statement else raise ECRCBadScheme.Create(rsCRCBadScheme); end; //case FScheme := crcNewScheme; end; //if..then end; //procedure TCRC.SetScheme //------------------------------------------------------------------------------ procedure TCRC.SetCRCParameters(iNewWidth : Integer; lNewPolynomial, lNewInitialValue: TLongHex; bNewReflectInput, bNewReflectCRC : Boolean; lNewXorToCRC : TLongHex); begin //procedure TCRC.SetCRCParameters Width := iNewWidth; Polynomial := lNewPolynomial; InitialValue := lNewInitialValue; ReflectInput := bNewReflectInput; ReflectCRC := bNewReflectCRC; XorToCRC := lNewXorToCRC; end; //procedure TCRC.SetCRCParameters //------------------------------------------------------------------------------ procedure TCRC.SetWidth(iNewWidth: Integer); begin //procedure TCRC.SetWidth if iNewWidth Width then begin //if..then FWidth := iNewWidth; Scheme := crcCustom; end; //if..then end; //procedure TCRC.SetWidth //------------------------------------------------------------------------------ procedure TCRC.SetPolynomial(lNewPolynomial: TLongHex); begin //procedure TCRC.SetPolynomial if lNewPolynomial Polynomial then begin //if..then FPolynomial := lNewPolynomial; Scheme := crcCustom; end; //if..then end; //procedure TCRC.SetPolynomial //------------------------------------------------------------------------------ procedure TCRC.SetInitialValue(lNewInitialValue: TLongHex); begin //procedure TCRC.SetInitialValue if lNewInitialValue InitialValue then begin //if..then FInitialValue := lNewInitialValue; Scheme := crcCustom; end; //if..then end; //procedure TCRC.SetInitialValue //------------------------------------------------------------------------------ procedure TCRC.SetReflectInput(bNewReflectInput: Boolean); begin //procedure TCRC.SetReflectInput} if bNewReflectInput ReflectInput then begin //if..then FReflectInput := bNewReflectInput; Scheme := crcCustom; end; //if..then end; //procedure TCRC.SetReflectInput //------------------------------------------------------------------------------ procedure TCRC.SetReflectCRC(bNewReflectCRC: Boolean); begin //procedure TCRC.SetReflectCRC if bNewReflectCRC ReflectCRC then begin //if..then FReflectCRC := bNewReflectCRC; Scheme := crcCustom; end; //if..then end; //procedure TCRC.SetReflectCRC //------------------------------------------------------------------------------ procedure TCRC.SetXorToCRC(lNewXorToCRC: TLongHex); begin //procedure TCRC.SetXorToCRC if lNewXorToCRC XorToCRC then begin //if..then FXorToCRC := lNewXorToCRC; Scheme := crcCustom; end; //if..then end; //procedure TCRC.SetXorToCRC //------------------------------------------------------------------------------ function TCRC.Reflect(lValue : TLongHex; iBottomBitsToReflect: Integer): TLongHex; var iLoop : Integer; lTempValue, lOrValue: TLongHex; begin //function TCRC.Reflect lTempValue := lValue; for iLoop := 0 to Pred(iBottomBitsToReflect) do begin //for lOrValue := Bitmask(Pred(iBottomBitsToReflect) - iLoop); if lTempValue and 1 0 then lValue := lValue or lOrValue else lValue := lValue and not lOrValue; lTempValue := lTempValue shr 1; end; //for Result := lValue; end; //function TCRC.Reflect //------------------------------------------------------------------------------ function TCRC.Bitmask(iBits: Integer): TLongHex; begin //function TCRC.Bitmask Result := 1 shl iBits; end; //function TCRC.Bitmask //------------------------------------------------------------------------------ function TCRC.MaskOfWidth: TLongHex; var lhResult: TLongHex; begin //function TCRC.MaskOfWidth lhResult := 1 shl Pred(Width); Result := (Pred(lhResult) shl 1) or 1; end; //function TCRC.MaskOfWidth //------------------------------------------------------------------------------ function TCRC.GetCRC: TLongHex; begin //function TCRC.GetCRC if ReflectCRC then Result := XorToCRC xor Reflect(FCRC, Width) else Result := XorToCRC xor FCRC; end; //function TCRC.GetCRC //------------------------------------------------------------------------------ procedure TCRC.Initialize; begin //procedure TCRC.Initialize FCRC := InitialValue; end; //procedure TCRC.Initialize //------------------------------------------------------------------------------ procedure TCRC.Update(byNewCharacter: Byte); var iLoop : Integer; lNewLong, lTopBit : TLongHex; begin //procedure TCRC.Update lNewLong := byNewCharacter; lTopBit := Bitmask(Pred(Width)); if ReflectInput then lNewLong := Reflect(lNewLong, BITSINABYTE); FCRC := FCRC xor (lNewLong shl (Width - BITSINABYTE)); for iLoop := 1 to BITSINABYTE do begin //for if FCRC and lTopBit 0 then FCRC := (FCRC shl 1) xor Polynomial else FCRC := FCRC shl 1; FCRC := FCRC and MaskOfWidth; end; //for end; //procedure TCRC.Update //------------------------------------------------------------------------------ procedure Register; begin //procedure Register RegisterPropertyEditor(TypeInfo(TLongHex), nil, '', TLongHexEditor); RegisterComponents(sCustomFolderName, [TCRC]); end; //procedure Register //------------------------------------------------------------------------------ procedure CustomRegister(const sFolderName: string); begin //procedure CustomRegister if Trim(sFolderName) '' then sCustomFolderName := sFolderName; Register; end; //procedure CustomRegister //------------------------------------------------------------------------------ end. //unit CCRC