Boost logo

Boost-Commit :

From: dwalker07_at_[hidden]
Date: 2008-08-10 11:45:18


Author: dlwalker
Date: 2008-08-10 11:45:17 EDT (Sun, 10 Aug 2008)
New Revision: 48059
URL: http://svn.boost.org/trac/boost/changeset/48059

Log:
Separated md5_computer type from main MD5 header; re-implemented some constants from that type as integral meta-constants, which also necessitated changes to some unit tests
Added:
   sandbox/md5/boost/coding/md5_computer.hpp (contents, props changed)
      - copied, changed from r48050, /sandbox/md5/boost/coding/md5.hpp
Text files modified:
   sandbox/md5/boost/coding/md5.hpp | 135 -------
   sandbox/md5/boost/coding/md5_computer.hpp | 676 +++++++++------------------------------
   sandbox/md5/boost/coding_fwd.hpp | 15
   sandbox/md5/libs/coding/src/md5.cpp | 46 ++
   sandbox/md5/libs/coding/test/md5_computer_test.cpp | 38 +-
   5 files changed, 241 insertions(+), 669 deletions(-)

Modified: sandbox/md5/boost/coding/md5.hpp
==============================================================================
--- sandbox/md5/boost/coding/md5.hpp (original)
+++ sandbox/md5/boost/coding/md5.hpp 2008-08-10 11:45:17 EDT (Sun, 10 Aug 2008)
@@ -19,8 +19,9 @@
 #define BOOST_CODING_MD5_HPP
 
 #include <boost/coding_fwd.hpp>
-#include <boost/coding/md5_digest.hpp> // for boost::coding::md5_digest
-#include <boost/coding/md5_context.hpp> // for boost::coding::md5_context
+#include <boost/coding/md5_digest.hpp> // for boost::coding::md5_digest
+#include <boost/coding/md5_context.hpp> // for boost::coding::md5_context
+#include <boost/coding/md5_computer.hpp> // for boost::coding::md5_computer
 
 #include <boost/array.hpp> // for boost::array
 #include <boost/assert.hpp> // for BOOST_ASSERT
@@ -245,106 +246,6 @@
 
 }; // md5_computerX
 
-/** \brief A class for generating a MD5 message digest from submitted data.
-
- This class can accept data in several runs and produce a hash based on that
- data from the MD5 message-digest algorithm described in RFC 1321. It should
- have a similar interface to Boost.CRC, plus specialized function object
- interfaces for bit- and byte-level processing (inspired by Boost.Bimap).
- Comparisons are supported for check-summing purposes, but not ordering.
- Persistence is supported though Boost.Serialization.
-
- \see boost::coding::md5_digest
- \see boost::coding::md5_context
- \see boost::coding::compute_md5(void const*,std::size_t)
-
- \todo Replace "uint_fast64_t" with "uint_t&lt;significant_bits_per_length&gt;::
- fast", where "significant_bits_per_length" is 64. (Need to tweak
- Boost.Integer to support 64-bit types.) Also need to make a
- convienent constant for the "16" in the base class declaration.
- (It's the number of words per block, from RFC 1321, section 3.4.)
- */
-class md5_computer
- : public bit_coding_shell<md5_context, true>
-{
- typedef bit_coding_shell<md5_context, true> base_type;
- typedef md5_computer self_type;
-
-public:
- // Constants
- static int const significant_bits_per_length =
- md5_computerX::significant_bits_per_length;
- static std::size_t const bits_per_block = md5_computerX::bits_per_block;
- static array<md5_digest::word_type, 64> const hashing_table;
-
- // Types
- typedef md5_context::length_type length_type;
- typedef array<md5_digest::word_type, md5_digest::words_per_digest::value>
- buffer_type;
-
- // Assignment
- //! Sets state back to initial conditions
- void reset() { *this = self_type(); }
- //! Changes the current state to a copy of another object's
- void assign( self_type const &c ) { *this = c; }
-
- //! Exchanges state with another object
- void swap( self_type &other ) { std::swap( *this, other ); }
-
- // Inspectors
- //! Returns the count of bits read so far
- length_type bits_read() const
- {
- return this->context().length &
- boost::integer_lo_mask<md5_context::bits_per_length::value>::value;
- }
- //! Returns the checksum buffer of hashed bits
- buffer_type last_buffer() const
- { return this->context().buffer; }
- //! Returns the count of the queued bits
- length_type bits_unbuffered() const
- { return this->bits_read() % md5_context::bits_per_block::value; }
- //! Copies out the queued bits
- template < typename OutputIterator >
- OutputIterator copy_unbuffered( OutputIterator o ) const
- {
- // Parameter check
- BOOST_CONCEPT_ASSERT( (boost::OutputIterator<OutputIterator, bool>) );
-
- return std::copy( this->context().queue.begin(),
- this->context().queue.begin() + this->bits_unbuffered(), o );
- }
-
- // Input processing
- //! Enters an octet
- void process_octet( uint_least8_t octet )
- {
- this->context().consume_octet( octet );
- }
- //! Enters a word for hashing
- void process_word( md5_digest::word_type word )
- {
- this->context().consume_word( word );
- }
- //! Enters a double-word for hashing
- void process_double_word( length_type dword )
- {
- this->context().consume_dword( dword );
- }
-
- // Extras
- static array<md5_digest::word_type, 64> generate_hashing_table()
- { return md5_computerX::generate_hashing_table(); }
-
-private:
- // Serialization
- friend class boost::serialization::access;
-
- template < class Archive >
- void serialize( Archive &ar, const unsigned int version ); // not defined yet
-
-}; // md5_computer
-
 
 // MD5 message-digest computation constructor definitions ------------------//
 
@@ -651,36 +552,6 @@
 }
 
 
