mirror of
https://github.com/boostorg/container_hash.git
synced 2025-08-04 15:04:39 +02:00
Add read32le to detail/hash_range.hpp
This commit is contained in:
@@ -38,6 +38,8 @@ template<> struct is_char_type<std::byte>: public boost::true_type {};
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// generic version
|
||||||
|
|
||||||
template<class It>
|
template<class It>
|
||||||
inline typename boost::enable_if_<
|
inline typename boost::enable_if_<
|
||||||
!is_char_type<typename std::iterator_traits<It>::value_type>::value,
|
!is_char_type<typename std::iterator_traits<It>::value_type>::value,
|
||||||
@@ -52,6 +54,34 @@ std::size_t >::type
|
|||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// specialized char[] version
|
||||||
|
|
||||||
|
template<class It> 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<boost::uint32_t>( static_cast<unsigned char>( p[0] ) ) |
|
||||||
|
static_cast<boost::uint32_t>( static_cast<unsigned char>( p[1] ) ) << 8 |
|
||||||
|
static_cast<boost::uint32_t>( static_cast<unsigned char>( p[2] ) ) << 16 |
|
||||||
|
static_cast<boost::uint32_t>( static_cast<unsigned char>( p[3] ) ) << 24;
|
||||||
|
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && !defined(__clang__)
|
||||||
|
|
||||||
|
template<class T> inline boost::uint32_t read32le( T* p )
|
||||||
|
{
|
||||||
|
boost::uint32_t w;
|
||||||
|
|
||||||
|
std::memcpy( &w, p, 4 );
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
template<class It>
|
template<class It>
|
||||||
inline typename boost::enable_if_<
|
inline typename boost::enable_if_<
|
||||||
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
|
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
|
||||||
@@ -63,15 +93,7 @@ std::size_t>::type
|
|||||||
|
|
||||||
for( ; n >= 4; first += 4, n -= 4 )
|
for( ; n >= 4; first += 4, n -= 4 )
|
||||||
{
|
{
|
||||||
// clang 5+, gcc 5+ figure out this pattern and use a single mov on x86
|
boost::uint32_t w = read32le( first );
|
||||||
// gcc on s390x and power BE even knows how to use load-reverse
|
|
||||||
|
|
||||||
boost::uint32_t w =
|
|
||||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
|
||||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
|
|
||||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
|
|
||||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[3] ) ) << 24;
|
|
||||||
|
|
||||||
hash_combine( seed, w );
|
hash_combine( seed, w );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,67 +139,6 @@ std::size_t>::type
|
|||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_MSC_VER) && !defined(__clang__)
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
inline typename boost::enable_if_<is_char_type<T>::value, std::size_t>::type
|
|
||||||
hash_range( std::size_t seed, T const* first, T const* last )
|
|
||||||
{
|
|
||||||
std::size_t n = static_cast<std::size_t>( 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<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
|
||||||
0x0100u;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
|
|
||||||
w =
|
|
||||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
|
||||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
|
|
||||||
0x010000u;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
|
|
||||||
w =
|
|
||||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
|
||||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
|
|
||||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
|
|
||||||
0x01000000u;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
hash_combine( seed, w );
|
|
||||||
}
|
|
||||||
|
|
||||||
return seed;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<class It>
|
template<class It>
|
||||||
inline typename boost::enable_if_<
|
inline typename boost::enable_if_<
|
||||||
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
|
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
|
||||||
|
Reference in New Issue
Block a user