![]() |
|
|||
File indexing completed on 2025-09-17 08:53:17
0001 // Boost CRC library crc.hpp header file -----------------------------------// 0002 0003 // Copyright 2001, 2004, 2011 Daryle Walker. 0004 // Distributed under the Boost Software License, Version 1.0. (See the 0005 // accompanying file LICENSE_1_0.txt or a copy at 0006 // <http://www.boost.org/LICENSE_1_0.txt>.) 0007 0008 // See <http://www.boost.org/libs/crc/> for the library's home page. 0009 0010 /** \file 0011 \brief A collection of function templates and class templates that compute 0012 various forms of Cyclic Redundancy Codes (CRCs). 0013 0014 \author Daryle Walker 0015 0016 \version 1.5 0017 0018 \copyright Boost Software License, version 1.0 0019 0020 Contains the declarations (and definitions) of various kinds of CRC 0021 computation functions, function object types, and encapsulated policy types. 0022 0023 \warning The sample CRC-computer types were just checked against the 0024 <a href="http://regregex.bbcmicro.net/crc-catalogue.htm">Catalogue of 0025 parametrised CRC algorithms</a>. New type aliases were added where I got 0026 a standard wrong. However, the mistaken <code>typedef</code>s are still 0027 there for backwards compatibility. 0028 \note There are references to the <i>Rocksoft™ Model CRC 0029 Algorithm</i>, as described within \"A Painless Guide to CRC Error 0030 Detection Algorithms,\" linked from \"<a 0031 href="http://www.ross.net/crc/crcpaper.html">CRC: A Paper On CRCs</a>\" by 0032 Ross Williams. It will be abbreviated \"RMCA\" in other documentation 0033 blocks. 0034 */ 0035 0036 #ifndef BOOST_CRC_HPP 0037 #define BOOST_CRC_HPP 0038 0039 #include <array> // for std::array 0040 #include <climits> // for CHAR_BIT, etc. 0041 #include <cstddef> // for std::size_t 0042 #include <cstdint> // for UINTMAX_C, std::uintmax_t 0043 #include <limits> // for std::numeric_limits 0044 #include <type_traits> // for std::conditional, std::integral_constant 0045 0046 // Local reimplementation of boost::uint_t, to avoid dependency on Integer 0047 0048 namespace boost { 0049 namespace crc_detail { 0050 0051 struct uint_t_8 0052 { 0053 typedef std::uint_least8_t fast; // matches boost::uint_t<8>::fast 0054 }; 0055 0056 struct uint_t_16 0057 { 0058 typedef std::uint_least16_t fast; // matches boost::uint_t<16>::fast 0059 }; 0060 0061 struct uint_t_32 0062 { 0063 typedef std::uint_least32_t fast; // matches boost::uint_t<32>::fast 0064 }; 0065 0066 template<class T> struct remap_long_long 0067 { 0068 typedef T type; 0069 }; 0070 0071 #if ULONG_MAX == ULLONG_MAX 0072 0073 template<> struct remap_long_long<unsigned long long> 0074 { 0075 typedef unsigned long type; 0076 }; 0077 0078 #endif 0079 0080 struct uint_t_64 0081 { 0082 typedef remap_long_long<std::uint_least64_t>::type fast; // matches boost::uint_t<64>::fast 0083 }; 0084 0085 struct uint_t_none 0086 { 0087 }; 0088 0089 template<int Bits> struct uint_t: 0090 std::conditional< (Bits <= 8), uint_t_8, 0091 typename std::conditional< (Bits <= 16), uint_t_16, 0092 typename std::conditional< (Bits <= 32), uint_t_32, 0093 typename std::conditional< (Bits <= 64), uint_t_64, 0094 uint_t_none>::type>::type>::type>::type 0095 { 0096 }; 0097 0098 } // namespace crc_detail 0099 } // namespace boost 0100 0101 // The type of CRC parameters that can go in a template should be related 0102 // on the CRC's bit count. This macro expresses that type in a compact 0103 // form. 0104 #define BOOST_CRC_PARM_TYPE typename ::boost::crc_detail::uint_t<Bits>::fast 0105 0106 namespace boost 0107 { 0108 0109 0110 // Forward declarations ----------------------------------------------------// 0111 0112 //! Bit-wise CRC computer 0113 template < std::size_t Bits > 0114 class crc_basic; 0115 0116 //! Table-driven CRC computer, usable as a function object 0117 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly = 0u, 0118 BOOST_CRC_PARM_TYPE InitRem = 0u, 0119 BOOST_CRC_PARM_TYPE FinalXor = 0u, bool ReflectIn = false, 0120 bool ReflectRem = false > 0121 class crc_optimal; 0122 0123 //! Compute the (unaugmented) CRC of a memory block 0124 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 0125 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 0126 bool ReflectIn, bool ReflectRem > 0127 typename crc_detail::uint_t<Bits>::fast crc( void const *buffer, 0128 std::size_t byte_count); 0129 0130 //! Compute the CRC of a memory block, with any augmentation provided by user 0131 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly > 0132 typename crc_detail::uint_t<Bits>::fast augmented_crc( void const *buffer, 0133 std::size_t byte_count, 0134 typename crc_detail::uint_t<Bits>::fast initial_remainder = 0u); 0135 0136 //! Computation type for ARC|CRC-16|CRC-IBM|CRC-16/ARC|CRC-16/LHA standard 0137 typedef crc_optimal<16, 0x8005, 0, 0, true, true> crc_16_type; 0138 //! Computation type for CRC-16/CCITT-FALSE standard 0139 typedef crc_optimal<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt_false_t; 0140 //! Computation type for the CRC mistakenly called the CCITT standard 0141 typedef crc_ccitt_false_t crc_ccitt_type; 0142 //! Computation type for the actual 0143 //! KERMIT|CRC-16/CCITT|CRC-16/CCITT-TRUE|CRC-CCITT standard 0144 typedef crc_optimal<16, 0x1021, 0, 0, true, true> crc_ccitt_true_t; 0145 //! Computation type that I mistakenly called the XMODEM standard; it inverts 0146 //! both reflection parameters and reflects the truncated divisor (Don't use?!) 0147 typedef crc_optimal<16, 0x8408, 0, 0, true, true> crc_xmodem_type; 0148 //! Computation type for the actual XMODEM|ZMODEM|CRC-16/ACORN standard 0149 typedef crc_optimal<16, 0x1021, 0, 0, false, false> crc_xmodem_t; 0150 0151 //! Computation type for CRC-32|CRC-32/ADCCP|PKZIP standard 0152 typedef crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true> 0153 crc_32_type; 0154 0155 0156 // Forward declarations for implementation detail stuff --------------------// 0157 // (Just for the stuff that will be needed for the next two sections) 0158 0159 //! \cond 0160 namespace detail 0161 { 0162 //! Mix-in class to add a possibly-reflecting member function 0163 template < int BitLength, bool DoIt, int Id = 0 > 0164 class possible_reflector; 0165 0166 //! Mix-in class for byte-fed, table-driven CRC algorithms 0167 template < int Order, std::uintmax_t TruncatedPolynomial, bool Reflect, 0168 int Id = 0 > 0169 class crc_driver; 0170 0171 } // namespace detail 0172 //! \endcond 0173 0174 0175 // Simple cyclic redundancy code (CRC) class declaration -------------------// 0176 0177 /** Objects of this type compute the CRC checksum of submitted data, where said 0178 data can be entered piecemeal through several different kinds of groupings. 0179 Modulo-2 polynomial division steps are always performed bit-wise, without 0180 the use of pre-computation tables. Said division uses the altered 0181 algorithm, so any data has to be unaugmented. 0182 0183 \pre 0 \< \a Bits \<= \c std\::numeric_limits\<uintmax_t\>\::digits 0184 0185 \tparam Bits The order of the modulo-2 polynomial divisor. (\e Width from 0186 the RMCA) 0187 */ 0188 template < std::size_t Bits > 0189 class crc_basic 0190 { 0191 public: 0192 // Type 0193 /** \brief The register type used for computations 0194 0195 This type is used for CRC calculations and is the type for any returned 0196 checksums and returned or submitted remainders, (truncated) divisors, or 0197 XOR masks. It is a built-in unsigned integer type. 0198 */ 0199 typedef typename boost::crc_detail::uint_t<Bits>::fast value_type; 0200 0201 // Constant for the template parameter 0202 //! A copy of \a Bits provided for meta-programming purposes 0203 static const std::size_t bit_count = Bits; 0204 0205 // Constructor (use the automatic copy-ctr, move-ctr, and dtr) 0206 //! Create a computer, separately listing each needed parameter 0207 explicit crc_basic( value_type truncated_polynomial, 0208 value_type initial_remainder = 0, value_type final_xor_value = 0, 0209 bool reflect_input = false, bool reflect_remainder = false ); 0210 0211 // Internal Operations 0212 //! Return the (truncated) polynomial divisor 0213 value_type get_truncated_polynominal() const; 0214 //! Return what the polynomial remainder was set to during construction 0215 value_type get_initial_remainder() const; 0216 //! Return the XOR-mask used during output processing 0217 value_type get_final_xor_value() const; 0218 //! Check if input-bytes will be reflected before processing 0219 bool get_reflect_input() const; 0220 //! Check if the remainder will be reflected during output processing 0221 bool get_reflect_remainder() const; 0222 0223 //! Return the remainder based from already-processed bits 0224 value_type get_interim_remainder() const; 0225 //! Change the interim remainder to a new value 0226 void reset( value_type new_rem ); 0227 //! Change the interim remainder back to the initial value 0228 void reset(); 0229 0230 // External Operations 0231 //! Submit a single bit for input processing 0232 void process_bit( bool bit ); 0233 //! Submit the lowest \a bit_length bits of a byte for input processing 0234 void process_bits( unsigned char bits, std::size_t bit_length ); 0235 //! Submit a single byte for input processing 0236 void process_byte( unsigned char byte ); 0237 //! Submit a memory block for input processing, iterator-pair style 0238 void process_block( void const *bytes_begin, void const *bytes_end ); 0239 //! Submit a memory block for input processing, pointer-and-size style 0240 void process_bytes( void const *buffer, std::size_t byte_count ); 0241 0242 //! Return the checksum of the already-processed bits 0243 value_type checksum() const; 0244 0245 private: 0246 // Member data 0247 value_type rem_; 0248 value_type poly_, init_, final_; // non-const to allow assignability 0249 bool rft_in_, rft_out_; // non-const to allow assignability 0250 0251 }; // boost::crc_basic 0252 0253 0254 // Optimized cyclic redundancy code (CRC) class declaration ----------------// 0255 0256 /** Objects of this type compute the CRC checksum of submitted data, where said 0257 data can be entered piecemeal through several different kinds of groupings. 0258 Modulo-2 polynomial division steps are performed byte-wise, aided by the use 0259 of pre-computation tables. Said division uses the altered algorithm, so any 0260 data has to be unaugmented. 0261 0262 \pre 0 \< \a Bits \<= \c std\::numeric_limits\<uintmax_t\>\::digits 0263 0264 \tparam Bits The order of the modulo-2 polynomial divisor. (\e Width from 0265 the RMCA) 0266 \tparam TruncPoly The lowest coefficients of the divisor polynomial. The 0267 highest-order coefficient is omitted and always assumed to be 1. Defaults 0268 to \c 0, i.e. the only non-zero term is the implicit one for 0269 x<sup><var>Bits</var></sup>. (\e Poly from the RMCA) 0270 \tparam InitRem The (unaugmented) initial state of the polynomial 0271 remainder. Defaults to \c 0 if omitted. (\e Init from the RMCA) 0272 \tparam FinalXor The (XOR) bit-mask to be applied to the output remainder, 0273 after possible reflection but before returning. Defaults to \c 0 (i.e. no 0274 bit changes) if omitted. (\e XorOut from the RMCA) 0275 \tparam ReflectIn If \c true, input bytes are read lowest-order bit first, 0276 otherwise highest-order bit first. Defaults to \c false if omitted. 0277 (\e RefIn from the RMCA) 0278 \tparam ReflectRem If \c true, the output remainder is reflected before the 0279 XOR-mask. Defaults to \c false if omitted. (\e RefOut from the RMCA) 0280 0281 \todo Get rid of the default value for \a TruncPoly. Choosing a divisor is 0282 an important decision with many factors, so a default is never useful, 0283 especially a bad one. 0284 */ 0285 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 0286 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 0287 bool ReflectIn, bool ReflectRem > 0288 class crc_optimal 0289 { 0290 public: 0291 // Type 0292 //! \copydoc boost::crc_basic::value_type 0293 typedef typename boost::crc_detail::uint_t<Bits>::fast value_type; 0294 0295 // Constants for the template parameters 0296 //! \copydoc boost::crc_basic::bit_count 0297 static const std::size_t bit_count = Bits; 0298 //! A copy of \a TruncPoly provided for meta-programming purposes 0299 static const value_type truncated_polynominal = TruncPoly; 0300 //! A copy of \a InitRem provided for meta-programming purposes 0301 static const value_type initial_remainder = InitRem; 0302 //! A copy of \a FinalXor provided for meta-programming purposes 0303 static const value_type final_xor_value = FinalXor; 0304 //! A copy of \a ReflectIn provided for meta-programming purposes 0305 static const bool reflect_input = ReflectIn; 0306 //! A copy of \a ReflectRem provided for meta-programming purposes 0307 static const bool reflect_remainder = ReflectRem; 0308 0309 // Constructor (use the automatic copy-ctr, move-ctr, and dtr) 0310 //! Create a computer, giving an initial remainder if desired 0311 explicit crc_optimal( value_type init_rem = initial_remainder ); 0312 0313 // Internal Operations 0314 //! \copybrief boost::crc_basic::get_truncated_polynominal 0315 value_type get_truncated_polynominal() const; 0316 //! \copybrief boost::crc_basic::get_initial_remainder 0317 value_type get_initial_remainder() const; 0318 //! \copybrief boost::crc_basic::get_final_xor_value 0319 value_type get_final_xor_value() const; 0320 //! \copybrief boost::crc_basic::get_reflect_input 0321 bool get_reflect_input() const; 0322 //! \copybrief boost::crc_basic::get_reflect_remainder 0323 bool get_reflect_remainder() const; 0324 0325 //! \copybrief boost::crc_basic::get_interim_remainder 0326 value_type get_interim_remainder() const; 0327 //! Change the interim remainder to either a given value or the initial one 0328 void reset( value_type new_rem = initial_remainder ); 0329 0330 // External Operations 0331 //! \copybrief boost::crc_basic::process_byte 0332 void process_byte( unsigned char byte ); 0333 //! \copybrief boost::crc_basic::process_block 0334 void process_block( void const *bytes_begin, void const *bytes_end ); 0335 //! \copybrief boost::crc_basic::process_bytes 0336 void process_bytes( void const *buffer, std::size_t byte_count ); 0337 0338 //! \copybrief boost::crc_basic::checksum 0339 value_type checksum() const; 0340 0341 // Operators 0342 //! Submit a single byte for input processing, suitable for the STL 0343 void operator ()( unsigned char byte ); 0344 //! Return the checksum of the already-processed bits, suitable for the STL 0345 value_type operator ()() const; 0346 0347 private: 0348 // Implementation types 0349 // (Processing for reflected input gives reflected remainders, so you only 0350 // have to apply output-reflection if Reflect-Remainder doesn't match 0351 // Reflect-Input.) 0352 typedef detail::possible_reflector<Bits, ReflectIn> reflect_i_type; 0353 typedef detail::crc_driver<Bits, TruncPoly, ReflectIn> crc_table_type; 0354 typedef detail::possible_reflector<Bits, ReflectRem != ReflectIn> 0355 reflect_o_type; 0356 0357 // Member data 0358 value_type rem_; 0359 0360 }; // boost::crc_optimal 0361 0362 0363 // Implementation detail stuff ---------------------------------------------// 0364 0365 //! \cond 0366 namespace detail 0367 { 0368 /** \brief Meta-programming integral constant for a single-bit bit-mask 0369 0370 Generates a compile-time constant for a bit-mask that affects a single 0371 bit. The \c value will be 2<sup><var>BitIndex</var></sup>. The \c type 0372 will be the smallest built-in unsigned integer type that can contain the 0373 value, unless there's a built-in type that the system can handle easier, 0374 then the \c type will be smallest fast-handled unsigned integer type. 0375 0376 \pre 0 \<= BitIndex \< \c std\::numeric_limits\<uintmax_t\>\::digits 0377 0378 \tparam BitIndex The place of the sole set bit. 0379 */ 0380 template < int BitIndex > 0381 struct high_bit_mask_c 0382 : std::integral_constant<typename boost::crc_detail::uint_t< BitIndex + 1 >::fast, 0383 ( UINTMAX_C(1) << BitIndex )> 0384 {}; 0385 0386 /** \brief Meta-programming integral constant for a lowest-bits bit-mask 0387 0388 Generates a compile-time constant for a bit-mask that affects the lowest 0389 bits. The \c value will be 2<sup><var>BitCount</var></sup> - 1. The 0390 \c type will be the smallest built-in unsigned integer type that can 0391 contain the value, unless there's a built-in type that the system can 0392 handle easier, then the \c type will be smallest fast-handled unsigned 0393 integer type. 0394 0395 \pre 0 \<= BitCount \<= \c std\::numeric_limits\<uintmax_t\>\::digits 0396 0397 \tparam BitCount The number of lowest-placed bits set. 0398 */ 0399 template < int BitCount > 0400 struct low_bits_mask_c 0401 : std::integral_constant<typename boost::crc_detail::uint_t< BitCount >::fast, ( 0402 BitCount ? (( (( UINTMAX_C(1) << (BitCount - 1) ) - 1u) << 1 ) | 0403 UINTMAX_C( 1 )) : 0u )> 0404 {}; 0405 0406 /** \brief Reflects the bits of a number 0407 0408 Reverses the order of the given number of bits within a value. For 0409 instance, if the given reflect count is 5, then the bit values for the 0410 16- and 1-place will switch and the 8- and 2-place will switch, leaving 0411 the other bits alone. (The 4-place bit is in the middle, so it wouldn't 0412 change.) 0413 0414 \pre \a Unsigned is a built-in unsigned integer type 0415 \pre 0 \< word_length \<= \c std\::numeric_limits\<Unsigned\>\::digits 0416 0417 \tparam Unsigned The type of \a x. 0418 0419 \param x The value to be (partially) reflected. 0420 \param word_length The number of low-order bits to reflect. Defaults 0421 to the total number of value bits in \a Unsigned. 0422 0423 \return The (partially) reflected value. 0424 0425 \todo Check if this is the fastest way. 0426 */ 0427 template < typename Unsigned > 0428 Unsigned reflect_unsigned( Unsigned x, int word_length 0429 = std::numeric_limits<Unsigned>::digits ) 0430 { 0431 for ( Unsigned l = 1u, h = static_cast<Unsigned>(l << (word_length - 1)) ; h > l ; h >>= 1, l 0432 <<= 1 ) 0433 { 0434 Unsigned const m = h | l, t = x & m; 0435 0436 if ( (t == h) || (t == l) ) 0437 x ^= m; 0438 } 0439 0440 return x; 0441 } 0442 0443 /** \brief Make a byte-to-byte-reflection map 0444 0445 Creates a mapping array so the results can be cached. Uses 0446 #reflect_unsigned to generate the element values. 0447 0448 \return An array <var>a</var> such that, for a given byte value 0449 <var>i</var>, <code><var>a</var>[ <var>i</var> ]</code> resolves to 0450 the reflected value of <var>i</var>. 0451 */ 0452 std::array< unsigned char, (UINTMAX_C( 1 ) << CHAR_BIT) > 0453 inline make_byte_reflection_table() 0454 { 0455 std::array<unsigned char, ( UINTMAX_C(1) << CHAR_BIT )> result; 0456 unsigned char i = 0u; 0457 0458 do 0459 result[ i ] = reflect_unsigned( i ); 0460 while ( ++i ); 0461 return result; 0462 } 0463 0464 /** \brief Reflects the bits of a single byte 0465 0466 Reverses the order of all the bits within a value. For instance, the 0467 bit values for the 2<sup><code>CHAR_BIT</code> - 1</sup>- and 1-place 0468 will switch and the 2<sup><code>CHAR_BIT</code> - 2</sup>- and 2-place 0469 will switch, etc. 0470 0471 \param x The byte value to be reflected. 0472 0473 \return The reflected value. 0474 0475 \note Since this could be the most common type of reflection, and the 0476 number of states is relatively small, the implementation pre-computes 0477 and uses a table of all the results. 0478 */ 0479 inline unsigned char reflect_byte( unsigned char x ) 0480 { 0481 static std::array<unsigned char, ( UINTMAX_C(1) << CHAR_BIT )> const 0482 table = make_byte_reflection_table(); 0483 0484 return table[ x ]; 0485 } 0486 0487 /** \brief Reflects some bits within a single byte 0488 0489 Like #reflect_unsigned, except it takes advantage of any (long-term) 0490 speed gains #reflect_byte may bring. 0491 0492 \pre 0 \< \a word_length \<= \c CHAR_BIT 0493 0494 \param x The value to be (partially) reflected. 0495 \param word_length The number of low-order bits to reflect. 0496 0497 \return The (partially) reflected value. 0498 */ 0499 inline unsigned char reflect_sub_byte( unsigned char x, int word_length ) 0500 { return reflect_byte(x) >> (CHAR_BIT - word_length); } 0501 0502 /** \brief Possibly reflects the bits of a number 0503 0504 Reverses the order of the given number of bits within a value. For 0505 instance, if the given reflect count is 5, then the bit values for the 0506 16- and 1-place will switch and the 8- and 2-place will switch, leaving 0507 the other bits alone. (The 4-place bit is in the middle, so it wouldn't 0508 change.) This variant function allows the reflection be controlled by 0509 an extra parameter, in case the decision to use reflection is made at 0510 run-time. 0511 0512 \pre \a Unsigned is a built-in unsigned integer type 0513 \pre 0 \< word_length \<= \c std\::numeric_limits\<Unsigned\>\::digits 0514 0515 \tparam Unsigned The type of \a x. 0516 0517 \param x The value to be (partially) reflected. 0518 \param reflect Controls whether \a x is actually reflected (\c true) or 0519 left alone (\c false). 0520 \param word_length The number of low-order bits to reflect. Defaults 0521 to the total number of value bits in \a Unsigned. 0522 0523 \return The possibly (partially) reflected value. 0524 */ 0525 template < typename Unsigned > 0526 inline 0527 Unsigned reflect_optionally( Unsigned x, bool reflect, int word_length 0528 = std::numeric_limits<Unsigned>::digits ) 0529 { return reflect ? reflect_unsigned(x, word_length) : x; } 0530 0531 /** \brief Possibly reflects the bits of a single byte 0532 0533 Uses #reflect_byte (if \a reflect is \c true). 0534 0535 \param x The byte value to be (possibly) reflected. 0536 \param reflect Whether (\c true) or not (\c false) \a x is reflected. 0537 0538 \return <code><var>reflect</var> ? reflect_byte(<var>x</var>) : 0539 <var>x</var></code> 0540 */ 0541 inline 0542 unsigned char reflect_byte_optionally( unsigned char x, bool reflect ) 0543 { return reflect ? reflect_byte(x) : x; } 0544 0545 /** \brief Update a CRC remainder by several bits, assuming a non-augmented 0546 message 0547 0548 Performs several steps of division required by the CRC algorithm, giving 0549 a new remainder polynomial based on the divisor polynomial and the 0550 synthesized dividend polynomial (from the old remainder and the 0551 newly-provided input). The computations assume that the CRC is directly 0552 exposed from the remainder, without any zero-valued bits augmented to 0553 the message bits. 0554 0555 \pre \a Register and \a Word are both built-in unsigned integer types 0556 \pre 0 \< \a register_length \<= std\::numeric_limits\<\a Register\> 0557 \::digits 0558 \pre 0 \< \a word_length \<= std\::numeric_limits\<\a Word\>\::digits 0559 0560 \tparam Register The type used for representing the remainder and 0561 divisor modulo-2 polynomials. The bit at <code>2<sup>i</sup></code> 0562 is used as the coefficient of <i>x<sup>i</sup></i>. 0563 \tparam Word The type used for storing the incoming terms of the 0564 dividend modulo-2 polynomial. The bit at <code>2<sup>i</sup></code> 0565 is used as the coefficient of <i>x<sup>i</sup></i> when \a reflect is 0566 \c false, and the coefficient of <i>x<sup><var>word_length</var> - 1 - 0567 i</sup></i> otherwise. 0568 0569 \param[in] register_length The number of significant low-order bits 0570 to be used from \a Register values. It is the order of the modulo-2 0571 polynomial remainder and one less than the divisor's order. 0572 \param[in,out] remainder The upper part of the dividend polynomial 0573 before division, and the remainder polynomial after. 0574 \param[in] new_dividend_bits The coefficients for the next 0575 \a word_length lowest terms of the dividend polynomial. 0576 \param[in] truncated_divisor The lowest coefficients of the divisor 0577 polynomial. The highest-order coefficient is omitted and always 0578 assumed to be 1. 0579 \param[in] word_length The number of lowest-order bits to read from 0580 \a new_dividend_bits. 0581 \param[in] reflect If \c false, read from the highest-order marked 0582 bit from \a new_dividend_bits and go down, as normal. Otherwise, 0583 proceed from the lowest-order bit and go up. 0584 0585 \note This routine performs a modulo-2 polynomial division variant. 0586 The exclusive-or operations are applied in a different order, since 0587 that kind of operation is commutative and associative. It also 0588 assumes that the zero-valued augment string was applied before this 0589 step, which means that the updated remainder can be directly used as 0590 the final CRC. 0591 */ 0592 template < typename Register, typename Word > 0593 void crc_modulo_word_update( int register_length, Register &remainder, Word 0594 new_dividend_bits, Register truncated_divisor, int word_length, bool 0595 reflect ) 0596 { 0597 // Create this masking constant outside the loop. 0598 Register const high_bit_mask = UINTMAX_C(1) << (register_length - 1); 0599 0600 // The natural reading order for division is highest digit/bit first. 0601 // The "reflect" parameter switches this. However, building a bit mask 0602 // for the lowest bit is the easiest.... 0603 new_dividend_bits = reflect_optionally( new_dividend_bits, !reflect, 0604 word_length ); 0605 0606 // Perform modulo-2 division for each new dividend input bit 0607 for ( int i = word_length ; i ; --i, new_dividend_bits >>= 1 ) 0608 { 0609 // compare the new bit with the remainder's highest 0610 remainder ^= ( new_dividend_bits & 1u ) ? high_bit_mask : 0u; 0611 0612 // perform modulo-2 division 0613 bool const quotient = (remainder & high_bit_mask) != 0; 0614 0615 remainder <<= 1; 0616 remainder ^= quotient ? truncated_divisor : 0u; 0617 0618 // The quotient isn't used for anything, so don't keep it. 0619 } 0620 0621 // Clear overflowed bits 0622 remainder &= (std::numeric_limits<Register>::max)() >> (std::numeric_limits<Register>::digits - register_length); 0623 } 0624 0625 /** \brief Update a CRC remainder by a single bit, assuming a non-augmented 0626 message 0627 0628 Performs the next step of division required by the CRC algorithm, giving 0629 a new remainder polynomial based on the divisor polynomial and the 0630 synthesized dividend polynomial (from the old remainder and the 0631 newly-provided input). The computations assume that the CRC is directly 0632 exposed from the remainder, without any zero-valued bits augmented to 0633 the message bits. 0634 0635 \pre \a Register is a built-in unsigned integer type 0636 \pre 0 \< \a register_length \<= std\::numeric_limits\<\a Register\> 0637 \::digits 0638 0639 \tparam Register The type used for representing the remainder and 0640 divisor modulo-2 polynomials. The bit at <code>2<sup>i</sup></code> 0641 is used as the coefficient of <i>x<sup>i</sup></i>. 0642 0643 \param[in] register_length The number of significant low-order bits 0644 to be used from \a Register values. It is the order of the modulo-2 0645 polynomial remainder and one less than the divisor's order. 0646 \param[in,out] remainder The upper part of the dividend polynomial 0647 before division, and the remainder polynomial after. 0648 \param[in] new_dividend_bit The coefficient for the constant term 0649 of the dividend polynomial. 0650 \param[in] truncated_divisor The lowest coefficients of the divisor 0651 polynomial. The highest-order coefficient is omitted and always 0652 assumed to be 1. 0653 0654 \note This routine performs a modulo-2 polynomial division variant. 0655 The exclusive-or operations are applied in a different order, since 0656 that kind of operation is commutative and associative. It also 0657 assumes that the zero-valued augment string was applied before this 0658 step, which means that the updated remainder can be directly used as 0659 the final CRC. 0660 */ 0661 template < typename Register > 0662 inline void crc_modulo_update( int register_length, Register &remainder, 0663 bool new_dividend_bit, Register truncated_divisor ) 0664 { 0665 crc_modulo_word_update( register_length, remainder, 0666 static_cast<unsigned>(new_dividend_bit), truncated_divisor, 1, false ); 0667 } 0668 0669 /** \brief Update a CRC remainder by several bits, assuming an augmented 0670 message 0671 0672 Performs several steps of division required by the CRC algorithm, giving 0673 a new remainder polynomial based on the divisor polynomial and the 0674 synthesized dividend polynomial (from the old remainder and the 0675 newly-provided input). The computations assume that a zero-valued 0676 string of bits will be appended to the message before extracting the 0677 CRC. 0678 0679 \pre \a Register and \a Word are both built-in unsigned integer types 0680 \pre 0 \< \a register_length \<= std\::numeric_limits\<\a Register\> 0681 \::digits 0682 \pre 0 \< \a word_length \<= std\::numeric_limits\<\a Word\>\::digits 0683 0684 \tparam Register The type used for representing the remainder and 0685 divisor modulo-2 polynomials. The bit at <code>2<sup>i</sup></code> 0686 is used as the coefficient of <i>x<sup>i</sup></i>. 0687 \tparam Word The type used for storing the incoming terms of the 0688 dividend modulo-2 polynomial. The bit at <code>2<sup>i</sup></code> 0689 is used as the coefficient of <i>x<sup>i</sup></i> when \a reflect is 0690 \c false, and the coefficient of <i>x<sup><var>word_length</var> - 1 - 0691 i</sup></i> otherwise. 0692 0693 \param[in] register_length The number of significant low-order bits 0694 to be used from \a Register values. It is the order of the modulo-2 0695 polynomial remainder and one less than the divisor's order. 0696 \param[in,out] remainder The upper part of the dividend polynomial 0697 before division, and the remainder polynomial after. 0698 \param[in] new_dividend_bits The coefficients for the next 0699 \a word_length lowest terms of the dividend polynomial. 0700 \param[in] truncated_divisor The lowest coefficients of the divisor 0701 polynomial. The highest-order coefficient is omitted and always 0702 assumed to be 1. 0703 \param[in] word_length The number of lowest-order bits to read from 0704 \a new_dividend_bits. 0705 \param[in] reflect If \c false, read from the highest-order marked 0706 bit from \a new_dividend_bits and go down, as normal. Otherwise, 0707 proceed from the lowest-order bit and go up. 0708 0709 \note This routine performs straight-forward modulo-2 polynomial 0710 division. It assumes that an augment string will be processed at the 0711 end of the message bits before doing CRC analysis. 0712 \todo Use this function somewhere so I can test it. 0713 */ 0714 template < typename Register, typename Word > 0715 void augmented_crc_modulo_word_update( int register_length, Register 0716 &remainder, Word new_dividend_bits, Register truncated_divisor, int 0717 word_length, bool reflect ) 0718 { 0719 // Create this masking constant outside the loop. 0720 Register const high_bit_mask = UINTMAX_C(1) << (register_length - 1); 0721 0722 // The natural reading order for division is highest digit/bit first. 0723 // The "reflect" parameter switches this. However, building a bit mask 0724 // for the lowest bit is the easiest.... 0725 new_dividend_bits = reflect_optionally( new_dividend_bits, !reflect, 0726 word_length ); 0727 0728 // Perform modulo-2 division for each new dividend input bit 0729 for ( int i = word_length ; i ; --i, new_dividend_bits >>= 1 ) 0730 { 0731 bool const quotient = (remainder & high_bit_mask) != 0; 0732 0733 remainder <<= 1; 0734 remainder |= new_dividend_bits & 1u; 0735 remainder ^= quotient ? truncated_divisor : 0u; 0736 0737 // The quotient isn't used for anything, so don't keep it. 0738 } 0739 } 0740 0741 /** \brief Update a CRC remainder by a single bit, assuming an augmented 0742 message 0743 0744 Performs the next step of division required by the CRC algorithm, giving 0745 a new remainder polynomial based on the divisor polynomial and the 0746 synthesized dividend polynomial (from the old remainder and the 0747 newly-provided input). The computations assume that a zero-valued 0748 string of bits will be appended to the message before extracting the 0749 CRC. 0750 0751 \pre \a Register is a built-in unsigned integer type 0752 \pre 0 \< \a register_length \<= std\::numeric_limits\<\a Register\> 0753 \::digits 0754 0755 \tparam Register The type used for representing the remainder and 0756 divisor modulo-2 polynomials. The bit at <code>2<sup>i</sup></code> 0757 is used as the coefficient of <i>x<sup>i</sup></i>. 0758 0759 \param[in] register_length The number of significant low-order bits 0760 to be used from \a Register values. It is the order of the modulo-2 0761 polynomial remainder and one less than the divisor's order. 0762 \param[in,out] remainder The upper part of the dividend polynomial 0763 before division, and the remainder polynomial after. 0764 \param[in] new_dividend_bit The coefficient for the constant term 0765 of the dividend polynomial. 0766 \param[in] truncated_divisor The lowest coefficients of the divisor 0767 polynomial. The highest-order coefficient is omitted and always 0768 assumed to be 1. 0769 0770 \note This routine performs straight-forward modulo-2 polynomial 0771 division. It assumes that an augment string will be processed at the 0772 end of the message bits before doing CRC analysis. 0773 \todo Use this function somewhere so I can test it. 0774 */ 0775 template < typename Register > 0776 inline void augmented_crc_modulo_update( int register_length, Register 0777 &remainder, bool new_dividend_bit, Register truncated_divisor ) 0778 { 0779 augmented_crc_modulo_word_update( register_length, remainder, 0780 static_cast<unsigned>(new_dividend_bit), truncated_divisor, 1, false ); 0781 } 0782 0783 /** \brief A mix-in class that returns its argument 0784 0785 This class template makes a function object that returns its argument 0786 as-is. It's one case for #possible_reflector. 0787 0788 \pre 0 \< \a BitLength \<= \c std\::numeric_limits\<uintmax_t\> 0789 \::digits 0790 0791 \tparam BitLength How many significant bits arguments have. 0792 */ 0793 template < int BitLength > 0794 class non_reflector 0795 { 0796 public: 0797 /** \brief The type to check for specialization 0798 0799 This is a Boost integral constant indicating that this class 0800 does not reflect its input values. 0801 */ 0802 typedef std::false_type is_reflecting_type; 0803 /** \brief The type to check for register bit length 0804 0805 This is a Boost integral constant indicating how many 0806 significant bits won't actually be reflected. 0807 */ 0808 typedef std::integral_constant< int, BitLength > width_c; 0809 /** \brief The type of (not-)reflected values 0810 0811 This type is the input and output type for the (possible-) 0812 reflection function, which does nothing here. 0813 */ 0814 typedef typename boost::crc_detail::uint_t< BitLength >::fast value_type; 0815 0816 /** \brief Does nothing 0817 0818 Returns the given value, not reflecting any part of it. 0819 0820 \param x The value to not be reflected. 0821 0822 \return \a x 0823 */ 0824 inline static value_type reflect_q( value_type x ) 0825 { return x; } 0826 }; 0827 0828 /** \brief A mix-in class that reflects (the lower part of) its argument, 0829 generally for types larger than a byte 0830 0831 This class template makes a function object that returns its argument 0832 after reflecting its lower-order bits. It's one sub-case for 0833 #possible_reflector. 0834 0835 \pre \c CHAR_BIT \< \a BitLength \<= \c std\::numeric_limits\<uintmax_t 0836 \>\::digits 0837 0838 \tparam BitLength How many significant bits arguments have. 0839 */ 0840 template < int BitLength > 0841 class super_byte_reflector 0842 { 0843 public: 0844 /** \brief The type to check for specialization 0845 0846 This is a Boost integral constant indicating that this class 0847 does reflect its input values. 0848 */ 0849 typedef std::true_type is_reflecting_type; 0850 /** \brief The type to check for register bit length 0851 0852 This is a Boost integral constant indicating how many 0853 significant bits will be reflected. 0854 */ 0855 typedef std::integral_constant< int, BitLength > width_c; 0856 /** \brief The type of reflected values 0857 0858 This is both the input and output type for the reflection function. 0859 */ 0860 typedef typename boost::crc_detail::uint_t< BitLength >::fast value_type; 0861 0862 /** \brief Reflect (part of) the given value 0863 0864 Reverses the order of the given number of bits within a value, 0865 using #reflect_unsigned. 0866 0867 \param x The value to be (partially) reflected. 0868 0869 \return ( <var>x</var> & 0870 ~(2<sup><var>width_c</var>\::value</sup> - 1) ) | REFLECT( 0871 <var>x</var> & (2<sup><var>width_c</var>\::value</sup> - 0872 1) ) 0873 */ 0874 inline static value_type reflect_q( value_type x ) 0875 { return reflect_unsigned(x, width_c::value); } 0876 }; 0877 0878 /** \brief A mix-in class that reflects (the lower part of) its argument, 0879 generally for bytes 0880 0881 This class template makes a function object that returns its argument 0882 after reflecting its lower-order bits. It's one sub-case for 0883 #possible_reflector. 0884 0885 \pre 0 \< \a BitLength \<= \c CHAR_BIT 0886 0887 \tparam BitLength How many significant bits arguments have. 0888 */ 0889 template < int BitLength > 0890 class sub_type_reflector 0891 { 0892 public: 0893 /** \brief The type to check for specialization 0894 0895 This is a Boost integral constant indicating that this class 0896 does reflect its input values. 0897 */ 0898 typedef std::true_type is_reflecting_type; 0899 /** \brief The type to check for register bit length 0900 0901 This is a Boost integral constant indicating how many 0902 significant bits will be reflected. 0903 */ 0904 typedef std::integral_constant< int, BitLength > width_c; 0905 /** \brief The type of reflected values 0906 0907 This is both the input and output type for the reflection function. 0908 */ 0909 typedef unsigned char value_type; 0910 0911 /** \brief Reflect (part of) the given value 0912 0913 Reverses the order of the given number of bits within a value, 0914 using #reflect_sub_byte. 0915 0916 \param x The value to be (partially) reflected. 0917 0918 \return ( <var>x</var> & 0919 ~(2<sup><var>width_c</var>\::value</sup> - 1) ) | REFLECT( 0920 <var>x</var> & (2<sup><var>width_c</var>\::value</sup> - 0921 1) ) 0922 */ 0923 inline static value_type reflect_q( value_type x ) 0924 { return reflect_sub_byte(x, width_c::value); } 0925 }; 0926 0927 /** \brief A mix-in class that reflects (the lower part of) its argument 0928 0929 This class template makes a function object that returns its argument 0930 after reflecting its lower-order bits. It's one case for 0931 #possible_reflector. 0932 0933 \pre 0 \< \a BitLength \<= \c std\::numeric_limits\<uintmax_t\> 0934 \::digits 0935 0936 \tparam BitLength How many significant bits arguments have. 0937 */ 0938 template < int BitLength > 0939 class reflector 0940 : public std::conditional< (BitLength > CHAR_BIT), 0941 super_byte_reflector<BitLength>, sub_type_reflector<BitLength> >::type 0942 { }; 0943 0944 /** This class template adds a member function #reflect_q that will 0945 conditionally reflect its first argument, controlled by a compile-time 0946 parameter. 0947 0948 \pre 0 \< \a BitLength \<= \c std\::numeric_limits\<uintmax_t\> 0949 \::digits 0950 0951 \tparam BitLength How many significant bits arguments have. 0952 \tparam DoIt \c true if #reflect_q will reflect, \c false if it should 0953 return its argument unchanged. 0954 \tparam Id An extra differentiator if multiple copies of this class 0955 template are mixed-in as base classes. Defaults to 0 if omitted. 0956 */ 0957 template < int BitLength, bool DoIt, int Id > 0958 class possible_reflector 0959 : public std::conditional< DoIt, reflector<BitLength>, 0960 non_reflector<BitLength> >::type 0961 { 0962 public: 0963 /** \brief The type to check for ID 0964 0965 This is a Boost integral constant indicating what ID number this 0966 instantiation used. 0967 */ 0968 typedef std::integral_constant<int, Id> id_type; 0969 }; 0970 0971 /** \brief Find the composite remainder update effect from a fixed bit 0972 sequence, for each potential sequence combination. 0973 0974 For each value between 0 and 2<sup><var>SubOrder</var></sup> - 1, 0975 computes the XOR mask corresponding to the composite effect they update 0976 the incoming remainder, which is the upper part of the dividend that 0977 gets (partially) pushed out of its register by the incoming value's 0978 bits. The composite value merges the \"partial products\" from each bit 0979 of the value being updated individually. 0980 0981 \pre \a Register is a built-in unsigned integer type 0982 \pre 0 \< \a SubOrder \<= \a register_length \<= 0983 std\::numeric_limits\<\a Register\>\::digits 0984 0985 \tparam SubOrder The number of low-order significant bits of the trial 0986 new dividends. 0987 \tparam Register The type used for representing the remainder and 0988 divisor modulo-2 polynomials. The bit at <code>2<sup>i</sup></code> 0989 is used as the coefficient of <i>x<sup>i</sup></i>. 0990 0991 \param[in] register_length The number of significant low-order bits 0992 to be used from \a Register values. It is the order of the modulo-2 0993 polynomial remainder and one less than the divisor's order. 0994 \param[in] truncated_divisor The lowest coefficients of the divisor 0995 polynomial. The highest-order coefficient is omitted and always 0996 assumed to be 1. 0997 \param[in] reflect If \c false, read from the highest-order marked 0998 bit from a new dividend's bits and go down, as normal. Otherwise, 0999 proceed from the lowest-order bit and go up. 1000 1001 \return An array such that the element at index <var>i</var> is the 1002 composite effect XOR mask for value <var>i</var>. 1003 1004 \note This routine performs a modulo-2 polynomial division variant. 1005 The exclusive-or operations are applied in a different order, since 1006 that kind of operation is commutative and associative. It also 1007 assumes that the zero-valued augment string was applied before this 1008 step, which means that the updated remainder can be directly used as 1009 the final CRC. 1010 \todo Check that using the unaugmented-CRC division routines give the 1011 same composite mask table as using augmented-CRC routines. 1012 */ 1013 template < int SubOrder, typename Register > 1014 std::array< Register, (UINTMAX_C( 1 ) << SubOrder) > 1015 make_partial_xor_products_table( int register_length, Register 1016 truncated_divisor, bool reflect ) 1017 { 1018 std::array<Register, ( UINTMAX_C(1) << SubOrder )> result = { 0 }; 1019 1020 // Loop over every possible dividend value 1021 for ( typename boost::crc_detail::uint_t<SubOrder + 1>::fast dividend = 0u; 1022 dividend < result.size() ; ++dividend ) 1023 { 1024 Register remainder = 0u; 1025 1026 crc_modulo_word_update( register_length, remainder, dividend, 1027 truncated_divisor, SubOrder, false ); 1028 result[ reflect_optionally(dividend, reflect, SubOrder) ] = 1029 reflect_optionally( remainder, reflect, register_length ); 1030 } 1031 return result; 1032 } 1033 1034 /** \brief A mix-in class for the table of table-driven CRC algorithms 1035 1036 Encapsulates the parameters need to make a global (technically, 1037 class-static) table usuable in CRC algorithms, and generates said 1038 table. 1039 1040 \pre 0 \< \a SubOrder \<= Order \<= 1041 std\::numeric_limits\<uintmax_t\>\::digits 1042 1043 \tparam Order The order of the modulo-2 polynomial remainder and one 1044 less than the divisor's order. 1045 \tparam SubOrder The number of low-order significant bits of the trial 1046 new dividends. 1047 \tparam TruncatedPolynomial The lowest coefficients of the divisor 1048 polynomial. The highest-order coefficient is omitted and always 1049 assumed to be 1. 1050 \tparam Reflect If \c false, read from the highest-order marked 1051 bit from a new dividend's bits and go down, as normal. Otherwise, 1052 proceed from the lowest-order bit and go up. 1053 */ 1054 template < int Order, int SubOrder, std::uintmax_t TruncatedPolynomial, 1055 bool Reflect > 1056 class crc_table_t 1057 { 1058 public: 1059 /** \brief The type to check for register bit length 1060 1061 This is a Boost integral constant indicating how many 1062 significant bits are in the remainder and (truncated) divisor. 1063 */ 1064 typedef std::integral_constant< int, Order > width_c; 1065 /** \brief The type to check for index-unit bit length 1066 1067 This is a Boost integral constant indicating how many 1068 significant bits are in the trial new dividends. 1069 */ 1070 typedef std::integral_constant< int, SubOrder > unit_width_c; 1071 /** \brief The type of registers 1072 1073 This is the output type for the partial-product map. 1074 */ 1075 typedef typename boost::crc_detail::uint_t< Order >::fast value_type; 1076 /** \brief The type to check the divisor 1077 1078 This is a Boost integral constant representing the (truncated) 1079 divisor. 1080 */ 1081 typedef std::integral_constant< value_type, TruncatedPolynomial > 1082 poly_c; 1083 /** \brief The type to check for reflection 1084 1085 This is a Boost integral constant representing whether input 1086 units should be read in reverse order. 1087 */ 1088 typedef std::integral_constant< bool, Reflect > refin_c; 1089 /** \brief The type to check for map size 1090 1091 This is a Boost integral constant representing the number of 1092 elements in the partial-product map, based on the unit size. 1093 */ 1094 typedef high_bit_mask_c< SubOrder > table_size_c; 1095 /** \brief The type of the unit TO partial-product map 1096 1097 This is the array type that takes units as the index and said unit's 1098 composite partial-product mask as the element. 1099 */ 1100 typedef std::array<value_type, table_size_c::value> array_type; 1101 /** \brief Create a global array for the mapping table 1102 1103 Creates an instance of a partial-product array with this class's 1104 parameters. 1105 1106 \return A reference to a immutable array giving the partial-product 1107 update XOR map for each potential sub-unit value. 1108 */ 1109 static array_type const & get_table() 1110 { 1111 static array_type const table = 1112 make_partial_xor_products_table<unit_width_c::value>( 1113 width_c::value, poly_c::value, refin_c::value ); 1114 1115 return table; 1116 } 1117 }; 1118 1119 /** \brief A mix-in class that handles direct (i.e. non-reflected) byte-fed 1120 table-driven CRC algorithms 1121 1122 This class template adds member functions #augmented_crc_update and 1123 #crc_update to update remainders from new input bytes. The bytes aren't 1124 reflected before processing. 1125 1126 \pre \c CHAR_BIT \<= \a Order \<= \c std\::numeric_limits\<uintmax_t\> 1127 \::digits 1128 1129 \tparam Order The order of the modulo-2 polynomial remainder and one 1130 less than the divisor's order. 1131 \tparam TruncatedPolynomial The lowest coefficients of the divisor 1132 polynomial. The highest-order coefficient is omitted and always 1133 assumed to be 1. 1134 */ 1135 template < int Order, std::uintmax_t TruncatedPolynomial > 1136 class direct_byte_table_driven_crcs 1137 : public crc_table_t<Order, CHAR_BIT, TruncatedPolynomial, false> 1138 { 1139 typedef crc_table_t<Order, CHAR_BIT, TruncatedPolynomial, false> 1140 base_type; 1141 1142 public: 1143 typedef typename base_type::value_type value_type; 1144 typedef typename base_type::array_type array_type; 1145 1146 /** \brief Compute the updated remainder after reading some bytes 1147 1148 The implementation reads from a table to speed-up applying 1149 augmented-CRC updates byte-wise. 1150 1151 \param remainder The pre-update remainder 1152 \param new_dividend_bytes The address where the new bytes start 1153 \param new_dividend_byte_count The number of new bytes to read 1154 1155 \return The updated remainder 1156 */ 1157 static value_type augmented_crc_update( value_type remainder, unsigned 1158 char const *new_dividend_bytes, std::size_t new_dividend_byte_count) 1159 { 1160 static array_type const & table = base_type::get_table(); 1161 1162 while ( new_dividend_byte_count-- ) 1163 { 1164 // Locates the merged partial product based on the leading byte 1165 unsigned char const index = ( remainder >> (Order - CHAR_BIT) ) 1166 & UCHAR_MAX; 1167 1168 // Complete the multi-bit modulo-2 polynomial division 1169 remainder <<= CHAR_BIT; 1170 remainder |= *new_dividend_bytes++; 1171 remainder ^= table[ index ]; 1172 } 1173 1174 return remainder; 1175 } 1176 1177 /** \brief Compute the updated remainder after reading some bytes 1178 1179 The implementation reads from a table to speed-up applying 1180 unaugmented-CRC updates byte-wise. 1181 1182 \param remainder The pre-update remainder 1183 \param new_dividend_bytes The address where the new bytes start 1184 \param new_dividend_byte_count The number of new bytes to read 1185 1186 \return The updated remainder 1187 */ 1188 static value_type crc_update( value_type remainder, unsigned char 1189 const *new_dividend_bytes, std::size_t new_dividend_byte_count) 1190 { 1191 static array_type const & table = base_type::get_table(); 1192 1193 while ( new_dividend_byte_count-- ) 1194 { 1195 // Locates the merged partial product based on comparing the 1196 // leading and incoming bytes 1197 unsigned char const index = ( (remainder >> ( Order - CHAR_BIT 1198 )) & UCHAR_MAX ) ^ *new_dividend_bytes++; 1199 1200 // Complete the multi-bit altered modulo-2 polynomial division 1201 remainder <<= CHAR_BIT; 1202 remainder ^= table[ index ]; 1203 } 1204 1205 return remainder; 1206 } 1207 }; 1208 1209 /** \brief A mix-in class that handles reflected byte-fed, table-driven CRC 1210 algorithms 1211 1212 This class template adds member functions #augmented_crc_update and 1213 #crc_update to update remainders from new input bytes. The bytes are 1214 reflected before processing. 1215 1216 \pre \c CHAR_BIT \<= \a Order \<= \c std\::numeric_limits\<uintmax_t\> 1217 \::digits 1218 1219 \tparam Order The order of the modulo-2 polynomial remainder and one 1220 less than the divisor's order. 1221 \tparam TruncatedPolynomial The lowest coefficients of the divisor 1222 polynomial. The highest-order coefficient is omitted and always 1223 assumed to be 1. 1224 */ 1225 template < int Order, std::uintmax_t TruncatedPolynomial > 1226 class reflected_byte_table_driven_crcs 1227 : public crc_table_t<Order, CHAR_BIT, TruncatedPolynomial, true> 1228 { 1229 typedef crc_table_t<Order, CHAR_BIT, TruncatedPolynomial, true> 1230 base_type; 1231 1232 public: 1233 typedef typename base_type::value_type value_type; 1234 typedef typename base_type::array_type array_type; 1235 1236 /** \brief Compute the updated remainder after reading some bytes 1237 1238 The implementation reads from a table to speed-up applying 1239 reflecting augmented-CRC updates byte-wise. 1240 1241 \param remainder The pre-update remainder; since the bytes are 1242 being reflected, this remainder also has to be reflected 1243 \param new_dividend_bytes The address where the new bytes start 1244 \param new_dividend_byte_count The number of new bytes to read 1245 1246 \return The updated, reflected remainder 1247 */ 1248 static value_type augmented_crc_update( value_type remainder, unsigned 1249 char const *new_dividend_bytes, std::size_t new_dividend_byte_count) 1250 { 1251 static array_type const & table = base_type::get_table(); 1252 1253 while ( new_dividend_byte_count-- ) 1254 { 1255 // Locates the merged partial product based on the leading byte 1256 // (which is at the low-order end for reflected remainders) 1257 unsigned char const index = remainder & UCHAR_MAX; 1258 1259 // Complete the multi-bit reflected modulo-2 polynomial division 1260 remainder >>= CHAR_BIT; 1261 remainder |= static_cast<value_type>( *new_dividend_bytes++ ) 1262 << ( Order - CHAR_BIT ); 1263 remainder ^= table[ index ]; 1264 } 1265 1266 return remainder; 1267 } 1268 1269 /** \brief Compute the updated remainder after reading some bytes 1270 1271 The implementation reads from a table to speed-up applying 1272 reflected unaugmented-CRC updates byte-wise. 1273 1274 \param remainder The pre-update remainder; since the bytes are 1275 being reflected, this remainder also has to be reflected 1276 \param new_dividend_bytes The address where the new bytes start 1277 \param new_dividend_byte_count The number of new bytes to read 1278 1279 \return The updated, reflected remainder 1280 */ 1281 static value_type crc_update( value_type remainder, unsigned char 1282 const *new_dividend_bytes, std::size_t new_dividend_byte_count) 1283 { 1284 static array_type const & table = base_type::get_table(); 1285 1286 while ( new_dividend_byte_count-- ) 1287 { 1288 // Locates the merged partial product based on comparing the 1289 // leading and incoming bytes 1290 unsigned char const index = ( remainder & UCHAR_MAX ) ^ 1291 *new_dividend_bytes++; 1292 1293 // Complete the multi-bit reflected altered modulo-2 polynomial 1294 // division 1295 remainder >>= CHAR_BIT; 1296 remainder ^= table[ index ]; 1297 } 1298 1299 return remainder; 1300 } 1301 }; 1302 1303 /** \brief Mix-in class for byte-fed, table-driven CRC algorithms with 1304 parameter values at least a byte in width 1305 1306 This class template adds member functions #augmented_crc_update and 1307 #crc_update to update remainders from new input bytes. The bytes may be 1308 reflected before processing, controlled by a compile-time parameter. 1309 1310 \pre \c CHAR_BIT \<= \a Order \<= \c std\::numeric_limits\<uintmax_t\> 1311 \::digits 1312 1313 \tparam Order The order of the modulo-2 polynomial remainder and one 1314 less than the divisor's order. 1315 \tparam TruncatedPolynomial The lowest coefficients of the divisor 1316 polynomial. The highest-order coefficient is omitted and always 1317 assumed to be 1. 1318 \tparam Reflect If \c false, read from the highest-order bit from a new 1319 input byte and go down, as normal. Otherwise, proceed from the 1320 lowest-order bit and go up. 1321 */ 1322 template < int Order, std::uintmax_t TruncatedPolynomial, bool Reflect > 1323 class byte_table_driven_crcs 1324 : public std::conditional< Reflect, 1325 reflected_byte_table_driven_crcs<Order, TruncatedPolynomial>, 1326 direct_byte_table_driven_crcs<Order, TruncatedPolynomial> >::type 1327 { }; 1328 1329 /** \brief A mix-in class that handles direct (i.e. non-reflected) byte-fed 1330 CRC algorithms for sub-byte parameters 1331 1332 This class template adds member functions #augmented_crc_update and 1333 #crc_update to update remainders from new input bytes. The bytes aren't 1334 reflected before processing. 1335 1336 \pre 0 \< \a Order \< \c CHAR_BIT 1337 1338 \tparam Order The order of the modulo-2 polynomial remainder and one 1339 less than the divisor's order. 1340 \tparam TruncatedPolynomial The lowest coefficients of the divisor 1341 polynomial. The highest-order coefficient is omitted and always 1342 assumed to be 1. 1343 */ 1344 template < int Order, std::uintmax_t TruncatedPolynomial > 1345 class direct_sub_byte_crcs 1346 : public crc_table_t<Order, Order, TruncatedPolynomial, false> 1347 { 1348 typedef crc_table_t<Order, Order, TruncatedPolynomial, false> 1349 base_type; 1350 1351 public: 1352 typedef typename base_type::width_c width_c; 1353 typedef typename base_type::value_type value_type; 1354 typedef typename base_type::poly_c poly_c; 1355 typedef typename base_type::array_type array_type; 1356 1357 /** \brief Compute the updated remainder after reading some bytes 1358 1359 The implementation reads from a table to speed-up applying 1360 augmented-CRC updates byte-wise. 1361 1362 \param remainder The pre-update remainder 1363 \param new_dividend_bytes The address where the new bytes start 1364 \param new_dividend_byte_count The number of new bytes to read 1365 1366 \return The updated remainder 1367 1368 \todo Use this function somewhere so I can test it. 1369 */ 1370 static value_type augmented_crc_update( value_type remainder, unsigned 1371 char const *new_dividend_bytes, std::size_t new_dividend_byte_count) 1372 { 1373 //static array_type const & table = base_type::get_table(); 1374 1375 while ( new_dividend_byte_count-- ) 1376 { 1377 // Without a table, process each byte explicitly 1378 augmented_crc_modulo_word_update( width_c::value, remainder, 1379 *new_dividend_bytes++, poly_c::value, CHAR_BIT, false ); 1380 } 1381 1382 return remainder; 1383 } 1384 1385 /** \brief Compute the updated remainder after reading some bytes 1386 1387 The implementation reads from a table to speed-up applying 1388 unaugmented-CRC updates byte-wise. 1389 1390 \param remainder The pre-update remainder 1391 \param new_dividend_bytes The address where the new bytes start 1392 \param new_dividend_byte_count The number of new bytes to read 1393 1394 \return The updated remainder 1395 */ 1396 static value_type crc_update( value_type remainder, unsigned char 1397 const *new_dividend_bytes, std::size_t new_dividend_byte_count) 1398 { 1399 //static array_type const & table = base_type::get_table(); 1400 1401 while ( new_dividend_byte_count-- ) 1402 { 1403 // Without a table, process each byte explicitly 1404 crc_modulo_word_update( width_c::value, remainder, 1405 *new_dividend_bytes++, poly_c::value, CHAR_BIT, false ); 1406 } 1407 1408 return remainder; 1409 } 1410 }; 1411 1412 /** \brief A mix-in class that handles reflected byte-fed, CRC algorithms 1413 for sub-byte parameters 1414 1415 This class template adds member functions #augmented_crc_update and 1416 #crc_update to update remainders from new input bytes. The bytes are 1417 reflected before processing. 1418 1419 \pre 0 \< \a Order \< \c CHAR_BIT 1420 1421 \tparam Order The order of the modulo-2 polynomial remainder and one 1422 less than the divisor's order. 1423 \tparam TruncatedPolynomial The lowest coefficients of the divisor 1424 polynomial. The highest-order coefficient is omitted and always 1425 assumed to be 1. 1426 */ 1427 template < int Order, std::uintmax_t TruncatedPolynomial > 1428 class reflected_sub_byte_crcs 1429 : public crc_table_t<Order, Order, TruncatedPolynomial, true> 1430 { 1431 typedef crc_table_t<Order, Order, TruncatedPolynomial, true> 1432 base_type; 1433 1434 public: 1435 typedef typename base_type::width_c width_c; 1436 typedef typename base_type::value_type value_type; 1437 typedef typename base_type::poly_c poly_c; 1438 typedef typename base_type::array_type array_type; 1439 1440 /** \brief Compute the updated remainder after reading some bytes 1441 1442 The implementation reads from a table to speed-up applying 1443 reflecting augmented-CRC updates byte-wise. 1444 1445 \param remainder The pre-update remainder; since the bytes are 1446 being reflected, this remainder also has to be reflected 1447 \param new_dividend_bytes The address where the new bytes start 1448 \param new_dividend_byte_count The number of new bytes to read 1449 1450 \return The updated, reflected remainder 1451 1452 \todo Use this function somewhere so I can test it. 1453 */ 1454 static value_type augmented_crc_update( value_type remainder, unsigned 1455 char const *new_dividend_bytes, std::size_t new_dividend_byte_count) 1456 { 1457 //static array_type const & table = base_type::get_table(); 1458 1459 remainder = reflect_sub_byte( remainder, width_c::value ); 1460 while ( new_dividend_byte_count-- ) 1461 { 1462 // Without a table, process each byte explicitly 1463 augmented_crc_modulo_word_update( width_c::value, remainder, 1464 *new_dividend_bytes++, poly_c::value, CHAR_BIT, true ); 1465 } 1466 remainder = reflect_sub_byte( remainder, width_c::value ); 1467 1468 return remainder; 1469 } 1470 1471 /** \brief Compute the updated remainder after reading some bytes 1472 1473 The implementation reads from a table to speed-up applying 1474 reflected unaugmented-CRC updates byte-wise. 1475 1476 \param remainder The pre-update remainder; since the bytes are 1477 being reflected, this remainder also has to be reflected 1478 \param new_dividend_bytes The address where the new bytes start 1479 \param new_dividend_byte_count The number of new bytes to read 1480 1481 \return The updated, reflected remainder 1482 */ 1483 static value_type crc_update( value_type remainder, unsigned char 1484 const *new_dividend_bytes, std::size_t new_dividend_byte_count) 1485 { 1486 //static array_type const & table = base_type::get_table(); 1487 1488 remainder = reflect_sub_byte( remainder, width_c::value ); 1489 while ( new_dividend_byte_count-- ) 1490 { 1491 // Without a table, process each byte explicitly 1492 crc_modulo_word_update( width_c::value, remainder, 1493 *new_dividend_bytes++, poly_c::value, CHAR_BIT, true ); 1494 } 1495 remainder = reflect_sub_byte( remainder, width_c::value ); 1496 1497 return remainder; 1498 } 1499 }; 1500 1501 /** \brief Mix-in class for byte-fed, table-driven CRC algorithms with 1502 sub-byte parameters 1503 1504 This class template adds member functions #augmented_crc_update and 1505 #crc_update to update remainders from new input bytes. The bytes may be 1506 reflected before processing, controlled by a compile-time parameter. 1507 1508 \pre 0 \< \a Order \< \c CHAR_BIT 1509 1510 \tparam Order The order of the modulo-2 polynomial remainder and one 1511 less than the divisor's order. 1512 \tparam TruncatedPolynomial The lowest coefficients of the divisor 1513 polynomial. The highest-order coefficient is omitted and always 1514 assumed to be 1. 1515 \tparam Reflect If \c false, read from the highest-order bit from a new 1516 input byte and go down, as normal. Otherwise, proceed from the 1517 lowest-order bit and go up. 1518 */ 1519 template < int Order, std::uintmax_t TruncatedPolynomial, bool Reflect > 1520 class sub_byte_crcs 1521 : public std::conditional< Reflect, 1522 reflected_sub_byte_crcs<Order, TruncatedPolynomial>, 1523 direct_sub_byte_crcs<Order, TruncatedPolynomial> >::type 1524 { }; 1525 1526 /** This class template adds member functions #augmented_crc_update and 1527 #crc_update to update remainders from new input bytes. The bytes may be 1528 reflected before processing, controlled by a compile-time parameter. 1529 1530 \pre 0 \< \a Order \<= \c std\::numeric_limits\<uintmax_t\>\::digits 1531 1532 \tparam Order The order of the modulo-2 polynomial remainder and one 1533 less than the divisor's order. 1534 \tparam TruncatedPolynomial The lowest coefficients of the divisor 1535 polynomial. The highest-order coefficient is omitted and always 1536 assumed to be 1. 1537 \tparam Reflect If \c false, read from the highest-order bit from a new 1538 input byte and go down, as normal. Otherwise, proceed from the 1539 lowest-order bit and go up. 1540 \tparam Id An extra differentiator if multiple copies of this class 1541 template are mixed-in as base classes. Defaults to 0 if omitted. 1542 */ 1543 template < int Order, std::uintmax_t TruncatedPolynomial, bool Reflect, 1544 int Id > 1545 class crc_driver 1546 : public std::conditional< (Order < CHAR_BIT), sub_byte_crcs<Order, 1547 TruncatedPolynomial, Reflect>, byte_table_driven_crcs<Order, 1548 TruncatedPolynomial, Reflect> >::type 1549 { 1550 public: 1551 /** \brief The type to check for ID 1552 1553 This is a Boost integral constant indicating what ID number this 1554 instantiation used. 1555 */ 1556 typedef std::integral_constant<int, Id> id_type; 1557 }; 1558 1559 1560 } // namespace detail 1561 //! \endcond 1562 1563 1564 // Simple CRC class function definitions -----------------------------------// 1565 1566 /** Constructs a \c crc_basic object with at least the required parameters to a 1567 particular CRC formula to be processed upon receiving input. 1568 1569 \param[in] truncated_polynomial The lowest coefficients of the divisor 1570 polynomial. The highest-order coefficient is omitted and always assumed 1571 to be 1. (\e Poly from the RMCA) 1572 \param[in] initial_remainder The (unaugmented) initial state of the 1573 polynomial remainder. Defaults to \c 0 if omitted. (\e Init from the 1574 RMCA) 1575 \param[in] final_xor_value The (XOR) bit-mask to be applied to the output 1576 remainder, after possible reflection but before returning. Defaults to 1577 \c 0 (i.e. no bit changes) if omitted. (\e XorOut from the RMCA) 1578 \param[in] reflect_input If \c true, input bytes are read lowest-order bit 1579 first, otherwise highest-order bit first. Defaults to \c false if 1580 omitted. (\e RefIn from the RMCA) 1581 \param[in] reflect_remainder If \c true, the output remainder is reflected 1582 before the XOR-mask. Defaults to \c false if omitted. (\e RefOut from 1583 the RMCA) 1584 1585 \post <code><var>truncated_polynomial</var> == 1586 this->get_truncated_polynominal()</code> 1587 \post <code><var>initial_remainder</var> == 1588 this->get_initial_remainder()</code> 1589 \post <code><var>final_xor_value</var> == 1590 this->get_final_xor_value()</code> 1591 \post <code><var>reflect_input</var> == 1592 this->get_reflect_input()</code> 1593 \post <code><var>reflect_remainder</var> == 1594 this->get_reflect_remainder()</code> 1595 \post <code><var>initial_remainder</var> == 1596 this->get_interim_remainder()</code> 1597 \post <code>(<var>reflect_remainder</var> ? 1598 REFLECT(<var>initial_remainder</var>) : <var>initial_remainder</var>) ^ 1599 <var>final_xor_value</var> == this->checksum()</code> 1600 */ 1601 template < std::size_t Bits > 1602 inline 1603 crc_basic<Bits>::crc_basic 1604 ( 1605 value_type truncated_polynomial, 1606 value_type initial_remainder, // = 0 1607 value_type final_xor_value, // = 0 1608 bool reflect_input, // = false 1609 bool reflect_remainder // = false 1610 ) 1611 : rem_( initial_remainder ), poly_( truncated_polynomial ) 1612 , init_( initial_remainder ), final_( final_xor_value ) 1613 , rft_in_( reflect_input ), rft_out_( reflect_remainder ) 1614 { 1615 } 1616 1617 /** Returns a representation of the polynomial divisor. The value of the 1618 2<sup>i</sup> bit is the value of the coefficient of the polynomial's 1619 x<sup>i</sup> term. The omitted bit for x<sup>(#bit_count)</sup> term is 1620 always 1. 1621 1622 \return The bit-packed list of coefficients. If the bit-length of 1623 #value_type exceeds #bit_count, the values of higher-placed bits should be 1624 ignored (even any for x<sup>(#bit_count)</sup>) since they're unregulated. 1625 */ 1626 template < std::size_t Bits > 1627 inline 1628 typename crc_basic<Bits>::value_type 1629 crc_basic<Bits>::get_truncated_polynominal 1630 ( 1631 ) const 1632 { 1633 return poly_; 1634 } 1635 1636 /** Returns a representation of the polynomial remainder before any input has 1637 been submitted. The value of the 2<sup>i</sup> bit is the value of the 1638 coefficient of the polynomial's x<sup>i</sup> term. 1639 1640 \return The bit-packed list of coefficients. If the bit-length of 1641 #value_type exceeds #bit_count, the values of higher-placed bits should be 1642 ignored since they're unregulated. 1643 */ 1644 template < std::size_t Bits > 1645 inline 1646 typename crc_basic<Bits>::value_type 1647 crc_basic<Bits>::get_initial_remainder 1648 ( 1649 ) const 1650 { 1651 return init_; 1652 } 1653 1654 /** Returns the mask to be used during creation of a checksum. The mask is used 1655 for an exclusive-or (XOR) operation applied bit-wise to the interim 1656 remainder representation (after any reflection, if #get_reflect_remainder() 1657 returns \c true). 1658 1659 \return The bit-mask. If the bit-length of #value_type exceeds #bit_count, 1660 the values of higher-placed bits should be ignored since they're 1661 unregulated. 1662 */ 1663 template < std::size_t Bits > 1664 inline 1665 typename crc_basic<Bits>::value_type 1666 crc_basic<Bits>::get_final_xor_value 1667 ( 1668 ) const 1669 { 1670 return final_; 1671 } 1672 1673 /** Returns a whether or not a submitted byte will be \"reflected\" before it is 1674 used to update the interim remainder. Only the byte-wise operations 1675 #process_byte, #process_block, and #process_bytes are affected. 1676 1677 \retval true Input bytes will be read starting from the lowest-order bit. 1678 \retval false Input bytes will be read starting from the highest-order bit. 1679 */ 1680 template < std::size_t Bits > 1681 inline 1682 bool 1683 crc_basic<Bits>::get_reflect_input 1684 ( 1685 ) const 1686 { 1687 return rft_in_; 1688 } 1689 1690 /** Indicates if the interim remainder will be \"reflected\" before it is passed 1691 to the XOR-mask stage when returning a checksum. 1692 1693 \retval true The interim remainder is reflected before further work. 1694 \retval false The interim remainder is applied to the XOR-mask as-is. 1695 */ 1696 template < std::size_t Bits > 1697 inline 1698 bool 1699 crc_basic<Bits>::get_reflect_remainder 1700 ( 1701 ) const 1702 { 1703 return rft_out_; 1704 } 1705 1706 /** Returns a representation of the polynomial remainder after all the input 1707 submissions since construction or the last #reset call. The value of the 1708 2<sup>i</sup> bit is the value of the coefficient of the polynomial's 1709 x<sup>i</sup> term. If CRC processing gets interrupted here, retain the 1710 value returned, and use it to start up the next CRC computer where you left 1711 off (with #reset(value_type) or construction). The next computer has to 1712 have its other parameters compatible with this computer. 1713 1714 \return The bit-packed list of coefficients. If the bit-length of 1715 #value_type exceeds #bit_count, the values of higher-placed bits should be 1716 ignored since they're unregulated. No output processing (reflection or 1717 XOR mask) has been applied to the value. 1718 */ 1719 template < std::size_t Bits > 1720 inline 1721 typename crc_basic<Bits>::value_type 1722 crc_basic<Bits>::get_interim_remainder 1723 ( 1724 ) const 1725 { 1726 return rem_ & detail::low_bits_mask_c<bit_count>::value; 1727 } 1728 1729 /** Changes the interim polynomial remainder to \a new_rem, purging any 1730 influence previously submitted input has had. The value of the 1731 2<sup>i</sup> bit is the value of the coefficient of the polynomial's 1732 x<sup>i</sup> term. 1733 1734 \param[in] new_rem The (unaugmented) state of the polynomial remainder 1735 starting from this point, with no output processing applied. 1736 1737 \post <code><var>new_rem</var> == this->get_interim_remainder()</code> 1738 \post <code>((this->get_reflect_remainder() ? 1739 REFLECT(<var>new_rem</var>) : <var>new_rem</var>) ^ 1740 this->get_final_xor_value()) == this->checksum()</code> 1741 */ 1742 template < std::size_t Bits > 1743 inline 1744 void 1745 crc_basic<Bits>::reset 1746 ( 1747 value_type new_rem 1748 ) 1749 { 1750 rem_ = new_rem; 1751 } 1752 1753 /** Changes the interim polynomial remainder to the initial remainder given 1754 during construction, purging any influence previously submitted input has 1755 had. The value of the 2<sup>i</sup> bit is the value of the coefficient of 1756 the polynomial's x<sup>i</sup> term. 1757 1758 \post <code>this->get_initial_remainder() == 1759 this->get_interim_remainder()</code> 1760 \post <code>((this->get_reflect_remainder() ? 1761 REFLECT(this->get_initial_remainder()) : 1762 this->get_initial_remainder()) ^ this->get_final_xor_value()) 1763 == this->checksum()</code> 1764 */ 1765 template < std::size_t Bits > 1766 inline 1767 void 1768 crc_basic<Bits>::reset 1769 ( 1770 ) 1771 { 1772 this->reset( this->get_initial_remainder() ); 1773 } 1774 1775 /** Updates the interim remainder with a single altered-CRC-division step. 1776 1777 \param[in] bit The new input bit. 1778 1779 \post The interim remainder is updated though a modulo-2 polynomial 1780 division, where the division steps are altered for unaugmented CRCs. 1781 */ 1782 template < std::size_t Bits > 1783 inline 1784 void 1785 crc_basic<Bits>::process_bit 1786 ( 1787 bool bit 1788 ) 1789 { 1790 detail::crc_modulo_update( bit_count, rem_, bit, poly_ ); 1791 } 1792 1793 /** Updates the interim remainder with several altered-CRC-division steps. Each 1794 bit is processed separately, starting from the one at the 1795 2<sup><var>bit_length</var> - 1</sup> place, then proceeding down to the 1796 lowest-placed bit. Any order imposed by 1797 <code>this->get_reflect_input()</code> is ignored. 1798 1799 \pre 0 \< \a bit_length \<= \c CHAR_BIT 1800 1801 \param[in] bits The byte containing the new input bits. 1802 \param[in] bit_length The number of bits in the byte to be read. 1803 1804 \post The interim remainder is updated though \a bit_length modulo-2 1805 polynomial divisions, where the division steps are altered for unaugmented 1806 CRCs. 1807 */ 1808 template < std::size_t Bits > 1809 void 1810 crc_basic<Bits>::process_bits 1811 ( 1812 unsigned char bits, 1813 std::size_t bit_length 1814 ) 1815 { 1816 // ignore the bits above the ones we want 1817 bits <<= CHAR_BIT - bit_length; 1818 1819 // compute the CRC for each bit, starting with the upper ones 1820 unsigned char const high_bit_mask = 1u << ( CHAR_BIT - 1u ); 1821 for ( std::size_t i = bit_length ; i > 0u ; --i, bits <<= 1u ) 1822 { 1823 process_bit( (bits & high_bit_mask) != 0 ); 1824 } 1825 } 1826 1827 /** Updates the interim remainder with a byte's worth of altered-CRC-division 1828 steps. The bits within the byte are processed from the highest place down 1829 if <code>this->get_reflect_input()</code> is \c false, and lowest place 1830 up otherwise. 1831 1832 \param[in] byte The new input byte. 1833 1834 \post The interim remainder is updated though \c CHAR_BIT modulo-2 1835 polynomial divisions, where the division steps are altered for unaugmented 1836 CRCs. 1837 */ 1838 template < std::size_t Bits > 1839 inline 1840 void 1841 crc_basic<Bits>::process_byte 1842 ( 1843 unsigned char byte 1844 ) 1845 { 1846 process_bits( (rft_in_ ? detail::reflect_byte( byte ) : byte), CHAR_BIT ); 1847 } 1848 1849 /** Updates the interim remainder with several bytes' worth of 1850 altered-CRC-division steps. The bits within each byte are processed from 1851 the highest place down if <code>this->get_reflect_input()</code> is 1852 \c false, and lowest place up otherwise. The bytes themselves are processed 1853 starting from the one pointed by \a bytes_begin until \a bytes_end is 1854 reached through forward iteration, treating the two pointers as if they 1855 point to <code>unsigned char</code> objects. 1856 1857 \pre \a bytes_end has to equal \a bytes_begin if the latter is \c NULL or 1858 otherwise doesn't point to a valid buffer. 1859 \pre \a bytes_end, if not equal to \a bytes_begin, has to point within or 1860 one-byte-past the same buffer \a bytes_begin points into. 1861 \pre \a bytes_end has to be reachable from \a bytes_begin through a finite 1862 number of forward byte-pointer increments. 1863 1864 \param[in] bytes_begin The address where the memory block begins. 1865 \param[in] bytes_end Points to one-byte past the address of the memory 1866 block's last byte, or \a bytes_begin if no bytes are to be read. 1867 1868 \post The interim remainder is updated though <code>CHAR_BIT * (((unsigned 1869 char const *) bytes_end) - ((unsigned char const *) bytes_begin))</code> 1870 modulo-2 polynomial divisions, where the division steps are altered for 1871 unaugmented CRCs. 1872 */ 1873 template < std::size_t Bits > 1874 void 1875 crc_basic<Bits>::process_block 1876 ( 1877 void const * bytes_begin, 1878 void const * bytes_end 1879 ) 1880 { 1881 for ( unsigned char const * p 1882 = static_cast<unsigned char const *>(bytes_begin) ; p < bytes_end ; ++p ) 1883 { 1884 process_byte( *p ); 1885 } 1886 } 1887 1888 /** Updates the interim remainder with several bytes' worth of 1889 altered-CRC-division steps. The bits within each byte are processed from 1890 the highest place down if <code>this->get_reflect_input()</code> is 1891 \c false, and lowest place up otherwise. The bytes themselves are processed 1892 starting from the one pointed by \a buffer, forward-iterated (as if the 1893 pointed-to objects were of <code>unsigned char</code>) until \a byte_count 1894 bytes are read. 1895 1896 \pre \a byte_count has to equal 0 if \a buffer is \c NULL or otherwise 1897 doesn't point to valid memory. 1898 \pre If \a buffer points within valid memory, then that block has to have 1899 at least \a byte_count more valid bytes allocated from that point. 1900 1901 \param[in] buffer The address where the memory block begins. 1902 \param[in] byte_count The number of bytes in the memory block. 1903 1904 \post The interim remainder is updated though <code>CHAR_BIT * 1905 <var>byte_count</var></code> modulo-2 polynomial divisions, where the 1906 division steps are altered for unaugmented CRCs. 1907 */ 1908 template < std::size_t Bits > 1909 inline 1910 void 1911 crc_basic<Bits>::process_bytes 1912 ( 1913 void const * buffer, 1914 std::size_t byte_count 1915 ) 1916 { 1917 unsigned char const * const b = static_cast<unsigned char const *>( 1918 buffer ); 1919 1920 process_block( b, b + byte_count ); 1921 } 1922 1923 /** Computes the checksum of all the submitted bits since construction or the 1924 last call to #reset. The checksum will be the raw checksum, i.e. the 1925 (interim) remainder after all the modulo-2 polynomial division, plus any 1926 output processing. 1927 1928 \return <code>(this->get_reflect_remainder() ? 1929 REFLECT(this->get_interim_remainder()) : 1930 this->get_interim_remainder()) ^ this->get_final_xor_value()</code> 1931 1932 \note Since checksums are meant to be compared, any higher-placed bits 1933 (when the bit-length of #value_type exceeds #bit_count) will be set to 0. 1934 */ 1935 template < std::size_t Bits > 1936 inline 1937 typename crc_basic<Bits>::value_type 1938 crc_basic<Bits>::checksum 1939 ( 1940 ) const 1941 { 1942 return ( (rft_out_ ? detail::reflect_unsigned( rem_, bit_count ) : 1943 rem_) ^ final_ ) & detail::low_bits_mask_c<bit_count>::value; 1944 } 1945 1946 1947 // Optimized CRC class function definitions --------------------------------// 1948 1949 // Macro to compact code 1950 #define BOOST_CRC_OPTIMAL_NAME crc_optimal<Bits, TruncPoly, InitRem, \ 1951 FinalXor, ReflectIn, ReflectRem> 1952 1953 /** Constructs a \c crc_optimal object with a particular CRC formula to be 1954 processed upon receiving input. The initial remainder may be overridden. 1955 1956 \param[in] init_rem The (unaugmented) initial state of the polynomial 1957 remainder. Defaults to #initial_remainder if omitted. 1958 1959 \post <code>#truncated_polynominal == 1960 this->get_truncated_polynominal()</code> 1961 \post <code>#initial_remainder == this->get_initial_remainder()</code> 1962 \post <code>#final_xor_value == this->get_final_xor_value()</code> 1963 \post <code>#reflect_input == this->get_reflect_input()</code> 1964 \post <code>#reflect_remainder == this->get_reflect_remainder()</code> 1965 \post <code><var>init_rem</var> == this->get_interim_remainder()</code> 1966 \post <code>(#reflect_remainder ? REFLECT(<var>init_rem</var>) : 1967 <var>init_rem</var>) ^ #final_xor_value == this->checksum()</code> 1968 */ 1969 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 1970 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 1971 bool ReflectIn, bool ReflectRem > 1972 inline 1973 BOOST_CRC_OPTIMAL_NAME::crc_optimal 1974 ( 1975 value_type init_rem // = initial_remainder 1976 ) 1977 : rem_( reflect_i_type::reflect_q(init_rem) ) 1978 { 1979 } 1980 1981 //! \copydetails boost::crc_basic::get_truncated_polynominal 1982 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 1983 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 1984 bool ReflectIn, bool ReflectRem > 1985 inline 1986 typename BOOST_CRC_OPTIMAL_NAME::value_type 1987 BOOST_CRC_OPTIMAL_NAME::get_truncated_polynominal 1988 ( 1989 ) const 1990 { 1991 return truncated_polynominal; 1992 } 1993 1994 //! \copydetails boost::crc_basic::get_initial_remainder 1995 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 1996 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 1997 bool ReflectIn, bool ReflectRem > 1998 inline 1999 typename BOOST_CRC_OPTIMAL_NAME::value_type 2000 BOOST_CRC_OPTIMAL_NAME::get_initial_remainder 2001 ( 2002 ) const 2003 { 2004 return initial_remainder; 2005 } 2006 2007 //! \copydetails boost::crc_basic::get_final_xor_value 2008 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2009 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2010 bool ReflectIn, bool ReflectRem > 2011 inline 2012 typename BOOST_CRC_OPTIMAL_NAME::value_type 2013 BOOST_CRC_OPTIMAL_NAME::get_final_xor_value 2014 ( 2015 ) const 2016 { 2017 return final_xor_value; 2018 } 2019 2020 //! \copydetails boost::crc_basic::get_reflect_input 2021 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2022 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2023 bool ReflectIn, bool ReflectRem > 2024 inline 2025 bool 2026 BOOST_CRC_OPTIMAL_NAME::get_reflect_input 2027 ( 2028 ) const 2029 { 2030 return reflect_input; 2031 } 2032 2033 //! \copydetails boost::crc_basic::get_reflect_remainder 2034 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2035 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2036 bool ReflectIn, bool ReflectRem > 2037 inline 2038 bool 2039 BOOST_CRC_OPTIMAL_NAME::get_reflect_remainder 2040 ( 2041 ) const 2042 { 2043 return reflect_remainder; 2044 } 2045 2046 //! \copydetails boost::crc_basic::get_interim_remainder 2047 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2048 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2049 bool ReflectIn, bool ReflectRem > 2050 inline 2051 typename BOOST_CRC_OPTIMAL_NAME::value_type 2052 BOOST_CRC_OPTIMAL_NAME::get_interim_remainder 2053 ( 2054 ) const 2055 { 2056 // Interim remainder should be _un_-reflected, so we have to undo it. 2057 return reflect_i_type::reflect_q( rem_ ) & 2058 detail::low_bits_mask_c<bit_count>::value; 2059 } 2060 2061 /** Changes the interim polynomial remainder to \a new_rem, purging any 2062 influence previously submitted input has had. The value of the 2063 2<sup>i</sup> bit is the value of the coefficient of the polynomial's 2064 x<sup>i</sup> term. 2065 2066 \param[in] new_rem The (unaugmented) state of the polynomial remainder 2067 starting from this point, with no output processing applied. Defaults to 2068 <code>this->get_initial_remainder()</code> if omitted. 2069 2070 \post <code><var>new_rem</var> == this->get_interim_remainder()</code> 2071 \post <code>((this->get_reflect_remainder() ? 2072 REFLECT(<var>new_rem</var>) : <var>new_rem</var>) ^ 2073 this->get_final_xor_value()) == this->checksum()</code> 2074 */ 2075 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2076 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2077 bool ReflectIn, bool ReflectRem > 2078 inline 2079 void 2080 BOOST_CRC_OPTIMAL_NAME::reset 2081 ( 2082 value_type new_rem // = initial_remainder 2083 ) 2084 { 2085 rem_ = reflect_i_type::reflect_q( new_rem ); 2086 } 2087 2088 /** \copydetails boost::crc_basic::process_byte 2089 2090 \note Any modulo-2 polynomial divisions may use a table of pre-computed 2091 remainder changes (as XOR masks) to speed computation when reading data 2092 byte-wise. 2093 */ 2094 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2095 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2096 bool ReflectIn, bool ReflectRem > 2097 inline 2098 void 2099 BOOST_CRC_OPTIMAL_NAME::process_byte 2100 ( 2101 unsigned char byte 2102 ) 2103 { 2104 process_bytes( &byte, sizeof(byte) ); 2105 } 2106 2107 /** \copydetails boost::crc_basic::process_block 2108 2109 \note Any modulo-2 polynomial divisions may use a table of pre-computed 2110 remainder changes (as XOR masks) to speed computation when reading data 2111 byte-wise. 2112 */ 2113 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2114 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2115 bool ReflectIn, bool ReflectRem > 2116 inline 2117 void 2118 BOOST_CRC_OPTIMAL_NAME::process_block 2119 ( 2120 void const * bytes_begin, 2121 void const * bytes_end 2122 ) 2123 { 2124 process_bytes( bytes_begin, static_cast<unsigned char const *>(bytes_end) - 2125 static_cast<unsigned char const *>(bytes_begin) ); 2126 } 2127 2128 /** \copydetails boost::crc_basic::process_bytes 2129 2130 \note Any modulo-2 polynomial divisions may use a table of pre-computed 2131 remainder changes (as XOR masks) to speed computation when reading data 2132 byte-wise. 2133 */ 2134 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2135 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2136 bool ReflectIn, bool ReflectRem > 2137 inline 2138 void 2139 BOOST_CRC_OPTIMAL_NAME::process_bytes 2140 ( 2141 void const * buffer, 2142 std::size_t byte_count 2143 ) 2144 { 2145 rem_ = crc_table_type::crc_update( rem_, static_cast<unsigned char const 2146 *>(buffer), byte_count ); 2147 } 2148 2149 //! \copydetails boost::crc_basic::checksum 2150 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2151 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2152 bool ReflectIn, bool ReflectRem > 2153 inline 2154 typename BOOST_CRC_OPTIMAL_NAME::value_type 2155 BOOST_CRC_OPTIMAL_NAME::checksum 2156 ( 2157 ) const 2158 { 2159 return ( reflect_o_type::reflect_q(rem_) ^ get_final_xor_value() ) 2160 & detail::low_bits_mask_c<bit_count>::value; 2161 } 2162 2163 /** Updates the interim remainder with a byte's worth of altered-CRC-division 2164 steps. The bits within the byte are processed from the highest place down 2165 if <code>this->get_reflect_input()</code> is \c false, and lowest place 2166 up otherwise. This function is meant to present a function-object interface 2167 to code that wants to process a stream of bytes with 2168 <code>std::for_each</code> or similar range-processing algorithms. Since 2169 some of these algorithms takes their function object by value, make sure to 2170 copy back the result to this object so the updates can be remembered. 2171 2172 \param[in] byte The new input byte. 2173 2174 \post The interim remainder is updated though \c CHAR_BIT modulo-2 2175 polynomial divisions, where the division steps are altered for unaugmented 2176 CRCs. 2177 2178 \note Any modulo-2 polynomial divisions may use a table of pre-computed 2179 remainder changes (as XOR masks) to speed computation when reading data 2180 byte-wise. 2181 */ 2182 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2183 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2184 bool ReflectIn, bool ReflectRem > 2185 inline 2186 void 2187 BOOST_CRC_OPTIMAL_NAME::operator () 2188 ( 2189 unsigned char byte 2190 ) 2191 { 2192 process_byte( byte ); 2193 } 2194 2195 /** Computes the checksum of all the submitted bits since construction or the 2196 last call to #reset. The checksum will be the raw checksum, i.e. the 2197 (interim) remainder after all the modulo-2 polynomial division, plus any 2198 output processing. This function is meant to present a function-object 2199 interface to code that wants to receive data like 2200 <code>std::generate_n</code> or similar data-processing algorithms. Note 2201 that if this object is used as a generator multiple times without an 2202 intervening mutating operation, the same value will always be returned. 2203 2204 \return <code>(this->get_reflect_remainder() ? 2205 REFLECT(this->get_interim_remainder()) : 2206 this->get_interim_remainder()) ^ this->get_final_xor_value()</code> 2207 2208 \note Since checksums are meant to be compared, any higher-placed bits 2209 (when the bit-length of #value_type exceeds #bit_count) will be set to 0. 2210 */ 2211 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2212 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2213 bool ReflectIn, bool ReflectRem > 2214 inline 2215 typename BOOST_CRC_OPTIMAL_NAME::value_type 2216 BOOST_CRC_OPTIMAL_NAME::operator () 2217 ( 2218 ) const 2219 { 2220 return checksum(); 2221 } 2222 2223 2224 // CRC computation function definition -------------------------------------// 2225 2226 /** Computes the polynomial remainder of a CRC run, assuming that \a buffer and 2227 \a byte_count describe a memory block representing the polynomial dividend. 2228 The division steps are altered so the result directly gives a checksum, 2229 without need to augment the memory block with scratch-space bytes. The 2230 first byte is considered the highest order, going down for subsequent bytes. 2231 2232 \pre 0 \< \a Bits \<= \c std\::numeric_limits\<uintmax_t\>\::digits 2233 2234 \tparam Bits The order of the modulo-2 polynomial divisor. (\e Width from 2235 the RMCA) 2236 \tparam TruncPoly The lowest coefficients of the divisor polynomial. The 2237 highest-order coefficient is omitted and always assumed to be 1. 2238 (\e Poly from the RMCA) 2239 \tparam InitRem The (unaugmented) initial state of the polynomial 2240 remainder. (\e Init from the RMCA) 2241 \tparam FinalXor The (XOR) bit-mask to be applied to the output remainder, 2242 after possible reflection but before returning. (\e XorOut from the RMCA) 2243 \tparam ReflectIn If \c True, input bytes are read lowest-order bit first, 2244 otherwise highest-order bit first. (\e RefIn from the RMCA) 2245 \tparam ReflectRem If \c True, the output remainder is reflected before the 2246 XOR-mask. (\e RefOut from the RMCA) 2247 2248 \param[in] buffer The address where the memory block begins. 2249 \param[in] byte_count The number of bytes in the memory block. 2250 2251 \return The checksum, which is the last (interim) remainder plus any output 2252 processing. 2253 2254 \note Unaugmented-style CRC runs perform modulo-2 polynomial division in 2255 an altered order. The trailing \a Bits number of zero-valued bits needed 2256 to extracted an (unprocessed) checksum is virtually moved to near the 2257 beginning of the message. This is OK since the XOR operation is 2258 commutative and associative. It also means that you can get a checksum 2259 anytime. Since data is being read byte-wise, a table of pre-computed 2260 remainder changes (as XOR masks) can be used to speed computation. 2261 2262 */ 2263 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly, 2264 BOOST_CRC_PARM_TYPE InitRem, BOOST_CRC_PARM_TYPE FinalXor, 2265 bool ReflectIn, bool ReflectRem > 2266 inline 2267 typename crc_detail::uint_t<Bits>::fast 2268 crc 2269 ( 2270 void const * buffer, 2271 std::size_t byte_count 2272 ) 2273 { 2274 BOOST_CRC_OPTIMAL_NAME computer; 2275 computer.process_bytes( buffer, byte_count ); 2276 return computer.checksum(); 2277 } 2278 2279 2280 // Augmented-message CRC computation function definition -------------------// 2281 2282 /** Computes the polynomial remainder of a CRC run, assuming that \a buffer and 2283 \a byte_count describe a memory block representing the polynomial dividend. 2284 The first byte is considered the highest order, going down for subsequent 2285 bytes. Within a byte, the highest-order bit is read first (corresponding to 2286 \e RefIn = \c False in the RMCA). Check the other parts of this function's 2287 documentation to see how a checksum can be gained and/or used. 2288 2289 \pre 0 \< \a Bits \<= \c std\::numeric_limit\<uintmax_t\>\::digits 2290 2291 \tparam Bits The order of the modulo-2 polynomial divisor. (\e Width from 2292 the RMCA) 2293 \tparam TruncPoly The lowest coefficients of the divisor polynomial. The 2294 highest-order coefficient is omitted and always assumed to be 1. 2295 (\e Poly from the RMCA) 2296 2297 \param[in] buffer The address where the memory block begins. 2298 \param[in] byte_count The number of bytes in the memory block. 2299 \param[in] initial_remainder The initial state of the polynomial 2300 remainder, defaulting to zero if omitted. If you are reading a memory 2301 block in multiple runs, put the return value of the previous run here. 2302 (Note that initial-remainders given by RMCA parameter lists, as 2303 \e Init, assume that the initial remainder is in its \b unaugmented state, 2304 so you would need to convert the value to make it suitable for this 2305 function. I currently don't provide a conversion routine.) 2306 2307 \return The interim remainder, if no augmentation is used. A special value 2308 if augmentation is used (see the notes). No output processing is done on 2309 the value. (In RMCA terms, \e RefOut is \c False and \e XorOut is \c 0.) 2310 2311 \note Augmented-style CRC runs use straight-up modulo-2 polynomial 2312 division. Since data is being read byte-wise, a table of pre-computed 2313 remainder changes (as XOR masks) can be used to speed computation. 2314 \note Reading just a memory block will yield an interim remainder, and not 2315 the final checksum. To get that checksum, allocate \a Bits / \c CHAR_BIT 2316 bytes directly after the block and fill them with zero values, then extend 2317 \a byte_count to include those extra bytes. A data block is corrupt if 2318 the return value doesn't equal your separately given checksum. 2319 \note Another way to perform a check is use the zero-byte extension method, 2320 but replace the zero values with your separately-given checksum. The 2321 checksum must be loaded in big-endian order. Here corruption, in either 2322 the data block or the given checksum, is confirmed if the return value is 2323 not zero. 2324 \note The two checksum techniques assume the CRC-run is performed bit-wise, 2325 while this function works byte-wise. That means that the techniques can 2326 be used only if \c CHAR_BIT divides \a Bits evenly! 2327 */ 2328 template < std::size_t Bits, BOOST_CRC_PARM_TYPE TruncPoly > 2329 typename crc_detail::uint_t<Bits>::fast 2330 augmented_crc 2331 ( 2332 void const * buffer, 2333 std::size_t byte_count, 2334 typename crc_detail::uint_t<Bits>::fast initial_remainder // = 0u 2335 ) 2336 { 2337 return detail::low_bits_mask_c<Bits>::value & 2338 detail::byte_table_driven_crcs<Bits, TruncPoly, false>:: 2339 augmented_crc_update( initial_remainder, static_cast<unsigned char const 2340 *>(buffer), byte_count ); 2341 } 2342 2343 2344 } // namespace boost 2345 2346 2347 // Undo header-private macros 2348 #undef BOOST_CRC_OPTIMAL_NAME 2349 #undef BOOST_CRC_PARM_TYPE 2350 2351 2352 #endif // BOOST_CRC_HPP 2353
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |