summaryrefslogtreecommitdiff
path: root/libs/crc
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
committerAnas Nashif <anas.nashif@intel.com>2012-10-30 12:57:26 -0700
commit1a78a62555be32868418fe52f8e330c9d0f95d5a (patch)
treed3765a80e7d3b9640ec2e930743630cd6b9fce2b /libs/crc
downloadboost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'libs/crc')
-rw-r--r--libs/crc/crc.html635
-rw-r--r--libs/crc/crc_example.cpp75
-rw-r--r--libs/crc/index.html61
-rw-r--r--libs/crc/test/Jamfile.v214
-rw-r--r--libs/crc/test/crc_test.cpp761
5 files changed, 1546 insertions, 0 deletions
diff --git a/libs/crc/crc.html b/libs/crc/crc.html
new file mode 100644
index 0000000000..bfb77a71e8
--- /dev/null
+++ b/libs/crc/crc.html
@@ -0,0 +1,635 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Boost CRC Library Documentation</title>
+</head>
+
+<body text="black" bgcolor="white" link="blue" vlink="purple" alink="red">
+
+<h1><img src="../../boost.png" alt="boost.png (6897 bytes)"
+align="middle" width="277" height="86">Header <cite>&lt;<a
+href="../../boost/crc.hpp">boost/crc.hpp</a>&gt;</cite></h1>
+
+<p>The header <cite>&lt;<a
+href="../../boost/crc.hpp">boost/crc.hpp</a>&gt;</cite> supplies two
+class templates in namespace <code>boost</code>. These templates define
+objects that can compute the <dfn>CRC</dfn>, or cyclic redundancy code
+(or check), of a given stream of data. The header also supplies
+function templates to compute a CRC in one step.</p>
+
+<h2><a name="contents">Contents</a></h2>
+
+<ol>
+ <li><a href="#contents">Contents</a></li>
+ <li><a href="#header">Header Synopsis</a></li>
+ <li><a href="#rationale">Rationale</a></li>
+ <li><a href="#background">Background</a>
+ <ul>
+ <li><a href="#parameters">CRC Parameters</a></li>
+ </ul></li>
+ <li><a href="#crc_basic">Theoretical CRC Computer</a></li>
+ <li><a href="#crc_optimal">Optimized CRC Computer</a></li>
+ <li><a href="#usage">Computer Usage</a></li>
+ <li><a href="#crc_func">CRC Function</a></li>
+ <li><a href="#a_crc_func">Augmented-CRC Functions</a></li>
+ <li><a href="#crc_ex">Pre-Defined CRC Samples</a></li>
+ <li><a href="#references">References</a></li>
+ <li><a href="#credits">Credits</a>
+ <ul>
+ <li><a href="#contributors">Contributors</a></li>
+ <li><a href="#acknowledgements">Acknowledgements</a></li>
+ <li><a href="#history">History</a></li>
+ </ul></li>
+</ol>
+
+<h2><a name="header">Header Synopsis</a></h2>
+
+<blockquote><pre>#include &lt;boost/integer.hpp&gt; <i>// for boost::uint_t</i>
+#include &lt;cstddef&gt; <i>// for std::size_t</i>
+
+namespace boost
+{
+
+template &lt; std::size_t Bits &gt;
+ class crc_basic;
+
+template &lt; std::size_t Bits, <em>impl_def</em> TruncPoly = 0u,
+ <em>impl_def</em> InitRem = 0u,
+ <em>impl_def</em> FinalXor = 0u, bool ReflectIn = false,
+ bool ReflectRem = false &gt;
+ class crc_optimal;
+
+template &lt; std::size_t Bits, <em>impl_def</em> TruncPoly,
+ <em>impl_def</em> InitRem, <em>impl_def</em> FinalXor,
+ bool ReflectIn, bool ReflectRem &gt;
+ typename uint_t&lt;Bits&gt;::fast crc( void const *buffer,
+ std::size_t byte_count );
+
+template &lt; std::size_t Bits, <em>impl_def</em> TruncPoly &gt;
+ typename uint_t&lt;Bits&gt;::fast augmented_crc( void const *buffer,
+ std::size_t byte_count,
+ typename uint_t&lt;Bits&gt;::fast initial_remainder );
+
+template &lt; std::size_t Bits, <em>impl_def</em> TruncPoly &gt;
+ typename uint_t&lt;Bits&gt;::fast augmented_crc( void const *buffer,
+ std::size_t byte_count );
+
+typedef crc_optimal&lt;16, 0x8005, 0, 0, true, true&gt; crc_16_type;
+typedef crc_optimal&lt;16, 0x1021, 0xFFFF, 0, false, false&gt; crc_ccitt_type;
+typedef crc_optimal&lt;16, 0x8408, 0, 0, true, true&gt; crc_xmodem_type;
+
+typedef crc_optimal&lt;32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true&gt;
+ crc_32_type;
+
+}
+</pre></blockquote>
+
+<p>The implementation-defined type <var>impl_def</var> stands for the
+quickest-to-manipulate built-in unsigned integral type that can
+represent at least <var>Bits</var> bits.</p>
+
+<h2><a name="rationale">Rationale</a></h2>
+
+<p>A common error detection technique, especially with electronic
+communications, is an appended checksum. The transmitter sends its data
+bits, followed by the bits of the checksum. The checksum is based on
+operations done on the data bit stream. The receiver applies the same
+operations on the bits it gets, and then gets the checksum. If the
+computed checksum doesn't match the received checksum, then an error
+ocurred in the transmission. There is the slight chance that the error
+is only in the checksum, and an actually-correct data stream is
+rejected. There is also the chance of an error occurring that does not
+change the checksum, making that error invisible. CRC is a common
+checksum type, used for error detection for hardware interfaces and
+encoding formats.</p>
+
+<h2><a name="background">Background</a></h2>
+
+<p>CRCs work by computing the remainder of a modulo-2 polynominal
+division. The message is treated as the (binary) coefficents of a long
+polynominal for the dividend, with the earlier bits of the message fed
+first as the polynominal's highest coefficents. A particular CRC
+algorithm has another polynominal associated with it to be used as the
+divisor. The quotient is ignored. The remainder of the division
+considered the checksum. However, the division uses modulo-2 rules (no
+carries) for the coefficents.</p>
+
+<p>See <cite><a href="http://www.ross.net/crc/crcpaper.html">A
+Painless Guide to CRC Error Detection Algorithms</a></cite> for complete
+information. A clearer guide is at the <a
+href="http://www.netrino.com/Connecting/2000-01/">Easier Said Than
+Done</a> web page.</p>
+
+<h3><a name="parameters">CRC Parameters</a></h3>
+
+<dl>
+ <dt>Truncated polynominal
+ <dd>The divisor polynominal has a degree one bit larger than the
+ checksum (remainder) size. That highest bit is always one, so
+ it is ignored when describing a particular CRC type. Excluding
+ this bit makes the divisor fit in the same data type as the
+ checksum.
+
+ <dt>Initial remainder
+ <dd>The interim CRC remainder changes as each bit is processed.
+ Usually, the interim remainder starts at zero, but some CRCs use
+ a different initial value to avoid &quot;blind spots.&quot; A
+ blind spot is when a common sequence of message bits does not
+ change certain interim remainder values.
+
+ <dt>Final XOR value
+ <dd>A CRC remainder can be combined with a defined value, <i>via</i>
+ a bitwise exclusive-or operation, before being returned to the
+ user. The value is usually zero, meaning the interim remainder
+ is returned unchanged. The other common value is an all-ones
+ value, meaning that the bitwise complement of the interim
+ remainder is returned.
+
+ <dt>Reflected input
+ <dd>A message's bits are usually fed a byte at a time, with the
+ highest bits of the byte treated as the higher bits of the
+ dividend polynominal. Some CRCs reflect the bits (about the
+ byte's center, so the first and last bits are switched,
+ <i>etc.</i>) before feeding.
+
+ <dt>Reflected (remainder) output
+ <dd>Some CRCs return the reflection of the interim remainder (taking
+ place <em>before</em> the final XOR value stage).
+</dl>
+
+<h2><a name="crc_basic">Theoretical CRC Computer</a></h2>
+
+<blockquote><pre>template &lt; std::size_t Bits &gt;
+class boost::crc_basic
+{
+public:
+ // Type
+ typedef <em>implementation_defined</em> value_type;
+
+ // Constant reflecting template parameter
+ static std::size_t const bit_count = Bits;
+
+ // Constructor
+ explicit crc_basic( value_type truncated_polynominal,
+ value_type initial_remainder = 0, value_type final_xor_value = 0,
+ bool reflect_input = false, bool reflect_remainder = false );
+
+ // Internal Operations
+ value_type get_truncated_polynominal() const;
+ value_type get_initial_remainder() const;
+ value_type get_final_xor_value() const;
+ bool get_reflect_input() const;
+ bool get_reflect_remainder() const;
+
+ value_type get_interim_remainder() const;
+ void reset( value_type new_rem );
+ void reset();
+
+ // External Operations
+ void process_bit( bool bit );
+ void process_bits( unsigned char bits, std::size_t bit_count );
+ void process_byte( unsigned char byte );
+ void process_block( void const *bytes_begin, void const *bytes_end );
+ void process_bytes( void const *buffer, std::size_t byte_count );
+
+ value_type checksum() const;
+
+};
+</pre></blockquote>
+
+<p>The <code>value_type</code> is the smallest built-in type that can
+hold the specified (by <code>Bits</code>) number of bits. This should
+be <code>boost::uint_t&lt;Bits&gt;::least</code>, see the <a
+href="../integer/doc/html/boost_integer/integer.html">documentation for integer type
+selection</a> for details.</p>
+
+<p>This implementation is slow since it computes its CRC the same way as
+in theory, bit by bit. No optimizations are performed. It wastes space
+since most of the CRC parameters are specified at run-time as
+constructor parameters.</p>
+
+<h2><a name="crc_optimal">Optimized CRC Computer</a></h2>
+
+<blockquote><pre>template &lt; std::size_t Bits, <em>impl_def</em> TruncPoly,
+ <em>impl_def</em> InitRem, <em>impl_def</em> FinalXor,
+ bool ReflectIn, bool ReflectRem &gt;
+class boost::crc_optimal
+{
+public:
+ // Type
+ typedef <em>implementation_defined</em> value_type;
+
+ // Constants reflecting template parameters
+ static std::size_t const bit_count = Bits;
+ static value_type const truncated_polynominal = TruncPoly;
+ static value_type const initial_remainder = InitRem;
+ static value_type const final_xor_value = FinalXor;
+ static bool const reflect_input = ReflectIn;
+ static bool const reflect_remainder = ReflectRem;
+
+ // Constructor
+ explicit crc_optimal( value_type init_rem = InitRem );
+
+ // Internal Operations
+ value_type get_truncated_polynominal() const;
+ value_type get_initial_remainder() const;
+ value_type get_final_xor_value() const;
+ bool get_reflect_input() const;
+ bool get_reflect_remainder() const;
+
+ value_type get_interim_remainder() const;
+ void reset( value_type new_rem = InitRem );
+
+ // External Operations
+ void process_byte( unsigned char byte );
+ void process_block( void const *bytes_begin, void const *bytes_end );
+ void process_bytes( void const *buffer, std::size_t byte_count );
+
+ value_type checksum() const;
+
+ // Operators
+ void operator ()( unsigned char byte );
+ value_type operator ()() const;
+
+};
+</pre></blockquote>
+
+<p>The <code>value_type</code> is the quickest-to-manipulate built-in
+type that can hold at least the specified (by <code>Bits</code>) number
+of bits. This should be <code>boost::uint_t&lt;Bits&gt;::fast</code>.
+See the <a href="../integer/doc/html/boost_integer/integer.html">integer type selection
+documentation</a> for details. The <code>TruncPoly</code>,
+<code>InitRem</code>, and <code>FinalXor</code> template parameters also
+are of this type.</p>
+
+<p>This implementation is fast since it uses as many optimizations as
+practical. All of the CRC parameters are specified at compile-time as
+template parameters. No individual bits are considered; only whole
+bytes are passed. A table of interim CRC values versus byte values is
+pre-computed when the first object using a particular bit size,
+truncated polynominal, and input reflection state is processed.</p>
+
+<h2><a name="usage">Computer Usage</a></h2>
+
+<p>The two class templates have different policies on where the CRC's
+parameters go. Both class templates use the number of bits in the CRC
+as the first template parameter. The theoretical computer class
+template has the bit count as its only template parameter, all the other
+CRC parameters are entered through the constructor. The optimized
+computer class template obtains all its CRC parameters as template
+parameters, and instantiated objects are usually
+default-constructed.</p>
+
+<p>The CRC parameters can be inspected at run-time with the following
+member functions: <code>get_truncated_polynominal</code>,
+<code>get_initial_remainder</code>, <code>get_final_xor_value</code>,
+<code>get_reflect_input</code>, and <code>get_reflect_remainder</code>.
+The fast computer also provides compile-time constants for its CRC
+parameters.</p>
+
+<p>The <code>get_interim_remainder</code> member function returns the
+internal state of the CRC remainder. It represents the unreflected
+remainder of the last division. Saving an interim remainder allows the
+freezing of CRC processing, as long as the other CRC parameters and the
+current position of the bit stream are saved. Restarting a frozen
+stream involves constructing a new computer with the most of the old
+computer's parameters. The only change is to use the frozen remainder
+as the new computer's initial remainder. Then the interrupted bit
+stream can be fed as if nothing happened. The fast CRC computer has a
+special constructor that takes one argument, an interim remainder, for
+this purpose (overriding the initial remainder CRC parameter).</p>
+
+<p>The <code>reset</code> member functions reset the internal state of
+the CRC remainder to the given value. If no value is given, then the
+internal remainder is set to the initial remainder value when the object
+was created. The remainder must be unreflected. When a CRC calculation
+is finished, calling <code>reset</code> lets the object be reused for a
+new session.</p>
+
+<p>After any construction, both CRC computers work the same way.
+Feeding new data to a computer is in a seperate operation(s) from
+extracting the current CRC value from the computer. The following table
+lists the feeding and extracting operations.</p>
+
+<table cellpadding="5" border="1">
+ <caption>Regular CRC Operations</caption>
+ <tr>
+ <th>Operation</th>
+ <th>Description</th>
+ </tr>
+ <tr>
+ <td><code>void process_bit( bool bit );</code></td>
+ <td>Feeds the single <var>bit</var> to the computer, updating
+ the interim CRC. It is only defined for the slow CRC
+ computer.</td>
+ </tr>
+ <tr>
+ <td><code>void process_bits( unsigned char bits, std::size_t
+ bit_count );</code></td>
+ <td>Acts as applying <code>process_bit</code> to the lowest
+ <var>bit_count</var> bits given in <var>bits</var>, most
+ significant relevant bit first. The results are undefined
+ if <var>bit_count</var> exceeds the number of bits per byte.
+ It is only defined for the slow CRC computer.</td>
+ </tr>
+ <tr>
+ <td><code>void process_byte( unsigned char byte );</code></td>
+ <td>Acts as applying <code>process_bit</code> to the all the
+ bits in <var>byte</var>. If reflection is not desired, the
+ bits are fed from the most to least significant. The bits
+ are fed in the opposite order if reflection is desired.</td>
+ </tr>
+ <tr>
+ <td><code>void process_block( void const *bytes_begin, void
+ const *bytes_end );</code></td>
+ <td>Acts as applying <code>process_byte</code> to each byte in
+ the given memory block. This memory block starts at
+ <var>bytes_begin</var> and finishes before
+ <var>bytes_end</var>. The bytes are processed in that
+ order.</td>
+ </tr>
+ <tr>
+ <td><code>void process_bytes( void const *buffer, std::size_t
+ byte_count );</code></td>
+ <td>Acts as applying <code>process_byte</code> to each byte in
+ the given memory block. This memory block starts at
+ <var>buffer</var> and lasts for <var>byte_count</var> bytes.
+ The bytes are processed in ascending order.</td>
+ </tr>
+ <tr>
+ <td><code>value_type checksum() const;</code></td>
+ <td>Returns the CRC checksum of the data passed in so far,
+ possibly after applying the remainder-reflection and
+ exclusive-or operations.</td>
+ </tr>
+ <tr>
+ <td><code>void operator ()( unsigned char byte );</code></td>
+ <td>Calls <code>process_byte</code>. This member function lets
+ its object act as a (stateful) function object. It is only
+ defined for the fast CRC computer.</td>
+ </tr>
+ <tr>
+ <td><code>value_type operator ()() const;</code></td>
+ <td>Calls <code>checksum</code>. This member function lets
+ its object act as a generator function object. It is only
+ defined for the fast CRC computer.</td>
+ </tr>
+</table>
+
+<p>You can use them like this:</p>
+
+<blockquote><pre>#include &lt;boost/crc.hpp&gt; <i>// for boost::crc_basic, boost::crc_optimal</i>
+#include &lt;boost/cstdint.hpp&gt; <i>// for boost::uint16_t</i>
+
+#include &lt;algorithm&gt; <i>// for std::for_each</i>
+#include &lt;cassert&gt; <i>// for assert</i>
+#include &lt;cstddef&gt; <i>// for std::size_t</i>
+#include &lt;iostream&gt; <i>// for std::cout</i>
+#include &lt;ostream&gt; <i>// for std::endl</i>
+
+
+// Main function
+int
+main ()
+{
+ // This is "123456789" in ASCII
+ unsigned char const data[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39 };
+ std::size_t const data_len = sizeof( data ) / sizeof( data[0] );
+
+ // The expected CRC for the given data
+ boost::uint16_t const expected = 0x29B1;
+
+ // Simulate CRC-CCITT
+ boost::crc_basic&lt;16&gt; crc_ccitt1( 0x1021, 0xFFFF, 0, false, false );
+ crc_ccitt1.process_bytes( data, data_len );
+ assert( crc_ccitt1.checksum() == expected );
+
+ // Repeat with the optimal version (assuming a 16-bit type exists)
+ boost::crc_optimal&lt;16, 0x1021, 0xFFFF, 0, false, false&gt; crc_ccitt2;
+ crc_ccitt2 = std::for_each( data, data + data_len, crc_ccitt2 );
+ assert( crc_ccitt2() == expected );
+
+ std::cout &lt;&lt; "All tests passed." &lt;&lt; std::endl;
+ return 0;
+}
+</pre></blockquote>
+
+<h2><a name="crc_func">CRC Function</a></h2>
+
+<blockquote><pre>template &lt; std::size_t Bits, <em>impl_def</em> TruncPoly,
+ <em>impl_def</em> InitRem, <em>impl_def</em> FinalXor,
+ bool ReflectIn, bool ReflectRem &gt;
+typename boost::uint_t&lt;Bits&gt;::fast
+boost::crc( void const *buffer, std::size_t byte_count );
+</pre></blockquote>
+
+<p>The <code>boost::crc</code> function template computes the CRC of a
+given data block. The data block starts at the address given by
+<var>buffer</var> and lasts for <var>byte_count</var> bytes. The CRC
+parameters are passed through template arguments, identical to the
+optimized CRC computer (<a href="#crc_optimal">see above</a>). In fact,
+such a computer is used to implement this function.</p>
+
+<h2><a name="a_crc_func">Augmented-CRC Functions</a></h2>
+
+<blockquote><pre>template &lt; std::size_t Bits, <em>impl_def</em> TruncPoly &gt;
+typename boost::uint_t&lt;Bits&gt;::fast
+boost::augmented_crc( void const *buffer, std::size_t byte_count,
+ typename boost::uint_t&lt;Bits&gt;::fast initial_remainder );
+
+template &lt; std::size_t Bits, <em>impl_def</em> TruncPoly &gt;
+typename boost::uint_t&lt;Bits&gt;::fast
+boost::augmented_crc( void const *buffer, std::size_t byte_count );
+</pre></blockquote>
+
+<p>All the other CRC-computing function or class templates work assuming
+that the division steps start immediately on the first message bits.
+The two <code>boost::augmented_crc</code> function templates have a
+different division order. Instead of combining (<i>via</i> bitwise
+exclusive-or) the current message bit with the highest bit of a separate
+remainder, these templates shift a new message bit into the low bit of a
+remainder register as the highest bit is shifted out. The new method
+means that the bits in the inital remainder value are processed before
+any of the actual message bits are processed. To compensate, the real
+CRC can only be extracted after feeding enough zero bits (the same count
+as the register size) after the message bits.</p>
+
+<p>The template parameters of both versions of the function template are
+the CRC's bit size (<code>Bits</code>) and the truncated polynominal
+(<code>TruncPoly</code>). The version of the function template that
+takes two arguments calls the three-argument version with the
+<var>initial_remainder</var> parameter filled as zero. Both versions
+work on the data block starting at the address <var>buffer</var> for
+<var>byte_count</var> bytes.</p>
+
+<p>These function templates are useful if the bytes of the CRC directly
+follow the message's bytes. First, set the bytes of where the CRC will
+go to zero. Then use <code>augmented_crc</code> over the augmented
+message, <i>i.e.</i> the message bytes and the appended CRC bytes. Then
+assign the result to the CRC. To later check a received message, either
+use <code>augmented_crc</code> (with the same parameters as
+transmission, of course) on the received <em>unaugmented</em> message
+and check if the result equals the CRC, or use
+<code>augmented_crc</code> on the received <em>augmented</em> message
+and check if the result equals zero. Note that the CRC has to be stored
+with the more-significant bytes first (big-endian).</p>
+
+<p>Interruptions in the CRC data can be handled by feeding the result of
+<code>augmented_crc</code> of the previous data block as the
+<var>initial_remainder</var> when calling <code>augmented_crc</code> on
+the next data block. Remember that the actual CRC can only be
+determined after feeding the augmented bytes. Since this method uses
+modulo-2 polynominal division at its most raw, neither final XOR values
+nor reflection can be used.</p>
+
+<p>Note that for the same CRC system, the initial remainder for
+augmented message method will be different than for the unaugmented
+message method. The main exception is zero; if the augmented-CRC
+algorithm uses a zero initial remainder, the equivalent unaugmented-CRC
+algorithm will also use a zero initial remainder. Given an initial
+remainder for a augmented-CRC algorithm, the result from processing just
+zero-valued CRC bytes without any message bytes is the equivalent inital
+remainder for the unaugmented-CRC algorithm. An example follows:</p>
+
+<blockquote><pre>#include &lt;boost/crc.hpp&gt; <i>// for boost::crc_basic, boost::augmented_crc</i>
+#include &lt;boost/cstdint.hpp&gt; <i>// for boost::uint16_t</i>
+
+#include &lt;cassert&gt; <i>// for assert</i>
+#include &lt;iostream&gt; <i>// for std::cout</i>
+#include &lt;ostream&gt; <i>// for std::endl</i>
+
+
+// Main function
+int
+main ()
+{
+ using boost::uint16_t;
+ using boost::augmented_crc;
+
+ uint16_t data[6] = { 2, 4, 31, 67, 98, 0 };
+ uint16_t const init_rem = 0x123;
+
+ uint16_t crc1 = augmented_crc&lt;16, 0x8005&gt;( data, sizeof(data), init_rem );
+
+ uint16_t const zero = 0;
+ uint16_t const new_init_rem = augmented_crc&lt;16, 0x8005&gt;( &amp;zero, sizeof(zero) );
+
+ boost::crc_basic&lt;16&gt; crc2( 0x8005, new_init_rem );
+ crc2.process_block( data, &amp;data[5] ); // don't include CRC
+ assert( crc2.checksum() == crc1 );
+
+ std::cout &lt;&lt; "All tests passed." &lt;&lt; std::endl;
+ return 0;
+}
+</pre></blockquote>
+
+<h2><a name="crc_ex">Pre-Defined CRC Samples</a></h2>
+
+<p>Four sample CRC types are given, representing several common CRC
+algorithms. For example, computations from <code>boost::crc_32_type</code>
+can be used for implementing the PKZip standard. Note that, in general, this
+library is concerned with CRC implementation, and not with determining
+&quot;good&quot; sets of CRC parameters.</p>
+
+<table cellpadding="5" border="1">
+ <caption>Common CRCs</caption>
+ <tr>
+ <th>Algorithm</th>
+ <th>Example Protocols</th>
+ </tr>
+ <tr>
+ <td><code>crc_16_type</code></td>
+ <td>BISYNCH, ARC</td>
+ </tr>
+ <tr>
+ <td><code>crc_ccitt_type</code></td>
+ <td>designated by CCITT (Comit&eacute; Consultatif International
+ T&eacute;l&eacute;graphique et T&eacute;l&eacute;phonique)</td>
+ </tr>
+ <tr>
+ <td><code>crc_xmodem_type</code></td>
+ <td>XMODEM</td>
+ </tr>
+ <tr>
+ <td><code>crc_32_type</code></td>
+ <td>PKZip, AUTODIN II, Ethernet, FDDI</td>
+ </tr>
+</table>
+
+<hr>
+
+<h2><a name="references">References</a></h2>
+
+<ul>
+ <li>The CRC header itself: <cite><a href="../../boost/crc.hpp">crc.hpp</a></cite>
+ <li>Some test code: <cite><a href="test/crc_test.cpp">crc_test.cpp</a></cite>
+ <li>Some example code: <cite><a href="crc_example.cpp">crc_example.cpp</a></cite>
+</ul>
+
+<h2><a name="credits">Credits</a></h2>
+
+<h3><a name="contributors">Contributors</a></h3>
+
+<dl>
+ <dt>Michael Barr (<a
+ href="mailto:mbarr@netrino.com">mbarr@netrino.com</a>)
+ <dd>Wrote <a
+ href="http://www.netrino.com/Connecting/2000-01/">Easier Said
+ Than Done</a>, a less-confusing guide to implementing CRC
+ algorithms. (Originally published as &quot;Slow and Steady
+ Never Lost the Race&quot; in the January 2000 issue of <cite><a
+ href="http://www.embedded.com/">Embedded Systems
+ Programming</a></cite>, pages 37&ndash;46.)
+
+ <dt>Daryle Walker
+ <dd>Started the library and contributed the theoretical and optimal
+ CRC computation class templates and the CRC computing function
+ template. Contributed <cite><a
+ href="test/crc_test.cpp">crc_test.cpp</a></cite> and <cite><a
+ href="crc_example.cpp">crc_example.cpp</a></cite>.
+
+ <dt>Ross N. Williams
+ <dd>Wrote <cite><a href="http://www.ross.net/crc/crcpaper.html">A
+ Painless Guide to CRC Error Detection Algorithms</a></cite>, a
+ definitive source of CRC information.
+</dl>
+
+<h3><a name="acknowledgements">Acknowledgements</a></h3>
+
+<p>For giving advice on compiler/C++ compliance, implementation,
+interface, algorithms, and bug reports:</p>
+
+<ul>
+ <li>Darin Adler</li>
+ <li>Beman Dawes</li>
+ <li>Doug Gregor</li>
+ <li>John Maddock</li>
+ <li>Joe Mariadassou</li>
+ <li>Jens Maurer</li>
+ <li>Vladimir Prus</li>
+ <li>Joel Young</li>
+</ul>
+
+<h3><a name="history">History</a></h3>
+
+<dl>
+ <dt>15 Jun 2003, Daryle Walker
+ <dd>Added example program.
+
+ <dt>14 May 2001, Daryle Walker
+ <dd>Initial version.
+</dl>
+
+<hr>
+
+<p>Revised: 15 June 2003</p>
+
+<p>Copyright 2001, 2003 Daryle Walker. Use, modification, and distribution
+are subject to the Boost Software License, Version 1.0. (See accompanying
+file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a copy at
+&lt;<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>&gt;.)</p>
+
+</body>
+</html>
diff --git a/libs/crc/crc_example.cpp b/libs/crc/crc_example.cpp
new file mode 100644
index 0000000000..a40e61d1e3
--- /dev/null
+++ b/libs/crc/crc_example.cpp
@@ -0,0 +1,75 @@
+// Boost CRC example program file ------------------------------------------//
+
+// Copyright 2003 Daryle Walker. Use, modification, and distribution are
+// subject to the Boost Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+// See <http://www.boost.org/libs/crc/> for the library's home page.
+
+// Revision History
+// 17 Jun 2003 Initial version (Daryle Walker)
+
+#include <boost/crc.hpp> // for boost::crc_32_type
+
+#include <cstdlib> // for EXIT_SUCCESS, EXIT_FAILURE
+#include <exception> // for std::exception
+#include <fstream> // for std::ifstream
+#include <ios> // for std::ios_base, etc.
+#include <iostream> // for std::cerr, std::cout
+#include <ostream> // for std::endl
+
+
+// Redefine this to change to processing buffer size
+#ifndef PRIVATE_BUFFER_SIZE
+#define PRIVATE_BUFFER_SIZE 1024
+#endif
+
+// Global objects
+std::streamsize const buffer_size = PRIVATE_BUFFER_SIZE;
+
+
+// Main program
+int
+main
+(
+ int argc,
+ char const * argv[]
+)
+try
+{
+ boost::crc_32_type result;
+
+ for ( int i = 1 ; i < argc ; ++i )
+ {
+ std::ifstream ifs( argv[i], std::ios_base::binary );
+
+ if ( ifs )
+ {
+ do
+ {
+ char buffer[ buffer_size ];
+
+ ifs.read( buffer, buffer_size );
+ result.process_bytes( buffer, ifs.gcount() );
+ } while ( ifs );
+ }
+ else
+ {
+ std::cerr << "Failed to open file '" << argv[i] << "'."
+ << std::endl;
+ }
+ }
+
+ std::cout << std::hex << std::uppercase << result.checksum() << std::endl;
+ return EXIT_SUCCESS;
+}
+catch ( std::exception &e )
+{
+ std::cerr << "Found an exception with '" << e.what() << "'." << std::endl;
+ return EXIT_FAILURE;
+}
+catch ( ... )
+{
+ std::cerr << "Found an unknown exception." << std::endl;
+ return EXIT_FAILURE;
+}
diff --git a/libs/crc/index.html b/libs/crc/index.html
new file mode 100644
index 0000000000..5e75417a76
--- /dev/null
+++ b/libs/crc/index.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
+<html>
+
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<title>Boost CRC Library</title>
+</head>
+
+<body bgcolor="white" text="black" link="blue" vlink="purple" alink="red">
+
+<table border="1" bgcolor="teal" cellpadding="2">
+ <tr>
+ <td bgcolor="white"><img src="../../boost.png"
+ alt="boost.png (6897 bytes)" WIDTH="277"
+ HEIGHT="86"></td>
+ <td><a href="../../index.htm"><font face="Arial"
+ color="white"><big>Home</big></font></a></td>
+ <td><a href="../libraries.htm"><font face="Arial"
+ color="white"><big>Libraries</big></font></a></td>
+ <td><a href="http://www.boost.org/people/people.htm"><font face="Arial"
+ color="white"><big>People</big></font></a></td>
+ <td><a href="http://www.boost.org/more/faq.htm"><font face="Arial"
+ color="white"><big>FAQ</big></font></a></td>
+ <td><a href="../../more/index.htm"><font face="Arial"
+ color="white"><big>More</big></font></a></td>
+ </tr>
+</table>
+
+<h1>CRC Library</h1>
+
+<p>The header <cite>crc.hpp</cite> provides two implementations of CRC
+(cyclic redundancy code) computation objects and two implementations of
+CRC computation functions. The implementations are template-based.</p>
+
+<p>The first object implementation is for theoretical use. It can
+process single bits, but is considered slow for practical use. The
+second object implementation is byte-oriented and uses look-up
+tables for fast operation. The optimized implementation should
+be suitable for general use. The first function implementation uses the
+optimized object. The second function implementation allows the use of
+a CRC that directly follows its data.</p>
+
+<ul>
+ <li><a href="crc.html">Documentation</a> (HTML).</li>
+ <li>Header <cite><a href="../../boost/crc.hpp">crc.hpp</a></cite>.</li>
+ <li>See the <a href="crc.html">documentation</a> for links to sample
+ programs.</li>
+ <li>Submitted by Daryle Walker.</li>
+</ul>
+
+<hr>
+
+<p>Revised: 14 May 2001</p>
+
+<p>Copyright 2001 Daryle Walker. Use, modification, and distribution
+are subject to the Boost Software License, Version 1.0. (See accompanying
+file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a copy at
+&lt;<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>&gt;.)</p>
+
+</body>
+</html>
diff --git a/libs/crc/test/Jamfile.v2 b/libs/crc/test/Jamfile.v2
new file mode 100644
index 0000000000..8916b6d7ab
--- /dev/null
+++ b/libs/crc/test/Jamfile.v2
@@ -0,0 +1,14 @@
+#~ Copyright Rene Rivera 2008
+#~ Distributed under the Boost Software License, Version 1.0.
+#~ (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+project
+ : requirements
+ <library>/boost/test//boost_test_exec_monitor/<link>static
+ ;
+
+import testing ;
+
+test-suite crc :
+ [ run crc_test.cpp ]
+ ;
diff --git a/libs/crc/test/crc_test.cpp b/libs/crc/test/crc_test.cpp
new file mode 100644
index 0000000000..8df203fe14
--- /dev/null
+++ b/libs/crc/test/crc_test.cpp
@@ -0,0 +1,761 @@
+// Boost CRC test program file ---------------------------------------------//
+
+// Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and
+// distribution are subject to the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or a copy at
+// <http://www.boost.org/LICENSE_1_0.txt>.)
+
+// See <http://www.boost.org/libs/crc/> for the library's home page.
+
+// Revision History
+// 28 Aug 2004 Added CRC tests for polynominals shorter than 8 bits
+// (Daryle Walker, by patch from Bert Klaps)
+// 23 Aug 2003 Adjust to updated Test framework (Daryle Walker)
+// 14 May 2001 Initial version (Daryle Walker)
+
+
+#include <boost/config.hpp> // for BOOST_MSVC, etc.
+#include <boost/crc.hpp> // for boost::crc_basic, etc.
+#include <boost/cstdint.hpp> // for boost::uint16_t, etc.
+#include <boost/cstdlib.hpp> // for boost::exit_success
+#include <boost/integer.hpp> // for boost::uint_t
+#include <boost/random/linear_congruential.hpp> // for boost::minstd_rand
+#include <boost/test/minimal.hpp> // for main, etc.
+#include <boost/timer.hpp> // for boost::timer
+
+#include <algorithm> // for std::for_each, std::generate_n, std::count
+#include <climits> // for CHAR_BIT
+#include <cstddef> // for std::size_t
+#include <iostream> // for std::cout (std::ostream and std::endl indirectly)
+
+
+#if CHAR_BIT != 8
+#error The expected results assume an eight-bit byte.
+#endif
+
+#if !(defined(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS) || (defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)))
+#define CRC_PARM_TYPE typename boost::uint_t<Bits>::fast
+#else
+#define CRC_PARM_TYPE unsigned long
+#endif
+
+#if !defined(BOOST_MSVC) && !defined(__GNUC__)
+#define PRIVATE_DECLARE_BOOST( TypeName ) using boost:: TypeName
+#else
+#define PRIVATE_DECLARE_BOOST( TypeName ) typedef boost:: TypeName TypeName
+#endif
+
+
+// Types
+template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
+ CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
+class crc_tester
+{
+public:
+ // All the following were separate function templates, but they have
+ // been moved to class-static member functions of a class template
+ // because MS VC++ 6 can't handle function templates that can't
+ // deduce all their template arguments from their function arguments.
+
+ typedef typename boost::uint_t<Bits>::fast value_type;
+
+ static void master_test( char const *test_name, value_type expected );
+
+private:
+ typedef boost::crc_optimal<Bits, TrPo, InRe, FiXo, ReIn, ReRe>
+ optimal_crc_type;
+ typedef boost::crc_basic<Bits> basic_crc_type;
+
+ static void compute_test( value_type expected );
+ static void interrupt_test( value_type expected );
+ static void error_test();
+
+}; // crc_tester
+
+// Global data
+unsigned char const std_data[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39 };
+std::size_t const std_data_len = sizeof( std_data ) / sizeof( std_data[0] );
+
+boost::uint16_t const std_crc_ccitt_result = 0x29B1;
+boost::uint16_t const std_crc_16_result = 0xBB3D;
+boost::uint32_t const std_crc_32_result = 0xCBF43926;
+
+// Function prototypes
+void timing_test();
+boost::uint32_t basic_crc32( void const *buffer, std::size_t byte_count );
+boost::uint32_t optimal_crc32( void const *buffer, std::size_t byte_count );
+boost::uint32_t quick_crc32( void const *buffer, std::size_t byte_count );
+boost::uint32_t quick_reflect( boost::uint32_t value, std::size_t bits );
+double time_trial( char const *name,
+ boost::uint32_t (*crc_func)(void const *, std::size_t),
+ boost::uint32_t expected, void const *data, std::size_t length );
+
+void augmented_tests();
+boost::uint32_t native_to_big( boost::uint32_t x );
+boost::uint32_t big_to_native( boost::uint32_t x );
+
+void small_crc_test1();
+void small_crc_test2();
+
+
+// Macro to compact code
+#define PRIVATE_TESTER_NAME crc_tester<Bits, TrPo, InRe, FiXo, ReIn, ReRe>
+
+// Run a test on slow and fast CRC computers and function
+template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
+ CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
+void
+PRIVATE_TESTER_NAME::compute_test
+(
+ typename PRIVATE_TESTER_NAME::value_type expected
+)
+{
+ std::cout << "\tDoing computation tests." << std::endl;
+
+ optimal_crc_type fast_crc;
+ basic_crc_type slow_crc( TrPo, InRe, FiXo, ReIn, ReRe );
+ value_type const func_result = boost::crc<Bits, TrPo, InRe, FiXo, ReIn,
+ ReRe>( std_data, std_data_len );
+
+ fast_crc.process_bytes( std_data, std_data_len );
+ slow_crc.process_bytes( std_data, std_data_len );
+ BOOST_CHECK( fast_crc.checksum() == expected );
+ BOOST_CHECK( slow_crc.checksum() == expected );
+ BOOST_CHECK( func_result == expected );
+}
+
+// Run a test in two runs, and check all the inspectors
+template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
+ CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
+void
+PRIVATE_TESTER_NAME::interrupt_test
+(
+ typename PRIVATE_TESTER_NAME::value_type expected
+)
+{
+ std::cout << "\tDoing interrupt tests." << std::endl;
+
+ // Process the first half of the data (also test accessors)
+ optimal_crc_type fast_crc1;
+ basic_crc_type slow_crc1( fast_crc1.get_truncated_polynominal(),
+ fast_crc1.get_initial_remainder(), fast_crc1.get_final_xor_value(),
+ fast_crc1.get_reflect_input(), fast_crc1.get_reflect_remainder() );
+
+ BOOST_CHECK( fast_crc1.get_interim_remainder() ==
+ slow_crc1.get_initial_remainder() );
+
+ std::size_t const mid_way = std_data_len / 2;
+ unsigned char const * const std_data_end = std_data + std_data_len;
+
+ fast_crc1.process_bytes( std_data, mid_way );
+ slow_crc1.process_bytes( std_data, mid_way );
+ BOOST_CHECK( fast_crc1.checksum() == slow_crc1.checksum() );
+
+ // Process the second half of the data (also test accessors)
+ boost::crc_optimal<optimal_crc_type::bit_count,
+ optimal_crc_type::truncated_polynominal, optimal_crc_type::initial_remainder,
+ optimal_crc_type::final_xor_value, optimal_crc_type::reflect_input,
+ optimal_crc_type::reflect_remainder>
+ fast_crc2( fast_crc1.get_interim_remainder() );
+ boost::crc_basic<basic_crc_type::bit_count> slow_crc2(
+ slow_crc1.get_truncated_polynominal(), slow_crc1.get_interim_remainder(),
+ slow_crc1.get_final_xor_value(), slow_crc1.get_reflect_input(),
+ slow_crc1.get_reflect_remainder() );
+
+ fast_crc2.process_block( std_data + mid_way, std_data_end );
+ slow_crc2.process_block( std_data + mid_way, std_data_end );
+ BOOST_CHECK( fast_crc2.checksum() == slow_crc2.checksum() );
+ BOOST_CHECK( fast_crc2.checksum() == expected );
+ BOOST_CHECK( slow_crc2.checksum() == expected );
+}
+
+// Run a test to see if a single-bit error is detected
+template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
+ CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
+void
+PRIVATE_TESTER_NAME::error_test
+(
+)
+{
+ PRIVATE_DECLARE_BOOST( uint32_t );
+
+ // A single-bit error is ensured to be detected if the polynominal
+ // has at least two bits set. The highest bit is what is removed
+ // to give the truncated polynominal, and it is always set. This
+ // means that the truncated polynominal needs at least one of its
+ // bits set, which implies that it cannot be zero.
+ if ( !(TrPo & boost::detail::mask_uint_t<Bits>::sig_bits_fast) )
+ {
+ BOOST_FAIL( "truncated CRC polymonial is zero" );
+ }
+
+ std::cout << "\tDoing error tests." << std::endl;
+
+ // Create a random block of data
+ uint32_t ran_data[ 256 ];
+ std::size_t const ran_length = sizeof(ran_data) / sizeof(ran_data[0]);
+
+ std::generate_n( ran_data, ran_length, boost::minstd_rand() );
+
+ // Create computers and compute the checksum of the data
+ optimal_crc_type fast_tester;
+ basic_crc_type slow_tester( TrPo, InRe, FiXo, ReIn, ReRe );
+
+ fast_tester.process_bytes( ran_data, sizeof(ran_data) );
+ slow_tester.process_bytes( ran_data, sizeof(ran_data) );
+
+ uint32_t const fast_checksum = fast_tester.checksum();
+ uint32_t const slow_checksum = slow_tester.checksum();
+
+ BOOST_CHECK( fast_checksum == slow_checksum );
+
+ // Do the checksum again (and test resetting ability)
+ fast_tester.reset();
+ slow_tester.reset( InRe );
+ fast_tester.process_bytes( ran_data, sizeof(ran_data) );
+ slow_tester.process_bytes( ran_data, sizeof(ran_data) );
+ BOOST_CHECK( fast_tester.checksum() == slow_tester.checksum() );
+ BOOST_CHECK( fast_tester.checksum() == fast_checksum );
+ BOOST_CHECK( slow_tester.checksum() == slow_checksum );
+
+ // Produce a single-bit error
+ ran_data[ ran_data[0] % ran_length ] ^= ( 1 << (ran_data[1] % 32) );
+
+ // Compute the checksum of the errorenous data
+ // (and continue testing resetting ability)
+ fast_tester.reset( InRe );
+ slow_tester.reset();
+ fast_tester.process_bytes( ran_data, sizeof(ran_data) );
+ slow_tester.process_bytes( ran_data, sizeof(ran_data) );
+ BOOST_CHECK( fast_tester.checksum() == slow_tester.checksum() );
+ BOOST_CHECK( fast_tester.checksum() != fast_checksum );
+ BOOST_CHECK( slow_tester.checksum() != slow_checksum );
+}
+
+// Run the other CRC object tests
+template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
+ CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
+void
+PRIVATE_TESTER_NAME::master_test
+(
+ char const * test_name,
+ typename PRIVATE_TESTER_NAME::value_type expected
+)
+{
+ std::cout << "Doing test suite for " << test_name << '.' << std::endl;
+ compute_test( expected );
+ interrupt_test( expected );
+ error_test();
+}
+
+// Undo limited macros
+#undef PRIVATE_TESTER_NAME
+
+
+// A CRC-32 computer based on crc_basic, for timing
+boost::uint32_t
+basic_crc32
+(
+ void const * buffer,
+ std::size_t byte_count
+)
+{
+ static boost::crc_basic<32> computer( 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF,
+ true, true );
+
+ computer.reset();
+ computer.process_bytes( buffer, byte_count );
+ return computer.checksum();
+}
+
+// A CRC-32 computer based on crc_optimal, for timing
+inline
+boost::uint32_t
+optimal_crc32
+(
+ void const * buffer,
+ std::size_t byte_count
+)
+{
+ static boost::crc_32_type computer;
+
+ computer.reset();
+ computer.process_bytes( buffer, byte_count );
+ return computer.checksum();
+}
+
+// Reflect the lower "bits" bits of a "value"
+boost::uint32_t
+quick_reflect
+(
+ boost::uint32_t value,
+ std::size_t bits
+)
+{
+ boost::uint32_t reflection = 0;
+ for ( std::size_t i = 0 ; i < bits ; ++i )
+ {
+ if ( value & (1u << i) )
+ {
+ reflection |= 1 << ( bits - 1 - i );
+ }
+ }
+
+ return reflection;
+}
+
+// A customized CRC-32 computer, for timing
+boost::uint32_t
+quick_crc32
+(
+ void const * buffer,
+ std::size_t byte_count
+)
+{
+ PRIVATE_DECLARE_BOOST( uint32_t );
+ typedef unsigned char byte_type;
+
+ // Compute the CRC table (first run only)
+ static bool did_init = false;
+ static uint32_t crc_table[ 1ul << CHAR_BIT ];
+ if ( !did_init )
+ {
+ uint32_t const value_high_bit = static_cast<uint32_t>(1) << 31u;
+
+ byte_type dividend = 0;
+ do
+ {
+ uint32_t remainder = 0;
+ for ( byte_type mask = 1u << (CHAR_BIT - 1u) ; mask ; mask >>= 1 )
+ {
+ if ( dividend & mask )
+ {
+ remainder ^= value_high_bit;
+ }
+
+ if ( remainder & value_high_bit )
+ {
+ remainder <<= 1;
+ remainder ^= 0x04C11DB7u;
+ }
+ else
+ {
+ remainder <<= 1;
+ }
+ }
+
+ crc_table[ quick_reflect(dividend, CHAR_BIT) ]
+ = quick_reflect( remainder, 32 );
+ }
+ while ( ++dividend );
+
+ did_init = true;
+ }
+
+ // Compute the CRC of the data
+ uint32_t rem = 0xFFFFFFFF;
+
+ byte_type const * const b_begin = static_cast<byte_type const *>( buffer );
+ byte_type const * const b_end = b_begin + byte_count;
+ for ( byte_type const *p = b_begin ; p < b_end ; ++p )
+ {
+ byte_type const byte_index = *p ^ rem;
+ rem >>= CHAR_BIT;
+ rem ^= crc_table[ byte_index ];
+ }
+
+ return ~rem;
+}
+
+// Run an individual timing trial
+double
+time_trial
+(
+ char const * name,
+ boost::uint32_t (*crc_func)(void const *, std::size_t),
+ boost::uint32_t expected,
+ void const * data,
+ std::size_t length
+)
+{
+ PRIVATE_DECLARE_BOOST( uint32_t );
+ using std::cout;
+
+ // Limits of a trial
+ static uint32_t const max_count = 1L << 16; // ~square-root of max
+ static double const max_time = 3.14159; // easy as pi(e)
+
+ // Mark the trial
+ cout << '\t' << name << " CRC-32: ";
+
+ // Trial loop
+ uint32_t trial_count = 0, wrong_count = 0;
+ double elapsed_time = 0.0;
+ boost::timer t;
+
+ do
+ {
+ uint32_t const scratch = (*crc_func)( data, length );
+
+ if ( scratch != expected )
+ {
+ ++wrong_count;
+ }
+ elapsed_time = t.elapsed();
+ ++trial_count;
+ } while ( (trial_count < max_count) && (elapsed_time < max_time) );
+
+ if ( wrong_count )
+ {
+ BOOST_ERROR( "at least one time trial didn't match expected" );
+ }
+
+ // Report results
+ double const rate = trial_count / elapsed_time;
+
+ cout << trial_count << " runs, " << elapsed_time << " s, " << rate
+ << " run/s" << std::endl;
+ return rate;
+}
+
+// Time runs of Boost CRCs vs. a customized CRC function
+void
+timing_test
+(
+)
+{
+ PRIVATE_DECLARE_BOOST( uint32_t );
+ using std::cout;
+ using std::endl;
+
+ cout << "Doing timing tests." << endl;
+
+ // Create a random block of data
+ boost::int32_t ran_data[ 256 ];
+ std::size_t const ran_length = sizeof(ran_data) / sizeof(ran_data[0]);
+
+ std::generate_n( ran_data, ran_length, boost::minstd_rand() );
+
+ // Use the first runs as a check. This gives a chance for first-
+ // time static initialization to not interfere in the timings.
+ uint32_t const basic_result = basic_crc32( ran_data, sizeof(ran_data) );
+ uint32_t const optimal_result = optimal_crc32( ran_data, sizeof(ran_data) );
+ uint32_t const quick_result = quick_crc32( ran_data, sizeof(ran_data) );
+
+ BOOST_CHECK( basic_result == optimal_result );
+ BOOST_CHECK( optimal_result == quick_result );
+ BOOST_CHECK( quick_result == basic_result );
+
+ // Run trials
+ double const basic_rate = time_trial( "Boost-Basic", basic_crc32,
+ basic_result, ran_data, sizeof(ran_data) );
+ double const optimal_rate = time_trial( "Boost-Optimal", optimal_crc32,
+ optimal_result, ran_data, sizeof(ran_data) );
+ double const quick_rate = time_trial( "Reference", quick_crc32,
+ quick_result, ran_data, sizeof(ran_data) );
+
+ // Report results
+ cout << "\tThe optimal Boost version is " << (quick_rate - optimal_rate)
+ / quick_rate * 100.0 << "% slower than the reference version.\n";
+ cout << "\tThe basic Boost version is " << (quick_rate - basic_rate)
+ / quick_rate * 100.0 << "% slower than the reference version.\n";
+ cout << "\tThe basic Boost version is " << (optimal_rate - basic_rate)
+ / optimal_rate * 100.0 << "% slower than the optimal Boost version."
+ << endl;
+}
+
+
+// Reformat an integer to the big-endian storage format
+boost::uint32_t
+native_to_big
+(
+ boost::uint32_t x
+)
+{
+ boost::uint32_t temp;
+ unsigned char * tp = reinterpret_cast<unsigned char *>( &temp );
+
+ for ( std::size_t i = sizeof(x) ; i > 0 ; --i )
+ {
+ tp[ i - 1 ] = static_cast<unsigned char>( x );
+ x >>= CHAR_BIT;
+ }
+
+ return temp;
+}
+
+// Restore an integer from the big-endian storage format
+boost::uint32_t
+big_to_native
+(
+ boost::uint32_t x
+)
+{
+ boost::uint32_t temp = 0;
+ unsigned char * xp = reinterpret_cast<unsigned char *>( &x );
+
+ for ( std::size_t i = 0 ; i < sizeof(x) ; ++i )
+ {
+ temp <<= CHAR_BIT;
+ temp |= xp[ i ];
+ }
+
+ return temp;
+}
+
+// Run tests on using CRCs on augmented messages
+void
+augmented_tests
+(
+)
+{
+ #define PRIVATE_ACRC_FUNC boost::augmented_crc<32, 0x04C11DB7>
+
+ using std::size_t;
+ PRIVATE_DECLARE_BOOST( uint32_t );
+
+ std::cout << "Doing CRC-augmented message tests." << std::endl;
+
+ // Create a random block of data, with space for a CRC.
+ uint32_t ran_data[ 257 ];
+ size_t const ran_length = sizeof(ran_data) / sizeof(ran_data[0]);
+ size_t const data_length = ran_length - 1;
+
+ std::generate_n( ran_data, data_length, boost::minstd_rand() );
+
+ // When creating a CRC for an augmented message, use
+ // zeros in the appended CRC spot for the first run.
+ uint32_t & ran_crc = ran_data[ data_length ];
+
+ ran_crc = 0;
+
+ // Compute the CRC with augmented-CRC computing function
+ typedef boost::uint_t<32>::fast return_type;
+
+ ran_crc = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data) );
+
+ // With the appended CRC set, running the checksum again should get zero.
+ // NOTE: CRC algorithm assumes numbers are in big-endian format
+ ran_crc = native_to_big( ran_crc );
+
+ uint32_t ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data) );
+
+ BOOST_CHECK( 0 == ran_crc_check );
+
+ // Compare that result with other CRC computing functions
+ // and classes, which don't accept augmented messages.
+ typedef boost::crc_optimal<32, 0x04C11DB7> fast_crc_type;
+ typedef boost::crc_basic<32> slow_crc_type;
+
+ fast_crc_type fast_tester;
+ slow_crc_type slow_tester( 0x04C11DB7 );
+ size_t const data_size = data_length * sizeof(ran_data[0]);
+ uint32_t const func_tester = boost::crc<32, 0x04C11DB7, 0, 0, false,
+ false>( ran_data, data_size );
+
+ fast_tester.process_bytes( ran_data, data_size );
+ slow_tester.process_bytes( ran_data, data_size );
+ BOOST_CHECK( fast_tester.checksum() == slow_tester.checksum() );
+ ran_crc = big_to_native( ran_crc );
+ BOOST_CHECK( fast_tester.checksum() == ran_crc );
+ BOOST_CHECK( func_tester == ran_crc );
+
+ // Do a single-bit error test
+ ran_crc = native_to_big( ran_crc );
+ ran_data[ ran_data[0] % ran_length ] ^= ( 1 << (ran_data[1] % 32) );
+ ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data) );
+ BOOST_CHECK( 0 != ran_crc_check );
+
+ // Run a version of these tests with a nonzero initial remainder.
+ uint32_t const init_rem = ran_data[ ran_data[2] % ran_length ];
+
+ ran_crc = 0;
+ ran_crc = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data), init_rem );
+
+ // Have some fun by processing data in two steps.
+ size_t const mid_index = ran_length / 2;
+
+ ran_crc = native_to_big( ran_crc );
+ ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, mid_index
+ * sizeof(ran_data[0]), init_rem );
+ ran_crc_check = PRIVATE_ACRC_FUNC( &ran_data[mid_index], sizeof(ran_data)
+ - mid_index * sizeof(ran_data[0]), ran_crc_check );
+ BOOST_CHECK( 0 == ran_crc_check );
+
+ // This substep translates an augmented-CRC initial
+ // remainder to an unaugmented-CRC initial remainder.
+ uint32_t const zero = 0;
+ uint32_t const new_init_rem = PRIVATE_ACRC_FUNC( &zero, sizeof(zero),
+ init_rem );
+ slow_crc_type slow_tester2( 0x04C11DB7, new_init_rem );
+
+ slow_tester2.process_bytes( ran_data, data_size );
+ ran_crc = big_to_native( ran_crc );
+ BOOST_CHECK( slow_tester2.checksum() == ran_crc );
+
+ // Redo single-bit error test
+ ran_data[ ran_data[3] % ran_length ] ^= ( 1 << (ran_data[4] % 32) );
+ ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data), init_rem );
+ BOOST_CHECK( 0 != ran_crc_check );
+
+ #undef PRIVATE_ACRC_FUNC
+}
+
+
+// Run tests on CRCs below a byte in size (here, 3 bits)
+void
+small_crc_test1
+(
+)
+{
+ std::cout << "Doing short-CRC (3-bit augmented) message tests."
+ << std::endl;
+
+ // The CRC standard is a SDH/SONET Low Order LCAS control word with CRC-3
+ // taken from ITU-T G.707 (12/03) XIII.2.
+
+ // Four samples, each four bytes; should all have a CRC of zero
+ unsigned char const samples[4][4]
+ = {
+ { 0x3A, 0xC4, 0x08, 0x06 },
+ { 0x42, 0xC5, 0x0A, 0x41 },
+ { 0x4A, 0xC5, 0x08, 0x22 },
+ { 0x52, 0xC4, 0x08, 0x05 }
+ };
+
+ // Basic computer
+ boost::crc_basic<3> tester1( 0x03 );
+
+ tester1.process_bytes( samples[0], 4 );
+ BOOST_CHECK( tester1.checksum() == 0 );
+
+ tester1.reset();
+ tester1.process_bytes( samples[1], 4 );
+ BOOST_CHECK( tester1.checksum() == 0 );
+
+ tester1.reset();
+ tester1.process_bytes( samples[2], 4 );
+ BOOST_CHECK( tester1.checksum() == 0 );
+
+ tester1.reset();
+ tester1.process_bytes( samples[3], 4 );
+ BOOST_CHECK( tester1.checksum() == 0 );
+
+ // Optimal computer
+ #define PRIVATE_CRC_FUNC boost::crc<3, 0x03, 0, 0, false, false>
+ #define PRIVATE_ACRC_FUNC boost::augmented_crc<3, 0x03>
+
+ BOOST_CHECK( 0 == PRIVATE_CRC_FUNC(samples[0], 4) );
+ BOOST_CHECK( 0 == PRIVATE_CRC_FUNC(samples[1], 4) );
+ BOOST_CHECK( 0 == PRIVATE_CRC_FUNC(samples[2], 4) );
+ BOOST_CHECK( 0 == PRIVATE_CRC_FUNC(samples[3], 4) );
+
+ // maybe the fix to CRC functions needs to be applied to augmented CRCs?
+
+ #undef PRIVATE_ACRC_FUNC
+ #undef PRIVATE_CRC_FUNC
+}
+
+// Run tests on CRCs below a byte in size (here, 7 bits)
+void
+small_crc_test2
+(
+)
+{
+ std::cout << "Doing short-CRC (7-bit augmented) message tests."
+ << std::endl;
+
+ // The CRC standard is a SDH/SONET J0/J1/J2/N1/N2/TR TTI (trace message)
+ // with CRC-7, o.a. ITU-T G.707 Annex B, G.832 Annex A.
+
+ // Two samples, each sixteen bytes
+ // Sample 1 is '\x80' + ASCII("123456789ABCDEF")
+ // Sample 2 is '\x80' + ASCII("TTI UNAVAILABLE")
+ unsigned char const samples[2][16]
+ = {
+ { 0x80, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41,
+ 0x42, 0x43, 0x44, 0x45, 0x46 },
+ { 0x80, 0x54, 0x54, 0x49, 0x20, 0x55, 0x4E, 0x41, 0x56, 0x41, 0x49,
+ 0x4C, 0x41, 0x42, 0x4C, 0x45 }
+ };
+ unsigned const results[2] = { 0x62, 0x23 };
+
+ // Basic computer
+ boost::crc_basic<7> tester1( 0x09 );
+
+ tester1.process_bytes( samples[0], 16 );
+ BOOST_CHECK( tester1.checksum() == results[0] );
+
+ tester1.reset();
+ tester1.process_bytes( samples[1], 16 );
+ BOOST_CHECK( tester1.checksum() == results[1] );
+
+ // Optimal computer
+ #define PRIVATE_CRC_FUNC boost::crc<7, 0x09, 0, 0, false, false>
+ #define PRIVATE_ACRC_FUNC boost::augmented_crc<7, 0x09>
+
+ BOOST_CHECK( results[0] == PRIVATE_CRC_FUNC(samples[0], 16) );
+ BOOST_CHECK( results[1] == PRIVATE_CRC_FUNC(samples[1], 16) );
+
+ // maybe the fix to CRC functions needs to be applied to augmented CRCs?
+
+ #undef PRIVATE_ACRC_FUNC
+ #undef PRIVATE_CRC_FUNC
+}
+
+
+#ifndef BOOST_MSVC
+// Explicit template instantiations
+// (needed to fix a link error in Metrowerks CodeWarrior Pro 5.3)
+template class crc_tester<16, 0x1021, 0xFFFF, 0, false, false>;
+template class crc_tester<16, 0x8005, 0, 0, true, true>;
+template class crc_tester<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true>;
+#endif
+
+// Main testing function
+int
+test_main
+(
+ int , // "argc" is unused
+ char * [] // "argv" is unused
+)
+{
+ using std::cout;
+ using std::endl;
+
+ // Run simulations on some CRC types
+ typedef crc_tester<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt_tester;
+ typedef crc_tester<16, 0x8005, 0, 0, true, true> crc_16_tester;
+ typedef crc_tester<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true>
+ crc_32_tester;
+
+ crc_ccitt_tester::master_test( "CRC-CCITT", std_crc_ccitt_result );
+ crc_16_tester::master_test( "CRC-16", std_crc_16_result );
+ crc_32_tester::master_test( "CRC-32", std_crc_32_result );
+
+ // Run a timing comparison test
+ timing_test();
+
+ // Test using augmented messages
+ augmented_tests();
+
+ // Test with CRC types smaller than a byte
+ small_crc_test1();
+ small_crc_test2();
+
+ // Try a CRC based on the (x + 1) polynominal, which is a factor in
+ // many real-life polynominals and doesn't fit evenly in a byte.
+ cout << "Doing one-bit polynominal CRC test." << endl;
+ boost::crc_basic<1> crc_1( 1 );
+ crc_1.process_bytes( std_data, std_data_len );
+ BOOST_CHECK( crc_1.checksum() == 1 );
+
+ // Test the function object interface
+ cout << "Doing functional object interface test." << endl;
+ boost::crc_optimal<16, 0x8005, 0, 0, true, true> crc_16;
+ crc_16 = std::for_each( std_data, std_data + std_data_len, crc_16 );
+ BOOST_CHECK( crc_16() == std_crc_16_result );
+
+ return boost::exit_success;
+}