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/ray
|
||||
hash/checksum
|
||||
hash/crc
|
||||
hash/fasthash
|
||||
hash/hmac
|
||||
hash/hotp
|
||||
|
91
hash/crc.cpp
91
hash/crc.cpp
@ -18,13 +18,53 @@
|
||||
|
||||
#include "../debug.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
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
|
||||
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);
|
||||
|
||||
return update (first, last - first);
|
||||
for (auto cursor = first; cursor != last; ++cursor) {
|
||||
m_digest = table[*cursor ^ (m_digest & 0xFF)] ^ (m_digest >> 8u);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
crc32::update (const void *restrict, size_t) noexcept
|
||||
crc32::update (const void *restrict _data, size_t len) noexcept
|
||||
{
|
||||
not_implemented ();
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
auto data = reinterpret_cast<const uint8_t *restrict> (_data);
|
||||
return update(data, data + len);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void
|
||||
crc32::finish (void)
|
||||
{ not_implemented (); }
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
typename crc32::digest_t
|
||||
crc32::digest (void) const
|
||||
{ not_implemented (); }
|
||||
{
|
||||
return ~m_digest;
|
||||
}
|
@ -27,7 +27,9 @@ namespace util::hash {
|
||||
public:
|
||||
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 uint8_t *restrict first, const uint8_t *restrict last) noexcept;
|
||||
@ -35,6 +37,9 @@ namespace util::hash {
|
||||
void finish (void);
|
||||
|
||||
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