Add UnsignedInteger class and tests

This commit is contained in:
Vinnie Falco
2013-07-13 09:32:24 -07:00
parent e1ca9e35b5
commit 6d1a76b320
11 changed files with 479 additions and 17 deletions

View File

@@ -912,6 +912,12 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\modules\beast_crypto\beast_crypto.cpp" />
<ClCompile Include="..\..\modules\beast_crypto\math\beast_UnsignedInteger.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="..\..\TODO.txt" />

View File

@@ -964,6 +964,9 @@
<ClCompile Include="..\..\modules\beast_crypto\beast_crypto.cpp">
<Filter>beast_crypto</Filter>
</ClCompile>
<ClCompile Include="..\..\modules\beast_crypto\math\beast_UnsignedInteger.cpp">
<Filter>beast_crypto\math</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="..\..\TODO.txt" />

View File

@@ -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:

View File

@@ -24,4 +24,6 @@
namespace beast
{
#include "math/beast_UnsignedInteger.cpp"
}

View File

@@ -37,6 +37,8 @@
# endif
#endif
#include "../beast_core/beast_core.h"
//------------------------------------------------------------------------------
namespace beast

View File

@@ -0,0 +1,88 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
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 <UnsignedIntegerTests>
{
public:
UnsignedIntegerTests ()
: UnitTestType <UnsignedIntegerTests> ("UnsignedInteger")
{
}
template <unsigned int Bytes>
void runTest ()
{
String s;
s << "UnsignedInteger <" << String(Bytes) << ">";
beginTest (s);
UnsignedInteger <Bytes> zero;
zero.fill (0);
expect (zero.isZero (), "should be zero");
expect (! zero.isNotZero (), "sould not be non-zero");
UnsignedInteger <Bytes> one;
one.clear ();
one [Bytes - 1] = 1;
expect (one == UnsignedInteger <Bytes>::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 <Bytes>::createFromInteger (0U), "should be zero");
expect (one == UnsignedInteger <Bytes>::createFromInteger (1U), "should be one");
expect (one != UnsignedInteger <Bytes>::createFromInteger (2U), "should not be two");
UnsignedInteger <Bytes> largest = UnsignedInteger <Bytes>::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 <UnsignedIntegerTests>;
#endif

View File

@@ -20,10 +20,332 @@
#ifndef BEAST_UNSIGNEDINTEGER_H_INCLUDED
#define BEAST_UNSIGNEDINTEGER_H_INCLUDED
template <int Bytes>
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 <unsigned int Bytes>
class UnsignedInteger : public SafeBool <UnsignedInteger <Bytes> >
{
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 <Bytes> const& other) noexcept
{
this->operator= (other);
}
/** Assignment.
*/
UnsignedInteger <Bytes>& 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 <class IntegerType>
UnsignedInteger <Bytes>& 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 <class IntegerType>
static UnsignedInteger <Bytes> createFromInteger (IntegerType value)
{
UnsignedInteger <Bytes> result;
result.operator= (value);
return result;
}
/** Construct with a filled value.
*/
static UnsignedInteger <Bytes> createFilled (unsigned char value)
{
UnsignedInteger <Bytes> 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 <Bytes> const& other) const noexcept
{
return memcmp (cbegin (), other.cbegin (), Bytes);
}
/** Determine equality.
*/
bool operator== (UnsignedInteger <Bytes> const& other) const noexcept
{
return compare (other) == 0;
}
/** Determine inequality.
*/
bool operator!= (UnsignedInteger <Bytes> const& other) const noexcept
{
return compare (other) != 0;
}
/** Ordered comparison.
*/
bool operator< (UnsignedInteger <Bytes> const& other) const noexcept
{
return compare (other) == -1;
}
/** Ordered comparison.
*/
bool operator<= (UnsignedInteger <Bytes> const& other) const noexcept
{
return compare (other) != 1;
}
/** Ordered comparison.
*/
bool operator> (UnsignedInteger <Bytes> const& other) const noexcept
{
return compare (other) == 1;
}
/** Ordered comparison.
*/
bool operator>= (UnsignedInteger <Bytes> const& other) const noexcept
{
return compare (other) != -1;
}
/** Perform bitwise logical-not.
*/
UnsignedInteger <Bytes> operator~ () const noexcept
{
UnsignedInteger <Bytes> result;
for (int i = 0; i < Bytes; ++i)
result [i] = ~getByte (i);
return result;
}
/** Perform bitwise logical-or.
*/
UnsignedInteger <Bytes>& operator|= (UnsignedInteger <Bytes> const& rhs) noexcept
{
for (int i = 0; i < Bytes; ++i)
getByte (i) |= rhs [i];
return *this;
}
/** Perform bitwise logical-or.
*/
UnsignedInteger <Bytes> operator| (UnsignedInteger <Bytes> const& rhs) const noexcept
{
UnsignedInteger <Bytes> result;
for (int i = 0; i < Bytes; ++i)
result [i] = getByte (i) | rhs [i];
return result;
}
/** Perform bitwise logical-and.
*/
UnsignedInteger <Bytes>& operator&= (UnsignedInteger <Bytes> const& rhs) noexcept
{
for (int i = 0; i < Bytes; ++i)
getByte (i) &= rhs [i];
return *this;
}
/** Perform bitwise logical-and.
*/
UnsignedInteger <Bytes> operator& (UnsignedInteger <Bytes> const& rhs) const noexcept
{
UnsignedInteger <Bytes> result;
for (int i = 0; i < Bytes; ++i)
result [i] = getByte (i) & rhs [i];
return result;
}
/** Perform bitwise logical-xor.
*/
UnsignedInteger <Bytes>& operator^= (UnsignedInteger <Bytes> const& rhs) noexcept
{
for (int i = 0; i < Bytes; ++i)
getByte (i) ^= rhs [i];
return *this;
}
/** Perform bitwise logical-xor.
*/
UnsignedInteger <Bytes> operator^ (UnsignedInteger <Bytes> const& rhs) const noexcept
{
UnsignedInteger <Bytes> 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

View File

@@ -29,6 +29,8 @@
#include "system/ripple_OpenSSLIncludes.h"
#include "beast/modules/beast_crypto/beast_crypto.h"
//------------------------------------------------------------------------------
// From

View File

@@ -14,7 +14,10 @@
class Validator
{
public:
typedef uint256 PublicKey;
// VFALCO TODO magic number argh!!!
// This type should be located elsewhere.
//
typedef UnsignedInteger <33> PublicKey;
explicit Validator (PublicKey const& publicKey);

View File

@@ -226,15 +226,51 @@ Validators* Validators::New (Listener* listener)
class TestValidatorSource : public Validators::Source
{
public:
static Validator makeValidator (int publicKeyIndex)
static Validator createValidator (unsigned int publicKeyIndex)
{
Validator validator (Validator::PublicKey::createFromInteger (publicKeyIndex));
return validator;
}
TestValidatorSource (unsigned startIndex, int numEntries)
: m_startIndex (startIndex)
, m_numEntries (numEntries)
{
}
ValidatorList::Ptr fetch ()
{
ValidatorList::Ptr list = new ValidatorList;
for (unsigned int publicKeyIndex = m_startIndex;
publicKeyIndex < m_startIndex + m_numEntries;
++publicKeyIndex)
{
list->add (createValidator (publicKeyIndex));
}
return list;
}
private:
unsigned const m_startIndex;
int const m_numEntries;
};
//------------------------------------------------------------------------------
class ValidatorListTests : public UnitTestType <ValidatorListTests>
{
public:
ValidatorListTests () : UnitTestType <ValidatorListTests> ("ValidatorList")
{
}
void runTest ()
{
beginTest ("ValidatorList");
}
};
template class UnitTestType <ValidatorListTests>;

View File

@@ -309,6 +309,8 @@ int rippleMain (int argc, char** argv)
//
if (vm.count ("unittest"))
{
runBeastUnitTests ();
// DEPRECATED
runBoostUnitTests (argc, argv);
return 0;