-// MD5 message-digest computation miscellaneous function definitions -------//
-
-/** \brief Non-member swapping function for \c md5_computer
-
- Exchanges the states of two \c md5_computer objects. This specialization of
- the algorithm can be called by generic code that uses free-function
- (template) swap assisted with Koenig lookup.
-
- \param a The first object involved in the swap.
- \param b The second object involved in the swap.
-
- \post <code><var>a</var> == <var>old_b</var> &amp;&amp; <var>old_a</var> ==
- <var>b</var></code>
-
- \see boost::coding::md5_computer::swap
-
- \relates boost::coding::md5_computer
- */
-inline
-void
-swap
-(
- md5_computer & a,
- md5_computer & b
-)
-{
- a.swap( b );
-}
-
-
 // MD5 message-digest computation function definition ----------------------//
 
 /** \brief Immediate MD5 message-digest computation

Copied: sandbox/md5/boost/coding/md5_computer.hpp (from r48050, /sandbox/md5/boost/coding/md5.hpp)
==============================================================================
--- /sandbox/md5/boost/coding/md5.hpp (original)
+++ sandbox/md5/boost/coding/md5_computer.hpp 2008-08-10 11:45:17 EDT (Sun, 10 Aug 2008)
@@ -1,12 +1,11 @@
-// Boost coding/md5.hpp header file -----------------------------------------//
+// Boost coding/md5_computer.hpp header file --------------------------------//
 /** \file
- \brief Declarations of MD5 computation components.
+ \brief Declaration of MD5 computation object.
 
     \author Daryle Walker
 
- Contains the declaration of types and functions used for computing MD5
- message digests of given data blocks and granting I/O capability to any
- applicable types. Non-inline items declared here are defined in
+ Contains the declaration of the presentation type used for the computing of
+ MD5 message digests. Non-inline items declared here are defined in
     &quot;$BOOST_ROOT/libs/coding/src/md5.cpp&quot;.
  
     (C) Copyright Daryle Walker 2008. Distributed under the Boost Software
@@ -15,36 +14,22 @@
  */
 // See <http://www.boost.org/libs/coding> for documentation.
 
-#ifndef BOOST_CODING_MD5_HPP
-#define BOOST_CODING_MD5_HPP
+#ifndef BOOST_CODING_MD5_COMPUTER_HPP
+#define BOOST_CODING_MD5_COMPUTER_HPP
 
 #include <boost/coding_fwd.hpp>
 #include <boost/coding/md5_digest.hpp> // for boost::coding::md5_digest
 #include <boost/coding/md5_context.hpp> // for boost::coding::md5_context
 
 #include <boost/array.hpp> // for boost::array
-#include <boost/assert.hpp> // for BOOST_ASSERT
-#include <boost/coding/coding_shell.hpp> // for b:c:bit_coding_shell
-#include <boost/coding/operations.hpp> // for b:c:queued_bit_processing_base
+#include <boost/coding/coding_shell.hpp> // for boost:coding:bit_coding_shell
 #include <boost/concept/assert.hpp> // for BOOST_CONCEPT_ASSERT
 #include <boost/concept_check.hpp> // for boost::OutputIterator
-#include <boost/cstdint.hpp> // for boost::uint_least8_t, etc.
-#include <boost/integer.hpp> // for boost::sized_integral, etc.
+#include <boost/cstdint.hpp> // for boost::uint_least8_t
 #include <boost/integer/integer_mask.hpp> // for boost::integer_lo_mask
-#include <boost/mpl/arithmetic.hpp> // for boost::mpl::times
-#include <boost/mpl/int.hpp> // for boost::mpl::int_
-#include <boost/mpl/size_t.hpp> // for boost::mpl::size_t
 #include <boost/serialization/access.hpp> // for boost::serialization::access
-#include <boost/static_assert.hpp> // for BOOST_STATIC_ASSERT
-#include <boost/typeof/typeof.hpp> // for BOOST_AUTO
 
-#include <algorithm> // for std::equal, swap
-#include <climits> // for CHAR_BIT
-#include <cstddef> // for std::size_t
-#include <ios> // for std::ios_base
-#include <istream> // for std::basic_istream
-#include <locale> // for std::use_facet, ctype
-#include <ostream> // for std::basic_ostream
+#include <algorithm> // for std::copy, swap
 
 
 namespace boost
