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