case n == 0:
return len(s)
case n == 1:
- return LastIndexByte(s, sep[0])
+ return bytealg.LastIndexByte(s, sep[0])
case n == len(s):
if Equal(s, sep) {
return 0
// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
func LastIndexByte(s []byte, c byte) int {
- for i := len(s) - 1; i >= 0; i-- {
- if s[i] == c {
- return i
- }
- }
- return -1
+ return bytealg.LastIndexByte(s, c)
}
// IndexRune interprets s as a sequence of UTF-8-encoded code points.
--- /dev/null
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bytealg
+
+func LastIndexByte(s []byte, c byte) int {
+ for i := len(s) - 1; i >= 0; i-- {
+ if s[i] == c {
+ return i
+ }
+ }
+ return -1
+}
+
+func LastIndexByteString(s string, c byte) int {
+ for i := len(s) - 1; i >= 0; i-- {
+ if s[i] == c {
+ return i
+ }
+ }
+ return -1
+}
package netip
-func stringsLastIndexByte(s string, b byte) int {
- for i := len(s) - 1; i >= 0; i-- {
- if s[i] == b {
- return i
- }
- }
- return -1
-}
-
func beUint64(b []byte) uint64 {
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
// ip string should parse as an IPv6 address or an IPv4 address, in
// order for s to be a valid ip:port string.
func splitAddrPort(s string) (ip, port string, v6 bool, err error) {
- i := stringsLastIndexByte(s, ':')
+ i := bytealg.LastIndexByteString(s, ':')
if i == -1 {
return "", "", false, errors.New("not an ip:port")
}
//
// Note that masked address bits are not zeroed. Use Masked for that.
func ParsePrefix(s string) (Prefix, error) {
- i := stringsLastIndexByte(s, '/')
+ i := bytealg.LastIndexByteString(s, '/')
if i < 0 {
return Prefix{}, errors.New("netip.ParsePrefix(" + strconv.Quote(s) + "): no '/'")
}
package os
import (
+ "internal/bytealg"
"internal/poll"
"io"
"runtime"
}
func rename(oldname, newname string) error {
- dirname := oldname[:lastIndex(oldname, '/')+1]
+ dirname := oldname[:bytealg.LastIndexByteString(oldname, '/')+1]
if hasPrefix(newname, dirname) {
newname = newname[len(dirname):]
} else {
// If newname still contains slashes after removing the oldname
// prefix, the rename is cross-directory and must be rejected.
- if lastIndex(newname, '/') >= 0 {
+ if bytealg.LastIndexByteString(newname, '/') >= 0 {
return &LinkError{"rename", oldname, newname, ErrInvalid}
}
import (
"errors"
+ "internal/bytealg"
"internal/itoa"
)
return "", "", errPatternHasSeparator
}
}
- if pos := lastIndex(pattern, '*'); pos != -1 {
+ if pos := bytealg.LastIndexByteString(pattern, '*'); pos != -1 {
prefix, suffix = pattern[:pos], pattern[pos+1:]
} else {
prefix = pattern
}
return dir + string(PathSeparator) + name
}
-
-// lastIndex from the strings package.
-func lastIndex(s string, sep byte) int {
- for i := len(s) - 1; i >= 0; i-- {
- if s[i] == sep {
- return i
- }
- }
- return -1
-}
case n == 0:
return len(s)
case n == 1:
- return LastIndexByte(s, substr[0])
+ return bytealg.LastIndexByteString(s, substr[0])
case n == len(s):
if substr == s {
return 0
// LastIndexByte returns the index of the last instance of c in s, or -1 if c is not present in s.
func LastIndexByte(s string, c byte) int {
- for i := len(s) - 1; i >= 0; i-- {
- if s[i] == c {
- return i
- }
- }
- return -1
+ return bytealg.LastIndexByteString(s, c)
}
// Generic split: splits after each instance of sep,