@@ -53,11 +38,6 @@
 {
 
 
-// Forward declarations ----------------------------------------------------//
-
-// None right now
-
-
 // MD5 message-digest computation class declaration ------------------------//
 
 /** \brief A class for generating a MD5 message digest from submitted data.
@@ -70,74 +50,22 @@
     Persistence is supported though Boost.Serialization.
 
     \see boost::coding::md5_digest
+ \see boost::coding::md5_context
     \see boost::coding::compute_md5(void const*,std::size_t)
-
- \todo Replace "uint_fast64_t" with "uint_t&lt;significant_bits_per_length&gt;::
- fast", where "significant_bits_per_length" is 64. (Need to tweak
- Boost.Integer to support 64-bit types.) Also need to make a
- convienent constant for the "16" in the base class declaration.
- (It's the number of words per block, from RFC 1321, section 3.4.)
- \todo The implementation base class was originally inherited privately, but
- the core member functions would give access errors when needed. The
- solution, for now, was either make \e all the base classes (direct
- and indirect) friends of this class, or change the inheritance to
- either public or protected. I haven't figured out why yet, or how to
- switch back to private inheritance without needing to add friendship.
- (Furthermore, I couldn't use \c base_type to establish friendship;
- i.e., both "friend base_type" and "friend class base_type" didn't
- work. I don't know why either.)
- */
-class md5_computerX
- : protected queued_bit_processing_base<md5_computerX, uint_fast64_t, 16u *
- md5_digest::bits_per_word::value>
+ */
+class md5_computer
+ : public bit_coding_shell<md5_context, true>
 {
- typedef queued_bit_processing_base<md5_computerX, uint_fast64_t, 16u *
- md5_digest::bits_per_word::value> base_type;
-
- friend void base_type::process_bit( bool ); // needs "update_hash" access
-
- // Implementation constants, followed by sanity checks
- static std::size_t const words_per_block = base_type::queue_length /
- md5_digest::bits_per_word::value;
-
- BOOST_STATIC_ASSERT( (base_type::queue_length % md5_digest::bits_per_word::value)
- == 0u );
- BOOST_STATIC_ASSERT( words_per_block == 16u ); // RFC 1321, section 3.4
+ typedef bit_coding_shell<md5_context, true> base_type;
+ typedef md5_computer self_type;
 
 public:
- // Special application interface
- using base_type::bits;
- using base_type::bytes;
-
- // Constants
- //! Number of bits for length quantities
- static int const significant_bits_per_length = 2 *
- md5_digest::bits_per_word::value;
- //! Number of bits in hash queue
- static std::size_t const bits_per_block = base_type::queue_length;
-
- //! Hashing sine table
- static array<md5_digest::word_type, 64> const hashing_table;
-
     // Types
- /** \brief Type of checksums
-
- Represents the type of hashes generated by this type.
- */
- typedef md5_digest value_type;
- /** \brief Type of size values
-
- Represents the type used for sizing parameters and returns. It should
- be an unsigned integer.
- */
- typedef base_type::size_type size_type;
-
     /** \brief Type of MD message lengths
 
         Represents the type needed to store the significant count of bits read.
      */
- typedef uint_least64_t length_type;
- // replace w/ uint_t<significant_bits_per_length>::least
+ typedef md5_context::length_type length_type;
     /** \brief Type of MD buffers
 
         Represents the intermediate MD buffer, holding the checksum for all
@@ -147,194 +75,67 @@
     typedef array<md5_digest::word_type, md5_digest::words_per_digest::value>
       buffer_type;
 
- // Lifetime management (use automatic destructor)
- //! Default construction
- md5_computerX();
- //! Copy construction
- md5_computerX( md5_computerX const &c );
+ /** \brief Type of hashing sine tables
 
- /*! \name Assignment */ //@{
- // Assignment
- //! Sets state back to initial conditions
- void reset();
- //! Changes the current state to a copy of another object's
- void assign( md5_computerX const &c );
+ Represents the storage for the hashing constants, based off the sine
+ function.
+ */
+ typedef array<md5_digest::word_type,
+ md5_context::hash_table_type::static_size> hash_table_type;
 
- //! Exchanges state with another object
- void swap( md5_computerX &other );//@}
+ /** \brief Number of bits in hash queue, as an integer meta-constant
+
+ Represents the number of submitted bits that are queued until that queue
+ is emptied as a single block to be hashed, implied from RFC 1321,
+ section 3.4. The count of unhashed bits is always less than this value.
+ (The input processing member functions trigger a hash right after a bit
+ fills the queue.)
+ */
+ typedef md5_context::bits_per_block bits_per_block;
+ /** \brief Number of bits for length quantities, as integer meta-constant
+
+ Represents the number of significant (low-order) bits kept for the
+ message length, which can also be processed as two words, all as given
+ in RFC 1321, section 3.2, paragraph 1.
+ */
+ typedef md5_context::bits_per_length significant_bits_per_length;
+
+ // Constants
+ //! Hashing sine table
+ static hash_table_type const hashing_table;
 
- /*! \name Inspection */ //@{
     // Inspectors
     //! Returns the count of bits read so far
     length_type bits_read() const;
     //! Returns the checksum buffer of hashed bits
     buffer_type last_buffer() const;
+ //! Returns the count of the queued bits
+ length_type bits_unbuffered() const;
 
- using base_type::bits_unbuffered;
- using base_type::copy_unbuffered;//@}
-
- /*! \name Bit-stream reading */ //@{
- // Input processing
- using base_type::process_bit;
- using base_type::process_bits;
- using base_type::process_bit_copies;
- using base_type::process_byte;
- using base_type::process_byte_copies;
- using base_type::process_block;
- using base_type::process_bytes;
- using base_type::process_octet;
-
- //! Enters a word for hashing
- void process_word( md5_digest::word_type word );
- //! Enters a double-word for hashing
- void process_double_word( length_type dword );//@}
-
- /*! \name Message-digest writing */ //@{
- // Output processing
- //! Returns the message digest, assuming all bits have been hashed
- value_type checksum() const;//@}
-
- /*! \name Operators */ //@{
- // Operators
- //! Copy-assignment
- md5_computerX & operator =( md5_computerX const &c );
-
- //! Equals
- bool operator ==( md5_computerX const &c ) const;
- //! Not-equals
- bool operator !=( md5_computerX const &c ) const;
-
- //! Application
- value_type operator ()() const;//@}
-
- // Extras
- //! Creates a copy of #hashing_table using calculated, not static, values
- static array<md5_digest::word_type, 64> generate_hashing_table();
-
-private:
- // Bad if computers someday get so big that a byte overflows the queue!
- BOOST_STATIC_ASSERT( bits_per_block > CHAR_BIT );
-
- // State maintainence
- bool test_invariant() const { return true; } // Nothing special right now
-
- // Serialization
- friend class serialization::access;
-
- /*! \name Persistence */ //@{
- //! Enables persistence with Boost.Serialization-compatible archives
- template < class Archive >
- void serialize( Archive &ar, const unsigned int version );//@}
- // may have to do save/load split; support XML archives
-
- // Implementation functions
- void update_hash( bool const *queue_b, bool const *queue_e );
-
- // Implementation types
- typedef md5_computerX self_type;
-
- typedef uint_t<md5_digest::bits_per_word::value>::fast iword_type;
- typedef array<iword_type, md5_digest::words_per_digest::value> ibuffer_type;
-
- // (Computation) member data
- ibuffer_type buffer_;
-
- static ibuffer_type const initial_buffer_;
-
- friend class md5_context;
-
-}; // md5_computerX
-
-/** \brief A class for generating a MD5 message digest from submitted data.
-
- This class can accept data in several runs and produce a hash based on that
- data from the MD5 message-digest algorithm described in RFC 1321. It should
- have a similar interface to Boost.CRC, plus specialized function object
- interfaces for bit- and byte-level processing (inspired by Boost.Bimap).
- Comparisons are supported for check-summing purposes, but not ordering.
- Persistence is supported though Boost.Serialization.
-
- \see boost::coding::md5_digest
- \see boost::coding::md5_context
- \see boost::coding::compute_md5(void const*,std::size_t)
-
- \todo Replace "uint_fast64_t" with "uint_t&lt;significant_bits_per_length&gt;::
- fast", where "significant_bits_per_length" is 64. (Need to tweak
- Boost.Integer to support 64-bit types.) Also need to make a
- convienent constant for the "16" in the base class declaration.
- (It's the number of words per block, from RFC 1321, section 3.4.)
- */
-class md5_computer
- : public bit_coding_shell<md5_context, true>
-{
- typedef bit_coding_shell<md5_context, true> base_type;
- typedef md5_computer self_type;
-
-public:
- // Constants
- static int const significant_bits_per_length =
- md5_computerX::significant_bits_per_length;
- static std::size_t const bits_per_block = md5_computerX::bits_per_block;
- static array<md5_digest::word_type, 64> const hashing_table;
-
- // Types
- typedef md5_context::length_type length_type;
- typedef array<md5_digest::word_type, md5_digest::words_per_digest::value>
- buffer_type;
+ //! Copies out the queued bits
+ template < typename OutputIterator >
+ OutputIterator copy_unbuffered( OutputIterator o ) const;
 
     // Assignment
     //! Sets state back to initial conditions
- void reset() { *this = self_type(); }
+ void reset();
     //! Changes the current state to a copy of another object's
- void assign( self_type const &c ) { *this = c; }
+ void assign( self_type const &c );
 
     //! Exchanges state with another object
- void swap( self_type &other ) { std::swap( *this, other ); }
-
- // Inspectors
- //! Returns the count of bits read so far
- length_type bits_read() const
- {
- return this->context().length &
- boost::integer_lo_mask<md5_context::bits_per_length::value>::value;
- }
- //! Returns the checksum buffer of hashed bits
- buffer_type last_buffer() const
- { return this->context().buffer; }
- //! Returns the count of the queued bits
- length_type bits_unbuffered() const
- { return this->bits_read() % md5_context::bits_per_block::value; }
- //! Copies out the queued bits
- template < typename OutputIterator >
- OutputIterator copy_unbuffered( OutputIterator o ) const
- {
- // Parameter check
- BOOST_CONCEPT_ASSERT( (boost::OutputIterator<OutputIterator, bool>) );
-
- return std::copy( this->context().queue.begin(),
- this->context().queue.begin() + this->bits_unbuffered(), o );
- }
+ void swap( self_type &other );
 
     // Input processing
     //! Enters an octet
- void process_octet( uint_least8_t octet )
- {
- this->context().consume_octet( octet );
- }
+ void process_octet( uint_least8_t octet );
     //! Enters a word for hashing
- void process_word( md5_digest::word_type word )
- {
- this->context().consume_word( word );
- }
+ void process_word( md5_digest::word_type word );
     //! Enters a double-word for hashing
- void process_double_word( length_type dword )
- {
- this->context().consume_dword( dword );
- }
+ void process_double_word( length_type dword );
 
     // Extras
- static array<md5_digest::word_type, 64> generate_hashing_table()
- { return md5_computerX::generate_hashing_table(); }
+ //! Creates copy of \c #hashing_table using calculated, not static, values
+ static hash_table_type generate_hashing_table();
 
 private:
     // Serialization
@@ -346,82 +147,73 @@
 }; // md5_computer
 
 
-// MD5 message-digest computation constructor definitions ------------------//
-
-/** Constructs a \c md5_computerX set to initial conditions. That is, with the
- buffer initialized as in RFC 1321, section 3.3, and no bits counted as read
- or currently left to be hashed.
-
- \post <code>#bits_read() == 0</code>
- \post <code>#last_buffer() == { 0x67452301, 0xEFCDAB89, 0x98BACDFE,
- 0x10325476 }</code>
- \post <code>#copy_unbuffered(<var>o</var>)</code> leaves \p o unused
- \post \c #bits and \c #bytes point to \c *this
- */
-inline
-md5_computerX::md5_computerX()
- : base_type()
- , buffer_( self_type::initial_buffer_ )
-{
- BOOST_ASSERT( this->test_invariant() );
-}
-
-/** Constructs a \c md5_computerX to the same computation state as <var>c</var>.
-
- \param c The original object to be copied.
-
- \post <code>#bits_read() == <var>c</var>.bits_read()</code>
- \post <code>#last_buffer() == <var>c</var>.last_buffer()</code>
- \post Given <code>#copy_unbuffered(<var>o1</var>)</code> and
- <code><var>c</var>.copy_unbuffered(<var>o2</var>)</code>, where both
- \p o1 and \p o2 are random access iterators to different container
- segments that each have at least <code>#bits_unbuffered()</code>
- elements available, <code>std::equal( o1, o1 + bits_unbuffered(), o2
- ) == true</code>
- \post \c #bits and \c #bytes point to \c *this
- */
-inline
-md5_computerX::md5_computerX( md5_computerX const &c )
- : base_type( c )
- , buffer_( c.buffer_ )
-{
- BOOST_ASSERT( this->test_invariant() );
-}
-
-
 // MD5 message-digest computation inspector member function definitions ----//
 
 /** Returns the number of bits that have been processed, both those that have
- been hashed and those that are on queue. Only the low-order 64 bits of
+ been hashed and those that are on queue. Only the lowest-order 64 bits of
     count are significant and kept/reliable.
 
     \return How many bits have been submitted, hashed and queued.
  */
-inline
-md5_computerX::length_type
-md5_computerX::bits_read() const
+inline md5_computer::length_type
+md5_computer::bits_read() const
 {
- // Don't count any wrap-around past 2**64
- // (Use mask value once Boost.Integer is upped to 64-bit support)
- return this->base_type::bits_read() & 0xFFFFFFFFFFFFFFFFull;
+ return this->context().length &
+ boost::integer_lo_mask<md5_context::bits_per_length::value>::value;
 }
 
 /** Returns the checksum of all the bits that have been hashed so far. Hashing
- occurs only after every \c #bits_per_block bit entries, so check
+ occurs only after every \c #bits_per_block::value bit entries, so check
     \c #bits_unbuffered() for any queued stragglers.
 
     \return The current state of the MD buffer, not counting any unhashed bits.
  */
-inline
-md5_computerX::buffer_type
-md5_computerX::last_buffer() const
+inline md5_computer::buffer_type
+md5_computer::last_buffer() const { return this->context().buffer; }
+
+/** Returns the number of bits that are still in the queue, unhashed. Hashing
+ occurs only after every \c #bits_per_block::value bit submissions, so this
+ member function can confirm queued stragglers. (The identities of hashed
+ bits are not retrievable.)
+
+ \return How many bits are queued to be hashed.
+
+ \see #bits_read()
+ \see #bits_per_block
+ */
+inline md5_computer::length_type
+md5_computer::bits_unbuffered() const
+{ return this->bits_read() % md5_context::bits_per_block::value; }
+
+/** Copies the last submitted bits that have not yet been hashed starting from
+ the oldest submission. Use \c #bits_unbuffered() for advance notice of how
+ many iterations are done. (Always less than \c #bits_per_block::value
+ elements are copied.)
+
+ \pre At least \c #bits_unbuffered() more elements are free to be created
+ and/or assigned through \p o.
+
+ \tparam OutputIterator The type of the iterator submitted. It should match
+ the requirements of either an output or a forward
+ (or above) mutable iterator over something that can
+ receive \c bool values via dereferenced assignment.
+
+ \param o The iterator starting the destination range.
+
+ \return \p o after the copying.
+
+ \see #bits_unbuffered()
+ \see #bits_per_block
+ */
+template < typename OutputIterator >
+inline OutputIterator
+md5_computer::copy_unbuffered( OutputIterator o ) const
 {
- // boost::array has no constructors (since it's POD), that means that if
- // buffer_type and ibuffer_type differ, we need to convert via assignment.
- buffer_type r;
+ // Parameter check
+ BOOST_CONCEPT_ASSERT( (boost::OutputIterator<OutputIterator, bool>) );
 
- r = this->buffer_;
- return r;
+ return std::copy( this->context().queue.begin(),
+ this->context().queue.begin() + this->bits_unbuffered(), o );
 }
 
 
@@ -429,49 +221,33 @@
 
 /** Changes an object to be like it was default-constructed.
 
- \post <code>#bits_read() == 0</code>
+ \post <code>#bits_read() == 0</code>.
     \post <code>#last_buffer() == { 0x67452301, 0xEFCDAB89, 0x98BACDFE,
- 0x10325476 }</code>
- \post <code>#copy_unbuffered(<var>o</var>)</code> leaves \p o unused
+ 0x10325476 }</code>.
+ \post <code>#copy_unbuffered(<var>o</var>)</code> leaves \p o unused.
 
- \see #md5_computerX()
+ \see #md5_computer()
  */
-inline
-void
-md5_computerX::reset()
-{
- this->base_type::reset();
- this->buffer_ = self_type::initial_buffer_;
-
- BOOST_ASSERT( this->test_invariant() );
-}
+inline void md5_computer::reset() { *this = self_type(); }
 
 /** Changes an object to be like the given object. Only the computation
     elements are copied; no function object proxies are reseated.
 
     \param c The object with the new state to be copied.
 
- \post <code>#bits_read() == <var>c</var>.bits_read()</code>
- \post <code>#last_buffer() == <var>c</var>.last_buffer()</code>
+ \post <code>#bits_read() == <var>c</var>.bits_read()</code>.
+ \post <code>#last_buffer() == <var>c</var>.last_buffer()</code>.
     \post Given <code>#copy_unbuffered(<var>o1</var>)</code> and
            <code><var>c</var>.copy_unbuffered(<var>o2</var>)</code>, where both
- \p o1 and \p o2 are random access iterators to different container
- segments that each have at least <code>#bits_unbuffered()</code>
- elements available, <code>std::equal( o1, o1 + bits_unbuffered(), o2
- ) == true</code>
+ \p o1 and \p o2 are forward iterators to different container segments
+ that each have at least <code>#bits_unbuffered()</code> elements
+ available, <code>std::equal( o1, o1 + bits_unbuffered(), o2 ) ==
+ true</code>.
     \post \c #bits and \c #bytes \e still point to \c *this
 
- \see #md5_computerX(md5_computerX const&)
+ \see #md5_computer(md5_computer const&)
  */
-inline
-void
-md5_computerX::assign( md5_computerX const &c )
-{
- this->base_type::assign( c );
- this->buffer_ = c.buffer_;
-
- BOOST_ASSERT( this->test_invariant() );
-}
+inline void md5_computer::assign( self_type const &c ) { *this = c; }
 
 /** Swaps the content of this object with another. Only the computation
     elements are changed; no function object proxies are reseated.
@@ -479,37 +255,55 @@
     \param other The other object to trade state with this object.
 
     \post <code>*this == <var>old_other</var> &amp;&amp; <var>old_this</var> ==
- <var>other</var></code>
+ <var>other</var></code>.
  */
-inline
-void
-md5_computerX::swap( md5_computerX &other )
-{
- // Use the appropriate swap via Koeing look-up
- using std::swap;
+inline void md5_computer::swap( self_type &other ) { std::swap(*this, other); }
 
- // Swap the computation members (don't reseat the function object proxies)
- this->base_type::swap( other );
- swap( this->buffer_, other.buffer_ );
 
- BOOST_ASSERT( this->test_invariant() );
- BOOST_ASSERT( other.test_invariant() );
-}
+// MD5 message-digest computation bit-input member function definitions ----//
 
+/** Submits an octet for computation. The bits are submitted starting from the
+ highest-order bit to the lowest. Note that a byte may be larger than eight
+ bits, so the lowest-significant bits within the containing byte (or larger
+ register) are chosen. This way, you don't have to shift up your octet value
+ by <code>sizeof(<var>octet</var>) * CHAR_BIT - 8</code> (or whatever) bits.
 
-// MD5 message-digest computation bit-input member function definitions ----//
+ \param octet The octet value to be submitted.
+
+ \post <code>#bits_read() == <var>old_this</var>.bits_read() + 8</code>.
+ \post <code>#bits_unbuffered() == (<var>old_this</var>.bits_unbuffered() +
+ 8) % bits_per_block</code>.
+ \post <code>#last_buffer() == (<var>old_this</var>.bits_unbuffered() + 8
+ &gt;= bits_per_block) ? <var>new_value</var> :
+ <var>old_this</var>.last_buffer()</code>. (The new value is computed
+ with the algorithm described in RFC 1321, section 3.4.)
+ \post If <code>bits_read() % bits_per_block == 0</code>, then
+ <code>#copy_unbuffered(<var>o1</var>)</code> leaves \p o1 unused,
+ otherwise if <code><var>old_this</var>.bits_unbuffered() + 8 &lt;
+ bits_per_block,</code> then <code>copy_unbuffered(<var>o2</var>) -
+ <var>old_this</var>.copy_unbuffered(<var>o2</var>) == 8</code>
+ (assuming that \p o2 is, at least, a forward iterator), otherwise the
+ range \p o3 to <code>copy_unbuffered(<var>o3</var>)</code> contains
+ the <code><var>old_this</var>.bits_unbuffered() + 8 -
+ bits_per_block</code> lowest-order bits of \p octet.
+
+ \see boost::coding::bit_coding_shell<>::process_bits(unsigned char,size_type)
+ */
+inline void
+md5_computer::process_octet( uint_least8_t octet )
+{ this->context().consume_octet( octet ); }
 
 /** Submits 32-bit MD-word for computation. The word is submitted an octet at a
     time, from the lowest-order octet to the highest.
 
     \param word The word value to be submitted.
 
- \post <code>#bits_read() == <var>old_this</var>.bits_read() + 32</code>
+ \post <code>#bits_read() == <var>old_this</var>.bits_read() + 32</code>.
     \post <code>#bits_unbuffered() == (<var>old_this</var>.bits_unbuffered() +
- 32) % bits_per_block</code>
+ 32) % bits_per_block</code>.
     \post <code>#last_buffer() == (<var>old_this</var>.bits_unbuffered() + 32
            &gt;= bits_per_block) ? <var>new_value</var> :
- <var>old_this</var>.last_buffer()</code> (The new value is computed
+ <var>old_this</var>.last_buffer()</code>. (The new value is computed
            with the algorithm described in RFC 1321, section 3.4.)
     \post If <code>bits_read() % bits_per_block == 0</code>, then
            <code>#copy_unbuffered(<var>o1</var>)</code> leaves \p o1 unused,
@@ -519,31 +313,25 @@
            (assuming that \p o2 is, at least, a forward iterator), otherwise the
            range \p o3 to <code>copy_unbuffered(<var>o3</var>)</code> contains
            the <code><var>old_this</var>.bits_unbuffered() + 32 -
- bits_per_block</code> lowest-order bits of \p word
+ bits_per_block</code> lowest-order bits of \p word.
 
     \see #process_octet(boost::uint_least8_t)
  */
-inline
-void
-md5_computerX::process_word( md5_digest::word_type word )
-{
- this->process_octet( word & 0xFFul );
- this->process_octet( (word >> 8) & 0xFFul );
- this->process_octet( (word >> 16) & 0xFFul );
- this->process_octet( (word >> 24) & 0xFFul );
-}
+inline void
+md5_computer::process_word( md5_digest::word_type word )
+{ this->context().consume_word( word ); }
 
 /** Submits 64-bit MD-length for computation. The double-word is submitted a
     word at a time, first the low-order word then the high-order word.
 
     \param dword The double-word value to be submitted.
 
- \post <code>#bits_read() == <var>old_this</var>.bits_read() + 64</code>
+ \post <code>#bits_read() == <var>old_this</var>.bits_read() + 64</code>.
     \post <code>#bits_unbuffered() == (<var>old_this</var>.bits_unbuffered() +
- 64) % bits_per_block</code>
+ 64) % bits_per_block</code>.
     \post <code>#last_buffer() == (<var>old_this</var>.bits_unbuffered() + 64
            &gt;= bits_per_block) ? <var>new_value</var> :
- <var>old_this</var>.last_buffer()</code> (The new value is computed
+ <var>old_this</var>.last_buffer()</code>. (The new value is computed
            with the algorithm described in RFC 1321, section 3.4.)
     \post If <code>bits_read() % bits_per_block == 0</code>, then
            <code>#copy_unbuffered(<var>o1</var>)</code> leaves \p o1 unused,
@@ -553,102 +341,13 @@
            (assuming that \p o2 is, at least, a forward iterator), otherwise the
            range \p o3 to <code>copy_unbuffered(<var>o3</var>)</code> contains
            the <code><var>old_this</var>.bits_unbuffered() + 64 -
- bits_per_block</code> lowest-order bits of \p word
+ bits_per_block</code> lowest-order bits of \p dword.
 
     \see #process_word(boost::coding::md5_digest::word_type)
  */
-inline
-void
-md5_computerX::process_double_word( md5_computerX::length_type dword )
-{
- this->process_word( dword & 0xFFFFFFFFull );
- this->process_word( (dword >> 32) & 0xFFFFFFFFull );
-}
-
-
-// MD5 message-digest structure member operator function definitions -------//
-
-/** Changes a MD5 message computer to have the same observable state as a given
- computer. (No function object proxies are reseated, however.)
-
- \param c The source object with the new state.
-
- \return \c *this
-
- \post <code>#bits_read() == <var>c</var>.bits_read()</code>
- \post <code>#last_buffer() == <var>c</var>.last_buffer()</code>
- \post Given <code>#copy_unbuffered(<var>o1</var>)</code> and
- <code><var>c</var>.copy_unbuffered(<var>o2</var>)</code>, where both
- \p o1 and \p o2 are random access iterators to different container
- segments that each have at least <code>#bits_unbuffered()</code>
- elements available, <code>std::equal( o1, o1 + bits_unbuffered(), o2
- ) == true</code>
- \post \c #bits and \c #bytes \e still point to \c *this
-
- \see #assign(md5_computerX const&)
- */
-inline
-md5_computerX &
-md5_computerX::operator =( md5_computerX const &c )
-{
- this->assign( c );
- return *this;
-}
-
-/** Compares MD5 message computers for equivalence. Such computers are equal if
- all of the corresponding parts of their significant state (data length,
- running hash, and bit queue) are equal.
-
- \param c The right-side operand to be compared.
-
- \retval true \c *this and \p c are equivalent.
- \retval false \c *this and \p c are not equivalent.
-
- \see #bits_read()
- \see #last_buffer()
- \see #copy_unbuffered(OutputIterator)
- */
-inline
-bool
-md5_computerX::operator ==( md5_computerX const &c ) const
-{
- // Don't compare the function object proxies since they don't carry
- // significant state. (Furthermore, they can't change once initalized and
- // don't have any comparison operators.)
- return ( this->buffer_ == c.buffer_ ) && this->base_type::operator ==( c );
-}
-
-/** Compares MD5 message computers for non-equivalence. Such computers are
- unequal if at least one set of corresponding parts of their significant
- state (data length, running hash, and bit queue) are unequal.
-
- \param c The right-side operand to be compared.
-
- \retval true \c *this and \p c are not equivalent.
- \retval false \c *this and \p c are equivalent.
-
- \see #operator==(md5_computerX const&)const
- */
-inline
-bool
-md5_computerX::operator !=( md5_computerX const &c ) const
-{
- return !this->operator ==( c );
-}
-
-/** Computes the check-sum of the submitted data, through a standard generator
- interface.
-
- \return The generated check-sum.
-
- \see #checksum()const
- */
-inline
-md5_computerX::value_type
-md5_computerX::operator ()() const
-{
- return this->checksum();
-}
+inline void
+md5_computer::process_double_word( length_type dword )
+{ this->context().consume_dword( dword ); }
 
 
 // MD5 message-digest computation miscellaneous function definitions -------//
@@ -669,54 +368,11 @@
 
     \relates boost::coding::md5_computer
  */
-inline
-void
-swap
-(
- md5_computer & a,
- md5_computer & b
-)
-{
- a.swap( b );
-}
-
-
-// MD5 message-digest computation function definition ----------------------//
-
-/** \brief Immediate MD5 message-digest computation
-
- Determines the MD5 message-digest of a given block of data, without
- requiring the setup of a computation object.
-
- \pre \p buffer must point to a valid region of memory that contains at
- least \p byte_count bytes past the given pointer.
-
- \param buffer Points to the beginning of the data block to be
- processed.
- \param byte_count The length of the data block to be processed, in bytes.
-
- \return The MD5 message digest of the data block.
-
- \see boost::coding::md5_digest
- \see boost::coding::md5_computer
- */
-inline
-md5_digest
-compute_md5
-(
- void const * buffer,
- std::size_t byte_count
-)
-{
- md5_computer c;
-
- c.process_bytes( buffer, byte_count );
- return c.checksum();
-}
+inline void swap( md5_computer &a, md5_computer &b ) { a.swap( b ); }
 
 
 } // namespace coding
 } // namespace boost
 
 
