hash.h 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright 2010-2013 Branimir Karadzic. All rights reserved.
  3. * License: http://www.opensource.org/licenses/BSD-2-Clause
  4. */
  5. #ifndef BX_HASH_H_HEADER_GUARD
  6. #define BX_HASH_H_HEADER_GUARD
  7. #include "bx.h"
  8. namespace bx
  9. {
  10. // MurmurHash2 was written by Austin Appleby, and is placed in the public
  11. // domain. The author hereby disclaims copyright to this source code.
  12. #define MURMUR_M 0x5bd1e995
  13. #define MURMUR_R 24
  14. #define mmix(_h, _k) { _k *= MURMUR_M; _k ^= _k >> MURMUR_R; _k *= MURMUR_M; _h *= MURMUR_M; _h ^= _k; }
  15. class HashMurmur2A
  16. {
  17. public:
  18. void begin(uint32_t _seed = 0)
  19. {
  20. m_hash = _seed;
  21. m_tail = 0;
  22. m_count = 0;
  23. m_size = 0;
  24. }
  25. void add(const void* _data, int _len)
  26. {
  27. const uint8_t* data = (uint8_t*)_data;
  28. m_size += _len;
  29. mixTail(data, _len);
  30. while(_len >= 4)
  31. {
  32. uint32_t kk = *(uint32_t*)data;
  33. mmix(m_hash, kk);
  34. data += 4;
  35. _len -= 4;
  36. }
  37. mixTail(data, _len);
  38. }
  39. template<typename Ty>
  40. void add(Ty _value)
  41. {
  42. add(&_value, sizeof(Ty) );
  43. }
  44. uint32_t end()
  45. {
  46. mmix(m_hash, m_tail);
  47. mmix(m_hash, m_size);
  48. m_hash ^= m_hash >> 13;
  49. m_hash *= MURMUR_M;
  50. m_hash ^= m_hash >> 15;
  51. return m_hash;
  52. }
  53. private:
  54. void mixTail(const uint8_t*& _data, int& _len)
  55. {
  56. while( _len && ((_len<4) || m_count) )
  57. {
  58. m_tail |= (*_data++) << (m_count * 8);
  59. m_count++;
  60. _len--;
  61. if(m_count == 4)
  62. {
  63. mmix(m_hash, m_tail);
  64. m_tail = 0;
  65. m_count = 0;
  66. }
  67. }
  68. }
  69. uint32_t m_hash;
  70. uint32_t m_tail;
  71. uint32_t m_count;
  72. uint32_t m_size;
  73. };
  74. #undef MURMUR_M
  75. #undef MURMUR_R
  76. #undef mmix
  77. inline uint32_t hashMurmur2A(const void* _data, uint32_t _size)
  78. {
  79. HashMurmur2A murmur;
  80. murmur.begin();
  81. murmur.add(_data, (int)_size);
  82. return murmur.end();
  83. }
  84. template <typename Ty>
  85. inline uint32_t hashMurmur2A(const Ty& _data)
  86. {
  87. return hashMurmur2A(&_data, sizeof(Ty) );
  88. }
  89. } // namespace bx
  90. #endif // BX_HASH_H_HEADER_GUARD