From c07630ac60f5d9555773953debf7c015cce1c902 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 2 Feb 2023 04:09:54 +0200 Subject: [PATCH] Add read32le to detail/hash_range.hpp --- .../container_hash/detail/hash_range.hpp | 101 ++++++------------ 1 file changed, 31 insertions(+), 70 deletions(-) diff --git a/include/boost/container_hash/detail/hash_range.hpp b/include/boost/container_hash/detail/hash_range.hpp index 4583ab4..2d5ae52 100644 --- a/include/boost/container_hash/detail/hash_range.hpp +++ b/include/boost/container_hash/detail/hash_range.hpp @@ -38,6 +38,8 @@ template<> struct is_char_type: public boost::true_type {}; #endif +// generic version + template inline typename boost::enable_if_< !is_char_type::value_type>::value, @@ -52,6 +54,34 @@ std::size_t >::type return seed; } +// specialized char[] version + +template inline boost::uint32_t read32le( It p ) +{ + // clang 5+, gcc 5+ figure out this pattern and use a single mov on x86 + // gcc on s390x and power BE even knows how to use load-reverse + + boost::uint32_t w = + static_cast( static_cast( p[0] ) ) | + static_cast( static_cast( p[1] ) ) << 8 | + static_cast( static_cast( p[2] ) ) << 16 | + static_cast( static_cast( p[3] ) ) << 24; + + return w; +} + +#if defined(_MSC_VER) && !defined(__clang__) + +template inline boost::uint32_t read32le( T* p ) +{ + boost::uint32_t w; + + std::memcpy( &w, p, 4 ); + return w; +} + +#endif + template inline typename boost::enable_if_< is_char_type::value_type>::value && @@ -63,15 +93,7 @@ std::size_t>::type for( ; n >= 4; first += 4, n -= 4 ) { - // clang 5+, gcc 5+ figure out this pattern and use a single mov on x86 - // gcc on s390x and power BE even knows how to use load-reverse - - boost::uint32_t w = - static_cast( static_cast( first[0] ) ) | - static_cast( static_cast( first[1] ) ) << 8 | - static_cast( static_cast( first[2] ) ) << 16 | - static_cast( static_cast( first[3] ) ) << 24; - + boost::uint32_t w = read32le( first ); hash_combine( seed, w ); } @@ -117,67 +139,6 @@ std::size_t>::type return seed; } -#if defined(_MSC_VER) && !defined(__clang__) - -template -inline typename boost::enable_if_::value, std::size_t>::type - hash_range( std::size_t seed, T const* first, T const* last ) -{ - std::size_t n = static_cast( last - first ); - - for( ; n >= 4; first += 4, n -= 4 ) - { - boost::uint32_t w; - - std::memcpy( &w, first, 4 ); - - hash_combine( seed, w ); - } - - { - // add a trailing suffix byte of 0x01 because otherwise sequences of - // trailing zeroes are indistinguishable from end of string - - boost::uint32_t w = 0x01u; - - switch( n ) - { - case 1: - - w = - static_cast( static_cast( first[0] ) ) | - 0x0100u; - - break; - - case 2: - - w = - static_cast( static_cast( first[0] ) ) | - static_cast( static_cast( first[1] ) ) << 8 | - 0x010000u; - - break; - - case 3: - - w = - static_cast( static_cast( first[0] ) ) | - static_cast( static_cast( first[1] ) ) << 8 | - static_cast( static_cast( first[2] ) ) << 16 | - 0x01000000u; - - break; - } - - hash_combine( seed, w ); - } - - return seed; -} - -#endif - template inline typename boost::enable_if_< is_char_type::value_type>::value &&