// 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