1*3f982cf4SFabien Sanglard // Copyright 2020 The Chromium Authors. All rights reserved. 2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be 3*3f982cf4SFabien Sanglard // found in the LICENSE file. 4*3f982cf4SFabien Sanglard 5*3f982cf4SFabien Sanglard #ifndef UTIL_HASHING_H_ 6*3f982cf4SFabien Sanglard #define UTIL_HASHING_H_ 7*3f982cf4SFabien Sanglard 8*3f982cf4SFabien Sanglard namespace openscreen { 9*3f982cf4SFabien Sanglard 10*3f982cf4SFabien Sanglard // Computes the aggregate hash of the provided hashable objects. 11*3f982cf4SFabien Sanglard // Seed must initially use a large prime between 2^63 and 2^64 as a starting 12*3f982cf4SFabien Sanglard // value, or the result of a previous call to this function. 13*3f982cf4SFabien Sanglard template <typename... T> ComputeAggregateHash(uint64_t seed,const T &...objs)14*3f982cf4SFabien Sanglarduint64_t ComputeAggregateHash(uint64_t seed, const T&... objs) { 15*3f982cf4SFabien Sanglard auto hash_combiner = [](uint64_t seed, uint64_t hash_value) -> uint64_t { 16*3f982cf4SFabien Sanglard static const uint64_t kMultiplier = UINT64_C(0x9ddfea08eb382d69); 17*3f982cf4SFabien Sanglard uint64_t a = (hash_value ^ seed) * kMultiplier; 18*3f982cf4SFabien Sanglard a ^= (a >> 47); 19*3f982cf4SFabien Sanglard uint64_t b = (seed ^ a) * kMultiplier; 20*3f982cf4SFabien Sanglard b ^= (b >> 47); 21*3f982cf4SFabien Sanglard b *= kMultiplier; 22*3f982cf4SFabien Sanglard return b; 23*3f982cf4SFabien Sanglard }; 24*3f982cf4SFabien Sanglard 25*3f982cf4SFabien Sanglard uint64_t result = seed; 26*3f982cf4SFabien Sanglard std::vector<uint64_t> hashes{std::hash<T>()(objs)...}; 27*3f982cf4SFabien Sanglard for (uint64_t hash : hashes) { 28*3f982cf4SFabien Sanglard result = hash_combiner(result, hash); 29*3f982cf4SFabien Sanglard } 30*3f982cf4SFabien Sanglard return result; 31*3f982cf4SFabien Sanglard } 32*3f982cf4SFabien Sanglard 33*3f982cf4SFabien Sanglard template <typename... T> ComputeAggregateHash(const T &...objs)34*3f982cf4SFabien Sanglarduint64_t ComputeAggregateHash(const T&... objs) { 35*3f982cf4SFabien Sanglard // This value is taken from absl::Hash implementation. 36*3f982cf4SFabien Sanglard constexpr uint64_t default_seed = UINT64_C(0xc3a5c85c97cb3127); 37*3f982cf4SFabien Sanglard return ComputeAggregateHash(default_seed, objs...); 38*3f982cf4SFabien Sanglard } 39*3f982cf4SFabien Sanglard 40*3f982cf4SFabien Sanglard struct PairHash { 41*3f982cf4SFabien Sanglard template <typename TFirst, typename TSecond> operatorPairHash42*3f982cf4SFabien Sanglard size_t operator()(const std::pair<TFirst, TSecond>& pair) const { 43*3f982cf4SFabien Sanglard return ComputeAggregateHash(pair.first, pair.second); 44*3f982cf4SFabien Sanglard } 45*3f982cf4SFabien Sanglard }; 46*3f982cf4SFabien Sanglard 47*3f982cf4SFabien Sanglard } // namespace openscreen 48*3f982cf4SFabien Sanglard 49*3f982cf4SFabien Sanglard #endif // UTIL_HASHING_H_ 50