github.com/GitbookIO/syncgroup@v0.0.0-20200915204659-4f0b2961ab10/quickhash/strhash.go (about)

     1  package quickhash
     2  
     3  import (
     4  	"reflect"
     5  	_ "runtime"
     6  	"unsafe" // required to use //go:linkname
     7  )
     8  
     9  // Fixed seed for deterministic outcomes
    10  const shSeed uint64 = 42
    11  
    12  // Modified from runtime/alg.go
    13  func rthash(ptr unsafe.Pointer, size int, seed uint64) uint64 {
    14  	if size == 0 {
    15  		return seed
    16  	}
    17  	// The runtime hasher only works on uintptr. For 64-bit
    18  	// architectures, we use the hasher directly. Otherwise,
    19  	// we use two parallel hashers on the lower and upper 32 bits.
    20  	if unsafe.Sizeof(uintptr(0)) == 8 {
    21  		return uint64(runtime_memhash(ptr, uintptr(seed), uintptr(size)))
    22  	}
    23  	lo := runtime_memhash(ptr, uintptr(seed), uintptr(size))
    24  	hi := runtime_memhash(ptr, uintptr(seed>>32), uintptr(size))
    25  	return uint64(hi)<<32 | uint64(lo)
    26  }
    27  
    28  //go:linkname runtime_memhash runtime.memhash
    29  //go:noescape
    30  func runtime_memhash(p unsafe.Pointer, seed, s uintptr) uintptr
    31  
    32  func StrHash(str string) uint64 {
    33  	hdr := (*reflect.StringHeader)(unsafe.Pointer(&str))
    34  	ptr := unsafe.Pointer(hdr.Data)
    35  	return uint64(rthash(ptr, len(str), shSeed))
    36  }
    37  
    38  func ByteHash(data []byte) uint64 {
    39  	return uint64(rthash(unsafe.Pointer(&data[0]), len(data), shSeed))
    40  }