]> Cypherpunks repositories - gostls13.git/commitdiff
bytes, strings: add TrimPrefix and TrimSuffix
authorBrad Fitzpatrick <bradfitz@golang.org>
Fri, 1 Feb 2013 16:41:25 +0000 (08:41 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 1 Feb 2013 16:41:25 +0000 (08:41 -0800)
Everybody either gets confused and thinks this is
TrimLeft/TrimRight or does this by hand which gets
repetitive looking.

R=rsc, kevlar
CC=golang-dev
https://golang.org/cl/7239044

21 files changed:
src/cmd/api/goapi.go
src/cmd/cgo/gcc.go
src/cmd/cgo/godefs.go
src/cmd/fix/typecheck.go
src/cmd/go/testflag.go
src/cmd/godoc/dirtrees.go
src/cmd/godoc/filesystem.go
src/cmd/godoc/godoc.go
src/cmd/godoc/main.go
src/cmd/vet/method.go
src/pkg/bytes/bytes.go
src/pkg/bytes/bytes_test.go
src/pkg/bytes/example_test.go
src/pkg/exp/html/parse_test.go
src/pkg/go/printer/printer.go
src/pkg/go/types/gcimporter.go
src/pkg/net/http/pprof/pprof.go
src/pkg/net/http/response.go
src/pkg/strings/example_test.go
src/pkg/strings/strings.go
src/pkg/strings/strings_test.go

index 906cd3a68d3ebb8aadbe7362ae36f540e9f7772b..0d76b0cdb640c1722c1e1de2000415159d706611 100644 (file)
@@ -778,8 +778,7 @@ func (w *Walker) walkConst(vs *ast.ValueSpec) {
                                }
                        }
                }
