Changed from generic interface inherited from ihash.

This commit is contained in:
John Wellbelove 2015-09-28 18:44:27 +01:00
parent 31e828b4bb
commit 04a50d2b8a
5 changed files with 52 additions and 305 deletions

View File

@ -34,7 +34,6 @@ SOFTWARE.
#include "static_assert.h"
#include "type_traits.h"
#include "endian.h"
#include "ihash.h"
///\defgroup checksum Checksum calculation
@ -45,11 +44,10 @@ namespace etl
//***************************************************************************
/// Calculates the checksum.
///\tparam TSum The type used for the sum.
///\tparam ENDIANNESS The endianness of the calculation for input types larger than uint8_t. Default = endian::little.
///\ingroup checksum
//***************************************************************************
template <typename TSum, const int ENDIANNESS = endian::little>
class checksum : public etl::ihash
template <typename TSum>
class checksum
{
public:
@ -61,7 +59,6 @@ namespace etl
/// Default constructor.
//*************************************************************************
checksum()
: ihash(etl::endian(ENDIANNESS))
{
reset();
}
@ -73,10 +70,14 @@ namespace etl
//*************************************************************************
template<typename TIterator>
checksum(TIterator begin, const TIterator end)
: ihash(etl::endian(ENDIANNESS))
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
reset();
add(begin, end);
while (begin != end)
{
sum += *begin++;
}
}
//*************************************************************************
@ -95,17 +96,12 @@ namespace etl
template<typename TIterator>
void add(TIterator begin, const TIterator end)
{
ihash::add(begin, end);
}
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
//*************************************************************************
/// Adds a value.
/// \param value The value to add to the checksum.
//*************************************************************************
template<typename TValue>
void add(TValue value)
{
ihash::add(value);
while (begin != end)
{
sum += *begin++;
}
}
//*************************************************************************
@ -132,14 +128,6 @@ namespace etl
return sum;
}
//*************************************************************************
/// Gets the generic digest value.
//*************************************************************************
generic_digest digest()
{
return ihash::get_digest(sum);
}
private:
value_type sum;

131
ihash.h
View File

@ -34,9 +34,8 @@ SOFTWARE.
#include <utility>
#include "exception.h"
#include "endian.h"
///\defgroup ihash Base class for all hash type classes.
///\defgroup ihash Common data for all hash type classes.
///\ingroup hash
namespace etl
@ -69,134 +68,6 @@ namespace etl
/// For the Americans
typedef hash_finalised hash_finalized;
//***************************************************************************
/// Hash algorithm base class.
/// \ingroup ihash
//***************************************************************************
class ihash
{
public:
/// Generic return type.
typedef std::pair<const uint8_t*, const uint8_t*> generic_digest;
//*************************************************************************
/// Default constructor.
/// \param endianness The endianness to use for integral types larger than uint8_t.
//*************************************************************************
ihash(etl::endian endianness)
: endianness(endianness)
{
}
//*************************************************************************
/// \param value The value to add to the hash.
//*************************************************************************
template<typename TValue>
void add(TValue value)
{
uint8_t* p_data = reinterpret_cast<uint8_t*>(&value);
if (endianness == endian::little)
{
for (int i = 0; i < sizeof(TValue); ++i)
{
add(p_data[i]);
}
}
else
{
for (int i = sizeof(TValue) - 1; i >= 0; --i)
{
add(p_data[i]);
}
}
}
//*************************************************************************
/// \param begin Start of the range.
/// \param end End of the range.
//*************************************************************************
template<typename TIterator>
void add(TIterator begin, const TIterator end)
{
while (begin != end)
{
add(*begin);
++begin;
}
}
//*************************************************************************
/// \param value The value to add to the checksum.
//*************************************************************************
template<typename TValue>
ihash& operator +=(TValue value)
{
add(value);
return *this;
}
//*************************************************************************
/// Get the endianness.
//*************************************************************************
etl::endian endian() const
{
return endianness;
}
//*************************************************************************
/// Set the endianness.
//*************************************************************************
void endian(etl::endian e)
{
endianness = e;
}
//*************************************************************************
/// \param value The uint8_t to add to the hash.
//*************************************************************************
virtual void add(uint8_t value) = 0;
//*************************************************************************
/// Resets the hash to the initial state.
//*************************************************************************
virtual void reset() = 0;
//*************************************************************************
/// Gets the result as a generic digest.
//*************************************************************************
virtual generic_digest digest() = 0;
protected:
//*************************************************************************
/// Gets the result as a generic digest.
/// Templated for derived class usage.
//*************************************************************************
template <typename T>
generic_digest get_digest(const T& hash) const
{
const uint8_t* begin = reinterpret_cast<const uint8_t*>(&hash);
return generic_digest(begin, begin + sizeof(hash));
}
private:
etl::endian endianness;
};
}
//*************************************************************************
/// Default streaming operator.
//*************************************************************************
template <typename T>
etl::ihash& operator << (etl::ihash& hash, T value)
{
hash.add(value);
return hash;
}
#endif

