diff options
| author | 2018-04-07 00:48:22 -0400 | |
|---|---|---|
| committer | 2018-04-13 23:48:22 -0400 | |
| commit | 45fd7c4a37d4b890f98f8a0a9373e57c0830cc8d (patch) | |
| tree | c8407755365316b1316407d5aee6871c0007ba85 /src/common/hash.h | |
| parent | renderer_opengl: Use OGLProgram instead of OGLShader. (diff) | |
| download | yuzu-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.h | 55 |
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 | ||
| 10 | namespace Common { | 12 | namespace Common { |
| 11 | 13 | ||
| 12 | void 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 | */ |
| 20 | static inline u64 ComputeHash64(const void* data, size_t len) { | 20 | static 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 | */ | ||
| 29 | template <typename T> | ||
| 30 | static 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. | ||
| 37 | template <typename T> | ||
| 38 | struct 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 |