mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-19 18:45:52 +00:00
752 lines
18 KiB
C++
752 lines
18 KiB
C++
//------------------------------------------------------------------------------
|
|
/*
|
|
This file is part of Beast: https://github.com/vinniefalco/Beast
|
|
Copyright 2014, Howard Hinnant <howard.hinnant@gmail.com>,
|
|
Vinnie Falco <vinnie.falco@gmail.com
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
//==============================================================================
|
|
|
|
#ifndef BEAST_CONTAINER_HASH_APPEND_H_INCLUDED
|
|
#define BEAST_CONTAINER_HASH_APPEND_H_INCLUDED
|
|
|
|
#include <beast/utility/meta.h>
|
|
|
|
#include <beast/container/impl/spookyv2.h>
|
|
|
|
#if BEAST_USE_BOOST_FEATURES
|
|
#include <boost/shared_ptr.hpp>
|
|
#endif
|
|
|
|
#include <beast/utility/noexcept.h>
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <beast/cxx14/type_traits.h> // <type_traits>
|
|
#include <beast/cxx14/utility.h> // <utility>
|
|
#include <vector>
|
|
|
|
// Set to 1 to disable variadic hash_append for tuple. When set, overloads
|
|
// will be manually provided for tuples up to 10-arity. This also causes
|
|
// is_contiguously_hashable<> to always return false for tuples.
|
|
//
|
|
#ifndef BEAST_NO_TUPLE_VARIADICS
|
|
# ifdef _MSC_VER
|
|
# define BEAST_NO_TUPLE_VARIADICS 1
|
|
# ifndef BEAST_VARIADIC_MAX
|
|
# ifdef _VARIADIC_MAX
|
|
# define BEAST_VARIADIC_MAX _VARIADIC_MAX
|
|
# else
|
|
# define BEAST_VARIADIC_MAX 10
|
|
# endif
|
|
# endif
|
|
# else
|
|
# define BEAST_NO_TUPLE_VARIADICS 0
|
|
# endif
|
|
#endif
|
|
|
|
// Set to 1 if std::pair fails the trait test on a platform.
|
|
#ifndef BEAST_NO_IS_CONTIGUOUS_HASHABLE_PAIR
|
|
#define BEAST_NO_IS_CONTIGUOUS_HASHABLE_PAIR 0
|
|
#endif
|
|
|
|
// Set to 1 if std::tuple fails the trait test on a platform.
|
|
#ifndef BEAST_NO_IS_CONTIGUOUS_HASHABLE_TUPLE
|
|
# ifdef _MSC_VER
|
|
# define BEAST_NO_IS_CONTIGUOUS_HASHABLE_TUPLE 1
|
|
# else
|
|
# define BEAST_NO_IS_CONTIGUOUS_HASHABLE_TUPLE 0
|
|
# endif
|
|
#endif
|
|
|
|
namespace beast {
|
|
|
|
/** Metafunction returning `true` if the type can be hashed in one call.
|
|
|
|
For `is_contiguously_hashable<T>::value` to be true, then for every
|
|
combination of possible values of `T` held in `x` and `y`,
|
|
if `x == y`, then it must be true that `memcmp(&x, &y, sizeof(T))`
|
|
return 0; i.e. that `x` and `y` are represented by the same bit pattern.
|
|
|
|
For example: A two's complement `int` should be contiguously hashable.
|
|
Every bit pattern produces a unique value that does not compare equal to
|
|
any other bit pattern's value. A IEEE floating point should not be
|
|
contiguously hashable because -0. and 0. have different bit patterns,
|
|
though they compare equal.
|
|
*/
|
|
/** @{ */
|
|
// scalars
|
|
template <class T>
|
|
struct is_contiguously_hashable
|
|
: public std::integral_constant <bool,
|
|
std::is_integral<T>::value ||
|
|
std::is_enum<T>::value ||
|
|
std::is_pointer<T>::value>
|
|
{
|
|
};
|
|
|
|
// If this fails, something is wrong with the trait
|
|
static_assert (is_contiguously_hashable<int>::value, "");
|
|
|
|
// pair
|
|
template <class T, class U>
|
|
struct is_contiguously_hashable <std::pair<T, U>>
|
|
: public std::integral_constant <bool,
|
|
is_contiguously_hashable<T>::value &&
|
|
is_contiguously_hashable<U>::value &&
|
|
sizeof(T) + sizeof(U) == sizeof(std::pair<T, U>)>
|
|
{
|
|
};
|
|
|
|
#if ! BEAST_NO_IS_CONTIGUOUS_HASHABLE_PAIR
|
|
static_assert (is_contiguously_hashable <std::pair <
|
|
unsigned long long, long long>>::value, "");
|
|
#endif
|
|
|
|
#if ! BEAST_NO_TUPLE_VARIADICS
|
|
// std::tuple
|
|
template <class ...T>
|
|
struct is_contiguously_hashable <std::tuple<T...>>
|
|
: public std::integral_constant <bool,
|
|
static_and <is_contiguously_hashable <T>::value...>::value &&
|
|
static_sum <sizeof(T)...>::value == sizeof(std::tuple<T...>)>
|
|
{
|
|
};
|
|
#endif
|
|
|
|
// std::array
|
|
template <class T, std::size_t N>
|
|
struct is_contiguously_hashable <std::array<T, N>>
|
|
: public std::integral_constant <bool,
|
|
is_contiguously_hashable<T>::value &&
|
|
sizeof(T)*N == sizeof(std::array<T, N>)>
|
|
{
|
|
};
|
|
|
|
static_assert (is_contiguously_hashable <std::array<char, 3>>::value, "");
|
|
|
|
#if ! BEAST_NO_IS_CONTIGUOUS_HASHABLE_TUPLE
|
|
static_assert (is_contiguously_hashable <
|
|
std::tuple <char, char, short>>::value, "");
|
|
#endif
|
|
|
|
/** @} */
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
/** Logically concatenate input data to a `Hasher`.
|
|
|
|
Hasher requirements:
|
|
|
|
`X` is the type `Hasher`
|
|
`h` is a value of type `x`
|
|
`p` is a value convertible to `void const*`
|
|
`n` is a value of type `std::size_t`, greater than zero
|
|
|
|
Expression:
|
|
`h.append (p, n);`
|
|
Throws:
|
|
Never
|
|
Effect:
|
|
Adds the input data to the hasher state.
|
|
|
|
Expression:
|
|
`static_cast<std::size_t>(j)`
|
|
Throws:
|
|
Never
|
|
Effect:
|
|
Returns the reslting hash of all the input data.
|
|
*/
|
|
/** @{ */
|
|
|
|
// scalars
|
|
|
|
template <class Hasher, class T>
|
|
inline
|
|
typename std::enable_if
|
|
<
|
|
is_contiguously_hashable<T>::value
|
|
>::type
|
|
hash_append (Hasher& h, T const& t) noexcept
|
|
{
|
|
h.append (&t, sizeof(t));
|
|
}
|
|
|
|
template <class Hasher, class T>
|
|
inline
|
|
typename std::enable_if
|
|
<
|
|
std::is_floating_point<T>::value
|
|
>::type
|
|
hash_append (Hasher& h, T t) noexcept
|
|
{
|
|
// hash both signed zeroes identically
|
|
if (t == 0)
|
|
t = 0;
|
|
h.append (&t, sizeof(t));
|
|
}
|
|
|
|
// arrays
|
|
|
|
template <class Hasher, class T, std::size_t N>
|
|
inline
|
|
typename std::enable_if
|
|
<
|
|
!is_contiguously_hashable<T>::value
|
|
>::type
|
|
hash_append (Hasher& h, T (&a)[N]) noexcept
|
|
{
|
|
for (auto const& t : a)
|
|
hash_append (h, t);
|
|
}
|
|
|
|
template <class Hasher, class T, std::size_t N>
|
|
inline
|
|
typename std::enable_if
|
|
<
|
|
is_contiguously_hashable<T>::value
|
|
>::type
|
|
hash_append (Hasher& h, T (&a)[N]) noexcept
|
|
{
|
|
h.append (a, N*sizeof(T));
|
|
}
|
|
|
|
// nullptr_t
|
|
|
|
template <class Hasher>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::nullptr_t p) noexcept
|
|
{
|
|
h.append (&p, sizeof(p));
|
|
}
|
|
|
|
// strings
|
|
|
|
template <class Hasher, class CharT, class Traits, class Alloc>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h,
|
|
std::basic_string <CharT, Traits, Alloc> const& s) noexcept
|
|
{
|
|
h.append (s.data (), (s.size()+1)*sizeof(CharT));
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// Forward declare hash_append for all containers. This is required so that
|
|
// argument dependent lookup works recursively (i.e. containers of containers).
|
|
|
|
template <class Hasher, class T, class U>
|
|
typename std::enable_if
|
|
<
|
|
!is_contiguously_hashable<std::pair<T, U>>::value
|
|
>::type
|
|
hash_append (Hasher& h, std::pair<T, U> const& p) noexcept;
|
|
|
|
template <class Hasher, class T, class Alloc>
|
|
typename std::enable_if
|
|
<
|
|
!is_contiguously_hashable<T>::value
|
|
>::type
|
|
hash_append (Hasher& h, std::vector<T, Alloc> const& v) noexcept;
|
|
|
|
template <class Hasher, class T, class Alloc>
|
|
typename std::enable_if
|
|
<
|
|
is_contiguously_hashable<T>::value
|
|
>::type
|
|
hash_append (Hasher& h, std::vector<T, Alloc> const& v) noexcept;
|
|
|
|
template <class Hasher, class T, std::size_t N>
|
|
typename std::enable_if
|
|
<
|
|
!is_contiguously_hashable<std::array<T, N>>::value
|
|
>::type
|
|
hash_append (Hasher& h, std::array<T, N> const& a) noexcept;
|
|
|
|
// std::tuple
|
|
|
|
template <class Hasher>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple<> const& t) noexcept;
|
|
|
|
#if BEAST_NO_TUPLE_VARIADICS
|
|
|
|
#if BEAST_VARIADIC_MAX >= 1
|
|
template <class Hasher, class T1>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <T1> const& t) noexcept;
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 2
|
|
template <class Hasher, class T1, class T2>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <T1, T2> const& t) noexcept;
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 3
|
|
template <class Hasher, class T1, class T2, class T3>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <T1, T2, T3> const& t) noexcept;
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 4
|
|
template <class Hasher, class T1, class T2, class T3, class T4>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <T1, T2, T3, T4> const& t) noexcept;
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 5
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <T1, T2, T3, T4, T5> const& t) noexcept;
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 6
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5,
|
|
class T6>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5, T6> const& t) noexcept;
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 7
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5,
|
|
class T6, class T7>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5, T6, T7> const& t) noexcept;
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 8
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5,
|
|
class T6, class T7, class T8>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5, T6, T7, T8> const& t) noexcept;
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 9
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5,
|
|
class T6, class T7, class T8, class T9>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5, T6, T7, T8, T9> const& t) noexcept;
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 10
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5,
|
|
class T6, class T7, class T8, class T9, class T10>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> const& t) noexcept;
|
|
#endif
|
|
|
|
#endif // BEAST_NO_TUPLE_VARIADICS
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
namespace detail {
|
|
|
|
template <class Hasher, class T>
|
|
inline
|
|
int
|
|
hash_one (Hasher& h, T const& t) noexcept
|
|
{
|
|
hash_append (h, t);
|
|
return 0;
|
|
}
|
|
|
|
} // detail
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
// std::tuple
|
|
|
|
template <class Hasher>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple<> const& t) noexcept
|
|
{
|
|
hash_append (h, nullptr);
|
|
}
|
|
|
|
#if BEAST_NO_TUPLE_VARIADICS
|
|
|
|
#if BEAST_VARIADIC_MAX >= 1
|
|
template <class Hasher, class T1>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <T1> const& t) noexcept
|
|
{
|
|
hash_append (h, std::get<0>(t));
|
|
}
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 2
|
|
template <class Hasher, class T1, class T2>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <T1, T2> const& t) noexcept
|
|
{
|
|
hash_append (h, std::get<0>(t));
|
|
hash_append (h, std::get<1>(t));
|
|
}
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 3
|
|
template <class Hasher, class T1, class T2, class T3>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <T1, T2, T3> const& t) noexcept
|
|
{
|
|
hash_append (h, std::get<0>(t));
|
|
hash_append (h, std::get<1>(t));
|
|
hash_append (h, std::get<2>(t));
|
|
}
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 4
|
|
template <class Hasher, class T1, class T2, class T3, class T4>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <T1, T2, T3, T4> const& t) noexcept
|
|
{
|
|
hash_append (h, std::get<0>(t));
|
|
hash_append (h, std::get<1>(t));
|
|
hash_append (h, std::get<2>(t));
|
|
hash_append (h, std::get<3>(t));
|
|
}
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 5
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5> const& t) noexcept
|
|
{
|
|
hash_append (h, std::get<0>(t));
|
|
hash_append (h, std::get<1>(t));
|
|
hash_append (h, std::get<2>(t));
|
|
hash_append (h, std::get<3>(t));
|
|
hash_append (h, std::get<4>(t));
|
|
}
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 6
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5,
|
|
class T6>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5, T6> const& t) noexcept
|
|
{
|
|
hash_append (h, std::get<0>(t));
|
|
hash_append (h, std::get<1>(t));
|
|
hash_append (h, std::get<2>(t));
|
|
hash_append (h, std::get<3>(t));
|
|
hash_append (h, std::get<4>(t));
|
|
hash_append (h, std::get<5>(t));
|
|
}
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 7
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5,
|
|
class T6, class T7>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5, T6, T7> const& t) noexcept
|
|
{
|
|
hash_append (h, std::get<0>(t));
|
|
hash_append (h, std::get<1>(t));
|
|
hash_append (h, std::get<2>(t));
|
|
hash_append (h, std::get<3>(t));
|
|
hash_append (h, std::get<4>(t));
|
|
hash_append (h, std::get<5>(t));
|
|
hash_append (h, std::get<6>(t));
|
|
}
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 8
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5,
|
|
class T6, class T7, class T8>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5, T6, T7, T8> const& t) noexcept
|
|
{
|
|
hash_append (h, std::get<0>(t));
|
|
hash_append (h, std::get<1>(t));
|
|
hash_append (h, std::get<2>(t));
|
|
hash_append (h, std::get<3>(t));
|
|
hash_append (h, std::get<4>(t));
|
|
hash_append (h, std::get<5>(t));
|
|
hash_append (h, std::get<6>(t));
|
|
hash_append (h, std::get<7>(t));
|
|
}
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 9
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5,
|
|
class T6, class T7, class T8, class T9>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5, T6, T7, T8, T9> const& t) noexcept
|
|
{
|
|
hash_append (h, std::get<0>(t));
|
|
hash_append (h, std::get<1>(t));
|
|
hash_append (h, std::get<2>(t));
|
|
hash_append (h, std::get<3>(t));
|
|
hash_append (h, std::get<4>(t));
|
|
hash_append (h, std::get<5>(t));
|
|
hash_append (h, std::get<6>(t));
|
|
hash_append (h, std::get<7>(t));
|
|
hash_append (h, std::get<8>(t));
|
|
}
|
|
#endif
|
|
|
|
#if BEAST_VARIADIC_MAX >= 10
|
|
template <class Hasher, class T1, class T2, class T3, class T4, class T5,
|
|
class T6, class T7, class T8, class T9, class T10>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::tuple <
|
|
T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> const& t) noexcept
|
|
{
|
|
hash_append (h, std::get<0>(t));
|
|
hash_append (h, std::get<1>(t));
|
|
hash_append (h, std::get<2>(t));
|
|
hash_append (h, std::get<3>(t));
|
|
hash_append (h, std::get<4>(t));
|
|
hash_append (h, std::get<5>(t));
|
|
hash_append (h, std::get<6>(t));
|
|
hash_append (h, std::get<7>(t));
|
|
hash_append (h, std::get<8>(t));
|
|
hash_append (h, std::get<9>(t));
|
|
}
|
|
#endif
|
|
|
|
#else // BEAST_NO_TUPLE_VARIADICS
|
|
|
|
namespace detail {
|
|
|
|
template <class Hasher, class ...T, std::size_t ...I>
|
|
inline
|
|
void
|
|
tuple_hash (Hasher& h, std::tuple<T...> const& t,
|
|
std::index_sequence<I...>) noexcept
|
|
{
|
|
struct for_each_item {
|
|
for_each_item (...) { }
|
|
};
|
|
for_each_item (hash_one(h, std::get<I>(t))...);
|
|
}
|
|
|
|
} // detail
|
|
|
|
template <class Hasher, class ...T>
|
|
inline
|
|
typename std::enable_if
|
|
<
|
|
!is_contiguously_hashable<std::tuple<T...>>::value
|
|
>::type
|
|
hash_append (Hasher& h, std::tuple<T...> const& t) noexcept
|
|
{
|
|
detail::tuple_hash(h, t, std::index_sequence_for<T...>{});
|
|
}
|
|
|
|
#endif // BEAST_NO_TUPLE_VARIADICS
|
|
|
|
// pair
|
|
|
|
template <class Hasher, class T, class U>
|
|
inline
|
|
typename std::enable_if
|
|
<
|
|
!is_contiguously_hashable<std::pair<T, U>>::value
|
|
>::type
|
|
hash_append (Hasher& h, std::pair<T, U> const& p) noexcept
|
|
{
|
|
hash_append (h, p.first);
|
|
hash_append (h, p.second);
|
|
}
|
|
|
|
// vector
|
|
|
|
template <class Hasher, class T, class Alloc>
|
|
inline
|
|
typename std::enable_if
|
|
<
|
|
!is_contiguously_hashable<T>::value
|
|
>::type
|
|
hash_append (Hasher& h, std::vector<T, Alloc> const& v) noexcept
|
|
{
|
|
for (auto const& t : v)
|
|
hash_append (h, t);
|
|
}
|
|
|
|
template <class Hasher, class T, class Alloc>
|
|
inline
|
|
typename std::enable_if
|
|
<
|
|
is_contiguously_hashable<T>::value
|
|
>::type
|
|
hash_append (Hasher& h, std::vector<T, Alloc> const& v) noexcept
|
|
{
|
|
h.append (v.data(), v.size()*sizeof(T));
|
|
}
|
|
|
|
// shared_ptr
|
|
|
|
template <class Hasher, class T>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, std::shared_ptr<T> const& p) noexcept
|
|
{
|
|
hash_append(h, p.get());
|
|
}
|
|
|
|
#if BEAST_USE_BOOST_FEATURES
|
|
template <class Hasher, class T>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, boost::shared_ptr<T> const& p) noexcept
|
|
{
|
|
hash_append(h, p.get());
|
|
}
|
|
#endif
|
|
|
|
// variadic hash_append
|
|
|
|
template <class Hasher, class T0, class T1, class ...T>
|
|
inline
|
|
void
|
|
hash_append (Hasher& h, T0 const& t0, T1 const& t1, T const& ...t) noexcept
|
|
{
|
|
hash_append (h, t0);
|
|
hash_append (h, t1, t...);
|
|
}
|
|
|
|
// See http://www.isthe.com/chongo/tech/comp/fnv/
|
|
class fnv1a
|
|
{
|
|
std::uint64_t state_ = 14695981039346656037ULL;
|
|
public:
|
|
|
|
using result_type = std::size_t;
|
|
|
|
void
|
|
append (void const* key, std::size_t len) noexcept
|
|
{
|
|
unsigned char const* p = static_cast<unsigned char const*>(key);
|
|
unsigned char const* const e = p + len;
|
|
for (; p < e; ++p)
|
|
state_ = (state_ ^ *p) * 1099511628211ULL;
|
|
}
|
|
|
|
explicit
|
|
operator std::size_t() noexcept
|
|
{
|
|
return static_cast<std::size_t>(state_);
|
|
}
|
|
};
|
|
|
|
// See http://burtleburtle.net/bob/hash/spooky.html
|
|
class spooky
|
|
{
|
|
SpookyHash state_;
|
|
public:
|
|
using result_type = std::size_t;
|
|
|
|
spooky (std::size_t seed1 = 1, std::size_t seed2 = 2) noexcept
|
|
{
|
|
state_.Init (seed1, seed2);
|
|
}
|
|
|
|
void
|
|
append (void const* key, std::size_t len) noexcept
|
|
{
|
|
state_.Update (key, len);
|
|
}
|
|
|
|
explicit
|
|
operator std::size_t() noexcept
|
|
{
|
|
std::uint64_t h1, h2;
|
|
state_.Final (&h1, &h2);
|
|
return static_cast <std::size_t> (h1);
|
|
}
|
|
};
|
|
|
|
// See https://131002.net/siphash/
|
|
class siphash
|
|
{
|
|
std::uint64_t v0_ = 0x736f6d6570736575ULL;
|
|
std::uint64_t v1_ = 0x646f72616e646f6dULL;
|
|
std::uint64_t v2_ = 0x6c7967656e657261ULL;
|
|
std::uint64_t v3_ = 0x7465646279746573ULL;
|
|
unsigned char buf_[8];
|
|
unsigned bufsize_ = 0;
|
|
unsigned total_length_ = 0;
|
|
public:
|
|
using result_type = std::size_t;
|
|
|
|
siphash() = default;
|
|
explicit siphash(std::uint64_t k0, std::uint64_t k1 = 0) noexcept;
|
|
|
|
void
|
|
append (void const* key, std::size_t len) noexcept;
|
|
|
|
explicit
|
|
operator std::size_t() noexcept;
|
|
};
|
|
|
|
template <class Hasher = spooky>
|
|
struct uhash
|
|
{
|
|
using result_type = typename Hasher::result_type;
|
|
|
|
template <class T>
|
|
result_type
|
|
operator()(T const& t) const noexcept
|
|
{
|
|
Hasher h;
|
|
hash_append (h, t);
|
|
return static_cast<result_type>(h);
|
|
}
|
|
};
|
|
|
|
|
|
} // beast
|
|
|
|
#endif
|