hash/crc: adapt implementation from png appendix
This commit is contained in:
parent
ca7f4b739a
commit
5a25f07f8e
@ -464,6 +464,7 @@ if (TESTS)
|
|||||||
geom/aabb
|
geom/aabb
|
||||||
geom/ray
|
geom/ray
|
||||||
hash/checksum
|
hash/checksum
|
||||||
|
hash/crc
|
||||||
hash/fasthash
|
hash/fasthash
|
||||||
hash/hmac
|
hash/hmac
|
||||||
hash/hotp
|
hash/hotp
|
||||||
|
91
hash/crc.cpp
91
hash/crc.cpp
@ -18,13 +18,53 @@
|
|||||||
|
|
||||||
#include "../debug.hpp"
|
#include "../debug.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
using util::hash::crc32;
|
using util::hash::crc32;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
static
|
||||||
|
std::array<uint32_t,256>
|
||||||
|
make_table (void)
|
||||||
|
{
|
||||||
|
std::array<uint32_t,256> value {};
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; ++i) {
|
||||||
|
std::uint32_t c = i;
|
||||||
|
|
||||||
|
for (int k = 0; k < 8; ++k) {
|
||||||
|
if (c & 1)
|
||||||
|
c = 0xEDB88320L ^ (c >> 1);
|
||||||
|
else
|
||||||
|
c >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
value[i] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static std::array<uint32_t,256> table = make_table ();
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
crc32::crc32 () noexcept
|
||||||
|
{
|
||||||
|
reset ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
crc32::reset (void)
|
crc32::reset (void) noexcept
|
||||||
{ ; }
|
{
|
||||||
|
m_digest = 0;
|
||||||
|
m_digest = ~m_digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -34,55 +74,32 @@ crc32::update (const uint8_t *restrict first,
|
|||||||
{
|
{
|
||||||
CHECK_LE (first, last);
|
CHECK_LE (first, last);
|
||||||
|
|
||||||
return update (first, last - first);
|
for (auto cursor = first; cursor != last; ++cursor) {
|
||||||
|
m_digest = table[*cursor ^ (m_digest & 0xFF)] ^ (m_digest >> 8u);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
crc32::update (const void *restrict, size_t) noexcept
|
crc32::update (const void *restrict _data, size_t len) noexcept
|
||||||
{
|
{
|
||||||
not_implemented ();
|
auto data = reinterpret_cast<const uint8_t *restrict> (_data);
|
||||||
|
return update(data, data + len);
|
||||||
/*
|
|
||||||
const uint8_t *restrict data = static_cast<const uint8_t*> (_data);
|
|
||||||
static const uint32_t POLYNOMIAL = hton (static_cast<uint32_t>(0x04C11DB7));
|
|
||||||
|
|
||||||
uint64_t bits = 0;
|
|
||||||
unsigned int i = 0;
|
|
||||||
|
|
||||||
if (size == 0)
|
|
||||||
return POLYNOMIAL;
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
default: bits |= static_cast<uint64_t>(data[3]) << 32U;
|
|
||||||
case 3: bits |= static_cast<uint64_t>(data[2]) << 40U;
|
|
||||||
case 2: bits |= static_cast<uint64_t>(data[1]) << 48U;
|
|
||||||
case 1: bits |= static_cast<uint64_t>(data[0]) << 56U;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < size; ++i) {
|
|
||||||
for (unsigned j = 0; j < 32; ++j) {
|
|
||||||
bool mix = bits 0x7000000000000000ULL;
|
|
||||||
bits <<= 1;
|
|
||||||
|
|
||||||
if (mix)
|
|
||||||
bits ^= POLYNOMIAL << 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
crc32::finish (void)
|
crc32::finish (void)
|
||||||
{ not_implemented (); }
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
typename crc32::digest_t
|
typename crc32::digest_t
|
||||||
crc32::digest (void) const
|
crc32::digest (void) const
|
||||||
{ not_implemented (); }
|
{
|
||||||
|
return ~m_digest;
|
||||||
|
}
|
@ -27,7 +27,9 @@ namespace util::hash {
|
|||||||
public:
|
public:
|
||||||
using digest_t = uint32_t;
|
using digest_t = uint32_t;
|
||||||
|
|
||||||
void reset (void);
|
crc32 () noexcept;
|
||||||
|
|
||||||
|
void reset (void) noexcept;
|
||||||
|
|
||||||
void update (const void *restrict data, size_t bytes) noexcept;
|
void update (const void *restrict data, size_t bytes) noexcept;
|
||||||
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
|
void update (const uint8_t *restrict first, const uint8_t *restrict last) noexcept;
|
||||||
@ -35,6 +37,9 @@ namespace util::hash {
|
|||||||
void finish (void);
|
void finish (void);
|
||||||
|
|
||||||
digest_t digest (void) const;
|
digest_t digest (void) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
digest_t m_digest;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
40
test/hash/crc.cpp
Normal file
40
test/hash/crc.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "tap.hpp"
|
||||||
|
#include "hash/crc.hpp"
|
||||||
|
#include "hash/simple.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
static const
|
||||||
|
struct {
|
||||||
|
uint32_t result;
|
||||||
|
const char *dat;
|
||||||
|
const char *msg;
|
||||||
|
} TESTS[] = {
|
||||||
|
{ 0x00000000, "", "empty" },
|
||||||
|
{ 0xe8b7be43, "a", "single letter" },
|
||||||
|
{ 0xa684c7c6, "0123456789", "10 digits" },
|
||||||
|
{ 0x414fa339, "The quick brown fox jumps over the lazy dog", "quick brown fox" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
main (int, char**)
|
||||||
|
{
|
||||||
|
util::TAP::logger tap;
|
||||||
|
|
||||||
|
for (const auto &t: TESTS) {
|
||||||
|
auto first = t.dat;
|
||||||
|
auto last = first + strlen (t.dat);
|
||||||
|
|
||||||
|
auto result = util::hash::simple<util::hash::crc32> (first, last);
|
||||||
|
|
||||||
|
tap.expect_eq (t.result, result, "%s %xu", t.msg, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tap.status ();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user