Figure 1: CRC Error-checking class
// Based on Ross Williams' Rocksoft Model CRC Algorithm, // available as part of the document "A Painless Guide to // CRC Error Detection Algorithms", also by Ross Williams // NOTE: ... indicates code omitted for brevity #if !defined(__CRC_H) #define __CRC_H namespace cdm_crc { static const int CRCMaxBits = 32; template<int Width, unsigned long Poly, unsigned long Init, unsigned long XOrOut, bool Ref, bool Direct = true> class CRCGenerator { public: class CRCTable; friend class CRCTable; class CRCTable { unsigned long Table[ 256 ]; // Calculate the table entry at 'index' unsigned long CalcTableEntry( int index ) { ... } public: CRCTable() { for( int i = 0; i < 256; i++ ) { Table[ i ] = CalcTableEntry( i ); } } unsigned long operator[](int i) const {return Table[ i ];} }; private: static const CRCTable Table; // Register holds the current value of the CRC calculation unsigned long Register; // Return an unsigned long with i'th bit set to one static unsigned long Bitmask( int i ) { return 1UL << i; } // Reflect the bottom b bits of val static unsigned long Reflect( unsigned long val, int b ) { ... } // Return an unsigned long with value ( 2^width )-1 static unsigned long WidthMask( int width ) { return ( ( ( 1UL<<(width-1) ) -1UL )<<1 ) | 1UL; } public: CRCGenerator(): Register( Init ) {} unsigned long GetCRC() const { return (XOrOut ^ Register) & WidthMask( Width ); } unsigned long GetNormalCRC() const { ... } bool GetDirect() const { return Direct; } bool GetReflect() const { return Ref; } int GetWidth() const { return Width; } void LoadRegister( unsigned long val ) { ... } void Process( unsigned char ch ) { ... } void Process( unsigned char* block, int block_length ) { ... } // Un-comment the following version if no member templates /// void Process(unsigned char* first, unsigned char* last) /// { /// while( first != last ) /// { /// Process( *first++ ); /// } /// } // Comment out the following version if no member templates template<class InIter> void Process( InIter first, InIter last ) { while( first != last ) { Process( *first ); ++first; } } // Process 'count' bits from 'bits'. if 'Ref' is false // reads starting from MSB of 'bits'. If 'Ref' is true // starts from LSB void ProcessBits( unsigned char bits, int count ) { ... } void Reset() { Register = Init; } void Write( ostream& os ) const { ... } }; template<int Width, unsigned long Poly, unsigned long Init, unsigned long XOrOut, bool Ref, bool Direct> const CRCGenerator<Width, Poly, Init, XOrOut, Ref, Direct>::CRCTable CRCGenerator<Width, Poly, Init, XOrOut, Ref, Direct>::Table; template<int Width, unsigned long Poly, unsigned long Init, unsigned long XOrOut, bool Ref, bool Direct> ostream& operator<<( ostream& os, CRCGenerator<Width, Poly, Init, XOrOut, Ref, Direct>& crc) { crc.Write( os ); return os; } }; // end of namespace cdm_crc #endif // __CRC_H