View File

@ -57,11 +57,10 @@ namespace etl
//***************************************************************************
/// Calculates a Pearson hash
///\tparam HASH_LENGTH The number of elements in the hash.
///\tparam ENDIANNESS The endianness of the calculation for input types larger than uint8_t. Default = endian::little.
/// \ingroup pearson
//***************************************************************************
template <const size_t HASH_LENGTH, const int ENDIANNESS = endian::little>
class pearson : public etl::ihash
template <const size_t HASH_LENGTH>
class pearson
{
public:
@ -71,8 +70,7 @@ namespace etl
/// Default constructor.
//*************************************************************************
pearson()
: first(true),
ihash(etl::endian(ENDIANNESS))
: first(true)
{
reset();
}
@ -84,9 +82,10 @@ namespace etl
//*************************************************************************
template<typename TIterator>
pearson(TIterator begin, const TIterator end)
: first(true),
ihash(etl::endian(ENDIANNESS))
: first(true)
{
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
reset();
add(begin, end);
}
@ -107,17 +106,12 @@ namespace etl
template<typename TIterator>
void add(TIterator begin, const TIterator end)
{
ihash::add(begin, end);
}
STATIC_ASSERT(sizeof(typename std::iterator_traits<TIterator>::value_type) == 1, "Type not supported");
//*************************************************************************
/// Adds a value.
/// \param value The value to add to the hash.
//*************************************************************************
template<typename TValue>
void add(TValue value)
{
ihash::add(value);
while (begin != end)
{
add(*begin++);
}
}
//*************************************************************************
@ -159,14 +153,6 @@ namespace etl
return value();
}
//*************************************************************************
/// Gets the generic digest value.
//*************************************************************************
generic_digest digest()
{
return generic_digest(etl::begin(hash), etl::end(hash));
}
private:
bool first;

View File

