From 56cb6a23261f34e2855c89c662b70030e89a2e77 Mon Sep 17 00:00:00 2001 From: Alex Fabijanic Date: Wed, 31 Mar 2021 20:39:17 +0200 Subject: [PATCH] feat(HashRange): port HashRange from boost --- Foundation/include/Poco/Hash.h | 95 ++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/Foundation/include/Poco/Hash.h b/Foundation/include/Poco/Hash.h index 7aafb66a6..69c09e138 100644 --- a/Foundation/include/Poco/Hash.h +++ b/Foundation/include/Poco/Hash.h @@ -10,6 +10,9 @@ // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // and Contributors. // +// HashRange Copyright 2005-2014 Daniel James. +// (Extracted from Boost 1.75.0 lib and adapted for poco on 2021-03-31) +// // SPDX-License-Identifier: BSL-1.0 // @@ -19,9 +22,17 @@ #include "Poco/Foundation.h" +#include "Poco/Types.h" #include +#if defined(_MSC_VER) +# define POCO_HASH_ROTL32(x, r) _rotl(x,r) +#else +# define POCO_HASH_ROTL32(x, r) (x << r) | (x >> (32 - r)) +#endif + + namespace Poco { @@ -99,6 +110,90 @@ inline std::size_t hash(UInt64 n) } +namespace Impl { + + +template +inline void HashCombine(SizeT& seed, SizeT value) +{ + seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2); +} + + +inline void HashCombine(Poco::UInt32& h1, Poco::UInt32 k1) +{ + const uint32_t c1 = 0xcc9e2d51; + const uint32_t c2 = 0x1b873593; + + k1 *= c1; + k1 = POCO_HASH_ROTL32(k1,15); + k1 *= c2; + + h1 ^= k1; + h1 = POCO_HASH_ROTL32(h1,13); + h1 = h1*5+0xe6546b64; +} + + +#if defined(POCO_PTR_IS_64_BIT) && !(defined(__GNUC__) && ULONG_MAX == 0xffffffff) + + +inline void HashCombine(Poco::UInt64& h, Poco::UInt64 k) +{ + const Poco::UInt64 m = UINT64_C(0xc6a4a7935bd1e995); + const int r = 47; + + k *= m; + k ^= k >> r; + k *= m; + + h ^= k; + h *= m; + + // Completely arbitrary number, to + // prevent zeros from hashing to 0. + h += 0xe6546b64; +} + + +#endif // POCO_PTR_IS_64_BIT + + +} // namespace Impl + + +template +inline void HashCombine(std::size_t& seed, T const& v) +{ + Hash hasher; + Impl::HashCombine(seed, hasher(v)); +} + + +template +inline std::size_t HashRange(It first, It last) +{ + std::size_t seed = 0; + + for(; first != last; ++first) + { + HashCombine::value_type>(seed, *first); + } + + return seed; +} + + +template +inline void HashRange(std::size_t& seed, It first, It last) +{ + for(; first != last; ++first) + { + HashCombine::value_type>(seed, *first); + } +} + + } // namespace Poco