Skip to content

Commit 4d8db00

Browse files
committed
all: use bytes.Cut, strings.Cut
Many uses of Index/IndexByte/IndexRune/Split/SplitN can be written more clearly using the new Cut functions. Do that. Also rewrite to other functions if that's clearer. For #46336. Change-Id: I68d024716ace41a57a8bf74455c62279bde0f448 Reviewed-on: https://go-review.googlesource.com/c/go/+/351711 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
1 parent 8e36ab0 commit 4d8db00

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+356
-577
lines changed

misc/cgo/errors/errors_test.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,13 @@ func check(t *testing.T, file string) {
3636
continue
3737
}
3838

39-
frags := bytes.SplitAfterN(line, []byte("ERROR HERE: "), 2)
40-
if len(frags) == 1 {
39+
_, frag, ok := bytes.Cut(line, []byte("ERROR HERE: "))
40+
if !ok {
4141
continue
4242
}
43-
frag := fmt.Sprintf(":%d:.*%s", i+1, frags[1])
44-
re, err := regexp.Compile(frag)
43+
re, err := regexp.Compile(fmt.Sprintf(":%d:.*%s", i+1, frag))
4544
if err != nil {
46-
t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frags[1])
45+
t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frag)
4746
continue
4847
}
4948
errors = append(errors, re)

