DAW JSON Link
Loading...
Searching...
No Matches
daw_murmur3.h
Go to the documentation of this file.
1// Copyright (c) Darrell Wright
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
5//
6// Official repository: https://github.com/beached/daw_json_link
7//
8
9#pragma once
10
11#include "version.h"
12
13#include <daw/daw_do_n.h>
14#include <daw/daw_endian.h>
15#include <daw/daw_string_view.h>
16#include <daw/daw_uint_buffer.h>
17
18#include <cstddef>
19#include <cstdint>
20#include <iterator>
21
22namespace daw {
23 using json_name_hash_t = daw::UInt64;
24
25 namespace murmur3_details {
26 [[nodiscard]] DAW_ATTRIB_FLATINLINE static constexpr daw::UInt32
27 murmur3_32_scramble( daw::UInt32 k ) {
28 using prime1 = daw::constant<0xcc9e'2d51_u32>;
29 using prime2 = daw::constant<0x1b87'3593_u32>;
30 k *= prime1::value;
31 k = rotate_left<15>( k );
32 k *= prime2::value;
33 return k;
34 }
35 } // namespace murmur3_details
36
37 template<typename T>
38 inline constexpr T fnv1a_basis_v = daw::undefined_v<T>;
39 template<typename T>
40 inline constexpr T fnv1a_prime_v = daw::undefined_v<T>;
41
42 template<>
43 inline constexpr auto fnv1a_basis_v<daw::UInt32> = 0x811c'9dc5_u32;
44 template<>
45 inline constexpr auto fnv1a_prime_v<daw::UInt32> = 0x0100'0193_u32;
46
47 template<>
48 inline constexpr auto fnv1a_basis_v<daw::UInt64> = 0xcbf2'9ce4'8422'2325_u64;
49 template<>
50 inline constexpr auto fnv1a_prime_v<daw::UInt64> = 0x0000'0100'0000'01b3_u64;
51
52 // Unrolled fnv1a to N elements
53 template<std::size_t N, typename Hash>
54 [[nodiscard]] DAW_ATTRIB_INLINE static constexpr auto
55 fnv1a_N( daw::not_null<char const *> first,
56 Hash hash = fnv1a_basis_v<Hash> ) {
57 daw::algorithm::do_n_arg<N>( [&]( std::size_t n ) {
58 hash ^= static_cast<Hash>( static_cast<unsigned char>( first[n] ) );
59 hash *= fnv1a_prime_v<Hash>;
60 } );
61 return hash;
62 }
63
64 template<typename Hash, bool expect_long_strings, typename StringView>
65 [[nodiscard]] static constexpr Hash fnv1a( StringView key ) {
66 static_assert( daw::traits::is_string_view_like_v<StringView>,
67 "Can only pass contiguous character ranges to fnv1a" );
68 std::size_t len = std::size( key );
69 daw::not_null ptr = std::data( key );
70 auto hash = fnv1a_basis_v<Hash>;
71 if constexpr( expect_long_strings ) {
72 while( DAW_UNLIKELY( len >= 8 ) ) {
73 hash = fnv1a_N<8>( ptr, hash );
74 len -= 8;
75 ptr += 8;
76 }
77 if( len >= 4 ) {
78 hash = fnv1a_N<4>( ptr, hash );
79 len -= 4;
80 ptr += 4;
81 }
82 }
83 for( std::size_t n = 0; n < len; ++n ) {
84 hash ^= static_cast<unsigned char>( ptr[n] );
85 hash *= fnv1a_prime_v<Hash>;
86 }
87 return hash;
88 }
89
90 template<bool expect_long_strings>
91 [[nodiscard]] DAW_ATTRIB_INLINE static constexpr json_name_hash_t
92 name_hash( daw::string_view key ) {
93 if( auto const Sz = std::size( key );
94 DAW_LIKELY( Sz <= sizeof( json_name_hash_t ) ) ) {
95 auto result = json_name_hash_t{ };
96 auto const *ptr = std::data( key );
97 for( std::size_t n = 0; n < Sz; ++n ) {
98 result <<= 8U;
99 result |= static_cast<unsigned char>( ptr[n] );
100 }
101 return result; // * fnv1a_prime_v<json_name_hash_t>; // mix it up with an
102 // fnv1a prime
103 }
104 return fnv1a<json_name_hash_t, expect_long_strings>( key );
105 }
106
107 template<typename StringView>
108 [[nodiscard]] static constexpr daw::UInt32
109 murmur3_32( StringView key, std::uint32_t seed = 0 ) {
110 static_assert( daw::traits::is_string_view_like_v<StringView>,
111 "Can only pass contiguous character ranges to fnv1a" );
112 daw::UInt32 h = to_uint32( seed );
113 daw::UInt32 k = 0_u32;
114 char const *first = std::data( key );
115 char const *const last = daw::data_end( key );
116 while( ( last - first ) >= 4 ) {
117 // Here is a source of differing results across endianness.
118 // A swap here has no effects on hash properties though.
119 k = daw::to_uint32_buffer( first );
120 first += 4;
121 h ^= murmur3_details::murmur3_32_scramble( k );
122 h = rotate_left<13>( h );
123 h = h * 5 + 0xe654'6b64_u32;
124 }
125
126 // Anything left over
127 k = 0_u32;
128 for( auto i = ( last - first ); i > 0; --i ) {
129 k <<= 8U;
130 k |= static_cast<unsigned char>( first[i - 1] );
131 }
132
133 h ^= murmur3_details::murmur3_32_scramble( k );
134
135 h ^= to_uint32( std::size( key ) );
136 h ^= h >> 16U;
137 h *= 0x85eb'ca6b_u32;
138 h ^= h >> 13U;
139 h *= 0xc2b2'ae35_u32;
140 h ^= h >> 16U;
141 return h;
142 }
143} // namespace daw
constexpr T fnv1a_prime_v
Definition daw_murmur3.h:40
static constexpr daw::UInt32 murmur3_32(StringView key, std::uint32_t seed=0)
static DAW_ATTRIB_INLINE constexpr auto fnv1a_N(daw::not_null< char const * > first, Hash hash=fnv1a_basis_v< Hash >)
Definition daw_murmur3.h:55
daw::UInt64 json_name_hash_t
Definition daw_murmur3.h:23
constexpr T fnv1a_basis_v
Definition daw_murmur3.h:38
static DAW_ATTRIB_INLINE constexpr json_name_hash_t name_hash(daw::string_view key)
Definition daw_murmur3.h:92
static constexpr Hash fnv1a(StringView key)
Definition daw_murmur3.h:65