// +build !safe // +build !appengine // +build !ppc64le // +build !mipsle // +build !ppc64be // +build !mips // +build !s390x package xxhash import ( "reflect" "unsafe" ) // Backend returns the current version of xxhash being used. const Backend = "GoUnsafe" // ChecksumString32S returns the checksum of the input data, without creating a copy, with the specific seed. func ChecksumString32S(s string, seed uint32) uint32 { if len(s) == 0 { return Checksum32S(nil, seed) } ss := (*reflect.StringHeader)(unsafe.Pointer(&s)) return Checksum32S((*[maxInt32]byte)(unsafe.Pointer(ss.Data))[:len(s):len(s)], seed) } func (xx *XXHash32) WriteString(s string) (int, error) { if len(s) == 0 { return 0, nil } ss := (*reflect.StringHeader)(unsafe.Pointer(&s)) return xx.Write((*[maxInt32]byte)(unsafe.Pointer(ss.Data))[:len(s):len(s)]) } // ChecksumString64S returns the checksum of the input data, without creating a copy, with the specific seed. func ChecksumString64S(s string, seed uint64) uint64 { if len(s) == 0 { return Checksum64S(nil, seed) } ss := (*reflect.StringHeader)(unsafe.Pointer(&s)) return Checksum64S((*[maxInt32]byte)(unsafe.Pointer(ss.Data))[:len(s):len(s)], seed) } func (xx *XXHash64) WriteString(s string) (int, error) { if len(s) == 0 { return 0, nil } ss := (*reflect.StringHeader)(unsafe.Pointer(&s)) return xx.Write((*[maxInt32]byte)(unsafe.Pointer(ss.Data))[:len(s):len(s)]) } //go:nocheckptr func checksum64(in []byte, seed uint64) uint64 { var ( wordsLen = len(in) >> 3 words = ((*[maxInt32 / 8]uint64)(unsafe.Pointer(&in[0])))[:wordsLen:wordsLen] v1, v2, v3, v4 = resetVs64(seed) h uint64 i int ) for ; i < len(words)-3; i += 4 { words := (*[4]uint64)(unsafe.Pointer(&words[i])) v1 = round64(v1, words[0]) v2 = round64(v2, words[1]) v3 = round64(v3, words[2]) v4 = round64(v4, words[3]) } h = rotl64_1(v1) + rotl64_7(v2) + rotl64_12(v3) + rotl64_18(v4) h = mergeRound64(h, v1) h = mergeRound64(h, v2) h = mergeRound64(h, v3) h = mergeRound64(h, v4) h += uint64(len(in)) for _, k := range words[i:] { h ^= round64(0, k) h = rotl64_27(h)*prime64x1 + prime64x4 } if in = in[wordsLen<<3 : len(in) : len(in)]; len(in) > 3 { words := (*[1]uint32)(unsafe.Pointer(&in[0])) h ^= uint64(words[0]) * prime64x1 h = rotl64_23(h)*prime64x2 + prime64x3 in = in[4:len(in):len(in)] } for _, b := range in { h ^= uint64(b) * prime64x5 h = rotl64_11(h) * prime64x1 } return mix64(h) } //go:nocheckptr func checksum64Short(in []byte, seed uint64) uint64 { var ( h = seed + prime64x5 + uint64(len(in)) i int ) if len(in) > 7 { var ( wordsLen = len(in) >> 3 words = ((*[maxInt32 / 8]uint64)(unsafe.Pointer(&in[0])))[:wordsLen:wordsLen] ) for i := range words { h ^= round64(0, words[i]) h = rotl64_27(h)*prime64x1 + prime64x4 } i = wordsLen << 3 } if in = in[i:len(in):len(in)]; len(in) > 3 { words := (*[1]uint32)(unsafe.Pointer(&in[0])) h ^= uint64(words[0]) * prime64x1 h = rotl64_23(h)*prime64x2 + prime64x3 in = in[4:len(in):len(in)] } for _, b := range in { h ^= uint64(b) * prime64x5 h = rotl64_11(h) * prime64x1 } return mix64(h) } func (xx *XXHash64) Write(in []byte) (n int, err error) { mem, idx := xx.mem[:], int(xx.memIdx) xx.ln, n = xx.ln+uint64(len(in)), len(in) if idx+len(in) < 32 { xx.memIdx += int8(copy(mem[idx:len(mem):len(mem)], in)) return } var ( v1, v2, v3, v4 = xx.v1, xx.v2, xx.v3, xx.v4 i int ) if d := 32 - int(idx); d > 0 && int(idx)+len(in) > 31 { copy(mem[idx:len(mem):len(mem)], in[:len(in):len(in)]) words := (*[4]uint64)(unsafe.Pointer(&mem[0])) v1 = round64(v1, words[0]) v2 = round64(v2, words[1]) v3 = round64(v3, words[2]) v4 = round64(v4, words[3]) if in, xx.memIdx = in[d:len(in):len(in)], 0; len(in) == 0 { goto RET } } for ; i < len(in)-31; i += 32 { words := (*[4]uint64)(unsafe.Pointer(&in[i])) v1 = round64(v1, words[0]) v2 = round64(v2, words[1]) v3 = round64(v3, words[2]) v4 = round64(v4, words[3]) } if len(in)-i != 0 { xx.memIdx += int8(copy(mem[xx.memIdx:len(mem):len(mem)], in[i:len(in):len(in)])) } RET: xx.v1, xx.v2, xx.v3, xx.v4 = v1, v2, v3, v4 return } func (xx *XXHash64) Sum64() (h uint64) { if seed := xx.seed; xx.ln > 31 { v1, v2, v3, v4 := xx.v1, xx.v2, xx.v3, xx.v4 h = rotl64_1(v1) + rotl64_7(v2) + rotl64_12(v3) + rotl64_18(v4) h = mergeRound64(h, v1) h = mergeRound64(h, v2) h = mergeRound64(h, v3) h = mergeRound64(h, v4) } else if seed == 0 { h = prime64x5 } else { h = seed + prime64x5 } h += uint64(xx.ln) if xx.memIdx == 0 { return mix64(h) } var ( in = xx.mem[:xx.memIdx:xx.memIdx] wordsLen = len(in) >> 3 words = ((*[maxInt32 / 8]uint64)(unsafe.Pointer(&in[0])))[:wordsLen:wordsLen] ) for _, k := range words { h ^= round64(0, k) h = rotl64_27(h)*prime64x1 + prime64x4 } if in = in[wordsLen<<3 : len(in) : len(in)]; len(in) > 3 { words := (*[1]uint32)(unsafe.Pointer(&in[0])) h ^= uint64(words[0]) * prime64x1 h = rotl64_23(h)*prime64x2 + prime64x3 in = in[4:len(in):len(in)] } for _, b := range in { h ^= uint64(b) * prime64x5 h = rotl64_11(h) * prime64x1 } return mix64(h) }