Boost logo

Boost-Commit :

From: dwalker07_at_[hidden]
Date: 2008-06-16 18:11:46


Author: dlwalker
Date: 2008-06-16 18:11:45 EDT (Mon, 16 Jun 2008)
New Revision: 46437
URL: http://svn.boost.org/trac/boost/changeset/46437

Log:
Added MD5 library
Added:
   sandbox/md5/
   sandbox/md5/boost/
   sandbox/md5/boost/coding/
   sandbox/md5/boost/coding.hpp (contents, props changed)
   sandbox/md5/boost/coding/md5.hpp (contents, props changed)
   sandbox/md5/boost/coding_fwd.hpp (contents, props changed)
   sandbox/md5/libs/
   sandbox/md5/libs/coding/
   sandbox/md5/libs/coding/doc/
   sandbox/md5/libs/coding/doc/md5.qbk (contents, props changed)
   sandbox/md5/libs/coding/example/
   sandbox/md5/libs/coding/example/md5check.cpp (contents, props changed)
   sandbox/md5/libs/coding/src/
   sandbox/md5/libs/coding/src/md5.cpp (contents, props changed)
   sandbox/md5/libs/coding/test/
   sandbox/md5/libs/coding/test/md5_bugs_test.cpp (contents, props changed)
   sandbox/md5/libs/coding/test/md5_computer_test.cpp (contents, props changed)
   sandbox/md5/libs/coding/test/md5_digest_test.cpp (contents, props changed)

Added: sandbox/md5/boost/coding.hpp
==============================================================================
--- (empty file)
+++ sandbox/md5/boost/coding.hpp 2008-06-16 18:11:45 EDT (Mon, 16 Jun 2008)
@@ -0,0 +1,39 @@
+// Boost coding.hpp header file ---------------------------------------------//
+
+// (C) Copyright Daryle Walker 2008. Distributed under the Boost Software
+// License, Version 1.0. (See the accompanying file LICENSE_1_0.txt or a copy
+// at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+// See <http://www.boost.org/libs/coding> for documentation.
+
+/** \file
+ \brief Group-inclusion of Boost.Coding components
+
+ \#Includes all of the headers of Boost.Coding and promotes the public names
+ to the main Boost namespace.
+ */
+
+#ifndef BOOST_CODING_HPP
+#define BOOST_CODING_HPP
+
+#include <boost/coding_fwd.hpp>
+
+#include <boost/coding/md5.hpp>
+
+
+namespace boost
+{
+
+
+// Namespace promotions ----------------------------------------------------//
+
+// From <boost/coding/md5.hpp>
+using coding::md5_digest;
+using coding::md5_computer;
+using coding::compute_md5;
+
+
+} // namespace boost
+
+
+#endif // BOOST_CODING_HPP

