Click here to Skip to main content
15,886,199 members
Articles / Web Development / HTML

Introducing Investigo: Using a Proxy DLL and embedded HTTP server for DirectX9 Performance Analysis, Debugging and Automated Performance Testing.

Rate me:
Please Sign up or sign in to vote.
4.90/5 (6 votes)
9 Nov 2012MIT48 min read 56.9K   1.4K   9  
Introducing Investigo: Using a Proxy DLL and embedded HTTP server for DirectX9 Performance Analysis, Debugging and Automated Performance Testing
//  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

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Chief Technology Officer
Australia Australia
Software craftsman | Author | Writing rapidfullstackdevelopment.com - Posting about how to survive and flourish as a software developer

Follow on Twitter for news and updates: https://twitter.com/codecapers

I'm writing a new book: Rapid Fullstack Development. Learn from my years of experience and become a better developer.

My second book, Bootstrapping Microservices, is a practical and project-based guide to building distributed applications with microservices.

My first book Data Wrangling with JavaScript is a comprehensive overview of working with data in JavaScript.

Data-Forge Notebook is my notebook-style application for data transformation, analysis and transformation in JavaScript.

I have a long history in software development with many years in apps, web apps, backends, serious games, simulations and VR. Making technology work for business is what I do: building bespoke software solutions that span multiple platforms.

I have years of experience managing development teams, preparing technical strategies and creation of software products. I can explain complicated technology to senior management. I have delivered cutting-edge products in fast-paced and high-pressure environments. I know how to focus and prioritize to get the important things done.

Author

- Rapid Fullstack Development
- Bootstrapping Microservices
- Data Wrangling with JavaScript

Creator of Market Wizard

- https://www.market-wizard.com.au/

Creator of Data-Forge and Data-Forge Notebook

- http://www.data-forge-js.com
- http://www.data-forge-notebook.com

Web

- www.codecapers.com.au

Open source

- https://github.com/ashleydavis
- https://github.com/data-forge
- https://github.com/data-forge-notebook


Skills

- Quickly building MVPs for startups
- Understanding how to get the most out of technology for business
- Developing technical strategies
- Management and coaching of teams & projects
- Microservices, devops, mobile and fullstack software development

Comments and Discussions