A Checksum Algorithm

Checksum.h

Checksum.h

class checksum {
public:
    checksum() { clear(); }
    void clear() { sum = 0; r = 55665; c1 = 52845; c2 = 22719;}
    void add(DWORD w);
    void add(BOOL w) { add((DWORD)w); }
    void add(UINT w) { add((DWORD)w); }
    void add(WORD w);
    void add(const CString & s);
    void add(LPBYTE b, UINT length);
    void add(BYTE b);
    DWORD get() { return sum; }
protected:
    WORD r;
    WORD c1;
    WORD c2;
    DWORD sum;
};

Don't worry about those "magic constants" you see r, c1, and c2 being initialized to. They are part of the encryption algorithm, and although I'm sure there is some mystical reason they are set to the particular values shown, many other values (perhaps any other values, except possibly 0 or 1) would suffice. 

Note the use of overloading to get various data types. To use the checksum algorithm, create a variable of type checksum, for example, in your desired data structure. You can then call the various add methods to add in the values you wish to checksum (it is rarely the case that doing a checksum of the bytes of the structure yields anything useful; for example, some might represent transient computations that do not affect the actual values of importance; and checksumming the bytes would mean that you checksum the pointers to strings, not the contents of the strings, which leads to the situation where two strings that are otherwise identical would produce different checksums because they were at different addresses. So at some point you determine the structure contains all the values you care about (for example, just after you've read the document, or initialized all the values in OnInitDialog), and you apply the following operations to your checksum variable (which I'll call original). It is convenient to package up the checksum algorithm as shown.

void CMyClass::doChecksum(checksum & chk)
   {
    chk.clear();
    chk.add(flag); // a BOOL
    chk.add(text); // a CString
    chk.add(size); // a DWORD
   }

so you call it as

    doChecksum(original);

Now, at some point, you determine that you have changed something; for example, the user has clicked a checkbox. You capture the Boolean value of the checkbox to the flag variable, then call doChecksum with a new variable, for example, by having the button-clicked, edit-changed, etc. handler call a function computeModification

void CMyClass::computeModification()
   {
    checksum current;
    current.clear();
    doChecksum(current);
    CMyClass::SetModified(current.get() != original.get());
   }

Note that if the checkbox was originally unchecked, and the user checks it, we get an indication (at least in the Modified flag) that the document has changed. If the user then unchecks it, and all other values have been unchanged, we get an indication that the content has not been modified (this means the checksum has to account for all forms of change! And that's your responsibility!)

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“I invented the term Object-Oriented, and I can tell you I did not have C++ in mind.” - Alan Kay