Added: sandbox/md5/boost/coding/md5.hpp
==============================================================================
--- (empty file)
+++ sandbox/md5/boost/coding/md5.hpp 2008-06-16 18:11:45 EDT (Mon, 16 Jun 2008)
@@ -0,0 +1,680 @@
+// Boost md5.hpp header file ------------------------------------------------//
+
+// (C) Copyright Daryle Walker 2008. Distributed under the Boost Software
+// License, Version 1.0. (See the accompanying file LICENSE_1_0.txt or a copy
+// at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+// See <http://www.boost.org/libs/coding> for documentation.
+
+/** \file
+ \brief Declarations of MD5 computation components
+
+ 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.
+ */
+
+#ifndef BOOST_CODING_MD5_HPP
+#define BOOST_CODING_MD5_HPP
+
+#include <boost/coding_fwd.hpp>
+
+#include <boost/array.hpp> // for boost::array
+#include <boost/integer.hpp> // for boost::uint_t
+#include <boost/serialization/access.hpp> // for boost::serialization::access
+#include <boost/typeof/typeof.hpp> // for BOOST_AUTO
+
+#include <algorithm> // for std::equal
+#include <cstddef> // for std::size_t
+#include <cstring> // for std::strlen
+#include <ios> // for std::ios
+#include <istream> // for std::basic_istream
+#include <locale> // for std::use_facet, ctype
+#include <ostream> // for std::basic_ostream
+
+
+namespace boost
+{
+namespace coding
+{
+
+
+// Forward declarations ----------------------------------------------------//
+
+// None right now
+
+
+// MD5 message-digest class declaration ------------------------------------//
+
+/** \brief A class for storing a MD5 message digest.
+
+ This type is as basic as possible, meant to be the return type for MD5
+ hashing operations. It is supposed to mirror the buffer described in RFC
+ 1321, sections 3.3&ndash;3.5. Comparisons are supported for check-summing
+ purposes, but not ordering. Persistence is supported through the standard
+ text stream I/O system.
+
+ \see boost::coding::md5_computer
+ \see boost::coding::compute_md5(void const*,std::size_t)
+ */
+class md5_digest
+{
+public:
+ /** \brief Number of bits for word-sized quantities
+
+ Represents the number of bits per word as given in RFC 1321, section 2.
+ */
+ static int const bits_per_word = 32;
+
+ /** \brief Type of MD register
+
+ Represents the type of each register of the MD buffer.
+ */
+ typedef uint_t<bits_per_word>::least word_type;
+
+ /** \brief Length of MD buffer
+
+ Represents the number of registers in a MD buffer.
+ */
+ static std::size_t const words_per_digest = 4u;
+
+ /** \brief The MD5 message digest checksum
+
+ Represents the checksum from a MD5 hashing, mirroring for format of the
+ MD buffer (see RFC 1321, section 3.3). The zero-index corresponds to
+ the "A" register, up to index 3 representing the "D" register.
+ */
+ word_type hash[ words_per_digest ];
+
+}; // md5_digest
+
+
+// MD5 message-digest computation class declaration ------------------------//
+
+/** \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::compute_md5(void const*,std::size_t)
+ */
+class md5_computer
+{
+ /** \brief A class for submitting bit-oriented data for a MD5 message
+ digest in a function-object interface.
+
+ This class represents objects that are proxy views to their owning MD5
+ computing object. The proxy interface appears as a function object that
+ takes a \c bool value, which passes it on to the owning computer for
+ processing. It should be suitable STL-like algorithms that use such a
+ function object. It supports assignment to work with \c std::for_each
+ and other algorithms that can return a post-use function object.
+
+ \see boost::coding::md5_computer
+ \see boost::coding::md5_computer::byte_applicator
+ \see boost::coding::md5_computer::bits
+ */
+ class bit_applicator
+ {
+ friend class md5_computer;
+ md5_computer *parent_;
+ explicit bit_applicator( md5_computer &p ) : parent_( &p ) {};
+ public:
+ //! Application
+ void operator ()( bool v );
+ //! Copy assignment
+ bit_applicator & operator =( bit_applicator const &c );
+
+ }; // bit_applicator
+
+ /** \brief A class for submitting byte-oriented data for a MD5 message
+ digest in a function-object interface.
+
+ This class represents objects that are proxy views to their owning MD5
+ computing object. The proxy interface appears as a function object that
+ takes an <code>unsigned char</code> value, which passes it on to the
+ owning computer for processing. It should be suitable STL-like
+ algorithms that use such a function object. It supports assignment to
+ work with \c std::for_each and other algorithms that can return a
+ post-use function object.
+
+ \see boost::coding::md5_computer
+ \see boost::coding::md5_computer::bit_applicator
+ \see boost::coding::md5_computer::bytes
+ */
+ class byte_applicator
+ {
+ friend class md5_computer;
+ md5_computer *parent_;
+ explicit byte_applicator( md5_computer &p ) : parent_( &p ) {};
+ public:
+ //! Application
+ void operator ()( unsigned char v );
+ //! Copy assignment
+ byte_applicator & operator =( byte_applicator const &c );
+
+ }; // byte_applicator
+
+public:
+ // Special application interface
+ /** \brief Proxy for bit-oriented application interface
+
+ Accesses an interface where <code>*this</code> can be used as a function
+ object take can take a single \c bool value as input. It cannot be
+ reseated from <code>*this</code>, but assignment to it will copy the
+ other's owner's state to <code>*this</code>, enabling algorithms that
+ return updated function objects to work.
+
+ \see boost::coding::md5_computer::bit_applicator
+ */
+ bit_applicator bits;
+ /** \brief Proxy for byte-oriented application interface
+
+ Accesses an interface where <code>*this</code> can be used as a function
+ object take can take a single <code>unsigned char</code> value as input.
+ It cannot be reseated from <code>*this</code>, but assignment to it will
+ copy the other's owner's state to <code>*this</code>, enabling
+ algorithms that return updated function objects to work.
+
+ \see boost::coding::md5_computer::byte_applicator
+ */
+ byte_applicator bytes;
+
+ // Constants
+ /** \brief Number of bits for length quantities
+
+ 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.
+ */
+ static int const significant_bits_per_length = 2 *
+ md5_digest::bits_per_word;
+
+ // 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 std::size_t 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
+ /** \brief Type of MD buffers
+
+ Represents the intermediate MD buffer, holding the checksum for all
+ prior \e completed hashed blocks. The zero-index corresponds to the "A"
+ register, up to index 3 representing the "D" register.
+ */
+ typedef array<md5_digest::word_type, md5_digest::words_per_digest>
+ buffer_type;
+
+ // Lifetime management (use automatic destructor)
+ //! Default construction
+ md5_computer();
+ //! Copy construction
+ md5_computer( md5_computer const &c );
+
+ /*! \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_computer const &c );
+
+ //! Exchanges state with another object
+ void swap( md5_computer &other );//@}
+
+ /*! \name Inspection */ //@{
+ // Inspectors
+ //! Returns the count of bits read so far
+ length_type bits_read() const;
+ //! Returns the count of bits not hashed into the buffer yet
+ length_type bits_unbuffered() const;
+ //! Returns the checksum buffer of hashed bits
+ buffer_type last_buffer() const;
+
+ //! Copies out the unhashed bits
+ template < typename OutputIterator >
+ OutputIterator copy_unbuffered( OutputIterator o );//@}
+
+ /*! \name Bit-stream reading */ //@{
+ // Input processing
+ //! Enters one bit for hashing
+ void process_bit( bool bit );
+ //! Enters part of a byte for hashing
+ void process_bits( unsigned char bits, size_type bit_count );
+ //! Enters several bits, all of the same value, for hashing
+ void process_bit_copies( bool value, size_type bit_count );
+
+ //! Enters a whole byte for hashing
+ void process_byte( unsigned char byte );
+ //! Enters several bytes, all of the same value, for hashing
+ void process_byte_copies( unsigned char value, size_type byte_count );
+
+ //! Enters a range of bytes in memory for hashing
+ void process_block( void const *bytes_begin, void const *bytes_end );
+ //! Enters a byte buffer in memory for hashing
+ void process_bytes( void const *buffer, size_type byte_count );//@}
+
+ /*! \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_computer & operator =( md5_computer const &c );
+
+ //! Equals
+ bool operator ==( md5_computer const &c ) const;
+ //! Not-equal
+ bool operator !=( md5_computer const &c ) const;
+
+ //! Application
+ value_type operator ()() const;//@}
+
+private:
+ // State maintainence
+ bool test_invariant() const;
+
+ // 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 types & constants
+ typedef uint_fast64_t ilength_type;
+ // replace w/ uint_t<significant_bits_per_length>::fast
+ typedef uint_t<md5_digest::bits_per_word>::fast iword_type;
+ typedef array<iword_type, md5_digest::words_per_digest> ibuffer_type;
+
+ static std::size_t const words_per_block = 16u;
+ // from RFC 1321, section 3.4
+ static std::size_t const bits_per_block = words_per_block *
+ md5_digest::bits_per_word;
+
+ typedef array<bool, bits_per_block> block_type;
+
+ // (Computation) member data
+ ilength_type length_;
+ ibuffer_type buffer_;
+ block_type unbuffered_;
+
+ static ibuffer_type const initial_buffer_;
+
+}; // md5_computer
+
+
+//! \cond
+// Implementation details --------------------------------------------------//
+
+namespace detail
+{
+
+// MD5 message digest constants, especially for I/O
+struct md5_constants
+{
+ // Nybbles and hexadecimal digits
+ static std::size_t const nybbles_per_hexadecimal_digit = 1u;
+ static std::size_t const bits_per_nybble = 4u;
+
+ static std::size_t const number_of_hexadecimal_digits = 16u; // duh!
+
+ static char const hex_digits_lc[ number_of_hexadecimal_digits + 1 ];
+ static char const hex_digits_uc[ number_of_hexadecimal_digits + 1 ];
+
+ // MD words
+ static std::size_t const nybbles_per_word = md5_digest::bits_per_word /
+ bits_per_nybble;
+
+ // MD strings
+ static std::size_t const characters_per_digest = md5_digest::bits_per_word
+ * md5_digest::words_per_digest / ( nybbles_per_hexadecimal_digit *
+ bits_per_nybble );
+
+}; // md5_constants
+
+} // namespace detail
+//! \endcond
+
+
+// MD5 message-digest structure non-member operator function definitions ---//
+
+/** \brief Equals
+
+ Compares MD5 message digests for equivalence. Such digests are equal if all
+ of the corresponding parts of their hashes are equal.
+
+ \param l The left-side operand to be compared.
+ \param r The right-side operand to be compared.
+
+ \retval true \p l and \p r are equivalent.
+ \retval false \p l and \p r are not equivalent.
+
+ \relates boost::coding::md5_digest
+ */
+inline
+bool
+operator ==( md5_digest const &l, md5_digest const &r )
+{
+ return std::equal( l.hash, l.hash + md5_digest::words_per_digest, r.hash );
+}
+
+/** \brief Not-equals
+
+ Compares MD5 message digests for non-equivalence. Such digests are unequal
+ if at least one set of corresponding parts in their hashes are unequal.
+
+ \param l The left-side operand to be compared.
+ \param r The right-side operand to be compared.
+
+ \retval true \p l and \p r are not equivalent.
+ \retval false \p l and \p r are equivalent.
+
+ \see boost::coding::operator==(md5_digest const&,md5_digest const&)
+
+ \relates boost::coding::md5_digest
+ */
+inline
+bool
+operator !=( md5_digest const &l, md5_digest const &r )
+{
+ return !( l == r );
+}
+
+/** \brief Reads a \c md5_digest from an input stream
+
+ Receives a \c md5_digest object from an input stream. The format is as
+ given in RFC 1321, section 3.5, i.e. go from the least-significant octet of
+ the first hash component to the most-significant octet of the last hash
+ component. The format for each octet read is two hexadecimal digits
+ (0&ndash;9 and either a&ndash;f or A&ndash;F), with the digit for the
+ most-significant nybble read first. The letter-case of the higher-order
+ hexadecimal digits does not matter. (Note that exactly 32 characters are
+ read, not counting how \c std::ios_base::skipws for \p i is set.)
+
+ \param i The input stream to perform the reading.
+ \param n The \c md5_digest object to store the read.
+
+ \return \p i
+
+ \see boost::coding::operator<<(std::basic_ostream<Ch,Tr>&,md5_digest const&)
+
+ \relates boost::coding::md5_digest
+ */
+template < typename Ch, class Tr >
+std::basic_istream<Ch, Tr> &
+operator >>( std::basic_istream<Ch, Tr> &i, md5_digest &n )
+{
+ typename std::basic_istream<Ch, Tr>::sentry is( i );
+
+ if ( is )
+ {
+ // Set up
+ BOOST_AUTO( const & f, std::use_facet< std::ctype<Ch> >(i.getloc()) );
+ std::size_t nybble_index = 0u;
+ md5_digest temp = { {0} };
+
+ // Read the exact number of characters
+ for ( std::istreambuf_iterator<Ch, Tr> ii(i), ie ; (ie != ii) &&
+ (nybble_index < detail::md5_constants::characters_per_digest) ; ++ii,
+ ++nybble_index )
+ {
+ // Read a character, which represents one nybble
+ md5_digest::word_type nybble = 0u;
+
+ switch ( f.narrow(*ii, '\0') )
+ {
+ case 'F': case 'f': ++nybble; // FALL THROUGH
+ case 'E': case 'e': ++nybble; // FALL THROUGH
+ case 'D': case 'd': ++nybble; // FALL THROUGH
+ case 'C': case 'c': ++nybble; // FALL THROUGH
+ case 'B': case 'b': ++nybble; // FALL THROUGH
+ case 'A': case 'a': ++nybble; // FALL THROUGH
+ case '9': ++nybble; // FALL THROUGH
+ case '8': ++nybble; // FALL THROUGH
+ case '7': ++nybble; // FALL THROUGH
+ case '6': ++nybble; // FALL THROUGH
+ case '5': ++nybble; // FALL THROUGH
+ case '4': ++nybble; // FALL THROUGH
+ case '3': ++nybble; // FALL THROUGH
+ case '2': ++nybble; // FALL THROUGH
+ case '1': ++nybble; // FALL THROUGH
+ case '0': break;
+ default: goto abort_read;
+ }
+
+ // Place the nybble within its word. (Octets are read lowest to
+ // highest, but the nybbles are read in the reverse order, so swap
+ // the positions of the high and low nybbles when putting them in
+ // the appropriate octet.)
+ temp.hash[ nybble_index / detail::md5_constants::nybbles_per_word ]
+ |= nybble << ( detail::md5_constants::bits_per_nybble * ((
+ nybble_index % detail::md5_constants::nybbles_per_word ) ^ 0x01u)
+ );
+ }
+
+abort_read:
+ // Finish up
+ if ( nybble_index < detail::md5_constants::characters_per_digest )
+ {
+ // Incomplete read
+ i.setstate( std::ios_base::failbit );
+ }
+ else
+ {
+ // Successful read
+ n = temp;
+ }
+ }
+
+ return i;
+}
+
+/** \brief Writes a \c md5_digest to an output stream
+
+ Sends a \c md5_digest object to an output stream. The format is as given
+ in RFC 1321, section 3.5, i.e. go from the least-significant octet of the
+ first hash component to the most-significant octet of the last hash
+ component. The format for each octet written is two hexadecimal digits
+ (0&ndash;9 and either a&ndash;f or A&ndash;F), with the digit for the
+ most-significant nybble written first. The setting of
+ \c std::ios_base::uppercase in \p o affects which characters are used for
+ the higher-order hexadecimal digits. (Note that exactly 32 characters are
+ written, not counting how <code><var>o</var>.width()</code> is set.)
+
+ \param o The output stream to perform the writing.
+ \param n The \c md5_digest object to be written.
+
+ \return \p o
+
+ \see boost::coding::operator>>(std::basic_istream<Ch,Tr>&,md5_digest&)
+
+ \relates boost::coding::md5_digest
+ */
+template < typename Ch, class Tr >
+std::basic_ostream<Ch, Tr> &
+operator <<( std::basic_ostream<Ch, Tr> &o, md5_digest const &n )
+{
+ // The message always has an exact number of characters; plot it out.
+ // (Leave an extra character for the NUL terminator.)
+ char hex_string[ detail::md5_constants::characters_per_digest + 1u ];
+ char * p = hex_string;
+
+ // Each nybble will be printed as a hexadecimal digit.
+ char const (&digits)[ detail::md5_constants::number_of_hexadecimal_digits +
+ 1 ] = ( o.flags() & std::ios_base::uppercase )
+ ? detail::md5_constants::hex_digits_uc
+ : detail::md5_constants::hex_digits_lc;
+
+ // Print each nybble. Since the nybble progression within an octet is the
+ // reverse of the octet and word progressions, stick in a reversal flag
+ // while indexing.
+ for ( std::size_t nybble_index = 0u ; nybble_index <
+ detail::md5_constants::characters_per_digest ; ++nybble_index )
+ {
+ *p++ = digits[ 0x0Fu & (n.hash[ nybble_index /
+ detail::md5_constants::nybbles_per_word ] >> (
+ detail::md5_constants::bits_per_nybble * (( nybble_index %
+ detail::md5_constants::nybbles_per_word ) ^ 0x01u) )) ];
+ }
+ *p = '\0';
+
+ // Print the message, taking stream settings into account
+ return o << hex_string;
+}
+
+
+// MD5 computation special applicator operator definitions -----------------//
+
+/** Calls <code><var>o</var>.process_bit( <var>v</var> )</code>, where
+ \p o is the owning \c md5_computer of <code>*this</code>.
+
+ \param v The bit to process.
+
+ \see boost::coding::md5_computer::process_bit(bool)
+ */
+inline
+void
+md5_computer::bit_applicator::operator ()( bool v )
+{
+ this->parent_->process_bit( v );
+}
+
+/** Calls <code>this-&lt;<var>p</var> = <var>c.p</var></code>, where
+ \p p holds the owning \c md5_computer of a particular proxy.
+
+ \return <code>*this</code>
+
+ \see boost::coding::md5_computer::operator=(md5_computer const&)
+ */
+inline
+md5_computer::bit_applicator &
+md5_computer::bit_applicator::operator =
+(
+ md5_computer::bit_applicator const & c
+)
+{
+ this->parent_ = c.parent_;
+ return *this;
+}
+
+/** Calls <code><var>o</var>.process_byte( <var>v</var> )</code>, where
+ \p o is the owning \c md5_computer of <code>*this</code>.
+
+ \param v The byte to process.
+
+ \see boost::coding::md5_computer::process_byte(unsigned char)
+ */
+inline
+void
+md5_computer::byte_applicator::operator ()( unsigned char v )
+{
+ this->parent_->process_byte( v );
+}
+
+/** Calls <code>this-&lt;<var>p</var> = <var>c.p</var></code>, where
+ \p p holds the owning \c md5_computer of a particular proxy.
+
+ \return <code>*this</code>
+
+ \see boost::coding::md5_computer::operator=(md5_computer const&)
+ */
+inline
+md5_computer::byte_applicator &
+md5_computer::byte_applicator::operator =
+(
+ md5_computer::byte_applicator const & c
+)
+{
+ this->parent_ = c.parent_;
+ return *this;
+}
+
+
+// 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
+
+ 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.
+ */
+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();
+}
+
+
+} // namespace coding
+} // namespace boost
+
+
+#endif // BOOST_CODING_MD5_HPP