@ -73,82 +73,14 @@ namespace
etl::checksum<uint8_t> checksum_calculator;
for (size_t i = 0; i < data.size(); ++i)
{
checksum_calculator += data[i];
}
uint8_t sum = checksum_calculator;
CHECK_EQUAL(221, int(sum));
}
//*************************************************************************
TEST(test_checksum_add_values8_operator_stream)
{
std::string data("123456789");
etl::checksum<uint8_t> checksum_calculator;
for (size_t i = 0; i < data.size(); ++i)
{
checksum_calculator << data[i];
}
uint8_t sum = checksum_calculator;
CHECK_EQUAL(221, int(sum));
}
//*************************************************************************
TEST(test_checksum_add_values32_add)
{
std::vector<uint32_t> data = { 0x04030201, 0x08070605 };
etl::checksum<uint32_t> checksum_calculator;
for (size_t i = 0; i < data.size(); ++i)
{
checksum_calculator += data[i];
}
uint32_t sum = checksum_calculator;
CHECK_EQUAL(36, int(sum));
}
//*************************************************************************
TEST(test_checksum_add_values32_plus_equals)
{
std::vector<uint32_t> data = { 0x04030201, 0x08070605 };
etl::checksum<uint32_t> checksum_calculator;
for (size_t i = 0; i < data.size(); ++i)
{
checksum_calculator.add(data[i]);
}
uint32_t sum = checksum_calculator;
uint8_t sum = checksum_calculator;
CHECK_EQUAL(36, int(sum));
}
//*************************************************************************
TEST(test_checksum_add_values32_operator_stream)
{
std::vector<uint32_t> data = { 0x04030201, 0x08070605 };
etl::checksum<uint32_t> checksum_calculator;
for (size_t i = 0; i < data.size(); ++i)
{
checksum_calculator << data[i];
}
uint32_t sum = checksum_calculator;
CHECK_EQUAL(36, int(sum));
CHECK_EQUAL(221, int(sum));
}
//*************************************************************************
@ -165,6 +97,20 @@ namespace
CHECK_EQUAL(221, int(sum));
}
//*************************************************************************
TEST(test_checksum_add_range_sum16)
{
std::string data("123456789");
etl::checksum<uint16_t> checksum_calculator;
checksum_calculator.add(data.begin(), data.end());
uint16_t sum = checksum_calculator.value();
CHECK_EQUAL(477, int(sum));
}
//*************************************************************************
TEST(test_checksum_add_range_sum32)
{
@ -184,58 +130,14 @@ namespace
{
std::vector<uint8_t> data1 = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
std::vector<uint32_t> data2 = { 0x04030201, 0x08070605 };
std::vector<uint32_t> data3 = { 0x01020304, 0x05060708 };
std::vector<uint8_t> data3 = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 };
uint8_t sum1 = etl::checksum<uint8_t, etl::endian::little>(data1.begin(), data1.end());
uint8_t sum2 = etl::checksum<uint8_t, etl::endian::little>(data2.begin(), data2.end());
CHECK_EQUAL(int(sum1), int(sum2));
uint32_t hash1 = etl::checksum<uint32_t>(data1.begin(), data1.end());
uint32_t hash2 = etl::checksum<uint32_t>((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size()));
CHECK_EQUAL(int(hash1), int(hash2));
uint8_t sum3 = etl::checksum<uint8_t, etl::endian::big>(data3.begin(), data3.end());
CHECK_EQUAL(int(sum1), int(sum3));
}
//*************************************************************************
TEST(test_checksum_add_double)
{
double d = 3.1415927;
etl::checksum<uint8_t> checksum_calculator;
checksum_calculator << d;
uint8_t sum = checksum_calculator.value();
CHECK_EQUAL(165, int(sum));
}
//*************************************************************************
TEST(test_digest)
{
std::string data("123456789");
etl::checksum<uint8_t> checksum_calculator8(data.begin(), data.end());
etl::checksum<uint16_t> checksum_calculator16(data.begin(), data.end());
etl::checksum<uint32_t> checksum_calculator32(data.begin(), data.end());
etl::checksum<uint64_t> checksum_calculator64(data.begin(), data.end());
etl::ihash::generic_digest digest;
digest = checksum_calculator8.digest();
CHECK_EQUAL(221, *digest.first);
CHECK_EQUAL(sizeof(uint8_t), std::distance(digest.first, digest.second));
digest = checksum_calculator16.digest();
CHECK_EQUAL(477, *reinterpret_cast<const uint16_t*>(digest.first));
CHECK_EQUAL(sizeof(uint16_t), std::distance(digest.first, digest.second));
digest = checksum_calculator32.digest();
CHECK_EQUAL(477, *reinterpret_cast<const uint32_t*>(digest.first));
CHECK_EQUAL(sizeof(uint32_t), std::distance(digest.first, digest.second));
digest = checksum_calculator64.digest();
CHECK_EQUAL(477, *reinterpret_cast<const uint64_t*>(digest.first));
CHECK_EQUAL(sizeof(uint64_t), std::distance(digest.first, digest.second));
uint32_t hash3 = etl::checksum<uint32_t>(data3.rbegin(), data3.rend());
CHECK_EQUAL(int(hash1), int(hash3));
}
};
}

View File

@ -109,7 +109,7 @@ namespace
for (size_t i = 0; i < data.size(); ++i)
{
pearson_calculator += data[i];
pearson_calculator.add(data[i]);
}
hash_t compare = Pearson_Compare(data);
@ -138,13 +138,13 @@ namespace
{
std::vector<uint8_t> data1 = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
std::vector<uint32_t> data2 = { 0x04030201, 0x08070605 };
std::vector<uint32_t> data3 = { 0x01020304, 0x05060708 };
std::vector<uint8_t> data3 = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 };
hash_t hash1 = etl::pearson<HASH_SIZE, etl::endian::little>(data1.begin(), data1.end());
hash_t hash2 = etl::pearson<HASH_SIZE, etl::endian::little>(data2.begin(), data2.end());
hash_t hash1 = etl::pearson<HASH_SIZE>(data1.begin(), data1.end());
hash_t hash2 = etl::pearson<HASH_SIZE>((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size()));
CHECK_EQUAL(hash1, hash2);
hash_t hash3 = etl::pearson<HASH_SIZE, etl::endian::big>(data3.begin(), data3.end());
hash_t hash3 = etl::pearson<HASH_SIZE>(data3.rbegin(), data3.rend());
CHECK_EQUAL(hash1, hash3);
}
};