hash.h 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Copyright 2015 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <cstddef>
  6. #include <cstring>
  7. #include "common/cityhash.h"
  8. #include "common/common_types.h"
  9. namespace Common {
  10. /**
  11. * Computes a 64-bit hash over the specified block of data
  12. * @param data Block of data to compute hash over
  13. * @param len Length of data (in bytes) to compute hash over
  14. * @returns 64-bit hash value that was computed over the data block
  15. */
  16. static inline u64 ComputeHash64(const void* data, size_t len) {
  17. return CityHash64(static_cast<const char*>(data), len);
  18. }
  19. /**
  20. * Computes a 64-bit hash of a struct. In addition to being trivially copyable, it is also critical
  21. * that either the struct includes no padding, or that any padding is initialized to a known value
  22. * by memsetting the struct to 0 before filling it in.
  23. */
  24. template <typename T>
  25. static inline u64 ComputeStructHash64(const T& data) {
  26. static_assert(std::is_trivially_copyable_v<T>,
  27. "Type passed to ComputeStructHash64 must be trivially copyable");
  28. return ComputeHash64(&data, sizeof(data));
  29. }
  30. /// A helper template that ensures the padding in a struct is initialized by memsetting to 0.
  31. template <typename T>
  32. struct HashableStruct {
  33. // In addition to being trivially copyable, T must also have a trivial default constructor,
  34. // because any member initialization would be overridden by memset
  35. static_assert(std::is_trivial_v<T>, "Type passed to HashableStruct must be trivial");
  36. /*
  37. * We use a union because "implicitly-defined copy/move constructor for a union X copies the
  38. * object representation of X." and "implicitly-defined copy assignment operator for a union X
  39. * copies the object representation (3.9) of X." = Bytewise copy instead of memberwise copy.
  40. * This is important because the padding bytes are included in the hash and comparison between
  41. * objects.
  42. */
  43. union {
  44. T state;
  45. };
  46. HashableStruct() {
  47. // Memset structure to zero padding bits, so that they will be deterministic when hashing
  48. std::memset(&state, 0, sizeof(T));
  49. }
  50. bool operator==(const HashableStruct<T>& o) const {
  51. return std::memcmp(&state, &o.state, sizeof(T)) == 0;
  52. };
  53. bool operator!=(const HashableStruct<T>& o) const {
  54. return !(*this == o);
  55. };
  56. size_t Hash() const {
  57. return Common::ComputeStructHash64(state);
  58. }
  59. };
  60. } // namespace Common