Added: sandbox/md5/boost/coding_fwd.hpp
==============================================================================
--- (empty file)
+++ sandbox/md5/boost/coding_fwd.hpp 2008-06-16 18:11:45 EDT (Mon, 16 Jun 2008)
@@ -0,0 +1,45 @@
+// Boost coding_fwd.hpp header file -----------------------------------------//
+
+// (C) Copyright Daryle Walker 2008. Distributed under the Boost Software
+// License, Version 1.0. (See the accompanying file LICENSE_1_0.txt or a copy
+// at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+// See <http://www.boost.org/libs/coding> for documentation.
+
+/** \file
+ \brief Forward declarations of Boost.Coding components
+
+ Contains the forward declarations of Boost.Coding's public structures,
+ classes, and templates thereof, and any type aliases.
+ */
+
+#ifndef BOOST_CODING_FWD_HPP
+#define BOOST_CODING_FWD_HPP
+
+
+namespace boost
+{
+/** \brief Name-space for Boost.Coding
+
+ Primary name-space for the public components of a library providing methods
+ of summarizing blocks of data, i.e. messages, as (relatively) compact values
+ to use for cryptography and data integrity.
+ */
+namespace coding
+{
+
+
+// From <boost/coding/md5.hpp> ---------------------------------------------//
+
+class md5_digest;
+
+class md5_computer;
+
+// Also has a free function
+
+
+} // namespace coding
+} // namespace boost
+
+
+#endif // BOOST_CODING_FWD_HPP

