You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2306 lines
93 KiB
2306 lines
93 KiB
// Boost CRC library crc.hpp header file -----------------------------------// |
|
|
|
// Copyright 2001, 2004, 2011 Daryle Walker. |
|
// Distributed under the Boost Software License, Version 1.0. (See the |
|
// accompanying file LICENSE_1_0.txt or a copy at |
|
// <http://www.boost.org/LICENSE_1_0.txt>.) |
|
|
|
// See <http://www.boost.org/libs/crc/> for the library's home page. |
|
|
|
/** \file |
|
\brief A collection of function templates and class templates that compute |
|
various forms of Cyclic Redundancy Codes (CRCs). |
|
|
|
\author Daryle Walker |
|
|
|
\version 1.5 |
|
|
|
\copyright Boost Software License, version 1.0 |
|
|
|
Contains the declarations (and definitions) of various kinds of CRC |
|
computation functions, function object types, and encapsulated policy types. |
|
|
|
\warning The sample CRC-computer types were just checked against the |
|
<a href="http://regregex.bbcmicro.net/crc-catalogue.htm">Catalogue of |
|
parametrised CRC algorithms</a>. New type aliases were added where I got |
|
a standard wrong. However, the mistaken <code>typedef</code>s are still |
|
there for backwards compatibility. |
|
\note There are references to the <i>Rocksoft™ Model CRC |
|
Algorithm</i>, as described within \"A Painless Guide to CRC Error |
|
Detection Algorithms,\" linked from \"<a |
|
href="http://www.ross.net/crc/crcpaper.html">CRC: A Paper On CRCs</a>\" by |
|
Ross Williams. It will be abbreviated \"RMCA\" in other documentation |
|
blocks. |
|
*/ |
|
|
|
#ifndef BOOST_CRC_HPP |
|
#define BOOST_CRC_HPP |
|
|
|
#include <boost/array.hpp> // for boost::array |
|
#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT, etc. |
|
#include <boost/cstdint.hpp> // for UINTMAX_C, boost::uintmax_t |
|
#include <boost/integer.hpp> // for boost::uint_t |
|
#include <boost/type_traits/conditional.hpp> |
|
#include <boost/type_traits/integral_constant.hpp> |
|
|
|
#include <climits> // for CHAR_BIT, etc. |
|
#include <cstddef> // for std::size_t |
|
|
|
#include <boost/limits.hpp> // for std::numeric_limits |
|
|
|
|
|
// The type of CRC parameters that can go in a template should be related |
|
// on the CRC's bit count. This macro expresses that type in a compact |
|
// form, but also allows an alternate type for compilers that don't support |
|
// dependent types (in template value-parameters). |
|
#if !(defined(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS)) |
|
#define BOOST_CRC_PARM_TYPE typename ::boost::uint_t<Bits>::fast |
|
#else |
|
#define BOOST_CRC_PARM_TYPE unsigned long |
|
#endif |
|
|
|
namespace boost |
|
{ |
|
|
|
|
|
// Forward declarations ----------------------------------------------------// |
|
|
|
//! Bit-wise CRC computer |
|
template < std::size_t Bits > |
|
class crc_basic; |
|
|
|
//! Table-driven CRC computer, usable as a function object |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly = 0u, |
|
BOOST_CRC_PARM_TYPE InitRem = 0u, |
|
BOOST_CRC_PARM_TYPE FinalXor = 0u, bool ReflectIn = false, |
|
bool ReflectRem = false > |
|
class crc_optimal; |
|
|
|
//! Compute the (unaugmented) CRC of a memory block |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
typename uint_t<Bits>::fast crc( void const *buffer, |
|
std::size_t byte_count); |
|
|
|
//! Compute the CRC of a memory block, with any augmentation provided by user |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly > |
|
typename uint_t<Bits>::fast augmented_crc( void const *buffer, |
|
std::size_t byte_count, |
|
typename uint_t<Bits>::fast initial_remainder = 0u); |
|
|
|
//! Computation type for ARC|CRC-16|CRC-IBM|CRC-16/ARC|CRC-16/LHA standard |
|
typedef crc_optimal<16, 0x8005, 0, 0, true, true> crc_16_type; |
|
//! Computation type for CRC-16/CCITT-FALSE standard |
|
typedef crc_optimal<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt_false_t; |
|
//! Computation type for the CRC mistakenly called the CCITT standard |
|
typedef crc_ccitt_false_t crc_ccitt_type; |
|
//! Computation type for the actual |
|
//! KERMIT|CRC-16/CCITT|CRC-16/CCITT-TRUE|CRC-CCITT standard |
|
typedef crc_optimal<16, 0x1021, 0, 0, true, true> crc_ccitt_true_t; |
|
//! Computation type that I mistakenly called the XMODEM standard; it inverts |
|
//! both reflection parameters and reflects the truncated divisor (Don't use?!) |
|
typedef crc_optimal<16, 0x8408, 0, 0, true, true> crc_xmodem_type; |
|
//! Computation type for the actual XMODEM|ZMODEM|CRC-16/ACORN standard |
|
typedef crc_optimal<16, 0x1021, 0, 0, false, false> crc_xmodem_t; |
|
|
|
//! Computation type for CRC-32|CRC-32/ADCCP|PKZIP standard |
|
typedef crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true> |
|
crc_32_type; |
|
|
|
|
|
// Forward declarations for implementation detail stuff --------------------// |
|
// (Just for the stuff that will be needed for the next two sections) |
|
|
|
//! \cond |
|
namespace detail |
|
{ |
|
//! Mix-in class to add a possibly-reflecting member function |
|
template < int BitLength, bool DoIt, int Id = 0 > |
|
class possible_reflector; |
|
|
|
//! Mix-in class for byte-fed, table-driven CRC algorithms |
|
template < int Order, boost::uintmax_t TruncatedPolynomial, bool Reflect, |
|
int Id = 0 > |
|
class crc_driver; |
|
|
|
} // namespace detail |
|
//! \endcond |
|
|
|
|
|
// Simple cyclic redundancy code (CRC) class declaration -------------------// |
|
|
|
/** Objects of this type compute the CRC checksum of submitted data, where said |
|
data can be entered piecemeal through several different kinds of groupings. |
|
Modulo-2 polynomial division steps are always performed bit-wise, without |
|
the use of pre-computation tables. Said division uses the altered |
|
algorithm, so any data has to be unaugmented. |
|
|
|
\pre 0 \< \a Bits \<= \c std\::numeric_limits\<uintmax_t\>\::digits |
|
|
|
\tparam Bits The order of the modulo-2 polynomial divisor. (\e Width from |
|
the RMCA) |
|
*/ |
|
template < std::size_t Bits > |
|
class crc_basic |
|
{ |
|
public: |
|
// Type |
|
/** \brief The register type used for computations |
|
|
|
This type is used for CRC calculations and is the type for any returned |
|
checksums and returned or submitted remainders, (truncated) divisors, or |
|
XOR masks. It is a built-in unsigned integer type. |
|
*/ |
|
typedef typename boost::uint_t<Bits>::fast value_type; |
|
|
|
// Constant for the template parameter |
|
//! A copy of \a Bits provided for meta-programming purposes |
|
BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits ); |
|
|
|
// Constructor (use the automatic copy-ctr, move-ctr, and dtr) |
|
//! Create a computer, separately listing each needed parameter |
|
explicit crc_basic( value_type truncated_polynomial, |
|
value_type initial_remainder = 0, value_type final_xor_value = 0, |
|
bool reflect_input = false, bool reflect_remainder = false ); |
|
|
|
// Internal Operations |
|
//! Return the (truncated) polynomial divisor |
|
value_type get_truncated_polynominal() const; |
|
//! Return what the polynomial remainder was set to during construction |
|
value_type get_initial_remainder() const; |
|
//! Return the XOR-mask used during output processing |
|
value_type get_final_xor_value() const; |
|
//! Check if input-bytes will be reflected before processing |
|
bool get_reflect_input() const; |
|
//! Check if the remainder will be reflected during output processing |
|
bool get_reflect_remainder() const; |
|
|
|
//! Return the remainder based from already-processed bits |
|
value_type get_interim_remainder() const; |
|
//! Change the interim remainder to a new value |
|
void reset( value_type new_rem ); |
|
//! Change the interim remainder back to the initial value |
|
void reset(); |
|
|
|
// External Operations |
|
//! Submit a single bit for input processing |
|
void process_bit( bool bit ); |
|
//! Submit the lowest \a bit_length bits of a byte for input processing |
|
void process_bits( unsigned char bits, std::size_t bit_length ); |
|
//! Submit a single byte for input processing |
|
void process_byte( unsigned char byte ); |
|
//! Submit a memory block for input processing, iterator-pair style |
|
void process_block( void const *bytes_begin, void const *bytes_end ); |
|
//! Submit a memory block for input processing, pointer-and-size style |
|
void process_bytes( void const *buffer, std::size_t byte_count ); |
|
|
|
//! Return the checksum of the already-processed bits |
|
value_type checksum() const; |
|
|
|
private: |
|
// Member data |
|
value_type rem_; |
|
value_type poly_, init_, final_; // non-const to allow assignability |
|
bool rft_in_, rft_out_; // non-const to allow assignability |
|
|
|
}; // boost::crc_basic |
|
|
|
|
|
// Optimized cyclic redundancy code (CRC) class declaration ----------------// |
|
|
|
/** Objects of this type compute the CRC checksum of submitted data, where said |
|
data can be entered piecemeal through several different kinds of groupings. |
|
Modulo-2 polynomial division steps are performed byte-wise, aided by the use |
|
of pre-computation tables. Said division uses the altered algorithm, so any |
|
data has to be unaugmented. |
|
|
|
\pre 0 \< \a Bits \<= \c std\::numeric_limits\<uintmax_t\>\::digits |
|
|
|
\tparam Bits The order of the modulo-2 polynomial divisor. (\e Width from |
|
the RMCA) |
|
\tparam TruncPoly The lowest coefficients of the divisor polynomial. The |
|
highest-order coefficient is omitted and always assumed to be 1. Defaults |
|
to \c 0, i.e. the only non-zero term is the implicit one for |
|
x<sup><var>Bits</var></sup>. (\e Poly from the RMCA) |
|
\tparam InitRem The (unaugmented) initial state of the polynomial |
|
remainder. Defaults to \c 0 if omitted. (\e Init from the RMCA) |
|
\tparam FinalXor The (XOR) bit-mask to be applied to the output remainder, |
|
after possible reflection but before returning. Defaults to \c 0 (i.e. no |
|
bit changes) if omitted. (\e XorOut from the RMCA) |
|
\tparam ReflectIn If \c true, input bytes are read lowest-order bit first, |
|
otherwise highest-order bit first. Defaults to \c false if omitted. |
|
(\e RefIn from the RMCA) |
|
\tparam ReflectRem If \c true, the output remainder is reflected before the |
|
XOR-mask. Defaults to \c false if omitted. (\e RefOut from the RMCA) |
|
|
|
\todo Get rid of the default value for \a TruncPoly. Choosing a divisor is |
|
an important decision with many factors, so a default is never useful, |
|
especially a bad one. |
|
*/ |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
class crc_optimal |
|
{ |
|
public: |
|
// Type |
|
//! \copydoc boost::crc_basic::value_type |
|
typedef typename boost::uint_t<Bits>::fast value_type; |
|
|
|
// Constants for the template parameters |
|
//! \copydoc boost::crc_basic::bit_count |
|
BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits ); |
|
//! A copy of \a TruncPoly provided for meta-programming purposes |
|
BOOST_STATIC_CONSTANT( value_type, truncated_polynominal = TruncPoly ); |
|
//! A copy of \a InitRem provided for meta-programming purposes |
|
BOOST_STATIC_CONSTANT( value_type, initial_remainder = InitRem ); |
|
//! A copy of \a FinalXor provided for meta-programming purposes |
|
BOOST_STATIC_CONSTANT( value_type, final_xor_value = FinalXor ); |
|
//! A copy of \a ReflectIn provided for meta-programming purposes |
|
BOOST_STATIC_CONSTANT( bool, reflect_input = ReflectIn ); |
|
//! A copy of \a ReflectRem provided for meta-programming purposes |
|
BOOST_STATIC_CONSTANT( bool, reflect_remainder = ReflectRem ); |
|
|
|
// Constructor (use the automatic copy-ctr, move-ctr, and dtr) |
|
//! Create a computer, giving an initial remainder if desired |
|
explicit crc_optimal( value_type init_rem = initial_remainder ); |
|
|
|
// Internal Operations |
|
//! \copybrief boost::crc_basic::get_truncated_polynominal |
|
value_type get_truncated_polynominal() const; |
|
//! \copybrief boost::crc_basic::get_initial_remainder |
|
value_type get_initial_remainder() const; |
|
//! \copybrief boost::crc_basic::get_final_xor_value |
|
value_type get_final_xor_value() const; |
|
//! \copybrief boost::crc_basic::get_reflect_input |
|
bool get_reflect_input() const; |
|
//! \copybrief boost::crc_basic::get_reflect_remainder |
|
bool get_reflect_remainder() const; |
|
|
|
//! \copybrief boost::crc_basic::get_interim_remainder |
|
value_type get_interim_remainder() const; |
|
//! Change the interim remainder to either a given value or the initial one |
|
void reset( value_type new_rem = initial_remainder ); |
|
|
|
// External Operations |
|
//! \copybrief boost::crc_basic::process_byte |
|
void process_byte( unsigned char byte ); |
|
//! \copybrief boost::crc_basic::process_block |
|
void process_block( void const *bytes_begin, void const *bytes_end ); |
|
//! \copybrief boost::crc_basic::process_bytes |
|
void process_bytes( void const *buffer, std::size_t byte_count ); |
|
|
|
//! \copybrief boost::crc_basic::checksum |
|
value_type checksum() const; |
|
|
|
// Operators |
|
//! Submit a single byte for input processing, suitable for the STL |
|
void operator ()( unsigned char byte ); |
|
//! Return the checksum of the already-processed bits, suitable for the STL |
|
value_type operator ()() const; |
|
|
|
private: |
|
// Implementation types |
|
// (Processing for reflected input gives reflected remainders, so you only |
|
// have to apply output-reflection if Reflect-Remainder doesn't match |
|
// Reflect-Input.) |
|
typedef detail::possible_reflector<Bits, ReflectIn> reflect_i_type; |
|
typedef detail::crc_driver<Bits, TruncPoly, ReflectIn> crc_table_type; |
|
typedef detail::possible_reflector<Bits, ReflectRem != ReflectIn> |
|
reflect_o_type; |
|
|
|
// Member data |
|
value_type rem_; |
|
|
|
}; // boost::crc_optimal |
|
|
|
|
|
// Implementation detail stuff ---------------------------------------------// |
|
|
|
//! \cond |
|
namespace detail |
|
{ |
|
/** \brief Meta-programming integral constant for a single-bit bit-mask |
|
|
|
Generates a compile-time constant for a bit-mask that affects a single |
|
bit. The \c value will be 2<sup><var>BitIndex</var></sup>. The \c type |
|
will be the smallest built-in unsigned integer type that can contain the |
|
value, unless there's a built-in type that the system can handle easier, |
|
then the \c type will be smallest fast-handled unsigned integer type. |
|
|
|
\pre 0 \<= BitIndex \< \c std\::numeric_limits\<uintmax_t\>\::digits |
|
|
|
\tparam BitIndex The place of the sole set bit. |
|
*/ |
|
template < int BitIndex > |
|
struct high_bit_mask_c |
|
: boost::integral_constant<typename boost::uint_t< BitIndex + 1 >::fast, |
|
( UINTMAX_C(1) << BitIndex )> |
|
{}; |
|
|
|
/** \brief Meta-programming integral constant for a lowest-bits bit-mask |
|
|
|
Generates a compile-time constant for a bit-mask that affects the lowest |
|
bits. The \c value will be 2<sup><var>BitCount</var></sup> - 1. The |
|
\c type will be the smallest built-in unsigned integer type that can |
|
contain the value, unless there's a built-in type that the system can |
|
handle easier, then the \c type will be smallest fast-handled unsigned |
|
integer type. |
|
|
|
\pre 0 \<= BitCount \<= \c std\::numeric_limits\<uintmax_t\>\::digits |
|
|
|
\tparam BitCount The number of lowest-placed bits set. |
|
*/ |
|
template < int BitCount > |
|
struct low_bits_mask_c |
|
: boost::integral_constant<typename boost::uint_t< BitCount >::fast, ( |
|
BitCount ? (( (( UINTMAX_C(1) << (BitCount - 1) ) - 1u) << 1 ) | |
|
UINTMAX_C( 1 )) : 0u )> |
|
{}; |
|
|
|
/** \brief Reflects the bits of a number |
|
|
|
Reverses the order of the given number of bits within a value. For |
|
instance, if the given reflect count is 5, then the bit values for the |
|
16- and 1-place will switch and the 8- and 2-place will switch, leaving |
|
the other bits alone. (The 4-place bit is in the middle, so it wouldn't |
|
change.) |
|
|
|
\pre \a Unsigned is a built-in unsigned integer type |
|
\pre 0 \< word_length \<= \c std\::numeric_limits\<Unsigned\>\::digits |
|
|
|
\tparam Unsigned The type of \a x. |
|
|
|
\param x The value to be (partially) reflected. |
|
\param word_length The number of low-order bits to reflect. Defaults |
|
to the total number of value bits in \a Unsigned. |
|
|
|
\return The (partially) reflected value. |
|
|
|
\todo Check if this is the fastest way. |
|
*/ |
|
template < typename Unsigned > |
|
Unsigned reflect_unsigned( Unsigned x, int word_length |
|
= std::numeric_limits<Unsigned>::digits ) |
|
{ |
|
for ( Unsigned l = 1u, h = l << (word_length - 1) ; h > l ; h >>= 1, l |
|
<<= 1 ) |
|
{ |
|
Unsigned const m = h | l, t = x & m; |
|
|
|
if ( (t == h) || (t == l) ) |
|
x ^= m; |
|
} |
|
|
|
return x; |
|
} |
|
|
|
/** \brief Make a byte-to-byte-reflection map |
|
|
|
Creates a mapping array so the results can be cached. Uses |
|
#reflect_unsigned to generate the element values. |
|
|
|
\return An array <var>a</var> such that, for a given byte value |
|
<var>i</var>, <code><var>a</var>[ <var>i</var> ]</code> resolves to |
|
the reflected value of <var>i</var>. |
|
*/ |
|
boost::array< unsigned char, (UINTMAX_C( 1 ) << CHAR_BIT) > |
|
inline make_byte_reflection_table() |
|
{ |
|
boost::array<unsigned char, ( UINTMAX_C(1) << CHAR_BIT )> result; |
|
unsigned char i = 0u; |
|
|
|
do |
|
result[ i ] = reflect_unsigned( i ); |
|
while ( ++i ); |
|
return result; |
|
} |
|
|
|
/** \brief Reflects the bits of a single byte |
|
|
|
Reverses the order of all the bits within a value. For instance, the |
|
bit values for the 2<sup><code>CHAR_BIT</code> - 1</sup>- and 1-place |
|
will switch and the 2<sup><code>CHAR_BIT</code> - 2</sup>- and 2-place |
|
will switch, etc. |
|
|
|
\param x The byte value to be reflected. |
|
|
|
\return The reflected value. |
|
|
|
\note Since this could be the most common type of reflection, and the |
|
number of states is relatively small, the implementation pre-computes |
|
and uses a table of all the results. |
|
*/ |
|
inline unsigned char reflect_byte( unsigned char x ) |
|
{ |
|
static boost::array<unsigned char, ( UINTMAX_C(1) << CHAR_BIT )> const |
|
table = make_byte_reflection_table(); |
|
|
|
return table[ x ]; |
|
} |
|
|
|
/** \brief Reflects some bits within a single byte |
|
|
|
Like #reflect_unsigned, except it takes advantage of any (long-term) |
|
speed gains #reflect_byte may bring. |
|
|
|
\pre 0 \< \a word_length \<= \c CHAR_BIT |
|
|
|
\param x The value to be (partially) reflected. |
|
\param word_length The number of low-order bits to reflect. |
|
|
|
\return The (partially) reflected value. |
|
*/ |
|
inline unsigned char reflect_sub_byte( unsigned char x, int word_length ) |
|
{ return reflect_byte(x) >> (CHAR_BIT - word_length); } |
|
|
|
/** \brief Possibly reflects the bits of a number |
|
|
|
Reverses the order of the given number of bits within a value. For |
|
instance, if the given reflect count is 5, then the bit values for the |
|
16- and 1-place will switch and the 8- and 2-place will switch, leaving |
|
the other bits alone. (The 4-place bit is in the middle, so it wouldn't |
|
change.) This variant function allows the reflection be controlled by |
|
an extra parameter, in case the decision to use reflection is made at |
|
run-time. |
|
|
|
\pre \a Unsigned is a built-in unsigned integer type |
|
\pre 0 \< word_length \<= \c std\::numeric_limits\<Unsigned\>\::digits |
|
|
|
\tparam Unsigned The type of \a x. |
|
|
|
\param x The value to be (partially) reflected. |
|
\param reflect Controls whether \a x is actually reflected (\c true) or |
|
left alone (\c false). |
|
\param word_length The number of low-order bits to reflect. Defaults |
|
to the total number of value bits in \a Unsigned. |
|
|
|
\return The possibly (partially) reflected value. |
|
*/ |
|
template < typename Unsigned > |
|
inline |
|
Unsigned reflect_optionally( Unsigned x, bool reflect, int word_length |
|
= std::numeric_limits<Unsigned>::digits ) |
|
{ return reflect ? reflect_unsigned(x, word_length) : x; } |
|
|
|
/** \brief Possibly reflects the bits of a single byte |
|
|
|
Uses #reflect_byte (if \a reflect is \c true). |
|
|
|
\param x The byte value to be (possibly) reflected. |
|
\param reflect Whether (\c true) or not (\c false) \a x is reflected. |
|
|
|
\return <code><var>reflect</var> ? reflect_byte(<var>x</var>) : |
|
<var>x</var></code> |
|
*/ |
|
inline |
|
unsigned char reflect_byte_optionally( unsigned char x, bool reflect ) |
|
{ return reflect ? reflect_byte(x) : x; } |
|
|
|
/** \brief Update a CRC remainder by several bits, assuming a non-augmented |
|
message |
|
|
|
Performs several steps of division required by the CRC algorithm, giving |
|
a new remainder polynomial based on the divisor polynomial and the |
|
synthesized dividend polynomial (from the old remainder and the |
|
newly-provided input). The computations assume that the CRC is directly |
|
exposed from the remainder, without any zero-valued bits augmented to |
|
the message bits. |
|
|
|
\pre \a Register and \a Word are both built-in unsigned integer types |
|
\pre 0 \< \a register_length \<= std\::numeric_limits\<\a Register\> |
|
\::digits |
|
\pre 0 \< \a word_length \<= std\::numeric_limits\<\a Word\>\::digits |
|
|
|
\tparam Register The type used for representing the remainder and |
|
divisor modulo-2 polynomials. The bit at <code>2<sup>i</sup></code> |
|
is used as the coefficient of <i>x<sup>i</sup></i>. |
|
\tparam Word The type used for storing the incoming terms of the |
|
dividend modulo-2 polynomial. The bit at <code>2<sup>i</sup></code> |
|
is used as the coefficient of <i>x<sup>i</sup></i> when \a reflect is |
|
\c false, and the coefficient of <i>x<sup><var>word_length</var> - 1 - |
|
i</sup></i> otherwise. |
|
|
|
\param[in] register_length The number of significant low-order bits |
|
to be used from \a Register values. It is the order of the modulo-2 |
|
polynomial remainder and one less than the divisor's order. |
|
\param[in,out] remainder The upper part of the dividend polynomial |
|
before division, and the remainder polynomial after. |
|
\param[in] new_dividend_bits The coefficients for the next |
|
\a word_length lowest terms of the dividend polynomial. |
|
\param[in] truncated_divisor The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
\param[in] word_length The number of lowest-order bits to read from |
|
\a new_dividend_bits. |
|
\param[in] reflect If \c false, read from the highest-order marked |
|
bit from \a new_dividend_bits and go down, as normal. Otherwise, |
|
proceed from the lowest-order bit and go up. |
|
|
|
\note This routine performs a modulo-2 polynomial division variant. |
|
The exclusive-or operations are applied in a different order, since |
|
that kind of operation is commutative and associative. It also |
|
assumes that the zero-valued augment string was applied before this |
|
step, which means that the updated remainder can be directly used as |
|
the final CRC. |
|
*/ |
|
template < typename Register, typename Word > |
|
void crc_modulo_word_update( int register_length, Register &remainder, Word |
|
new_dividend_bits, Register truncated_divisor, int word_length, bool |
|
reflect ) |
|
{ |
|
// Create this masking constant outside the loop. |
|
Register const high_bit_mask = UINTMAX_C(1) << (register_length - 1); |
|
|
|
// The natural reading order for division is highest digit/bit first. |
|
// The "reflect" parameter switches this. However, building a bit mask |
|
// for the lowest bit is the easiest.... |
|
new_dividend_bits = reflect_optionally( new_dividend_bits, !reflect, |
|
word_length ); |
|
|
|
// Perform modulo-2 division for each new dividend input bit |
|
for ( int i = word_length ; i ; --i, new_dividend_bits >>= 1 ) |
|
{ |
|
// compare the new bit with the remainder's highest |
|
remainder ^= ( new_dividend_bits & 1u ) ? high_bit_mask : 0u; |
|
|
|
// perform modulo-2 division |
|
bool const quotient = remainder & high_bit_mask; |
|
|
|
remainder <<= 1; |
|
remainder ^= quotient ? truncated_divisor : 0u; |
|
|
|
// The quotient isn't used for anything, so don't keep it. |
|
} |
|
} |
|
|
|
/** \brief Update a CRC remainder by a single bit, assuming a non-augmented |
|
message |
|
|
|
Performs the next step of division required by the CRC algorithm, giving |
|
a new remainder polynomial based on the divisor polynomial and the |
|
synthesized dividend polynomial (from the old remainder and the |
|
newly-provided input). The computations assume that the CRC is directly |
|
exposed from the remainder, without any zero-valued bits augmented to |
|
the message bits. |
|
|
|
\pre \a Register is a built-in unsigned integer type |
|
\pre 0 \< \a register_length \<= std\::numeric_limits\<\a Register\> |
|
\::digits |
|
|
|
\tparam Register The type used for representing the remainder and |
|
divisor modulo-2 polynomials. The bit at <code>2<sup>i</sup></code> |
|
is used as the coefficient of <i>x<sup>i</sup></i>. |
|
|
|
\param[in] register_length The number of significant low-order bits |
|
to be used from \a Register values. It is the order of the modulo-2 |
|
polynomial remainder and one less than the divisor's order. |
|
\param[in,out] remainder The upper part of the dividend polynomial |
|
before division, and the remainder polynomial after. |
|
\param[in] new_dividend_bit The coefficient for the constant term |
|
of the dividend polynomial. |
|
\param[in] truncated_divisor The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
|
|
\note This routine performs a modulo-2 polynomial division variant. |
|
The exclusive-or operations are applied in a different order, since |
|
that kind of operation is commutative and associative. It also |
|
assumes that the zero-valued augment string was applied before this |
|
step, which means that the updated remainder can be directly used as |
|
the final CRC. |
|
*/ |
|
template < typename Register > |
|
inline void crc_modulo_update( int register_length, Register &remainder, |
|
bool new_dividend_bit, Register truncated_divisor ) |
|
{ |
|
crc_modulo_word_update( register_length, remainder, |
|
static_cast<unsigned>(new_dividend_bit), truncated_divisor, 1, false ); |
|
} |
|
|
|
/** \brief Update a CRC remainder by several bits, assuming an augmented |
|
message |
|
|
|
Performs several steps of division required by the CRC algorithm, giving |
|
a new remainder polynomial based on the divisor polynomial and the |
|
synthesized dividend polynomial (from the old remainder and the |
|
newly-provided input). The computations assume that a zero-valued |
|
string of bits will be appended to the message before extracting the |
|
CRC. |
|
|
|
\pre \a Register and \a Word are both built-in unsigned integer types |
|
\pre 0 \< \a register_length \<= std\::numeric_limits\<\a Register\> |
|
\::digits |
|
\pre 0 \< \a word_length \<= std\::numeric_limits\<\a Word\>\::digits |
|
|
|
\tparam Register The type used for representing the remainder and |
|
divisor modulo-2 polynomials. The bit at <code>2<sup>i</sup></code> |
|
is used as the coefficient of <i>x<sup>i</sup></i>. |
|
\tparam Word The type used for storing the incoming terms of the |
|
dividend modulo-2 polynomial. The bit at <code>2<sup>i</sup></code> |
|
is used as the coefficient of <i>x<sup>i</sup></i> when \a reflect is |
|
\c false, and the coefficient of <i>x<sup><var>word_length</var> - 1 - |
|
i</sup></i> otherwise. |
|
|
|
\param[in] register_length The number of significant low-order bits |
|
to be used from \a Register values. It is the order of the modulo-2 |
|
polynomial remainder and one less than the divisor's order. |
|
\param[in,out] remainder The upper part of the dividend polynomial |
|
before division, and the remainder polynomial after. |
|
\param[in] new_dividend_bits The coefficients for the next |
|
\a word_length lowest terms of the dividend polynomial. |
|
\param[in] truncated_divisor The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
\param[in] word_length The number of lowest-order bits to read from |
|
\a new_dividend_bits. |
|
\param[in] reflect If \c false, read from the highest-order marked |
|
bit from \a new_dividend_bits and go down, as normal. Otherwise, |
|
proceed from the lowest-order bit and go up. |
|
|
|
\note This routine performs straight-forward modulo-2 polynomial |
|
division. It assumes that an augment string will be processed at the |
|
end of the message bits before doing CRC analysis. |
|
\todo Use this function somewhere so I can test it. |
|
*/ |
|
template < typename Register, typename Word > |
|
void augmented_crc_modulo_word_update( int register_length, Register |
|
&remainder, Word new_dividend_bits, Register truncated_divisor, int |
|
word_length, bool reflect ) |
|
{ |
|
// Create this masking constant outside the loop. |
|
Register const high_bit_mask = UINTMAX_C(1) << (register_length - 1); |
|
|
|
// The natural reading order for division is highest digit/bit first. |
|
// The "reflect" parameter switches this. However, building a bit mask |
|
// for the lowest bit is the easiest.... |
|
new_dividend_bits = reflect_optionally( new_dividend_bits, not reflect, |
|
word_length ); |
|
|
|
// Perform modulo-2 division for each new dividend input bit |
|
for ( int i = word_length ; i ; --i, new_dividend_bits >>= 1 ) |
|
{ |
|
bool const quotient = remainder & high_bit_mask; |
|
|
|
remainder <<= 1; |
|
remainder |= new_dividend_bits & 1u; |
|
remainder ^= quotient ? truncated_divisor : 0u; |
|
|
|
// The quotient isn't used for anything, so don't keep it. |
|
} |
|
} |
|
|
|
/** \brief Update a CRC remainder by a single bit, assuming an augmented |
|
message |
|
|
|
Performs the next step of division required by the CRC algorithm, giving |
|
a new remainder polynomial based on the divisor polynomial and the |
|
synthesized dividend polynomial (from the old remainder and the |
|
newly-provided input). The computations assume that a zero-valued |
|
string of bits will be appended to the message before extracting the |
|
CRC. |
|
|
|
\pre \a Register is a built-in unsigned integer type |
|
\pre 0 \< \a register_length \<= std\::numeric_limits\<\a Register\> |
|
\::digits |
|
|
|
\tparam Register The type used for representing the remainder and |
|
divisor modulo-2 polynomials. The bit at <code>2<sup>i</sup></code> |
|
is used as the coefficient of <i>x<sup>i</sup></i>. |
|
|
|
\param[in] register_length The number of significant low-order bits |
|
to be used from \a Register values. It is the order of the modulo-2 |
|
polynomial remainder and one less than the divisor's order. |
|
\param[in,out] remainder The upper part of the dividend polynomial |
|
before division, and the remainder polynomial after. |
|
\param[in] new_dividend_bit The coefficient for the constant term |
|
of the dividend polynomial. |
|
\param[in] truncated_divisor The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
|
|
\note This routine performs straight-forward modulo-2 polynomial |
|
division. It assumes that an augment string will be processed at the |
|
end of the message bits before doing CRC analysis. |
|
\todo Use this function somewhere so I can test it. |
|
*/ |
|
template < typename Register > |
|
inline void augmented_crc_modulo_update( int register_length, Register |
|
&remainder, bool new_dividend_bit, Register truncated_divisor ) |
|
{ |
|
augmented_crc_modulo_word_update( register_length, remainder, |
|
static_cast<unsigned>(new_dividend_bit), truncated_divisor, 1, false ); |
|
} |
|
|
|
/** \brief A mix-in class that returns its argument |
|
|
|
This class template makes a function object that returns its argument |
|
as-is. It's one case for #possible_reflector. |
|
|
|
\pre 0 \< \a BitLength \<= \c std\::numeric_limits\<uintmax_t\> |
|
\::digits |
|
|
|
\tparam BitLength How many significant bits arguments have. |
|
*/ |
|
template < int BitLength > |
|
class non_reflector |
|
{ |
|
public: |
|
/** \brief The type to check for specialization |
|
|
|
This is a Boost integral constant indicating that this class |
|
does not reflect its input values. |
|
*/ |
|
typedef boost::false_type is_reflecting_type; |
|
/** \brief The type to check for register bit length |
|
|
|
This is a Boost integral constant indicating how many |
|
significant bits won't actually be reflected. |
|
*/ |
|
typedef boost::integral_constant< int, BitLength > width_c; |
|
/** \brief The type of (not-)reflected values |
|
|
|
This type is the input and output type for the (possible-) |
|
reflection function, which does nothing here. |
|
*/ |
|
typedef typename boost::uint_t< BitLength >::fast value_type; |
|
|
|
/** \brief Does nothing |
|
|
|
Returns the given value, not reflecting any part of it. |
|
|
|
\param x The value to not be reflected. |
|
|
|
\return \a x |
|
*/ |
|
inline static value_type reflect_q( value_type x ) |
|
{ return x; } |
|
}; |
|
|
|
/** \brief A mix-in class that reflects (the lower part of) its argument, |
|
generally for types larger than a byte |
|
|
|
This class template makes a function object that returns its argument |
|
after reflecting its lower-order bits. It's one sub-case for |
|
#possible_reflector. |
|
|
|
\pre \c CHAR_BIT \< \a BitLength \<= \c std\::numeric_limits\<uintmax_t |
|
\>\::digits |
|
|
|
\tparam BitLength How many significant bits arguments have. |
|
*/ |
|
template < int BitLength > |
|
class super_byte_reflector |
|
{ |
|
public: |
|
/** \brief The type to check for specialization |
|
|
|
This is a Boost integral constant indicating that this class |
|
does reflect its input values. |
|
*/ |
|
typedef boost::true_type is_reflecting_type; |
|
/** \brief The type to check for register bit length |
|
|
|
This is a Boost integral constant indicating how many |
|
significant bits will be reflected. |
|
*/ |
|
typedef boost::integral_constant< int, BitLength > width_c; |
|
/** \brief The type of reflected values |
|
|
|
This is both the input and output type for the reflection function. |
|
*/ |
|
typedef typename boost::uint_t< BitLength >::fast value_type; |
|
|
|
/** \brief Reflect (part of) the given value |
|
|
|
Reverses the order of the given number of bits within a value, |
|
using #reflect_unsigned. |
|
|
|
\param x The value to be (partially) reflected. |
|
|
|
\return ( <var>x</var> & |
|
~(2<sup><var>width_c</var>\::value</sup> - 1) ) | REFLECT( |
|
<var>x</var> & (2<sup><var>width_c</var>\::value</sup> - |
|
1) ) |
|
*/ |
|
inline static value_type reflect_q( value_type x ) |
|
{ return reflect_unsigned(x, width_c::value); } |
|
}; |
|
|
|
/** \brief A mix-in class that reflects (the lower part of) its argument, |
|
generally for bytes |
|
|
|
This class template makes a function object that returns its argument |
|
after reflecting its lower-order bits. It's one sub-case for |
|
#possible_reflector. |
|
|
|
\pre 0 \< \a BitLength \<= \c CHAR_BIT |
|
|
|
\tparam BitLength How many significant bits arguments have. |
|
*/ |
|
template < int BitLength > |
|
class sub_type_reflector |
|
{ |
|
public: |
|
/** \brief The type to check for specialization |
|
|
|
This is a Boost integral constant indicating that this class |
|
does reflect its input values. |
|
*/ |
|
typedef boost::true_type is_reflecting_type; |
|
/** \brief The type to check for register bit length |
|
|
|
This is a Boost integral constant indicating how many |
|
significant bits will be reflected. |
|
*/ |
|
typedef boost::integral_constant< int, BitLength > width_c; |
|
/** \brief The type of reflected values |
|
|
|
This is both the input and output type for the reflection function. |
|
*/ |
|
typedef unsigned char value_type; |
|
|
|
/** \brief Reflect (part of) the given value |
|
|
|
Reverses the order of the given number of bits within a value, |
|
using #reflect_sub_byte. |
|
|
|
\param x The value to be (partially) reflected. |
|
|
|
\return ( <var>x</var> & |
|
~(2<sup><var>width_c</var>\::value</sup> - 1) ) | REFLECT( |
|
<var>x</var> & (2<sup><var>width_c</var>\::value</sup> - |
|
1) ) |
|
*/ |
|
inline static value_type reflect_q( value_type x ) |
|
{ return reflect_sub_byte(x, width_c::value); } |
|
}; |
|
|
|
/** \brief A mix-in class that reflects (the lower part of) its argument |
|
|
|
This class template makes a function object that returns its argument |
|
after reflecting its lower-order bits. It's one case for |
|
#possible_reflector. |
|
|
|
\pre 0 \< \a BitLength \<= \c std\::numeric_limits\<uintmax_t\> |
|
\::digits |
|
|
|
\tparam BitLength How many significant bits arguments have. |
|
*/ |
|
template < int BitLength > |
|
class reflector |
|
: public boost::conditional< (BitLength > CHAR_BIT), |
|
super_byte_reflector<BitLength>, sub_type_reflector<BitLength> >::type |
|
{ }; |
|
|
|
/** This class template adds a member function #reflect_q that will |
|
conditionally reflect its first argument, controlled by a compile-time |
|
parameter. |
|
|
|
\pre 0 \< \a BitLength \<= \c std\::numeric_limits\<uintmax_t\> |
|
\::digits |
|
|
|
\tparam BitLength How many significant bits arguments have. |
|
\tparam DoIt \c true if #reflect_q will reflect, \c false if it should |
|
return its argument unchanged. |
|
\tparam Id An extra differentiator if multiple copies of this class |
|
template are mixed-in as base classes. Defaults to 0 if omitted. |
|
*/ |
|
template < int BitLength, bool DoIt, int Id > |
|
class possible_reflector |
|
: public boost::conditional< DoIt, reflector<BitLength>, |
|
non_reflector<BitLength> >::type |
|
{ |
|
public: |
|
/** \brief The type to check for ID |
|
|
|
This is a Boost integral constant indicating what ID number this |
|
instantiation used. |
|
*/ |
|
typedef boost::integral_constant<int, Id> id_type; |
|
}; |
|
|
|
/** \brief Find the composite remainder update effect from a fixed bit |
|
sequence, for each potential sequence combination. |
|
|
|
For each value between 0 and 2<sup><var>SubOrder</var></sup> - 1, |
|
computes the XOR mask corresponding to the composite effect they update |
|
the incoming remainder, which is the upper part of the dividend that |
|
gets (partially) pushed out of its register by the incoming value's |
|
bits. The composite value merges the \"partial products\" from each bit |
|
of the value being updated individually. |
|
|
|
\pre \a Register is a built-in unsigned integer type |
|
\pre 0 \< \a SubOrder \<= \a register_length \<= |
|
std\::numeric_limits\<\a Register\>\::digits |
|
|
|
\tparam SubOrder The number of low-order significant bits of the trial |
|
new dividends. |
|
\tparam Register The type used for representing the remainder and |
|
divisor modulo-2 polynomials. The bit at <code>2<sup>i</sup></code> |
|
is used as the coefficient of <i>x<sup>i</sup></i>. |
|
|
|
\param[in] register_length The number of significant low-order bits |
|
to be used from \a Register values. It is the order of the modulo-2 |
|
polynomial remainder and one less than the divisor's order. |
|
\param[in] truncated_divisor The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
\param[in] reflect If \c false, read from the highest-order marked |
|
bit from a new dividend's bits and go down, as normal. Otherwise, |
|
proceed from the lowest-order bit and go up. |
|
|
|
\return An array such that the element at index <var>i</var> is the |
|
composite effect XOR mask for value <var>i</var>. |
|
|
|
\note This routine performs a modulo-2 polynomial division variant. |
|
The exclusive-or operations are applied in a different order, since |
|
that kind of operation is commutative and associative. It also |
|
assumes that the zero-valued augment string was applied before this |
|
step, which means that the updated remainder can be directly used as |
|
the final CRC. |
|
\todo Check that using the unaugmented-CRC division routines give the |
|
same composite mask table as using augmented-CRC routines. |
|
*/ |
|
template < int SubOrder, typename Register > |
|
boost::array< Register, (UINTMAX_C( 1 ) << SubOrder) > |
|
make_partial_xor_products_table( int register_length, Register |
|
truncated_divisor, bool reflect ) |
|
{ |
|
boost::array<Register, ( UINTMAX_C(1) << SubOrder )> result; |
|
|
|
// Loop over every possible dividend value |
|
for ( typename boost::uint_t<SubOrder + 1>::fast dividend = 0u; |
|
dividend < result.size() ; ++dividend ) |
|
{ |
|
Register remainder = 0u; |
|
|
|
crc_modulo_word_update( register_length, remainder, dividend, |
|
truncated_divisor, SubOrder, false ); |
|
result[ reflect_optionally(dividend, reflect, SubOrder) ] = |
|
reflect_optionally( remainder, reflect, register_length ); |
|
} |
|
return result; |
|
} |
|
|
|
/** \brief A mix-in class for the table of table-driven CRC algorithms |
|
|
|
Encapsulates the parameters need to make a global (technically, |
|
class-static) table usuable in CRC algorithms, and generates said |
|
table. |
|
|
|
\pre 0 \< \a SubOrder \<= Order \<= |
|
std\::numeric_limits\<uintmax_t\>\::digits |
|
|
|
\tparam Order The order of the modulo-2 polynomial remainder and one |
|
less than the divisor's order. |
|
\tparam SubOrder The number of low-order significant bits of the trial |
|
new dividends. |
|
\tparam TruncatedPolynomial The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
\tparam Reflect If \c false, read from the highest-order marked |
|
bit from a new dividend's bits and go down, as normal. Otherwise, |
|
proceed from the lowest-order bit and go up. |
|
*/ |
|
template < int Order, int SubOrder, boost::uintmax_t TruncatedPolynomial, |
|
bool Reflect > |
|
class crc_table_t |
|
{ |
|
public: |
|
/** \brief The type to check for register bit length |
|
|
|
This is a Boost integral constant indicating how many |
|
significant bits are in the remainder and (truncated) divisor. |
|
*/ |
|
typedef boost::integral_constant< int, Order > width_c; |
|
/** \brief The type to check for index-unit bit length |
|
|
|
This is a Boost integral constant indicating how many |
|
significant bits are in the trial new dividends. |
|
*/ |
|
typedef boost::integral_constant< int, SubOrder > unit_width_c; |
|
/** \brief The type of registers |
|
|
|
This is the output type for the partial-product map. |
|
*/ |
|
typedef typename boost::uint_t< Order >::fast value_type; |
|
/** \brief The type to check the divisor |
|
|
|
This is a Boost integral constant representing the (truncated) |
|
divisor. |
|
*/ |
|
typedef boost::integral_constant< value_type, TruncatedPolynomial > |
|
poly_c; |
|
/** \brief The type to check for reflection |
|
|
|
This is a Boost integral constant representing whether input |
|
units should be read in reverse order. |
|
*/ |
|
typedef boost::integral_constant< bool, Reflect > refin_c; |
|
/** \brief The type to check for map size |
|
|
|
This is a Boost integral constant representing the number of |
|
elements in the partial-product map, based on the unit size. |
|
*/ |
|
typedef high_bit_mask_c< SubOrder > table_size_c; |
|
/** \brief The type of the unit TO partial-product map |
|
|
|
This is the array type that takes units as the index and said unit's |
|
composite partial-product mask as the element. |
|
*/ |
|
typedef boost::array<value_type, table_size_c::value> array_type; |
|
/** \brief Create a global array for the mapping table |
|
|
|
Creates an instance of a partial-product array with this class's |
|
parameters. |
|
|
|
\return A reference to a immutable array giving the partial-product |
|
update XOR map for each potential sub-unit value. |
|
*/ |
|
static array_type const & get_table() |
|
{ |
|
static array_type const table = |
|
make_partial_xor_products_table<unit_width_c::value>( |
|
width_c::value, poly_c::value, refin_c::value ); |
|
|
|
return table; |
|
} |
|
}; |
|
|
|
/** \brief A mix-in class that handles direct (i.e. non-reflected) byte-fed |
|
table-driven CRC algorithms |
|
|
|
This class template adds member functions #augmented_crc_update and |
|
#crc_update to update remainders from new input bytes. The bytes aren't |
|
reflected before processing. |
|
|
|
\pre \c CHAR_BIT \<= \a Order \<= \c std\::numeric_limits\<uintmax_t\> |
|
\::digits |
|
|
|
\tparam Order The order of the modulo-2 polynomial remainder and one |
|
less than the divisor's order. |
|
\tparam TruncatedPolynomial The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
*/ |
|
template < int Order, boost::uintmax_t TruncatedPolynomial > |
|
class direct_byte_table_driven_crcs |
|
: public crc_table_t<Order, CHAR_BIT, TruncatedPolynomial, false> |
|
{ |
|
typedef crc_table_t<Order, CHAR_BIT, TruncatedPolynomial, false> |
|
base_type; |
|
|
|
public: |
|
typedef typename base_type::value_type value_type; |
|
typedef typename base_type::array_type array_type; |
|
|
|
/** \brief Compute the updated remainder after reading some bytes |
|
|
|
The implementation reads from a table to speed-up applying |
|
augmented-CRC updates byte-wise. |
|
|
|
\param remainder The pre-update remainder |
|
\param new_dividend_bytes The address where the new bytes start |
|
\param new_dividend_byte_count The number of new bytes to read |
|
|
|
\return The updated remainder |
|
*/ |
|
static value_type augmented_crc_update( value_type remainder, unsigned |
|
char const *new_dividend_bytes, std::size_t new_dividend_byte_count) |
|
{ |
|
static array_type const & table = base_type::get_table(); |
|
|
|
while ( new_dividend_byte_count-- ) |
|
{ |
|
// Locates the merged partial product based on the leading byte |
|
unsigned char const index = ( remainder >> (Order - CHAR_BIT) ) |
|
& UCHAR_MAX; |
|
|
|
// Complete the multi-bit modulo-2 polynomial division |
|
remainder <<= CHAR_BIT; |
|
remainder |= *new_dividend_bytes++; |
|
remainder ^= table.elems[ index ]; |
|
} |
|
|
|
return remainder; |
|
} |
|
|
|
/** \brief Compute the updated remainder after reading some bytes |
|
|
|
The implementation reads from a table to speed-up applying |
|
unaugmented-CRC updates byte-wise. |
|
|
|
\param remainder The pre-update remainder |
|
\param new_dividend_bytes The address where the new bytes start |
|
\param new_dividend_byte_count The number of new bytes to read |
|
|
|
\return The updated remainder |
|
*/ |
|
static value_type crc_update( value_type remainder, unsigned char |
|
const *new_dividend_bytes, std::size_t new_dividend_byte_count) |
|
{ |
|
static array_type const & table = base_type::get_table(); |
|
|
|
while ( new_dividend_byte_count-- ) |
|
{ |
|
// Locates the merged partial product based on comparing the |
|
// leading and incoming bytes |
|
unsigned char const index = ( (remainder >> ( Order - CHAR_BIT |
|
)) & UCHAR_MAX ) ^ *new_dividend_bytes++; |
|
|
|
// Complete the multi-bit altered modulo-2 polynomial division |
|
remainder <<= CHAR_BIT; |
|
remainder ^= table.elems[ index ]; |
|
} |
|
|
|
return remainder; |
|
} |
|
}; |
|
|
|
/** \brief A mix-in class that handles reflected byte-fed, table-driven CRC |
|
algorithms |
|
|
|
This class template adds member functions #augmented_crc_update and |
|
#crc_update to update remainders from new input bytes. The bytes are |
|
reflected before processing. |
|
|
|
\pre \c CHAR_BIT \<= \a Order \<= \c std\::numeric_limits\<uintmax_t\> |
|
\::digits |
|
|
|
\tparam Order The order of the modulo-2 polynomial remainder and one |
|
less than the divisor's order. |
|
\tparam TruncatedPolynomial The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
*/ |
|
template < int Order, boost::uintmax_t TruncatedPolynomial > |
|
class reflected_byte_table_driven_crcs |
|
: public crc_table_t<Order, CHAR_BIT, TruncatedPolynomial, true> |
|
{ |
|
typedef crc_table_t<Order, CHAR_BIT, TruncatedPolynomial, true> |
|
base_type; |
|
|
|
public: |
|
typedef typename base_type::value_type value_type; |
|
typedef typename base_type::array_type array_type; |
|
|
|
/** \brief Compute the updated remainder after reading some bytes |
|
|
|
The implementation reads from a table to speed-up applying |
|
reflecting augmented-CRC updates byte-wise. |
|
|
|
\param remainder The pre-update remainder; since the bytes are |
|
being reflected, this remainder also has to be reflected |
|
\param new_dividend_bytes The address where the new bytes start |
|
\param new_dividend_byte_count The number of new bytes to read |
|
|
|
\return The updated, reflected remainder |
|
*/ |
|
static value_type augmented_crc_update( value_type remainder, unsigned |
|
char const *new_dividend_bytes, std::size_t new_dividend_byte_count) |
|
{ |
|
static array_type const & table = base_type::get_table(); |
|
|
|
while ( new_dividend_byte_count-- ) |
|
{ |
|
// Locates the merged partial product based on the leading byte |
|
// (which is at the low-order end for reflected remainders) |
|
unsigned char const index = remainder & UCHAR_MAX; |
|
|
|
// Complete the multi-bit reflected modulo-2 polynomial division |
|
remainder >>= CHAR_BIT; |
|
remainder |= static_cast<value_type>( *new_dividend_bytes++ ) |
|
<< ( Order - CHAR_BIT ); |
|
remainder ^= table.elems[ index ]; |
|
} |
|
|
|
return remainder; |
|
} |
|
|
|
/** \brief Compute the updated remainder after reading some bytes |
|
|
|
The implementation reads from a table to speed-up applying |
|
reflected unaugmented-CRC updates byte-wise. |
|
|
|
\param remainder The pre-update remainder; since the bytes are |
|
being reflected, this remainder also has to be reflected |
|
\param new_dividend_bytes The address where the new bytes start |
|
\param new_dividend_byte_count The number of new bytes to read |
|
|
|
\return The updated, reflected remainder |
|
*/ |
|
static value_type crc_update( value_type remainder, unsigned char |
|
const *new_dividend_bytes, std::size_t new_dividend_byte_count) |
|
{ |
|
static array_type const & table = base_type::get_table(); |
|
|
|
while ( new_dividend_byte_count-- ) |
|
{ |
|
// Locates the merged partial product based on comparing the |
|
// leading and incoming bytes |
|
unsigned char const index = ( remainder & UCHAR_MAX ) ^ |
|
*new_dividend_bytes++; |
|
|
|
// Complete the multi-bit reflected altered modulo-2 polynomial |
|
// division |
|
remainder >>= CHAR_BIT; |
|
remainder ^= table.elems[ index ]; |
|
} |
|
|
|
return remainder; |
|
} |
|
}; |
|
|
|
/** \brief Mix-in class for byte-fed, table-driven CRC algorithms with |
|
parameter values at least a byte in width |
|
|
|
This class template adds member functions #augmented_crc_update and |
|
#crc_update to update remainders from new input bytes. The bytes may be |
|
reflected before processing, controlled by a compile-time parameter. |
|
|
|
\pre \c CHAR_BIT \<= \a Order \<= \c std\::numeric_limits\<uintmax_t\> |
|
\::digits |
|
|
|
\tparam Order The order of the modulo-2 polynomial remainder and one |
|
less than the divisor's order. |
|
\tparam TruncatedPolynomial The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
\tparam Reflect If \c false, read from the highest-order bit from a new |
|
input byte and go down, as normal. Otherwise, proceed from the |
|
lowest-order bit and go up. |
|
*/ |
|
template < int Order, boost::uintmax_t TruncatedPolynomial, bool Reflect > |
|
class byte_table_driven_crcs |
|
: public boost::conditional< Reflect, |
|
reflected_byte_table_driven_crcs<Order, TruncatedPolynomial>, |
|
direct_byte_table_driven_crcs<Order, TruncatedPolynomial> >::type |
|
{ }; |
|
|
|
/** \brief A mix-in class that handles direct (i.e. non-reflected) byte-fed |
|
CRC algorithms for sub-byte parameters |
|
|
|
This class template adds member functions #augmented_crc_update and |
|
#crc_update to update remainders from new input bytes. The bytes aren't |
|
reflected before processing. |
|
|
|
\pre 0 \< \a Order \< \c CHAR_BIT |
|
|
|
\tparam Order The order of the modulo-2 polynomial remainder and one |
|
less than the divisor's order. |
|
\tparam TruncatedPolynomial The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
*/ |
|
template < int Order, boost::uintmax_t TruncatedPolynomial > |
|
class direct_sub_byte_crcs |
|
: public crc_table_t<Order, Order, TruncatedPolynomial, false> |
|
{ |
|
typedef crc_table_t<Order, Order, TruncatedPolynomial, false> |
|
base_type; |
|
|
|
public: |
|
typedef typename base_type::width_c width_c; |
|
typedef typename base_type::value_type value_type; |
|
typedef typename base_type::poly_c poly_c; |
|
typedef typename base_type::array_type array_type; |
|
|
|
/** \brief Compute the updated remainder after reading some bytes |
|
|
|
The implementation reads from a table to speed-up applying |
|
augmented-CRC updates byte-wise. |
|
|
|
\param remainder The pre-update remainder |
|
\param new_dividend_bytes The address where the new bytes start |
|
\param new_dividend_byte_count The number of new bytes to read |
|
|
|
\return The updated remainder |
|
|
|
\todo Use this function somewhere so I can test it. |
|
*/ |
|
static value_type augmented_crc_update( value_type remainder, unsigned |
|
char const *new_dividend_bytes, std::size_t new_dividend_byte_count) |
|
{ |
|
//static array_type const & table = base_type::get_table(); |
|
|
|
while ( new_dividend_byte_count-- ) |
|
{ |
|
// Without a table, process each byte explicitly |
|
augmented_crc_modulo_word_update( width_c::value, remainder, |
|
*new_dividend_bytes++, poly_c::value, CHAR_BIT, false ); |
|
} |
|
|
|
return remainder; |
|
} |
|
|
|
/** \brief Compute the updated remainder after reading some bytes |
|
|
|
The implementation reads from a table to speed-up applying |
|
unaugmented-CRC updates byte-wise. |
|
|
|
\param remainder The pre-update remainder |
|
\param new_dividend_bytes The address where the new bytes start |
|
\param new_dividend_byte_count The number of new bytes to read |
|
|
|
\return The updated remainder |
|
*/ |
|
static value_type crc_update( value_type remainder, unsigned char |
|
const *new_dividend_bytes, std::size_t new_dividend_byte_count) |
|
{ |
|
//static array_type const & table = base_type::get_table(); |
|
|
|
while ( new_dividend_byte_count-- ) |
|
{ |
|
// Without a table, process each byte explicitly |
|
crc_modulo_word_update( width_c::value, remainder, |
|
*new_dividend_bytes++, poly_c::value, CHAR_BIT, false ); |
|
} |
|
|
|
return remainder; |
|
} |
|
}; |
|
|
|
/** \brief A mix-in class that handles reflected byte-fed, CRC algorithms |
|
for sub-byte parameters |
|
|
|
This class template adds member functions #augmented_crc_update and |
|
#crc_update to update remainders from new input bytes. The bytes are |
|
reflected before processing. |
|
|
|
\pre 0 \< \a Order \< \c CHAR_BIT |
|
|
|
\tparam Order The order of the modulo-2 polynomial remainder and one |
|
less than the divisor's order. |
|
\tparam TruncatedPolynomial The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
*/ |
|
template < int Order, boost::uintmax_t TruncatedPolynomial > |
|
class reflected_sub_byte_crcs |
|
: public crc_table_t<Order, Order, TruncatedPolynomial, true> |
|
{ |
|
typedef crc_table_t<Order, Order, TruncatedPolynomial, true> |
|
base_type; |
|
|
|
public: |
|
typedef typename base_type::width_c width_c; |
|
typedef typename base_type::value_type value_type; |
|
typedef typename base_type::poly_c poly_c; |
|
typedef typename base_type::array_type array_type; |
|
|
|
/** \brief Compute the updated remainder after reading some bytes |
|
|
|
The implementation reads from a table to speed-up applying |
|
reflecting augmented-CRC updates byte-wise. |
|
|
|
\param remainder The pre-update remainder; since the bytes are |
|
being reflected, this remainder also has to be reflected |
|
\param new_dividend_bytes The address where the new bytes start |
|
\param new_dividend_byte_count The number of new bytes to read |
|
|
|
\return The updated, reflected remainder |
|
|
|
\todo Use this function somewhere so I can test it. |
|
*/ |
|
static value_type augmented_crc_update( value_type remainder, unsigned |
|
char const *new_dividend_bytes, std::size_t new_dividend_byte_count) |
|
{ |
|
//static array_type const & table = base_type::get_table(); |
|
|
|
remainder = reflect_sub_byte( remainder, width_c::value ); |
|
while ( new_dividend_byte_count-- ) |
|
{ |
|
// Without a table, process each byte explicitly |
|
augmented_crc_modulo_word_update( width_c::value, remainder, |
|
*new_dividend_bytes++, poly_c::value, CHAR_BIT, true ); |
|
} |
|
remainder = reflect_sub_byte( remainder, width_c::value ); |
|
|
|
return remainder; |
|
} |
|
|
|
/** \brief Compute the updated remainder after reading some bytes |
|
|
|
The implementation reads from a table to speed-up applying |
|
reflected unaugmented-CRC updates byte-wise. |
|
|
|
\param remainder The pre-update remainder; since the bytes are |
|
being reflected, this remainder also has to be reflected |
|
\param new_dividend_bytes The address where the new bytes start |
|
\param new_dividend_byte_count The number of new bytes to read |
|
|
|
\return The updated, reflected remainder |
|
*/ |
|
static value_type crc_update( value_type remainder, unsigned char |
|
const *new_dividend_bytes, std::size_t new_dividend_byte_count) |
|
{ |
|
//static array_type const & table = base_type::get_table(); |
|
|
|
remainder = reflect_sub_byte( remainder, width_c::value ); |
|
while ( new_dividend_byte_count-- ) |
|
{ |
|
// Without a table, process each byte explicitly |
|
crc_modulo_word_update( width_c::value, remainder, |
|
*new_dividend_bytes++, poly_c::value, CHAR_BIT, true ); |
|
} |
|
remainder = reflect_sub_byte( remainder, width_c::value ); |
|
|
|
return remainder; |
|
} |
|
}; |
|
|
|
/** \brief Mix-in class for byte-fed, table-driven CRC algorithms with |
|
sub-byte parameters |
|
|
|
This class template adds member functions #augmented_crc_update and |
|
#crc_update to update remainders from new input bytes. The bytes may be |
|
reflected before processing, controlled by a compile-time parameter. |
|
|
|
\pre 0 \< \a Order \< \c CHAR_BIT |
|
|
|
\tparam Order The order of the modulo-2 polynomial remainder and one |
|
less than the divisor's order. |
|
\tparam TruncatedPolynomial The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
\tparam Reflect If \c false, read from the highest-order bit from a new |
|
input byte and go down, as normal. Otherwise, proceed from the |
|
lowest-order bit and go up. |
|
*/ |
|
template < int Order, boost::uintmax_t TruncatedPolynomial, bool Reflect > |
|
class sub_byte_crcs |
|
: public boost::conditional< Reflect, |
|
reflected_sub_byte_crcs<Order, TruncatedPolynomial>, |
|
direct_sub_byte_crcs<Order, TruncatedPolynomial> >::type |
|
{ }; |
|
|
|
/** This class template adds member functions #augmented_crc_update and |
|
#crc_update to update remainders from new input bytes. The bytes may be |
|
reflected before processing, controlled by a compile-time parameter. |
|
|
|
\pre 0 \< \a Order \<= \c std\::numeric_limits\<uintmax_t\>\::digits |
|
|
|
\tparam Order The order of the modulo-2 polynomial remainder and one |
|
less than the divisor's order. |
|
\tparam TruncatedPolynomial The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always |
|
assumed to be 1. |
|
\tparam Reflect If \c false, read from the highest-order bit from a new |
|
input byte and go down, as normal. Otherwise, proceed from the |
|
lowest-order bit and go up. |
|
\tparam Id An extra differentiator if multiple copies of this class |
|
template are mixed-in as base classes. Defaults to 0 if omitted. |
|
*/ |
|
template < int Order, boost::uintmax_t TruncatedPolynomial, bool Reflect, |
|
int Id > |
|
class crc_driver |
|
: public boost::conditional< (Order < CHAR_BIT), sub_byte_crcs<Order, |
|
TruncatedPolynomial, Reflect>, byte_table_driven_crcs<Order, |
|
TruncatedPolynomial, Reflect> >::type |
|
{ |
|
public: |
|
/** \brief The type to check for ID |
|
|
|
This is a Boost integral constant indicating what ID number this |
|
instantiation used. |
|
*/ |
|
typedef boost::integral_constant<int, Id> id_type; |
|
}; |
|
|
|
|
|
} // namespace detail |
|
//! \endcond |
|
|
|
|
|
// Simple CRC class function definitions -----------------------------------// |
|
|
|
/** Constructs a \c crc_basic object with at least the required parameters to a |
|
particular CRC formula to be processed upon receiving input. |
|
|
|
\param[in] truncated_polynomial The lowest coefficients of the divisor |
|
polynomial. The highest-order coefficient is omitted and always assumed |
|
to be 1. (\e Poly from the RMCA) |
|
\param[in] initial_remainder The (unaugmented) initial state of the |
|
polynomial remainder. Defaults to \c 0 if omitted. (\e Init from the |
|
RMCA) |
|
\param[in] final_xor_value The (XOR) bit-mask to be applied to the output |
|
remainder, after possible reflection but before returning. Defaults to |
|
\c 0 (i.e. no bit changes) if omitted. (\e XorOut from the RMCA) |
|
\param[in] reflect_input If \c true, input bytes are read lowest-order bit |
|
first, otherwise highest-order bit first. Defaults to \c false if |
|
omitted. (\e RefIn from the RMCA) |
|
\param[in] reflect_remainder If \c true, the output remainder is reflected |
|
before the XOR-mask. Defaults to \c false if omitted. (\e RefOut from |
|
the RMCA) |
|
|
|
\post <code><var>truncated_polynomial</var> == |
|
this->get_truncated_polynominal()</code> |
|
\post <code><var>initial_remainder</var> == |
|
this->get_initial_remainder()</code> |
|
\post <code><var>final_xor_value</var> == |
|
this->get_final_xor_value()</code> |
|
\post <code><var>reflect_input</var> == |
|
this->get_reflect_input()</code> |
|
\post <code><var>reflect_remainder</var> == |
|
this->get_reflect_remainder()</code> |
|
\post <code><var>initial_remainder</var> == |
|
this->get_interim_remainder()</code> |
|
\post <code>(<var>reflect_remainder</var> ? |
|
REFLECT(<var>initial_remainder</var>) : <var>initial_remainder</var>) ^ |
|
<var>final_xor_value</var> == this->checksum()</code> |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
crc_basic<Bits>::crc_basic |
|
( |
|
value_type truncated_polynomial, |
|
value_type initial_remainder, // = 0 |
|
value_type final_xor_value, // = 0 |
|
bool reflect_input, // = false |
|
bool reflect_remainder // = false |
|
) |
|
: rem_( initial_remainder ), poly_( truncated_polynomial ) |
|
, init_( initial_remainder ), final_( final_xor_value ) |
|
, rft_in_( reflect_input ), rft_out_( reflect_remainder ) |
|
{ |
|
} |
|
|
|
/** Returns a representation of the polynomial divisor. The value of the |
|
2<sup>i</sup> bit is the value of the coefficient of the polynomial's |
|
x<sup>i</sup> term. The omitted bit for x<sup>(#bit_count)</sup> term is |
|
always 1. |
|
|
|
\return The bit-packed list of coefficients. If the bit-length of |
|
#value_type exceeds #bit_count, the values of higher-placed bits should be |
|
ignored (even any for x<sup>(#bit_count)</sup>) since they're unregulated. |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
typename crc_basic<Bits>::value_type |
|
crc_basic<Bits>::get_truncated_polynominal |
|
( |
|
) const |
|
{ |
|
return poly_; |
|
} |
|
|
|
/** Returns a representation of the polynomial remainder before any input has |
|
been submitted. The value of the 2<sup>i</sup> bit is the value of the |
|
coefficient of the polynomial's x<sup>i</sup> term. |
|
|
|
\return The bit-packed list of coefficients. If the bit-length of |
|
#value_type exceeds #bit_count, the values of higher-placed bits should be |
|
ignored since they're unregulated. |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
typename crc_basic<Bits>::value_type |
|
crc_basic<Bits>::get_initial_remainder |
|
( |
|
) const |
|
{ |
|
return init_; |
|
} |
|
|
|
/** Returns the mask to be used during creation of a checksum. The mask is used |
|
for an exclusive-or (XOR) operation applied bit-wise to the interim |
|
remainder representation (after any reflection, if #get_reflect_remainder() |
|
returns \c true). |
|
|
|
\return The bit-mask. If the bit-length of #value_type exceeds #bit_count, |
|
the values of higher-placed bits should be ignored since they're |
|
unregulated. |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
typename crc_basic<Bits>::value_type |
|
crc_basic<Bits>::get_final_xor_value |
|
( |
|
) const |
|
{ |
|
return final_; |
|
} |
|
|
|
/** Returns a whether or not a submitted byte will be \"reflected\" before it is |
|
used to update the interim remainder. Only the byte-wise operations |
|
#process_byte, #process_block, and #process_bytes are affected. |
|
|
|
\retval true Input bytes will be read starting from the lowest-order bit. |
|
\retval false Input bytes will be read starting from the highest-order bit. |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
bool |
|
crc_basic<Bits>::get_reflect_input |
|
( |
|
) const |
|
{ |
|
return rft_in_; |
|
} |
|
|
|
/** Indicates if the interim remainder will be \"reflected\" before it is passed |
|
to the XOR-mask stage when returning a checksum. |
|
|
|
\retval true The interim remainder is reflected before further work. |
|
\retval false The interim remainder is applied to the XOR-mask as-is. |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
bool |
|
crc_basic<Bits>::get_reflect_remainder |
|
( |
|
) const |
|
{ |
|
return rft_out_; |
|
} |
|
|
|
/** Returns a representation of the polynomial remainder after all the input |
|
submissions since construction or the last #reset call. The value of the |
|
2<sup>i</sup> bit is the value of the coefficient of the polynomial's |
|
x<sup>i</sup> term. If CRC processing gets interrupted here, retain the |
|
value returned, and use it to start up the next CRC computer where you left |
|
off (with #reset(value_type) or construction). The next computer has to |
|
have its other parameters compatible with this computer. |
|
|
|
\return The bit-packed list of coefficients. If the bit-length of |
|
#value_type exceeds #bit_count, the values of higher-placed bits should be |
|
ignored since they're unregulated. No output processing (reflection or |
|
XOR mask) has been applied to the value. |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
typename crc_basic<Bits>::value_type |
|
crc_basic<Bits>::get_interim_remainder |
|
( |
|
) const |
|
{ |
|
return rem_ & detail::low_bits_mask_c<bit_count>::value; |
|
} |
|
|
|
/** Changes the interim polynomial remainder to \a new_rem, purging any |
|
influence previously submitted input has had. The value of the |
|
2<sup>i</sup> bit is the value of the coefficient of the polynomial's |
|
x<sup>i</sup> term. |
|
|
|
\param[in] new_rem The (unaugmented) state of the polynomial remainder |
|
starting from this point, with no output processing applied. |
|
|
|
\post <code><var>new_rem</var> == this->get_interim_remainder()</code> |
|
\post <code>((this->get_reflect_remainder() ? |
|
REFLECT(<var>new_rem</var>) : <var>new_rem</var>) ^ |
|
this->get_final_xor_value()) == this->checksum()</code> |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
void |
|
crc_basic<Bits>::reset |
|
( |
|
value_type new_rem |
|
) |
|
{ |
|
rem_ = new_rem; |
|
} |
|
|
|
/** Changes the interim polynomial remainder to the initial remainder given |
|
during construction, purging any influence previously submitted input has |
|
had. The value of the 2<sup>i</sup> bit is the value of the coefficient of |
|
the polynomial's x<sup>i</sup> term. |
|
|
|
\post <code>this->get_initial_remainder() == |
|
this->get_interim_remainder()</code> |
|
\post <code>((this->get_reflect_remainder() ? |
|
REFLECT(this->get_initial_remainder()) : |
|
this->get_initial_remainder()) ^ this->get_final_xor_value()) |
|
== this->checksum()</code> |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
void |
|
crc_basic<Bits>::reset |
|
( |
|
) |
|
{ |
|
this->reset( this->get_initial_remainder() ); |
|
} |
|
|
|
/** Updates the interim remainder with a single altered-CRC-division step. |
|
|
|
\param[in] bit The new input bit. |
|
|
|
\post The interim remainder is updated though a modulo-2 polynomial |
|
division, where the division steps are altered for unaugmented CRCs. |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
void |
|
crc_basic<Bits>::process_bit |
|
( |
|
bool bit |
|
) |
|
{ |
|
detail::crc_modulo_update( bit_count, rem_, bit, poly_ ); |
|
} |
|
|
|
/** Updates the interim remainder with several altered-CRC-division steps. Each |
|
bit is processed separately, starting from the one at the |
|
2<sup><var>bit_length</var> - 1</sup> place, then proceeding down to the |
|
lowest-placed bit. Any order imposed by |
|
<code>this->get_reflect_input()</code> is ignored. |
|
|
|
\pre 0 \< \a bit_length \<= \c CHAR_BIT |
|
|
|
\param[in] bits The byte containing the new input bits. |
|
\param[in] bit_length The number of bits in the byte to be read. |
|
|
|
\post The interim remainder is updated though \a bit_length modulo-2 |
|
polynomial divisions, where the division steps are altered for unaugmented |
|
CRCs. |
|
*/ |
|
template < std::size_t Bits > |
|
void |
|
crc_basic<Bits>::process_bits |
|
( |
|
unsigned char bits, |
|
std::size_t bit_length |
|
) |
|
{ |
|
// ignore the bits above the ones we want |
|
bits <<= CHAR_BIT - bit_length; |
|
|
|
// compute the CRC for each bit, starting with the upper ones |
|
unsigned char const high_bit_mask = 1u << ( CHAR_BIT - 1u ); |
|
for ( std::size_t i = bit_length ; i > 0u ; --i, bits <<= 1u ) |
|
{ |
|
process_bit( static_cast<bool>(bits & high_bit_mask) ); |
|
} |
|
} |
|
|
|
/** Updates the interim remainder with a byte's worth of altered-CRC-division |
|
steps. The bits within the byte are processed from the highest place down |
|
if <code>this->get_reflect_input()</code> is \c false, and lowest place |
|
up otherwise. |
|
|
|
\param[in] byte The new input byte. |
|
|
|
\post The interim remainder is updated though \c CHAR_BIT modulo-2 |
|
polynomial divisions, where the division steps are altered for unaugmented |
|
CRCs. |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
void |
|
crc_basic<Bits>::process_byte |
|
( |
|
unsigned char byte |
|
) |
|
{ |
|
process_bits( (rft_in_ ? detail::reflect_byte( byte ) : byte), CHAR_BIT ); |
|
} |
|
|
|
/** Updates the interim remainder with several bytes' worth of |
|
altered-CRC-division steps. The bits within each byte are processed from |
|
the highest place down if <code>this->get_reflect_input()</code> is |
|
\c false, and lowest place up otherwise. The bytes themselves are processed |
|
starting from the one pointed by \a bytes_begin until \a bytes_end is |
|
reached through forward iteration, treating the two pointers as if they |
|
point to <code>unsigned char</code> objects. |
|
|
|
\pre \a bytes_end has to equal \a bytes_begin if the latter is \c NULL or |
|
otherwise doesn't point to a valid buffer. |
|
\pre \a bytes_end, if not equal to \a bytes_begin, has to point within or |
|
one-byte-past the same buffer \a bytes_begin points into. |
|
\pre \a bytes_end has to be reachable from \a bytes_begin through a finite |
|
number of forward byte-pointer increments. |
|
|
|
\param[in] bytes_begin The address where the memory block begins. |
|
\param[in] bytes_end Points to one-byte past the address of the memory |
|
block's last byte, or \a bytes_begin if no bytes are to be read. |
|
|
|
\post The interim remainder is updated though <code>CHAR_BIT * (((unsigned |
|
char const *) bytes_end) - ((unsigned char const *) bytes_begin))</code> |
|
modulo-2 polynomial divisions, where the division steps are altered for |
|
unaugmented CRCs. |
|
*/ |
|
template < std::size_t Bits > |
|
void |
|
crc_basic<Bits>::process_block |
|
( |
|
void const * bytes_begin, |
|
void const * bytes_end |
|
) |
|
{ |
|
for ( unsigned char const * p |
|
= static_cast<unsigned char const *>(bytes_begin) ; p < bytes_end ; ++p ) |
|
{ |
|
process_byte( *p ); |
|
} |
|
} |
|
|
|
/** Updates the interim remainder with several bytes' worth of |
|
altered-CRC-division steps. The bits within each byte are processed from |
|
the highest place down if <code>this->get_reflect_input()</code> is |
|
\c false, and lowest place up otherwise. The bytes themselves are processed |
|
starting from the one pointed by \a buffer, forward-iterated (as if the |
|
pointed-to objects were of <code>unsigned char</code>) until \a byte_count |
|
bytes are read. |
|
|
|
\pre \a byte_count has to equal 0 if \a buffer is \c NULL or otherwise |
|
doesn't point to valid memory. |
|
\pre If \a buffer points within valid memory, then that block has to have |
|
at least \a byte_count more valid bytes allocated from that point. |
|
|
|
\param[in] buffer The address where the memory block begins. |
|
\param[in] byte_count The number of bytes in the memory block. |
|
|
|
\post The interim remainder is updated though <code>CHAR_BIT * |
|
<var>byte_count</var></code> modulo-2 polynomial divisions, where the |
|
division steps are altered for unaugmented CRCs. |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
void |
|
crc_basic<Bits>::process_bytes |
|
( |
|
void const * buffer, |
|
std::size_t byte_count |
|
) |
|
{ |
|
unsigned char const * const b = static_cast<unsigned char const *>( |
|
buffer ); |
|
|
|
process_block( b, b + byte_count ); |
|
} |
|
|
|
/** Computes the checksum of all the submitted bits since construction or the |
|
last call to #reset. The checksum will be the raw checksum, i.e. the |
|
(interim) remainder after all the modulo-2 polynomial division, plus any |
|
output processing. |
|
|
|
\return <code>(this->get_reflect_remainder() ? |
|
REFLECT(this->get_interim_remainder()) : |
|
this->get_interim_remainder()) ^ this->get_final_xor_value()</code> |
|
|
|
\note Since checksums are meant to be compared, any higher-placed bits |
|
(when the bit-length of #value_type exceeds #bit_count) will be set to 0. |
|
*/ |
|
template < std::size_t Bits > |
|
inline |
|
typename crc_basic<Bits>::value_type |
|
crc_basic<Bits>::checksum |
|
( |
|
) const |
|
{ |
|
return ( (rft_out_ ? detail::reflect_unsigned( rem_, bit_count ) : |
|
rem_) ^ final_ ) & detail::low_bits_mask_c<bit_count>::value; |
|
} |
|
|
|
|
|
// Optimized CRC class function definitions --------------------------------// |
|
|
|
// Macro to compact code |
|
#define BOOST_CRC_OPTIMAL_NAME crc_optimal<Bits, TruncPoly, InitRem, \ |
|
FinalXor, ReflectIn, ReflectRem> |
|
|
|
/** Constructs a \c crc_optimal object with a particular CRC formula to be |
|
processed upon receiving input. The initial remainder may be overridden. |
|
|
|
\param[in] init_rem The (unaugmented) initial state of the polynomial |
|
remainder. Defaults to #initial_remainder if omitted. |
|
|
|
\post <code>#truncated_polynominal == |
|
this->get_truncated_polynominal()</code> |
|
\post <code>#initial_remainder == this->get_initial_remainder()</code> |
|
\post <code>#final_xor_value == this->get_final_xor_value()</code> |
|
\post <code>#reflect_input == this->get_reflect_input()</code> |
|
\post <code>#reflect_remainder == this->get_reflect_remainder()</code> |
|
\post <code><var>init_rem</var> == this->get_interim_remainder()</code> |
|
\post <code>(#reflect_remainder ? REFLECT(<var>init_rem</var>) : |
|
<var>init_rem</var>) ^ #final_xor_value == this->checksum()</code> |
|
*/ |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
BOOST_CRC_OPTIMAL_NAME::crc_optimal |
|
( |
|
value_type init_rem // = initial_remainder |
|
) |
|
: rem_( reflect_i_type::reflect_q(init_rem) ) |
|
{ |
|
} |
|
|
|
//! \copydetails boost::crc_basic::get_truncated_polynominal |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
typename BOOST_CRC_OPTIMAL_NAME::value_type |
|
BOOST_CRC_OPTIMAL_NAME::get_truncated_polynominal |
|
( |
|
) const |
|
{ |
|
return truncated_polynominal; |
|
} |
|
|
|
//! \copydetails boost::crc_basic::get_initial_remainder |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
typename BOOST_CRC_OPTIMAL_NAME::value_type |
|
BOOST_CRC_OPTIMAL_NAME::get_initial_remainder |
|
( |
|
) const |
|
{ |
|
return initial_remainder; |
|
} |
|
|
|
//! \copydetails boost::crc_basic::get_final_xor_value |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
typename BOOST_CRC_OPTIMAL_NAME::value_type |
|
BOOST_CRC_OPTIMAL_NAME::get_final_xor_value |
|
( |
|
) const |
|
{ |
|
return final_xor_value; |
|
} |
|
|
|
//! \copydetails boost::crc_basic::get_reflect_input |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
bool |
|
BOOST_CRC_OPTIMAL_NAME::get_reflect_input |
|
( |
|
) const |
|
{ |
|
return reflect_input; |
|
} |
|
|
|
//! \copydetails boost::crc_basic::get_reflect_remainder |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
bool |
|
BOOST_CRC_OPTIMAL_NAME::get_reflect_remainder |
|
( |
|
) const |
|
{ |
|
return reflect_remainder; |
|
} |
|
|
|
//! \copydetails boost::crc_basic::get_interim_remainder |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
typename BOOST_CRC_OPTIMAL_NAME::value_type |
|
BOOST_CRC_OPTIMAL_NAME::get_interim_remainder |
|
( |
|
) const |
|
{ |
|
// Interim remainder should be _un_-reflected, so we have to undo it. |
|
return reflect_i_type::reflect_q( rem_ ) & |
|
detail::low_bits_mask_c<bit_count>::value; |
|
} |
|
|
|
/** Changes the interim polynomial remainder to \a new_rem, purging any |
|
influence previously submitted input has had. The value of the |
|
2<sup>i</sup> bit is the value of the coefficient of the polynomial's |
|
x<sup>i</sup> term. |
|
|
|
\param[in] new_rem The (unaugmented) state of the polynomial remainder |
|
starting from this point, with no output processing applied. Defaults to |
|
<code>this->get_initial_remainder()</code> if omitted. |
|
|
|
\post <code><var>new_rem</var> == this->get_interim_remainder()</code> |
|
\post <code>((this->get_reflect_remainder() ? |
|
REFLECT(<var>new_rem</var>) : <var>new_rem</var>) ^ |
|
this->get_final_xor_value()) == this->checksum()</code> |
|
*/ |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
void |
|
BOOST_CRC_OPTIMAL_NAME::reset |
|
( |
|
value_type new_rem // = initial_remainder |
|
) |
|
{ |
|
rem_ = reflect_i_type::reflect_q( new_rem ); |
|
} |
|
|
|
/** \copydetails boost::crc_basic::process_byte |
|
|
|
\note Any modulo-2 polynomial divisions may use a table of pre-computed |
|
remainder changes (as XOR masks) to speed computation when reading data |
|
byte-wise. |
|
*/ |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
void |
|
BOOST_CRC_OPTIMAL_NAME::process_byte |
|
( |
|
unsigned char byte |
|
) |
|
{ |
|
process_bytes( &byte, sizeof(byte) ); |
|
} |
|
|
|
/** \copydetails boost::crc_basic::process_block |
|
|
|
\note Any modulo-2 polynomial divisions may use a table of pre-computed |
|
remainder changes (as XOR masks) to speed computation when reading data |
|
byte-wise. |
|
*/ |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
void |
|
BOOST_CRC_OPTIMAL_NAME::process_block |
|
( |
|
void const * bytes_begin, |
|
void const * bytes_end |
|
) |
|
{ |
|
process_bytes( bytes_begin, static_cast<unsigned char const *>(bytes_end) - |
|
static_cast<unsigned char const *>(bytes_begin) ); |
|
} |
|
|
|
/** \copydetails boost::crc_basic::process_bytes |
|
|
|
\note Any modulo-2 polynomial divisions may use a table of pre-computed |
|
remainder changes (as XOR masks) to speed computation when reading data |
|
byte-wise. |
|
*/ |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
void |
|
BOOST_CRC_OPTIMAL_NAME::process_bytes |
|
( |
|
void const * buffer, |
|
std::size_t byte_count |
|
) |
|
{ |
|
rem_ = crc_table_type::crc_update( rem_, static_cast<unsigned char const |
|
*>(buffer), byte_count ); |
|
} |
|
|
|
//! \copydetails boost::crc_basic::checksum |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
typename BOOST_CRC_OPTIMAL_NAME::value_type |
|
BOOST_CRC_OPTIMAL_NAME::checksum |
|
( |
|
) const |
|
{ |
|
return ( reflect_o_type::reflect_q(rem_) ^ get_final_xor_value() ) |
|
& detail::low_bits_mask_c<bit_count>::value; |
|
} |
|
|
|
/** Updates the interim remainder with a byte's worth of altered-CRC-division |
|
steps. The bits within the byte are processed from the highest place down |
|
if <code>this->get_reflect_input()</code> is \c false, and lowest place |
|
up otherwise. This function is meant to present a function-object interface |
|
to code that wants to process a stream of bytes with |
|
<code>std::for_each</code> or similar range-processing algorithms. Since |
|
some of these algorithms takes their function object by value, make sure to |
|
copy back the result to this object so the updates can be remembered. |
|
|
|
\param[in] byte The new input byte. |
|
|
|
\post The interim remainder is updated though \c CHAR_BIT modulo-2 |
|
polynomial divisions, where the division steps are altered for unaugmented |
|
CRCs. |
|
|
|
\note Any modulo-2 polynomial divisions may use a table of pre-computed |
|
remainder changes (as XOR masks) to speed computation when reading data |
|
byte-wise. |
|
*/ |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
void |
|
BOOST_CRC_OPTIMAL_NAME::operator () |
|
( |
|
unsigned char byte |
|
) |
|
{ |
|
process_byte( byte ); |
|
} |
|
|
|
/** Computes the checksum of all the submitted bits since construction or the |
|
last call to #reset. The checksum will be the raw checksum, i.e. the |
|
(interim) remainder after all the modulo-2 polynomial division, plus any |
|
output processing. This function is meant to present a function-object |
|
interface to code that wants to receive data like |
|
<code>std::generate_n</code> or similar data-processing algorithms. Note |
|
that if this object is used as a generator multiple times without an |
|
intervening mutating operation, the same value will always be returned. |
|
|
|
\return <code>(this->get_reflect_remainder() ? |
|
REFLECT(this->get_interim_remainder()) : |
|
this->get_interim_remainder()) ^ this->get_final_xor_value()</code> |
|
|
|
\note Since checksums are meant to be compared, any higher-placed bits |
|
(when the bit-length of #value_type exceeds #bit_count) will be set to 0. |
|
*/ |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
typename BOOST_CRC_OPTIMAL_NAME::value_type |
|
BOOST_CRC_OPTIMAL_NAME::operator () |
|
( |
|
) const |
|
{ |
|
return checksum(); |
|
} |
|
|
|
|
|
// CRC computation function definition -------------------------------------// |
|
|
|
/** Computes the polynomial remainder of a CRC run, assuming that \a buffer and |
|
\a byte_count describe a memory block representing the polynomial dividend. |
|
The division steps are altered so the result directly gives a checksum, |
|
without need to augment the memory block with scratch-space bytes. The |
|
first byte is considered the highest order, going down for subsequent bytes. |
|
|
|
\pre 0 \< \a Bits \<= \c std\::numeric_limits\<uintmax_t\>\::digits |
|
|
|
\tparam Bits The order of the modulo-2 polynomial divisor. (\e Width from |
|
the RMCA) |
|
\tparam TruncPoly The lowest coefficients of the divisor polynomial. The |
|
highest-order coefficient is omitted and always assumed to be 1. |
|
(\e Poly from the RMCA) |
|
\tparam InitRem The (unaugmented) initial state of the polynomial |
|
remainder. (\e Init from the RMCA) |
|
\tparam FinalXor The (XOR) bit-mask to be applied to the output remainder, |
|
after possible reflection but before returning. (\e XorOut from the RMCA) |
|
\tparam ReflectIn If \c True, input bytes are read lowest-order bit first, |
|
otherwise highest-order bit first. (\e RefIn from the RMCA) |
|
\tparam ReflectRem If \c True, the output remainder is reflected before the |
|
XOR-mask. (\e RefOut from the RMCA) |
|
|
|
\param[in] buffer The address where the memory block begins. |
|
\param[in] byte_count The number of bytes in the memory block. |
|
|
|
\return The checksum, which is the last (interim) remainder plus any output |
|
processing. |
|
|
|
\note Unaugmented-style CRC runs perform modulo-2 polynomial division in |
|
an altered order. The trailing \a Bits number of zero-valued bits needed |
|
to extracted an (unprocessed) checksum is virtually moved to near the |
|
beginning of the message. This is OK since the XOR operation is |
|
commutative and associative. It also means that you can get a checksum |
|
anytime. Since data is being read byte-wise, a table of pre-computed |
|
remainder changes (as XOR masks) can be used to speed computation. |
|
|
|
*/ |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
|
BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
|
bool ReflectIn, bool ReflectRem > |
|
inline |
|
typename uint_t<Bits>::fast |
|
crc |
|
( |
|
void const * buffer, |
|
std::size_t byte_count |
|
) |
|
{ |
|
BOOST_CRC_OPTIMAL_NAME computer; |
|
computer.process_bytes( buffer, byte_count ); |
|
return computer.checksum(); |
|
} |
|
|
|
|
|
// Augmented-message CRC computation function definition -------------------// |
|
|
|
/** Computes the polynomial remainder of a CRC run, assuming that \a buffer and |
|
\a byte_count describe a memory block representing the polynomial dividend. |
|
The first byte is considered the highest order, going down for subsequent |
|
bytes. Within a byte, the highest-order bit is read first (corresponding to |
|
\e RefIn = \c False in the RMCA). Check the other parts of this function's |
|
documentation to see how a checksum can be gained and/or used. |
|
|
|
\pre 0 \< \a Bits \<= \c std\::numeric_limit\<uintmax_t\>\::digits |
|
|
|
\tparam Bits The order of the modulo-2 polynomial divisor. (\e Width from |
|
the RMCA) |
|
\tparam TruncPoly The lowest coefficients of the divisor polynomial. The |
|
highest-order coefficient is omitted and always assumed to be 1. |
|
(\e Poly from the RMCA) |
|
|
|
\param[in] buffer The address where the memory block begins. |
|
\param[in] byte_count The number of bytes in the memory block. |
|
\param[in] initial_remainder The initial state of the polynomial |
|
remainder, defaulting to zero if omitted. If you are reading a memory |
|
block in multiple runs, put the return value of the previous run here. |
|
(Note that initial-remainders given by RMCA parameter lists, as |
|
\e Init, assume that the initial remainder is in its \b unaugmented state, |
|
so you would need to convert the value to make it suitable for this |
|
function. I currently don't provide a conversion routine.) |
|
|
|
\return The interim remainder, if no augmentation is used. A special value |
|
if augmentation is used (see the notes). No output processing is done on |
|
the value. (In RMCA terms, \e RefOut is \c False and \e XorOut is \c 0.) |
|
|
|
\note Augmented-style CRC runs use straight-up modulo-2 polynomial |
|
division. Since data is being read byte-wise, a table of pre-computed |
|
remainder changes (as XOR masks) can be used to speed computation. |
|
\note Reading just a memory block will yield an interim remainder, and not |
|
the final checksum. To get that checksum, allocate \a Bits / \c CHAR_BIT |
|
bytes directly after the block and fill them with zero values, then extend |
|
\a byte_count to include those extra bytes. A data block is corrupt if |
|
the return value doesn't equal your separately given checksum. |
|
\note Another way to perform a check is use the zero-byte extension method, |
|
but replace the zero values with your separately-given checksum. The |
|
checksum must be loaded in big-endian order. Here corruption, in either |
|
the data block or the given checksum, is confirmed if the return value is |
|
not zero. |
|
\note The two checksum techniques assume the CRC-run is performed bit-wise, |
|
while this function works byte-wise. That means that the techniques can |
|
be used only if \c CHAR_BIT divides \a Bits evenly! |
|
*/ |
|
template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly > |
|
typename uint_t<Bits>::fast |
|
augmented_crc |
|
( |
|
void const * buffer, |
|
std::size_t byte_count, |
|
typename uint_t<Bits>::fast initial_remainder // = 0u |
|
) |
|
{ |
|
return detail::low_bits_mask_c<Bits>::value & |
|
detail::byte_table_driven_crcs<Bits, TruncPoly, false>:: |
|
augmented_crc_update( initial_remainder, static_cast<unsigned char const |
|
*>(buffer), byte_count ); |
|
} |
|
|
|
|
|
} // namespace boost |
|
|
|
|
|
// Undo header-private macros |
|
#undef BOOST_CRC_OPTIMAL_NAME |
|
#undef BOOST_CRC_PARM_TYPE |
|
|
|
|
|
#endif // BOOST_CRC_HPP |
|
|
|
|