-#endif // BOOST_CODING_MD5_HPP
+#endif // BOOST_CODING_MD5_COMPUTER_HPP

Modified: sandbox/md5/boost/coding_fwd.hpp
==============================================================================
--- sandbox/md5/boost/coding_fwd.hpp (original)
+++ sandbox/md5/boost/coding_fwd.hpp 2008-08-10 11:45:17 EDT (Sun, 10 Aug 2008)
@@ -68,13 +68,22 @@
 // Only has operator free-functions, #includes "md5_digest_core.hpp"
 
 
-// From <boost/coding/md5.hpp> ---------------------------------------------//
-
-class md5_computerX;
+// From <boost/coding/md5_context.hpp> -------------------------------------//
 
 class md5_context;
+
+
+// From <boost/coding/md5_computer.hpp> ------------------------------------//
+
 class md5_computer;
 
+// Also has a support free-function
+
+
+// From <boost/coding/md5.hpp> ---------------------------------------------//
+
+class md5_computerX;
+
 // Also has a free function
 
 

Modified: sandbox/md5/libs/coding/src/md5.cpp
==============================================================================
--- sandbox/md5/libs/coding/src/md5.cpp (original)
+++ sandbox/md5/libs/coding/src/md5.cpp 2008-08-10 11:45:17 EDT (Sun, 10 Aug 2008)
@@ -6,7 +6,8 @@
 
     Contains the definitions of constants and functions used for computing MD5
     message digests of given data blocks and granting I/O capability to any