Added: sandbox/md5/libs/coding/doc/md5.qbk
==============================================================================

Added: sandbox/md5/libs/coding/example/md5check.cpp
==============================================================================
--- (empty file)
+++ sandbox/md5/libs/coding/example/md5check.cpp 2008-06-16 18:11:45 EDT (Mon, 16 Jun 2008)
@@ -0,0 +1,110 @@
+// Boost MD5 example program file -------------------------------------------//
+
+// (C) Copyright 2008 Daryle Walker. Distributed under the Boost Software
+// License, Version 1.0. (See the accompanying file LICENSE_1_0.txt or a copy
+// at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+// See <http://www.boost.org/libs/coding> for the library's home page.
+
+#include <boost/coding/md5.hpp> // for boost::coding::md5_computer
+
+#include <boost/lexical_cast.hpp> // for boost::lexical_cast, bad_lexical_cast
+
+#include <algorithm> // for std::for_each
+#include <exception> // for std::exception
+#include <iostream> // for std::cerr, cout, cin
+#include <iterator> // for std::istream_iterator
+#include <ostream> // for std::endl
+
+
+// Error return codes
+enum
+{
+ bad_argument_format = -3,
+ bad_argument_count = -2,
+ process_error = -1,
+ program_ok = 0,
+ bad_checksum = +1
+};
+
+// Using declarations
+using std::cerr;
+using std::endl;
+
+
+// Main program
+int
+main
+(
+ int argc,
+ char * argv[]
+)
+try
+{
+ using boost::coding::md5_result;
+ using std::cout;
+
+ typedef std::istream_iterator<unsigned char> byte_read_iterator;
+
+ // Perform a MD5 checksum over the bytes read from standard input.
+ // (TODO: put code to force std::cin into binary mode)
+ boost::coding::md5_computer checksummer;
+
+ checksummer.bytes = std::for_each( byte_read_iterator(std::cin),
+ byte_read_iterator(), checksummer.bytes );
+
+ md5_result const fingerprint = checksummer();
+
+ // Use the results based on the program's mode
+ switch ( argc )
+ {
+ case 1:
+ // No extra arguments -> act as Un*x-like filter, converting bytes from
+ // input to message digest text sent to output
+ cout << fingerprint << endl;
+ return program_ok;
+ case 2:
+ // One extra argument -> match the input bytes' checksum to the given
+ // argument
+ try
+ {
+ md5_result const expected = boost::lexical_cast<md5_result>(
+ argv[1] );
+
+ if ( fingerprint == expected )
+ {
+ cout << "The checksums matched (as '" << fingerprint << "')." <<
+ endl;
+ return program_ok;
+ }
+ else
+ {
+ cout << "The checksums did not match (wanted: '" << argv[ 1 ] <<
+ "', got: '" << fingerprint << "')." << endl;
+ return bad_checksum;
+ }
+ }
+ catch ( boost::bad_lexical_cast &e )
+ {
+ cerr << "The given checksum ('" << argv[ 1 ] <<
+ "') was not in the md5 format, giving error '" << e.what() << "'."
+ << endl;
+ return bad_argument_format;
+ }
+ default:
+ // No other argument combinations allowed
+ cerr << "Improper number of arguments (0 or 1, not " << (argc - 1) <<
+ ")." << endl;
+ return bad_argument_count;
+ }
+}
+catch ( std::exception &e )
+{
+ cerr << "Found an exception with '" << e.what() << "'." << endl;
+ return process_error;
+}
+catch ( ... )
+{
+ cerr << "Found an unknown exception." << endl;
+ return process_error;
+}

