github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/core/util/string.go (about) 1 package util 2 3 import ( 4 "fmt" 5 "os" 6 "strconv" 7 "time" 8 ) 9 10 const primeRK = 16777619 11 12 /* simple string hash used by Go strings package */ 13 func Hashstr(sep string) int { 14 hash := uint32(0) 15 for i := 0; i < len(sep); i++ { 16 hash = hash*primeRK + uint32(sep[i]) 17 } 18 return int(hash) 19 } 20 21 // util/StringHelper.java 22 23 /* 24 Poached from Guava: set a different salt/seed for each VM instance, 25 to frustrate hash key collision denial of service attacks, and to 26 catch any places that somehow rely on hash function/order across VM 27 instances: 28 */ 29 var GOOD_FAST_HASH_SEED = func() uint32 { 30 if prop := os.Getenv("tests_seed"); prop != "" { 31 // so if there is a test failure that relied on hash order, we 32 // remain reproducible based on the test seed: 33 if len(prop) > 8 { 34 prop = prop[len(prop)-8:] 35 } 36 n, err := strconv.ParseInt(prop, 16, 64) 37 if err != nil { 38 panic(err) 39 } 40 fmt.Printf("tests_seed=%v\n", uint32(n)) 41 return uint32(n) 42 } else { 43 return uint32(time.Now().Nanosecond()) 44 } 45 }() 46 47 /* Returns true iff the ref starts with the given prefix. Otherwise false. */ 48 func StartsWith(ref, prefix []byte) bool { 49 return sliceEquals(ref, prefix, 0) 50 } 51 52 func sliceEquals(sliceToTest, other []byte, pos int) bool { 53 panic("niy") 54 } 55 56 /* 57 Returns the MurmurHash3_x86_32 hash. 58 Original source/tests at https://github.com/yonik/java_util/ 59 */ 60 func MurmurHash3_x86_32(data []byte, seed uint32) uint32 { 61 c1, c2 := uint32(0xcc9e2d51), uint32(0x1b873593) 62 63 h1 := seed 64 roundedEnd := (len(data) & 0xfffffffc) // round down to 4 byte block 65 66 for i := 0; i < roundedEnd; i += 4 { 67 // little endian load order 68 k1 := uint32(data[i]) | (uint32(data[i+1]) << 8) | 69 (uint32(data[i+2]) << 16) | (uint32(data[i+3]) << 24) 70 k1 *= c1 71 k1 = rotateLeft(k1, 15) 72 k1 *= c2 73 74 h1 ^= k1 75 h1 = rotateLeft(h1, 13) 76 h1 = h1*5 + 0xe6546b64 77 } 78 79 // tail 80 k1 := uint32(0) 81 82 left := len(data) & 0x03 83 if left == 3 { 84 k1 = uint32(data[roundedEnd+2]) << 16 85 } 86 if left >= 2 { 87 k1 |= uint32(data[roundedEnd+1]) << 8 88 } 89 if left >= 1 { 90 k1 |= uint32(data[roundedEnd]) 91 k1 *= c1 92 k1 = rotateLeft(k1, 15) 93 k1 *= c2 94 h1 ^= k1 95 } 96 97 // finalization 98 h1 ^= uint32(len(data)) 99 100 // fmix(h1); 101 h1 ^= h1 >> 16 102 h1 *= 0x85ebca6b 103 h1 ^= h1 >> 13 104 h1 *= 0xc2b2ae35 105 h1 ^= h1 >> 16 106 107 return h1 108 } 109 110 func rotateLeft(n uint32, offset uint) uint32 { 111 mask := uint32(1<<(32-offset)) - 1 112 hi := (n & mask) << offset 113 low := (n - (n & mask)) >> (32 - offset) 114 return hi | low 115 }