-               if strings.HasPrefix(litType, constDepPrefix) {
-                       dep := litType[len(constDepPrefix):]
+               if dep := strings.TrimPrefix(litType, constDepPrefix); dep != litType {
                        w.constDep[ident.Name] = dep
                        continue
                }
index 3266abe6187ea5179c0a4bb1a4c6c7766f7ab6fc..1449a8d6b58201e777d14b6c9adc3ee5af4e8577 100644 (file)
@@ -1542,8 +1542,8 @@ func godefsFields(fld []*ast.Field) {
        npad := 0
        for _, f := range fld {
                for _, n := range f.Names {
-                       if strings.HasPrefix(n.Name, prefix) && n.Name != prefix {
-                               n.Name = n.Name[len(prefix):]
+                       if n.Name != prefix {
+                               n.Name = strings.TrimPrefix(n.Name, prefix)
                        }
                        if n.Name == "_" {
                                // Use exported name instead.
index fec70a334b03b7fa008db83c21419d79c4160b54..20376170dafd975654902f4a632a9e361ac792fc 100644 (file)
@@ -180,7 +180,7 @@ func (p *Package) cdefs(f *File, srcfile string) string {
                        for _, line := range lines {
                                line = strings.TrimSpace(line)
                                if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
-                                       s := line[len("type ") : len(line)-len(" struct {")]
+                                       s := strings.TrimSuffix(strings.TrimPrefix(line, "type "), " struct {")
                                        printf("typedef struct %s %s;\n", s, s)
                                }
                        }
index d54d375478dbdbe9bec388e54f62cc13103e2801..d33b69fddc95b4a001c1676908265d2856064cd7 100644 (file)
@@ -395,9 +395,7 @@ func typecheck1(cfg *TypeConfig, f interface{}, typeof map[interface{}]string, a
                        // Field or method.
                        name := n.Sel.Name
                        if t := typeof[n.X]; t != "" {
-                               if strings.HasPrefix(t, "*") {
-                                       t = t[1:] // implicit *
-                               }
+                               t = strings.TrimPrefix(t, "*") // implicit *
                                if typ := cfg.Type[t]; typ != nil {
                                        if t := typ.dot(cfg, name); t != "" {
                                                typeof[n] = t
index 8dd51437d774b3510664669c80aec7c48b9148a7..b2ca66b0940510917c945d7b17be2241e2b5a6c4 100644 (file)
@@ -195,9 +195,7 @@ func testFlag(args []string, i int) (f *testFlagSpec, value string, extra bool)
        }
        name := arg[1:]
        // If there's already "test.", drop it for now.
-       if strings.HasPrefix(name, "test.") {
-               name = name[5:]
-       }
+       name = strings.TrimPrefix(name, "test.")
        equals := strings.Index(name, "=")
        if equals >= 0 {
                value = name[equals+1:]
index 29bd39e6b0d3cc1072cbb6177971a305b8c080fb..08dbfc2e8b6b7568b43f1f688e93b5c23d27678e 100644 (file)
@@ -229,9 +229,7 @@ func (dir *Directory) lookupLocal(name string) *Directory {
 }
 
 func splitPath(p string) []string {
-       if strings.HasPrefix(p, "/") {
-               p = p[1:]
-       }
+       p = strings.TrimPrefix(p, "/")
        if p == "" {
                return nil
        }
@@ -310,14 +308,9 @@ func (root *Directory) listing(skipRoot bool) *DirList {
                // the path is relative to root.Path - remove the root.Path
                // prefix (the prefix should always be present but avoid
                // crashes and check)
-               path := d.Path
-               if strings.HasPrefix(d.Path, root.Path) {
-                       path = d.Path[len(root.Path):]
-               }
+               path := strings.TrimPrefix(d.Path, root.Path)
                // remove leading separator if any - path must be relative
-               if len(path) > 0 && path[0] == '/' {
-                       path = path[1:]
-               }
+               path = strings.TrimPrefix(path, "/")
                p.Path = path
                p.Name = d.Name
                p.HasPkg = d.HasPkg
index c4afbed80077370ef8f4749b9c4f1e84c3da83a9..0309d7cabe73882fa34a23d0232e8b65b75cf832 100644 (file)
@@ -459,9 +459,7 @@ func (ns nameSpace) ReadDir(path string) ([]os.FileInfo, error) {
                if hasPathPrefix(old, path) && old != path {
                        // Find next element after path in old.
                        elem := old[len(path):]
-                       if strings.HasPrefix(elem, "/") {
-                               elem = elem[1:]
-                       }
+                       elem = strings.TrimPrefix(elem, "/")
                        if i := strings.Index(elem, "/"); i >= 0 {
                                elem = elem[:i]
                        }
index 4d66c3011cad7e4a66ef7c3d3a232cff046770c6..887480911aa52115b3864f5d16a196e9501fd80b 100644 (file)
@@ -419,9 +419,7 @@ func pkgLinkFunc(path string) string {
        relpath := path[1:]
        // because of the irregular mapping under goroot
        // we need to correct certain relative paths
-       if strings.HasPrefix(relpath, "src/pkg/") {
-               relpath = relpath[len("src/pkg/"):]
-       }
+       relpath = strings.TrimPrefix(relpath, "src/pkg/")
        return pkgHandler.pattern[1:] + relpath // remove trailing '/' for relative URL
 }
 
index 02891444b0f2dd7f397f4fceb034b5848bdca2f1..13441009067876e2d733cdc3f190013991be6070 100644 (file)
@@ -347,7 +347,7 @@ func main() {
                fs.Bind(target, OS(path), "/", bindReplace)
                abspath = target
        } else if strings.HasPrefix(path, cmdPrefix) {
-               path = path[len(cmdPrefix):]
+               path = strings.TrimPrefix(path, cmdPrefix)
                forceCmd = true
        } else if bp, _ := build.Import(path, "", build.FindOnly); bp.Dir != "" && bp.ImportPath != "" {
                fs.Bind(target, OS(bp.Dir), "/", bindReplace)
index 41df96cec5a7e46b41cfa722410e59f2b59b9b84..dcfa8a02f395df32b677845fb115219b28d091f3 100644 (file)
@@ -90,9 +90,7 @@ func (f *File) checkCanonicalMethod(id *ast.Ident, t *ast.FuncType) {
                        fmt.Fprintf(&f.b, "<%s>", err)
                }
                actual := f.b.String()
-               if strings.HasPrefix(actual, "func(") {
-                       actual = actual[4:]
-               }
+               actual = strings.TrimPrefix(actual, "func(")
                actual = id.Name + actual
 
                f.Warnf(id.Pos(), "method %s should have signature %s", actual, expectFmt)
index e3ee5b1d88a63712f5e84bbc6d59af3240fcda02..31cf89ea87cc764711de02ef91a6f2bfb39858ad 100644 (file)
@@ -515,6 +515,24 @@ func TrimFunc(s []byte, f func(r rune) bool) []byte {
        return TrimRightFunc(TrimLeftFunc(s, f), f)
 }
 
+// TrimPrefix returns s without the provided leading prefix string.
+// If s doesn't start with prefix, s is returned unchanged.
+func TrimPrefix(s, prefix []byte) []byte {
+       if HasPrefix(s, prefix) {
+               return s[len(prefix):]
+       }
+       return s
+}
+
+// TrimSuffix returns s without the provided trailing suffix string.
+// If s doesn't end with suffix, s is returned unchanged.
+func TrimSuffix(s, suffix []byte) []byte {
+       if HasSuffix(s, suffix) {
+               return s[:len(s)-len(suffix)]
+       }
+       return s
+}
+
 // IndexFunc interprets s as a sequence of UTF-8-encoded Unicode code points.
 // It returns the byte index in s of the first Unicode
 // code point satisfying f(c), or -1 if none do.
index 05956d460a90db9e339f27c8cbaf7eccb4eb5994..1d073b143bd2b590e36574ec37cc2062a5652300 100644 (file)
@@ -794,8 +794,8 @@ func TestRunes(t *testing.T) {
 }
 
 type TrimTest struct {
-       f               string
-       in, cutset, out string
+       f            string
+       in, arg, out string
 }
 
 var trimTests = []TrimTest{
@@ -820,12 +820,17 @@ var trimTests = []TrimTest{
        {"TrimRight", "", "123", ""},
        {"TrimRight", "", "", ""},
        {"TrimRight", "☺\xc0", "☺", "☺\xc0"},
+       {"TrimPrefix", "aabb", "a", "abb"},
+       {"TrimPrefix", "aabb", "b", "aabb"},
+       {"TrimSuffix", "aabb", "a", "aabb"},
+       {"TrimSuffix", "aabb", "b", "aab"},
 }
 
 func TestTrim(t *testing.T) {
        for _, tc := range trimTests {
                name := tc.f
                var f func([]byte, string) []byte
+               var fb func([]byte, []byte) []byte
                switch name {
                case "Trim":
                        f = Trim
@@ -833,12 +838,21 @@ func TestTrim(t *testing.T) {
                        f = TrimLeft
                case "TrimRight":
                        f = TrimRight
+               case "TrimPrefix":
+                       fb = TrimPrefix
+               case "TrimSuffix":
+                       fb = TrimSuffix
                default:
                        t.Errorf("Undefined trim function %s", name)
                }
-               actual := string(f([]byte(tc.in), tc.cutset))
+               var actual string
+               if f != nil {
+                       actual = string(f([]byte(tc.in), tc.arg))
+               } else {
+                       actual = string(fb([]byte(tc.in), []byte(tc.arg)))
+               }
                if actual != tc.out {
-                       t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
+                       t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
                }
        }
 }
index dc66b6a40f67b73c24bd9c158bb82bded3f8d064..ad2dbc69b77a73362fbd79dfe318c61b0ae0c026 100644 (file)
@@ -66,3 +66,20 @@ func ExampleCompare_search() {
                // Found it!
        }
 }
+
+func ExampleTrimSuffix() {
+       var b = []byte("Hello, goodbye, etc!")
+       b = bytes.TrimSuffix(b, []byte("goodbye, etc!"))
+       b = bytes.TrimSuffix(b, []byte("gopher"))
+       b = append(b, bytes.TrimSuffix([]byte("world!"), []byte("x!"))...)
+       os.Stdout.Write(b)
+       // Output: Hello, world!
+}
+
+func ExampleTrimPrefix() {
+       var b = []byte("Goodbye,, world!")
+       b = bytes.TrimPrefix(b, []byte("Goodbye,"))
+       b = bytes.TrimPrefix(b, []byte("See ya,"))
+       fmt.Printf("Hello%s", b)
+       // Output: Hello, world!
+}
index 4896dfb7a0f558695d6954087997978bb77ceeba..f72af4597058da18d854d0bf5b6b973a170d309e 100644 (file)
@@ -42,10 +42,7 @@ func readParseTest(r *bufio.Reader) (text, want, context string, err error) {
                }
                b = append(b, line...)
        }
-       text = string(b)
-       if strings.HasSuffix(text, "\n") {
-               text = text[:len(text)-1]
-       }
+       text = strings.TrimSuffix(string(b), "\n")
        b = b[:0]
 
        // Skip the error list.
index f1c07bd3be2d6c993bc624ab017419c365f8be97..3c8d23e6553fb7b1cb7787645f4686aefebf69c2 100644 (file)
@@ -551,9 +551,7 @@ func stripCommonPrefix(lines []string) {
                        }
                        // Shorten the computed common prefix by the length of
                        // suffix, if it is found as suffix of the prefix.
-                       if strings.HasSuffix(prefix, string(suffix)) {
-                               prefix = prefix[0 : len(prefix)-len(suffix)]
-                       }
+                       prefix = strings.TrimSuffix(prefix, string(suffix))
                }
        }
 
index edd3e4dec7d595440e0bc5548bb1bddbe17a1594..e0e4cea3c77520318e00dc003c48dff3a8036cb7 100644 (file)
@@ -44,10 +44,7 @@ func FindPkg(path, srcDir string) (filename, id string) {
                if bp.PkgObj == "" {
                        return
                }
-               noext = bp.PkgObj
-               if strings.HasSuffix(noext, ".a") {
-                       noext = noext[:len(noext)-len(".a")]
-               }
+               noext = strings.TrimSuffix(bp.PkgObj, ".a")
 
        case build.IsLocalImport(path):
                // "./x" -> "/this/directory/x.ext", "/this/directory/x"
index 0c03e5b2b75c5ff82ced1de40071d3392908122f..0c7548e3ef3792adaeb6866081f6bf6aa0bc4159 100644 (file)
@@ -172,7 +172,7 @@ func (name handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 // listing the available profiles.
 func Index(w http.ResponseWriter, r *http.Request) {
        if strings.HasPrefix(r.URL.Path, "/debug/pprof/") {
-               name := r.URL.Path[len("/debug/pprof/"):]
+               name := strings.TrimPrefix(r.URL.Path, "/debug/pprof/")
                if name != "" {
                        handler(name).ServeHTTP(w, r)
                        return
index 7901c49f5a50db51866afd31b7f264e8bf02c4bd..391ebbf6d70f6337605d914eb3504791fc5852d2 100644 (file)
@@ -198,9 +198,7 @@ func (r *Response) Write(w io.Writer) error {
        }
        protoMajor, protoMinor := strconv.Itoa(r.ProtoMajor), strconv.Itoa(r.ProtoMinor)
        statusCode := strconv.Itoa(r.StatusCode) + " "
-       if strings.HasPrefix(text, statusCode) {
-               text = text[len(statusCode):]
-       }
+       text = strings.TrimPrefix(text, statusCode)
        io.WriteString(w, "HTTP/"+protoMajor+"."+protoMinor+" "+statusCode+text+"\r\n")
 
        // Process Body,ContentLength,Close,Trailer
index 733caf5f2db27bc5d5cbda3d1bb821d9301038f9..36e0a42fb031099829d9f2f2a90aa7c0a3d35f5c 100644 (file)
@@ -179,3 +179,19 @@ func ExampleToLower() {
        fmt.Println(strings.ToLower("Gopher"))
        // Output: gopher
 }
+
+func ExampleTrimSuffix() {
+       var s = "Hello, goodbye, etc!"
+       s = strings.TrimSuffix(s, "goodbye, etc!")
+       s = strings.TrimSuffix(s, "planet")
+       fmt.Print(s, "world!")
+       // Output: Hello, world!
+}
+
+func ExampleTrimPrefix() {
+       var s = "Goodbye,, world!"
+       s = strings.TrimPrefix(s, "Goodbye,")
+       s = strings.TrimPrefix(s, "Howdy,")
+       fmt.Print("Hello" + s)
+       // Output: Hello, world!
+}
index b411ba5d8b3b43d4b0e4b84585568aae253dde0d..d4b3f034736a94726884f2fa713bd21c61ebf01d 100644 (file)
@@ -558,6 +558,24 @@ func TrimSpace(s string) string {
        return TrimFunc(s, unicode.IsSpace)
 }
 
+// TrimPrefix returns s without the provided leading prefix string.
+// If s doesn't start with prefix, s is returned unchanged.
+func TrimPrefix(s, prefix string) string {
+       if HasPrefix(s, prefix) {
+               return s[len(prefix):]
+       }
+       return s
+}
+
+// TrimSuffix returns s without the provided trailing suffix string.
+// If s doesn't end with suffix, s is returned unchanged.
+func TrimSuffix(s, suffix string) string {
+       if HasSuffix(s, suffix) {
+               return s[:len(s)-len(suffix)]
+       }
+       return s
+}
+
 // Replace returns a copy of the string s with the first n
 // non-overlapping instances of old replaced by new.
 // If n < 0, there is no limit on the number of replacements.
index 7be41a8dcadc128dfa0fd4d9269910329e8bc1f3..e222af14a7c30ffacfdde3f517c3e2a87e681d2b 100644 (file)
@@ -496,8 +496,8 @@ func TestSpecialCase(t *testing.T) {
 func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
 
 var trimTests = []struct {
-       f               string
-       in, cutset, out string
+       f            string
+       in, arg, out string
 }{
        {"Trim", "abba", "a", "bb"},
        {"Trim", "abba", "ab", ""},
@@ -520,6 +520,10 @@ var trimTests = []struct {
        {"TrimRight", "", "123", ""},
        {"TrimRight", "", "", ""},
        {"TrimRight", "☺\xc0", "☺", "☺\xc0"},
+       {"TrimPrefix", "aabb", "a", "abb"},
+       {"TrimPrefix", "aabb", "b", "aabb"},
+       {"TrimSuffix", "aabb", "a", "aabb"},
+       {"TrimSuffix", "aabb", "b", "aab"},
 }
 
 func TestTrim(t *testing.T) {
@@ -533,12 +537,16 @@ func TestTrim(t *testing.T) {
                        f = TrimLeft
                case "TrimRight":
                        f = TrimRight
+               case "TrimPrefix":
+                       f = TrimPrefix
+               case "TrimSuffix":
+                       f = TrimSuffix
                default:
                        t.Errorf("Undefined trim function %s", name)
                }
-               actual := f(tc.in, tc.cutset)
+               actual := f(tc.in, tc.arg)
                if actual != tc.out {
-                       t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.cutset, actual, tc.out)
+                       t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
                }
        }
 }