From e9f3c2422900f597400f05828f80fbffed012294 Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Mon, 27 Feb 2023 17:19:35 +0300 Subject: [PATCH] [#65] Use `strings.Cut` instead of `strings.Split*` where possible Signed-off-by: Anton Nikiforov --- .../internal/modules/morph/config.go | 10 +++--- .../internal/modules/morph/policy.go | 10 +++--- cmd/frostfs-cli/modules/container/create.go | 6 ++-- cmd/frostfs-cli/modules/object/put.go | 22 ++++++------ cmd/frostfs-cli/modules/object/range.go | 8 ++--- cmd/frostfs-cli/modules/object/util.go | 6 ++-- cmd/frostfs-cli/modules/tree/add.go | 8 ++--- cmd/frostfs-cli/modules/util/acl.go | 35 +++++++++---------- cmd/frostfs-node/config/test/config.go | 8 ++--- .../blobstor/fstree/fstree.go | 8 ++--- pkg/util/attributes/parser.go | 20 +++++------ 11 files changed, 69 insertions(+), 72 deletions(-) diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config.go index 4a653cb6..8a888ab2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config.go @@ -141,13 +141,13 @@ func setConfigCmd(cmd *cobra.Command, args []string) error { } func parseConfigPair(kvStr string, force bool) (key string, val any, err error) { - kv := strings.SplitN(kvStr, "=", 2) - if len(kv) != 2 { + k, v, found := strings.Cut(kvStr, "=") + if !found { return "", nil, fmt.Errorf("invalid parameter format: must be 'key=val', got: %s", kvStr) } - key = kv[0] - valRaw := kv[1] + key = k + valRaw := v switch key { case netmapAuditFeeKey, netmapBasicIncomeRateKey, @@ -162,7 +162,7 @@ func parseConfigPair(kvStr string, force bool) (key string, val any, err error) case netmapEigenTrustAlphaKey: // just check that it could // be parsed correctly - _, err = strconv.ParseFloat(kv[1], 64) + _, err = strconv.ParseFloat(v, 64) if err != nil { err = fmt.Errorf("could not parse %s's value '%s' as float: %w", key, valRaw, err) } diff --git a/cmd/frostfs-adm/internal/modules/morph/policy.go b/cmd/frostfs-adm/internal/modules/morph/policy.go index b00fa9c7..0703ebc2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/policy.go +++ b/cmd/frostfs-adm/internal/modules/morph/policy.go @@ -27,23 +27,23 @@ func setPolicyCmd(cmd *cobra.Command, args []string) error { bw := io.NewBufBinWriter() for i := range args { - kv := strings.SplitN(args[i], "=", 2) - if len(kv) != 2 { + k, v, found := strings.Cut(args[i], "=") + if !found { return fmt.Errorf("invalid parameter format, must be Parameter=Value") } - switch kv[0] { + switch k { case execFeeParam, storagePriceParam, setFeeParam: default: return fmt.Errorf("parameter must be one of %s, %s and %s", execFeeParam, storagePriceParam, setFeeParam) } - value, err := strconv.ParseUint(kv[1], 10, 32) + value, err := strconv.ParseUint(v, 10, 32) if err != nil { return fmt.Errorf("can't parse parameter value '%s': %w", args[1], err) } - emit.AppCall(bw.BinWriter, policy.Hash, "set"+kv[0], callflag.All, int64(value)) + emit.AppCall(bw.BinWriter, policy.Hash, "set"+k, callflag.All, int64(value)) } if err := wCtx.sendCommitteeTx(bw.Bytes(), false); err != nil { diff --git a/cmd/frostfs-cli/modules/container/create.go b/cmd/frostfs-cli/modules/container/create.go index 930529ef..50305934 100644 --- a/cmd/frostfs-cli/modules/container/create.go +++ b/cmd/frostfs-cli/modules/container/create.go @@ -201,12 +201,12 @@ func parseContainerPolicy(cmd *cobra.Command, policyString string) (*netmap.Plac func parseAttributes(dst *container.Container, attributes []string) error { for i := range attributes { - kvPair := strings.Split(attributes[i], attributeDelimiter) - if len(kvPair) != 2 { + k, v, found := strings.Cut(attributes[i], attributeDelimiter) + if !found { return errors.New("invalid container attribute") } - dst.SetAttribute(kvPair[0], kvPair[1]) + dst.SetAttribute(k, v) } if !containerNoTimestamp { diff --git a/cmd/frostfs-cli/modules/object/put.go b/cmd/frostfs-cli/modules/object/put.go index c94c3844..11bfedbd 100644 --- a/cmd/frostfs-cli/modules/object/put.go +++ b/cmd/frostfs-cli/modules/object/put.go @@ -179,12 +179,12 @@ func parseObjectAttrs(cmd *cobra.Command) ([]object.Attribute, error) { attrs := make([]object.Attribute, len(rawAttrs), len(rawAttrs)+2) // name + timestamp attributes for i := range rawAttrs { - kv := strings.SplitN(rawAttrs[i], "=", 2) - if len(kv) != 2 { + k, v, found := strings.Cut(rawAttrs[i], "=") + if !found { return nil, fmt.Errorf("invalid attribute format: %s", rawAttrs[i]) } - attrs[i].SetKey(kv[0]) - attrs[i].SetValue(kv[1]) + attrs[i].SetKey(k) + attrs[i].SetValue(v) } disableFilename, _ := cmd.Flags().GetBool("disable-filename") @@ -218,26 +218,26 @@ func parseObjectNotifications(cmd *cobra.Command) (*object.NotificationInfo, err return nil, nil } - rawSlice := strings.SplitN(raw, separator, 2) - if len(rawSlice) != 2 { + before, after, found := strings.Cut(raw, separator) + if !found { return nil, fmt.Errorf("notification must be in the form of: *epoch*%s*topic*, got %s", separator, raw) } ni := new(object.NotificationInfo) - epoch, err := strconv.ParseUint(rawSlice[0], 10, 64) + epoch, err := strconv.ParseUint(before, 10, 64) if err != nil { - return nil, fmt.Errorf("could not parse notification epoch %s: %w", rawSlice[0], err) + return nil, fmt.Errorf("could not parse notification epoch %s: %w", before, err) } ni.SetEpoch(epoch) - if rawSlice[1] == "" { + if after == "" { return nil, fmt.Errorf("incorrect empty topic: use %s to force using default topic", useDefaultTopic) } - if rawSlice[1] != useDefaultTopic { - ni.SetTopic(rawSlice[1]) + if after != useDefaultTopic { + ni.SetTopic(after) } return ni, nil diff --git a/cmd/frostfs-cli/modules/object/range.go b/cmd/frostfs-cli/modules/object/range.go index 1c983213..7a4d3a38 100644 --- a/cmd/frostfs-cli/modules/object/range.go +++ b/cmd/frostfs-cli/modules/object/range.go @@ -154,16 +154,16 @@ func getRangeList(cmd *cobra.Command) ([]*object.Range, error) { vs := strings.Split(v, ",") rs := make([]*object.Range, len(vs)) for i := range vs { - r := strings.Split(vs[i], rangeSep) - if len(r) != 2 { + before, after, found := strings.Cut(vs[i], rangeSep) + if !found { return nil, fmt.Errorf("invalid range specifier: %s", vs[i]) } - offset, err := strconv.ParseUint(r[0], 10, 64) + offset, err := strconv.ParseUint(before, 10, 64) if err != nil { return nil, fmt.Errorf("invalid '%s' range offset specifier: %w", vs[i], err) } - length, err := strconv.ParseUint(r[1], 10, 64) + length, err := strconv.ParseUint(after, 10, 64) if err != nil { return nil, fmt.Errorf("invalid '%s' range length specifier: %w", vs[i], err) } diff --git a/cmd/frostfs-cli/modules/object/util.go b/cmd/frostfs-cli/modules/object/util.go index e225191d..7832db44 100644 --- a/cmd/frostfs-cli/modules/object/util.go +++ b/cmd/frostfs-cli/modules/object/util.go @@ -63,12 +63,12 @@ func parseXHeaders(cmd *cobra.Command) []string { xs := make([]string, 0, 2*len(xHeaders)) for i := range xHeaders { - kv := strings.SplitN(xHeaders[i], "=", 2) - if len(kv) != 2 { + k, v, found := strings.Cut(xHeaders[i], "=") + if !found { panic(fmt.Errorf("invalid X-Header format: %s", xHeaders[i])) } - xs = append(xs, kv[0], kv[1]) + xs = append(xs, k, v) } return xs diff --git a/cmd/frostfs-cli/modules/tree/add.go b/cmd/frostfs-cli/modules/tree/add.go index 90815e1a..81930770 100644 --- a/cmd/frostfs-cli/modules/tree/add.go +++ b/cmd/frostfs-cli/modules/tree/add.go @@ -79,14 +79,14 @@ func parseMeta(cmd *cobra.Command) ([]*tree.KeyValue, error) { pairs := make([]*tree.KeyValue, 0, len(raws)) for i := range raws { - kv := strings.SplitN(raws[i], "=", 2) - if len(kv) != 2 { + k, v, found := strings.Cut(raws[i], "=") + if !found { return nil, fmt.Errorf("invalid meta pair format: %s", raws[i]) } var pair tree.KeyValue - pair.Key = kv[0] - pair.Value = []byte(kv[1]) + pair.Key = k + pair.Value = []byte(v) pairs = append(pairs, &pair) } diff --git a/cmd/frostfs-cli/modules/util/acl.go b/cmd/frostfs-cli/modules/util/acl.go index 1d568ee4..9314e223 100644 --- a/cmd/frostfs-cli/modules/util/acl.go +++ b/cmd/frostfs-cli/modules/util/acl.go @@ -226,35 +226,32 @@ func parseEACLTable(tb *eacl.Table, args []string) error { func parseEACLRecord(args []string) (*eacl.Record, error) { r := new(eacl.Record) - for i := range args { - ss := strings.SplitN(args[i], ":", 2) + for _, arg := range args { + before, after, found := strings.Cut(arg, ":") - switch prefix := strings.ToLower(ss[0]); prefix { + switch prefix := strings.ToLower(before); prefix { case "req", "obj": // filters - if len(ss) != 2 { - return nil, fmt.Errorf("invalid filter or target: %s", args[i]) - } - - i := strings.Index(ss[1], "=") - if i < 0 { - return nil, fmt.Errorf("invalid filter key-value pair: %s", ss[1]) + if !found { + return nil, fmt.Errorf("invalid filter or target: %s", arg) } var key, value string var op eacl.Match + var f bool - if 0 < i && ss[1][i-1] == '!' { - key = ss[1][:i-1] + key, value, f = strings.Cut(after, "!=") + if f { op = eacl.MatchStringNotEqual } else { - key = ss[1][:i] + key, value, f = strings.Cut(after, "=") + if !f { + return nil, fmt.Errorf("invalid filter key-value pair: %s", after) + } op = eacl.MatchStringEqual } - value = ss[1][i+1:] - typ := eacl.HeaderFromRequest - if ss[0] == "obj" { + if before == "obj" { typ = eacl.HeaderFromObject } @@ -263,8 +260,8 @@ func parseEACLRecord(args []string) (*eacl.Record, error) { var err error var pubs []ecdsa.PublicKey - if len(ss) == 2 { - pubs, err = parseKeyList(ss[1]) + if found { + pubs, err = parseKeyList(after) if err != nil { return nil, err } @@ -281,7 +278,7 @@ func parseEACLRecord(args []string) (*eacl.Record, error) { eacl.AddFormedTarget(r, role, pubs...) default: - return nil, fmt.Errorf("invalid prefix: %s", ss[0]) + return nil, fmt.Errorf("invalid prefix: %s", before) } } diff --git a/cmd/frostfs-node/config/test/config.go b/cmd/frostfs-node/config/test/config.go index 5dbc20f4..19012c6b 100644 --- a/cmd/frostfs-node/config/test/config.go +++ b/cmd/frostfs-node/config/test/config.go @@ -65,14 +65,14 @@ func loadEnv(path string) { scanner := bufio.NewScanner(f) for scanner.Scan() { - pair := strings.SplitN(scanner.Text(), "=", 2) - if len(pair) != 2 { + k, v, found := strings.Cut(scanner.Text(), "=") + if !found { continue } - pair[1] = strings.Trim(pair[1], `"`) + v = strings.Trim(v, `"`) - err = os.Setenv(pair[0], pair[1]) + err = os.Setenv(k, v) if err != nil { panic("can't set environment variable") } diff --git a/pkg/local_object_storage/blobstor/fstree/fstree.go b/pkg/local_object_storage/blobstor/fstree/fstree.go index 8f468e29..0446cfcc 100644 --- a/pkg/local_object_storage/blobstor/fstree/fstree.go +++ b/pkg/local_object_storage/blobstor/fstree/fstree.go @@ -73,18 +73,18 @@ func stringifyAddress(addr oid.Address) string { } func addressFromString(s string) (oid.Address, error) { - i := strings.IndexByte(s, '.') - if i == -1 { + before, after, found := strings.Cut(s, ".") + if !found { return oid.Address{}, errors.New("invalid address") } var obj oid.ID - if err := obj.DecodeString(s[:i]); err != nil { + if err := obj.DecodeString(before); err != nil { return oid.Address{}, err } var cnr cid.ID - if err := cnr.DecodeString(s[i+1:]); err != nil { + if err := cnr.DecodeString(after); err != nil { return oid.Address{}, err } diff --git a/pkg/util/attributes/parser.go b/pkg/util/attributes/parser.go index b92c84db..9b3b8ae8 100644 --- a/pkg/util/attributes/parser.go +++ b/pkg/util/attributes/parser.go @@ -19,29 +19,29 @@ func ReadNodeAttributes(dst *netmap.NodeInfo, attrs []string) error { for i := range attrs { line := replaceEscaping(attrs[i], false) // replaced escaped symbols with non-printable symbols - words := strings.Split(line, keyValueSeparator) - if len(words) != 2 { + k, v, found := strings.Cut(line, keyValueSeparator) + if !found { return errors.New("missing attribute key and/or value") } - _, ok := cache[words[0]] + _, ok := cache[k] if ok { - return fmt.Errorf("duplicated keys %s", words[0]) + return fmt.Errorf("duplicated keys %s", k) } - cache[words[0]] = struct{}{} + cache[k] = struct{}{} // replace non-printable symbols with escaped symbols without escape character - words[0] = replaceEscaping(words[0], true) - words[1] = replaceEscaping(words[1], true) + k = replaceEscaping(k, true) + v = replaceEscaping(v, true) - if words[0] == "" { + if k == "" { return errors.New("empty key") - } else if words[1] == "" { + } else if v == "" { return errors.New("empty value") } - dst.SetAttribute(words[0], words[1]) + dst.SetAttribute(k, v) } return nil