Field digest is endian-independent:

fix #1863
close #1864

* Added some comments
* Add 64-bit specific calculation
* Fix endian-dependence in digest
This commit is contained in:
Vinnie Falco
2020-02-28 08:30:04 -08:00
parent 2c2e2c0812
commit f5273300f9
2 changed files with 31 additions and 10 deletions

View File

@ -7,6 +7,7 @@ Version 286:
* Refactor flat_static_buffer * Refactor flat_static_buffer
* Fix missing include in sha1.hpp * Fix missing include in sha1.hpp
* Fix ostream warning * Fix ostream warning
* Field digest is endian-independent
API Changes: API Changes:

View File

@ -24,6 +24,22 @@ namespace detail {
struct field_table struct field_table
{ {
static
std::uint32_t
get_chars(
unsigned char const* p) noexcept
{
// VFALCO memcpy is endian-dependent
//std::memcpy(&v, p, 4);
// Compiler should be smart enough to
// optimize this down to one instruction.
return
p[0] |
(p[1] << 8) |
(p[2] << 16) |
(p[3] << 24);
}
using array_type = using array_type =
std::array<string_view, 353>; std::array<string_view, 353>;
@ -34,16 +50,19 @@ struct field_table
{ {
std::uint32_t r = 0; std::uint32_t r = 0;
std::size_t n = s.size(); std::size_t n = s.size();
unsigned char const* p =reinterpret_cast< auto p = reinterpret_cast<
unsigned char const*>(s.data()); unsigned char const*>(s.data());
// consume N characters at a time
// VFALCO Can we do 8 on 64-bit systems?
while(n >= 4) while(n >= 4)
{ {
std::uint32_t v; auto const v = get_chars(p);
std::memcpy(&v, p, 4); r = (r * 5 + (
r = r * 5 + ( v | 0x20202020 ); v | 0x20202020 )); // convert to lower
p += 4; p += 4;
n -= 4; n -= 4;
} }
// handle remaining characters
while( n > 0 ) while( n > 0 )
{ {
r = r * 5 + ( *p | 0x20 ); r = r * 5 + ( *p | 0x20 );
@ -59,20 +78,21 @@ struct field_table
bool bool
equals(string_view lhs, string_view rhs) equals(string_view lhs, string_view rhs)
{ {
using Int = std::uint32_t; // or std::size_t using Int = std::uint32_t; // VFALCO std::size_t?
auto n = lhs.size(); auto n = lhs.size();
if(n != rhs.size()) if(n != rhs.size())
return false; return false;
auto p1 = lhs.data(); auto p1 = reinterpret_cast<
auto p2 = rhs.data(); unsigned char const*>(lhs.data());
auto p2 = reinterpret_cast<
unsigned char const*>(rhs.data());
auto constexpr S = sizeof(Int); auto constexpr S = sizeof(Int);
auto constexpr Mask = static_cast<Int>( auto constexpr Mask = static_cast<Int>(
0xDFDFDFDFDFDFDFDF & ~Int{0}); 0xDFDFDFDFDFDFDFDF & ~Int{0});
for(; n >= S; p1 += S, p2 += S, n -= S) for(; n >= S; p1 += S, p2 += S, n -= S)
{ {
Int v1, v2; Int const v1 = get_chars(p1);
std::memcpy( &v1, p1, S ); Int const v2 = get_chars(p2);
std::memcpy( &v2, p2, S );
if((v1 ^ v2) & Mask) if((v1 ^ v2) & Mask)
return false; return false;
} }