diff --git a/Builds/VisualStudio2012/beast.vcxproj b/Builds/VisualStudio2012/beast.vcxproj
index 0664d04e9..137ce781a 100644
--- a/Builds/VisualStudio2012/beast.vcxproj
+++ b/Builds/VisualStudio2012/beast.vcxproj
@@ -912,6 +912,12 @@
true
+
+ true
+ true
+ true
+ true
+
diff --git a/Builds/VisualStudio2012/beast.vcxproj.filters b/Builds/VisualStudio2012/beast.vcxproj.filters
index 9d1862dde..cc8c9fba4 100644
--- a/Builds/VisualStudio2012/beast.vcxproj.filters
+++ b/Builds/VisualStudio2012/beast.vcxproj.filters
@@ -964,6 +964,9 @@
beast_crypto
+
+ beast_crypto\math
+
diff --git a/modules/beast_core/diagnostic/beast_SafeBool.h b/modules/beast_core/diagnostic/beast_SafeBool.h
index be592299b..0c12a3ceb 100644
--- a/modules/beast_core/diagnostic/beast_SafeBool.h
+++ b/modules/beast_core/diagnostic/beast_SafeBool.h
@@ -20,26 +20,22 @@
#ifndef BEAST_SAFEBOOL_BEASTHEADER
#define BEAST_SAFEBOOL_BEASTHEADER
-/**
- Safe evaluation of class as `bool`.
+/** Safe evaluation of class as `bool`.
- This allows a class to be safely evaluated as a bool without the usual harmful
- side effects of the straightforward operator conversion approach. To use it,
- derive your class from SafeBool and implement `asBoolean()` as:
+ This allows a class to be safely evaluated as a bool without the usual
+ harmful side effects of the straightforward operator conversion approach.
+ To use it, derive your class from SafeBool and implement `asBoolean()` as:
- @code
+ @code
- bool asBoolean () const;
+ bool asBoolean () const;
- @endcode
+ @endcode
- Ideas from http://www.artima.com/cppsource/safebool.html
+ Ideas from http://www.artima.com/cppsource/safebool.html
- @class SafeBool
-
- @ingroup beast_core
+ @class SafeBool
*/
-
class BEAST_API SafeBoolBase
{
private:
diff --git a/modules/beast_crypto/beast_crypto.cpp b/modules/beast_crypto/beast_crypto.cpp
index da4c6d135..a2408a38e 100644
--- a/modules/beast_crypto/beast_crypto.cpp
+++ b/modules/beast_crypto/beast_crypto.cpp
@@ -24,4 +24,6 @@
namespace beast
{
+#include "math/beast_UnsignedInteger.cpp"
+
}
diff --git a/modules/beast_crypto/beast_crypto.h b/modules/beast_crypto/beast_crypto.h
index e5bd96e63..af560a335 100644
--- a/modules/beast_crypto/beast_crypto.h
+++ b/modules/beast_crypto/beast_crypto.h
@@ -37,6 +37,8 @@
# endif
#endif
+#include "../beast_core/beast_core.h"
+
//------------------------------------------------------------------------------
namespace beast
diff --git a/modules/beast_crypto/math/beast_UnsignedInteger.cpp b/modules/beast_crypto/math/beast_UnsignedInteger.cpp
new file mode 100644
index 000000000..cb46c3879
--- /dev/null
+++ b/modules/beast_crypto/math/beast_UnsignedInteger.cpp
@@ -0,0 +1,88 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+class UnsignedIntegerTests : public UnitTestType
+{
+public:
+ UnsignedIntegerTests ()
+ : UnitTestType ("UnsignedInteger")
+ {
+ }
+
+ template
+ void runTest ()
+ {
+ String s;
+
+ s << "UnsignedInteger <" << String(Bytes) << ">";
+
+ beginTest (s);
+
+ UnsignedInteger zero;
+ zero.fill (0);
+ expect (zero.isZero (), "should be zero");
+ expect (! zero.isNotZero (), "sould not be non-zero");
+
+ UnsignedInteger one;
+ one.clear ();
+ one [Bytes - 1] = 1;
+ expect (one == UnsignedInteger ::createFromInteger (1U), "should be equal");
+
+ expect (! one.isZero (), "should not be zero");
+ expect (one.isNotZero (), "sould be non-zero");
+
+ expect (zero < one, "should be less");
+ expect (one > zero, "should be greater");
+ expect (zero >= zero, "should be less than or equal");
+ expect (one <= one, "should be less than or equal");
+
+ expect (zero == zero, "should be equal");
+ expect (zero != one, "should not be equal");
+
+ expect ((zero | zero) == zero, "should be zero");
+ expect ((zero | one) != zero, "should not be zero");
+ expect ((one | one) != zero, "should not be zero");
+
+ expect ((one & zero) == zero, "should be zero");
+ expect ((one & one) == one, "should be one");
+ expect ((zero & zero) == zero, "should be zero");
+
+ expect (zero == UnsignedInteger ::createFromInteger (0U), "should be zero");
+ expect (one == UnsignedInteger ::createFromInteger (1U), "should be one");
+ expect (one != UnsignedInteger ::createFromInteger (2U), "should not be two");
+
+ UnsignedInteger largest = UnsignedInteger ::createFilled (0xff);
+
+ expect (largest > zero && largest > one, "should be greater");
+ expect (~largest == zero, "should be zero");
+ expect (~one < largest, "should be less");
+ }
+
+ void runTest()
+ {
+ runTest <16> ();
+ runTest <33> ();
+ }
+
+private:
+};
+
+#if BEAST_UNIT_TESTS
+template class UnitTestType ;
+#endif
diff --git a/modules/beast_crypto/math/beast_UnsignedInteger.h b/modules/beast_crypto/math/beast_UnsignedInteger.h
index 0aa0650cd..17558bfda 100644
--- a/modules/beast_crypto/math/beast_UnsignedInteger.h
+++ b/modules/beast_crypto/math/beast_UnsignedInteger.h
@@ -20,10 +20,332 @@
#ifndef BEAST_UNSIGNEDINTEGER_H_INCLUDED
#define BEAST_UNSIGNEDINTEGER_H_INCLUDED
-template
-class UnsignedInteger
+/** Represents a set of bits of fixed size.
+
+ Integer representations are stored as big endian.
+
+ @note The number of bits represented can only be a multiple of 8.
+
+ @tparam Bytes The number of bytes of storage.
+*/
+template
+class UnsignedInteger : public SafeBool >
{
public:
+ enum
+ {
+ /** Constant for determining the number of bytes.
+ */
+ sizeInBytes = Bytes
+ };
+
+ // Standard container compatibility
+ typedef unsigned char* iterator;
+ typedef unsigned char const* const_iterator;
+
+ /** Construct the object.
+
+ The values are uninitialized.
+ */
+ UnsignedInteger () noexcept
+ {
+ }
+
+ /** Copy construction.
+ */
+ UnsignedInteger (UnsignedInteger const& other) noexcept
+ {
+ this->operator= (other);
+ }
+
+ /** Assignment.
+ */
+ UnsignedInteger & operator= (UnsignedInteger const& other) noexcept
+ {
+ memcpy (m_byte, other.m_byte, Bytes);
+ return *this;
+ }
+
+ /** Assignment from an integer type.
+
+ @invariant IntegerType must be an unsigned integer type.
+ */
+ // If you get ambiguous calls to overloaded function errors it
+ // means you're trying to pass a signed integer, which doesn't work here!
+ //
+ template
+ UnsignedInteger & operator= (IntegerType value)
+ {
+ static_bassert (sizeof (Bytes) >= sizeof (IntegerType));
+ clear ();
+ value = ByteOrder::swapIfLittleEndian (value);
+ memcpy (end () - sizeof (value), &value, sizeof (value));
+ return *this;
+ }
+
+ /** Create from an integer type.
+
+ @invariant IntegerType must be an unsigned integer type.
+ */
+ template
+ static UnsignedInteger createFromInteger (IntegerType value)
+ {
+ UnsignedInteger result;
+ result.operator= (value);
+ return result;
+ }
+
+ /** Construct with a filled value.
+ */
+ static UnsignedInteger createFilled (unsigned char value)
+ {
+ UnsignedInteger result;
+ result.fill (value);
+ return result;
+ }
+
+ /** Fill with a particular byte value.
+ */
+ void fill (unsigned char value) noexcept
+ {
+ memset (m_byte, value, Bytes);
+ }
+
+ /** Clear the contents to zero.
+ */
+ void clear () noexcept
+ {
+ fill (0);
+ }
+
+ /** Determine if all bits are zero.
+ */
+ bool isZero () const noexcept
+ {
+ for (int i = 0; i < Bytes; ++i)
+ {
+ if (m_byte [i] != 0)
+ return false;
+ }
+
+ return true;
+ }
+
+ /** Determine if any bit is non-zero.
+ */
+ bool isNotZero () const noexcept
+ {
+ return ! isZero ();
+ }
+
+ /** Support conversion to `bool`.
+
+ @return `true` if any bit is non-zero.
+
+ @see SafeBool
+ */
+ bool asBoolean () const noexcept
+ {
+ return isNonZero ();
+ }
+
+ /** Access a particular byte.
+ */
+ unsigned char& getByte (int byteIndex) noexcept
+ {
+ bassert (byteIndex >= 0 && byteIndex < Bytes);
+
+ return m_byte [byteIndex];
+ }
+
+ /** Access a particular byte as `const`.
+ */
+ unsigned char getByte (int byteIndex) const noexcept
+ {
+ bassert (byteIndex >= 0 && byteIndex < Bytes);
+
+ return m_byte [byteIndex];
+ }
+
+ /** Access a particular byte.
+ */
+ unsigned char& operator[] (int byteIndex) noexcept
+ {
+ return getByte (byteIndex);
+ }
+
+ /** Access a particular byte as `const`.
+ */
+ unsigned char const operator[] (int byteIndex) const noexcept
+ {
+ return getByte (byteIndex);
+ }
+
+ /** Get an iterator to the beginning.
+ */
+ iterator begin () noexcept
+ {
+ return &m_byte [0];
+ }
+
+ /** Get an iterator to the end.
+ */
+ iterator end ()
+ {
+ return &m_byte [Bytes];
+ }
+
+ /** Get a const iterator to the beginning.
+ */
+ const_iterator cbegin () const noexcept
+ {
+ return &m_byte [0];
+ }
+
+ /** Get a const iterator to the end.
+ */
+ const_iterator cend () const noexcept
+ {
+ return &m_byte [Bytes];
+ }
+
+ /** Compare two objects.
+ */
+ int compare (UnsignedInteger const& other) const noexcept
+ {
+ return memcmp (cbegin (), other.cbegin (), Bytes);
+ }
+
+ /** Determine equality.
+ */
+ bool operator== (UnsignedInteger const& other) const noexcept
+ {
+ return compare (other) == 0;
+ }
+
+ /** Determine inequality.
+ */
+ bool operator!= (UnsignedInteger const& other) const noexcept
+ {
+ return compare (other) != 0;
+ }
+
+ /** Ordered comparison.
+ */
+ bool operator< (UnsignedInteger const& other) const noexcept
+ {
+ return compare (other) == -1;
+ }
+
+ /** Ordered comparison.
+ */
+ bool operator<= (UnsignedInteger const& other) const noexcept
+ {
+ return compare (other) != 1;
+ }
+
+ /** Ordered comparison.
+ */
+ bool operator> (UnsignedInteger const& other) const noexcept
+ {
+ return compare (other) == 1;
+ }
+
+ /** Ordered comparison.
+ */
+ bool operator>= (UnsignedInteger const& other) const noexcept
+ {
+ return compare (other) != -1;
+ }
+
+ /** Perform bitwise logical-not.
+ */
+ UnsignedInteger operator~ () const noexcept
+ {
+ UnsignedInteger result;
+
+ for (int i = 0; i < Bytes; ++i)
+ result [i] = ~getByte (i);
+
+ return result;
+ }
+
+ /** Perform bitwise logical-or.
+ */
+ UnsignedInteger & operator|= (UnsignedInteger const& rhs) noexcept
+ {
+ for (int i = 0; i < Bytes; ++i)
+ getByte (i) |= rhs [i];
+
+ return *this;
+ }
+
+ /** Perform bitwise logical-or.
+ */
+ UnsignedInteger operator| (UnsignedInteger const& rhs) const noexcept
+ {
+ UnsignedInteger result;
+
+ for (int i = 0; i < Bytes; ++i)
+ result [i] = getByte (i) | rhs [i];
+
+ return result;
+ }
+
+ /** Perform bitwise logical-and.
+ */
+ UnsignedInteger & operator&= (UnsignedInteger const& rhs) noexcept
+ {
+ for (int i = 0; i < Bytes; ++i)
+ getByte (i) &= rhs [i];
+
+ return *this;
+ }
+
+ /** Perform bitwise logical-and.
+ */
+ UnsignedInteger operator& (UnsignedInteger const& rhs) const noexcept
+ {
+ UnsignedInteger result;
+
+ for (int i = 0; i < Bytes; ++i)
+ result [i] = getByte (i) & rhs [i];
+
+ return result;
+ }
+
+ /** Perform bitwise logical-xor.
+ */
+ UnsignedInteger & operator^= (UnsignedInteger const& rhs) noexcept
+ {
+ for (int i = 0; i < Bytes; ++i)
+ getByte (i) ^= rhs [i];
+
+ return *this;
+ }
+
+ /** Perform bitwise logical-xor.
+ */
+ UnsignedInteger operator^ (UnsignedInteger const& rhs) const noexcept
+ {
+ UnsignedInteger result;
+
+ for (int i = 0; i < Bytes; ++i)
+ result [i] = getByte (i) ^ rhs [i];
+
+ return result;
+ }
+
+ // VFALCO TODO:
+ //
+ // increment, decrement, add, subtract
+ // negate
+ // other stuff that makes sense from base_uint <>
+ // missing stuff that built-in integers do
+ //
+
+private:
+ unsigned char m_byte [Bytes];
};
#endif