- applicable types. Non-inline items from &lt;boost/coding/md5.hpp&gt; and
+ applicable types. Non-inline items from
+ &lt;boost/coding/md5_computer.hpp&gt; and
     &lt;boost/coding/md5_context.hpp&gt; are defined here.
  
     (C) Copyright Daryle Walker 2008. Distributed under the Boost Software
@@ -439,11 +440,6 @@
     return r;
 }
 
-int const md5_computer::significant_bits_per_length;
-std::size_t const md5_computer::bits_per_block;
-array<md5_digest::word_type, 64> const md5_computer::hashing_table =
- md5_computerX::hashing_table;
-
 
 // MD5 message-digest core computation non-inline member definitions -------//
 
@@ -580,5 +576,43 @@
 }
 
 
+// MD5 message-digest computation non-inline member definitions ------------//
+
+/** Sample of the table described in RFC 1321, section 3.4, paragraph 4. Its
+ values are taken directly from the "MD5Transform" function in the RFC's
+ section A.3, and are not computed. Of course, the index is zero-based (C++)
+ instead of one-based (RFC).
+
+ \see #generate_hashing_table
+ */
+md5_computer::hash_table_type const md5_computer::hashing_table =
+ md5_computerX::hashing_table;
+
+/** Constructs the hashing sine table based on the directions given in RFC 1321,
+ section 3.4, paragraph 4. It should give the same values as
+ \c #hashing_table, but it is dependent on the quality of the platform's math
+ library, thereby testing that environment.
+
+ \return The computed hashing sine table
+
+ \see #hashing_table
+ */
+md5_computer::hash_table_type
+md5_computer::generate_hashing_table()
+{
+ hash_table_type result;
+
+ for ( int i = 0 ; i < hash_table_type::static_size ; ++i )
+ {
+ double x = std::ldexp( std::abs(std::sin( static_cast<double>(i + 1)
+ )), +32 ); // 2**32 * abs(sin(I)), where I = i + 1
+
+ std::modf( x, &x ); // x -> x rounded towards zero
+ result[ i ] = static_cast<unsigned long>( x );
+ }
+ return result;
+}
+
+
 } // namespace coding
 } // namespace boost