Added: sandbox/md5/libs/coding/src/md5.cpp
==============================================================================
--- (empty file)
+++ sandbox/md5/libs/coding/src/md5.cpp 2008-06-16 18:11:45 EDT (Mon, 16 Jun 2008)
@@ -0,0 +1,72 @@
+// Boost md5.cpp implementation file ----------------------------------------//
+
+// (C) Copyright Daryle Walker 2008. Distributed under the Boost Software
+// License, Version 1.0. (See the accompanying file LICENSE_1_0.txt or a copy
+// at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+// See <http://www.boost.org/libs/coding> for documentation.
+
+/** \file
+ \brief Definitions of MD5 computation components
+
+ 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.
+ */
+
+#include <boost/coding/md5.hpp>
+
+#include <cstddef> // for std::size_t
+
+
+namespace boost
+{
+namespace coding
+{
+
+
+// MD5 message-digest class-static member definitions ----------------------//
+
+int const md5_digest::bits_per_word;
+std::size_t const md5_digest::words_per_digest;
+
+
+// Implementation detail object definitions --------------------------------//
+
+namespace detail
+{
+
+// Nybbles and hexadecimal digits
+std::size_t const md5_constants::nybbles_per_hexadecimal_digit;
+std::size_t const md5_constants::bits_per_nybble;
+
+std::size_t const md5_constants::number_of_hexadecimal_digits;
+
+char const md5_constants::hex_digits_lc[] = "0123456789abcdef";
+char const md5_constants::hex_digits_uc[] = "0123456789ABCDEF";
+
+// MD words
+std::size_t const md5_constants::nybbles_per_word;
+
+// MD strings
+std::size_t const md5_constants::characters_per_digest;
+
+} // namespace detail
+
+
+// MD5 message-digest computer class-static member definitions -------------//
+
+int const md5_computer::significant_bits_per_length;
+
+std::size_t const md5_computer::words_per_block;
+std::size_t const md5_computer::bits_per_block;
+
+// Initial values of the MD buffer, taken from RFC 1321, section 3.3. (Note
+// that the RFC lists each number low-order byte first, while numbers need to be
+// written high-order byte first in C++.)
+md5_computer::ibuffer_type const md5_computer::initial_buffer_ = {
+ {0x67452301ul, 0xEFCDAB89ul, 0x98BACDFEul, 0x10325476ul} };
+
+
+} // namespace coding
+} // namespace boost

