// CRC32.h #ifndef CRC32h #define CRC32h #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 /* CRC is a "digital fingerprint" of a file. With CRC32 you can get a single 32-bit number that represents a string or file (of any size). If the file data changes in any way (even a single bit) the CRC32 calculation would yield a completely different value. This algorithm is used by WinZip and PKZIP (ie the same numbers are generated) so: pkunzip.exe -vt File.zip gives the same CRC value as you get by giving the file to this code. A single 1kB table is allocated while instances of CCRC32 exist. Usage: DWORD CRC=CCRC32().From(Buffer,Size); or use one instance for several CRCs: CCRC32 CRC32; DWORD CRC1=CRC32.From(Buffer1,Size1); DWORD CRC2=CRC32.From(Buffer2,Size2); or if reading data in blocks: int OK; CCRC32 CRC32; BYTE Buffer[1024]; FILE* File=fopen("C:\\CheckMe.txt","rb"); if(File) do CRC32.From(Buffer, OK=fread(Buffer, 1, 1024, File), true); while(OK); fclose(File); DWORD CRC=CRC32.GetCRC(); But since we want the fastest routines we should use CreateFile and thats what the class uses internally for retrieving the CRC32 of a file: DWORD CRC=CCRC32().From("C:\\CheckMe.txt"); */ class CCRC32 { DWORD* Tbl; // These let us use the static variables in the constructor without having to have a .cpp file to initialise the statics int* Instances; DWORD LastCRC; public: CCRC32() { static DWORD* StaticTbl=0; // Table of CRC values for every possible BYTE static int StaticInstances=0; // Count of references to Tbl (Instances of CCRC32) Tbl=StaticTbl; Instances=&StaticInstances; if(Tbl) ++Instances; else { LastCRC=-1; *Instances=0; Tbl=new DWORD[256]; if(!Tbl) return; *Instances=1; DWORD* ptr=Tbl; for(DWORD n=0; n<256; ++n){ DWORD c=n; for(int k=0; k<8; ++k) c=(c&1 ? 0xEDB88320^(c>>1) : c>>1); *ptr++=c; } } } virtual ~CCRC32() { if(*Instances) --*Instances; if(*Instances) return; try{delete[] Tbl;}catch(...){} Tbl=0; } DWORD GetCRC() const {return ~LastCRC;} DWORD From(const char* Path, bool Partial=false) { if(!Partial) Reset(); DWORD OK; char Buffer[1024]; HANDLE File=CreateFile(Path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if(File) do { ReadFile(File, Buffer, sizeof(Buffer), &OK, 0); From(Buffer, OK, true); }while(OK); CloseHandle(File); return GetCRC(); } void Reset() {LastCRC=-1;} // Only use this to use one CRC32 class for a whole new checksum when only using From(...) with Partial=true. // Since all that happens with the Buffer is an Exclusive OR operation, it doesn't matter if Buffer holds signed or unsigned chars. DWORD From(const char* Buffer, int Len, bool Partial=false) {return From(Buffer, (DWORD)Len, Partial);} DWORD From(const char* Buffer, DWORD Len, bool Partial=false) { if(!Len || !Tbl || !Buffer) return 0; register DWORD CRC=(Partial ? LastCRC : LastCRC=-1); while(Len--) CRC=(CRC>>8)^Tbl[(CRC^(*Buffer++))&0xFF]; // Modern processors will NOT benefit from coded loop optimisation techniques (unrolling)! return ~(LastCRC=CRC); } }; #ifdef Assert // Run tests if Tester.h is included in stdafx.h namespace { // namespace prevents multiple definitions if instantiating in the header like this: struct CRC32Tester : Tester, CCRC32 { CRC32Tester() { Assert(From("resume",6)==0x60C1D0A0); Assert(From("resumé",6)==0x84CF1FAB); Assert(From("foo",3)==0x8C736521); Assert(From("test0123456789",24)==0x97F206A3); Assert(From("\x80\x00",2)==0x7A5A8AB4); Assert(From("\x00\x08",2)==0x4F029ACD); Assert(From("\x00\x80",2)==0xAC6191DF); Assert(From("\x80",1)==0x3FBA6CAD); Assert(From("\x80\x00\x00\x00",4)==0xCC1D6927); Assert(From("\x00\x00\x00\x01",4)==0x5643EF8A); } } _CRC32Tester; } #endif // def Assert #endif // ndef CRC32h