fnv1a.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #ifndef BOOST_HASH2_FNV1A_HPP_INCLUDED
  2. #define BOOST_HASH2_FNV1A_HPP_INCLUDED
  3. // Copyright 2017, 2018 Peter Dimov.
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // https://www.boost.org/LICENSE_1_0.txt
  6. //
  7. // FNV-1a
  8. //
  9. // https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
  10. #include <boost/hash2/detail/write.hpp>
  11. #include <boost/assert.hpp>
  12. #include <boost/config.hpp>
  13. #include <cstdint>
  14. #include <cstddef>
  15. namespace boost
  16. {
  17. namespace hash2
  18. {
  19. namespace detail
  20. {
  21. template<class T> struct fnv1a_const;
  22. template<> struct fnv1a_const<std::uint32_t>
  23. {
  24. static constexpr std::uint32_t basis = 0x811C9DC5ul;
  25. static constexpr std::uint32_t prime = 0x01000193ul;
  26. };
  27. template<> struct fnv1a_const<std::uint64_t>
  28. {
  29. static constexpr std::uint64_t basis = 0xCBF29CE484222325ull;
  30. static constexpr std::uint64_t prime = 0x00000100000001B3ull;
  31. };
  32. template<class T> class fnv1a
  33. {
  34. private:
  35. T st_ = fnv1a_const<T>::basis;
  36. public:
  37. typedef T result_type;
  38. constexpr fnv1a() = default;
  39. BOOST_CXX14_CONSTEXPR explicit fnv1a( std::uint64_t seed )
  40. {
  41. if( seed )
  42. {
  43. unsigned char tmp[ 8 ] = {};
  44. detail::write64le( tmp, seed );
  45. update( tmp, 8 );
  46. }
  47. }
  48. BOOST_CXX14_CONSTEXPR fnv1a( unsigned char const * p, std::size_t n )
  49. {
  50. if( n != 0 )
  51. {
  52. update( p, n );
  53. unsigned char tmp[ 4 ] = {};
  54. detail::write32le( tmp, static_cast<std::uint32_t>( n ) );
  55. update( tmp, 4 );
  56. }
  57. }
  58. fnv1a( void const * p, std::size_t n ): fnv1a( static_cast<unsigned char const*>( p ), n )
  59. {
  60. }
  61. BOOST_CXX14_CONSTEXPR void update( unsigned char const * p, std::size_t n )
  62. {
  63. T h = st_;
  64. for( std::size_t i = 0; i < n; ++i )
  65. {
  66. h ^= static_cast<T>( p[i] );
  67. h *= fnv1a_const<T>::prime;
  68. }
  69. st_ = h;
  70. }
  71. void update( void const * pv, std::size_t n )
  72. {
  73. unsigned char const* p = static_cast<unsigned char const*>( pv );
  74. update( p, n );
  75. }
  76. BOOST_CXX14_CONSTEXPR T result()
  77. {
  78. T r = st_;
  79. // advance as if by update( "\xFF", 1 ), to allow
  80. // multiple result() calls to generate a sequence
  81. // of distinct values
  82. st_ = ( st_ ^ 0xFF ) * fnv1a_const<T>::prime;
  83. return r;
  84. }
  85. };
  86. } // namespace detail
  87. class fnv1a_32: public detail::fnv1a<std::uint32_t>
  88. {
  89. public:
  90. constexpr fnv1a_32() = default;
  91. BOOST_CXX14_CONSTEXPR explicit fnv1a_32( std::uint64_t seed ): detail::fnv1a<std::uint32_t>( seed )
  92. {
  93. }
  94. BOOST_CXX14_CONSTEXPR fnv1a_32( unsigned char const * p, std::size_t n ): detail::fnv1a<std::uint32_t>( p, n )
  95. {
  96. }
  97. fnv1a_32( void const * p, std::size_t n ): detail::fnv1a<std::uint32_t>( p, n )
  98. {
  99. }
  100. };
  101. class fnv1a_64: public detail::fnv1a<std::uint64_t>
  102. {
  103. public:
  104. constexpr fnv1a_64() = default;
  105. BOOST_CXX14_CONSTEXPR explicit fnv1a_64( std::uint64_t seed ): detail::fnv1a<std::uint64_t>( seed )
  106. {
  107. }
  108. BOOST_CXX14_CONSTEXPR fnv1a_64( unsigned char const * p, std::size_t n ): detail::fnv1a<std::uint64_t>( p, n )
  109. {
  110. }
  111. fnv1a_64( void const * p, std::size_t n ): detail::fnv1a<std::uint64_t>( p, n )
  112. {
  113. }
  114. };
  115. } // namespace hash2
  116. } // namespace boost
  117. #endif // #ifndef BOOST_HASH2_FNV1A_HPP_INCLUDED