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