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!)
Comments