diff --git a/include/orc/memory.hpp b/include/orc/memory.hpp index 75ed239..f3d3924 100644 --- a/include/orc/memory.hpp +++ b/include/orc/memory.hpp @@ -45,6 +45,16 @@ decltype(auto) make_leaky(Args&&... args) { #endif } +/**************************************************************************************************/ +// Useful for reading integer values (that otherwise need to be aligned) from unaligned memory. The +// typical solution is to use memcpy and let the compiler optimize it further. +template +Integer unaligned_read(const void* p) { + Integer result{Integer()}; + std::memcpy(&result, p, sizeof(result)); + return result; +} + /**************************************************************************************************/ } // namespace orc diff --git a/src/hash.cpp b/src/hash.cpp index 7d6db77..1a0c4fb 100644 --- a/src/hash.cpp +++ b/src/hash.cpp @@ -7,6 +7,9 @@ // identity #include "orc/hash.hpp" +// application +#include "orc/memory.hpp" + /**************************************************************************************************/ namespace { @@ -37,7 +40,9 @@ inline uint64_t rotl64(uint64_t x, int8_t r) { return (x << r) | (x >> (64 - r)) /**************************************************************************************************/ -FORCE_INLINE uint64_t getblock64(const uint64_t* p, int i) { return p[i]; } +FORCE_INLINE std::uint64_t getblock64(const uint64_t* p, int i) { + return orc::unaligned_read(p + i); +} /**************************************************************************************************/ diff --git a/src/string_pool.cpp b/src/string_pool.cpp index dd35e4a..ca73926 100644 --- a/src/string_pool.cpp +++ b/src/string_pool.cpp @@ -32,9 +32,7 @@ namespace { /**************************************************************************************************/ -std::size_t string_view_hash(std::string_view s) { - return orc::murmur3_64(s.data(), s.length()); -} +std::size_t string_view_hash(std::string_view s) { return orc::murmur3_64(s.data(), s.length()); } /**************************************************************************************************/ @@ -85,19 +83,16 @@ struct pool { std::size_t pool_string::get_size(const char* d) { assert(d); const void* bytes = d - sizeof(std::uint32_t) - sizeof(std::size_t); - std::uint32_t s; - std::memcpy(&s, bytes, sizeof(s)); // not aligned - need to use memcpy - assert(s > 0); // required, else should have been _data == nullptr - assert(s < 100000); // sanity check + std::uint32_t s = orc::unaligned_read(bytes); + assert(s > 0); // required, else should have been _data == nullptr + assert(s < 100000); // sanity check return s; } std::size_t pool_string::get_hash(const char* d) { assert(d); const void* bytes = d - sizeof(std::size_t); - std::size_t h; - std::memcpy(&h, bytes, sizeof(h)); // not aligned -- need to use memcpy - return h; + return orc::unaligned_read(bytes); } pool_string empool(std::string_view src) { @@ -106,7 +101,8 @@ pool_string empool(std::string_view src) { // default_view would be returned.) if (src.empty()) return pool_string(nullptr); - static decltype(auto) keys = orc::make_leaky>(); + static decltype(auto) keys = + orc::make_leaky>(); const std::size_t h = string_view_hash(src);