Added: sandbox/md5/libs/coding/test/md5_bugs_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/md5/libs/coding/test/md5_bugs_test.cpp 2008-06-16 18:11:45 EDT (Mon, 16 Jun 2008)
@@ -0,0 +1,37 @@
+// Boost md5_bugs_test.cpp test file ----------------------------------------//
+
+// (C) Copyright 2008 Daryle Walker. Distributed under the Boost Software
+// License, Version 1.0. (See the accompanying file LICENSE_1_0.txt or a copy
+// at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+// See <http://www.boost.org/libs/coding> for the library's home page.
+
+
+#include <boost/coding/md5.hpp>
+
+#include <boost/test/unit_test.hpp> // unit testing framework
+
+
+#pragma mark Intro stuff
+
+// Put any using-ed types & templates, and typedefs here
+
+
+// Put custom types/templates and helper functions here
+namespace
+{
+} // unnamed namespace
+
+
+// Mark any unprintable tested types here
+
+
+#pragma mark -
+#pragma mark MD5 Bug Testing Suite
+
+// Confirmation tests of bugs in Boost.Coding.MD5 and their fixes
+BOOST_AUTO_TEST_SUITE( md5_bug_suite )
+
+// Hopefully, this will stay empty
+
+BOOST_AUTO_TEST_SUITE_END()

Added: sandbox/md5/libs/coding/test/md5_computer_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/md5/libs/coding/test/md5_computer_test.cpp 2008-06-16 18:11:45 EDT (Mon, 16 Jun 2008)
@@ -0,0 +1,75 @@
+// Boost md5_computer_test.cpp test file ------------------------------------//
+
+// (C) Copyright 2008 Daryle Walker. Distributed under the Boost Software
+// License, Version 1.0. (See the accompanying file LICENSE_1_0.txt or a copy
+// at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+// See <http://www.boost.org/libs/coding> for the library's home page.
+
+
+#include <boost/coding/md5.hpp>
+
+#include <boost/test/unit_test.hpp> // unit testing framework
+
+
+#pragma mark Intro stuff
+
+// Put any using-ed types & templates, and typedefs here
+
+
+// Put custom types/templates and helper functions here
+namespace
+{
+} // unnamed namespace
+
+
+// Mark any unprintable tested types here
+
+
+#pragma mark -
+#pragma mark MD5 Digest Computer Suite
+
+// Test the operations of the MD5 computation class and function
+BOOST_AUTO_TEST_SUITE( md5_computer_suite )
+
+// Construction and inspector test
+BOOST_AUTO_TEST_CASE( md5_computer_constructor_status_test )
+{
+}
+
+// Equality operators test
+BOOST_AUTO_TEST_CASE( md5_computer_equality_test )
+{
+}
+
+// Output archiving test
+BOOST_AUTO_TEST_CASE( md5_computer_output_test )
+{
+}
+
+// Input archiving test
+BOOST_AUTO_TEST_CASE( md5_computer_input_test )
+{
+}
+
+// Bit-wise computation test
+BOOST_AUTO_TEST_CASE( md5_computer_bit_input_test )
+{
+}
+
+// Byte-wise computation test
+BOOST_AUTO_TEST_CASE( md5_computer_byte_input_test )
+{
+}
+
+// Checksum computation test
+BOOST_AUTO_TEST_CASE( md5_computer_checksum_test )
+{
+}
+
+// Single-call function test
+BOOST_AUTO_TEST_CASE( compute_md5_test )
+{
+}
+
+BOOST_AUTO_TEST_SUITE_END()

