github.com/kelleygo/clashcore@v1.0.2/common/murmur3/murmur32.go (about) 1 package murmur3 2 3 // https://github.com/spaolacci/murmur3/blob/master/murmur32.go 4 5 import ( 6 "hash" 7 "math/bits" 8 "unsafe" 9 ) 10 11 // Make sure interfaces are correctly implemented. 12 var ( 13 _ hash.Hash32 = new(digest32) 14 _ bmixer = new(digest32) 15 ) 16 17 const ( 18 c1_32 uint32 = 0xcc9e2d51 19 c2_32 uint32 = 0x1b873593 20 ) 21 22 // digest32 represents a partial evaluation of a 32 bites hash. 23 type digest32 struct { 24 digest 25 h1 uint32 // Unfinalized running hash. 26 } 27 28 // New32 returns new 32-bit hasher 29 func New32() hash.Hash32 { return New32WithSeed(0) } 30 31 // New32WithSeed returns new 32-bit hasher set with explicit seed value 32 func New32WithSeed(seed uint32) hash.Hash32 { 33 d := new(digest32) 34 d.seed = seed 35 d.bmixer = d 36 d.Reset() 37 return d 38 } 39 40 func (d *digest32) Size() int { return 4 } 41 42 func (d *digest32) reset() { d.h1 = d.seed } 43 44 func (d *digest32) Sum(b []byte) []byte { 45 h := d.Sum32() 46 return append(b, byte(h>>24), byte(h>>16), byte(h>>8), byte(h)) 47 } 48 49 // Digest as many blocks as possible. 50 func (d *digest32) bmix(p []byte) (tail []byte) { 51 h1 := d.h1 52 53 nblocks := len(p) / 4 54 for i := 0; i < nblocks; i++ { 55 k1 := *(*uint32)(unsafe.Pointer(&p[i*4])) 56 57 k1 *= c1_32 58 k1 = bits.RotateLeft32(k1, 15) 59 k1 *= c2_32 60 61 h1 ^= k1 62 h1 = bits.RotateLeft32(h1, 13) 63 h1 = h1*4 + h1 + 0xe6546b64 64 } 65 d.h1 = h1 66 return p[nblocks*d.Size():] 67 } 68 69 func (d *digest32) Sum32() (h1 uint32) { 70 h1 = d.h1 71 72 var k1 uint32 73 switch len(d.tail) & 3 { 74 case 3: 75 k1 ^= uint32(d.tail[2]) << 16 76 fallthrough 77 case 2: 78 k1 ^= uint32(d.tail[1]) << 8 79 fallthrough 80 case 1: 81 k1 ^= uint32(d.tail[0]) 82 k1 *= c1_32 83 k1 = bits.RotateLeft32(k1, 15) 84 k1 *= c2_32 85 h1 ^= k1 86 } 87 88 h1 ^= uint32(d.clen) 89 90 h1 ^= h1 >> 16 91 h1 *= 0x85ebca6b 92 h1 ^= h1 >> 13 93 h1 *= 0xc2b2ae35 94 h1 ^= h1 >> 16 95 96 return h1 97 } 98 99 func Sum32(data []byte) uint32 { return Sum32WithSeed(data, 0) } 100 101 func Sum32WithSeed(data []byte, seed uint32) uint32 { 102 h1 := seed 103 104 nblocks := len(data) / 4 105 for i := 0; i < nblocks; i++ { 106 k1 := *(*uint32)(unsafe.Pointer(&data[i*4])) 107 108 k1 *= c1_32 109 k1 = bits.RotateLeft32(k1, 15) 110 k1 *= c2_32 111 112 h1 ^= k1 113 h1 = bits.RotateLeft32(h1, 13) 114 h1 = h1*4 + h1 + 0xe6546b64 115 } 116 117 tail := data[nblocks*4:] 118 119 var k1 uint32 120 switch len(tail) & 3 { 121 case 3: 122 k1 ^= uint32(tail[2]) << 16 123 fallthrough 124 case 2: 125 k1 ^= uint32(tail[1]) << 8 126 fallthrough 127 case 1: 128 k1 ^= uint32(tail[0]) 129 k1 *= c1_32 130 k1 = bits.RotateLeft32(k1, 15) 131 k1 *= c2_32 132 h1 ^= k1 133 } 134 135 h1 ^= uint32(len(data)) 136 137 h1 ^= h1 >> 16 138 h1 *= 0x85ebca6b 139 h1 ^= h1 >> 13 140 h1 *= 0xc2b2ae35 141 h1 ^= h1 >> 16 142 143 return h1 144 }