summaryrefslogtreecommitdiff
path: root/src/common/hash.h
diff options
context:
space:
mode:
authorGravatar bunnei2018-04-07 00:48:22 -0400
committerGravatar bunnei2018-04-13 23:48:22 -0400
commit45fd7c4a37d4b890f98f8a0a9373e57c0830cc8d (patch)
treec8407755365316b1316407d5aee6871c0007ba85 /src/common/hash.h
parentrenderer_opengl: Use OGLProgram instead of OGLShader. (diff)
downloadyuzu-45fd7c4a37d4b890f98f8a0a9373e57c0830cc8d.tar.gz
yuzu-45fd7c4a37d4b890f98f8a0a9373e57c0830cc8d.tar.xz
yuzu-45fd7c4a37d4b890f98f8a0a9373e57c0830cc8d.zip
common: Port cityhash code from Citra.
Diffstat (limited to '')
-rw-r--r--src/common/hash.h55
1 files changed, 50 insertions, 5 deletions
diff --git a/src/common/hash.h b/src/common/hash.h
index ee2560dad..73c326980 100644
--- a/src/common/hash.h
+++ b/src/common/hash.h
@@ -5,12 +5,12 @@
5#pragma once 5#pragma once
6 6
7#include <cstddef> 7#include <cstddef>
8#include <cstring>
9#include "common/cityhash.h"
8#include "common/common_types.h" 10#include "common/common_types.h"
9 11
10namespace Common { 12namespace Common {
11 13
12void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out);
13
14/** 14/**
15 * Computes a 64-bit hash over the specified block of data 15 * Computes a 64-bit hash over the specified block of data
16 * @param data Block of data to compute hash over 16 * @param data Block of data to compute hash over
@@ -18,9 +18,54 @@ void MurmurHash3_128(const void* key, size_t len, u32 seed, void* out);
18 * @returns 64-bit hash value that was computed over the data block 18 * @returns 64-bit hash value that was computed over the data block
19 */ 19 */
20static inline u64 ComputeHash64(const void* data, size_t len) { 20static inline u64 ComputeHash64(const void* data, size_t len) {
21 u64 res[2]; 21 return CityHash64(static_cast<const char*>(data), len);
22 MurmurHash3_128(data, len, 0, res); 22}
23 return res[0]; 23
24/**
25 * Computes a 64-bit hash of a struct. In addition to being trivially copyable, it is also critical
26 * that either the struct includes no padding, or that any padding is initialized to a known value
27 * by memsetting the struct to 0 before filling it in.
28 */
29template <typename T>
30static inline u64 ComputeStructHash64(const T& data) {
31 static_assert(std::is_trivially_copyable<T>(),
32 "Type passed to ComputeStructHash64 must be trivially copyable");
33 return ComputeHash64(&data, sizeof(data));
24} 34}
25 35
36/// A helper template that ensures the padding in a struct is initialized by memsetting to 0.
37template <typename T>
38struct HashableStruct {
39 // In addition to being trivially copyable, T must also have a trivial default constructor,
40 // because any member initialization would be overridden by memset
41 static_assert(std::is_trivial<T>(), "Type passed to HashableStruct must be trivial");
42 /*
43 * We use a union because "implicitly-defined copy/move constructor for a union X copies the
44 * object representation of X." and "implicitly-defined copy assignment operator for a union X
45 * copies the object representation (3.9) of X." = Bytewise copy instead of memberwise copy.
46 * This is important because the padding bytes are included in the hash and comparison between
47 * objects.
48 */
49 union {
50 T state;
51 };
52
53 HashableStruct() {
54 // Memset structure to zero padding bits, so that they will be deterministic when hashing
55 std::memset(&state, 0, sizeof(T));
56 }
57
58 bool operator==(const HashableStruct<T>& o) const {
59 return std::memcmp(&state, &o.state, sizeof(T)) == 0;
60 };
61
62 bool operator!=(const HashableStruct<T>& o) const {
63 return !(*this == o);
64 };
65
66 size_t Hash() const {
67 return Common::ComputeStructHash64(state);
68 }
69};
70
26} // namespace Common 71} // namespace Common