Theoretical CRC Computer

| Home | Libraries | People | FAQ | More

## Theoretical CRC Computer

    #include <cstddef>  // for std::size_t

    namespace boost
    {
        template < std::size_t Bits >
        class crc_basic;
    }

The `boost::crc_basic` class template acts as an unaugmented-CRC processor that can accept input at the bit-level. It only takes one Rocksoft™ Model CRC Algorithm parameter as a template parameter, the WIDTH, which determines the built-in unsigned integer type used for division registers. The other Rocksoft™ Model CRC Algorithm parameters can be passed on through the constructor. (Most of the parameters have defaults.)

The integer type used for registers is published as `value_type`, while the Rocksoft™ Model CRC Algorithm attributes can be discovered as:

Table 9.1. RMCA Parameters in boost::crc_basic

Parameter | Member Name | Kind | Expression Type
--- | --- | --- | ---
WIDTH | `bit_count` | class-static immutable data member | `std::size_t`
POLY | `get_truncated_polynominal` | `const` member function | `value_type`
INIT | `get_initial_remainder` | `const` member function | `value_type`
REFIN | `get_reflect_input` | `const` member function | `bool`
REFOUT | `get_reflect_remainder` | `const` member function | `bool`
XOROUT | `get_final_xor_value` | `const` member function | `value_type`

Since most of the parameters are specified at run-time, you can reuse a single computer object for separate runs with differing parameters. The type uses the automatically-defined copy/move/assign and destruction routines.

Here's an example of reuse:

    std::pair<unsigned, unsigned> crc_16_and_xmodem( void const *b, std::size_t l )
    {
        std::pair<unsigned, unsigned>  result;
        boost::crc_basic<16>           crc1( 0x8005u, 0u, 0u, true, true );

        crc1.process_bytes( b, l );
        result.first = crc1.checksum();
        crc1 = boost::crc_basic<16>( 0x8408u, crc1.get_initial_remainder(),
         crc1.get_final_xor_value(), crc1.get_reflect_input(),
         crc1.get_reflect_remainder() );
        crc1.process_bytes( b, l );
        result.second = crc1.checksum();

        return result;
    }

For now, most Rocksoft™ Model CRC Algorithm parameters can only be changed through assignment to the entire object.

| The parameters are based on `boost::crc_16_type`.
| Change the parameters to match `boost::crc_xmodem_type`.

This example necessarily demonstrates input and output. There is one output member function, `checksum` that returns the remainder from the CRC steps plus any post-processing reflection and/or XOR-masking. There are several options to submit input data for processing:

Table 9.2. Member Functions for Input in boost::crc_basic

Member Function | Input Type/Style
--- | ---
`process_bit` | A single bit.
`process_bits` | A specified number of bits within the given byte. Reading starts from the highest-order desired bit.
`process_byte` | An entire byte. The bits within the byte are read in an order consistent with `get_reflect_input`.
`process_block` | All bytes in the range. The range is defined by a pointer to the first byte and another pointer to one (byte) past-the-end.
`process_bytes` | All bytes in the range. The range is defined by a pointer to the first byte and a count of number of bytes to read.

The input functions currently do not return anything.

Persistent objects mean that the data doesn't have to be in one block:

    unsigned  combined_crc_16( unsigned block_count, ... )
    {
        using namespace std;

        boost::crc_basic<16>  crc1( 0x8005u, 0u, 0u, true, true );
        va_list               ap;

        va_start( ap, block_count );
        while ( block_count-- )
        {
            void const * const  bs = va_arg( ap, void const * );
            size_t const        bl = va_arg( ap, size_t );

            crc1.process_bytes( bs, bl );
        }
        va_end( ap );

        return crc1.checksum();
    }

No CRC operation throws, so there is no need for extra protection between the varargs macro calls.

| C-style variable-argument routines are or may be macros.
| The parameters are based on `boost::crc_16_type`.
| The `va_arg` calls were within the `process_bytes` call, but I remembered that calling order is not guaranteed among function arguments, so I need explicit object declarations to enforce the extraction order.

The input-influenced state of a computer object may be read with the `get_interim_remainder` member function. An object may be loaded with the same kind of state with the one-argument version of the `reset` member function. The state is the remainder from the CRC operations performed on all the already-entered input, without any output post-processing.

The two functions can be used together to save the state to a persistent medium and restore it later. Note that the Rocksoft™ Model CRC Algorithm parameters have to saved/restored via other means, if they're not fixed within a program.

Calling `reset` with no arguments sets the interim remainder to what INIT was set at object construction. This lets one computer object be used for independent runs with separate data messages using the same CRC standard.