diff options
Diffstat (limited to 'ext/boost/crc.hpp')
-rw-r--r-- | ext/boost/crc.hpp | 1110 |
1 files changed, 1110 insertions, 0 deletions
diff --git a/ext/boost/crc.hpp b/ext/boost/crc.hpp new file mode 100644 index 0000000000..6be5aa1d8b --- /dev/null +++ b/ext/boost/crc.hpp @@ -0,0 +1,1110 @@ +// 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 + |