Added: sandbox/md5/libs/coding/test/md5_digest_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/md5/libs/coding/test/md5_digest_test.cpp 2008-06-16 18:11:45 EDT (Mon, 16 Jun 2008)
@@ -0,0 +1,249 @@
+// Boost md5_digest_test.cpp test file --------------------------------------//
+
+// (C) Copyright 2008 Daryle Walker. Distributed under the Boost Software
+// License, Version 1.0. (See the accompanying file LICENSE_1_0.txt or a copy
+// at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+// See <http://www.boost.org/libs/coding> for the library's home page.
+
+
+#define BOOST_TEST_MODULE "MD5 tests"
+
+#include <boost/coding/md5.hpp>
+
+#include <boost/lexical_cast.hpp> // for boost::lexical_cast
+#include <boost/test/unit_test.hpp> // unit testing framework
+
+#include <cstddef> // for std::size_t
+#include <cstdio> // for EOF
+#include <cwchar> // for WEOF, std::wint_t
+#include <iomanip> // for std::setfill, setw
+#include <ios> // for std::left, uppercase
+#include <sstream> // for std::[w](o|i)stringstream
+#include <string> // for std::string, wstring
+
+
+#pragma mark Intro stuff
+
+// Put any using-ed types & templates, and typedefs here
+using boost::coding::md5_digest;
+
+
+// Put custom types/templates, helper functions, and objects here
+namespace
+{
+
+// Sample MD5 message digest values
+md5_digest const md5_initial = { {0x67452301ul, 0xEFCDAB89ul, 0x98BADCFEul,
+ 0x10325476ul} }; // from RFC 1321, section 3.3
+md5_digest const zeros = { {0u, 0u, 0u, 0u} }; // all zeros (duh!)
+
+// Common string representations of the above values, based on RFC 1321,
+// section 3.5
+char const md5_initial_s[] = "0123456789abcdeffedcba9876543210";
+wchar_t const md5_initial_ws[] = L"0123456789abcdeffedcba9876543210";
+char const md5_initial_us[] = "0123456789ABCDEFFEDCBA9876543210";
+wchar_t const md5_initial_uws[] = L"0123456789ABCDEFFEDCBA9876543210";
+
+char const zeros_s[] = "00000000000000000000000000000000";
+wchar_t const zeros_ws[] = L"00000000000000000000000000000000";
+
+} // unnamed namespace
+
+
+// Mark any unprintable tested types here
+
+
+#pragma mark -
+#pragma mark MD5 Digest Result Suite
+
+// Test the operations of the MD5 result structure
+BOOST_AUTO_TEST_SUITE( md5_digest_suite )
+
+// Equality operators test
+BOOST_AUTO_TEST_CASE( md5_digest_equality_test )
+{
+ // Equality operator
+ md5_digest const initial_copy = md5_initial;
+
+ BOOST_CHECK_EQUAL( md5_initial.hash[0], initial_copy.hash[0] );
+ BOOST_CHECK_EQUAL( md5_initial.hash[1], initial_copy.hash[1] );
+ BOOST_CHECK_EQUAL( md5_initial.hash[2], initial_copy.hash[2] );
+ BOOST_CHECK_EQUAL( md5_initial.hash[3], initial_copy.hash[3] );
+ BOOST_CHECK( md5_initial == initial_copy );
+
+ // Inequality operator
+ md5_digest const just_one = { {1u, 0u, 0u, 0u} };
+
+ BOOST_CHECK( just_one.hash[0] != zeros.hash[0] );
+ BOOST_CHECK_EQUAL( just_one.hash[1], zeros.hash[1] );
+ BOOST_CHECK_EQUAL( just_one.hash[2], zeros.hash[2] );
+ BOOST_CHECK_EQUAL( just_one.hash[3], zeros.hash[3] );
+ BOOST_CHECK( just_one != zeros );
+
+ // Cross- and self-checks
+ BOOST_CHECK( zeros != md5_initial );
+ BOOST_CHECK( md5_initial == md5_initial );
+}
+
+// Output streaming test
+BOOST_AUTO_TEST_CASE( md5_digest_output_test )
+{
+ using boost::lexical_cast;
+ using std::string;
+ using std::wstring;
+ using std::setfill;
+ using std::setw;
+ using boost::coding::detail::md5_constants;
+ using std::left;
+ using std::uppercase;
+
+ // Basics, using Boost.LexicalCast
+ BOOST_CHECK_EQUAL( lexical_cast<string>(md5_initial), md5_initial_s );
+ BOOST_CHECK_EQUAL( lexical_cast<string>(zeros), zeros_s );
+
+ // Use character types besides "char"
+ BOOST_CHECK( lexical_cast<wstring>(md5_initial) == md5_initial_ws );
+ BOOST_CHECK( lexical_cast<wstring>(zeros) == zeros_ws );
+
+ // Use format options
+ {
+ std::ostringstream oss;
+
+ // Check generic options
+ oss << setfill( '*' ) << setw( md5_constants::characters_per_digest + 2
+ ) << left << md5_initial;
+ BOOST_CHECK_EQUAL( oss.str(), string(md5_initial_s) + "**" );
+
+ // Check upper-case flag
+ oss.str( "" );
+ oss << uppercase << md5_initial;
+ BOOST_CHECK_EQUAL( oss.str(), md5_initial_us );
+
+ // Redo for the all-zeros value
+ oss.str( "" );
+ oss << setfill( '*' ) << setw( md5_constants::characters_per_digest + 2
+ ) << left << zeros;
+ BOOST_CHECK_EQUAL( oss.str(), string(zeros_s) + "**" );
+
+ oss.str( "" );
+ oss << uppercase << zeros;
+ BOOST_CHECK_EQUAL( oss.str(), zeros_s );
+ }
+
+ // Use format options on non-"char"
+ {
+ std::wostringstream woss;
+
+ // Check generic options
+ woss << setfill( L'*' ) << setw( md5_constants::characters_per_digest +
+ 2 ) << left << md5_initial;
+ BOOST_CHECK( woss.str() == (wstring( md5_initial_ws ) + L"**") );
+
+ // Check upper-case flag
+ woss.str( L"" );
+ woss << uppercase << md5_initial;
+ BOOST_CHECK( woss.str() == md5_initial_uws );
+
+ // Redo for the all-zeros value
+ woss.str( L"" );
+ woss << setfill( L'*' ) << setw( md5_constants::characters_per_digest +
+ 2 ) << left << zeros;
+ BOOST_CHECK( woss.str() == (wstring( zeros_ws ) + L"**") );
+
+ woss.str( L"" );
+ woss << uppercase << zeros;
+ BOOST_CHECK( woss.str() == zeros_ws );
+ }
+}
+
+// Input streaming test
+BOOST_AUTO_TEST_CASE( md5_digest_input_test )
+{
+ using boost::lexical_cast;
+ using std::string;
+
+ // Basics, using Boost.LexicalCast
+ BOOST_CHECK_EQUAL( lexical_cast<md5_digest>(md5_initial_s), md5_initial );
+ BOOST_CHECK_EQUAL( lexical_cast<md5_digest>(md5_initial_us), md5_initial );
+ BOOST_CHECK_EQUAL( lexical_cast<md5_digest>(zeros_s), zeros );
+
+ // Use character types besides "char"
+ BOOST_CHECK( lexical_cast<md5_digest>(md5_initial_ws) == md5_initial );
+ BOOST_CHECK( lexical_cast<md5_digest>(md5_initial_uws) == md5_initial );
+ BOOST_CHECK( lexical_cast<md5_digest>(zeros_ws) == zeros );
+
+ // Check mixed letter-case
+ BOOST_CHECK_EQUAL( lexical_cast<md5_digest>(
+ "0123456789AbCdEfFeDcBa9876543210"), md5_initial );
+ BOOST_CHECK( lexical_cast<md5_digest>(L"0123456789aBcDeFfEdCbA9876543210")
+ == md5_initial );
+
+ // Check bad formats
+ {
+ // Bad characters
+ std::istringstream iss( "21b0_at_qM78C9a" );
+ md5_digest x = md5_initial;
+
+ iss >> x;
+ BOOST_CHECK_EQUAL( x, md5_initial );
+ BOOST_CHECK( iss.fail() && !iss.bad() );
+ iss.clear();
+ BOOST_CHECK_EQUAL( iss.peek(), static_cast<int>('@') );
+
+ // Not enough characters
+ iss.str( "31a0F" );
+ iss >> x;
+ BOOST_CHECK_EQUAL( x, md5_initial );
+ BOOST_CHECK( iss.fail() && !iss.bad() );
+ iss.clear();
+ BOOST_CHECK_EQUAL( iss.peek(), EOF );
+ BOOST_CHECK( iss.eof() );
+
+ // Read 2 in a row
+ iss.clear();
+ iss.str( string(zeros_s) + md5_initial_s );
+ iss >> x;
+ BOOST_CHECK_EQUAL( x, zeros );
+ iss >> x;
+ BOOST_CHECK_EQUAL( x, md5_initial );
+ BOOST_CHECK( iss.good() );
+ }
+
+ // Check bad formats on non-"char"
+ {
+ // Bad characters
+ std::wistringstream wiss( L"21b0_at_qM78C9a" );
+ md5_digest y = md5_initial;
+
+ wiss >> y;
+ BOOST_CHECK_EQUAL( y, md5_initial );
+ BOOST_CHECK( wiss.fail() && !wiss.bad() );
+ wiss.clear();
+ BOOST_CHECK_EQUAL( wiss.peek(), static_cast<std::wint_t>(L'@') );
+
+ // Not enough characters
+ wiss.str( L"31a0F" );
+ wiss >> y;
+ BOOST_CHECK_EQUAL( y, md5_initial );
+ BOOST_CHECK( wiss.fail() && !wiss.bad() );
+ wiss.clear();
+ BOOST_CHECK_EQUAL( wiss.peek(), WEOF );
+ BOOST_CHECK( wiss.eof() );
+
+ // Read 2 in a row (in upper-case)
+ wiss.clear();
+ wiss.str( std::wstring(zeros_ws) + md5_initial_uws );
+ wiss >> y;
+ BOOST_CHECK_EQUAL( y, zeros );
+ wiss >> y;
+ BOOST_CHECK_EQUAL( y, md5_initial );
+ BOOST_CHECK( wiss.good() );
+ }
+
+ // Matching input vs. output
+ BOOST_CHECK_EQUAL( md5_initial,
+ lexical_cast<md5_digest>(lexical_cast<string>( md5_initial )) );
+}
+
+BOOST_AUTO_TEST_SUITE_END()


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