github.com/Nigel2392/go-datastructures@v1.1.5/fastcompare.go (about) 1 package datastructures 2 3 import "unsafe" 4 5 // Inspiration from https://github.com/golang/go/blob/master/src/runtime/map_faststr.go 6 // 7 //go:linkname memequal runtime.memequal 8 func memequal(a, b unsafe.Pointer, n uintptr) bool 9 10 // Inspiration from https://github.com/golang/go/blob/master/src/runtime/map_faststr.go 11 type _string struct { 12 str unsafe.Pointer 13 len int 14 } 15 16 type stringType interface { 17 ~string 18 } 19 20 // A fast string comparison function. 21 // 22 // Can compare any type which is a direct or indirect subtype of string. 23 // 24 // This function is based on the map_faststr.go implementation in the Go runtime. 25 // 26 // Returns true if the strings are equal, false otherwise. 27 func FastStrCmp[T stringType](a, b T) bool { 28 var ( 29 aStr = (*_string)(unsafe.Pointer(&a)) 30 bStr = (*_string)(unsafe.Pointer(&b)) 31 ) 32 if aStr.len != bStr.len { 33 return false 34 } 35 // if len < 32 a lot of comparisons wont matter, or so the documentation says. 36 if aStr.len < 32 { 37 return aStr.str == bStr.str || memequal(aStr.str, bStr.str, uintptr(aStr.len)) 38 } 39 40 // Check if the first 4 bytes are equal 41 if *((*[4]byte)(unsafe.Pointer(aStr.str))) != *((*[4]byte)(unsafe.Pointer(bStr.str))) { 42 return false 43 } 44 // Check if the last 4 bytes are equal 45 if *((*[4]byte)(unsafe.Pointer(uintptr(aStr.str) + uintptr(aStr.len) - 4))) != *((*[4]byte)(unsafe.Pointer(uintptr(bStr.str) + uintptr(bStr.len) - 4))) { 46 return false 47 } 48 49 // compare the whole string 50 return memequal(aStr.str, bStr.str, uintptr(aStr.len)) 51 } 52 53 func FastStrHash[T stringType](s T) uint64 { 54 // return murmurHash3_64(s, 0) 55 var ( 56 str = (*_string)(unsafe.Pointer(&s)) 57 h = uint64(0) 58 ) 59 for i := 0; i < str.len; i++ { 60 h = 63*h + uint64(*(*byte)(unsafe.Pointer(uintptr(str.str) + uintptr(i)))) 61 } 62 return h 63 }