/*=============================================================================
|
| NAME
|  
|     crcCode.h
|
| DESCRIPTION
|  
|     Class definition for CRCCode
|
| AUTHOR
|
|      Sean O'Connor
|    
| LEGAL
|
|     CRCDemo Version 2.1 - A Program for generating and checking CRC codes.
|     Copyright (C) 1999-2017 by Sean Erik O'Connor.  All Rights Reserved.
|
|     This program is free software: you can redistribute it and/or modify
|     it under the terms of the GNU General Public License as published by
|     the Free Software Foundation, either version 3 of the License, or
|     (at your option) any later version.
|
|     This program is distributed in the hope that it will be useful,
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
|     GNU General Public License for more details.
|
|     You should have received a copy of the GNU General Public License
|     along with this program.  If not, see <http://www.gnu.org/licenses/>.
|     
|     The author's address is artificer!AT!seanerikoconnor!DOT!freeservers!DOT!com
|     with !DOT! replaced by . and the !AT! replaced by @
|
+============================================================================*/

#ifndef __CRC_CODE_H__
#define __CRC_CODE_H__

#include <string>
using namespace std ;




/*=============================================================================
|
| NAME
|  
|    CRCCode     
|
| DESCRIPTION
|  
|    Class for CRC (Cyclic Redundancy Check) code encoding and 
|    decoding.
|
| METHOD
|
|    Encoding (systematic):
|
|      c( x ) = m( x ) + p( x )
|
|                  n-k
|      m( x ) =  x     i( x )             Message portion of codeword c(x).
|                  n-k
|      p( x ) = -x     i( x ) mod g( x )  Parity portion of codeword c(x).
|
|    Decoding:
|
|      s( x ) = c( x ) mod g( x )         Syndrome of codeword c(x).
|
|      The shift register computes
|
|          n-k
|      [ x     c( x ) ] mod g( x )
|
|      This shifted syndrome is OK to use for error checking because it 
|      is zero iff c( x ) was a codeword.
|
+============================================================================*/

class CRCCode
{
    public:
        // Construct CRC from given generator polynomial.
        CRCCode( const string &                       g,
                 syndrome_t    shiftRegisterPreset = 0L,
                 bool          invertParity        = false ) ;

        ~CRCCode() ;

        // Return the parity bits computed on the data in the buffer.
        // Parity bits are in the most significant bits of the buffer.
        syndrome_t parityBits( unsigned char * buffer, long int n ) ;

        // Append CRC parity bytes to the end of the buffer.
        // The buffer must be long enough to accomodate the
        // extra parity bits.  Buffer length is increased
        // upon exit.
        void addParityToBuffer( unsigned char * buffer, long int n ) ;

        // Compute the shifted syndrome of the codeword.
        // Zero indicates we have a codeword.
        syndrome_t shiftedSyndrome( unsigned char * buffer,
                                    long int        n ) ;

        // Return the number of parity bytes.
        int getNumParityBytes( void ) const ;

    private:
        // The linear feedback shift register circuit we will use
        // to do all the computations.
        ShiftRegister shiftRegister_ ;

        // Number of parity bits, n - k
        int numParityBits_ ;

        // Shift register may be loaded with a value
        // (usually FFF..FFF) instead of zero.
        int shiftRegisterPreset_ ;

        // Some implementations do a 1's complement
        // of the parity bits.
        bool invertParity_ ;

    private:
        // Disable automatic generation of copy constructor
        // and assignment operator.
        CRCCode( const CRCCode & ) ;
        CRCCode operator=( const CRCCode & ) ;
} ;

#endif // __CRC_CODE_H__