github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/bytes/bytes_amd64.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package bytes 6 7 //go:noescape 8 9 // indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s. 10 // indexShortStr requires 2 <= len(c) <= shortStringLen 11 func indexShortStr(s, c []byte) int // ../runtime/asm_$GOARCH.s 12 func supportAVX2() bool // ../runtime/asm_$GOARCH.s 13 14 var shortStringLen int 15 16 func init() { 17 if supportAVX2() { 18 shortStringLen = 63 19 } else { 20 shortStringLen = 31 21 } 22 } 23 24 // Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. 25 func Index(s, sep []byte) int { 26 n := len(sep) 27 switch { 28 case n == 0: 29 return 0 30 case n == 1: 31 return IndexByte(s, sep[0]) 32 case n <= shortStringLen: 33 return indexShortStr(s, sep) 34 case n == len(s): 35 if Equal(sep, s) { 36 return 0 37 } 38 return -1 39 case n > len(s): 40 return -1 41 } 42 // Rabin-Karp search 43 hashsep, pow := hashStr(sep) 44 var h uint32 45 for i := 0; i < n; i++ { 46 h = h*primeRK + uint32(s[i]) 47 } 48 if h == hashsep && Equal(s[:n], sep) { 49 return 0 50 } 51 for i := n; i < len(s); { 52 h *= primeRK 53 h += uint32(s[i]) 54 h -= pow * uint32(s[i-n]) 55 i++ 56 if h == hashsep && Equal(s[i-n:i], sep) { 57 return i - n 58 } 59 } 60 return -1 61 } 62 63 // primeRK is the prime base used in Rabin-Karp algorithm. 64 const primeRK = 16777619 65 66 // hashStr returns the hash and the appropriate multiplicative 67 // factor for use in Rabin-Karp algorithm. 68 func hashStr(sep []byte) (uint32, uint32) { 69 hash := uint32(0) 70 for i := 0; i < len(sep); i++ { 71 hash = hash*primeRK + uint32(sep[i]) 72 } 73 var pow, sq uint32 = 1, primeRK 74 for i := len(sep); i > 0; i >>= 1 { 75 if i&1 != 0 { 76 pow *= sq 77 } 78 sq *= sq 79 } 80 return hash, pow 81 }