Modified: sandbox/md5/libs/coding/test/md5_computer_test.cpp
==============================================================================
--- sandbox/md5/libs/coding/test/md5_computer_test.cpp (original)
+++ sandbox/md5/libs/coding/test/md5_computer_test.cpp 2008-08-10 11:45:17 EDT (Sun, 10 Aug 2008)
@@ -27,7 +27,7 @@
 using boost::coding::md5_computer;
 using boost::coding::md5_digest;
 
-typedef array<bool, md5_computer::bits_per_block> bit_queue;
+typedef array<bool, md5_computer::bits_per_block::value> bit_queue;
 
 
 // Put custom types/templates and helper functions here
@@ -188,7 +188,8 @@
         md5_computer c7;
         size_t const bytes_to_use = 3u;
         unsigned char const value = 0x37u; // {'0' x (CHAR_BIT-6)}110111
- BOOST_REQUIRE( CHAR_BIT * bytes_to_use < md5_computer::bits_per_block );
+ BOOST_REQUIRE_LT( CHAR_BIT * bytes_to_use,
+ md5_computer::bits_per_block::value );
         c7.process_byte_copies( value, bytes_to_use );
         BOOST_CHECK_EQUAL( c7.bits_read(), CHAR_BIT * bytes_to_use );
         BOOST_CHECK_EQUAL( c7.bits_unbuffered(), CHAR_BIT * bytes_to_use );