misc/cgo/testcshared/cshared_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ func adbRun(t *testing.T, env []string, adbargs ...string) string {
200200
args := append(adbCmd(), "exec-out")
201201
// Propagate LD_LIBRARY_PATH to the adb shell invocation.
202202
for _, e := range env {
203-
if strings.Index(e, "LD_LIBRARY_PATH=") != -1 {
203+
if strings.Contains(e, "LD_LIBRARY_PATH=") {
204204
adbargs = append([]string{e}, adbargs...)
205205
break
206206
}
@@ -326,7 +326,7 @@ func createHeaders() error {
326326
base, name := filepath.Split(args[0])
327327
args[0] = filepath.Join(base, "llvm-dlltool")
328328
var machine string
329-
switch strings.SplitN(name, "-", 2)[0] {
329+
switch prefix, _, _ := strings.Cut(name, "-"); prefix {
330330
case "i686":
331331
machine = "i386"
332332
case "x86_64":

misc/cgo/testsanitizers/cc_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ func (c *config) checkCSanitizer() (skip bool, err error) {
344344
if os.IsNotExist(err) {
345345
return true, fmt.Errorf("%#q failed to produce executable: %v", strings.Join(cmd.Args, " "), err)
346346
}
347-
snippet := bytes.SplitN(out, []byte{'\n'}, 2)[0]
347+
snippet, _, _ := bytes.Cut(out, []byte("\n"))
348348
return true, fmt.Errorf("%#q generated broken executable: %v\n%s", strings.Join(cmd.Args, " "), err, snippet)
349349
}
350350

misc/ios/go_ios_exec.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,8 @@ func runOnDevice(appdir string) error {
148148
// Device IDs as listed with ios-deploy -c.
149149
deviceID = os.Getenv("GOIOS_DEVICE_ID")
150150

151-
parts := strings.SplitN(appID, ".", 2)
152-
if len(parts) == 2 {
153-
bundleID = parts[1]
151+
if _, id, ok := strings.Cut(appID, "."); ok {
152+
bundleID = id
154153
}
155154

156155
if err := signApp(appdir); err != nil {
@@ -291,11 +290,10 @@ func findDevImage() (string, error) {
291290
var iosVer, buildVer string
292291
lines := bytes.Split(out, []byte("\n"))
293292
for _, line := range lines {
294-
spl := bytes.SplitN(line, []byte(": "), 2)
295-
if len(spl) != 2 {
293+
key, val, ok := strings.Cut(string(line), ": ")
294+
if !ok {
296295
continue
297296
}
298-
key, val := string(spl[0]), string(spl[1])
299297
switch key {
300298
case "ProductVersion":
301299
iosVer = val

misc/linkcheck/linkcheck.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,8 @@ func crawl(url string, sourceURL string) {
8181
}
8282
mu.Lock()
8383
defer mu.Unlock()
84-
var frag string
85-
if i := strings.Index(url, "#"); i >= 0 {
86-
frag = url[i+1:]
87-
url = url[:i]
84+
if u, frag, ok := strings.Cut(url, "#"); ok {
85+
url = u
8886
if frag != "" {
8987
uf := urlFrag{url, frag}
9088
neededFrags[uf] = append(neededFrags[uf], sourceURL)

src/archive/tar/strconv.go

+12-31
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414

1515
// hasNUL reports whether the NUL character exists within s.
1616
func hasNUL(s string) bool {
17-
return strings.IndexByte(s, 0) >= 0
17+
return strings.Contains(s, "\x00")
1818
}
1919

2020
// isASCII reports whether the input is an ASCII C-style string.
@@ -201,10 +201,7 @@ func parsePAXTime(s string) (time.Time, error) {
201201
const maxNanoSecondDigits = 9
202202

203203
// Split string into seconds and sub-seconds parts.
204-
ss, sn := s, ""
205-
if pos := strings.IndexByte(s, '.'); pos >= 0 {
206-
ss, sn = s[:pos], s[pos+1:]
207-
}
204+
ss, sn, _ := strings.Cut(s, ".")
208205

209206
// Parse the seconds.
210207
secs, err := strconv.ParseInt(ss, 10, 64)
@@ -254,48 +251,32 @@ func formatPAXTime(ts time.Time) (s string) {
254251
// return the remainder as r.
255252
func parsePAXRecord(s string) (k, v, r string, err error) {
256253
// The size field ends at the first space.
257-
sp := strings.IndexByte(s, ' ')
258-
if sp == -1 {
254+
nStr, rest, ok := strings.Cut(s, " ")
255+
if !ok {
259256
return "", "", s, ErrHeader
260257
}
261258

262259
// Parse the first token as a decimal integer.
263-
n, perr := strconv.ParseInt(s[:sp], 10, 0) // Intentionally parse as native int
264-
if perr != nil || n < 5 || int64(len(s)) < n {
260+
n, perr := strconv.ParseInt(nStr, 10, 0) // Intentionally parse as native int
261+
if perr != nil || n < 5 || n > int64(len(s)) {
265262
return "", "", s, ErrHeader
266263
}
267-
268-
afterSpace := int64(sp + 1)
269-
beforeLastNewLine := n - 1
270-
// In some cases, "length" was perhaps padded/malformed, and
271-
// trying to index past where the space supposedly is goes past
272-
// the end of the actual record.
273-
// For example:
274-
// "0000000000000000000000000000000030 mtime=1432668921.098285006\n30 ctime=2147483649.15163319"
275-
// ^ ^
276-
// | |
277-
// | afterSpace=35
278-
// |
279-
// beforeLastNewLine=29
280-
// yet indexOf(firstSpace) MUST BE before endOfRecord.
281-
//
282-
// See https://golang.org/issues/40196.
283-
if afterSpace >= beforeLastNewLine {
264+
n -= int64(len(nStr) + 1) // convert from index in s to index in rest
265+
if n <= 0 {
284266
return "", "", s, ErrHeader
285267
}
286268

287269
// Extract everything between the space and the final newline.
288-
rec, nl, rem := s[afterSpace:beforeLastNewLine], s[beforeLastNewLine:n], s[n:]
270+
rec, nl, rem := rest[:n-1], rest[n-1:n], rest[n:]
289271
if nl != "\n" {
290272
return "", "", s, ErrHeader
291273
}
292274

293275
// The first equals separates the key from the value.
294-
eq := strings.IndexByte(rec, '=')
295-
if eq == -1 {
276+
k, v, ok = strings.Cut(rec, "=")
277+
if !ok {
296278
return "", "", s, ErrHeader
297279
}
298-
k, v = rec[:eq], rec[eq+1:]
299280

300281
if !validPAXRecord(k, v) {
301282
return "", "", s, ErrHeader
@@ -333,7 +314,7 @@ func formatPAXRecord(k, v string) (string, error) {
333314
// for the PAX version of the USTAR string fields.
334315
// The key must not contain an '=' character.
335316
func validPAXRecord(k, v string) bool {
336-
if k == "" || strings.IndexByte(k, '=') >= 0 {
317+
if k == "" || strings.Contains(k, "=") {
337318
return false
338319
}
339320
switch k {

src/archive/tar/writer_test.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -988,9 +988,7 @@ func TestIssue12594(t *testing.T) {
988988
var blk block
989989
copy(blk[:], b.Bytes())
990990
prefix := string(blk.toUSTAR().prefix())
991-
if i := strings.IndexByte(prefix, 0); i >= 0 {
992-
prefix = prefix[:i] // Truncate at the NUL terminator
993-
}
991+
prefix, _, _ = strings.Cut(prefix, "\x00") // Truncate at the NUL terminator
994992
if blk.getFormat() == FormatGNU && len(prefix) > 0 && strings.HasPrefix(name, prefix) {
995993
t.Errorf("test %d, found prefix in GNU format: %s", i, prefix)
996994
}

src/archive/zip/writer_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ func TestWriterDirAttributes(t *testing.T) {
362362
}
363363

364364
binary.LittleEndian.PutUint32(sig[:], uint32(dataDescriptorSignature))
365-
if bytes.Index(b, sig[:]) != -1 {
365+
if bytes.Contains(b, sig[:]) {
366366
t.Error("there should be no data descriptor")
367367
}
368368
}

src/cmd/doc/dirs.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,7 @@ func findCodeRoots() []Dir {
221221
cmd.Stderr = os.Stderr
222222
out, _ := cmd.Output()
223223
for _, line := range strings.Split(string(out), "\n") {
224-
i := strings.Index(line, "\t")
225-
if i < 0 {
226-
continue
227-
}
228-
path, dir := line[:i], line[i+1:]
224+
path, dir, _ := strings.Cut(line, "\t")
229225
if dir != "" {
230226
list = append(list, Dir{importPath: path, dir: dir, inModule: true})
231227
}

src/cmd/doc/pkg.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,7 @@ func (pkg *Package) oneLineNodeDepth(node ast.Node, depth int) string {
315315
recv = "(" + recv + ") "
316316
}
317317
fnc := pkg.oneLineNodeDepth(n.Type, depth)
318-
if strings.Index(fnc, "func") == 0 {
319-
fnc = fnc[4:]
320-
}
318+
fnc = strings.TrimPrefix(fnc, "func")
321319
return fmt.Sprintf("func %s%s%s", recv, name, fnc)
322320

323321
case *ast.TypeSpec:

src/cmd/fix/typecheck.go

+7-11
Original file line numberDiff line numberDiff line change
@@ -544,8 +544,8 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a
544544
if strings.HasPrefix(t, "[") || strings.HasPrefix(t, "map[") {
545545
// Lazy: assume there are no nested [] in the array
546546
// length or map key type.
547-
if i := strings.Index(t, "]"); i >= 0 {
548-
typeof[n] = t[i+1:]
547+
if _, elem, ok := strings.Cut(t, "]"); ok {
548+
typeof[n] = elem
549549
}
550550
}
551551

@@ -575,8 +575,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a
575575
t := expand(typeof[n])
576576
if strings.HasPrefix(t, "[") { // array or slice
577577
// Lazy: assume there are no nested [] in the array length.
578-
if i := strings.Index(t, "]"); i >= 0 {
579-
et := t[i+1:]
578+
if _, et, ok := strings.Cut(t, "]"); ok {
580579
for _, e := range n.Elts {
581580
if kv, ok := e.(*ast.KeyValueExpr); ok {
582581
e = kv.Value
@@ -589,8 +588,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a
589588
}
590589
if strings.HasPrefix(t, "map[") { // map
591590
// Lazy: assume there are no nested [] in the map key type.
592-
if i := strings.Index(t, "]"); i >= 0 {
593-
kt, vt := t[4:i], t[i+1:]
591+
if kt, vt, ok := strings.Cut(t[len("map["):], "]"); ok {
594592
for _, e := range n.Elts {
595593
if kv, ok := e.(*ast.KeyValueExpr); ok {
596594
if typeof[kv.Key] == "" {
@@ -629,12 +627,10 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a
629627
key, value = "int", "rune"
630628
} else if strings.HasPrefix(t, "[") {
631629
key = "int"
632-
if i := strings.Index(t, "]"); i >= 0 {
633-
value = t[i+1:]
634-
}
630+
_, value, _ = strings.Cut(t, "]")
635631
} else if strings.HasPrefix(t, "map[") {
636-
if i := strings.Index(t, "]"); i >= 0 {
637-
key, value = t[4:i], t[i+1:]
632+
if k, v, ok := strings.Cut(t[len("map["):], "]"); ok {
633+
key, value = k, v
638634
}
639635
}
640636
changed := false

src/cmd/vet/vet_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,8 @@ func errorCheck(outStr string, wantAuto bool, fullshort ...string) (err error) {
241241
// Assume errmsg says "file:line: foo".
242242
// Cut leading "file:line: " to avoid accidental matching of file name instead of message.
243243
text := errmsg
244-
if i := strings.Index(text, " "); i >= 0 {
245-
text = text[i+1:]
244+
if _, suffix, ok := strings.Cut(text, " "); ok {
245+
text = suffix
246246
}
247247
if we.re.MatchString(text) {
248248
matched = true

src/crypto/ecdsa/ecdsa_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,9 @@ func TestVectors(t *testing.T) {
219219

220220
if line[0] == '[' {
221221
line = line[1 : len(line)-1]
222-
parts := strings.SplitN(line, ",", 2)
222+
curve, hash, _ := strings.Cut(line, ",")
223223

224-
switch parts[0] {
224+
switch curve {
225225
case "P-224":
226226
pub.Curve = elliptic.P224()
227227
case "P-256":
@@ -234,7 +234,7 @@ func TestVectors(t *testing.T) {
234234
pub.Curve = nil
235235
}
236236

237-
switch parts[1] {
237+
switch hash {
238238
case "SHA-1":
239239
h = sha1.New()
240240
case "SHA-224":

src/crypto/tls/handshake_client_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,18 @@ func (o *opensslOutputSink) Write(data []byte) (n int, err error) {
9797
o.all = append(o.all, data...)
9898

9999
for {
100-
i := bytes.IndexByte(o.line, '\n')
101-
if i < 0 {
100+
line, next, ok := bytes.Cut(o.line, []byte("\n"))
101+
if !ok {
102102
break
103103
}
104104

105-
if bytes.Equal([]byte(opensslEndOfHandshake), o.line[:i]) {
105+
if bytes.Equal([]byte(opensslEndOfHandshake), line) {
106106
o.handshakeComplete <- struct{}{}
107107
}
108-
if bytes.Equal([]byte(opensslReadKeyUpdate), o.line[:i]) {
108+
if bytes.Equal([]byte(opensslReadKeyUpdate), line) {
109109
o.readKeyUpdate <- struct{}{}
110110
}
111-
o.line = o.line[i+1:]
111+
o.line = next
112112
}
113113

114114
return len(data), nil

src/crypto/tls/handshake_test.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -191,18 +191,17 @@ func parseTestData(r io.Reader) (flows [][]byte, err error) {
191191
// Otherwise the line is a line of hex dump that looks like:
192192
// 00000170 fc f5 06 bf (...) |.....X{&?......!|
193193
// (Some bytes have been omitted from the middle section.)
194-
195-
if i := strings.IndexByte(line, ' '); i >= 0 {
196-
line = line[i:]
197-
} else {
194+
_, after, ok := strings.Cut(line, " ")
195+
if !ok {
198196
return nil, errors.New("invalid test data")
199197
}
198+
line = after
200199

201-
if i := strings.IndexByte(line, '|'); i >= 0 {
202-
line = line[:i]
203-
} else {
200+
before, _, ok := strings.Cut(line, "|")
201+
if !ok {
204202
return nil, errors.New("invalid test data")
205203
}
204+
line = before
206205

207206
hexBytes := strings.Fields(line)
208207
for _, hexByte := range hexBytes {

src/crypto/x509/pem_decrypt.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,11 @@ func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) {
127127
return nil, errors.New("x509: no DEK-Info header in block")
128128
}
129129

130-
idx := strings.Index(dek, ",")
131-
if idx == -1 {
130+
mode, hexIV, ok := strings.Cut(dek, ",")
131+
if !ok {
132132
return nil, errors.New("x509: malformed DEK-Info header")
133133
}
134134

135-
mode, hexIV := dek[:idx], dek[idx+1:]
136135
ciph := cipherByName(mode)
137136
if ciph == nil {
138137
return nil, errors.New("x509: unknown encryption mode")

src/encoding/asn1/common.go

+1-8
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,7 @@ type fieldParameters struct {
9494
func parseFieldParameters(str string) (ret fieldParameters) {
9595
var part string
9696
for len(str) > 0 {
97-
// This loop uses IndexByte and explicit slicing
98-
// instead of strings.Split(str, ",") to reduce allocations.
99-
i := strings.IndexByte(str, ',')
100-
if i < 0 {
101-
part, str = str, ""
102-
} else {
103-
part, str = str[:i], str[i+1:]
104-
}
97+
part, str, _ = strings.Cut(str, ",")
10598
switch {
10699
case part == "optional":
107100
ret.optional = true

0 commit comments

Comments
 (0)