// Copyright 2012 Daniel James. // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // This is also released into the public domain. #if !defined(BOOST_HASH_EXAMPLES_SIPHASH_HEADER) #define BOOST_HASH_EXAMPLES_SIPHASH_HEADER #include #include #include #include #include namespace hash { // Random key used to make sure the hash function isn't predictable. struct sipkey { boost::uint64_t k0, k1; }; // Generate a secure sipkey. // This only works when boost::random_device is available. sipkey generate_sipkey(); // This is the class that does the actual hashing. struct siphash_state { boost::uint64_t v0, v1, v2, v3; union { boost::uint64_t m; unsigned char buffer[8]; }; unsigned char buffered; unsigned char b; explicit siphash_state(sipkey const&); void update(void const*, unsigned); boost::uint64_t finalize(); private: void sip_round(unsigned); }; // The genereric hash function. // // Don't sepecialize this. Unless you really want to. template struct siphash { sipkey key; /* implicit */ siphash(sipkey const& k) : key(k) {} std::size_t operator()(T const&) const; }; // Add support for a type by specializing this class. // // 'Enable' is used as a SFINAE hook. template struct siphash_impl { static void update(siphash_state&, T const&); }; // The implementation of the generic hash function. template std::size_t siphash::operator()(T const& x) const { siphash_state state(key); siphash_impl::update(state, x); return static_cast(state.finalize()); } // A couple of basic traits for hashing binary data. struct enable_siphash_false { enum { value = false }; }; struct enable_siphash_true { enum { value = true }; }; template struct enable_siphash_binary : enable_siphash_false {}; template struct enable_siphash_binary_array { enum { value = enable_siphash_binary::value && sizeof(T[2]) == sizeof(T) * 2 }; }; // Some general purpose hash implementations, siphash_impl // can inherit from these. template struct siphash_binary_impl { static void update(siphash_state& state, int x) { state.update(&x, sizeof(x)); } }; template struct siphash_container_impl { static void update(siphash_state& state, T const& x) { siphash_impl value_impl; for (typename T::const_iterator begin = x.begin(), end = x.end(); begin != end; ++begin) { value_impl.update(state, *begin); } } }; template ::value> struct siphash_binary_container_impl; template struct siphash_binary_container_impl : siphash_container_impl {}; template struct siphash_binary_container_impl { static void update(siphash_state& state, T const& x) { state.update(&*x.cbegin(), sizeof(T) * x.size()); } }; // Specialize siphash_impl for various types. template struct siphash_impl::value>::type > : siphash_binary_impl {}; template struct siphash_impl > : siphash_container_impl {}; template struct siphash_impl > : siphash_binary_container_impl {}; template struct siphash_impl, Alloc> > : siphash_binary_container_impl {}; // Specialize the binary trait for builtin types. template <> struct enable_siphash_binary : enable_siphash_true {}; template <> struct enable_siphash_binary : enable_siphash_true {}; template <> struct enable_siphash_binary : enable_siphash_true {}; template <> struct enable_siphash_binary : enable_siphash_true {}; template <> struct enable_siphash_binary : enable_siphash_true {}; template <> struct enable_siphash_binary : enable_siphash_true {}; template <> struct enable_siphash_binary : enable_siphash_true {}; template <> struct enable_siphash_binary : enable_siphash_true {}; template <> struct enable_siphash_binary : enable_siphash_true {}; template <> struct enable_siphash_binary : enable_siphash_true {}; #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) template <> struct enable_siphash_binary : enable_siphash_true {}; #endif #if !defined(BOOST_NO_LONG_LONG) template <> struct enable_siphash_binary : enable_siphash_true {}; template <> struct enable_siphash_binary : enable_siphash_true {}; #endif #if defined(BOOST_HAS_INT128) template <> struct enable_siphash_binary : boost::hash_detail::enable_hash_value {}; template <> struct enable_siphash_binary : boost::hash_detail::enable_hash_value {}; #endif } #endif