@@ -213,7 +214,8 @@
         md5_computer c8;
         array<unsigned char, 3> const values = { {0x37u, 0x48u, 0x1Cu} };
         size_t const bytes_to_use = 3u;
- BOOST_REQUIRE( CHAR_BIT * bytes_to_use < md5_computer::bits_per_block );
+ BOOST_REQUIRE_LT( CHAR_BIT * bytes_to_use,
+ md5_computer::bits_per_block::value );
         c8.process_block( values.begin(), values.end() );
         BOOST_CHECK_EQUAL( c8.bits_read(), CHAR_BIT * bytes_to_use );
         BOOST_CHECK_EQUAL( c8.bits_unbuffered(), CHAR_BIT * bytes_to_use );
@@ -323,10 +325,10 @@
     // This simulates running MD5 on an empty message
     md5_computer c;
     c.process_bit( true );
- c.process_bit_copies( false, md5_computer::bits_per_block -
- md5_computer::significant_bits_per_length - 1u );
+ c.process_bit_copies( false, md5_computer::bits_per_block::value -
+ md5_computer::significant_bits_per_length::value - 1u );
     c.process_double_word( 0ull );
- BOOST_CHECK_EQUAL( c.bits_read(), md5_computer::bits_per_block );
+ BOOST_CHECK_EQUAL( c.bits_read(), md5_computer::bits_per_block::value );
     BOOST_CHECK_EQUAL( c.bits_unbuffered(), 0u );
 
     md5_computer::buffer_type const b = c.last_buffer();
