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