/
xxh32.go
120 lines (100 loc) · 2.09 KB
/
xxh32.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package xxhash
import (
"bytes"
"hash"
)
const (
prime32_1 = 0x9e3779b1
prime32_2 = 0x85ebca77
prime32_3 = 0xc2b2ae3d
prime32_4 = 0x27d4eb2f
prime32_5 = 0x165667b1
)
type digest32 struct {
seed, v1, v2, v3, v4 uint32
buf *bytes.Buffer
totalLen int
rbuf [4]byte
}
func (d *digest32) read32() (v uint32) {
d.buf.Read(d.rbuf[:4])
for i := 0; i < 4; i++ {
v |= uint32(d.rbuf[i]) << (8 * uint(i))
}
return
}
func (d *digest32) read8() uint32 {
d.buf.Read(d.rbuf[:1])
return uint32(d.rbuf[0])
}
// XXH32 returns new hash.Hash32
func XXH32(seed uint32) hash.Hash32 {
d := &digest32{seed: seed, buf: new(bytes.Buffer)}
d.Reset()
return d
}
func (d *digest32) Write(p []byte) (n int, err error) {
n, err = d.buf.Write(p)
if err != nil {
return 0, err
}
d.totalLen += n
for d.buf.Len() >= 16 {
d.v1 = round32(d.v1, d.read32())
d.v2 = round32(d.v2, d.read32())
d.v3 = round32(d.v3, d.read32())
d.v4 = round32(d.v4, d.read32())
}
return n, nil
}
func (d *digest32) Sum(b []byte) []byte {
v := d.Sum32()
for i := d.Size() - 1; i >= 0; i-- {
b = append(b, byte(v>>uint(8*i)))
}
return b
}
func (d *digest32) Reset() {
d.v1 = d.seed + prime32_1 + prime32_2
d.v2 = d.seed + prime32_2
d.v3 = d.seed
d.v4 = d.seed - prime32_1
d.buf.Reset()
d.totalLen = 0
}
func (d *digest32) Size() int {
return 4
}
func (d *digest32) BlockSize() int {
return 16
}
func (d *digest32) Sum32() uint32 {
var sum uint32
if d.totalLen >= 16 {
sum = rotl32(d.v1, 1) + rotl32(d.v2, 7) + rotl32(d.v3, 12) + rotl32(d.v4, 18)
} else {
sum = d.v3 + prime32_5
}
sum += uint32(d.totalLen)
for d.buf.Len() >= 4 {
sum += d.read32() * prime32_3
sum = rotl32(sum, 17) * prime32_4
}
for d.buf.Len() >= 1 {
sum += d.read8() * prime32_5
sum = rotl32(sum, 11) * prime32_1
}
sum ^= sum >> 15
sum *= prime32_2
sum ^= sum >> 13
sum *= prime32_3
sum ^= sum >> 16
return sum
}
func round32(acc, val uint32) uint32 {
acc += val * prime32_2
return rotl32(acc, 13) * prime32_1
}
func rotl32(x uint32, r uint) uint32 {
return (x << r) | (x >> (32 - r))
}