@@ -344,13 +346,13 @@
 
     // Make some non-default, something like an empty MD5
     c3.process_bit( true );
- c3.process_bit_copies( false, md5_computer::bits_per_block -
- md5_computer::significant_bits_per_length - 1u );
+ c3.process_bit_copies( false, md5_computer::bits_per_block::value -
+ md5_computer::significant_bits_per_length::value - 1u );
     c3.process_double_word( 0ull );
 
     c4.process_bit( true );
- c4.process_bit_copies( false, md5_computer::bits_per_block -
- md5_computer::significant_bits_per_length - 1u );
+ c4.process_bit_copies( false, md5_computer::bits_per_block::value -
+ md5_computer::significant_bits_per_length::value - 1u );
     c4.process_double_word( 0ull );
 
     // Compare
@@ -365,8 +367,8 @@
 
     // Make the only difference at the hash level
     c2.process_bit( true );
- c2.process_bit_copies( false, md5_computer::bits_per_block -
- md5_computer::significant_bits_per_length - 1u );
+ c2.process_bit_copies( false, md5_computer::bits_per_block::value -
+ md5_computer::significant_bits_per_length::value - 1u );
     c2.process_double_word( 1ull ); // one bit differs
     BOOST_REQUIRE_EQUAL( c2.bits_read(), c3.bits_read() );
     BOOST_REQUIRE_EQUAL( c2.bits_unbuffered(), 0u );
@@ -388,8 +390,8 @@
     bit_queue scratch;
 
     c1.process_bit( true );
- c1.process_bit_copies( false, md5_computer::bits_per_block -
- md5_computer::significant_bits_per_length - 1u );
+ c1.process_bit_copies( false, md5_computer::bits_per_block::value -
+ md5_computer::significant_bits_per_length::value - 1u );
     c1.process_double_word( 0ull );
     c1.process_bit( false ); // one extra after buffer hash
     BOOST_CHECK( c1.bits_read() != c1.bits_unbuffered() );
@@ -446,8 +448,8 @@
     // Non-empty message below the limit of padding wrap-around
     c1.process_octet( 0x61u ); // 'a' in ASCII
     BOOST_REQUIRE( c1.bits_unbuffered() > 0u );
- BOOST_REQUIRE( c1.bits_unbuffered() < md5_computer::bits_per_block -
- md5_computer::significant_bits_per_length );
+ BOOST_REQUIRE_LT( c1.bits_unbuffered(), md5_computer::bits_per_block::value
+ - md5_computer::significant_bits_per_length::value );
     BOOST_CHECK_EQUAL( c1.checksum(),
      lexical_cast<md5_digest>("0cc175b9c0f1b6a831c399e269772661") );
 
@@ -458,8 +460,8 @@
     for ( unsigned i = 48 ; i <= 57 ; ++i ) c1.process_octet( i );
         // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" in
         // ASCII
- BOOST_REQUIRE( c1.bits_unbuffered() > md5_computer::bits_per_block -
- md5_computer::significant_bits_per_length );
+ BOOST_REQUIRE_GT( c1.bits_unbuffered(), md5_computer::bits_per_block::value
+ - md5_computer::significant_bits_per_length::value );
     BOOST_CHECK_EQUAL( c1.checksum(),
      lexical_cast<md5_digest>("d174ab98d277d9f5a5611c2c9f419d9f") );
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk