package zstd
import (
"encoding/binary"
"math/bits"
)
const (
xxhPrime64c1 = 0x9e3779b185ebca87
xxhPrime64c2 = 0xc2b2ae3d27d4eb4f
xxhPrime64c3 = 0x165667b19e3779f9
xxhPrime64c4 = 0x85ebca77c2b2ae63
xxhPrime64c5 = 0x27d4eb2f165667c5
)
type xxhash64 struct {
len uint64
v [4 ]uint64
buf [32 ]byte
cnt int
}
func (xh *xxhash64 ) reset () {
xh .len = 0
xh .v [0 ] = xxhPrime64c1
xh .v [0 ] += xxhPrime64c2
xh .v [1 ] = xxhPrime64c2
xh .v [2 ] = 0
xh .v [3 ] = xxhPrime64c1
xh .v [3 ] = -xh .v [3 ]
for i := range xh .buf {
xh .buf [i ] = 0
}
xh .cnt = 0
}
func (xh *xxhash64 ) update (b []byte ) {
xh .len += uint64 (len (b ))
if xh .cnt +len (b ) < len (xh .buf ) {
copy (xh .buf [xh .cnt :], b )
xh .cnt += len (b )
return
}
if xh .cnt > 0 {
n := copy (xh .buf [xh .cnt :], b )
b = b [n :]
xh .v [0 ] = xh .round (xh .v [0 ], binary .LittleEndian .Uint64 (xh .buf [:]))
xh .v [1 ] = xh .round (xh .v [1 ], binary .LittleEndian .Uint64 (xh .buf [8 :]))
xh .v [2 ] = xh .round (xh .v [2 ], binary .LittleEndian .Uint64 (xh .buf [16 :]))
xh .v [3 ] = xh .round (xh .v [3 ], binary .LittleEndian .Uint64 (xh .buf [24 :]))
xh .cnt = 0
}
for len (b ) >= 32 {
xh .v [0 ] = xh .round (xh .v [0 ], binary .LittleEndian .Uint64 (b ))
xh .v [1 ] = xh .round (xh .v [1 ], binary .LittleEndian .Uint64 (b [8 :]))
xh .v [2 ] = xh .round (xh .v [2 ], binary .LittleEndian .Uint64 (b [16 :]))
xh .v [3 ] = xh .round (xh .v [3 ], binary .LittleEndian .Uint64 (b [24 :]))
b = b [32 :]
}
if len (b ) > 0 {
copy (xh .buf [:], b )
xh .cnt = len (b )
}
}
func (xh *xxhash64 ) digest () uint64 {
var h64 uint64
if xh .len < 32 {
h64 = xh .v [2 ] + xxhPrime64c5
} else {
h64 = bits .RotateLeft64 (xh .v [0 ], 1 ) +
bits .RotateLeft64 (xh .v [1 ], 7 ) +
bits .RotateLeft64 (xh .v [2 ], 12 ) +
bits .RotateLeft64 (xh .v [3 ], 18 )
h64 = xh .mergeRound (h64 , xh .v [0 ])
h64 = xh .mergeRound (h64 , xh .v [1 ])
h64 = xh .mergeRound (h64 , xh .v [2 ])
h64 = xh .mergeRound (h64 , xh .v [3 ])
}
h64 += xh .len
len := xh .len
len &= 31
buf := xh .buf [:]
for len >= 8 {
k1 := xh .round (0 , binary .LittleEndian .Uint64 (buf ))
buf = buf [8 :]
h64 ^= k1
h64 = bits .RotateLeft64 (h64 , 27 )*xxhPrime64c1 + xxhPrime64c4
len -= 8
}
if len >= 4 {
h64 ^= uint64 (binary .LittleEndian .Uint32 (buf )) * xxhPrime64c1
buf = buf [4 :]
h64 = bits .RotateLeft64 (h64 , 23 )*xxhPrime64c2 + xxhPrime64c3
len -= 4
}
for len > 0 {
h64 ^= uint64 (buf [0 ]) * xxhPrime64c5
buf = buf [1 :]
h64 = bits .RotateLeft64 (h64 , 11 ) * xxhPrime64c1
len --
}
h64 ^= h64 >> 33
h64 *= xxhPrime64c2
h64 ^= h64 >> 29
h64 *= xxhPrime64c3
h64 ^= h64 >> 32
return h64
}
func (xh *xxhash64 ) round (v , n uint64 ) uint64 {
v += n * xxhPrime64c2
v = bits .RotateLeft64 (v , 31 )
v *= xxhPrime64c1
return v
}
func (xh *xxhash64 ) mergeRound (v , n uint64 ) uint64 {
n = xh .round (0 , n )
v ^= n
v = v *xxhPrime64c1 + xxhPrime64c4
return v
}
The pages are generated with Golds v0.7.0-preview . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .