Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Calculating CRC Checksums in C++


June 1999/Calculating CRC Checksums in C++/Figure 1

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


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.