replace strings.Split(N) for strings.Cut() or alternatives
Go 1.18 and up now provides a strings.Cut() which is better suited for
splitting key/value pairs (and similar constructs), and performs better:
```go
func BenchmarkSplit(b *testing.B) {
b.ReportAllocs()
data := []string{"12hello=world", "12hello=", "12=hello", "12hello"}
for i := 0; i < b.N; i++ {
for _, s := range data {
_ = strings.SplitN(s, "=", 2)[0]
}
}
}
func BenchmarkCut(b *testing.B) {
b.ReportAllocs()
data := []string{"12hello=world", "12hello=", "12=hello", "12hello"}
for i := 0; i < b.N; i++ {
for _, s := range data {
_, _, _ = strings.Cut(s, "=")
}
}
}
```
BenchmarkSplit
BenchmarkSplit-10 8244206 128.0 ns/op 128 B/op 4 allocs/op
BenchmarkCut
BenchmarkCut-10 54411998 21.80 ns/op 0 B/op 0 allocs/op
While looking at occurrences of `strings.Split()`, I also updated some for alternatives,
or added some constraints; for cases where an specific number of items is expected, I used `strings.SplitN()`
with a suitable limit. This prevents (theoretical) unlimited splits.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
@@ -80,15 +80,14 @@ func ParseProcPIDStatus(r io.Reader) (map[Type]uint64, error) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
pair := strings.SplitN(line, ":", 2)
|
||||
if len(pair) != 2 {
|
||||
k, v, ok := strings.Cut(line, ":")
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
k := strings.TrimSpace(pair[0])
|
||||
v := strings.TrimSpace(pair[1])
|
||||
k = strings.TrimSpace(k)
|
||||
switch k {
|
||||
case "CapInh", "CapPrm", "CapEff", "CapBnd", "CapAmb":
|
||||
ui64, err := strconv.ParseUint(v, 16, 64)
|
||||
ui64, err := strconv.ParseUint(strings.TrimSpace(v), 16, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse line %q", line)
|
||||
}
|
||||
|
||||
@@ -243,15 +243,15 @@ func WithDevices(config *runtime.ContainerConfig) oci.SpecOpts {
|
||||
|
||||
hostPath := device.HostPath
|
||||
if strings.HasPrefix(hostPath, "class/") {
|
||||
hostPath = strings.Replace(hostPath, "class/", "class://", 1)
|
||||
hostPath = "class://" + strings.TrimPrefix(hostPath, "class/")
|
||||
}
|
||||
|
||||
splitParts := strings.SplitN(hostPath, "://", 2)
|
||||
if len(splitParts) != 2 {
|
||||
idType, id, ok := strings.Cut(hostPath, "://")
|
||||
if !ok {
|
||||
return fmt.Errorf("unrecognised HostPath format %v, must match IDType://ID", device.HostPath)
|
||||
}
|
||||
|
||||
o := oci.WithWindowsDevice(splitParts[0], splitParts[1])
|
||||
o := oci.WithWindowsDevice(idType, id)
|
||||
if err := o(ctx, client, c, s); err != nil {
|
||||
return fmt.Errorf("failed adding device with HostPath %v: %w", device.HostPath, err)
|
||||
}
|
||||
|
||||
@@ -233,11 +233,10 @@ func ParseAuth(auth *runtime.AuthConfig, host string) (string, string, error) {
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
fields := strings.SplitN(string(decoded), ":", 2)
|
||||
if len(fields) != 2 {
|
||||
user, passwd, ok := strings.Cut(string(decoded), ":")
|
||||
if !ok {
|
||||
return "", "", fmt.Errorf("invalid decoded auth: %q", decoded)
|
||||
}
|
||||
user, passwd := fields[0], fields[1]
|
||||
return user, strings.Trim(passwd, "\x00"), nil
|
||||
}
|
||||
// TODO(random-liu): Support RegistryToken.
|
||||
|
||||
@@ -232,11 +232,10 @@ func ParseAuth(auth *runtime.AuthConfig, host string) (string, string, error) {
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
fields := strings.SplitN(string(decoded), ":", 2)
|
||||
if len(fields) != 2 {
|
||||
user, passwd, ok := strings.Cut(string(decoded), ":")
|
||||
if !ok {
|
||||
return "", "", fmt.Errorf("invalid decoded auth: %q", decoded)
|
||||
}
|
||||
user, passwd := fields[0], fields[1]
|
||||
return user, strings.Trim(passwd, "\x00"), nil
|
||||
}
|
||||
// TODO(random-liu): Support RegistryToken.
|
||||
|
||||
Reference in New Issue
Block a user