Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
500 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi



Loremo - the 1.5 liter car coming in 2009




Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (7)


Calculating CRCs EffectivelyFormat this article printer-friendly!Bookmark function is only available for registered users!
Parameterized CRC Algorithm Component
Product:
Delphi 5.x (or higher)
Category:
Algorithm
Skill Level:
Scoring:
Last Update:
05/09/2001
Search Keys:
delphi delphi3000 article borland vcl code-snippet CRC Algorithm Component Bit-Operations
Times Scored:
4
Visits:
1831
Uploader: Jesse Slicer
Company:
Reference: intervocative.com
 
Question/Problem/Abstract:
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





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
great stuff, butt...
    Martin Glob (May 10 2001 6:22PM)

hi

Nice work you've done - but frankly I must admit that the way you comment your source was a bit frustrating... I KNOW that all programmers has their favorite way of commenting source code. I just guess that I'm used to comments that explains some "not so evident" source code - and not stuff like

procedure MyProc;
begin //MyProc
  DoMyOtherProc;
end //MyProc

Isn't this overdoing it?
Respond

RE: great stuff, butt...
Martin Glob (May 10 2001 6:23PM)

ouch! who put a repeat on my t in but? :-)
Respond

RE: RE: great stuff, butt...
Jesse Slicer (May 10 2001 9:21PM)

Force of habit since at my day job we frequently work with nested functions and procedures that can be over a viewable page long. It may be a bit anal, but I figure stick with one style for all code rather than say don't comment functions with no branching or are less than x lines.
Respond

Explantation
    Peter Morris (May 10 2001 8:47AM)

Could you include an explanation of how CRC works, why one is better than another etc ?

This would have proven to be an interesting article if it were not just a source-code listing.
Respond

RE: Explantation
Jesse Slicer (May 10 2001 9:32AM)

You do have a good point.  I'll simply say that a CRC is one of the most foolproof ways to ensure data integrity from Point A to Point B with the least amount of additional overhead.

That being said, I have sought out a couple of GREAT sources on the web with regards to how CRCs work and where and why you'd want to use them:

http://www.io.com/~ritter/ARTS/CRCMYST.HTM
http://www.efg2.com/Lab/Mathematics/CRC.htm (lots of links here)

and my favorite, which I actually generated the code from:

http://www.microconsultants.com/tips/crc/crc.txt

Respond

RE: Explantation
testercho testis (Apr 20 2005 4:58PM)

This not work at Delphi 7 :(
Respond

RE: RE: Explantation
Jesse Slicer (Apr 20 2005 5:41PM)

Quite true. The article was written in early 2001 when Delphi 5 was the latest version we were using. Because the unit includes DsgnIntf, it becomes incompatible in a design- and run-time package. In late 2001, we removed the reference to DsgnIntf and the TLongHexEditor class, functions and registration and it should be fine after that. Feel free to shoot me an email at jslicer at spamcop dot net if you want an electronic copy of the latest
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
C.A. Longen
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)