| // Boost CRC library crc.hpp header file -----------------------------------// |
| |
| // Copyright 2001, 2004 Daryle Walker. Use, modification, and distribution are |
| // subject to the Boost Software License, Version 1.0. (See 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. |
| |
| #ifndef BOOST_CRC_HPP |
| #define BOOST_CRC_HPP |
| |
| #include <boost/config.hpp> // for BOOST_STATIC_CONSTANT, etc. |
| #include <boost/integer.hpp> // for boost::uint_t |
| |
| #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) || (defined(BOOST_MSVC) && (BOOST_MSVC <= 1300))) |
| #define BOOST_CRC_PARM_TYPE typename ::boost::uint_t<Bits>::fast |
| #else |
| #define BOOST_CRC_PARM_TYPE unsigned long |
| #endif |
| |
| // Some compilers [MS VC++ 6] cannot correctly set up several versions of a |
| // function template unless every template argument can be unambiguously |
| // deduced from the function arguments. (The bug is hidden if only one version |
| // is needed.) Since all of the CRC function templates have this problem, the |
| // workaround is to make up a dummy function argument that encodes the template |
| // arguments. Calls to such template functions need all their template |
| // arguments explicitly specified. At least one compiler that needs this |
| // workaround also needs the default value for the dummy argument to be |
| // specified in the definition. |
| #if defined(__GNUC__) || !defined(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS) |
| #define BOOST_CRC_DUMMY_PARM_TYPE |
| #define BOOST_CRC_DUMMY_INIT |
| #define BOOST_ACRC_DUMMY_PARM_TYPE |
| #define BOOST_ACRC_DUMMY_INIT |
| #else |
| namespace boost { namespace detail { |
| template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
| BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
| bool ReflectIn, bool ReflectRem > |
| struct dummy_crc_argument { }; |
| } } |
| #define BOOST_CRC_DUMMY_PARM_TYPE , detail::dummy_crc_argument<Bits, \ |
| TruncPoly, InitRem, FinalXor, ReflectIn, ReflectRem> *p_ |
| #define BOOST_CRC_DUMMY_INIT BOOST_CRC_DUMMY_PARM_TYPE = 0 |
| #define BOOST_ACRC_DUMMY_PARM_TYPE , detail::dummy_crc_argument<Bits, \ |
| TruncPoly, 0, 0, false, false> *p_ |
| #define BOOST_ACRC_DUMMY_INIT BOOST_ACRC_DUMMY_PARM_TYPE = 0 |
| #endif |
| |
| |
| namespace boost |
| { |
| |
| |
| // Forward declarations ----------------------------------------------------// |
| |
| template < std::size_t Bits > |
| class crc_basic; |
| |
| 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; |
| |
| 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 |
| BOOST_CRC_DUMMY_PARM_TYPE ); |
| |
| 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 |
| BOOST_ACRC_DUMMY_PARM_TYPE ); |
| |
| 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 |
| BOOST_ACRC_DUMMY_PARM_TYPE ); |
| |
| typedef crc_optimal<16, 0x8005, 0, 0, true, true> crc_16_type; |
| typedef crc_optimal<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt_type; |
| typedef crc_optimal<16, 0x8408, 0, 0, true, true> crc_xmodem_type; |
| |
| 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) |
| |
| namespace detail |
| { |
| template < std::size_t Bits > |
| struct mask_uint_t; |
| |
| template < > |
| struct mask_uint_t< std::numeric_limits<unsigned char>::digits >; |
| |
| #if USHRT_MAX > UCHAR_MAX |
| template < > |
| struct mask_uint_t< std::numeric_limits<unsigned short>::digits >; |
| #endif |
| |
| #if UINT_MAX > USHRT_MAX |
| template < > |
| struct mask_uint_t< std::numeric_limits<unsigned int>::digits >; |
| #endif |
| |
| #if ULONG_MAX > UINT_MAX |
| template < > |
| struct mask_uint_t< std::numeric_limits<unsigned long>::digits >; |
| #endif |
| |
| template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, bool Reflect > |
| struct crc_table_t; |
| |
| template < std::size_t Bits, bool DoReflect > |
| class crc_helper; |
| |
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| template < std::size_t Bits > |
| class crc_helper< Bits, false >; |
| #endif |
| |
| } // namespace detail |
| |
| |
| // Simple cyclic redundancy code (CRC) class declaration -------------------// |
| |
| template < std::size_t Bits > |
| class crc_basic |
| { |
| // Implementation type |
| typedef detail::mask_uint_t<Bits> masking_type; |
| |
| public: |
| // Type |
| typedef typename masking_type::least value_type; |
| |
| // Constant for the template parameter |
| BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits ); |
| |
| // Constructor |
| explicit crc_basic( value_type truncated_polynominal, |
| value_type initial_remainder = 0, value_type final_xor_value = 0, |
| bool reflect_input = false, bool reflect_remainder = false ); |
| |
| // Internal Operations |
| value_type get_truncated_polynominal() const; |
| value_type get_initial_remainder() const; |
| value_type get_final_xor_value() const; |
| bool get_reflect_input() const; |
| bool get_reflect_remainder() const; |
| |
| value_type get_interim_remainder() const; |
| void reset( value_type new_rem ); |
| void reset(); |
| |
| // External Operations |
| void process_bit( bool bit ); |
| void process_bits( unsigned char bits, std::size_t bit_count ); |
| void process_byte( unsigned char byte ); |
| void process_block( void const *bytes_begin, void const *bytes_end ); |
| void process_bytes( void const *buffer, std::size_t byte_count ); |
| |
| 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 ----------------// |
| |
| 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 |
| { |
| // Implementation type |
| typedef detail::mask_uint_t<Bits> masking_type; |
| |
| public: |
| // Type |
| typedef typename masking_type::fast value_type; |
| |
| // Constants for the template parameters |
| BOOST_STATIC_CONSTANT( std::size_t, bit_count = Bits ); |
| BOOST_STATIC_CONSTANT( value_type, truncated_polynominal = TruncPoly ); |
| BOOST_STATIC_CONSTANT( value_type, initial_remainder = InitRem ); |
| BOOST_STATIC_CONSTANT( value_type, final_xor_value = FinalXor ); |
| BOOST_STATIC_CONSTANT( bool, reflect_input = ReflectIn ); |
| BOOST_STATIC_CONSTANT( bool, reflect_remainder = ReflectRem ); |
| |
| // Constructor |
| explicit crc_optimal( value_type init_rem = InitRem ); |
| |
| // Internal Operations |
| value_type get_truncated_polynominal() const; |
| value_type get_initial_remainder() const; |
| value_type get_final_xor_value() const; |
| bool get_reflect_input() const; |
| bool get_reflect_remainder() const; |
| |
| value_type get_interim_remainder() const; |
| void reset( value_type new_rem = InitRem ); |
| |
| // External Operations |
| void process_byte( unsigned char byte ); |
| void process_block( void const *bytes_begin, void const *bytes_end ); |
| void process_bytes( void const *buffer, std::size_t byte_count ); |
| |
| value_type checksum() const; |
| |
| // Operators |
| void operator ()( unsigned char byte ); |
| value_type operator ()() const; |
| |
| private: |
| // The implementation of output reflection depends on both reflect states. |
| BOOST_STATIC_CONSTANT( bool, reflect_output = (ReflectRem != ReflectIn) ); |
| |
| #ifndef __BORLANDC__ |
| #define BOOST_CRC_REF_OUT_VAL reflect_output |
| #else |
| typedef crc_optimal self_type; |
| #define BOOST_CRC_REF_OUT_VAL (self_type::reflect_output) |
| #endif |
| |
| // More implementation types |
| typedef detail::crc_table_t<Bits, TruncPoly, ReflectIn> crc_table_type; |
| typedef detail::crc_helper<Bits, ReflectIn> helper_type; |
| typedef detail::crc_helper<Bits, BOOST_CRC_REF_OUT_VAL> reflect_out_type; |
| |
| #undef BOOST_CRC_REF_OUT_VAL |
| |
| // Member data |
| value_type rem_; |
| |
| }; // boost::crc_optimal |
| |
| |
| // Implementation detail stuff ---------------------------------------------// |
| |
| namespace detail |
| { |
| // Forward declarations for more implementation details |
| template < std::size_t Bits > |
| struct high_uint_t; |
| |
| template < std::size_t Bits > |
| struct reflector; |
| |
| |
| // Traits class for mask; given the bit number |
| // (1-based), get the mask for that bit by itself. |
| template < std::size_t Bits > |
| struct high_uint_t |
| : boost::uint_t< Bits > |
| { |
| typedef boost::uint_t<Bits> base_type; |
| typedef typename base_type::least least; |
| typedef typename base_type::fast fast; |
| |
| #if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243 |
| static const least high_bit = 1ul << ( Bits - 1u ); |
| static const fast high_bit_fast = 1ul << ( Bits - 1u ); |
| #else |
| BOOST_STATIC_CONSTANT( least, high_bit = (least( 1u ) << ( Bits |
| - 1u )) ); |
| BOOST_STATIC_CONSTANT( fast, high_bit_fast = (fast( 1u ) << ( Bits |
| - 1u )) ); |
| #endif |
| |
| }; // boost::detail::high_uint_t |
| |
| |
| // Reflection routine class wrapper |
| // (since MS VC++ 6 couldn't handle the unwrapped version) |
| template < std::size_t Bits > |
| struct reflector |
| { |
| typedef typename boost::uint_t<Bits>::fast value_type; |
| |
| static value_type reflect( value_type x ); |
| |
| }; // boost::detail::reflector |
| |
| // Function that reflects its argument |
| template < std::size_t Bits > |
| typename reflector<Bits>::value_type |
| reflector<Bits>::reflect |
| ( |
| typename reflector<Bits>::value_type x |
| ) |
| { |
| value_type reflection = 0; |
| value_type const one = 1; |
| |
| for ( std::size_t i = 0 ; i < Bits ; ++i, x >>= 1 ) |
| { |
| if ( x & one ) |
| { |
| reflection |= ( one << (Bits - 1u - i) ); |
| } |
| } |
| |
| return reflection; |
| } |
| |
| |
| // Traits class for masks; given the bit number (1-based), |
| // get the mask for that bit and its lower bits. |
| template < std::size_t Bits > |
| struct mask_uint_t |
| : high_uint_t< Bits > |
| { |
| typedef high_uint_t<Bits> base_type; |
| typedef typename base_type::least least; |
| typedef typename base_type::fast fast; |
| |
| #ifndef __BORLANDC__ |
| using base_type::high_bit; |
| using base_type::high_bit_fast; |
| #else |
| BOOST_STATIC_CONSTANT( least, high_bit = base_type::high_bit ); |
| BOOST_STATIC_CONSTANT( fast, high_bit_fast = base_type::high_bit_fast ); |
| #endif |
| |
| #if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243 |
| static const least sig_bits = (~( ~( 0ul ) << Bits )) ; |
| #else |
| BOOST_STATIC_CONSTANT( least, sig_bits = (~( ~(least( 0u )) << Bits )) ); |
| #endif |
| #if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 2 |
| // Work around a weird bug that ICEs the compiler in build_c_cast |
| BOOST_STATIC_CONSTANT( fast, sig_bits_fast = static_cast<fast>(sig_bits) ); |
| #else |
| BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); |
| #endif |
| }; // boost::detail::mask_uint_t |
| |
| template < > |
| struct mask_uint_t< std::numeric_limits<unsigned char>::digits > |
| : high_uint_t< std::numeric_limits<unsigned char>::digits > |
| { |
| typedef high_uint_t<std::numeric_limits<unsigned char>::digits> |
| base_type; |
| typedef base_type::least least; |
| typedef base_type::fast fast; |
| |
| #ifndef __BORLANDC__ |
| using base_type::high_bit; |
| using base_type::high_bit_fast; |
| #else |
| BOOST_STATIC_CONSTANT( least, high_bit = base_type::high_bit ); |
| BOOST_STATIC_CONSTANT( fast, high_bit_fast = base_type::high_bit_fast ); |
| #endif |
| |
| BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); |
| BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); |
| |
| }; // boost::detail::mask_uint_t |
| |
| #if USHRT_MAX > UCHAR_MAX |
| template < > |
| struct mask_uint_t< std::numeric_limits<unsigned short>::digits > |
| : high_uint_t< std::numeric_limits<unsigned short>::digits > |
| { |
| typedef high_uint_t<std::numeric_limits<unsigned short>::digits> |
| base_type; |
| typedef base_type::least least; |
| typedef base_type::fast fast; |
| |
| #ifndef __BORLANDC__ |
| using base_type::high_bit; |
| using base_type::high_bit_fast; |
| #else |
| BOOST_STATIC_CONSTANT( least, high_bit = base_type::high_bit ); |
| BOOST_STATIC_CONSTANT( fast, high_bit_fast = base_type::high_bit_fast ); |
| #endif |
| |
| BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); |
| BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); |
| |
| }; // boost::detail::mask_uint_t |
| #endif |
| |
| #if UINT_MAX > USHRT_MAX |
| template < > |
| struct mask_uint_t< std::numeric_limits<unsigned int>::digits > |
| : high_uint_t< std::numeric_limits<unsigned int>::digits > |
| { |
| typedef high_uint_t<std::numeric_limits<unsigned int>::digits> |
| base_type; |
| typedef base_type::least least; |
| typedef base_type::fast fast; |
| |
| #ifndef __BORLANDC__ |
| using base_type::high_bit; |
| using base_type::high_bit_fast; |
| #else |
| BOOST_STATIC_CONSTANT( least, high_bit = base_type::high_bit ); |
| BOOST_STATIC_CONSTANT( fast, high_bit_fast = base_type::high_bit_fast ); |
| #endif |
| |
| BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); |
| BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); |
| |
| }; // boost::detail::mask_uint_t |
| #endif |
| |
| #if ULONG_MAX > UINT_MAX |
| template < > |
| struct mask_uint_t< std::numeric_limits<unsigned long>::digits > |
| : high_uint_t< std::numeric_limits<unsigned long>::digits > |
| { |
| typedef high_uint_t<std::numeric_limits<unsigned long>::digits> |
| base_type; |
| typedef base_type::least least; |
| typedef base_type::fast fast; |
| |
| #ifndef __BORLANDC__ |
| using base_type::high_bit; |
| using base_type::high_bit_fast; |
| #else |
| BOOST_STATIC_CONSTANT( least, high_bit = base_type::high_bit ); |
| BOOST_STATIC_CONSTANT( fast, high_bit_fast = base_type::high_bit_fast ); |
| #endif |
| |
| BOOST_STATIC_CONSTANT( least, sig_bits = (~( least(0u) )) ); |
| BOOST_STATIC_CONSTANT( fast, sig_bits_fast = fast(sig_bits) ); |
| |
| }; // boost::detail::mask_uint_t |
| #endif |
| |
| |
| // CRC table generator |
| template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, bool Reflect > |
| struct crc_table_t |
| { |
| BOOST_STATIC_CONSTANT( std::size_t, byte_combos = (1ul << CHAR_BIT) ); |
| |
| typedef mask_uint_t<Bits> masking_type; |
| typedef typename masking_type::fast value_type; |
| #if defined(__BORLANDC__) && defined(_M_IX86) && (__BORLANDC__ == 0x560) |
| // for some reason Borland's command line compiler (version 0x560) |
| // chokes over this unless we do the calculation for it: |
| typedef value_type table_type[ 0x100 ]; |
| #elif defined(__GNUC__) |
| // old versions of GCC (before 4.0.2) choke on using byte_combos |
| // as a constant expression when compiling with -pedantic. |
| typedef value_type table_type[1ul << CHAR_BIT]; |
| #else |
| typedef value_type table_type[ byte_combos ]; |
| #endif |
| |
| static void init_table(); |
| |
| static table_type table_; |
| |
| }; // boost::detail::crc_table_t |
| |
| // CRC table generator static data member definition |
| // (Some compilers [Borland C++] require the initializer to be present.) |
| template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, bool Reflect > |
| typename crc_table_t<Bits, TruncPoly, Reflect>::table_type |
| crc_table_t<Bits, TruncPoly, Reflect>::table_ |
| = { 0 }; |
| |
| // Populate CRC lookup table |
| template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, bool Reflect > |
| void |
| crc_table_t<Bits, TruncPoly, Reflect>::init_table |
| ( |
| ) |
| { |
| // compute table only on the first run |
| static bool did_init = false; |
| if ( did_init ) return; |
| |
| // factor-out constants to avoid recalculation |
| value_type const fast_hi_bit = masking_type::high_bit_fast; |
| unsigned char const byte_hi_bit = 1u << (CHAR_BIT - 1u); |
| |
| // loop over every possible dividend value |
| unsigned char dividend = 0; |
| do |
| { |
| value_type remainder = 0; |
| |
| // go through all the dividend's bits |
| for ( unsigned char mask = byte_hi_bit ; mask ; mask >>= 1 ) |
| { |
| // check if divisor fits |
| if ( dividend & mask ) |
| { |
| remainder ^= fast_hi_bit; |
| } |
| |
| // do polynominal division |
| if ( remainder & fast_hi_bit ) |
| { |
| remainder <<= 1; |
| remainder ^= TruncPoly; |
| } |
| else |
| { |
| remainder <<= 1; |
| } |
| } |
| |
| table_[ crc_helper<CHAR_BIT, Reflect>::reflect(dividend) ] |
| = crc_helper<Bits, Reflect>::reflect( remainder ); |
| } |
| while ( ++dividend ); |
| |
| did_init = true; |
| } |
| |
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| // Align the msb of the remainder to a byte |
| template < std::size_t Bits, bool RightShift > |
| class remainder |
| { |
| public: |
| typedef typename uint_t<Bits>::fast value_type; |
| |
| static unsigned char align_msb( value_type rem ) |
| { return rem >> (Bits - CHAR_BIT); } |
| }; |
| |
| // Specialization for the case that the remainder has less |
| // bits than a byte: align the remainder msb to the byte msb |
| template < std::size_t Bits > |
| class remainder< Bits, false > |
| { |
| public: |
| typedef typename uint_t<Bits>::fast value_type; |
| |
| static unsigned char align_msb( value_type rem ) |
| { return rem << (CHAR_BIT - Bits); } |
| }; |
| #endif |
| |
| // CRC helper routines |
| template < std::size_t Bits, bool DoReflect > |
| class crc_helper |
| { |
| public: |
| // Type |
| typedef typename uint_t<Bits>::fast value_type; |
| |
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| // Possibly reflect a remainder |
| static value_type reflect( value_type x ) |
| { return detail::reflector<Bits>::reflect( x ); } |
| |
| // Compare a byte to the remainder's highest byte |
| static unsigned char index( value_type rem, unsigned char x ) |
| { return x ^ rem; } |
| |
| // Shift out the remainder's highest byte |
| static value_type shift( value_type rem ) |
| { return rem >> CHAR_BIT; } |
| #else |
| // Possibly reflect a remainder |
| static value_type reflect( value_type x ) |
| { return DoReflect ? detail::reflector<Bits>::reflect( x ) : x; } |
| |
| // Compare a byte to the remainder's highest byte |
| static unsigned char index( value_type rem, unsigned char x ) |
| { return x ^ ( DoReflect ? rem : |
| ((Bits>CHAR_BIT)?( rem >> (Bits - CHAR_BIT) ) : |
| ( rem << (CHAR_BIT - Bits) ))); } |
| |
| // Shift out the remainder's highest byte |
| static value_type shift( value_type rem ) |
| { return DoReflect ? rem >> CHAR_BIT : rem << CHAR_BIT; } |
| #endif |
| |
| }; // boost::detail::crc_helper |
| |
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
| template < std::size_t Bits > |
| class crc_helper<Bits, false> |
| { |
| public: |
| // Type |
| typedef typename uint_t<Bits>::fast value_type; |
| |
| // Possibly reflect a remainder |
| static value_type reflect( value_type x ) |
| { return x; } |
| |
| // Compare a byte to the remainder's highest byte |
| static unsigned char index( value_type rem, unsigned char x ) |
| { return x ^ remainder<Bits,(Bits>CHAR_BIT)>::align_msb( rem ); } |
| |
| // Shift out the remainder's highest byte |
| static value_type shift( value_type rem ) |
| { return rem << CHAR_BIT; } |
| |
| }; // boost::detail::crc_helper |
| #endif |
| |
| |
| } // namespace detail |
| |
| |
| // Simple CRC class function definitions -----------------------------------// |
| |
| template < std::size_t Bits > |
| inline |
| crc_basic<Bits>::crc_basic |
| ( |
| typename crc_basic<Bits>::value_type truncated_polynominal, |
| typename crc_basic<Bits>::value_type initial_remainder, // = 0 |
| typename crc_basic<Bits>::value_type final_xor_value, // = 0 |
| bool reflect_input, // = false |
| bool reflect_remainder // = false |
| ) |
| : rem_( initial_remainder ), poly_( truncated_polynominal ) |
| , init_( initial_remainder ), final_( final_xor_value ) |
| , rft_in_( reflect_input ), rft_out_( reflect_remainder ) |
| { |
| } |
| |
| template < std::size_t Bits > |
| inline |
| typename crc_basic<Bits>::value_type |
| crc_basic<Bits>::get_truncated_polynominal |
| ( |
| ) const |
| { |
| return poly_; |
| } |
| |
| template < std::size_t Bits > |
| inline |
| typename crc_basic<Bits>::value_type |
| crc_basic<Bits>::get_initial_remainder |
| ( |
| ) const |
| { |
| return init_; |
| } |
| |
| template < std::size_t Bits > |
| inline |
| typename crc_basic<Bits>::value_type |
| crc_basic<Bits>::get_final_xor_value |
| ( |
| ) const |
| { |
| return final_; |
| } |
| |
| template < std::size_t Bits > |
| inline |
| bool |
| crc_basic<Bits>::get_reflect_input |
| ( |
| ) const |
| { |
| return rft_in_; |
| } |
| |
| template < std::size_t Bits > |
| inline |
| bool |
| crc_basic<Bits>::get_reflect_remainder |
| ( |
| ) const |
| { |
| return rft_out_; |
| } |
| |
| template < std::size_t Bits > |
| inline |
| typename crc_basic<Bits>::value_type |
| crc_basic<Bits>::get_interim_remainder |
| ( |
| ) const |
| { |
| return rem_ & masking_type::sig_bits; |
| } |
| |
| template < std::size_t Bits > |
| inline |
| void |
| crc_basic<Bits>::reset |
| ( |
| typename crc_basic<Bits>::value_type new_rem |
| ) |
| { |
| rem_ = new_rem; |
| } |
| |
| template < std::size_t Bits > |
| inline |
| void |
| crc_basic<Bits>::reset |
| ( |
| ) |
| { |
| this->reset( this->get_initial_remainder() ); |
| } |
| |
| template < std::size_t Bits > |
| inline |
| void |
| crc_basic<Bits>::process_bit |
| ( |
| bool bit |
| ) |
| { |
| value_type const high_bit_mask = masking_type::high_bit; |
| |
| // compare the new bit with the remainder's highest |
| rem_ ^= ( bit ? high_bit_mask : 0u ); |
| |
| // a full polynominal division step is done when the highest bit is one |
| bool const do_poly_div = static_cast<bool>( rem_ & high_bit_mask ); |
| |
| // shift out the highest bit |
| rem_ <<= 1; |
| |
| // carry out the division, if needed |
| if ( do_poly_div ) |
| { |
| rem_ ^= poly_; |
| } |
| } |
| |
| template < std::size_t Bits > |
| void |
| crc_basic<Bits>::process_bits |
| ( |
| unsigned char bits, |
| std::size_t bit_count |
| ) |
| { |
| // ignore the bits above the ones we want |
| bits <<= CHAR_BIT - bit_count; |
| |
| // 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_count ; i > 0u ; --i, bits <<= 1u ) |
| { |
| process_bit( static_cast<bool>(bits & high_bit_mask) ); |
| } |
| } |
| |
| template < std::size_t Bits > |
| inline |
| void |
| crc_basic<Bits>::process_byte |
| ( |
| unsigned char byte |
| ) |
| { |
| process_bits( (rft_in_ ? detail::reflector<CHAR_BIT>::reflect(byte) |
| : byte), CHAR_BIT ); |
| } |
| |
| 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 ); |
| } |
| } |
| |
| 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 ); |
| } |
| |
| template < std::size_t Bits > |
| inline |
| typename crc_basic<Bits>::value_type |
| crc_basic<Bits>::checksum |
| ( |
| ) const |
| { |
| return ( (rft_out_ ? detail::reflector<Bits>::reflect( rem_ ) : rem_) |
| ^ final_ ) & masking_type::sig_bits; |
| } |
| |
| |
| // Optimized CRC class function definitions --------------------------------// |
| |
| // Macro to compact code |
| #define BOOST_CRC_OPTIMAL_NAME crc_optimal<Bits, TruncPoly, InitRem, \ |
| FinalXor, ReflectIn, ReflectRem> |
| |
| 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 |
| ( |
| typename BOOST_CRC_OPTIMAL_NAME::value_type init_rem // = InitRem |
| ) |
| : rem_( helper_type::reflect(init_rem) ) |
| { |
| crc_table_type::init_table(); |
| } |
| |
| 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 TruncPoly; |
| } |
| |
| 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 InitRem; |
| } |
| |
| 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 FinalXor; |
| } |
| |
| 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 ReflectIn; |
| } |
| |
| 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 ReflectRem; |
| } |
| |
| 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 helper_type::reflect( rem_ ) & masking_type::sig_bits_fast; |
| } |
| |
| 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 |
| ( |
| typename BOOST_CRC_OPTIMAL_NAME::value_type new_rem // = InitRem |
| ) |
| { |
| rem_ = helper_type::reflect( new_rem ); |
| } |
| |
| 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) ); |
| } |
| |
| template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, |
| BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, |
| bool ReflectIn, bool ReflectRem > |
| void |
| BOOST_CRC_OPTIMAL_NAME::process_block |
| ( |
| void const * bytes_begin, |
| void const * bytes_end |
| ) |
| { |
| // Recompute the CRC for each byte passed |
| for ( unsigned char const * p |
| = static_cast<unsigned char const *>(bytes_begin) ; p < bytes_end ; ++p ) |
| { |
| // Compare the new byte with the remainder's higher bits to |
| // get the new bits, shift out the remainder's current higher |
| // bits, and update the remainder with the polynominal division |
| // of the new bits. |
| unsigned char const byte_index = helper_type::index( rem_, *p ); |
| rem_ = helper_type::shift( rem_ ); |
| rem_ ^= crc_table_type::table_[ byte_index ]; |
| } |
| } |
| |
| 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 |
| ) |
| { |
| unsigned char const * const b = static_cast<unsigned char const *>( |
| buffer ); |
| process_block( b, b + byte_count ); |
| } |
| |
| 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_out_type::reflect(rem_) ^ get_final_xor_value() ) |
| & masking_type::sig_bits_fast; |
| } |
| |
| 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 ); |
| } |
| |
| 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 -------------------------------------// |
| |
| 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_DUMMY_INIT |
| ) |
| { |
| BOOST_CRC_OPTIMAL_NAME computer; |
| computer.process_bytes( buffer, byte_count ); |
| return computer.checksum(); |
| } |
| |
| |
| // Augmented-message CRC computation function definitions ------------------// |
| |
| 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 |
| BOOST_ACRC_DUMMY_INIT |
| ) |
| { |
| typedef unsigned char byte_type; |
| typedef detail::mask_uint_t<Bits> masking_type; |
| typedef detail::crc_table_t<Bits, TruncPoly, false> crc_table_type; |
| |
| typename masking_type::fast rem = initial_remainder; |
| byte_type const * const b = static_cast<byte_type const *>( buffer ); |
| byte_type const * const e = b + byte_count; |
| |
| crc_table_type::init_table(); |
| for ( byte_type const * p = b ; p < e ; ++p ) |
| { |
| // Use the current top byte as the table index to the next |
| // "partial product." Shift out that top byte, shifting in |
| // the next augmented-message byte. Complete the division. |
| byte_type const byte_index = rem >> ( Bits - CHAR_BIT ); |
| rem <<= CHAR_BIT; |
| rem |= *p; |
| rem ^= crc_table_type::table_[ byte_index ]; |
| } |
| |
| return rem & masking_type::sig_bits_fast; |
| } |
| |
| template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly > |
| inline |
| typename uint_t<Bits>::fast |
| augmented_crc |
| ( |
| void const * buffer, |
| std::size_t byte_count |
| BOOST_ACRC_DUMMY_INIT |
| ) |
| { |
| // The last function argument has its type specified so the other version of |
| // augmented_crc will be called. If the cast wasn't in place, and the |
| // BOOST_ACRC_DUMMY_INIT added a third argument (for a workaround), the "0" |
| // would match as that third argument, leading to infinite recursion. |
| return augmented_crc<Bits, TruncPoly>( buffer, byte_count, |
| static_cast<typename uint_t<Bits>::fast>(0) ); |
| } |
| |
| |
| } // namespace boost |
| |
| |
| // Undo header-private macros |
| #undef BOOST_CRC_OPTIMAL_NAME |
| #undef BOOST_ACRC_DUMMY_INIT |
| #undef BOOST_ACRC_DUMMY_PARM_TYPE |
| #undef BOOST_CRC_DUMMY_INIT |
| #undef BOOST_CRC_DUMMY_PARM_TYPE |
| #undef BOOST_CRC_PARM_TYPE |
| |
| |
| #endif // BOOST_CRC_HPP |
| |