12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306 |
- // 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 <climits> // for CHAR_BIT, etc.
- #include <cstddef> // for std::size_t
- #include <boost/limits.hpp> // for std::numeric_limits
- // The type of CRC parameters that can go in a template should be related
- // on the CRC's bit count. This macro expresses that type in a compact
- // form, but also allows an alternate type for compilers that don't support
- // dependent types (in template value-parameters).
- #if !(defined(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS))
- #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 = 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;
- remainder <<= 1;
- 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 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, not 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;
- 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;
- // 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( static_cast<bool>(bits & high_bit_mask) );
- }
- }
- /** 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
|